1 From 700a1a11144c9b18b9da3d900a1d8bfa30a195a8 Mon Sep 17 00:00:00 2001
2 From: David Plowman <david.plowman@raspberrypi.com>
3 Date: Wed, 22 Mar 2023 12:01:57 +0000
4 Subject: [PATCH] drivers: media: i2c: imx708: Fix WIDE_DYNAMIC_RANGE
5 control with long exposure
7 Setting V4L2_CID_WIDE_DYNAMIC_RANGE was causing the long exposure
8 shift count to be reset, which is incorrect if the user has already
9 changed the frame length to cause it to have a non-zero value.
11 Because it only updates control ranges and doesn't set any registers,
12 the control can also be applied when the sensor is not powered on.
14 Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
16 drivers/media/i2c/imx708.c | 45 ++++++++++++++++++++++++--------------
17 1 file changed, 28 insertions(+), 17 deletions(-)
19 --- a/drivers/media/i2c/imx708.c
20 +++ b/drivers/media/i2c/imx708.c
21 @@ -171,7 +171,7 @@ struct imx708_mode {
22 /* Not all modes have the same exposure lines step. */
23 u32 exposure_lines_step;
25 - /* HDR flag, currently not used at runtime */
26 + /* HDR flag, used for checking if the current mode is HDR */
30 @@ -1060,9 +1060,6 @@ static void imx708_set_framing_limits(st
32 const struct imx708_mode *mode = imx708->mode;
34 - /* Default to no long exposure multiplier */
35 - imx708->long_exp_shift = 0;
37 __v4l2_ctrl_modify_range(imx708->pixel_rate,
38 mode->pixel_rate, mode->pixel_rate,
40 @@ -1091,12 +1088,33 @@ static int imx708_set_ctrl(struct v4l2_c
41 unsigned int code, num_modes;
45 - * The VBLANK control may change the limits of usable exposure, so check
46 - * and adjust if necessary.
48 - if (ctrl->id == V4L2_CID_VBLANK)
50 + case V4L2_CID_VBLANK:
52 + * The VBLANK control may change the limits of usable exposure,
53 + * so check and adjust if necessary.
55 imx708_adjust_exposure_range(imx708, ctrl);
58 + case V4L2_CID_WIDE_DYNAMIC_RANGE:
60 + * The WIDE_DYNAMIC_RANGE control can also be applied immediately
61 + * as it doesn't set any registers. Don't do anything if the mode
64 + if (imx708->mode && imx708->mode->hdr != ctrl->val) {
65 + code = imx708_get_format_code(imx708);
66 + get_mode_table(code, &mode_list, &num_modes, ctrl->val);
67 + imx708->mode = v4l2_find_nearest_size(mode_list,
70 + imx708->mode->width,
71 + imx708->mode->height);
72 + imx708_set_framing_limits(imx708);
78 * Applying V4L2 control value only happens
79 @@ -1158,14 +1176,7 @@ static int imx708_set_ctrl(struct v4l2_c
80 imx708->notify_gains->p_new.p_u32[3]);
82 case V4L2_CID_WIDE_DYNAMIC_RANGE:
83 - code = imx708_get_format_code(imx708);
84 - get_mode_table(code, &mode_list, &num_modes, ctrl->val);
85 - imx708->mode = v4l2_find_nearest_size(mode_list,
88 - imx708->mode->width,
89 - imx708->mode->height);
90 - imx708_set_framing_limits(imx708);
91 + /* Already handled above. */
94 dev_info(&client->dev,