bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0737-media-i2c-ov7251-Add-V4L2_CID_VBLANK.patch
1 From 9e6a5b925f3b401c9a047237c0014367655b291a Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 17 Feb 2022 18:08:39 +0000
4 Subject: [PATCH] media: i2c: ov7251: Add V4L2_CID_VBLANK
5
6 This is a raw sensor so should be implementing V4L2_CID_VBLANK
7 instead of the frame_interval ops, as per docs at
8 https://www.kernel.org/doc/html/latest/driver-api/media/camera-sensor.html#frame-interval-configuration
9
10 This driver already implemented the frame_interval ops, so
11 removing them would be a regression.
12 Implement V4L2_CID_VBLANK, with the frame_interval ops setting
13 that control.
14
15 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
16 ---
17 drivers/media/i2c/ov7251.c | 56 +++++++++++++++++++++++++++++---------
18 1 file changed, 43 insertions(+), 13 deletions(-)
19
20 --- a/drivers/media/i2c/ov7251.c
21 +++ b/drivers/media/i2c/ov7251.c
22 @@ -43,6 +43,8 @@
23 #define OV7251_HTS 0x3a0
24 #define OV7251_VTS_HIGH 0x380e
25 #define OV7251_VTS_LOW 0x380f
26 +#define OV7251_VTS_MIN_OFFSET 92
27 +#define OV7251_VTS_MAX 0x7fff
28 #define OV7251_TIMING_FORMAT1 0x3820
29 #define OV7251_TIMING_FORMAT1_VFLIP BIT(2)
30 #define OV7251_TIMING_FORMAT2 0x3821
31 @@ -136,6 +138,7 @@ struct ov7251 {
32 struct v4l2_ctrl_handler ctrls;
33 struct v4l2_ctrl *exposure;
34 struct v4l2_ctrl *hblank;
35 + struct v4l2_ctrl *vblank;
36
37 /* Cached register values */
38 u8 aec_pk_manual;
39 @@ -688,6 +691,19 @@ static int ov7251_set_vflip(struct ov725
40 return ret;
41 }
42
43 +static int ov7251_set_vblank(struct ov7251 *ov7251, s32 value)
44 +{
45 + u16 reg;
46 + u8 val[2];
47 +
48 + reg = OV7251_VTS_HIGH;
49 + value += ov7251->current_mode->height;
50 + val[0] = (value & 0xff00) >> 8; /* goes to OV7251_VTS_HIGH */
51 + val[1] = value & 0xff; /* goes to OV7251_VTS_LOW */
52 +
53 + return ov7251_write_seq_regs(ov7251, reg, val, 2);
54 +}
55 +
56 static int ov7251_set_test_pattern(struct ov7251 *ov7251, s32 value)
57 {
58 u8 val = ov7251->pre_isp_00;
59 @@ -714,9 +730,20 @@ static int ov7251_s_ctrl(struct v4l2_ctr
60 {
61 struct ov7251 *ov7251 = container_of(ctrl->handler,
62 struct ov7251, ctrls);
63 + s64 max;
64 int ret;
65
66 /* v4l2_ctrl_lock() locks our mutex */
67 + switch (ctrl->id) {
68 + case V4L2_CID_VBLANK:
69 + /* Update max exposure while meeting expected vblanking */
70 + max = ov7251->current_mode->height + ctrl->val - OV7251_EXPOSURE_OFFSET;
71 + __v4l2_ctrl_modify_range(ov7251->exposure,
72 + ov7251->exposure->minimum, max,
73 + ov7251->exposure->step,
74 + ov7251->exposure->default_value);
75 + break;
76 + }
77
78 if (!pm_runtime_get_if_in_use(ov7251->dev))
79 return 0;
80 @@ -737,6 +764,9 @@ static int ov7251_s_ctrl(struct v4l2_ctr
81 case V4L2_CID_VFLIP:
82 ret = ov7251_set_vflip(ov7251, ctrl->val);
83 break;
84 + case V4L2_CID_VBLANK:
85 + ret = ov7251_set_vblank(ov7251, ctrl->val);
86 + break;
87 default:
88 ret = -EINVAL;
89 break;
90 @@ -1030,14 +1060,6 @@ static int ov7251_s_stream(struct v4l2_s
91 ov7251->current_mode->height);
92 goto err_power_down;
93 }
94 - ret = ov7251_write_reg(ov7251, OV7251_VTS_HIGH,
95 - ov7251->current_ival->vts >> 8);
96 - if (ret)
97 - goto err_power_down;
98 - ret = ov7251_write_reg(ov7251, OV7251_VTS_LOW,
99 - ov7251->current_ival->vts & 0xff);
100 - if (ret)
101 - goto err_power_down;
102 ret = __v4l2_ctrl_handler_setup(&ov7251->ctrls);
103 if (ret < 0) {
104 dev_err(ov7251->dev, "could not sync v4l2 controls\n");
105 @@ -1088,12 +1110,13 @@ static int ov7251_set_frame_interval(str
106 ret = __v4l2_ctrl_modify_range(ov7251->exposure, 1,
107 new_ival->vts -
108 OV7251_EXPOSURE_OFFSET,
109 - 1, ov7251->current_mode->exposure_def);
110 + 1, ov7251->exposure->val);
111 if (ret < 0)
112 goto exit;
113
114 - ret = __v4l2_ctrl_s_ctrl(ov7251->exposure,
115 - ov7251->current_mode->exposure_def);
116 + ret = __v4l2_ctrl_s_ctrl(ov7251->vblank,
117 + new_ival->vts -
118 + ov7251->current_mode->height);
119 if (ret < 0)
120 goto exit;
121
122 @@ -1233,7 +1256,7 @@ static int ov7251_probe(struct i2c_clien
123 struct v4l2_ctrl *ctrl;
124 struct ov7251 *ov7251;
125 unsigned int rate = 0;
126 - u32 h_blank;
127 + u32 h_blank, v_blank, v_blank_max;
128 int ret;
129 int i;
130
131 @@ -1314,7 +1337,7 @@ static int ov7251_probe(struct i2c_clien
132 ov7251->current_mode = &ov7251_mode_info_data[0];
133 ov7251->current_ival = &ov7251_frame_ival_info_data[0];
134
135 - v4l2_ctrl_handler_init(&ov7251->ctrls, 10);
136 + v4l2_ctrl_handler_init(&ov7251->ctrls, 11);
137 ov7251->ctrls.lock = &ov7251->lock;
138
139 v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops,
140 @@ -1345,6 +1368,13 @@ static int ov7251_probe(struct i2c_clien
141 if (ov7251->hblank)
142 ov7251->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
143
144 + v_blank = ov7251->current_ival->vts - ov7251->current_mode->height;
145 + v_blank_max = OV7251_VTS_MAX - ov7251->current_mode->width;
146 + ov7251->vblank = v4l2_ctrl_new_std(&ov7251->ctrls, &ov7251_ctrl_ops,
147 + V4L2_CID_VBLANK,
148 + OV7251_VTS_MIN_OFFSET,
149 + v_blank_max, 1, v_blank);
150 +
151 ov7251->sd.ctrl_handler = &ov7251->ctrls;
152
153 if (ov7251->ctrls.error) {