mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-04 06:54: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>
		
			
				
	
	
		
			157 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From b1d7e2e6a94018681fe027edbe90038727c6d169 Mon Sep 17 00:00:00 2001
 | 
						|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
 | 
						|
Date: Tue, 7 Jul 2020 11:23:48 +0100
 | 
						|
Subject: [PATCH] media: i2c: imx290: Add support for g_selection to
 | 
						|
 report cropping
 | 
						|
 | 
						|
Userspace needs to know the cropping arrangements for each mode,
 | 
						|
so expose this through g_selection.
 | 
						|
 | 
						|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
 | 
						|
---
 | 
						|
 drivers/media/i2c/imx290.c | 84 ++++++++++++++++++++++++++++++++++++++
 | 
						|
 1 file changed, 84 insertions(+)
 | 
						|
 | 
						|
--- a/drivers/media/i2c/imx290.c
 | 
						|
+++ b/drivers/media/i2c/imx290.c
 | 
						|
@@ -61,6 +61,13 @@ enum imx290_clk_index {
 | 
						|
 #define IMX290_PGCTRL_THRU BIT(1)
 | 
						|
 #define IMX290_PGCTRL_MODE(n) ((n) << 4)
 | 
						|
 
 | 
						|
+#define IMX290_NATIVE_WIDTH		1945U
 | 
						|
+#define IMX290_NATIVE_HEIGHT		1109U
 | 
						|
+#define IMX290_PIXEL_ARRAY_LEFT		4U
 | 
						|
+#define IMX290_PIXEL_ARRAY_TOP		12U
 | 
						|
+#define IMX290_PIXEL_ARRAY_WIDTH	1937U
 | 
						|
+#define IMX290_PIXEL_ARRAY_HEIGHT	1097U
 | 
						|
+
 | 
						|
 static const char * const imx290_supply_name[] = {
 | 
						|
 	"vdda",
 | 
						|
 	"vddd",
 | 
						|
@@ -80,6 +87,7 @@ struct imx290_mode {
 | 
						|
 	u32 hmax;
 | 
						|
 	u32 vmax;
 | 
						|
 	u8 link_freq_index;
 | 
						|
+	struct v4l2_rect crop;
 | 
						|
 
 | 
						|
 	const struct imx290_regval *data;
 | 
						|
 	u32 data_size;
 | 
						|
@@ -384,6 +392,12 @@ static const struct imx290_mode imx290_m
 | 
						|
 		.hmax = 0x1130,
 | 
						|
 		.vmax = 0x0465,
 | 
						|
 		.link_freq_index = FREQ_INDEX_1080P,
 | 
						|
+		.crop = {
 | 
						|
+			.left = 4 + 8,
 | 
						|
+			.top = 12 + 8,
 | 
						|
+			.width = 1920,
 | 
						|
+			.height = 1080,
 | 
						|
+		},
 | 
						|
 		.data = imx290_1080p_settings,
 | 
						|
 		.data_size = ARRAY_SIZE(imx290_1080p_settings),
 | 
						|
 		.clk_data = {
 | 
						|
@@ -398,6 +412,12 @@ static const struct imx290_mode imx290_m
 | 
						|
 		.hmax = 0x19c8,
 | 
						|
 		.vmax = 0x02ee,
 | 
						|
 		.link_freq_index = FREQ_INDEX_720P,
 | 
						|
+		.crop = {
 | 
						|
+			.left = 4 + 8 + 320,
 | 
						|
+			.top = 12 + 8 + 180,
 | 
						|
+			.width = 1280,
 | 
						|
+			.height = 720,
 | 
						|
+		},
 | 
						|
 		.data = imx290_720p_settings,
 | 
						|
 		.data_size = ARRAY_SIZE(imx290_720p_settings),
 | 
						|
 		.clk_data = {
 | 
						|
@@ -415,6 +435,12 @@ static const struct imx290_mode imx290_m
 | 
						|
 		.hmax = 0x0898,
 | 
						|
 		.vmax = 0x0465,
 | 
						|
 		.link_freq_index = FREQ_INDEX_1080P,
 | 
						|
+		.crop = {
 | 
						|
+			.left = 4 + 8,
 | 
						|
+			.top = 12 + 8,
 | 
						|
+			.width = 1920,
 | 
						|
+			.height = 1080,
 | 
						|
+		},
 | 
						|
 		.data = imx290_1080p_settings,
 | 
						|
 		.data_size = ARRAY_SIZE(imx290_1080p_settings),
 | 
						|
 		.clk_data = {
 | 
						|
@@ -429,6 +455,12 @@ static const struct imx290_mode imx290_m
 | 
						|
 		.hmax = 0x0ce4,
 | 
						|
 		.vmax = 0x02ee,
 | 
						|
 		.link_freq_index = FREQ_INDEX_720P,
 | 
						|
+		.crop = {
 | 
						|
+			.left = 4 + 8 + 320,
 | 
						|
+			.top = 12 + 8 + 180,
 | 
						|
+			.width = 1280,
 | 
						|
+			.height = 720,
 | 
						|
+		},
 | 
						|
 		.data = imx290_720p_settings,
 | 
						|
 		.data_size = ARRAY_SIZE(imx290_720p_settings),
 | 
						|
 		.clk_data = {
 | 
						|
@@ -875,6 +907,57 @@ static int imx290_write_current_format(s
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static const struct v4l2_rect *
 | 
						|
+__imx290_get_pad_crop(struct imx290 *imx290, 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(&imx290->sd, cfg, pad);
 | 
						|
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
 | 
						|
+		return &imx290->current_mode->crop;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return NULL;
 | 
						|
+}
 | 
						|
+
 | 
						|
+static int imx290_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 imx290 *imx290 = to_imx290(sd);
 | 
						|
+
 | 
						|
+		mutex_lock(&imx290->lock);
 | 
						|
+		sel->r = *__imx290_get_pad_crop(imx290, cfg, sel->pad,
 | 
						|
+						sel->which);
 | 
						|
+		mutex_unlock(&imx290->lock);
 | 
						|
+
 | 
						|
+		return 0;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	case V4L2_SEL_TGT_NATIVE_SIZE:
 | 
						|
+		sel->r.top = 0;
 | 
						|
+		sel->r.left = 0;
 | 
						|
+		sel->r.width = IMX290_NATIVE_WIDTH;
 | 
						|
+		sel->r.height = IMX290_NATIVE_HEIGHT;
 | 
						|
+
 | 
						|
+		return 0;
 | 
						|
+
 | 
						|
+	case V4L2_SEL_TGT_CROP_DEFAULT:
 | 
						|
+	case V4L2_SEL_TGT_CROP_BOUNDS:
 | 
						|
+		sel->r.top = IMX290_PIXEL_ARRAY_TOP;
 | 
						|
+		sel->r.left = IMX290_PIXEL_ARRAY_LEFT;
 | 
						|
+		sel->r.width = IMX290_PIXEL_ARRAY_WIDTH;
 | 
						|
+		sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
 | 
						|
+
 | 
						|
+		return 0;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	return -EINVAL;
 | 
						|
+}
 | 
						|
+
 | 
						|
 /* Start streaming */
 | 
						|
 static int imx290_start_streaming(struct imx290 *imx290)
 | 
						|
 {
 | 
						|
@@ -1069,6 +1152,7 @@ static const struct v4l2_subdev_pad_ops
 | 
						|
 	.enum_frame_size = imx290_enum_frame_size,
 | 
						|
 	.get_fmt = imx290_get_fmt,
 | 
						|
 	.set_fmt = imx290_set_fmt,
 | 
						|
+	.get_selection = imx290_get_selection,
 | 
						|
 };
 | 
						|
 
 | 
						|
 static const struct v4l2_subdev_ops imx290_subdev_ops = {
 |