aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-4.19/950-0648-staging-bcm2835-codec-switch-to-multi-planar-API.patch
blob: ce590c96451f472757d3f7f033cde58b8dc3a87e (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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
From cb053a15c5c23e775647d6b65fef4c378bf34b5b Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Thu, 18 Jul 2019 17:07:05 +0800
Subject: [PATCH] staging: bcm2835-codec: switch to multi-planar API

There are two APIs for mem2mem devices, the older single-planar API and
the newer multi-planar one. Without making things overly complex, the
driver can only support one or the other. However the userspace libv4l2
library has a plugin that allows multi-planar API devices to service
single-planar consumers.

Chromium supports the multi-planar API exclusively, though this is
currently limited to ChromiumOS. It would be possible to add support
for generic Linux.

Switching to the multi-planar API would allow usage of both APIs from
userspace.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 .../bcm2835-codec/bcm2835-v4l2-codec.c        | 145 +++++++++---------
 1 file changed, 76 insertions(+), 69 deletions(-)

--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
+++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
@@ -504,7 +504,7 @@ static struct bcm2835_codec_fmt *find_fo
 
 	for (k = 0; k < fmts->num_entries; k++) {
 		fmt = &fmts->list[k];
-		if (fmt->fourcc == f->fmt.pix.pixelformat)
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
 			break;
 	}
 	if (k == fmts->num_entries)
@@ -522,9 +522,9 @@ static struct bcm2835_codec_q_data *get_
 					       enum v4l2_buf_type type)
 {
 	switch (type) {
-	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		return &ctx->q_data[V4L2_M2M_SRC];
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		return &ctx->q_data[V4L2_M2M_DST];
 	default:
 		v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
@@ -541,9 +541,9 @@ static struct vchiq_mmal_port *get_port_
 		return NULL;
 
 	switch (type) {
-	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		return &ctx->component->input[0];
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		return &ctx->component->output[0];
 	default:
 		v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
@@ -752,7 +752,7 @@ static void handle_fmt_changed(struct bc
 		 format->es.video.crop.width, format->es.video.crop.height,
 		 format->es.video.color_space);
 
-	q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 	q_data->crop_width = format->es.video.crop.width;
 	q_data->crop_height = format->es.video.crop.height;
 	q_data->bytesperline = format->es.video.crop.width;
@@ -945,7 +945,7 @@ static int vidioc_querycap(struct file *
 	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
 	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
 		 MEM2MEM_NAME);
-	cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
+	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 	return 0;
 }
@@ -996,16 +996,20 @@ static int vidioc_g_fmt(struct bcm2835_c
 
 	q_data = get_q_data(ctx, f->type);
 
-	f->fmt.pix.width	= q_data->crop_width;
-	f->fmt.pix.height	= q_data->height;
-	f->fmt.pix.field	= V4L2_FIELD_NONE;
-	f->fmt.pix.pixelformat	= q_data->fmt->fourcc;
-	f->fmt.pix.bytesperline	= q_data->bytesperline;
-	f->fmt.pix.sizeimage	= q_data->sizeimage;
-	f->fmt.pix.colorspace	= ctx->colorspace;
-	f->fmt.pix.xfer_func	= ctx->xfer_func;
-	f->fmt.pix.ycbcr_enc	= ctx->ycbcr_enc;
-	f->fmt.pix.quantization	= ctx->quant;
+	f->fmt.pix_mp.width			= q_data->crop_width;
+	f->fmt.pix_mp.height			= q_data->height;
+	f->fmt.pix_mp.pixelformat		= q_data->fmt->fourcc;
+	f->fmt.pix_mp.field			= V4L2_FIELD_NONE;
+	f->fmt.pix_mp.colorspace		= ctx->colorspace;
+	f->fmt.pix_mp.plane_fmt[0].sizeimage	= q_data->sizeimage;
+	f->fmt.pix_mp.plane_fmt[0].bytesperline	= q_data->bytesperline;
+	f->fmt.pix_mp.num_planes		= 1;
+	f->fmt.pix_mp.ycbcr_enc			= ctx->ycbcr_enc;
+	f->fmt.pix_mp.quantization		= ctx->quant;
+	f->fmt.pix_mp.xfer_func			= ctx->xfer_func;
+
+	memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
+	       sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
 
 	return 0;
 }
@@ -1029,17 +1033,17 @@ static int vidioc_try_fmt(struct bcm2835
 	 * The V4L2 specification requires the driver to correct the format
 	 * struct if any of the dimensions is unsupported
 	 */
-	if (f->fmt.pix.width > MAX_W)
-		f->fmt.pix.width = MAX_W;
-	if (f->fmt.pix.height > MAX_H)
-		f->fmt.pix.height = MAX_H;
+	if (f->fmt.pix_mp.width > MAX_W)
+		f->fmt.pix_mp.width = MAX_W;
+	if (f->fmt.pix_mp.height > MAX_H)
+		f->fmt.pix_mp.height = MAX_H;
 
 	if (!fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
 		/* Only clip min w/h on capture. Treat 0x0 as unknown. */
-		if (f->fmt.pix.width < MIN_W)
-			f->fmt.pix.width = MIN_W;
-		if (f->fmt.pix.height < MIN_H)
-			f->fmt.pix.height = MIN_H;
+		if (f->fmt.pix_mp.width < MIN_W)
+			f->fmt.pix_mp.width = MIN_W;
+		if (f->fmt.pix_mp.height < MIN_H)
+			f->fmt.pix_mp.height = MIN_H;
 
 		/*
 		 * For codecs the buffer must have a vertical alignment of 16
@@ -1048,16 +1052,18 @@ static int vidioc_try_fmt(struct bcm2835
 		 * some of the pixels are active.
 		 */
 		if (ctx->dev->role != ISP)
-			f->fmt.pix.height = ALIGN(f->fmt.pix.height, 16);
+			f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
 	}
-	f->fmt.pix.bytesperline = get_bytesperline(f->fmt.pix.width,
-						   fmt);
-	f->fmt.pix.sizeimage = get_sizeimage(f->fmt.pix.bytesperline,
-					     f->fmt.pix.width,
-					     f->fmt.pix.height,
-					     fmt);
+	f->fmt.pix_mp.num_planes = 1;
+	f->fmt.pix_mp.plane_fmt[0].bytesperline =
+		get_bytesperline(f->fmt.pix_mp.width, fmt);
+	f->fmt.pix_mp.plane_fmt[0].sizeimage =
+		get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
+			      f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt);
+	memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
+	       sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
 
-	f->fmt.pix.field = V4L2_FIELD_NONE;
+	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
 
 	return 0;
 }
@@ -1070,8 +1076,8 @@ static int vidioc_try_fmt_vid_cap(struct
 
 	fmt = find_format(f, ctx->dev, true);
 	if (!fmt) {
-		f->fmt.pix.pixelformat = get_default_format(ctx->dev,
-							    true)->fourcc;
+		f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
+							       true)->fourcc;
 		fmt = find_format(f, ctx->dev, true);
 	}
 
@@ -1086,13 +1092,13 @@ static int vidioc_try_fmt_vid_out(struct
 
 	fmt = find_format(f, ctx->dev, false);
 	if (!fmt) {
-		f->fmt.pix.pixelformat = get_default_format(ctx->dev,
-							    false)->fourcc;
+		f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
+							       false)->fourcc;
 		fmt = find_format(f, ctx->dev, false);
 	}
 
-	if (!f->fmt.pix.colorspace)
-		f->fmt.pix.colorspace = ctx->colorspace;
+	if (!f->fmt.pix_mp.colorspace)
+		f->fmt.pix_mp.colorspace = ctx->colorspace;
 
 	return vidioc_try_fmt(ctx, f, fmt);
 }
