summaryrefslogtreecommitdiffstats
path: root/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0388-media-rcar-imr-Add-stride-support-to-IMR.patch
blob: ba522ddbff95e1da5bb4f88d0e3af084fecf2283 (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
207
208
209
210
211
212
213
214
215
216
From 48485fd8cc4049745e286d8a4d3617327e5551e8 Mon Sep 17 00:00:00 2001
From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
Date: Wed, 23 Jan 2019 08:07:38 -0800
Subject: [PATCH 208/211] media: rcar-imr: Add stride support to IMR

Add stride support to IMR

Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
---
 drivers/media/platform/rcar_imr.c | 96 ++++++++++++++++++++++++++++++---------
 1 file changed, 74 insertions(+), 22 deletions(-)

diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c
index cdd847c..cb982b8 100644
--- a/drivers/media/platform/rcar_imr.c
+++ b/drivers/media/platform/rcar_imr.c
@@ -418,28 +418,33 @@ static int imr_queue_setup(struct vb2_queue *vq,
 {
 	struct imr_ctx     *ctx = vb2_get_drv_priv(vq);
 	struct imr_q_data  *q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(vq->type) ? 0 : 1];
-	int                 w = q_data->fmt.width;
+	int                 s = q_data->fmt.bytesperline;
 	int                 h = q_data->fmt.height;
 
 	/* ...we use only single-plane formats */
 	*nplanes = 1;
 
+	v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format: %c%c%c%c, s=%d, h=%d\n",
+		(q_data->fmt.pixelformat >> 0) & 0xff, (q_data->fmt.pixelformat >> 8) & 0xff,
+		(q_data->fmt.pixelformat >> 16) & 0xff, (q_data->fmt.pixelformat >> 24) & 0xff,
+		s, h);
+
 	/* ...specify plane size */
 	switch (q_data->fmt.pixelformat) {
 	case V4L2_PIX_FMT_UYVY:
 	case V4L2_PIX_FMT_YUYV:
 	case V4L2_PIX_FMT_VYUY:
 	case V4L2_PIX_FMT_YVYU:
-	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_Y10:
 	case V4L2_PIX_FMT_Y12:
 	case V4L2_PIX_FMT_Y16:
-		sizes[0] = w * h * 2;
-		break;
-
 	case V4L2_PIX_FMT_UV8:
 	case V4L2_PIX_FMT_GREY:
-		sizes[0] = w * h;
+		sizes[0] = s * h;
+		break;
+
+	case V4L2_PIX_FMT_NV16:
+		sizes[0] = s * h * 2;
 		break;
 
 	default:
@@ -782,8 +787,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 	u16     dst_uv_fmt = (cflags & IMR_F_UV12 ? 2 : (cflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_DUV_SHIFT;
 	int     w = ctx->queue[0].fmt.width;
 	int     h = ctx->queue[0].fmt.height;
+	int     s = ctx->queue[0].fmt.bytesperline;
 	int     W = ctx->queue[1].fmt.width;
 	int     H = ctx->queue[1].fmt.height;
+	int     S = ctx->queue[1].fmt.bytesperline;
 	u32     tricr = ctx->color & 0xFFFFFF;
 	int     i;
 
@@ -856,15 +863,15 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 			*dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type) | __imr_clce(type));
 
 			/* ...set source/destination strides basing on Y-plane precision */
-			*dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0));
-			*dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 1 : 0));
+			*dl++ = IMR_OP_WTS(IMR_DSTR, S);
+			*dl++ = IMR_OP_WTS(IMR_SSTR, s);
 		} else {
 			/* ...setup UV-plane processing only */
 			*dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type));
 
 			/* ...set source/destination strides basing on UV-plane precision */
-			*dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_UV10 ? 1 : 0));
-			*dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_UV10 ? 1 : 0));
+			*dl++ = IMR_OP_WTS(IMR_DSTR, S);
+			*dl++ = IMR_OP_WTS(IMR_SSTR, s);
 		}
 	} else {
 		u16		src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0);
@@ -879,19 +886,22 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 		*dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type));
 
 		/* ...set source stride basing on precision (2 or 4 bytes/pixel) */
