207 lines
5.3 KiB
Diff
207 lines
5.3 KiB
Diff
From 450dc10dd858314fcb5e18942b6e5260e3478f10 Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
Date: Wed, 29 Apr 2020 11:46:07 +0100
|
|
Subject: [PATCH] media: i2c: ov5647: Add support for g_selection to
|
|
reflect cropping/binning
|
|
|
|
In order to apply lens shading correctly the client needs to know how
|
|
each mode crops or scales the image compared to the full sensor array.
|
|
Implement this (based on the imx219 equivalent).
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
---
|
|
drivers/media/i2c/ov5647.c | 119 ++++++++++++++++++++++++++++++-------
|
|
1 file changed, 96 insertions(+), 23 deletions(-)
|
|
|
|
--- a/drivers/media/i2c/ov5647.c
|
|
+++ b/drivers/media/i2c/ov5647.c
|
|
@@ -70,25 +70,14 @@
|
|
#define VAL_TERM 0xfe
|
|
#define REG_DLY 0xffff
|
|
|
|
-#define OV5647_ROW_START 0x01
|
|
-#define OV5647_ROW_START_MIN 0
|
|
-#define OV5647_ROW_START_MAX 2004
|
|
-#define OV5647_ROW_START_DEF 54
|
|
-
|
|
-#define OV5647_COLUMN_START 0x02
|
|
-#define OV5647_COLUMN_START_MIN 0
|
|
-#define OV5647_COLUMN_START_MAX 2750
|
|
-#define OV5647_COLUMN_START_DEF 16
|
|
-
|
|
-#define OV5647_WINDOW_HEIGHT 0x03
|
|
-#define OV5647_WINDOW_HEIGHT_MIN 2
|
|
-#define OV5647_WINDOW_HEIGHT_MAX 2006
|
|
-#define OV5647_WINDOW_HEIGHT_DEF 1944
|
|
-
|
|
-#define OV5647_WINDOW_WIDTH 0x04
|
|
-#define OV5647_WINDOW_WIDTH_MIN 2
|
|
-#define OV5647_WINDOW_WIDTH_MAX 2752
|
|
-#define OV5647_WINDOW_WIDTH_DEF 2592
|
|
+/* OV5647 native and active pixel array size */
|
|
+#define OV5647_NATIVE_WIDTH 2624U
|
|
+#define OV5647_NATIVE_HEIGHT 1956U
|
|
+
|
|
+#define OV5647_PIXEL_ARRAY_LEFT 16U
|
|
+#define OV5647_PIXEL_ARRAY_TOP 16U
|
|
+#define OV5647_PIXEL_ARRAY_WIDTH 2592U
|
|
+#define OV5647_PIXEL_ARRAY_HEIGHT 1944U
|
|
|
|
struct regval_list {
|
|
u16 addr;
|
|
@@ -97,6 +86,9 @@ struct regval_list {
|
|
|
|
struct ov5647_mode {
|
|
struct v4l2_mbus_framefmt format;
|
|
+ /* Analog crop rectangle. */
|
|
+ struct v4l2_rect crop;
|
|
+
|
|
struct regval_list *reg_list;
|
|
unsigned int num_regs;
|
|
};
|
|
@@ -603,6 +595,12 @@ static struct ov5647_mode supported_mode
|
|
.width = 640,
|
|
.height = 480
|
|
},
|
|
+ .crop = {
|
|
+ .left = 0,
|
|
+ .top = 0,
|
|
+ .width = 1280,
|
|
+ .height = 960,
|
|
+ },
|
|
ov5647_640x480_8bit,
|
|
ARRAY_SIZE(ov5647_640x480_8bit)
|
|
},
|
|
@@ -620,6 +618,12 @@ static struct ov5647_mode supported_mode
|
|
.width = 2592,
|
|
.height = 1944
|
|
},
|
|
+ .crop = {
|
|
+ .left = 0,
|
|
+ .top = 0,
|
|
+ .width = 2592,
|
|
+ .height = 1944
|
|
+ },
|
|
ov5647_2592x1944_10bit,
|
|
ARRAY_SIZE(ov5647_2592x1944_10bit)
|
|
},
|
|
@@ -635,6 +639,12 @@ static struct ov5647_mode supported_mode
|
|
.width = 1920,
|
|
.height = 1080
|
|
},
|
|
+ .crop = {
|
|
+ .left = 348,
|
|
+ .top = 434,
|
|
+ .width = 1928,
|
|
+ .height = 1080,
|
|
+ },
|
|
ov5647_1080p30_10bit,
|
|
ARRAY_SIZE(ov5647_1080p30_10bit)
|
|
},
|
|
@@ -649,6 +659,12 @@ static struct ov5647_mode supported_mode
|
|
.width = 1296,
|
|
.height = 972
|
|
},
|
|
+ .crop = {
|
|
+ .left = 0,
|
|
+ .top = 0,
|
|
+ .width = 2592,
|
|
+ .height = 1944,
|
|
+ },
|
|
ov5647_2x2binned_10bit,
|
|
ARRAY_SIZE(ov5647_2x2binned_10bit)
|
|
},
|
|
@@ -664,6 +680,12 @@ static struct ov5647_mode supported_mode
|
|
.width = 640,
|
|
.height = 480
|
|
},
|
|
+ .crop = {
|
|
+ .left = 16,
|
|
+ .top = 0,
|
|
+ .width = 2560,
|
|
+ .height = 1920,
|
|
+ },
|
|
ov5647_640x480_10bit,
|
|
ARRAY_SIZE(ov5647_640x480_10bit)
|
|
},
|
|
@@ -971,6 +993,56 @@ static const struct v4l2_subdev_core_ops
|
|
#endif
|
|
};
|
|
|
|
+static const struct v4l2_rect *
|
|
+__ov5647_get_pad_crop(struct ov5647 *ov5647, struct v4l2_subdev_pad_config *cfg,
|
|
+ unsigned int pad, enum v4l2_subdev_format_whence which)
|
|
+{
|
|
+ switch (which) {
|
|
+ case V4L2_SUBDEV_FORMAT_TRY:
|
|
+ return v4l2_subdev_get_try_crop(&ov5647->sd, cfg, pad);
|
|
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
|
+ return &ov5647->mode->crop;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int ov5647_get_selection(struct v4l2_subdev *sd,
|
|
+ struct v4l2_subdev_pad_config *cfg,
|
|
+ struct v4l2_subdev_selection *sel)
|
|
+{
|
|
+ switch (sel->target) {
|
|
+ case V4L2_SEL_TGT_CROP: {
|
|
+ struct ov5647 *state = to_state(sd);
|
|
+
|
|
+ mutex_lock(&state->lock);
|
|
+ sel->r = *__ov5647_get_pad_crop(state, cfg, sel->pad,
|
|
+ sel->which);
|
|
+ mutex_unlock(&state->lock);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ case V4L2_SEL_TGT_NATIVE_SIZE:
|
|
+ sel->r.top = 0;
|
|
+ sel->r.left = 0;
|
|
+ sel->r.width = OV5647_NATIVE_WIDTH;
|
|
+ sel->r.height = OV5647_NATIVE_HEIGHT;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+ case V4L2_SEL_TGT_CROP_DEFAULT:
|
|
+ sel->r.top = OV5647_PIXEL_ARRAY_TOP;
|
|
+ sel->r.left = OV5647_PIXEL_ARRAY_LEFT;
|
|
+ sel->r.width = OV5647_PIXEL_ARRAY_WIDTH;
|
|
+ sel->r.height = OV5647_PIXEL_ARRAY_HEIGHT;
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
|
|
{
|
|
struct ov5647 *state = to_state(sd);
|
|
@@ -1122,6 +1194,7 @@ static const struct v4l2_subdev_pad_ops
|
|
.enum_mbus_code = ov5647_enum_mbus_code,
|
|
.set_fmt = ov5647_set_fmt,
|
|
.get_fmt = ov5647_get_fmt,
|
|
+ .get_selection = ov5647_get_selection,
|
|
.enum_frame_size = ov5647_enum_frame_size,
|
|
};
|
|
|
|
@@ -1170,10 +1243,10 @@ static int ov5647_open(struct v4l2_subde
|
|
v4l2_subdev_get_try_crop(sd, fh->pad, 0);
|
|
struct ov5647 *state = to_state(sd);
|
|
|
|
- crop->left = OV5647_COLUMN_START_DEF;
|
|
- crop->top = OV5647_ROW_START_DEF;
|
|
- crop->width = OV5647_WINDOW_WIDTH_DEF;
|
|
- crop->height = OV5647_WINDOW_HEIGHT_DEF;
|
|
+ crop->left = OV5647_PIXEL_ARRAY_LEFT;
|
|
+ crop->top = OV5647_PIXEL_ARRAY_TOP;
|
|
+ crop->width = OV5647_PIXEL_ARRAY_WIDTH;
|
|
+ crop->height = OV5647_PIXEL_ARRAY_HEIGHT;
|
|
|
|
/* Set the default format to the same as the sensor. */
|
|
*format = state->mode->format;
|