From 790eee22115c3ebb348a9d735896196d4f7edf64 Mon Sep 17 00:00:00 2001 From: Allon Huang Date: Tue, 18 Aug 2020 12:57:10 +0800 Subject: [PATCH] media: rockchip: cif: support hdr_x3 mode Signed-off-by: Allon Huang Change-Id: I51bca04810f3084e9ba9f446a639e27150bf10d8 --- drivers/media/platform/rockchip/cif/capture.c | 225 ++++++++++++++---- drivers/media/platform/rockchip/cif/dev.h | 6 +- .../media/platform/rockchip/cif/subdev-itf.c | 8 +- 3 files changed, 188 insertions(+), 51 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index b7ee5260e608..f9a904e0096a 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -480,7 +480,7 @@ static struct rkcif_sensor_info *sd_to_sensor(struct rkcif_device *dev, static int rkcif_update_sensor_info(struct rkcif_stream *stream) { - struct rkcif_sensor_info *sensor; + struct rkcif_sensor_info *sensor, *terminal_sensor; struct v4l2_subdev *sensor_sd; int ret = 0; @@ -499,7 +499,8 @@ static int rkcif_update_sensor_info(struct rkcif_stream *stream) return ret; stream->cifdev->active_sensor = sensor; - get_remote_terminal_sensor(stream, &stream->cifdev->terminal_sensor); + terminal_sensor = &stream->cifdev->terminal_sensor; + get_remote_terminal_sensor(stream, &terminal_sensor->sd); return ret; } @@ -1131,12 +1132,12 @@ static void rkcif_assign_new_buffer_pingpong(struct rkcif_stream *stream, if (stream->curr_buf) { rkcif_write_register(dev, frm0_addr_y, stream->curr_buf->buff_addr[RKCIF_PLANE_Y]); - if (dev->chip_id != CHIP_RV1126_CIF_LITE) + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm0_addr_uv, stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]); } else { rkcif_write_register(dev, frm0_addr_y, dummy_buf->dma_addr); - if (dev->chip_id != CHIP_RV1126_CIF_LITE) + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm0_addr_uv, dummy_buf->dma_addr); } @@ -1151,12 +1152,12 @@ static void rkcif_assign_new_buffer_pingpong(struct rkcif_stream *stream, if (stream->next_buf) { rkcif_write_register(dev, frm1_addr_y, stream->next_buf->buff_addr[RKCIF_PLANE_Y]); - if (dev->chip_id != CHIP_RV1126_CIF_LITE) + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm1_addr_uv, stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]); } else { rkcif_write_register(dev, frm1_addr_y, dummy_buf->dma_addr); - if (dev->chip_id != CHIP_RV1126_CIF_LITE) + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm1_addr_uv, dummy_buf->dma_addr); } spin_unlock(&stream->vbq_lock); @@ -1203,12 +1204,12 @@ static void rkcif_assign_new_buffer_pingpong(struct rkcif_stream *stream, if (buffer) { rkcif_write_register(dev, frm_addr_y, buffer->buff_addr[RKCIF_PLANE_Y]); - if (dev->chip_id != CHIP_RV1126_CIF_LITE) + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm_addr_uv, buffer->buff_addr[RKCIF_PLANE_CBCR]); } else { rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr); - if (dev->chip_id != CHIP_RV1126_CIF_LITE) + if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW) rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr); v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "frame Drop to dummy buf\n"); @@ -1271,12 +1272,20 @@ static void rkcif_csi_set_lvds_sav_eav(struct rkcif_stream *stream, } else { if (channel->id == RKCIF_STREAM_MIPI_ID0) frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_LONG]; - else if (channel->id == RKCIF_STREAM_MIPI_ID1) - frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_SHORT]; - else if (channel->id == RKCIF_STREAM_MIPI_ID2) - frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_MEDIUM]; - else - frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_LONG]; + + if (dev->hdr.mode == HDR_X2) { + if (channel->id == RKCIF_STREAM_MIPI_ID1) + frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_SHORT]; + else + frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_LONG]; + } else if (dev->hdr.mode == HDR_X3) { + if (channel->id == RKCIF_STREAM_MIPI_ID1) + frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_MEDIUM]; + else if (channel->id == RKCIF_STREAM_MIPI_ID2) + frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_SHORT]; + else + frm_sync_code = &lvds_cfg->frm_sync_code[LVDS_CODE_GRP_LONG]; + } odd_sync_code = &frm_sync_code->odd_sync_code; even_sync_code = &frm_sync_code->even_sync_code; @@ -1507,7 +1516,7 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream) channel = &dev->channels[stream->id]; channel->id = stream->id; - ret = v4l2_subdev_call(dev->terminal_sensor, core, + ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, RKMODULE_GET_LVDS_CFG, &channel->lvds_cfg); if (ret) { @@ -1732,8 +1741,9 @@ static void rkcif_stop_streaming(struct vb2_queue *queue) if (dev->hdr.mode != NO_HDR) { unsigned int index; struct rkcif_buffer *tmp_buf; - bool has_added = false; + bool has_added; for (index = 0; index < RDBK_MAX; index++) { + has_added = false; if (dev->rdbk_buf[index]) { if (dev->rdbk_buf[index] != stream->curr_buf && dev->rdbk_buf[index] != stream->next_buf) { @@ -1935,10 +1945,10 @@ static void rkcif_sync_crop_info(struct rkcif_stream *stream) struct v4l2_subdev_selection input_sel; int ret; - if (dev->terminal_sensor) { + if (dev->terminal_sensor.sd) { input_sel.target = V4L2_SEL_TGT_CROP_BOUNDS; - ret = v4l2_subdev_call(dev->terminal_sensor, + ret = v4l2_subdev_call(dev->terminal_sensor.sd, pad, get_selection, NULL, &input_sel); if (!ret) { @@ -2132,6 +2142,7 @@ static int rkcif_start_streaming(struct vb2_queue *queue, unsigned int count) struct rkcif_device *dev = stream->cifdev; struct v4l2_device *v4l2_dev = &dev->v4l2_dev; struct rkcif_sensor_info *sensor_info = dev->active_sensor; + struct rkcif_sensor_info *terminal_sensor = &dev->terminal_sensor; struct rkmodule_hdr_cfg hdr_cfg; int ret; @@ -2153,8 +2164,8 @@ static int rkcif_start_streaming(struct vb2_queue *queue, unsigned int count) } } - if (dev->terminal_sensor) { - ret = v4l2_subdev_call(dev->terminal_sensor, + if (terminal_sensor->sd) { + ret = v4l2_subdev_call(terminal_sensor->sd, core, ioctl, RKMODULE_GET_HDR_CFG, &hdr_cfg); @@ -2163,6 +2174,11 @@ static int rkcif_start_streaming(struct vb2_queue *queue, unsigned int count) else dev->hdr.mode = NO_HDR; + ret = v4l2_subdev_call(terminal_sensor->sd, + video, g_frame_interval, &terminal_sensor->fi); + if (ret) + terminal_sensor->fi.interval = (struct v4l2_fract) {1, 30}; + rkcif_sync_crop_info(stream); } @@ -2327,8 +2343,8 @@ static void rkcif_set_fmt(struct rkcif_stream *stream, get_input_fmt(dev->active_sensor->sd, &input_rect, stream->id + 1); - if (dev->terminal_sensor) { - ret = v4l2_subdev_call(dev->terminal_sensor, + if (dev->terminal_sensor.sd) { + ret = v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl, RKMODULE_GET_HDR_CFG, &hdr_cfg); @@ -3434,39 +3450,126 @@ static int rkcif_csi_g_mipi_id(struct v4l2_device *v4l2_dev, return -EINVAL; } -static void rdbk_frame_end(struct rkcif_stream *stream) +static void rkcif_rdbk_frame_end(struct rkcif_stream *stream) { struct rkcif_device *dev = stream->cifdev; - u64 l_ts, s_ts; + struct rkcif_sensor_info *sensor = &stream->cifdev->terminal_sensor; + u32 denominator, numerator; + u64 l_ts, m_ts, s_ts, time = 30000000LL; + int ret, fps = -1; - if (stream->id != RKCIF_STREAM_MIPI_ID1) - return; + if (dev->hdr.mode == HDR_X2) { + if (stream->id != RKCIF_STREAM_MIPI_ID1 || + dev->stream[RKCIF_STREAM_MIPI_ID0].state != RKCIF_STATE_STREAMING || + dev->stream[RKCIF_STREAM_MIPI_ID1].state != RKCIF_STATE_STREAMING) + return; + } else if (dev->hdr.mode == HDR_X3) { + if (stream->id != RKCIF_STREAM_MIPI_ID2 || + dev->stream[RKCIF_STREAM_MIPI_ID0].state != RKCIF_STATE_STREAMING || + dev->stream[RKCIF_STREAM_MIPI_ID1].state != RKCIF_STATE_STREAMING || + dev->stream[RKCIF_STREAM_MIPI_ID2].state != RKCIF_STATE_STREAMING) + return; + } + + numerator = sensor->fi.interval.numerator; + denominator = sensor->fi.interval.denominator; + if (denominator && numerator) + time = numerator * 1000 / denominator * 1000 * 1000; if (dev->hdr.mode == HDR_X3) { - /* TODO: HDR_X3 */ - } else if (dev->hdr.mode == HDR_X2) { - if (dev->rdbk_buf[RDBK_L] && dev->rdbk_buf[RDBK_S]) { + if (dev->rdbk_buf[RDBK_L] && + dev->rdbk_buf[RDBK_M] && + dev->rdbk_buf[RDBK_S]) { l_ts = dev->rdbk_buf[RDBK_L]->vb.vb2_buf.timestamp; + m_ts = dev->rdbk_buf[RDBK_M]->vb.vb2_buf.timestamp; s_ts = dev->rdbk_buf[RDBK_S]->vb.vb2_buf.timestamp; + if ((m_ts - l_ts) > time || (s_ts - m_ts) > time) { + ret = v4l2_subdev_call(sensor->sd, + video, + g_frame_interval, + &sensor->fi); + if (!ret) { + denominator = sensor->fi.interval.denominator; + numerator = sensor->fi.interval.numerator; + if (denominator && numerator) { + time = numerator * 1000 / denominator * 1000 * 1000; + fps = denominator / numerator; + } + } - if ((s_ts - l_ts) > 30000000LL || s_ts < l_ts) { + if ((m_ts - l_ts) > time || (s_ts - m_ts) > time) { + v4l2_err(&dev->v4l2_dev, + "timestamp no match, s:%lld m:%lld l:%lld, fps:%d\n", + s_ts, m_ts, l_ts, fps); + goto RDBK_FRM_UNMATCH; + } + } + + if (m_ts < l_ts || s_ts < m_ts) { v4l2_err(&dev->v4l2_dev, - "HDR_X2:timestamp is not match (%lld, %lld)\n", - l_ts, s_ts); + "s/m/l frame err, timestamp s:%lld m:%lld l:%lld\n", + s_ts, m_ts, l_ts); goto RDBK_FRM_UNMATCH; } - dev->rdbk_buf[RDBK_S]->vb.sequence = - dev->rdbk_buf[RDBK_L]->vb.sequence; + dev->rdbk_buf[RDBK_M]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence; + dev->rdbk_buf[RDBK_S]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence; rkcif_vb_done_oneframe(stream, &dev->rdbk_buf[RDBK_L]->vb); + rkcif_vb_done_oneframe(stream, &dev->rdbk_buf[RDBK_M]->vb); rkcif_vb_done_oneframe(stream, &dev->rdbk_buf[RDBK_S]->vb); } else { if (!dev->rdbk_buf[RDBK_L]) v4l2_err(&dev->v4l2_dev, "lost long frames\n"); + if (!dev->rdbk_buf[RDBK_M]) + v4l2_err(&dev->v4l2_dev, "lost medium frames\n"); if (!dev->rdbk_buf[RDBK_S]) v4l2_err(&dev->v4l2_dev, "lost short frames\n"); goto RDBK_FRM_UNMATCH; } + } else if (dev->hdr.mode == HDR_X2) { + if (dev->rdbk_buf[RDBK_L] && dev->rdbk_buf[RDBK_M]) { + l_ts = dev->rdbk_buf[RDBK_L]->vb.vb2_buf.timestamp; + s_ts = dev->rdbk_buf[RDBK_M]->vb.vb2_buf.timestamp; + + if ((s_ts - l_ts) > time) { + ret = v4l2_subdev_call(sensor->sd, + video, + g_frame_interval, + &sensor->fi); + if (!ret) { + denominator = sensor->fi.interval.denominator; + numerator = sensor->fi.interval.numerator; + if (denominator && numerator) { + time = numerator * 1000 / denominator * 1000 * 1000; + fps = denominator / numerator; + } + } + if ((s_ts - l_ts) > time) { + v4l2_err(&dev->v4l2_dev, + "timestamp no match, s:%lld l:%lld, fps:%d\n", + s_ts, l_ts, fps); + goto RDBK_FRM_UNMATCH; + } + } + + if (s_ts < l_ts) { + v4l2_err(&dev->v4l2_dev, + "s/l frame err, timestamp s:%lld l:%lld\n", + s_ts, l_ts); + goto RDBK_FRM_UNMATCH; + } + + dev->rdbk_buf[RDBK_M]->vb.sequence = + dev->rdbk_buf[RDBK_L]->vb.sequence; + rkcif_vb_done_oneframe(stream, &dev->rdbk_buf[RDBK_L]->vb); + rkcif_vb_done_oneframe(stream, &dev->rdbk_buf[RDBK_M]->vb); + } else { + if (!dev->rdbk_buf[RDBK_L]) + v4l2_err(&dev->v4l2_dev, "lost long frames\n"); + if (!dev->rdbk_buf[RDBK_M]) + v4l2_err(&dev->v4l2_dev, "lost short frames\n"); + goto RDBK_FRM_UNMATCH; + } } else { rkcif_vb_done_oneframe(stream, &dev->rdbk_buf[RDBK_S]->vb); } @@ -3622,11 +3725,12 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) if (cif_dev->hdr.mode == NO_HDR) { if (active_buf) rkcif_vb_done_oneframe(stream, vb_done); - } else if (cif_dev->hdr.mode == HDR_X2) { + } else { if (mipi_id == RKCIF_STREAM_MIPI_ID0) { if (cif_dev->rdbk_buf[RDBK_L]) { v4l2_err(&cif_dev->v4l2_dev, - "multiple long data in hdr frame,frm_idx:%d,state:0x%x\n", + "multiple long data in %s frame,frm_idx:%d,state:0x%x\n", + cif_dev->hdr.mode == HDR_X2 ? "hdr_x2" : "hdr_x3", stream->frame_idx, cif_dev->rdbk_buf[RDBK_L]->vb.vb2_buf.state); cif_dev->rdbk_buf[RDBK_L]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; @@ -3634,18 +3738,32 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) } cif_dev->rdbk_buf[RDBK_L] = active_buf; } else if (mipi_id == RKCIF_STREAM_MIPI_ID1) { + if (cif_dev->rdbk_buf[RDBK_M]) { + v4l2_err(&cif_dev->v4l2_dev, + "multiple %s frame,frm_idx:%d,state:0x%x\n", + cif_dev->hdr.mode == HDR_X2 ? "short data in hdr_x2" : "medium data in hdr_x3", + stream->frame_idx, + cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf.state); + cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; + rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf); + } + cif_dev->rdbk_buf[RDBK_M] = active_buf; + if (cif_dev->hdr.mode == HDR_X2) + rkcif_rdbk_frame_end(stream); + } else if (mipi_id == RKCIF_STREAM_MIPI_ID2) { if (cif_dev->rdbk_buf[RDBK_S]) { v4l2_err(&cif_dev->v4l2_dev, - "multiple short data in hdr frame, state:0x%x\n", + "multiple %s frame, frm_idx:%d,state:0x%x\n", + cif_dev->hdr.mode == HDR_X2 ? "err short data in hdr_x3" : "short data in hdr_x3", + stream->frame_idx, cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf.state); cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf); } cif_dev->rdbk_buf[RDBK_S] = active_buf; - rdbk_frame_end(stream); + if (cif_dev->hdr.mode == HDR_X3) + rkcif_rdbk_frame_end(stream); } - } else if (cif_dev->hdr.mode == HDR_X3) { - /*TODO: HDR_X3*/ } } } else { @@ -3841,11 +3959,12 @@ void rkcif_irq_lite_lvds(struct rkcif_device *cif_dev) if (cif_dev->hdr.mode == NO_HDR) { if (active_buf) rkcif_vb_done_oneframe(stream, vb_done); - } else if (cif_dev->hdr.mode == HDR_X2) { + } else { if (mipi_id == RKCIF_STREAM_MIPI_ID0) { if (cif_dev->rdbk_buf[RDBK_L]) { v4l2_err(&cif_dev->v4l2_dev, - "cif lite multiple long data in hdr frame,frm_idx:%d,state:0x%x\n", + "cif lite multiple long data in %s frame,frm_idx:%d,state:0x%x\n", + cif_dev->hdr.mode == HDR_X2 ? "hdr_x2" : "hdr_x3", stream->frame_idx, cif_dev->rdbk_buf[RDBK_L]->vb.vb2_buf.state); cif_dev->rdbk_buf[RDBK_L]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; @@ -3853,18 +3972,32 @@ void rkcif_irq_lite_lvds(struct rkcif_device *cif_dev) } cif_dev->rdbk_buf[RDBK_L] = active_buf; } else if (mipi_id == RKCIF_STREAM_MIPI_ID1) { + if (cif_dev->rdbk_buf[RDBK_M]) { + v4l2_err(&cif_dev->v4l2_dev, + "cif lite multiple %s frame,frm_idx:%d, state:0x%x\n", + cif_dev->hdr.mode == HDR_X2 ? "short data in hdr_x2" : "medium data in hdr_x3", + stream->frame_idx, + cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf.state); + cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; + rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_M]->vb.vb2_buf); + } + cif_dev->rdbk_buf[RDBK_M] = active_buf; + if (cif_dev->hdr.mode == HDR_X2) + rkcif_rdbk_frame_end(stream); + } else if (mipi_id == RKCIF_STREAM_MIPI_ID2) { if (cif_dev->rdbk_buf[RDBK_S]) { v4l2_err(&cif_dev->v4l2_dev, - "cif lite multiple short data in hdr frame, state:0x%x\n", + "multiple %s frame, frm_idx:%d,state:0x%x\n", + cif_dev->hdr.mode == HDR_X2 ? "err short data in hdr_x3" : "short data in hdr_x3", + stream->frame_idx, cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf.state); cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE; rkcif_buf_queue(&cif_dev->rdbk_buf[RDBK_S]->vb.vb2_buf); } cif_dev->rdbk_buf[RDBK_S] = active_buf; - rdbk_frame_end(stream); + if (cif_dev->hdr.mode == HDR_X3) + rkcif_rdbk_frame_end(stream); } - } else if (cif_dev->hdr.mode == HDR_X3) { - /*TODO: HDR_X3*/ } } } diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 2f44909ef821..5ec53e5c04e7 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -159,11 +159,15 @@ extern int rkcif_debug; /* * struct rkcif_sensor_info - Sensor infomations + * @sd: v4l2 subdev of sensor * @mbus: media bus configuration + * @fi: v4l2 subdev frame interval + * @lanes: lane num of sensor */ struct rkcif_sensor_info { struct v4l2_subdev *sd; struct v4l2_mbus_config mbus; + struct v4l2_subdev_frame_interval fi; int lanes; }; @@ -350,7 +354,7 @@ struct rkcif_device { struct rkcif_sensor_info sensors[RKCIF_MAX_SENSOR]; u32 num_sensors; struct rkcif_sensor_info *active_sensor; - struct v4l2_subdev *terminal_sensor; + struct rkcif_sensor_info terminal_sensor; struct rkcif_stream stream[RKCIF_MULTI_STREAMS_NUM]; struct rkcif_pipeline pipe; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index e45040ae6348..7689f3662065 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -94,8 +94,8 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) struct rkcif_device *cif_dev = priv->cif_dev; struct v4l2_subdev *sensor_sd; - if (cif_dev->terminal_sensor) { - sensor_sd = cif_dev->terminal_sensor; + if (cif_dev->terminal_sensor.sd) { + sensor_sd = cif_dev->terminal_sensor.sd; return v4l2_subdev_call(sensor_sd, core, ioctl, cmd, arg); } @@ -110,8 +110,8 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd, struct rkcif_device *cif_dev = priv->cif_dev; struct v4l2_subdev *sensor_sd; - if (cif_dev->terminal_sensor) { - sensor_sd = cif_dev->terminal_sensor; + if (cif_dev->terminal_sensor.sd) { + sensor_sd = cif_dev->terminal_sensor.sd; return v4l2_subdev_call(sensor_sd, core, compat_ioctl32, cmd, arg); }