[SRU][N:linux-xilinx][PATCH v2 06/14] drivers: media: i2c: imx708: Fix WIDE_DYNAMIC_RANGE control with long exposure
Stewart Hore
stewart.hore at canonical.com
Sun Oct 19 04:15:27 UTC 2025
From: David Plowman <david.plowman at raspberrypi.com>
BugLink: https://bugs.launchpad.net/bugs/2127886
Setting V4L2_CID_WIDE_DYNAMIC_RANGE was causing the long exposure
shift count to be reset, which is incorrect if the user has already
changed the frame length to cause it to have a non-zero value.
Because it only updates control ranges and doesn't set any registers,
the control can also be applied when the sensor is not powered on.
Signed-off-by: David Plowman <david.plowman at raspberrypi.com>
(cherry picked from commit cdf4a3716c8bc0bc6d8715a8ac10e2c759e1682b rpi-6.6.y)
Signed-off-by: Juerg Haefliger <juerg.haefliger at canonical.com>
(cherry picked from commit 9d40b73edd44ba680d390019141e518c7adb735e noble:linux-raspi)
Signed-off-by: Stewart Hore <stewart.hore at canonical.com>
---
drivers/media/i2c/imx708.c | 45 ++++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/drivers/media/i2c/imx708.c b/drivers/media/i2c/imx708.c
index 0f8fad5d7b02..f046d896bc78 100644
--- a/drivers/media/i2c/imx708.c
+++ b/drivers/media/i2c/imx708.c
@@ -171,7 +171,7 @@ struct imx708_mode {
/* Not all modes have the same exposure lines step. */
u32 exposure_lines_step;
- /* HDR flag, currently not used at runtime */
+ /* HDR flag, used for checking if the current mode is HDR */
bool hdr;
};
@@ -1060,9 +1060,6 @@ static void imx708_set_framing_limits(struct imx708 *imx708)
unsigned int hblank;
const struct imx708_mode *mode = imx708->mode;
- /* Default to no long exposure multiplier */
- imx708->long_exp_shift = 0;
-
__v4l2_ctrl_modify_range(imx708->pixel_rate,
mode->pixel_rate, mode->pixel_rate,
1, mode->pixel_rate);
@@ -1091,12 +1088,33 @@ static int imx708_set_ctrl(struct v4l2_ctrl *ctrl)
unsigned int code, num_modes;
int ret = 0;
- /*
- * The VBLANK control may change the limits of usable exposure, so check
- * and adjust if necessary.
- */
- if (ctrl->id == V4L2_CID_VBLANK)
+ switch (ctrl->id) {
+ case V4L2_CID_VBLANK:
+ /*
+ * The VBLANK control may change the limits of usable exposure,
+ * so check and adjust if necessary.
+ */
imx708_adjust_exposure_range(imx708, ctrl);
+ break;
+
+ case V4L2_CID_WIDE_DYNAMIC_RANGE:
+ /*
+ * The WIDE_DYNAMIC_RANGE control can also be applied immediately
+ * as it doesn't set any registers. Don't do anything if the mode
+ * already matches.
+ */
+ if (imx708->mode && imx708->mode->hdr != ctrl->val) {
+ code = imx708_get_format_code(imx708);
+ get_mode_table(code, &mode_list, &num_modes, ctrl->val);
+ imx708->mode = v4l2_find_nearest_size(mode_list,
+ num_modes,
+ width, height,
+ imx708->mode->width,
+ imx708->mode->height);
+ imx708_set_framing_limits(imx708);
+ }
+ break;
+ }
/*
* Applying V4L2 control value only happens
@@ -1158,14 +1176,7 @@ static int imx708_set_ctrl(struct v4l2_ctrl *ctrl)
imx708->notify_gains->p_new.p_u32[3]);
break;
case V4L2_CID_WIDE_DYNAMIC_RANGE:
- code = imx708_get_format_code(imx708);
- get_mode_table(code, &mode_list, &num_modes, ctrl->val);
- imx708->mode = v4l2_find_nearest_size(mode_list,
- num_modes,
- width, height,
- imx708->mode->width,
- imx708->mode->height);
- imx708_set_framing_limits(imx708);
+ /* Already handled above. */
break;
default:
dev_info(&client->dev,
--
2.48.1
More information about the kernel-team
mailing list