1c906e963f658d6f37d855cc1156ea617ef3369f
[openwrt/staging/neocturne.git] /
1 From 4721f56a81e13353f6900a7346bebf330d3d560b Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 31 Mar 2022 16:45:36 +0100
4 Subject: [PATCH] media: i2c: imx258: Add support for long exposure
5 modes
6
7 The sensor has a register CIT_LSHIFT which extends the exposure
8 and frame times by the specified power of 2 for longer
9 exposure times.
10
11 Add support for this by configuring this register via V4L2_CID_VBLANK
12 and extending the V4L2_CID_EXPOSURE range accordingly.
13
14 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
15 ---
16 drivers/media/i2c/imx258.c | 38 ++++++++++++++++++++++++++++++++------
17 1 file changed, 32 insertions(+), 6 deletions(-)
18
19 --- a/drivers/media/i2c/imx258.c
20 +++ b/drivers/media/i2c/imx258.c
21 @@ -69,6 +69,10 @@
22 #define IMX258_HDR_RATIO_STEP 1
23 #define IMX258_HDR_RATIO_DEFAULT 0x0
24
25 +/* Long exposure multiplier */
26 +#define IMX258_LONG_EXP_SHIFT_MAX 7
27 +#define IMX258_LONG_EXP_SHIFT_REG 0x3002
28 +
29 /* Test Pattern Control */
30 #define IMX258_REG_TEST_PATTERN 0x0600
31
32 @@ -843,6 +847,8 @@ struct imx258 {
33 struct v4l2_ctrl *exposure;
34 struct v4l2_ctrl *hflip;
35 struct v4l2_ctrl *vflip;
36 + /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
37 + unsigned int long_exp_shift;
38
39 /* Current mode */
40 const struct imx258_mode *cur_mode;
41 @@ -1020,6 +1026,26 @@ static void imx258_adjust_exposure_range
42 exposure_def);
43 }
44
45 +static int imx258_set_frame_length(struct imx258 *imx258, unsigned int val)
46 +{
47 + int ret;
48 +
49 + imx258->long_exp_shift = 0;
50 +
51 + while (val > IMX258_VTS_MAX) {
52 + imx258->long_exp_shift++;
53 + val >>= 1;
54 + }
55 +
56 + ret = imx258_write_reg(imx258, IMX258_REG_VTS,
57 + IMX258_REG_VALUE_16BIT, val);
58 + if (ret)
59 + return ret;
60 +
61 + return imx258_write_reg(imx258, IMX258_LONG_EXP_SHIFT_REG,
62 + IMX258_REG_VALUE_08BIT, imx258->long_exp_shift);
63 +}
64 +
65 static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
66 {
67 struct imx258 *imx258 =
68 @@ -1050,7 +1076,7 @@ static int imx258_set_ctrl(struct v4l2_c
69 case V4L2_CID_EXPOSURE:
70 ret = imx258_write_reg(imx258, IMX258_REG_EXPOSURE,
71 IMX258_REG_VALUE_16BIT,
72 - ctrl->val);
73 + ctrl->val >> imx258->long_exp_shift);
74 break;
75 case V4L2_CID_DIGITAL_GAIN:
76 ret = imx258_update_digital_gain(imx258, IMX258_REG_VALUE_16BIT,
77 @@ -1078,9 +1104,8 @@ static int imx258_set_ctrl(struct v4l2_c
78 }
79 break;
80 case V4L2_CID_VBLANK:
81 - ret = imx258_write_reg(imx258, IMX258_REG_VTS,
82 - IMX258_REG_VALUE_16BIT,
83 - imx258->cur_mode->height + ctrl->val);
84 + ret = imx258_set_frame_length(imx258,
85 + imx258->cur_mode->height + ctrl->val);
86 break;
87 case V4L2_CID_VFLIP:
88 case V4L2_CID_HFLIP:
89 @@ -1218,8 +1243,9 @@ static int imx258_set_pad_format(struct
90 imx258->cur_mode->height;
91 __v4l2_ctrl_modify_range(
92 imx258->vblank, vblank_min,
93 - IMX258_VTS_MAX - imx258->cur_mode->height, 1,
94 - vblank_def);
95 + ((1 << IMX258_LONG_EXP_SHIFT_MAX) * IMX258_VTS_MAX) -
96 + imx258->cur_mode->height,
97 + 1, vblank_def);
98 __v4l2_ctrl_s_ctrl(imx258->vblank, vblank_def);
99 h_blank =
100 imx258->link_freq_configs[mode->link_freq_index].pixels_per_line