2d0c0e4ffe811b7f96c69e8a4011a03ace6c1857
[openwrt/staging/blocktrron.git] /
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
6
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.
10
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.
13
14 Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
15 ---
16 drivers/media/i2c/imx708.c | 45 ++++++++++++++++++++++++--------------
17 1 file changed, 28 insertions(+), 17 deletions(-)
18
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;
24
25 - /* HDR flag, currently not used at runtime */
26 + /* HDR flag, used for checking if the current mode is HDR */
27 bool hdr;
28 };
29
30 @@ -1060,9 +1060,6 @@ static void imx708_set_framing_limits(st
31 unsigned int hblank;
32 const struct imx708_mode *mode = imx708->mode;
33
34 - /* Default to no long exposure multiplier */
35 - imx708->long_exp_shift = 0;
36 -
37 __v4l2_ctrl_modify_range(imx708->pixel_rate,
38 mode->pixel_rate, mode->pixel_rate,
39 1, mode->pixel_rate);
40 @@ -1091,12 +1088,33 @@ static int imx708_set_ctrl(struct v4l2_c
41 unsigned int code, num_modes;
42 int ret = 0;
43
44 - /*
45 - * The VBLANK control may change the limits of usable exposure, so check
46 - * and adjust if necessary.
47 - */
48 - if (ctrl->id == V4L2_CID_VBLANK)
49 + switch (ctrl->id) {
50 + case V4L2_CID_VBLANK:
51 + /*
52 + * The VBLANK control may change the limits of usable exposure,
53 + * so check and adjust if necessary.
54 + */
55 imx708_adjust_exposure_range(imx708, ctrl);
56 + break;
57 +
58 + case V4L2_CID_WIDE_DYNAMIC_RANGE:
59 + /*
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
62 + * already matches.
63 + */
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,
68 + num_modes,
69 + width, height,
70 + imx708->mode->width,
71 + imx708->mode->height);
72 + imx708_set_framing_limits(imx708);
73 + }
74 + break;
75 + }
76
77 /*
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]);
81 break;
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,
86 - num_modes,
87 - width, height,
88 - imx708->mode->width,
89 - imx708->mode->height);
90 - imx708_set_framing_limits(imx708);
91 + /* Already handled above. */
92 break;
93 default:
94 dev_info(&client->dev,