Skip to content

Commit 4612c18

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 4612c18

File tree

1 file changed

+70
-2
lines changed

1 file changed

+70
-2
lines changed

drivers/media/i2c/imx500.c

Lines changed: 70 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

@@ -1579,6 +1580,25 @@ static int imx500_set_inference_window(struct imx500 *imx500)
15791580
ARRAY_SIZE(window_regs), NULL);
15801581
}
15811582

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

16211641
u32 data_size;
1642+
u32 extra_bytes_size = 0;
16221643

16231644
const char *end = data + maxlen;
16241645

@@ -1635,13 +1656,16 @@ static int imx500_validate_fw_block(const char *data, size_t maxlen)
16351656
memcpy(&data_size, data + sizeof(header_id), sizeof(data_size));
16361657
data_size = ___constant_swab32(data_size);
16371658

1638-
if (end - data_size - footer_size < data)
1659+
/* check the device_lock flag */
1660+
extra_bytes_size = *((u8 *)(data + 0x0e)) & 0x01 ? 32 : 0;
1661+
1662+
if (end - data_size - footer_size - extra_bytes_size < data)
16391663
return -1;
16401664
if (memcmp(data + data_size + footer_size - sizeof(footer_id),
16411665
&footer_id, sizeof(footer_id)))
16421666
return -1;
16431667

1644-
return data_size + footer_size;
1668+
return data_size + footer_size + extra_bytes_size;
16451669
}
16461670

16471671
/* Parse fw block by block, returning total valid fw size */
@@ -1997,7 +2021,35 @@ static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
19972021
return ret;
19982022
}
19992023

2024+
static int imx500_get_ctrl(struct v4l2_ctrl *ctrl)
2025+
{
2026+
struct imx500 *imx500 = container_of(ctrl->handler, struct imx500,
2027+
ctrl_handler);
2028+
struct i2c_client *client = v4l2_get_subdevdata(&imx500->sd);
2029+
u32 device_id[4] = {0};
2030+
int ret;
2031+
2032+
switch (ctrl->id) {
2033+
case V4L2_CID_USER_GET_IMX500_DEVICE_ID:
2034+
if (!imx500->network_written) {
2035+
dev_err(&client->dev, "Unable to get device id without network fw loaded\n");
2036+
return -EINVAL;
2037+
}
2038+
ret = imx500_get_device_id(imx500, device_id);
2039+
memcpy(ctrl->p_new.p_u32, device_id, sizeof(device_id));
2040+
break;
2041+
default:
2042+
dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n",
2043+
ctrl->id, ctrl->val);
2044+
ret = -EINVAL;
2045+
break;
2046+
}
2047+
2048+
return ret;
2049+
}
2050+
20002051
static const struct v4l2_ctrl_ops imx500_ctrl_ops = {
2052+
.g_volatile_ctrl = imx500_get_ctrl,
20012053
.s_ctrl = imx500_set_ctrl,
20022054
};
20032055

@@ -2846,6 +2898,21 @@ 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+
.elem_size = sizeof(u32),
2910+
.min = 0x00,
2911+
.max = U32_MAX,
2912+
.step = 1,
2913+
.def = 0,
2914+
};
2915+
28492916
/* Initialize control handlers */
28502917
static int imx500_init_controls(struct imx500 *imx500)
28512918
{
@@ -2909,6 +2976,7 @@ static int imx500_init_controls(struct imx500 *imx500)
29092976
v4l2_ctrl_new_custom(ctrl_hdlr, &inf_window_ctrl, NULL);
29102977
imx500->network_fw_ctrl =
29112978
v4l2_ctrl_new_custom(ctrl_hdlr, &network_fw_fd, NULL);
2979+
v4l2_ctrl_new_custom(ctrl_hdlr, &cam_get_device_id, NULL);
29122980

29132981
if (ctrl_hdlr->error) {
29142982
ret = ctrl_hdlr->error;

0 commit comments

Comments
 (0)