c6e568e79d8dac18eba356861164da0c95cf55e0
[openwrt/staging/linusw.git] /
1 From f6523a46d1ad95d1f269a691ddb7998c86b9264f Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 16 Jun 2021 17:19:17 +0100
4 Subject: [PATCH] media: i2c: imx258: Follow normal V4L2 behaviours for
5 clipping exposure
6
7 V4L2 sensor drivers are expected are expected to clip the supported
8 exposure range based on the VBLANK configured.
9 IMX258 wasn't doing that as register 0x350 (FRM_LENGTH_CTL)
10 switches it to a mode where frame length tracks coarse exposure time.
11
12 Disable this mode and clip the range for V4L2_CID_EXPOSURE appropriately
13 based on V4L2_CID_VBLANK.
14
15 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
16 ---
17 drivers/media/i2c/imx258.c | 35 ++++++++++++++++++++++++++++-------
18 1 file changed, 28 insertions(+), 7 deletions(-)
19
20 --- a/drivers/media/i2c/imx258.c
21 +++ b/drivers/media/i2c/imx258.c
22 @@ -32,15 +32,16 @@
23
24 #define IMX258_REG_VTS 0x0340
25
26 -/* HBLANK control - read only */
27 -#define IMX258_PPL_DEFAULT 5352
28 -
29 /* Exposure control */
30 #define IMX258_REG_EXPOSURE 0x0202
31 +#define IMX258_EXPOSURE_OFFSET 10
32 #define IMX258_EXPOSURE_MIN 4
33 #define IMX258_EXPOSURE_STEP 1
34 #define IMX258_EXPOSURE_DEFAULT 0x640
35 -#define IMX258_EXPOSURE_MAX 65535
36 +#define IMX258_EXPOSURE_MAX (IMX258_VTS_MAX - IMX258_EXPOSURE_OFFSET)
37 +
38 +/* HBLANK control - read only */
39 +#define IMX258_PPL_DEFAULT 5352
40
41 /* Analog gain control */
42 #define IMX258_REG_ANALOG_GAIN 0x0204
43 @@ -377,7 +378,7 @@ static const struct imx258_reg mode_4208
44 { 0x034D, 0x70 },
45 { 0x034E, 0x0C },
46 { 0x034F, 0x30 },
47 - { 0x0350, 0x01 },
48 + { 0x0350, 0x00 },
49 { 0x0204, 0x00 },
50 { 0x0205, 0x00 },
51 { 0x020E, 0x01 },
52 @@ -489,7 +490,7 @@ static const struct imx258_reg mode_2104
53 { 0x034D, 0x38 },
54 { 0x034E, 0x06 },
55 { 0x034F, 0x18 },
56 - { 0x0350, 0x01 },
57 + { 0x0350, 0x00 },
58 { 0x0204, 0x00 },
59 { 0x0205, 0x00 },
60 { 0x020E, 0x01 },
61 @@ -601,7 +602,7 @@ static const struct imx258_reg mode_1048
62 { 0x034D, 0x18 },
63 { 0x034E, 0x03 },
64 { 0x034F, 0x0C },
65 - { 0x0350, 0x01 },
66 + { 0x0350, 0x00 },
67 { 0x0204, 0x00 },
68 { 0x0205, 0x00 },
69 { 0x020E, 0x01 },
70 @@ -966,6 +967,19 @@ static int imx258_update_digital_gain(st
71 return 0;
72 }
73
74 +static void imx258_adjust_exposure_range(struct imx258 *imx258)
75 +{
76 + int exposure_max, exposure_def;
77 +
78 + /* Honour the VBLANK limits when setting exposure. */
79 + exposure_max = imx258->cur_mode->height + imx258->vblank->val -
80 + IMX258_EXPOSURE_OFFSET;
81 + exposure_def = min(exposure_max, imx258->exposure->val);
82 + __v4l2_ctrl_modify_range(imx258->exposure, imx258->exposure->minimum,
83 + exposure_max, imx258->exposure->step,
84 + exposure_def);
85 +}
86 +
87 static int imx258_set_ctrl(struct v4l2_ctrl *ctrl)
88 {
89 struct imx258 *imx258 =
90 @@ -974,6 +988,13 @@ static int imx258_set_ctrl(struct v4l2_c
91 int ret = 0;
92
93 /*
94 + * The VBLANK control may change the limits of usable exposure, so check
95 + * and adjust if necessary.
96 + */
97 + if (ctrl->id == V4L2_CID_VBLANK)
98 + imx258_adjust_exposure_range(imx258);
99 +
100 + /*
101 * Applying V4L2 control value only happens
102 * when power is up for streaming
103 */