aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0886-media-i2c-imx290-Add-support-for-g_selection-to-repo.patch
blob: 86680af234d4cfe37dc691269202a51b70bd1543 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
From a191c6d6e5180f54ecf16adda61988a16ce9fe48 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)
 {
@@ -1073,6 +1156,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 = {