aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0677-media-i2c-ov5647-Add-support-for-g_selection-to-refl.patch
blob: 66715a108e08db995655dc82ecc5c140524115db (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
From 940cac315aaeca33483bffcf09a235195e3f5272 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;