-		*dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 2 : 1));
+		*dl++ = IMR_OP_WTS(IMR_SSTR, s/* << (iflags & IMR_F_Y10 ? 2 : 1)*/);
 
 		/* ...if output is planar, put the offset value */
 		if (oflags & IMR_F_PLANAR) {
 			/* ...specify offset of a destination UV plane */
 			*dl++ = IMR_OP_WTL(IMR_DSOR, 1);
-			*dl++ = W * H;
+			*dl++ = S * H;
+
+			/* ...force planar output */
+			*dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YISM);
 
 			/* ...destination stride is 1 or 2 bytes/pixel (same for both Y and UV planes) */
-			*dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0));
+			*dl++ = IMR_OP_WTS(IMR_DSTR, S);
 		} else {
 			/* ...destination stride if 2 or 4 bytes/pixel (Y and UV planes interleaved) */
-			*dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 2 : 1));
+			*dl++ = IMR_OP_WTS(IMR_DSTR, S);
 		}
 	}
 
@@ -921,9 +931,6 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg
 		/* ...select correction mode */
 		*dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type) | __imr_luce(type));
 
-		/* ...luminance correction bit must be cleared (if it was set) */
-		//*dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE);
-
 		/* ...draw triangles */
 		*dl++ = IMR_OP_GOSUB;
 		*dl++ = subaddr;
@@ -1226,6 +1233,43 @@ static int imr_extstride_set(struct imr_ctx *ctx, struct imr_rse_param *param)
  * V4L2 I/O controls
  ******************************************************************************/
 
+/* ...check the format stride */
+static inline int __imr_verify_fmt_stride(struct v4l2_pix_format *pix)
+{
+	int     stride;
+
+	switch (pix->pixelformat) {
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_GREY:
+	case V4L2_PIX_FMT_UV8:
+		/* ...single byte per pixel */
+		stride = pix->width;
+		break;
+
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_VYUY:
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_YVYU:
+	case V4L2_PIX_FMT_Y10:
+	case V4L2_PIX_FMT_Y12:
+		/* ...two bytes per pixel */
+		stride = pix->width * 2;
+		break;
+
+	default:
+		/* ...unsupported format */
+		return -1;
+	}
+
+	if (pix->bytesperline)
+		return (pix->bytesperline >= stride ? 0 : -1);
+
+	/* ...no stride is specified; use default one */
+	pix->bytesperline = stride;
+
+	return 0;
+}
+
 /* ...test for a format supported */
 static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f)
 {
@@ -1233,22 +1277,30 @@ static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f)
 	u32     fourcc = pix->pixelformat;
 	int     i;
 
+	/* ...fix-up format stride if needed */
+	if (__imr_verify_fmt_stride(pix) < 0)
+		return -EINVAL;
+
 	/* ...both output and capture interface have the same set of supported formats */
 	for (i = 0; i < ARRAY_SIZE(imr_lx4_formats); i++) {
 		if (fourcc == imr_lx4_formats[i].fourcc) {
 			/* ...fix-up format specification as needed */
 			pix->field = V4L2_FIELD_NONE;
 
-			v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format request: '%c%c%c%c', %d*%d\n",
+			v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s-format request: '%c%c%c%c', %d*%d\n",
+				(V4L2_TYPE_IS_OUTPUT(f->type) ? "output" : "capture"),
 				(fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff,
 				(fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff,
 				pix->width, pix->height);
 
 			/* ...verify source/destination image dimensions */
 			if (V4L2_TYPE_IS_OUTPUT(f->type))
-				v4l_bound_align_image(&pix->width, 128, 2048, 7, &pix->height, 1, 2048, 0, 0);
+				v4l_bound_align_image(&pix->bytesperline, 256, 8192, 8, &pix->height, 1, 2048, 0, 0);
 			else
-				v4l_bound_align_image(&pix->width, 64, 2048, 6, &pix->height, 1, 2048, 0, 0);
+				v4l_bound_align_image(&pix->bytesperline, 64, 8192, 6, &pix->height, 1, 2048, 0, 0);
+
+			/* ...verify width is not exceeding the maximal value */
+			(pix->width > 2048 ? pix->width = 2048 : 0);
 
 			return i;
 		}
@@ -1751,8 +1803,8 @@ static void imr_device_run(void *priv)
 
 	/* ...adjust source/destination parameters of the UV-plane as needed */
 	if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) {
-		*cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height;
-		*cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.width * ctx->queue[1].fmt.height;
+		*cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.bytesperline * ctx->queue[0].fmt.height;
+		*cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.bytesperline * ctx->queue[1].fmt.height;
 	}
 
 	v4l2_dbg(3, debug, &imr->v4l2_dev, "process buffer-pair 0x%08x:0x%08x\n",
-- 
2.7.4