mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-21 06:33:41 +00:00
170 lines
4.5 KiB
Diff
170 lines
4.5 KiB
Diff
|
From 6e8b94f48ce58e2b9c09000eb77642f3633a6b0b Mon Sep 17 00:00:00 2001
|
||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||
|
Date: Wed, 23 Mar 2022 15:48:49 +0000
|
||
|
Subject: [PATCH] media: i2c: imx258: Add get_selection for pixel array
|
||
|
information
|
||
|
|
||
|
Libcamera requires the cropping information for each mode, so
|
||
|
add this information to the driver.
|
||
|
|
||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||
|
---
|
||
|
drivers/media/i2c/imx258.c | 90 ++++++++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 90 insertions(+)
|
||
|
|
||
|
--- a/drivers/media/i2c/imx258.c
|
||
|
+++ b/drivers/media/i2c/imx258.c
|
||
|
@@ -78,6 +78,14 @@
|
||
|
#define REG_CONFIG_MIRROR_VFLIP 0x02
|
||
|
#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
|
||
|
|
||
|
+/* IMX258 native and active pixel array size. */
|
||
|
+#define IMX258_NATIVE_WIDTH 4224U
|
||
|
+#define IMX258_NATIVE_HEIGHT 3192U
|
||
|
+#define IMX258_PIXEL_ARRAY_LEFT 8U
|
||
|
+#define IMX258_PIXEL_ARRAY_TOP 16U
|
||
|
+#define IMX258_PIXEL_ARRAY_WIDTH 4208U
|
||
|
+#define IMX258_PIXEL_ARRAY_HEIGHT 3120U
|
||
|
+
|
||
|
struct imx258_reg {
|
||
|
u16 address;
|
||
|
u8 val;
|
||
|
@@ -116,6 +124,9 @@ struct imx258_mode {
|
||
|
u32 link_freq_index;
|
||
|
/* Default register values */
|
||
|
struct imx258_reg_list reg_list;
|
||
|
+
|
||
|
+ /* Analog crop rectangle. */
|
||
|
+ struct v4l2_rect crop;
|
||
|
};
|
||
|
|
||
|
/* 4208x3120 needs 1267Mbps/lane, 4 lanes. Use that rate on 2 lanes as well */
|
||
|
@@ -774,6 +785,12 @@ static const struct imx258_mode supporte
|
||
|
.regs = mode_4208x3120_regs,
|
||
|
},
|
||
|
.link_freq_index = IMX258_LINK_FREQ_1267MBPS,
|
||
|
+ .crop = {
|
||
|
+ .left = IMX258_PIXEL_ARRAY_LEFT,
|
||
|
+ .top = IMX258_PIXEL_ARRAY_TOP,
|
||
|
+ .width = 4208,
|
||
|
+ .height = 3120,
|
||
|
+ },
|
||
|
},
|
||
|
{
|
||
|
.width = 2104,
|
||
|
@@ -785,6 +802,12 @@ static const struct imx258_mode supporte
|
||
|
.regs = mode_2104_1560_regs,
|
||
|
},
|
||
|
.link_freq_index = IMX258_LINK_FREQ_640MBPS,
|
||
|
+ .crop = {
|
||
|
+ .left = IMX258_PIXEL_ARRAY_LEFT,
|
||
|
+ .top = IMX258_PIXEL_ARRAY_TOP,
|
||
|
+ .width = 4208,
|
||
|
+ .height = 3120,
|
||
|
+ },
|
||
|
},
|
||
|
{
|
||
|
.width = 1048,
|
||
|
@@ -796,6 +819,12 @@ static const struct imx258_mode supporte
|
||
|
.regs = mode_1048_780_regs,
|
||
|
},
|
||
|
.link_freq_index = IMX258_LINK_FREQ_640MBPS,
|
||
|
+ .crop = {
|
||
|
+ .left = IMX258_PIXEL_ARRAY_LEFT,
|
||
|
+ .top = IMX258_PIXEL_ARRAY_TOP,
|
||
|
+ .width = 4208,
|
||
|
+ .height = 3120,
|
||
|
+ },
|
||
|
},
|
||
|
};
|
||
|
|
||
|
@@ -930,6 +959,7 @@ static int imx258_open(struct v4l2_subde
|
||
|
struct imx258 *imx258 = to_imx258(sd);
|
||
|
struct v4l2_mbus_framefmt *try_fmt =
|
||
|
v4l2_subdev_get_try_format(sd, fh->state, 0);
|
||
|
+ struct v4l2_rect *try_crop;
|
||
|
|
||
|
/* Initialize try_fmt */
|
||
|
try_fmt->width = supported_modes[0].width;
|
||
|
@@ -937,6 +967,13 @@ static int imx258_open(struct v4l2_subde
|
||
|
try_fmt->code = imx258_get_format_code(imx258);
|
||
|
try_fmt->field = V4L2_FIELD_NONE;
|
||
|
|
||
|
+ /* Initialize try_crop */
|
||
|
+ try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
|
||
|
+ try_crop->left = IMX258_PIXEL_ARRAY_LEFT;
|
||
|
+ try_crop->top = IMX258_PIXEL_ARRAY_TOP;
|
||
|
+ try_crop->width = IMX258_PIXEL_ARRAY_WIDTH;
|
||
|
+ try_crop->height = IMX258_PIXEL_ARRAY_HEIGHT;
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -1193,6 +1230,58 @@ static int imx258_set_pad_format(struct
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static const struct v4l2_rect *
|
||
|
+__imx258_get_pad_crop(struct imx258 *imx258,
|
||
|
+ struct v4l2_subdev_state *sd_state,
|
||
|
+ unsigned int pad, enum v4l2_subdev_format_whence which)
|
||
|
+{
|
||
|
+ switch (which) {
|
||
|
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||
|
+ return v4l2_subdev_get_try_crop(&imx258->sd, sd_state, pad);
|
||
|
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||
|
+ return &imx258->cur_mode->crop;
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static int imx258_get_selection(struct v4l2_subdev *sd,
|
||
|
+ struct v4l2_subdev_state *sd_state,
|
||
|
+ struct v4l2_subdev_selection *sel)
|
||
|
+{
|
||
|
+ switch (sel->target) {
|
||
|
+ case V4L2_SEL_TGT_CROP: {
|
||
|
+ struct imx258 *imx258 = to_imx258(sd);
|
||
|
+
|
||
|
+ mutex_lock(&imx258->mutex);
|
||
|
+ sel->r = *__imx258_get_pad_crop(imx258, sd_state, sel->pad,
|
||
|
+ sel->which);
|
||
|
+ mutex_unlock(&imx258->mutex);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ case V4L2_SEL_TGT_NATIVE_SIZE:
|
||
|
+ sel->r.left = 0;
|
||
|
+ sel->r.top = 0;
|
||
|
+ sel->r.width = IMX258_NATIVE_WIDTH;
|
||
|
+ sel->r.height = IMX258_NATIVE_HEIGHT;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ case V4L2_SEL_TGT_CROP_DEFAULT:
|
||
|
+ case V4L2_SEL_TGT_CROP_BOUNDS:
|
||
|
+ sel->r.left = IMX258_PIXEL_ARRAY_LEFT;
|
||
|
+ sel->r.top = IMX258_PIXEL_ARRAY_TOP;
|
||
|
+ sel->r.width = IMX258_PIXEL_ARRAY_WIDTH;
|
||
|
+ sel->r.height = IMX258_PIXEL_ARRAY_HEIGHT;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+}
|
||
|
+
|
||
|
/* Start streaming */
|
||
|
static int imx258_start_streaming(struct imx258 *imx258)
|
||
|
{
|
||
|
@@ -1389,6 +1478,7 @@ static const struct v4l2_subdev_pad_ops
|
||
|
.get_fmt = imx258_get_pad_format,
|
||
|
.set_fmt = imx258_set_pad_format,
|
||
|
.enum_frame_size = imx258_enum_frame_size,
|
||
|
+ .get_selection = imx258_get_selection,
|
||
|
};
|
||
|
|
||
|
static const struct v4l2_subdev_ops imx258_subdev_ops = {
|