1 From 9e584d9de3387588bf455d3c45ec6a092bfa4266 Mon Sep 17 00:00:00 2001
2 From: David Plowman <david.plowman@raspberrypi.com>
3 Date: Wed, 29 Jan 2020 15:30:53 +0000
4 Subject: [PATCH] media: ov5647: Add basic support for multiple sensor
9 Added a structure ov5647_mode and a list of supported_modes (though no
10 actual new modes as yet). The state object points to the "current mode".
12 ov5647_enum_mbus_code, ov5647_enum_frame_size, ov5647_set_fmt and
13 ov5647_get_fmt all needed upgrading to cope with multiple modes.
15 __sensor_init (which writes all the registers) is now called by
16 ov5647_stream_on (once the mode is known) rather than by
19 Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
20 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
22 drivers/media/i2c/ov5647.c | 268 ++++++++++++++++++++++++++++---------
23 1 file changed, 202 insertions(+), 66 deletions(-)
25 --- a/drivers/media/i2c/ov5647.c
26 +++ b/drivers/media/i2c/ov5647.c
27 @@ -86,13 +86,17 @@ struct regval_list {
32 + struct v4l2_mbus_framefmt format;
33 + struct regval_list *reg_list;
34 + unsigned int num_regs;
38 struct v4l2_subdev sd;
41 - struct v4l2_mbus_framefmt format;
43 - unsigned int height;
44 + const struct ov5647_mode *mode;
47 struct gpio_desc *pwdn;
48 @@ -207,6 +211,32 @@ static struct regval_list ov5647_640x480
52 +static struct ov5647_mode supported_modes_8bit[] = {
54 + * Original 8-bit VGA mode
55 + * Uncentred crop (top left quarter) from 2x2 binned 1296x972 image.
59 + .code = MEDIA_BUS_FMT_SBGGR8_1X8,
60 + .colorspace = V4L2_COLORSPACE_SRGB,
61 + .field = V4L2_FIELD_NONE,
66 + ARRAY_SIZE(ov5647_640x480)
68 + /* more modes below here... */
71 +static struct ov5647_mode supported_modes_10bit[] = {
72 + /* no 10-bit modes yet */
75 +/* Use original 8-bit VGA mode as default. */
76 +#define OV5647_DEFAULT_MODE (&supported_modes_8bit[0])
78 static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val)
81 @@ -293,12 +323,55 @@ static int ov5647_set_virtual_channel(st
82 return ov5647_write(sd, OV5647_REG_MIPI_CTRL14, channel_id | (channel << 6));
85 +static int __sensor_init(struct v4l2_subdev *sd)
89 + struct i2c_client *client = v4l2_get_subdevdata(sd);
90 + struct ov5647 *state = to_state(sd);
92 + ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval);
96 + ret = ov5647_write_array(sd, state->mode->reg_list,
97 + state->mode->num_regs);
99 + dev_err(&client->dev, "write sensor default regs error\n");
103 + ret = ov5647_set_virtual_channel(sd, 0);
107 + ret = ov5647_read(sd, OV5647_SW_STANDBY, &resetval);
111 + if (!(resetval & 0x01)) {
112 + dev_err(&client->dev, "Device was in SW standby");
113 + ret = ov5647_write(sd, OV5647_SW_STANDBY, 0x01);
121 static int ov5647_stream_on(struct v4l2_subdev *sd)
123 + struct i2c_client *client = v4l2_get_subdevdata(sd);
124 struct ov5647 *ov5647 = to_state(sd);
125 u8 val = MIPI_CTRL00_BUS_IDLE;
128 + ret = __sensor_init(sd);
130 + dev_err(&client->dev, "sensor_init failed\n");
134 if (ov5647->flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK)
135 val |= MIPI_CTRL00_CLOCK_LANE_GATE |
136 MIPI_CTRL00_LINE_SYNC_ENABLE;
137 @@ -347,44 +420,6 @@ static int set_sw_standby(struct v4l2_su
138 return ov5647_write(sd, OV5647_SW_STANDBY, rdval);
141 -static int __sensor_init(struct v4l2_subdev *sd)
144 - u8 resetval, rdval;
145 - struct i2c_client *client = v4l2_get_subdevdata(sd);
147 - ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval);
151 - ret = ov5647_write_array(sd, ov5647_640x480,
152 - ARRAY_SIZE(ov5647_640x480));
154 - dev_err(&client->dev, "write sensor default regs error\n");
158 - ret = ov5647_set_virtual_channel(sd, 0);
162 - ret = ov5647_read(sd, OV5647_SW_STANDBY, &resetval);
166 - if (!(resetval & 0x01)) {
167 - dev_err(&client->dev, "Device was in SW standby");
168 - ret = ov5647_write(sd, OV5647_SW_STANDBY, 0x01);
174 - * stream off to make the clock lane into LP-11 state.
176 - return ov5647_stream_off(sd);
179 static int ov5647_sensor_power(struct v4l2_subdev *sd, int on)
182 @@ -408,7 +443,7 @@ static int ov5647_sensor_power(struct v4
185 ret = ov5647_write_array(sd, sensor_oe_enable_regs,
186 - ARRAY_SIZE(sensor_oe_enable_regs));
187 + ARRAY_SIZE(sensor_oe_enable_regs));
189 clk_disable_unprepare(ov5647->xclk);
190 dev_err(&client->dev,
191 @@ -416,7 +451,10 @@ static int ov5647_sensor_power(struct v4
195 - ret = __sensor_init(sd);
197 + * Ensure streaming off to make clock lane go into LP-11 state.
199 + ret = ov5647_stream_off(sd);
201 clk_disable_unprepare(ov5647->xclk);
202 dev_err(&client->dev,
203 @@ -427,7 +465,7 @@ static int ov5647_sensor_power(struct v4
204 dev_dbg(&client->dev, "OV5647 power off\n");
206 ret = ov5647_write_array(sd, sensor_oe_disable_regs,
207 - ARRAY_SIZE(sensor_oe_disable_regs));
208 + ARRAY_SIZE(sensor_oe_disable_regs));
211 dev_dbg(&client->dev, "disable oe failed\n");
212 @@ -489,10 +527,19 @@ static const struct v4l2_subdev_core_ops
214 static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
216 + struct ov5647 *state = to_state(sd);
219 + mutex_lock(&state->lock);
222 - return ov5647_stream_on(sd);
223 + ret = ov5647_stream_on(sd);
225 - return ov5647_stream_off(sd);
226 + ret = ov5647_stream_off(sd);
228 + mutex_unlock(&state->lock);
233 static const struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
234 @@ -503,38 +550,127 @@ static int ov5647_enum_mbus_code(struct
235 struct v4l2_subdev_pad_config *cfg,
236 struct v4l2_subdev_mbus_code_enum *code)
238 - if (code->index > 0)
239 + if (code->index == 0 && ARRAY_SIZE(supported_modes_8bit))
240 + code->code = MEDIA_BUS_FMT_SBGGR8_1X8;
241 + else if (code->index == 0 && ARRAY_SIZE(supported_modes_8bit) == 0 &&
242 + ARRAY_SIZE(supported_modes_10bit))
243 + code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
244 + else if (code->index == 1 && ARRAY_SIZE(supported_modes_8bit) &&
245 + ARRAY_SIZE(supported_modes_10bit))
246 + code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
250 - code->code = MEDIA_BUS_FMT_SBGGR8_1X8;
254 +static int ov5647_enum_frame_size(struct v4l2_subdev *sd,
255 + struct v4l2_subdev_pad_config *cfg,
256 + struct v4l2_subdev_frame_size_enum *fse)
258 + struct ov5647_mode *mode = NULL;
260 + if (fse->code == MEDIA_BUS_FMT_SBGGR8_1X8) {
261 + if (fse->index >= ARRAY_SIZE(supported_modes_8bit))
263 + mode = &supported_modes_8bit[fse->index];
264 + } else if (fse->code == MEDIA_BUS_FMT_SBGGR10_1X10) {
265 + if (fse->index >= ARRAY_SIZE(supported_modes_10bit))
267 + mode = &supported_modes_10bit[fse->index];
272 + fse->min_width = mode->format.width;
273 + fse->max_width = fse->min_width;
274 + fse->min_height = mode->format.height;
275 + fse->max_height = fse->min_height;
280 +static int ov5647_set_fmt(struct v4l2_subdev *sd,
281 + struct v4l2_subdev_pad_config *cfg,
282 + struct v4l2_subdev_format *format)
284 + struct v4l2_mbus_framefmt *fmt = &format->format;
285 + struct ov5647 *state = to_state(sd);
286 + struct v4l2_mbus_framefmt *framefmt;
287 + const struct ov5647_mode *mode_8bit, *mode_10bit, *mode = NULL;
289 + if (format->pad != 0)
292 + mutex_lock(&state->lock);
295 + * Try to respect any given pixel format, otherwise try for a 10-bit
298 + mode_8bit = v4l2_find_nearest_size(supported_modes_8bit,
299 + ARRAY_SIZE(supported_modes_8bit),
300 + format.width, format.height,
301 + format->format.width,
302 + format->format.height);
303 + mode_10bit = v4l2_find_nearest_size(supported_modes_10bit,
304 + ARRAY_SIZE(supported_modes_10bit),
305 + format.width, format.height,
306 + format->format.width,
307 + format->format.height);
308 + if (format->format.code == MEDIA_BUS_FMT_SBGGR8_1X8 && mode_8bit)
310 + else if (format->format.code == MEDIA_BUS_FMT_SBGGR10_1X10 &&
313 + else if (mode_10bit)
321 + *fmt = mode->format;
322 + if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
323 + framefmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
324 + *framefmt = format->format;
326 + state->mode = mode;
329 + mutex_unlock(&state->lock);
334 -static int ov5647_set_get_fmt(struct v4l2_subdev *sd,
335 - struct v4l2_subdev_pad_config *cfg,
336 - struct v4l2_subdev_format *format)
337 +static int ov5647_get_fmt(struct v4l2_subdev *sd,
338 + struct v4l2_subdev_pad_config *cfg,
339 + struct v4l2_subdev_format *format)
341 struct v4l2_mbus_framefmt *fmt = &format->format;
342 + struct ov5647 *state = to_state(sd);
344 if (format->pad != 0)
347 - /* Only one format is supported, so return that */
348 - memset(fmt, 0, sizeof(*fmt));
349 - fmt->code = MEDIA_BUS_FMT_SBGGR8_1X8;
350 - fmt->colorspace = V4L2_COLORSPACE_SRGB;
351 - fmt->field = V4L2_FIELD_NONE;
354 + mutex_lock(&state->lock);
356 + if (format->which == V4L2_SUBDEV_FORMAT_TRY)
357 + *fmt = *v4l2_subdev_get_try_format(sd, cfg, format->pad);
359 + *fmt = state->mode->format;
361 + mutex_unlock(&state->lock);
366 static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
367 .enum_mbus_code = ov5647_enum_mbus_code,
368 - .set_fmt = ov5647_set_get_fmt,
369 - .get_fmt = ov5647_set_get_fmt,
370 + .set_fmt = ov5647_set_fmt,
371 + .get_fmt = ov5647_get_fmt,
372 + .enum_frame_size = ov5647_enum_frame_size,
375 static const struct v4l2_subdev_ops ov5647_subdev_ops = {
376 @@ -580,18 +716,15 @@ static int ov5647_open(struct v4l2_subde
377 v4l2_subdev_get_try_format(sd, fh->pad, 0);
378 struct v4l2_rect *crop =
379 v4l2_subdev_get_try_crop(sd, fh->pad, 0);
380 + struct ov5647 *state = to_state(sd);
382 crop->left = OV5647_COLUMN_START_DEF;
383 crop->top = OV5647_ROW_START_DEF;
384 crop->width = OV5647_WINDOW_WIDTH_DEF;
385 crop->height = OV5647_WINDOW_HEIGHT_DEF;
387 - format->code = MEDIA_BUS_FMT_SBGGR8_1X8;
389 - format->width = OV5647_WINDOW_WIDTH_DEF;
390 - format->height = OV5647_WINDOW_HEIGHT_DEF;
391 - format->field = V4L2_FIELD_NONE;
392 - format->colorspace = V4L2_COLORSPACE_SRGB;
393 + /* Set the default format to the same as the sensor. */
394 + *format = state->mode->format;
398 @@ -660,6 +793,9 @@ static int ov5647_probe(struct i2c_clien
400 mutex_init(&sensor->lock);
402 + /* Set the default mode before we init the subdev */
403 + sensor->mode = OV5647_DEFAULT_MODE;
406 v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops);
407 sensor->sd.internal_ops = &ov5647_subdev_internal_ops;