mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	Build system: x86_64 Build-tested: bcm2708, bcm2709, bcm2710, bcm2711 Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B Signed-off-by: Marty Jones <mj8263788@gmail.com> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
		
			
				
	
	
		
			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 = {
 |