1 From 004f4065edbb817a54121937514eb94159ecce69 Mon Sep 17 00:00:00 2001
2 From: David Plowman <david.plowman@raspberrypi.com>
3 Date: Wed, 29 Jan 2020 15:31:28 +0000
4 Subject: [PATCH] media: ov5647: Add extra 10-bit sensor modes.
6 The 8-bit VGA mode remains, we add the following 10-bit modes:
8 Mode 0: 2592x1944 full resolution.
10 Mode 1: 1920x1080 full resolution, but centre-cropped.
11 (This mode achieves 30fps, mode 0 does not.)
13 Mode 2: 1296x972 full field-of-view 2x2 binned mode.
15 Mode 3: VGA full field of view mode.
17 Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
18 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
20 drivers/media/i2c/ov5647.c | 463 ++++++++++++++++++++++++++++++++++++-
21 1 file changed, 452 insertions(+), 11 deletions(-)
23 --- a/drivers/media/i2c/ov5647.c
24 +++ b/drivers/media/i2c/ov5647.c
25 @@ -111,6 +111,7 @@ struct ov5647 {
26 struct gpio_desc *pwdn;
28 struct v4l2_ctrl_handler ctrls;
29 + bool write_mode_regs;
32 static inline struct ov5647 *to_state(struct v4l2_subdev *sd)
33 @@ -130,7 +131,7 @@ static struct regval_list sensor_oe_enab
37 -static struct regval_list ov5647_640x480[] = {
38 +static struct regval_list ov5647_640x480_8bit[] = {
42 @@ -220,9 +221,378 @@ static struct regval_list ov5647_640x480
46 +static struct regval_list ov5647_2592x1944_10bit[] = {
137 +static struct regval_list ov5647_1080p30_10bit[] = {
228 +static struct regval_list ov5647_2x2binned_10bit[] = {
323 +static struct regval_list ov5647_640x480_10bit[] = {
415 static struct ov5647_mode supported_modes_8bit[] = {
417 - * Original 8-bit VGA mode
418 + * MODE 0: Original 8-bit VGA mode.
419 * Uncentred crop (top left quarter) from 2x2 binned 1296x972 image.
422 @@ -233,14 +603,70 @@ static struct ov5647_mode supported_mode
427 - ARRAY_SIZE(ov5647_640x480)
428 + ov5647_640x480_8bit,
429 + ARRAY_SIZE(ov5647_640x480_8bit)
431 - /* more modes below here... */
434 static struct ov5647_mode supported_modes_10bit[] = {
435 - /* no 10-bit modes yet */
437 + * MODE 0: 2592x1944 full resolution full FOV 10-bit mode.
441 + .code = MEDIA_BUS_FMT_SBGGR10_1X10,
442 + .colorspace = V4L2_COLORSPACE_SRGB,
443 + .field = V4L2_FIELD_NONE,
447 + ov5647_2592x1944_10bit,
448 + ARRAY_SIZE(ov5647_2592x1944_10bit)
451 + * MODE 1: 1080p30 10-bit mode.
452 + * Full resolution centre-cropped down to 1080p.
456 + .code = MEDIA_BUS_FMT_SBGGR10_1X10,
457 + .colorspace = V4L2_COLORSPACE_SRGB,
458 + .field = V4L2_FIELD_NONE,
462 + ov5647_1080p30_10bit,
463 + ARRAY_SIZE(ov5647_1080p30_10bit)
466 + * MODE 2: 2x2 binned full FOV 10-bit mode.
470 + .code = MEDIA_BUS_FMT_SBGGR10_1X10,
471 + .colorspace = V4L2_COLORSPACE_SRGB,
472 + .field = V4L2_FIELD_NONE,
476 + ov5647_2x2binned_10bit,
477 + ARRAY_SIZE(ov5647_2x2binned_10bit)
480 + * MODE 3: 10-bit VGA full FOV mode 60fps.
481 + * 2x2 binned and subsampled down to VGA.
485 + .code = MEDIA_BUS_FMT_SBGGR10_1X10,
486 + .colorspace = V4L2_COLORSPACE_SRGB,
487 + .field = V4L2_FIELD_NONE,
491 + ov5647_640x480_10bit,
492 + ARRAY_SIZE(ov5647_640x480_10bit)
496 /* Use original 8-bit VGA mode as default. */
497 @@ -343,11 +769,14 @@ static int __sensor_init(struct v4l2_sub
501 - ret = ov5647_write_array(sd, state->mode->reg_list,
502 - state->mode->num_regs);
504 - dev_err(&client->dev, "write sensor default regs error\n");
506 + if (state->write_mode_regs) {
507 + ret = ov5647_write_array(sd, state->mode->reg_list,
508 + state->mode->num_regs);
510 + dev_err(&client->dev, "write sensor default regs error\n");
513 + state->write_mode_regs = false;
516 ret = ov5647_set_virtual_channel(sd, 0);
517 @@ -475,6 +904,9 @@ static int ov5647_sensor_power(struct v4
518 "Camera not available, check Power\n");
522 + /* Write out the register set over I2C on stream-on. */
523 + ov5647->write_mode_regs = true;
524 } else if (!on && ov5647->power_count == 1) {
525 dev_dbg(&client->dev, "OV5647 power off\n");
527 @@ -650,6 +1082,12 @@ static int ov5647_set_fmt(struct v4l2_su
528 framefmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
529 *framefmt = format->format;
532 + * If we have changed modes, write the I2C register list on
535 + if (state->mode != mode)
536 + state->write_mode_regs = true;
540 @@ -967,6 +1405,9 @@ static int ov5647_probe(struct i2c_clien
541 /* Set the default mode before we init the subdev */
542 sensor->mode = OV5647_DEFAULT_MODE;
544 + /* Write out the register set over I2C on stream-on. */
545 + sensor->write_mode_regs = true;
548 v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops);
549 sensor->sd.internal_ops = &ov5647_subdev_internal_ops;