@@ -1106,9 +1112,10 @@ static int vidioc_s_fmt(struct bcm2835_c
 	bool update_capture_port = false;
 	int ret;
 
-	v4l2_dbg(1, debug, &ctx->dev->v4l2_dev,	"Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
-		 f->type, f->fmt.pix.width, f->fmt.pix.height,
-		 f->fmt.pix.pixelformat, f->fmt.pix.sizeimage);
+	v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
+		 f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		 f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.plane_fmt[0].sizeimage);
+
 
 	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 	if (!vq)
@@ -1124,9 +1131,9 @@ static int vidioc_s_fmt(struct bcm2835_c
 	}
 
 	q_data->fmt = find_format(f, ctx->dev,
-				  f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	q_data->crop_width = f->fmt.pix.width;
-	q_data->height = f->fmt.pix.height;
+				  f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+	q_data->crop_width = f->fmt.pix_mp.width;
+	q_data->height = f->fmt.pix_mp.height;
 	if (!q_data->selection_set)
 		q_data->crop_height = requested_height;
 
@@ -1134,21 +1141,21 @@ static int vidioc_s_fmt(struct bcm2835_c
 	 * Copying the behaviour of vicodec which retains a single set of
 	 * colorspace parameters for both input and output.
 	 */
-	ctx->colorspace = f->fmt.pix.colorspace;
-	ctx->xfer_func = f->fmt.pix.xfer_func;
-	ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
-	ctx->quant = f->fmt.pix.quantization;
+	ctx->colorspace = f->fmt.pix_mp.colorspace;
+	ctx->xfer_func = f->fmt.pix_mp.xfer_func;
+	ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+	ctx->quant = f->fmt.pix_mp.quantization;
 
 	/* All parameters should have been set correctly by try_fmt */
-	q_data->bytesperline = f->fmt.pix.bytesperline;
-	q_data->sizeimage = f->fmt.pix.sizeimage;
+	q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
+	q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
 
 	v4l2_dbg(1, debug, &ctx->dev->v4l2_dev,	"Calulated bpl as %u, size %u\n",
 		 q_data->bytesperline, q_data->sizeimage);
 
 	if (ctx->dev->role == DECODE &&
 	    q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
-	    f->fmt.pix.width && f->fmt.pix.height) {
+	    q_data->crop_width && q_data->height) {
 		/*
 		 * On the decoder, if provided with a resolution on the input
 		 * side, then replicate that to the output side.
@@ -1165,7 +1172,7 @@ static int vidioc_s_fmt(struct bcm2835_c
 		q_data_dst->height = ALIGN(q_data->crop_height, 16);
 
 		q_data_dst->bytesperline =
-			get_bytesperline(f->fmt.pix.width, q_data_dst->fmt);
+			get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt);
 		q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
 						      q_data_dst->crop_width,
 						      q_data_dst->height,
@@ -1215,7 +1222,7 @@ static int vidioc_s_fmt(struct bcm2835_c
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	unsigned int height = f->fmt.pix.height;
+	unsigned int height = f->fmt.pix_mp.height;
 	int ret;
 
 	ret = vidioc_try_fmt_vid_cap(file, priv, f);
@@ -1228,7 +1235,7 @@ static int vidioc_s_fmt_vid_cap(struct f
 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 				struct v4l2_format *f)
 {
-	unsigned int height = f->fmt.pix.height;
+	unsigned int height = f->fmt.pix_mp.height;
 	int ret;
 
 	ret = vidioc_try_fmt_vid_out(file, priv, f);
@@ -1244,7 +1251,7 @@ static int vidioc_g_selection(struct fil
 {
 	struct bcm2835_codec_ctx *ctx = file2ctx(file);
 	struct bcm2835_codec_q_data *q_data;
-	bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
+	bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
 								true : false;
 
 	if ((ctx->dev->role == DECODE && !capture_queue) ||
@@ -1307,7 +1314,7 @@ static int vidioc_s_selection(struct fil
 {
 	struct bcm2835_codec_ctx *ctx = file2ctx(file);
 	struct bcm2835_codec_q_data *q_data = NULL;
-	bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ?
+	bool capture_queue = s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
 								true : false;
 
 	v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: ctx %p, type %d, q_data %p, target %d, rect x/y %d/%d, w/h %ux%u\n",
@@ -1368,7 +1375,7 @@ static int vidioc_s_parm(struct file *fi
 {
 	struct bcm2835_codec_ctx *ctx = file2ctx(file);
 
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 		return -EINVAL;
 
 	ctx->framerate_num =
@@ -1738,15 +1745,15 @@ static int vidioc_encoder_cmd(struct fil
 static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
 	.vidioc_querycap	= vidioc_querycap,
 
-	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
-	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
-
-	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
-	.vidioc_g_fmt_vid_out	= vidioc_g_fmt_vid_out,
-	.vidioc_try_fmt_vid_out	= vidioc_try_fmt_vid_out,
-	.vidioc_s_fmt_vid_out	= vidioc_s_fmt_vid_out,
+	.vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_s_fmt_vid_cap,
+
+	.vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_g_fmt_vid_out,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_s_fmt_vid_out,
 
 	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
 	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
@@ -2089,7 +2096,7 @@ static int bcm2835_codec_start_streaming
 		ctx->component_enabled = true;
 	}
 
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		/*
 		 * Create the EOS buffer.
 		 * We only need the MMAL part, and want to NOT attach a memory
@@ -2216,7 +2223,7 @@ static int queue_init(void *priv, struct
 	struct bcm2835_codec_ctx *ctx = priv;
 	int ret;
 
-	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 	src_vq->drv_priv = ctx;
 	src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
@@ -2230,7 +2237,7 @@ static int queue_init(void *priv, struct
 	if (ret)
 		return ret;
 
-	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
 	dst_vq->drv_priv = ctx;
 	dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);