Skip to content

drivers: media: imx500: Add device id readback control #6897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 72 additions & 2 deletions drivers/media/i2c/imx500.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ enum pad_types { IMAGE_PAD, METADATA_PAD, NUM_PADS };

#define V4L2_CID_USER_IMX500_INFERENCE_WINDOW (V4L2_CID_USER_IMX500_BASE + 0)
#define V4L2_CID_USER_IMX500_NETWORK_FW_FD (V4L2_CID_USER_IMX500_BASE + 1)
#define V4L2_CID_USER_GET_IMX500_DEVICE_ID (V4L2_CID_USER_IMX500_BASE + 2)

#define ONE_MIB (1024 * 1024)

Expand Down Expand Up @@ -1365,6 +1366,7 @@ struct imx500 {
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *network_fw_ctrl;
struct v4l2_ctrl *device_id;

struct v4l2_rect inference_window;

Expand Down Expand Up @@ -1579,6 +1581,25 @@ static int imx500_set_inference_window(struct imx500 *imx500)
ARRAY_SIZE(window_regs), NULL);
}

static int imx500_get_device_id(struct imx500 *imx500, u32 *device_id)
{
const u32 addr = 0xd040;
unsigned int i;
int ret = 0;
u64 tmp, data;

for (i = 0; i < 4; i++) {
ret = cci_read(imx500->regmap, CCI_REG32(addr + i * 4), &tmp,
NULL);
if (ret)
return -EREMOTEIO;
data = tmp & 0xffffffff;
device_id[i] = data;
}

return ret;
}

static int imx500_reg_val_write_cbk(void *arg,
const struct cci_reg_sequence *reg)
{
Expand Down Expand Up @@ -1619,6 +1640,7 @@ static int imx500_validate_fw_block(const char *data, size_t maxlen)
static const char footer_id[] = { '3', '6', '9', '5' };

u32 data_size;
u32 extra_bytes_size = 0;

const char *end = data + maxlen;

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

if (end - data_size - footer_size < data)
/* check the device_lock flag */
extra_bytes_size = *((u8 *)(data + 0x0e)) & 0x01 ? 32 : 0;

if (end - data_size - footer_size - extra_bytes_size < data)
return -1;
if (memcmp(data + data_size + footer_size - sizeof(footer_id),
&footer_id, sizeof(footer_id)))
return -1;

return data_size + footer_size;
return data_size + footer_size + extra_bytes_size;
}

/* Parse fw block by block, returning total valid fw size */
Expand Down Expand Up @@ -1875,6 +1900,7 @@ static void imx500_clear_fw_network(struct imx500 *imx500)
imx500->fw_network = NULL;
imx500->network_written = false;
imx500->fw_progress = 0;
v4l2_ctrl_activate(imx500->device_id, false);
}

static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
Expand Down Expand Up @@ -1997,7 +2023,31 @@ static int imx500_set_ctrl(struct v4l2_ctrl *ctrl)
return ret;
}

static int imx500_get_ctrl(struct v4l2_ctrl *ctrl)
{
struct imx500 *imx500 = container_of(ctrl->handler, struct imx500,
ctrl_handler);
struct i2c_client *client = v4l2_get_subdevdata(&imx500->sd);
u32 device_id[4] = {0};
int ret;

switch (ctrl->id) {
case V4L2_CID_USER_GET_IMX500_DEVICE_ID:
ret = imx500_get_device_id(imx500, device_id);
memcpy(ctrl->p_new.p_u32, device_id, sizeof(device_id));
break;
default:
dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n",
ctrl->id, ctrl->val);
ret = -EINVAL;
break;
}

return ret;
}

static const struct v4l2_ctrl_ops imx500_ctrl_ops = {
.g_volatile_ctrl = imx500_get_ctrl,
.s_ctrl = imx500_set_ctrl,
};

Expand Down Expand Up @@ -2592,6 +2642,8 @@ static int imx500_start_streaming(struct imx500 *imx500)
__func__);
return ret;
}

v4l2_ctrl_activate(imx500->device_id, true);
}

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

/* Custom control to get camera device id */
static const struct v4l2_ctrl_config cam_get_device_id = {
.name = "Get IMX500 Device ID",
.id = V4L2_CID_USER_GET_IMX500_DEVICE_ID,
.dims[0] = 4,
.ops = &imx500_ctrl_ops,
.type = V4L2_CTRL_TYPE_U32,
.flags = V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE |
V4L2_CTRL_FLAG_INACTIVE,
.elem_size = sizeof(u32),
.min = 0x00,
.max = U32_MAX,
.step = 1,
.def = 0,
};

/* Initialize control handlers */
static int imx500_init_controls(struct imx500 *imx500)
{
Expand Down Expand Up @@ -2909,6 +2977,8 @@ static int imx500_init_controls(struct imx500 *imx500)
v4l2_ctrl_new_custom(ctrl_hdlr, &inf_window_ctrl, NULL);
imx500->network_fw_ctrl =
v4l2_ctrl_new_custom(ctrl_hdlr, &network_fw_fd, NULL);
imx500->device_id =
v4l2_ctrl_new_custom(ctrl_hdlr, &cam_get_device_id, NULL);

if (ctrl_hdlr->error) {
ret = ctrl_hdlr->error;
Expand Down