bcm27xx: 6.1: add kernel patches
[openwrt/staging/stintel.git] / target / linux / bcm27xx / patches-6.1 / 950-0533-drivers-media-imx708-Enable-long-exposure-mode.patch
1 From 321814f1f361336278e9d682492152098b0a0f00 Mon Sep 17 00:00:00 2001
2 From: Naushir Patuck <naush@raspberrypi.com>
3 Date: Thu, 5 Jan 2023 14:44:48 +0000
4 Subject: [PATCH] drivers: media: imx708: Enable long exposure mode
5
6 Enable long exposure modes by using the long exposure shift register setting
7 in the imx708 sensor.
8
9 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
10 ---
11 drivers/media/i2c/imx708.c | 41 +++++++++++++++++++++++++++++++++-----
12 1 file changed, 36 insertions(+), 5 deletions(-)
13
14 --- a/drivers/media/i2c/imx708.c
15 +++ b/drivers/media/i2c/imx708.c
16 @@ -44,6 +44,10 @@
17 #define IMX708_REG_FRAME_LENGTH 0x0340
18 #define IMX708_FRAME_LENGTH_MAX 0xffff
19
20 +/* Long exposure multiplier */
21 +#define IMX708_LONG_EXP_SHIFT_MAX 7
22 +#define IMX708_LONG_EXP_SHIFT_REG 0x3100
23 +
24 /* Exposure control */
25 #define IMX708_REG_EXPOSURE 0x0202
26 #define IMX708_EXPOSURE_OFFSET 48
27 @@ -806,6 +810,9 @@ struct imx708 {
28
29 /* Rewrite common registers on stream on? */
30 bool common_regs_written;
31 +
32 + /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
33 + unsigned int long_exp_shift;
34 };
35
36 static inline struct imx708 *to_imx708(struct v4l2_subdev *_sd)
37 @@ -994,7 +1001,8 @@ static int imx708_set_exposure(struct im
38 * will automatically divide the medium and short ones by 4,16.
39 */
40 ret = imx708_write_reg(imx708, IMX708_REG_EXPOSURE,
41 - IMX708_REG_VALUE_16BIT, val);
42 + IMX708_REG_VALUE_16BIT,
43 + val >> imx708->long_exp_shift);
44
45 return ret;
46 }
47 @@ -1027,18 +1035,42 @@ static int imx708_set_analogue_gain(stru
48 return ret;
49 }
50
51 +static int imx708_set_frame_length(struct imx708 *imx708, unsigned int val)
52 +{
53 + int ret = 0;
54 +
55 + imx708->long_exp_shift = 0;
56 +
57 + while (val > IMX708_FRAME_LENGTH_MAX) {
58 + imx708->long_exp_shift++;
59 + val >>= 1;
60 + }
61 +
62 + ret = imx708_write_reg(imx708, IMX708_REG_FRAME_LENGTH,
63 + IMX708_REG_VALUE_16BIT, val);
64 + if (ret)
65 + return ret;
66 +
67 + return imx708_write_reg(imx708, IMX708_LONG_EXP_SHIFT_REG,
68 + IMX708_REG_VALUE_08BIT, imx708->long_exp_shift);
69 +}
70 +
71 static void imx708_set_framing_limits(struct imx708 *imx708)
72 {
73 unsigned int hblank;
74 const struct imx708_mode *mode = imx708->mode;
75
76 + /* Default to no long exposure multiplier */
77 + imx708->long_exp_shift = 0;
78 +
79 __v4l2_ctrl_modify_range(imx708->pixel_rate,
80 mode->pixel_rate, mode->pixel_rate,
81 1, mode->pixel_rate);
82
83 /* Update limits and set FPS to default */
84 __v4l2_ctrl_modify_range(imx708->vblank, mode->vblank_min,
85 - IMX708_FRAME_LENGTH_MAX - mode->height,
86 + ((1 << IMX708_LONG_EXP_SHIFT_MAX) *
87 + IMX708_FRAME_LENGTH_MAX) - mode->height,
88 1, mode->vblank_default);
89
90 /*
91 @@ -1112,9 +1144,8 @@ static int imx708_set_ctrl(struct v4l2_c
92 imx708->vflip->val << 1);
93 break;
94 case V4L2_CID_VBLANK:
95 - ret = imx708_write_reg(imx708, IMX708_REG_FRAME_LENGTH,
96 - IMX708_REG_VALUE_16BIT,
97 - imx708->mode->height + ctrl->val);
98 + ret = imx708_set_frame_length(imx708,
99 + imx708->mode->height + ctrl->val);
100 break;
101 case V4L2_CID_NOTIFY_GAINS:
102 ret = imx708_write_reg(imx708, IMX708_REG_COLOUR_BALANCE_BLUE,