From e7dcca347192008daa0e44f352ba61aa6f91c81c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 21 Dec 2023 18:03:34 +0000 Subject: [PATCH] media: i2c: adv7180: Add support for V4L2_CID_LINK_FREQ For CSI2 receivers that need to know the link frequency, add it as a control to the driver. Interlaced modes are 216Mbp/s or 108MHz, whilst going through the I2P to deinterlace gives 432Mb/s or 216MHz. Signed-off-by: Dave Stevenson --- drivers/media/i2c/adv7180.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index f165f78ee7c7..e9fe1bceab65 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -189,6 +189,16 @@ /* Initial number of frames to skip to avoid possible garbage */ #define ADV7180_NUM_OF_SKIP_FRAMES 2 +enum adv7180_link_freq_idx { + INTERLACED_IDX, + I2P_IDX, +}; + +static const s64 adv7180_link_freqs[] = { + [INTERLACED_IDX] = 108000000, + [I2P_IDX] = 216000000, +}; + static int dbg_input; module_param(dbg_input, int, 0644); MODULE_PARM_DESC(dbg_input, "Input number (0-31)"); @@ -228,6 +238,7 @@ struct adv7180_state { const struct adv7180_chip_info *chip_info; enum v4l2_field field; bool force_bt656_4; + struct v4l2_ctrl *link_freq; }; #define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \ struct adv7180_state, \ @@ -621,6 +632,9 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) if (ret) return ret; + if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) + goto unlock; + val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -662,6 +676,7 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) ret = -EINVAL; } +unlock: mutex_unlock(&state->mutex); return ret; } @@ -682,7 +697,7 @@ static const struct v4l2_ctrl_config adv7180_ctrl_fast_switch = { static int adv7180_init_controls(struct adv7180_state *state) { - v4l2_ctrl_handler_init(&state->ctrl_hdl, 4); + v4l2_ctrl_handler_init(&state->ctrl_hdl, 5); v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops, V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN, @@ -704,6 +719,17 @@ static int adv7180_init_controls(struct adv7180_state *state) 0, ARRAY_SIZE(test_pattern_menu) - 1, test_pattern_menu); + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { + state->link_freq = + v4l2_ctrl_new_int_menu(&state->ctrl_hdl, + &adv7180_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(adv7180_link_freqs) - 1, + 0, adv7180_link_freqs); + if (state->link_freq) + state->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + } + state->sd.ctrl_handler = &state->ctrl_hdl; if (state->ctrl_hdl.error) { int err = state->ctrl_hdl.error; @@ -836,6 +862,10 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd, adv7180_set_power(state, false); adv7180_set_field_mode(state); adv7180_set_power(state, true); + if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) + __v4l2_ctrl_s_ctrl(state->link_freq, + (state->field == V4L2_FIELD_NONE) ? + I2P_IDX : INTERLACED_IDX); } } else { framefmt = v4l2_subdev_get_try_format(sd, sd_state, 0);