Skip to content

Commit 0bef2fa

Browse files
committed
drivers: media: imx500: Add device id readback control
Add a new custom control V4L2_CID_USER_GET_IMX500_DEVICE_ID to allow userland to query the device id from the IMX500 sensor eeprom. Note that this device id can only be accessed when a network firmware has been upoloaded to the device, so cannot be cached on probe. Signed-off-by: Naushir Patuck <[email protected]>
1 parent 3174771 commit 0bef2fa

File tree

1 file changed

+72
-2
lines changed

1 file changed

+72
-2
lines changed

drivers/media/i2c/imx500.c

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ enum pad_types { IMAGE_PAD, METADATA_PAD, NUM_PADS };
239239

240240
#define V4L2_CID_USER_IMX500_INFERENCE_WINDOW (V4L2_CID_USER_IMX500_BASE + 0)
241241
#define V4L2_CID_USER_IMX500_NETWORK_FW_FD (V4L2_CID_USER_IMX500_BASE + 1)
242+
#define V4L2_CID_USER_GET_IMX500_DEVICE_ID (V4L2_CID_USER_IMX500_BASE + 2)
242243

243244
#define ONE_MIB (1024 * 1024)
244245

@@ -1365,6 +1366,7 @@ struct imx500 {
13651366
struct v4l2_ctrl *vblank;
13661367
struct v4l2_ctrl *hblank;
13671368
struct v4l2_ctrl *network_fw_ctrl;
1369+
struct v4l2_ctrl *device_id;
13681370

13691371
struct v4l2_rect inference_window;
13701372

@@ -1579,6 +1581,25 @@ static int imx500_set_inference_window(struct imx500 *imx500)
15791581
ARRAY_SIZE(window_regs), NULL);
15801582
}
15811583

1584+
static int imx500_get_device_id(struct imx500 *imx500, u32 *device_id)
1585+
{
1586+
const u32 addr = 0xd040;
1587+
unsigned int i;
1588+
int ret = 0;
1589+
u64 tmp, data;
1590+
1591+
for (i = 0; i < 4; i++) {
1592+
ret = cci_read(imx500->regmap, CCI_REG32(addr + i * 4), &tmp,
1593+
NULL);
1594+
if (ret)
1595+
return -EREMOTEIO;
1596+
data = tmp & 0xffffffff;
1597+
device_id[i] = data;
1598+
}
1599+
1600+
return ret;
1601+
}
1602+
15821603
static int imx500_reg_val_write_cbk(void *arg,
15831604
const struct cci_reg_sequence *reg)
15841605
{
@@ -1619,6 +1640,7 @@ static int imx500_validate_fw_block(const char *data, size_t maxlen)
16191640
static const char footer_id[] = { '3', '6', '9', '5' };
16201641

16211642
u32 data_size;
1643+
u32 extra_bytes_size = 0;
16221644

16231645
const char *end = data + maxlen;
16241646

@@ -1635,13 +1657,16 @@ static int imx500_validate_fw_block(const char *data, size_t maxlen)
16351657
memcpy(&data_size, data + sizeof(header_id), sizeof(data_size));
16361658
data_size = ___constant_swab32(data_size);
16371659

1638-
if (end - data_size - footer_size < data)
1660+
/* check the device_lock flag */
1661+
extra_bytes_size = *((u8 *)(data + 0x0e)) & 0x01 ? 32 : 0;
1662+
1663+
if (end - data_size - footer_size - extra_bytes_size < data)
16391664
return -1;
16401665
if (memcmp(data + data_size + footer_size - sizeof(footer_id),
16411666
&footer_id, sizeof(footer_id)))
16421667
return -1;
16431668

1644-
return data_size + footer_size;
1669+
return data_size + footer_size + extra_bytes_size;
16451670
}
16461671

16471672
/* Parse fw block by block, returning total valid fw size */
@@ -1875,6 +1900,7 @@ static void imx500_clear_fw_network(struct imx500 *imx500)
18751900
imx500->fw_network = NULL;
18761901
imx500->network_written = false;
18771902
imx500->fw_progress = 0;
1903+
imx500->device_id->flags &= ~V4L2_CTRL_FLAG_INACTIVE;
18781904
}
18791905

18801906
static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
@@ -1997,7 +2023,31 @@ static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
19972023
return ret;
19982024
}
19992025

2026+
static int imx500_get_ctrl(struct v4l2_ctrl *ctrl)
2027+
{
2028+
struct imx500 *imx500 = container_of(ctrl->handler, struct imx500,
2029+
ctrl_handler);
2030+
struct i2c_client *client = v4l2_get_subdevdata(&imx500->sd);
2031+
u32 device_id[4] = {0};
2032+
int ret;
2033+
2034+
switch (ctrl->id) {
2035+
case V4L2_CID_USER_GET_IMX500_DEVICE_ID:
2036+
ret = imx500_get_device_id(imx500, device_id);
2037+
memcpy(ctrl->p_new.p_u32, device_id, sizeof(device_id));
2038+
break;
2039+
default:
2040+
dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n",
2041+
ctrl->id, ctrl->val);
2042+
ret = -EINVAL;
2043+
break;
2044+
}
2045+
2046+
return ret;
2047+
}
2048+
20002049
static const struct v4l2_ctrl_ops imx500_ctrl_ops = {
2050+
.g_volatile_ctrl = imx500_get_ctrl,
20012051
.s_ctrl = imx500_set_ctrl,
20022052
};
20032053

@@ -2592,6 +2642,8 @@ static int imx500_start_streaming(struct imx500 *imx500)
25922642
__func__);
25932643
return ret;
25942644
}
2645+
2646+
imx500->device_id->flags &= ~V4L2_CTRL_FLAG_INACTIVE;
25952647
}
25962648

25972649
/* Apply default values of current mode */
@@ -2846,6 +2898,22 @@ static const struct v4l2_ctrl_config network_fw_fd = {
28462898
.def = -1,
28472899
};
28482900

2901+
/* Custom control to get camera device id */
2902+
static const struct v4l2_ctrl_config cam_get_device_id = {
2903+
.name = "Get IMX500 Device ID",
2904+
.id = V4L2_CID_USER_GET_IMX500_DEVICE_ID,
2905+
.dims[0] = 4,
2906+
.ops = &imx500_ctrl_ops,
2907+
.type = V4L2_CTRL_TYPE_U32,
2908+
.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE |
2909+
V4L2_CTRL_FLAG_INACTIVE,
2910+
.elem_size = sizeof(u32),
2911+
.min = 0x00,
2912+
.max = U32_MAX,
2913+
.step = 1,
2914+
.def = 0,
2915+
};
2916+
28492917
/* Initialize control handlers */
28502918
static int imx500_init_controls(struct imx500 *imx500)
28512919
{
@@ -2909,6 +2977,8 @@ static int imx500_init_controls(struct imx500 *imx500)
29092977
v4l2_ctrl_new_custom(ctrl_hdlr, &inf_window_ctrl, NULL);
29102978
imx500->network_fw_ctrl =
29112979
v4l2_ctrl_new_custom(ctrl_hdlr, &network_fw_fd, NULL);
2980+
imx500->device_id =
2981+
v4l2_ctrl_new_custom(ctrl_hdlr, &cam_get_device_id, NULL);
29122982

29132983
if (ctrl_hdlr->error) {
29142984
ret = ctrl_hdlr->error;

0 commit comments

Comments
 (0)