3b3bba282c2610f7b7c6bd37ae989728f28b3c8f
[openwrt/staging/rmilecki.git] /
1 From 450dc10dd858314fcb5e18942b6e5260e3478f10 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 29 Apr 2020 11:46:07 +0100
4 Subject: [PATCH] media: i2c: ov5647: Add support for g_selection to
5 reflect cropping/binning
6
7 In order to apply lens shading correctly the client needs to know how
8 each mode crops or scales the image compared to the full sensor array.
9 Implement this (based on the imx219 equivalent).
10
11 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
12 ---
13 drivers/media/i2c/ov5647.c | 119 ++++++++++++++++++++++++++++++-------
14 1 file changed, 96 insertions(+), 23 deletions(-)
15
16 --- a/drivers/media/i2c/ov5647.c
17 +++ b/drivers/media/i2c/ov5647.c
18 @@ -70,25 +70,14 @@
19 #define VAL_TERM 0xfe
20 #define REG_DLY 0xffff
21
22 -#define OV5647_ROW_START 0x01
23 -#define OV5647_ROW_START_MIN 0
24 -#define OV5647_ROW_START_MAX 2004
25 -#define OV5647_ROW_START_DEF 54
26 -
27 -#define OV5647_COLUMN_START 0x02
28 -#define OV5647_COLUMN_START_MIN 0
29 -#define OV5647_COLUMN_START_MAX 2750
30 -#define OV5647_COLUMN_START_DEF 16
31 -
32 -#define OV5647_WINDOW_HEIGHT 0x03
33 -#define OV5647_WINDOW_HEIGHT_MIN 2
34 -#define OV5647_WINDOW_HEIGHT_MAX 2006
35 -#define OV5647_WINDOW_HEIGHT_DEF 1944
36 -
37 -#define OV5647_WINDOW_WIDTH 0x04
38 -#define OV5647_WINDOW_WIDTH_MIN 2
39 -#define OV5647_WINDOW_WIDTH_MAX 2752
40 -#define OV5647_WINDOW_WIDTH_DEF 2592
41 +/* OV5647 native and active pixel array size */
42 +#define OV5647_NATIVE_WIDTH 2624U
43 +#define OV5647_NATIVE_HEIGHT 1956U
44 +
45 +#define OV5647_PIXEL_ARRAY_LEFT 16U
46 +#define OV5647_PIXEL_ARRAY_TOP 16U
47 +#define OV5647_PIXEL_ARRAY_WIDTH 2592U
48 +#define OV5647_PIXEL_ARRAY_HEIGHT 1944U
49
50 struct regval_list {
51 u16 addr;
52 @@ -97,6 +86,9 @@ struct regval_list {
53
54 struct ov5647_mode {
55 struct v4l2_mbus_framefmt format;
56 + /* Analog crop rectangle. */
57 + struct v4l2_rect crop;
58 +
59 struct regval_list *reg_list;
60 unsigned int num_regs;
61 };
62 @@ -603,6 +595,12 @@ static struct ov5647_mode supported_mode
63 .width = 640,
64 .height = 480
65 },
66 + .crop = {
67 + .left = 0,
68 + .top = 0,
69 + .width = 1280,
70 + .height = 960,
71 + },
72 ov5647_640x480_8bit,
73 ARRAY_SIZE(ov5647_640x480_8bit)
74 },
75 @@ -620,6 +618,12 @@ static struct ov5647_mode supported_mode
76 .width = 2592,
77 .height = 1944
78 },
79 + .crop = {
80 + .left = 0,
81 + .top = 0,
82 + .width = 2592,
83 + .height = 1944
84 + },
85 ov5647_2592x1944_10bit,
86 ARRAY_SIZE(ov5647_2592x1944_10bit)
87 },
88 @@ -635,6 +639,12 @@ static struct ov5647_mode supported_mode
89 .width = 1920,
90 .height = 1080
91 },
92 + .crop = {
93 + .left = 348,
94 + .top = 434,
95 + .width = 1928,
96 + .height = 1080,
97 + },
98 ov5647_1080p30_10bit,
99 ARRAY_SIZE(ov5647_1080p30_10bit)
100 },
101 @@ -649,6 +659,12 @@ static struct ov5647_mode supported_mode
102 .width = 1296,
103 .height = 972
104 },
105 + .crop = {
106 + .left = 0,
107 + .top = 0,
108 + .width = 2592,
109 + .height = 1944,
110 + },
111 ov5647_2x2binned_10bit,
112 ARRAY_SIZE(ov5647_2x2binned_10bit)
113 },
114 @@ -664,6 +680,12 @@ static struct ov5647_mode supported_mode
115 .width = 640,
116 .height = 480
117 },
118 + .crop = {
119 + .left = 16,
120 + .top = 0,
121 + .width = 2560,
122 + .height = 1920,
123 + },
124 ov5647_640x480_10bit,
125 ARRAY_SIZE(ov5647_640x480_10bit)
126 },
127 @@ -971,6 +993,56 @@ static const struct v4l2_subdev_core_ops
128 #endif
129 };
130
131 +static const struct v4l2_rect *
132 +__ov5647_get_pad_crop(struct ov5647 *ov5647, struct v4l2_subdev_pad_config *cfg,
133 + unsigned int pad, enum v4l2_subdev_format_whence which)
134 +{
135 + switch (which) {
136 + case V4L2_SUBDEV_FORMAT_TRY:
137 + return v4l2_subdev_get_try_crop(&ov5647->sd, cfg, pad);
138 + case V4L2_SUBDEV_FORMAT_ACTIVE:
139 + return &ov5647->mode->crop;
140 + }
141 +
142 + return NULL;
143 +}
144 +
145 +static int ov5647_get_selection(struct v4l2_subdev *sd,
146 + struct v4l2_subdev_pad_config *cfg,
147 + struct v4l2_subdev_selection *sel)
148 +{
149 + switch (sel->target) {
150 + case V4L2_SEL_TGT_CROP: {
151 + struct ov5647 *state = to_state(sd);
152 +
153 + mutex_lock(&state->lock);
154 + sel->r = *__ov5647_get_pad_crop(state, cfg, sel->pad,
155 + sel->which);
156 + mutex_unlock(&state->lock);
157 +
158 + return 0;
159 + }
160 +
161 + case V4L2_SEL_TGT_NATIVE_SIZE:
162 + sel->r.top = 0;
163 + sel->r.left = 0;
164 + sel->r.width = OV5647_NATIVE_WIDTH;
165 + sel->r.height = OV5647_NATIVE_HEIGHT;
166 +
167 + return 0;
168 +
169 + case V4L2_SEL_TGT_CROP_DEFAULT:
170 + sel->r.top = OV5647_PIXEL_ARRAY_TOP;
171 + sel->r.left = OV5647_PIXEL_ARRAY_LEFT;
172 + sel->r.width = OV5647_PIXEL_ARRAY_WIDTH;
173 + sel->r.height = OV5647_PIXEL_ARRAY_HEIGHT;
174 +
175 + return 0;
176 + }
177 +
178 + return -EINVAL;
179 +}
180 +
181 static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
182 {
183 struct ov5647 *state = to_state(sd);
184 @@ -1122,6 +1194,7 @@ static const struct v4l2_subdev_pad_ops
185 .enum_mbus_code = ov5647_enum_mbus_code,
186 .set_fmt = ov5647_set_fmt,
187 .get_fmt = ov5647_get_fmt,
188 + .get_selection = ov5647_get_selection,
189 .enum_frame_size = ov5647_enum_frame_size,
190 };
191
192 @@ -1170,10 +1243,10 @@ static int ov5647_open(struct v4l2_subde
193 v4l2_subdev_get_try_crop(sd, fh->pad, 0);
194 struct ov5647 *state = to_state(sd);
195
196 - crop->left = OV5647_COLUMN_START_DEF;
197 - crop->top = OV5647_ROW_START_DEF;
198 - crop->width = OV5647_WINDOW_WIDTH_DEF;
199 - crop->height = OV5647_WINDOW_HEIGHT_DEF;
200 + crop->left = OV5647_PIXEL_ARRAY_LEFT;
201 + crop->top = OV5647_PIXEL_ARRAY_TOP;
202 + crop->width = OV5647_PIXEL_ARRAY_WIDTH;
203 + crop->height = OV5647_PIXEL_ARRAY_HEIGHT;
204
205 /* Set the default format to the same as the sensor. */
206 *format = state->mode->format;