bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0300-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch
1 From ce81c616a15c8b57fbe0e10ebceffef81a30f156 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 8 Oct 2020 20:24:12 +0100
4 Subject: [PATCH] staging: vc04_services: Add a V4L2 M2M codec driver
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 This adds a V4L2 memory to memory device that wraps the MMAL
10 video decode and video_encode components for H264 and MJPEG encode
11 and decode, MPEG4, H263, and VP8 decode (and MPEG2 decode
12 if the appropriate licence has been purchased).
13
14 This patch squashes all the work done in developing the driver
15 on the Raspberry Pi rpi-5.4.y kernel branch.
16 Thanks to Kieran Bingham, Aman Gupta, Chen-Yu Tsai, and
17 Marek BehĂșn for their contributions. Please refer to the
18 rpi-5.4.y branch for the full history.
19
20 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
21
22 staging/bcm2835-codec: Ensure OUTPUT timestamps are always forwarded
23
24 The firmware by default tries to ensure that decoded frame
25 timestamps always increment. This is counter to the V4L2 API
26 which wants exactly the OUTPUT queue timestamps passed to the
27 CAPTURE queue buffers.
28
29 Disable the firmware option.
30
31 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
32
33 staging/vc04_services/codec: Add support for CID MPEG_HEADER_MODE
34
35 Control V4L2_CID_MPEG_VIDEO_HEADER_MODE controls whether the encoder
36 is meant to emit the header bytes as a separate packet or with the
37 first encoded frame.
38 Add support for it.
39
40 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
41
42 staging/vc04_services/codec: Clear last buf dequeued flag on START
43
44 It appears that the V4L2 M2M framework requires the driver to manually
45 call vb2_clear_last_buffer_dequeued on the CAPTURE queue during a
46 V4L2_DEC_CMD_START.
47 Add such a call.
48
49 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
50
51 staging/vc04-services/codec: Fix logical precedence issue
52
53 Two issues identified with operator precedence in logical
54 expressions. Fix them.
55
56 https://github.com/raspberrypi/linux/issues/4040
57
58 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
59 ---
60 drivers/staging/vc04_services/Kconfig | 1 +
61 drivers/staging/vc04_services/Makefile | 1 +
62 .../vc04_services/bcm2835-codec/Kconfig | 11 +
63 .../vc04_services/bcm2835-codec/Makefile | 8 +
64 .../staging/vc04_services/bcm2835-codec/TODO | 1 +
65 .../bcm2835-codec/bcm2835-v4l2-codec.c | 3016 +++++++++++++++++
66 .../vchiq-mmal/mmal-parameters.h | 3 +
67 7 files changed, 3041 insertions(+)
68 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Kconfig
69 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Makefile
70 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/TODO
71 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
72
73 --- a/drivers/staging/vc04_services/Kconfig
74 +++ b/drivers/staging/vc04_services/Kconfig
75 @@ -44,6 +44,7 @@ source "drivers/staging/vc04_services/bc
76 source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
77
78 source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
79 +source "drivers/staging/vc04_services/bcm2835-codec/Kconfig"
80
81 source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
82
83 --- a/drivers/staging/vc04_services/Makefile
84 +++ b/drivers/staging/vc04_services/Makefile
85 @@ -15,6 +15,7 @@ obj-$(CONFIG_SND_BCM2835) += bcm2835-au
86 obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
87 obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
88 obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
89 +obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec/
90
91 ccflags-y += -I $(srctree)/$(src)/include
92
93 --- /dev/null
94 +++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
95 @@ -0,0 +1,11 @@
96 +config VIDEO_CODEC_BCM2835
97 + tristate "BCM2835 Video codec support"
98 + depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
99 + depends on VIDEO_V4L2 && (ARCH_BCM2835 || COMPILE_TEST)
100 + select BCM2835_VCHIQ_MMAL
101 + select VIDEOBUF2_DMA_CONTIG
102 + select V4L2_MEM2MEM_DEV
103 + help
104 + Say Y here to enable the V4L2 video codecs for
105 + Broadcom BCM2835 SoC. This operates over the VCHIQ interface
106 + to a service running on VideoCore.
107 --- /dev/null
108 +++ b/drivers/staging/vc04_services/bcm2835-codec/Makefile
109 @@ -0,0 +1,8 @@
110 +# SPDX-License-Identifier: GPL-2.0
111 +bcm2835-codec-objs := bcm2835-v4l2-codec.o
112 +
113 +obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec.o
114 +
115 +ccflags-y += \
116 + -I$(srctree)/drivers/staging/vc04_services \
117 + -D__VCCOREVER__=0x04000000
118 --- /dev/null
119 +++ b/drivers/staging/vc04_services/bcm2835-codec/TODO
120 @@ -0,0 +1 @@
121 +No issues. Depends on VCHIQ which is in staging.
122 \ No newline at end of file
123 --- /dev/null
124 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
125 @@ -0,0 +1,3016 @@
126 +// SPDX-License-Identifier: GPL-2.0
127 +
128 +/*
129 + * A v4l2-mem2mem device that wraps the video codec MMAL component.
130 + *
131 + * Copyright 2018 Raspberry Pi (Trading) Ltd.
132 + * Author: Dave Stevenson (dave.stevenson@raspberrypi.com)
133 + *
134 + * Loosely based on the vim2m virtual driver by Pawel Osciak
135 + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
136 + * Pawel Osciak, <pawel@osciak.com>
137 + * Marek Szyprowski, <m.szyprowski@samsung.com>
138 + *
139 + * Whilst this driver uses the v4l2_mem2mem framework, it does not need the
140 + * scheduling aspects, so will always take the buffers, pass them to the VPU,
141 + * and then signal the job as complete.
142 + *
143 + * This program is free software; you can redistribute it and/or modify
144 + * it under the terms of the GNU General Public License as published by the
145 + * Free Software Foundation; either version 2 of the
146 + * License, or (at your option) any later version
147 + */
148 +#include <linux/module.h>
149 +#include <linux/delay.h>
150 +#include <linux/fs.h>
151 +#include <linux/timer.h>
152 +#include <linux/sched.h>
153 +#include <linux/slab.h>
154 +#include <linux/platform_device.h>
155 +#include <linux/syscalls.h>
156 +
157 +#include <media/v4l2-mem2mem.h>
158 +#include <media/v4l2-device.h>
159 +#include <media/v4l2-ioctl.h>
160 +#include <media/v4l2-ctrls.h>
161 +#include <media/v4l2-event.h>
162 +#include <media/videobuf2-dma-contig.h>
163 +
164 +#include "vchiq-mmal/mmal-encodings.h"
165 +#include "vchiq-mmal/mmal-msg.h"
166 +#include "vchiq-mmal/mmal-parameters.h"
167 +#include "vchiq-mmal/mmal-vchiq.h"
168 +
169 +/*
170 + * Default /dev/videoN node numbers for decode and encode.
171 + * Deliberately avoid the very low numbers as these are often taken by webcams
172 + * etc, and simple apps tend to only go for /dev/video0.
173 + */
174 +static int decode_video_nr = 10;
175 +module_param(decode_video_nr, int, 0644);
176 +MODULE_PARM_DESC(decode_video_nr, "decoder video device number");
177 +
178 +static int encode_video_nr = 11;
179 +module_param(encode_video_nr, int, 0644);
180 +MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
181 +
182 +static int isp_video_nr = 12;
183 +module_param(isp_video_nr, int, 0644);
184 +MODULE_PARM_DESC(isp_video_nr, "isp video device number");
185 +
186 +/*
187 + * Workaround for GStreamer v4l2convert component not considering Bayer formats
188 + * as raw, and therefore not considering a V4L2 device that supports them as
189 + * a suitable candidate.
190 + */
191 +static bool disable_bayer;
192 +module_param(disable_bayer, bool, 0644);
193 +MODULE_PARM_DESC(disable_bayer, "Disable support for Bayer formats");
194 +
195 +static unsigned int debug;
196 +module_param(debug, uint, 0644);
197 +MODULE_PARM_DESC(debug, "activates debug info (0-3)");
198 +
199 +enum bcm2835_codec_role {
200 + DECODE,
201 + ENCODE,
202 + ISP,
203 +};
204 +
205 +static const char * const roles[] = {
206 + "decode",
207 + "encode",
208 + "isp"
209 +};
210 +
211 +static const char * const components[] = {
212 + "ril.video_decode",
213 + "ril.video_encode",
214 + "ril.isp",
215 +};
216 +
217 +/* Timeout for stop_streaming to allow all buffers to return */
218 +#define COMPLETE_TIMEOUT (2 * HZ)
219 +
220 +#define MIN_W 32
221 +#define MIN_H 32
222 +#define MAX_W 1920
223 +#define MAX_H 1920
224 +#define BPL_ALIGN 32
225 +#define DEFAULT_WIDTH 640
226 +#define DEFAULT_HEIGHT 480
227 +/*
228 + * The unanswered question - what is the maximum size of a compressed frame?
229 + * V4L2 mandates that the encoded frame must fit in a single buffer. Sizing
230 + * that buffer is a compromise between wasting memory and risking not fitting.
231 + * The 1080P version of Big Buck Bunny has some frames that exceed 512kB.
232 + * Adopt a moderately arbitrary split at 720P for switching between 512 and
233 + * 768kB buffers.
234 + */
235 +#define DEF_COMP_BUF_SIZE_GREATER_720P (768 << 10)
236 +#define DEF_COMP_BUF_SIZE_720P_OR_LESS (512 << 10)
237 +
238 +/* Flags that indicate a format can be used for capture/output */
239 +#define MEM2MEM_CAPTURE BIT(0)
240 +#define MEM2MEM_OUTPUT BIT(1)
241 +
242 +#define MEM2MEM_NAME "bcm2835-codec"
243 +
244 +struct bcm2835_codec_fmt {
245 + u32 fourcc;
246 + int depth;
247 + int bytesperline_align;
248 + u32 flags;
249 + u32 mmal_fmt;
250 + int size_multiplier_x2;
251 + bool is_bayer;
252 +};
253 +
254 +static const struct bcm2835_codec_fmt supported_formats[] = {
255 + {
256 + /* YUV formats */
257 + .fourcc = V4L2_PIX_FMT_YUV420,
258 + .depth = 8,
259 + .bytesperline_align = 32,
260 + .flags = 0,
261 + .mmal_fmt = MMAL_ENCODING_I420,
262 + .size_multiplier_x2 = 3,
263 + }, {
264 + .fourcc = V4L2_PIX_FMT_YVU420,
265 + .depth = 8,
266 + .bytesperline_align = 32,
267 + .flags = 0,
268 + .mmal_fmt = MMAL_ENCODING_YV12,
269 + .size_multiplier_x2 = 3,
270 + }, {
271 + .fourcc = V4L2_PIX_FMT_NV12,
272 + .depth = 8,
273 + .bytesperline_align = 32,
274 + .flags = 0,
275 + .mmal_fmt = MMAL_ENCODING_NV12,
276 + .size_multiplier_x2 = 3,
277 + }, {
278 + .fourcc = V4L2_PIX_FMT_NV21,
279 + .depth = 8,
280 + .bytesperline_align = 32,
281 + .flags = 0,
282 + .mmal_fmt = MMAL_ENCODING_NV21,
283 + .size_multiplier_x2 = 3,
284 + }, {
285 + .fourcc = V4L2_PIX_FMT_RGB565,
286 + .depth = 16,
287 + .bytesperline_align = 32,
288 + .flags = 0,
289 + .mmal_fmt = MMAL_ENCODING_RGB16,
290 + .size_multiplier_x2 = 2,
291 + }, {
292 + .fourcc = V4L2_PIX_FMT_YUYV,
293 + .depth = 16,
294 + .bytesperline_align = 32,
295 + .flags = 0,
296 + .mmal_fmt = MMAL_ENCODING_YUYV,
297 + .size_multiplier_x2 = 2,
298 + }, {
299 + .fourcc = V4L2_PIX_FMT_UYVY,
300 + .depth = 16,
301 + .bytesperline_align = 32,
302 + .flags = 0,
303 + .mmal_fmt = MMAL_ENCODING_UYVY,
304 + .size_multiplier_x2 = 2,
305 + }, {
306 + .fourcc = V4L2_PIX_FMT_YVYU,
307 + .depth = 16,
308 + .bytesperline_align = 32,
309 + .flags = 0,
310 + .mmal_fmt = MMAL_ENCODING_YVYU,
311 + .size_multiplier_x2 = 2,
312 + }, {
313 + .fourcc = V4L2_PIX_FMT_VYUY,
314 + .depth = 16,
315 + .bytesperline_align = 32,
316 + .flags = 0,
317 + .mmal_fmt = MMAL_ENCODING_VYUY,
318 + .size_multiplier_x2 = 2,
319 + }, {
320 + /* RGB formats */
321 + .fourcc = V4L2_PIX_FMT_RGB24,
322 + .depth = 24,
323 + .bytesperline_align = 32,
324 + .flags = 0,
325 + .mmal_fmt = MMAL_ENCODING_RGB24,
326 + .size_multiplier_x2 = 2,
327 + }, {
328 + .fourcc = V4L2_PIX_FMT_BGR24,
329 + .depth = 24,
330 + .bytesperline_align = 32,
331 + .flags = 0,
332 + .mmal_fmt = MMAL_ENCODING_BGR24,
333 + .size_multiplier_x2 = 2,
334 + }, {
335 + .fourcc = V4L2_PIX_FMT_BGR32,
336 + .depth = 32,
337 + .bytesperline_align = 32,
338 + .flags = 0,
339 + .mmal_fmt = MMAL_ENCODING_BGRA,
340 + .size_multiplier_x2 = 2,
341 + }, {
342 + /* Bayer formats */
343 + /* 8 bit */
344 + .fourcc = V4L2_PIX_FMT_SRGGB8,
345 + .depth = 8,
346 + .bytesperline_align = 32,
347 + .flags = 0,
348 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
349 + .size_multiplier_x2 = 2,
350 + .is_bayer = true,
351 + }, {
352 + .fourcc = V4L2_PIX_FMT_SBGGR8,
353 + .depth = 8,
354 + .bytesperline_align = 32,
355 + .flags = 0,
356 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
357 + .size_multiplier_x2 = 2,
358 + .is_bayer = true,
359 + }, {
360 + .fourcc = V4L2_PIX_FMT_SGRBG8,
361 + .depth = 8,
362 + .bytesperline_align = 32,
363 + .flags = 0,
364 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
365 + .size_multiplier_x2 = 2,
366 + .is_bayer = true,
367 + }, {
368 + .fourcc = V4L2_PIX_FMT_SGBRG8,
369 + .depth = 8,
370 + .bytesperline_align = 32,
371 + .flags = 0,
372 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
373 + .size_multiplier_x2 = 2,
374 + .is_bayer = true,
375 + }, {
376 + /* 10 bit */
377 + .fourcc = V4L2_PIX_FMT_SRGGB10P,
378 + .depth = 10,
379 + .bytesperline_align = 32,
380 + .flags = 0,
381 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
382 + .size_multiplier_x2 = 2,
383 + .is_bayer = true,
384 + }, {
385 + .fourcc = V4L2_PIX_FMT_SBGGR10P,
386 + .depth = 10,
387 + .bytesperline_align = 32,
388 + .flags = 0,
389 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
390 + .size_multiplier_x2 = 2,
391 + .is_bayer = true,
392 + }, {
393 + .fourcc = V4L2_PIX_FMT_SGRBG10P,
394 + .depth = 10,
395 + .bytesperline_align = 32,
396 + .flags = 0,
397 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
398 + .size_multiplier_x2 = 2,
399 + .is_bayer = true,
400 + }, {
401 + .fourcc = V4L2_PIX_FMT_SGBRG10P,
402 + .depth = 10,
403 + .bytesperline_align = 32,
404 + .flags = 0,
405 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
406 + .size_multiplier_x2 = 2,
407 + .is_bayer = true,
408 + }, {
409 + /* 12 bit */
410 + .fourcc = V4L2_PIX_FMT_SRGGB12P,
411 + .depth = 12,
412 + .bytesperline_align = 32,
413 + .flags = 0,
414 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
415 + .size_multiplier_x2 = 2,
416 + .is_bayer = true,
417 + }, {
418 + .fourcc = V4L2_PIX_FMT_SBGGR12P,
419 + .depth = 12,
420 + .bytesperline_align = 32,
421 + .flags = 0,
422 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
423 + .size_multiplier_x2 = 2,
424 + .is_bayer = true,
425 + }, {
426 + .fourcc = V4L2_PIX_FMT_SGRBG12P,
427 + .depth = 12,
428 + .bytesperline_align = 32,
429 + .flags = 0,
430 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
431 + .size_multiplier_x2 = 2,
432 + .is_bayer = true,
433 + }, {
434 + .fourcc = V4L2_PIX_FMT_SGBRG12P,
435 + .depth = 12,
436 + .bytesperline_align = 32,
437 + .flags = 0,
438 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
439 + .size_multiplier_x2 = 2,
440 + .is_bayer = true,
441 + }, {
442 + /* 14 bit */
443 + .fourcc = V4L2_PIX_FMT_SRGGB14P,
444 + .depth = 14,
445 + .bytesperline_align = 32,
446 + .flags = 0,
447 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB14P,
448 + .size_multiplier_x2 = 2,
449 + .is_bayer = true,
450 + }, {
451 + .fourcc = V4L2_PIX_FMT_SBGGR14P,
452 + .depth = 14,
453 + .bytesperline_align = 32,
454 + .flags = 0,
455 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR14P,
456 + .size_multiplier_x2 = 2,
457 + .is_bayer = true,
458 +
459 + }, {
460 + .fourcc = V4L2_PIX_FMT_SGRBG14P,
461 + .depth = 14,
462 + .bytesperline_align = 32,
463 + .flags = 0,
464 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG14P,
465 + .size_multiplier_x2 = 2,
466 + .is_bayer = true,
467 + }, {
468 + .fourcc = V4L2_PIX_FMT_SGBRG14P,
469 + .depth = 14,
470 + .bytesperline_align = 32,
471 + .flags = 0,
472 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG14P,
473 + .size_multiplier_x2 = 2,
474 + .is_bayer = true,
475 + }, {
476 + /* 16 bit */
477 + .fourcc = V4L2_PIX_FMT_SRGGB16,
478 + .depth = 16,
479 + .bytesperline_align = 32,
480 + .flags = 0,
481 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
482 + .size_multiplier_x2 = 2,
483 + .is_bayer = true,
484 + }, {
485 + .fourcc = V4L2_PIX_FMT_SBGGR16,
486 + .depth = 16,
487 + .bytesperline_align = 32,
488 + .flags = 0,
489 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
490 + .size_multiplier_x2 = 2,
491 + .is_bayer = true,
492 + }, {
493 + .fourcc = V4L2_PIX_FMT_SGRBG16,
494 + .depth = 16,
495 + .bytesperline_align = 32,
496 + .flags = 0,
497 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
498 + .size_multiplier_x2 = 2,
499 + .is_bayer = true,
500 + }, {
501 + .fourcc = V4L2_PIX_FMT_SGBRG16,
502 + .depth = 16,
503 + .bytesperline_align = 32,
504 + .flags = 0,
505 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
506 + .size_multiplier_x2 = 2,
507 + .is_bayer = true,
508 + }, {
509 + /* Monochrome MIPI formats */
510 + /* 8 bit */
511 + .fourcc = V4L2_PIX_FMT_GREY,
512 + .depth = 8,
513 + .bytesperline_align = 32,
514 + .flags = 0,
515 + .mmal_fmt = MMAL_ENCODING_GREY,
516 + .size_multiplier_x2 = 2,
517 + }, {
518 + /* 10 bit */
519 + .fourcc = V4L2_PIX_FMT_Y10P,
520 + .depth = 10,
521 + .bytesperline_align = 32,
522 + .flags = 0,
523 + .mmal_fmt = MMAL_ENCODING_Y10P,
524 + .size_multiplier_x2 = 2,
525 + }, {
526 + /* 12 bit */
527 + .fourcc = V4L2_PIX_FMT_Y12P,
528 + .depth = 12,
529 + .bytesperline_align = 32,
530 + .flags = 0,
531 + .mmal_fmt = MMAL_ENCODING_Y12P,
532 + .size_multiplier_x2 = 2,
533 + }, {
534 + /* 14 bit */
535 + .fourcc = V4L2_PIX_FMT_Y14P,
536 + .depth = 14,
537 + .bytesperline_align = 32,
538 + .flags = 0,
539 + .mmal_fmt = MMAL_ENCODING_Y14P,
540 + .size_multiplier_x2 = 2,
541 + }, {
542 + /* 16 bit */
543 + .fourcc = V4L2_PIX_FMT_Y16,
544 + .depth = 16,
545 + .bytesperline_align = 32,
546 + .flags = 0,
547 + .mmal_fmt = MMAL_ENCODING_Y16,
548 + .size_multiplier_x2 = 2,
549 + }, {
550 + /* Compressed formats */
551 + .fourcc = V4L2_PIX_FMT_H264,
552 + .depth = 0,
553 + .flags = V4L2_FMT_FLAG_COMPRESSED,
554 + .mmal_fmt = MMAL_ENCODING_H264,
555 + }, {
556 + .fourcc = V4L2_PIX_FMT_MJPEG,
557 + .depth = 0,
558 + .flags = V4L2_FMT_FLAG_COMPRESSED,
559 + .mmal_fmt = MMAL_ENCODING_MJPEG,
560 + }, {
561 + .fourcc = V4L2_PIX_FMT_MPEG4,
562 + .depth = 0,
563 + .flags = V4L2_FMT_FLAG_COMPRESSED,
564 + .mmal_fmt = MMAL_ENCODING_MP4V,
565 + }, {
566 + .fourcc = V4L2_PIX_FMT_H263,
567 + .depth = 0,
568 + .flags = V4L2_FMT_FLAG_COMPRESSED,
569 + .mmal_fmt = MMAL_ENCODING_H263,
570 + }, {
571 + .fourcc = V4L2_PIX_FMT_MPEG2,
572 + .depth = 0,
573 + .flags = V4L2_FMT_FLAG_COMPRESSED,
574 + .mmal_fmt = MMAL_ENCODING_MP2V,
575 + }, {
576 + .fourcc = V4L2_PIX_FMT_VP8,
577 + .depth = 0,
578 + .flags = V4L2_FMT_FLAG_COMPRESSED,
579 + .mmal_fmt = MMAL_ENCODING_VP8,
580 + },
581 +};
582 +
583 +struct bcm2835_codec_fmt_list {
584 + struct bcm2835_codec_fmt *list;
585 + unsigned int num_entries;
586 +};
587 +
588 +struct m2m_mmal_buffer {
589 + struct v4l2_m2m_buffer m2m;
590 + struct mmal_buffer mmal;
591 +};
592 +
593 +/* Per-queue, driver-specific private data */
594 +struct bcm2835_codec_q_data {
595 + /*
596 + * These parameters should be treated as gospel, with everything else
597 + * being determined from them.
598 + */
599 + /* Buffer width/height */
600 + unsigned int bytesperline;
601 + unsigned int height;
602 + /* Crop size used for selection handling */
603 + unsigned int crop_width;
604 + unsigned int crop_height;
605 + bool selection_set;
606 +
607 + unsigned int sizeimage;
608 + unsigned int sequence;
609 + struct bcm2835_codec_fmt *fmt;
610 +
611 + /* One extra buffer header so we can send an EOS. */
612 + struct m2m_mmal_buffer eos_buffer;
613 + bool eos_buffer_in_use; /* debug only */
614 +};
615 +
616 +struct bcm2835_codec_dev {
617 + struct platform_device *pdev;
618 +
619 + /* v4l2 devices */
620 + struct v4l2_device v4l2_dev;
621 + struct video_device vfd;
622 + /* mutex for the v4l2 device */
623 + struct mutex dev_mutex;
624 + atomic_t num_inst;
625 +
626 + /* allocated mmal instance and components */
627 + enum bcm2835_codec_role role;
628 + /* The list of formats supported on input and output queues. */
629 + struct bcm2835_codec_fmt_list supported_fmts[2];
630 +
631 + struct vchiq_mmal_instance *instance;
632 +
633 + struct v4l2_m2m_dev *m2m_dev;
634 +};
635 +
636 +struct bcm2835_codec_ctx {
637 + struct v4l2_fh fh;
638 + struct bcm2835_codec_dev *dev;
639 +
640 + struct v4l2_ctrl_handler hdl;
641 +
642 + struct vchiq_mmal_component *component;
643 + bool component_enabled;
644 +
645 + enum v4l2_colorspace colorspace;
646 + enum v4l2_ycbcr_encoding ycbcr_enc;
647 + enum v4l2_xfer_func xfer_func;
648 + enum v4l2_quantization quant;
649 +
650 + /* Source and destination queue data */
651 + struct bcm2835_codec_q_data q_data[2];
652 + s32 bitrate;
653 + unsigned int framerate_num;
654 + unsigned int framerate_denom;
655 +
656 + bool aborting;
657 + int num_ip_buffers;
658 + int num_op_buffers;
659 + struct completion frame_cmplt;
660 +};
661 +
662 +struct bcm2835_codec_driver {
663 + struct platform_device *pdev;
664 + struct media_device mdev;
665 +
666 + struct bcm2835_codec_dev *encode;
667 + struct bcm2835_codec_dev *decode;
668 + struct bcm2835_codec_dev *isp;
669 +};
670 +
671 +enum {
672 + V4L2_M2M_SRC = 0,
673 + V4L2_M2M_DST = 1,
674 +};
675 +
676 +static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
677 +{
678 + unsigned int i;
679 +
680 + for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
681 + if (supported_formats[i].mmal_fmt == mmal_fmt &&
682 + (!disable_bayer || !supported_formats[i].is_bayer))
683 + return &supported_formats[i];
684 + }
685 + return NULL;
686 +}
687 +
688 +static inline
689 +struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
690 + bool capture)
691 +{
692 + return &dev->supported_fmts[capture ? 1 : 0];
693 +}
694 +
695 +static
696 +struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
697 + bool capture)
698 +{
699 + return &dev->supported_fmts[capture ? 1 : 0].list[0];
700 +}
701 +
702 +static
703 +struct bcm2835_codec_fmt *find_format_pix_fmt(u32 pix_fmt,
704 + struct bcm2835_codec_dev *dev,
705 + bool capture)
706 +{
707 + struct bcm2835_codec_fmt *fmt;
708 + unsigned int k;
709 + struct bcm2835_codec_fmt_list *fmts =
710 + &dev->supported_fmts[capture ? 1 : 0];
711 +
712 + for (k = 0; k < fmts->num_entries; k++) {
713 + fmt = &fmts->list[k];
714 + if (fmt->fourcc == pix_fmt)
715 + break;
716 + }
717 + if (k == fmts->num_entries)
718 + return NULL;
719 +
720 + return &fmts->list[k];
721 +}
722 +
723 +static inline
724 +struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
725 + struct bcm2835_codec_dev *dev,
726 + bool capture)
727 +{
728 + return find_format_pix_fmt(f->fmt.pix_mp.pixelformat, dev, capture);
729 +}
730 +
731 +static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
732 +{
733 + return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
734 +}
735 +
736 +static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
737 + enum v4l2_buf_type type)
738 +{
739 + switch (type) {
740 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
741 + return &ctx->q_data[V4L2_M2M_SRC];
742 + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
743 + return &ctx->q_data[V4L2_M2M_DST];
744 + default:
745 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
746 + __func__, type);
747 + break;
748 + }
749 + return NULL;
750 +}
751 +
752 +static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
753 + enum v4l2_buf_type type)
754 +{
755 + if (!ctx->component)
756 + return NULL;
757 +
758 + switch (type) {
759 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
760 + return &ctx->component->input[0];
761 + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
762 + return &ctx->component->output[0];
763 + default:
764 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
765 + __func__, type);
766 + break;
767 + }
768 + return NULL;
769 +}
770 +
771 +/*
772 + * mem2mem callbacks
773 + */
774 +
775 +/*
776 + * job_ready() - check whether an instance is ready to be scheduled to run
777 + */
778 +static int job_ready(void *priv)
779 +{
780 + struct bcm2835_codec_ctx *ctx = priv;
781 +
782 + if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
783 + !v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
784 + return 0;
785 +
786 + return 1;
787 +}
788 +
789 +static void job_abort(void *priv)
790 +{
791 + struct bcm2835_codec_ctx *ctx = priv;
792 +
793 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s\n", __func__);
794 + /* Will cancel the transaction in the next interrupt handler */
795 + ctx->aborting = 1;
796 +}
797 +
798 +static inline unsigned int get_sizeimage(int bpl, int width, int height,
799 + struct bcm2835_codec_fmt *fmt)
800 +{
801 + if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
802 + if (width * height > 1280 * 720)
803 + return DEF_COMP_BUF_SIZE_GREATER_720P;
804 + else
805 + return DEF_COMP_BUF_SIZE_720P_OR_LESS;
806 + } else {
807 + return (bpl * height * fmt->size_multiplier_x2) >> 1;
808 + }
809 +}
810 +
811 +static inline unsigned int get_bytesperline(int width,
812 + struct bcm2835_codec_fmt *fmt)
813 +{
814 + return ALIGN((width * fmt->depth) >> 3, fmt->bytesperline_align);
815 +}
816 +
817 +static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
818 + struct bcm2835_codec_q_data *q_data,
819 + struct vchiq_mmal_port *port)
820 +{
821 + port->format.encoding = q_data->fmt->mmal_fmt;
822 +
823 + if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
824 + /* Raw image format - set width/height */
825 + port->es.video.width = (q_data->bytesperline << 3) /
826 + q_data->fmt->depth;
827 + port->es.video.height = q_data->height;
828 + port->es.video.crop.width = q_data->crop_width;
829 + port->es.video.crop.height = q_data->crop_height;
830 + port->es.video.frame_rate.num = ctx->framerate_num;
831 + port->es.video.frame_rate.den = ctx->framerate_denom;
832 + } else {
833 + /* Compressed format - leave resolution as 0 for decode */
834 + if (ctx->dev->role == DECODE) {
835 + port->es.video.width = 0;
836 + port->es.video.height = 0;
837 + port->es.video.crop.width = 0;
838 + port->es.video.crop.height = 0;
839 + } else {
840 + port->es.video.width = q_data->crop_width;
841 + port->es.video.height = q_data->height;
842 + port->es.video.crop.width = q_data->crop_width;
843 + port->es.video.crop.height = q_data->crop_height;
844 + port->format.bitrate = ctx->bitrate;
845 + port->es.video.frame_rate.num = ctx->framerate_num;
846 + port->es.video.frame_rate.den = ctx->framerate_denom;
847 + }
848 + }
849 + port->es.video.crop.x = 0;
850 + port->es.video.crop.y = 0;
851 +
852 + port->current_buffer.size = q_data->sizeimage;
853 +};
854 +
855 +static void ip_buffer_cb(struct vchiq_mmal_instance *instance,
856 + struct vchiq_mmal_port *port, int status,
857 + struct mmal_buffer *mmal_buf)
858 +{
859 + struct bcm2835_codec_ctx *ctx = port->cb_ctx/*, *curr_ctx*/;
860 + struct m2m_mmal_buffer *buf =
861 + container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
862 +
863 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: port %p buf %p length %lu, flags %x\n",
864 + __func__, port, mmal_buf, mmal_buf->length,
865 + mmal_buf->mmal_flags);
866 +
867 + if (buf == &ctx->q_data[V4L2_M2M_SRC].eos_buffer) {
868 + /* Do we need to add lcoking to prevent multiple submission of
869 + * the EOS, and therefore handle mutliple return here?
870 + */
871 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: eos buffer returned.\n",
872 + __func__);
873 + ctx->q_data[V4L2_M2M_SRC].eos_buffer_in_use = false;
874 + return;
875 + }
876 +
877 + if (status) {
878 + /* error in transfer */
879 + if (buf)
880 + /* there was a buffer with the error so return it */
881 + vb2_buffer_done(&buf->m2m.vb.vb2_buf,
882 + VB2_BUF_STATE_ERROR);
883 + return;
884 + }
885 + if (mmal_buf->cmd) {
886 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Not expecting cmd msgs on ip callback - %08x\n",
887 + __func__, mmal_buf->cmd);
888 + /*
889 + * CHECKME: Should we return here. The buffer shouldn't have a
890 + * message context or vb2 buf associated.
891 + */
892 + }
893 +
894 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: no error. Return buffer %p\n",
895 + __func__, &buf->m2m.vb.vb2_buf);
896 + vb2_buffer_done(&buf->m2m.vb.vb2_buf, VB2_BUF_STATE_DONE);
897 +
898 + ctx->num_ip_buffers++;
899 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d input buffers\n",
900 + __func__, ctx->num_ip_buffers);
901 +
902 + if (!port->enabled)
903 + complete(&ctx->frame_cmplt);
904 +}
905 +
906 +static void queue_res_chg_event(struct bcm2835_codec_ctx *ctx)
907 +{
908 + static const struct v4l2_event ev_src_ch = {
909 + .type = V4L2_EVENT_SOURCE_CHANGE,
910 + .u.src_change.changes =
911 + V4L2_EVENT_SRC_CH_RESOLUTION,
912 + };
913 +
914 + v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
915 +}
916 +
917 +static void send_eos_event(struct bcm2835_codec_ctx *ctx)
918 +{
919 + static const struct v4l2_event ev = {
920 + .type = V4L2_EVENT_EOS,
921 + };
922 +
923 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Sending EOS event\n");
924 +
925 + v4l2_event_queue_fh(&ctx->fh, &ev);
926 +}
927 +
928 +static void color_mmal2v4l(struct bcm2835_codec_ctx *ctx, u32 mmal_color_space)
929 +{
930 + switch (mmal_color_space) {
931 + case MMAL_COLOR_SPACE_ITUR_BT601:
932 + ctx->colorspace = V4L2_COLORSPACE_REC709;
933 + ctx->xfer_func = V4L2_XFER_FUNC_709;
934 + ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
935 + ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
936 + break;
937 +
938 + case MMAL_COLOR_SPACE_ITUR_BT709:
939 + ctx->colorspace = V4L2_COLORSPACE_REC709;
940 + ctx->xfer_func = V4L2_XFER_FUNC_709;
941 + ctx->ycbcr_enc = V4L2_YCBCR_ENC_709;
942 + ctx->quant = V4L2_QUANTIZATION_LIM_RANGE;
943 + break;
944 + }
945 +}
946 +
947 +static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
948 + struct mmal_buffer *mmal_buf)
949 +{
950 + struct bcm2835_codec_q_data *q_data;
951 + struct mmal_msg_event_format_changed *format =
952 + (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
953 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
954 + __func__,
955 + format->buffer_size_min,
956 + format->buffer_size_recommended,
957 + format->buffer_num_min,
958 + format->buffer_num_recommended
959 + );
960 + if (format->format.type != MMAL_ES_TYPE_VIDEO) {
961 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed but not video %u\n",
962 + __func__, format->format.type);
963 + return;
964 + }
965 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed to %ux%u, crop %ux%u, colourspace %08X\n",
966 + __func__, format->es.video.width, format->es.video.height,
967 + format->es.video.crop.width, format->es.video.crop.height,
968 + format->es.video.color_space);
969 +
970 + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
971 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format was %ux%u, crop %ux%u\n",
972 + __func__, q_data->bytesperline, q_data->height,
973 + q_data->crop_width, q_data->crop_height);
974 +
975 + q_data->crop_width = format->es.video.crop.width;
976 + q_data->crop_height = format->es.video.crop.height;
977 + q_data->bytesperline = get_bytesperline(format->es.video.width,
978 + q_data->fmt);
979 +
980 + q_data->height = format->es.video.height;
981 + q_data->sizeimage = format->buffer_size_min;
982 + if (format->es.video.color_space)
983 + color_mmal2v4l(ctx, format->es.video.color_space);
984 +
985 + queue_res_chg_event(ctx);
986 +}
987 +
988 +static void op_buffer_cb(struct vchiq_mmal_instance *instance,
989 + struct vchiq_mmal_port *port, int status,
990 + struct mmal_buffer *mmal_buf)
991 +{
992 + struct bcm2835_codec_ctx *ctx = port->cb_ctx;
993 + struct m2m_mmal_buffer *buf;
994 + struct vb2_v4l2_buffer *vb2;
995 +
996 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev,
997 + "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
998 + __func__, status, mmal_buf, mmal_buf->length,
999 + mmal_buf->mmal_flags, mmal_buf->pts);
1000 +
1001 + buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
1002 + vb2 = &buf->m2m.vb;
1003 +
1004 + if (status) {
1005 + /* error in transfer */
1006 + if (vb2) {
1007 + /* there was a buffer with the error so return it */
1008 + vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
1009 + }
1010 + return;
1011 + }
1012 +
1013 + if (mmal_buf->cmd) {
1014 + switch (mmal_buf->cmd) {
1015 + case MMAL_EVENT_FORMAT_CHANGED:
1016 + {
1017 + handle_fmt_changed(ctx, mmal_buf);
1018 + break;
1019 + }
1020 + default:
1021 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Unexpected event on output callback - %08x\n",
1022 + __func__, mmal_buf->cmd);
1023 + break;
1024 + }
1025 + return;
1026 + }
1027 +
1028 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
1029 + __func__, mmal_buf->length, mmal_buf->mmal_flags,
1030 + vb2->vb2_buf.index);
1031 +
1032 + if (mmal_buf->length == 0) {
1033 + /* stream ended, or buffer being returned during disable. */
1034 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
1035 + __func__, mmal_buf->mmal_flags);
1036 + if (!(mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS)) {
1037 + vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
1038 + if (!port->enabled)
1039 + complete(&ctx->frame_cmplt);
1040 + return;
1041 + }
1042 + }
1043 + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
1044 + /* EOS packet from the VPU */
1045 + send_eos_event(ctx);
1046 + vb2->flags |= V4L2_BUF_FLAG_LAST;
1047 + }
1048 +
1049 + /* vb2 timestamps in nsecs, mmal in usecs */
1050 + vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
1051 +
1052 + vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
1053 + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
1054 + vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
1055 +
1056 + vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_DONE);
1057 + ctx->num_op_buffers++;
1058 +
1059 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d output buffers\n",
1060 + __func__, ctx->num_op_buffers);
1061 +
1062 + if (!port->enabled)
1063 + complete(&ctx->frame_cmplt);
1064 +}
1065 +
1066 +/* vb2_to_mmal_buffer() - converts vb2 buffer header to MMAL
1067 + *
1068 + * Copies all the required fields from a VB2 buffer to the MMAL buffer header,
1069 + * ready for sending to the VPU.
1070 + */
1071 +static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
1072 + struct vb2_v4l2_buffer *vb2)
1073 +{
1074 + u64 pts;
1075 +
1076 + buf->mmal.mmal_flags = 0;
1077 + if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
1078 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
1079 +
1080 + /*
1081 + * Adding this means that the data must be framed correctly as one frame
1082 + * per buffer. The underlying decoder has no such requirement, but it
1083 + * will reduce latency as the bistream parser will be kicked immediately
1084 + * to parse the frame, rather than relying on its own heuristics for
1085 + * when to wake up.
1086 + */
1087 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
1088 +
1089 + buf->mmal.length = vb2->vb2_buf.planes[0].bytesused;
1090 + /*
1091 + * Minor ambiguity in the V4L2 spec as to whether passing in a 0 length
1092 + * buffer, or one with V4L2_BUF_FLAG_LAST set denotes end of stream.
1093 + * Handle either.
1094 + */
1095 + if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
1096 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
1097 +
1098 + /* vb2 timestamps in nsecs, mmal in usecs */
1099 + pts = vb2->vb2_buf.timestamp;
1100 + do_div(pts, 1000);
1101 + buf->mmal.pts = pts;
1102 + buf->mmal.dts = MMAL_TIME_UNKNOWN;
1103 +}
1104 +
1105 +/* device_run() - prepares and starts the device
1106 + *
1107 + * This simulates all the immediate preparations required before starting
1108 + * a device. This will be called by the framework when it decides to schedule
1109 + * a particular instance.
1110 + */
1111 +static void device_run(void *priv)
1112 +{
1113 + struct bcm2835_codec_ctx *ctx = priv;
1114 + struct bcm2835_codec_dev *dev = ctx->dev;
1115 + struct vb2_v4l2_buffer *src_buf, *dst_buf;
1116 + struct m2m_mmal_buffer *src_m2m_buf = NULL, *dst_m2m_buf = NULL;
1117 + struct v4l2_m2m_buffer *m2m;
1118 + int ret;
1119 +
1120 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: off we go\n", __func__);
1121 +
1122 + src_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->out_q_ctx);
1123 + if (src_buf) {
1124 + m2m = container_of(src_buf, struct v4l2_m2m_buffer, vb);
1125 + src_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
1126 + vb2_to_mmal_buffer(src_m2m_buf, src_buf);
1127 +
1128 + ret = vchiq_mmal_submit_buffer(dev->instance,
1129 + &ctx->component->input[0],
1130 + &src_m2m_buf->mmal);
1131 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted ip buffer len %lu, pts %llu, flags %04x\n",
1132 + __func__, src_m2m_buf->mmal.length,
1133 + src_m2m_buf->mmal.pts, src_m2m_buf->mmal.mmal_flags);
1134 + if (ret)
1135 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting ip buffer\n",
1136 + __func__);
1137 + }
1138 +
1139 + dst_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->cap_q_ctx);
1140 + if (dst_buf) {
1141 + m2m = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
1142 + dst_m2m_buf = container_of(m2m, struct m2m_mmal_buffer, m2m);
1143 + vb2_to_mmal_buffer(dst_m2m_buf, dst_buf);
1144 +
1145 + ret = vchiq_mmal_submit_buffer(dev->instance,
1146 + &ctx->component->output[0],
1147 + &dst_m2m_buf->mmal);
1148 + if (ret)
1149 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed submitting op buffer\n",
1150 + __func__);
1151 + }
1152 +
1153 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted src %p, dst %p\n",
1154 + __func__, src_m2m_buf, dst_m2m_buf);
1155 +
1156 + /* Complete the job here. */
1157 + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
1158 +}
1159 +
1160 +/*
1161 + * video ioctls
1162 + */
1163 +static int vidioc_querycap(struct file *file, void *priv,
1164 + struct v4l2_capability *cap)
1165 +{
1166 + struct bcm2835_codec_dev *dev = video_drvdata(file);
1167 +
1168 + strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
1169 + strncpy(cap->card, dev->vfd.name, sizeof(cap->card) - 1);
1170 + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1171 + MEM2MEM_NAME);
1172 + return 0;
1173 +}
1174 +
1175 +static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
1176 + bool capture)
1177 +{
1178 + struct bcm2835_codec_fmt *fmt;
1179 + struct bcm2835_codec_fmt_list *fmts =
1180 + get_format_list(ctx->dev, capture);
1181 +
1182 + if (f->index < fmts->num_entries) {
1183 + /* Format found */
1184 + fmt = &fmts->list[f->index];
1185 + f->pixelformat = fmt->fourcc;
1186 + f->flags = fmt->flags;
1187 + return 0;
1188 + }
1189 +
1190 + /* Format not found */
1191 + return -EINVAL;
1192 +}
1193 +
1194 +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1195 + struct v4l2_fmtdesc *f)
1196 +{
1197 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1198 +
1199 + return enum_fmt(f, ctx, true);
1200 +}
1201 +
1202 +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
1203 + struct v4l2_fmtdesc *f)
1204 +{
1205 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1206 +
1207 + return enum_fmt(f, ctx, false);
1208 +}
1209 +
1210 +static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
1211 +{
1212 + struct vb2_queue *vq;
1213 + struct bcm2835_codec_q_data *q_data;
1214 +
1215 + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
1216 + if (!vq)
1217 + return -EINVAL;
1218 +
1219 + q_data = get_q_data(ctx, f->type);
1220 +
1221 + f->fmt.pix_mp.width = q_data->crop_width;
1222 + f->fmt.pix_mp.height = q_data->height;
1223 + f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc;
1224 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
1225 + f->fmt.pix_mp.colorspace = ctx->colorspace;
1226 + f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage;
1227 + f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
1228 + f->fmt.pix_mp.num_planes = 1;
1229 + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
1230 + f->fmt.pix_mp.quantization = ctx->quant;
1231 + f->fmt.pix_mp.xfer_func = ctx->xfer_func;
1232 +
1233 + memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
1234 + sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
1235 +
1236 + return 0;
1237 +}
1238 +
1239 +static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
1240 + struct v4l2_format *f)
1241 +{
1242 + return vidioc_g_fmt(file2ctx(file), f);
1243 +}
1244 +
1245 +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1246 + struct v4l2_format *f)
1247 +{
1248 + return vidioc_g_fmt(file2ctx(file), f);
1249 +}
1250 +
1251 +static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
1252 + struct bcm2835_codec_fmt *fmt)
1253 +{
1254 + /*
1255 + * The V4L2 specification requires the driver to correct the format
1256 + * struct if any of the dimensions is unsupported
1257 + */
1258 + if (f->fmt.pix_mp.width > MAX_W)
1259 + f->fmt.pix_mp.width = MAX_W;
1260 + if (f->fmt.pix_mp.height > MAX_H)
1261 + f->fmt.pix_mp.height = MAX_H;
1262 +
1263 + if (!(fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
1264 + /* Only clip min w/h on capture. Treat 0x0 as unknown. */
1265 + if (f->fmt.pix_mp.width < MIN_W)
1266 + f->fmt.pix_mp.width = MIN_W;
1267 + if (f->fmt.pix_mp.height < MIN_H)
1268 + f->fmt.pix_mp.height = MIN_H;
1269 +
1270 + /*
1271 + * For decoders the buffer must have a vertical alignment of 16
1272 + * lines.
1273 + * The selection will reflect any cropping rectangle when only
1274 + * some of the pixels are active.
1275 + */
1276 + if (ctx->dev->role == DECODE)
1277 + f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
1278 + }
1279 + f->fmt.pix_mp.num_planes = 1;
1280 + f->fmt.pix_mp.plane_fmt[0].bytesperline =
1281 + get_bytesperline(f->fmt.pix_mp.width, fmt);
1282 + f->fmt.pix_mp.plane_fmt[0].sizeimage =
1283 + get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
1284 + f->fmt.pix_mp.width, f->fmt.pix_mp.height, fmt);
1285 + memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
1286 + sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
1287 +
1288 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
1289 +
1290 + return 0;
1291 +}
1292 +
1293 +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1294 + struct v4l2_format *f)
1295 +{
1296 + struct bcm2835_codec_fmt *fmt;
1297 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1298 +
1299 + fmt = find_format(f, ctx->dev, true);
1300 + if (!fmt) {
1301 + f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
1302 + true)->fourcc;
1303 + fmt = find_format(f, ctx->dev, true);
1304 + }
1305 +
1306 + return vidioc_try_fmt(ctx, f, fmt);
1307 +}
1308 +
1309 +static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
1310 + struct v4l2_format *f)
1311 +{
1312 + struct bcm2835_codec_fmt *fmt;
1313 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1314 +
1315 + fmt = find_format(f, ctx->dev, false);
1316 + if (!fmt) {
1317 + f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
1318 + false)->fourcc;
1319 + fmt = find_format(f, ctx->dev, false);
1320 + }
1321 +
1322 + if (!f->fmt.pix_mp.colorspace)
1323 + f->fmt.pix_mp.colorspace = ctx->colorspace;
1324 +
1325 + return vidioc_try_fmt(ctx, f, fmt);
1326 +}
1327 +
1328 +static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
1329 + unsigned int requested_height)
1330 +{
1331 + struct bcm2835_codec_q_data *q_data;
1332 + struct vb2_queue *vq;
1333 + struct vchiq_mmal_port *port;
1334 + bool update_capture_port = false;
1335 + int ret;
1336 +
1337 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
1338 + f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
1339 + f->fmt.pix_mp.pixelformat,
1340 + f->fmt.pix_mp.plane_fmt[0].sizeimage);
1341 +
1342 + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
1343 + if (!vq)
1344 + return -EINVAL;
1345 +
1346 + q_data = get_q_data(ctx, f->type);
1347 + if (!q_data)
1348 + return -EINVAL;
1349 +
1350 + if (vb2_is_busy(vq)) {
1351 + v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
1352 + return -EBUSY;
1353 + }
1354 +
1355 + q_data->fmt = find_format(f, ctx->dev,
1356 + f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1357 + q_data->crop_width = f->fmt.pix_mp.width;
1358 + q_data->height = f->fmt.pix_mp.height;
1359 + if (!q_data->selection_set)
1360 + q_data->crop_height = requested_height;
1361 +
1362 + /*
1363 + * Copying the behaviour of vicodec which retains a single set of
1364 + * colorspace parameters for both input and output.
1365 + */
1366 + ctx->colorspace = f->fmt.pix_mp.colorspace;
1367 + ctx->xfer_func = f->fmt.pix_mp.xfer_func;
1368 + ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
1369 + ctx->quant = f->fmt.pix_mp.quantization;
1370 +
1371 + /* All parameters should have been set correctly by try_fmt */
1372 + q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
1373 + q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
1374 +
1375 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calulated bpl as %u, size %u\n",
1376 + q_data->bytesperline, q_data->sizeimage);
1377 +
1378 + if (ctx->dev->role == DECODE &&
1379 + q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
1380 + q_data->crop_width && q_data->height) {
1381 + /*
1382 + * On the decoder, if provided with a resolution on the input
1383 + * side, then replicate that to the output side.
1384 + * GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
1385 + * nor set up a resolution on the output side, therefore
1386 + * we can't decode anything at a resolution other than the
1387 + * default one.
1388 + */
1389 + struct bcm2835_codec_q_data *q_data_dst =
1390 + &ctx->q_data[V4L2_M2M_DST];
1391 +
1392 + q_data_dst->crop_width = q_data->crop_width;
1393 + q_data_dst->crop_height = q_data->crop_height;
1394 + q_data_dst->height = ALIGN(q_data->crop_height, 16);
1395 +
1396 + q_data_dst->bytesperline =
1397 + get_bytesperline(f->fmt.pix_mp.width, q_data_dst->fmt);
1398 + q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
1399 + q_data_dst->crop_width,
1400 + q_data_dst->height,
1401 + q_data_dst->fmt);
1402 + update_capture_port = true;
1403 + }
1404 +
1405 + /* If we have a component then setup the port as well */
1406 + port = get_port_data(ctx, vq->type);
1407 + if (!port)
1408 + return 0;
1409 +
1410 + setup_mmal_port_format(ctx, q_data, port);
1411 + ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
1412 + if (ret) {
1413 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
1414 + __func__, ret);
1415 + ret = -EINVAL;
1416 + }
1417 +
1418 + if (q_data->sizeimage < port->minimum_buffer.size) {
1419 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Current buffer size of %u < min buf size %u - driver mismatch to MMAL\n",
1420 + __func__, q_data->sizeimage,
1421 + port->minimum_buffer.size);
1422 + }
1423 +
1424 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
1425 + f->type, q_data->crop_width, q_data->height,
1426 + q_data->fmt->fourcc, q_data->sizeimage);
1427 +
1428 + if (update_capture_port) {
1429 + struct vchiq_mmal_port *port_dst = &ctx->component->output[0];
1430 + struct bcm2835_codec_q_data *q_data_dst =
1431 + &ctx->q_data[V4L2_M2M_DST];
1432 +
1433 + setup_mmal_port_format(ctx, q_data_dst, port_dst);
1434 + ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
1435 + if (ret) {
1436 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
1437 + __func__, ret);
1438 + ret = -EINVAL;
1439 + }
1440 + }
1441 + return ret;
1442 +}
1443 +
1444 +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1445 + struct v4l2_format *f)
1446 +{
1447 + unsigned int height = f->fmt.pix_mp.height;
1448 + int ret;
1449 +
1450 + ret = vidioc_try_fmt_vid_cap(file, priv, f);
1451 + if (ret)
1452 + return ret;
1453 +
1454 + return vidioc_s_fmt(file2ctx(file), f, height);
1455 +}
1456 +
1457 +static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
1458 + struct v4l2_format *f)
1459 +{
1460 + unsigned int height = f->fmt.pix_mp.height;
1461 + int ret;
1462 +
1463 + ret = vidioc_try_fmt_vid_out(file, priv, f);
1464 + if (ret)
1465 + return ret;
1466 +
1467 + ret = vidioc_s_fmt(file2ctx(file), f, height);
1468 + return ret;
1469 +}
1470 +
1471 +static int vidioc_g_selection(struct file *file, void *priv,
1472 + struct v4l2_selection *s)
1473 +{
1474 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1475 + struct bcm2835_codec_q_data *q_data;
1476 +
1477 + /*
1478 + * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
1479 + * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
1480 + * API. The V4L2 core will have converted the MPLANE variants to
1481 + * non-MPLANE.
1482 + * Open code this instead of using get_q_data in this case.
1483 + */
1484 + switch (s->type) {
1485 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1486 + /* CAPTURE on encoder is not valid. */
1487 + if (ctx->dev->role == ENCODE)
1488 + return -EINVAL;
1489 + q_data = &ctx->q_data[V4L2_M2M_DST];
1490 + break;
1491 + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1492 + /* OUTPUT on deoder is not valid. */
1493 + if (ctx->dev->role == DECODE)
1494 + return -EINVAL;
1495 + q_data = &ctx->q_data[V4L2_M2M_SRC];
1496 + break;
1497 + default:
1498 + return -EINVAL;
1499 + }
1500 +
1501 + switch (ctx->dev->role) {
1502 + case DECODE:
1503 + switch (s->target) {
1504 + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1505 + case V4L2_SEL_TGT_COMPOSE:
1506 + s->r.left = 0;
1507 + s->r.top = 0;
1508 + s->r.width = q_data->crop_width;
1509 + s->r.height = q_data->crop_height;
1510 + break;
1511 + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1512 + s->r.left = 0;
1513 + s->r.top = 0;
1514 + s->r.width = q_data->crop_width;
1515 + s->r.height = q_data->crop_height;
1516 + break;
1517 + default:
1518 + return -EINVAL;
1519 + }
1520 + break;
1521 + case ENCODE:
1522 + switch (s->target) {
1523 + case V4L2_SEL_TGT_CROP_DEFAULT:
1524 + case V4L2_SEL_TGT_CROP_BOUNDS:
1525 + s->r.top = 0;
1526 + s->r.left = 0;
1527 + s->r.width = q_data->bytesperline;
1528 + s->r.height = q_data->height;
1529 + break;
1530 + case V4L2_SEL_TGT_CROP:
1531 + s->r.top = 0;
1532 + s->r.left = 0;
1533 + s->r.width = q_data->crop_width;
1534 + s->r.height = q_data->crop_height;
1535 + break;
1536 + default:
1537 + return -EINVAL;
1538 + }
1539 + break;
1540 + case ISP:
1541 + break;
1542 + }
1543 +
1544 + return 0;
1545 +}
1546 +
1547 +static int vidioc_s_selection(struct file *file, void *priv,
1548 + struct v4l2_selection *s)
1549 +{
1550 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1551 + struct bcm2835_codec_q_data *q_data = NULL;
1552 +
1553 + /*
1554 + * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
1555 + * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
1556 + * API. The V4L2 core will have converted the MPLANE variants to
1557 + * non-MPLANE.
1558 + *
1559 + * Open code this instead of using get_q_data in this case.
1560 + */
1561 + switch (s->type) {
1562 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1563 + /* CAPTURE on encoder is not valid. */
1564 + if (ctx->dev->role == ENCODE)
1565 + return -EINVAL;
1566 + q_data = &ctx->q_data[V4L2_M2M_DST];
1567 + break;
1568 + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1569 + /* OUTPUT on deoder is not valid. */
1570 + if (ctx->dev->role == DECODE)
1571 + return -EINVAL;
1572 + q_data = &ctx->q_data[V4L2_M2M_SRC];
1573 + break;
1574 + default:
1575 + return -EINVAL;
1576 + }
1577 +
1578 + 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",
1579 + __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
1580 + s->r.width, s->r.height);
1581 +
1582 + switch (ctx->dev->role) {
1583 + case DECODE:
1584 + switch (s->target) {
1585 + case V4L2_SEL_TGT_COMPOSE:
1586 + /* Accept cropped image */
1587 + s->r.left = 0;
1588 + s->r.top = 0;
1589 + s->r.width = min(s->r.width, q_data->crop_width);
1590 + s->r.height = min(s->r.height, q_data->height);
1591 + q_data->crop_width = s->r.width;
1592 + q_data->crop_height = s->r.height;
1593 + q_data->selection_set = true;
1594 + break;
1595 + default:
1596 + return -EINVAL;
1597 + }
1598 + break;
1599 + case ENCODE:
1600 + switch (s->target) {
1601 + case V4L2_SEL_TGT_CROP:
1602 + /* Only support crop from (0,0) */
1603 + s->r.top = 0;
1604 + s->r.left = 0;
1605 + s->r.width = min(s->r.width, q_data->crop_width);
1606 + s->r.height = min(s->r.height, q_data->crop_height);
1607 + q_data->crop_width = s->r.width;
1608 + q_data->crop_height = s->r.height;
1609 + q_data->selection_set = true;
1610 + break;
1611 + default:
1612 + return -EINVAL;
1613 + }
1614 + break;
1615 + case ISP:
1616 + break;
1617 + }
1618 +
1619 + return 0;
1620 +}
1621 +
1622 +static int vidioc_s_parm(struct file *file, void *priv,
1623 + struct v4l2_streamparm *parm)
1624 +{
1625 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1626 +
1627 + if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1628 + return -EINVAL;
1629 +
1630 + if (!parm->parm.output.timeperframe.denominator ||
1631 + !parm->parm.output.timeperframe.numerator)
1632 + return -EINVAL;
1633 +
1634 + ctx->framerate_num =
1635 + parm->parm.output.timeperframe.denominator;
1636 + ctx->framerate_denom =
1637 + parm->parm.output.timeperframe.numerator;
1638 +
1639 + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
1640 +
1641 + return 0;
1642 +}
1643 +
1644 +static int vidioc_g_parm(struct file *file, void *priv,
1645 + struct v4l2_streamparm *parm)
1646 +{
1647 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1648 +
1649 + if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1650 + return -EINVAL;
1651 +
1652 + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
1653 + parm->parm.output.timeperframe.denominator =
1654 + ctx->framerate_num;
1655 + parm->parm.output.timeperframe.numerator =
1656 + ctx->framerate_denom;
1657 +
1658 + return 0;
1659 +}
1660 +
1661 +static int vidioc_subscribe_evt(struct v4l2_fh *fh,
1662 + const struct v4l2_event_subscription *sub)
1663 +{
1664 + switch (sub->type) {
1665 + case V4L2_EVENT_EOS:
1666 + return v4l2_event_subscribe(fh, sub, 2, NULL);
1667 + case V4L2_EVENT_SOURCE_CHANGE:
1668 + return v4l2_src_change_event_subscribe(fh, sub);
1669 + default:
1670 + return v4l2_ctrl_subscribe_event(fh, sub);
1671 + }
1672 +}
1673 +
1674 +static int bcm2835_codec_set_level_profile(struct bcm2835_codec_ctx *ctx,
1675 + struct v4l2_ctrl *ctrl)
1676 +{
1677 + struct mmal_parameter_video_profile param;
1678 + int param_size = sizeof(param);
1679 + int ret;
1680 +
1681 + /*
1682 + * Level and Profile are set via the same MMAL parameter.
1683 + * Retrieve the current settings and amend the one that has changed.
1684 + */
1685 + ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
1686 + &ctx->component->output[0],
1687 + MMAL_PARAMETER_PROFILE,
1688 + &param,
1689 + &param_size);
1690 + if (ret)
1691 + return ret;
1692 +
1693 + switch (ctrl->id) {
1694 + case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
1695 + switch (ctrl->val) {
1696 + case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
1697 + param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
1698 + break;
1699 + case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
1700 + param.profile =
1701 + MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
1702 + break;
1703 + case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
1704 + param.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
1705 + break;
1706 + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
1707 + param.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
1708 + break;
1709 + default:
1710 + /* Should never get here */
1711 + break;
1712 + }
1713 + break;
1714 +
1715 + case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
1716 + switch (ctrl->val) {
1717 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
1718 + param.level = MMAL_VIDEO_LEVEL_H264_1;
1719 + break;
1720 + case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
1721 + param.level = MMAL_VIDEO_LEVEL_H264_1b;
1722 + break;
1723 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
1724 + param.level = MMAL_VIDEO_LEVEL_H264_11;
1725 + break;
1726 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
1727 + param.level = MMAL_VIDEO_LEVEL_H264_12;
1728 + break;
1729 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
1730 + param.level = MMAL_VIDEO_LEVEL_H264_13;
1731 + break;
1732 + case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
1733 + param.level = MMAL_VIDEO_LEVEL_H264_2;
1734 + break;
1735 + case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
1736 + param.level = MMAL_VIDEO_LEVEL_H264_21;
1737 + break;
1738 + case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
1739 + param.level = MMAL_VIDEO_LEVEL_H264_22;
1740 + break;
1741 + case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
1742 + param.level = MMAL_VIDEO_LEVEL_H264_3;
1743 + break;
1744 + case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
1745 + param.level = MMAL_VIDEO_LEVEL_H264_31;
1746 + break;
1747 + case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
1748 + param.level = MMAL_VIDEO_LEVEL_H264_32;
1749 + break;
1750 + case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
1751 + param.level = MMAL_VIDEO_LEVEL_H264_4;
1752 + break;
1753 + default:
1754 + /* Should never get here */
1755 + break;
1756 + }
1757 + }
1758 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1759 + &ctx->component->output[0],
1760 + MMAL_PARAMETER_PROFILE,
1761 + &param,
1762 + param_size);
1763 +
1764 + return ret;
1765 +}
1766 +
1767 +static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
1768 +{
1769 + struct bcm2835_codec_ctx *ctx =
1770 + container_of(ctrl->handler, struct bcm2835_codec_ctx, hdl);
1771 + int ret = 0;
1772 +
1773 + switch (ctrl->id) {
1774 + case V4L2_CID_MPEG_VIDEO_BITRATE:
1775 + ctx->bitrate = ctrl->val;
1776 + if (!ctx->component)
1777 + break;
1778 +
1779 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1780 + &ctx->component->output[0],
1781 + MMAL_PARAMETER_VIDEO_BIT_RATE,
1782 + &ctrl->val,
1783 + sizeof(ctrl->val));
1784 + break;
1785 +
1786 + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
1787 + u32 bitrate_mode;
1788 +
1789 + if (!ctx->component)
1790 + break;
1791 +
1792 + switch (ctrl->val) {
1793 + default:
1794 + case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
1795 + bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
1796 + break;
1797 + case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
1798 + bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
1799 + break;
1800 + }
1801 +
1802 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1803 + &ctx->component->output[0],
1804 + MMAL_PARAMETER_RATECONTROL,
1805 + &bitrate_mode,
1806 + sizeof(bitrate_mode));
1807 + break;
1808 + }
1809 + case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
1810 + if (!ctx->component)
1811 + break;
1812 +
1813 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1814 + &ctx->component->output[0],
1815 + MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
1816 + &ctrl->val,
1817 + sizeof(ctrl->val));
1818 + break;
1819 +
1820 + case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
1821 + if (!ctx->component)
1822 + break;
1823 +
1824 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1825 + &ctx->component->output[0],
1826 + MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
1827 + &ctrl->val,
1828 + sizeof(ctrl->val));
1829 + break;
1830 +
1831 + case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
1832 + if (!ctx->component)
1833 + break;
1834 +
1835 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1836 + &ctx->component->output[0],
1837 + MMAL_PARAMETER_INTRAPERIOD,
1838 + &ctrl->val,
1839 + sizeof(ctrl->val));
1840 + break;
1841 +
1842 + case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
1843 + case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
1844 + if (!ctx->component)
1845 + break;
1846 +
1847 + ret = bcm2835_codec_set_level_profile(ctx, ctrl);
1848 + break;
1849 +
1850 + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: {
1851 + u32 mmal_bool = 1;
1852 +
1853 + if (!ctx->component)
1854 + break;
1855 +
1856 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
1857 + &ctx->component->output[0],
1858 + MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
1859 + &mmal_bool,
1860 + sizeof(mmal_bool));
1861 + break;
1862 + }
1863 +
1864 + default:
1865 + v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
1866 + return -EINVAL;
1867 + }
1868 +
1869 + if (ret)
1870 + v4l2_err(&ctx->dev->v4l2_dev, "Failed setting ctrl %08x, ret %d\n",
1871 + ctrl->id, ret);
1872 + return ret ? -EINVAL : 0;
1873 +}
1874 +
1875 +static const struct v4l2_ctrl_ops bcm2835_codec_ctrl_ops = {
1876 + .s_ctrl = bcm2835_codec_s_ctrl,
1877 +};
1878 +
1879 +static int vidioc_try_decoder_cmd(struct file *file, void *priv,
1880 + struct v4l2_decoder_cmd *cmd)
1881 +{
1882 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1883 +
1884 + if (ctx->dev->role != DECODE)
1885 + return -EINVAL;
1886 +
1887 + switch (cmd->cmd) {
1888 + case V4L2_DEC_CMD_STOP:
1889 + if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) {
1890 + v4l2_err(&ctx->dev->v4l2_dev, "%s: DEC cmd->flags=%u stop to black not supported",
1891 + __func__, cmd->flags);
1892 + return -EINVAL;
1893 + }
1894 + break;
1895 + case V4L2_DEC_CMD_START:
1896 + break;
1897 + default:
1898 + return -EINVAL;
1899 + }
1900 + return 0;
1901 +}
1902 +
1903 +static int vidioc_decoder_cmd(struct file *file, void *priv,
1904 + struct v4l2_decoder_cmd *cmd)
1905 +{
1906 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1907 + struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
1908 + struct vb2_queue *dst_vq;
1909 + int ret;
1910 +
1911 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
1912 + cmd->cmd);
1913 + ret = vidioc_try_decoder_cmd(file, priv, cmd);
1914 + if (ret)
1915 + return ret;
1916 +
1917 + switch (cmd->cmd) {
1918 + case V4L2_DEC_CMD_STOP:
1919 + if (q_data->eos_buffer_in_use)
1920 + v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
1921 + q_data->eos_buffer_in_use = true;
1922 +
1923 + q_data->eos_buffer.mmal.buffer_size = 0;
1924 + q_data->eos_buffer.mmal.length = 0;
1925 + q_data->eos_buffer.mmal.mmal_flags =
1926 + MMAL_BUFFER_HEADER_FLAG_EOS;
1927 + q_data->eos_buffer.mmal.pts = 0;
1928 + q_data->eos_buffer.mmal.dts = 0;
1929 +
1930 + if (!ctx->component)
1931 + break;
1932 +
1933 + ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
1934 + &ctx->component->input[0],
1935 + &q_data->eos_buffer.mmal);
1936 + if (ret)
1937 + v4l2_err(&ctx->dev->v4l2_dev,
1938 + "%s: EOS buffer submit failed %d\n",
1939 + __func__, ret);
1940 +
1941 + break;
1942 +
1943 + case V4L2_DEC_CMD_START:
1944 + dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1945 + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1946 + vb2_clear_last_buffer_dequeued(dst_vq);
1947 + break;
1948 +
1949 + default:
1950 + return -EINVAL;
1951 + }
1952 +
1953 + return 0;
1954 +}
1955 +
1956 +static int vidioc_try_encoder_cmd(struct file *file, void *priv,
1957 + struct v4l2_encoder_cmd *cmd)
1958 +{
1959 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1960 +
1961 + if (ctx->dev->role != ENCODE)
1962 + return -EINVAL;
1963 +
1964 + switch (cmd->cmd) {
1965 + case V4L2_ENC_CMD_STOP:
1966 + break;
1967 +
1968 + case V4L2_ENC_CMD_START:
1969 + /* Do we need to do anything here? */
1970 + break;
1971 + default:
1972 + return -EINVAL;
1973 + }
1974 + return 0;
1975 +}
1976 +
1977 +static int vidioc_encoder_cmd(struct file *file, void *priv,
1978 + struct v4l2_encoder_cmd *cmd)
1979 +{
1980 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1981 + struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
1982 + int ret;
1983 +
1984 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
1985 + cmd->cmd);
1986 + ret = vidioc_try_encoder_cmd(file, priv, cmd);
1987 + if (ret)
1988 + return ret;
1989 +
1990 + switch (cmd->cmd) {
1991 + case V4L2_ENC_CMD_STOP:
1992 + if (q_data->eos_buffer_in_use)
1993 + v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
1994 + q_data->eos_buffer_in_use = true;
1995 +
1996 + q_data->eos_buffer.mmal.buffer_size = 0;
1997 + q_data->eos_buffer.mmal.length = 0;
1998 + q_data->eos_buffer.mmal.mmal_flags =
1999 + MMAL_BUFFER_HEADER_FLAG_EOS;
2000 + q_data->eos_buffer.mmal.pts = 0;
2001 + q_data->eos_buffer.mmal.dts = 0;
2002 +
2003 + if (!ctx->component)
2004 + break;
2005 +
2006 + ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
2007 + &ctx->component->input[0],
2008 + &q_data->eos_buffer.mmal);
2009 + if (ret)
2010 + v4l2_err(&ctx->dev->v4l2_dev,
2011 + "%s: EOS buffer submit failed %d\n",
2012 + __func__, ret);
2013 +
2014 + break;
2015 + case V4L2_ENC_CMD_START:
2016 + /* Do we need to do anything here? */
2017 + break;
2018 +
2019 + default:
2020 + return -EINVAL;
2021 + }
2022 +
2023 + return 0;
2024 +}
2025 +
2026 +static int vidioc_enum_framesizes(struct file *file, void *fh,
2027 + struct v4l2_frmsizeenum *fsize)
2028 +{
2029 + struct bcm2835_codec_fmt *fmt;
2030 +
2031 + fmt = find_format_pix_fmt(fsize->pixel_format, file2ctx(file)->dev,
2032 + true);
2033 + if (!fmt)
2034 + fmt = find_format_pix_fmt(fsize->pixel_format,
2035 + file2ctx(file)->dev,
2036 + false);
2037 +
2038 + if (!fmt)
2039 + return -EINVAL;
2040 +
2041 + if (fsize->index)
2042 + return -EINVAL;
2043 +
2044 + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
2045 +
2046 + fsize->stepwise.min_width = MIN_W;
2047 + fsize->stepwise.max_width = MAX_W;
2048 + fsize->stepwise.step_width = 1;
2049 + fsize->stepwise.min_height = MIN_H;
2050 + fsize->stepwise.max_height = MAX_H;
2051 + fsize->stepwise.step_height = 1;
2052 +
2053 + return 0;
2054 +}
2055 +
2056 +static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
2057 + .vidioc_querycap = vidioc_querycap,
2058 +
2059 + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
2060 + .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap,
2061 + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
2062 + .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
2063 +
2064 + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
2065 + .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
2066 + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
2067 + .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
2068 +
2069 + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
2070 + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
2071 + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
2072 + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
2073 + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
2074 + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
2075 + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
2076 +
2077 + .vidioc_streamon = v4l2_m2m_ioctl_streamon,
2078 + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
2079 +
2080 + .vidioc_g_selection = vidioc_g_selection,
2081 + .vidioc_s_selection = vidioc_s_selection,
2082 +
2083 + .vidioc_g_parm = vidioc_g_parm,
2084 + .vidioc_s_parm = vidioc_s_parm,
2085 +
2086 + .vidioc_subscribe_event = vidioc_subscribe_evt,
2087 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
2088 +
2089 + .vidioc_decoder_cmd = vidioc_decoder_cmd,
2090 + .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
2091 + .vidioc_encoder_cmd = vidioc_encoder_cmd,
2092 + .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
2093 + .vidioc_enum_framesizes = vidioc_enum_framesizes,
2094 +};
2095 +
2096 +static int bcm2835_codec_set_ctrls(struct bcm2835_codec_ctx *ctx)
2097 +{
2098 + /*
2099 + * Query the control handler for the value of the various controls and
2100 + * set them.
2101 + */
2102 + const u32 control_ids[] = {
2103 + V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
2104 + V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
2105 + V4L2_CID_MPEG_VIDEO_HEADER_MODE,
2106 + V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
2107 + V4L2_CID_MPEG_VIDEO_H264_LEVEL,
2108 + V4L2_CID_MPEG_VIDEO_H264_PROFILE,
2109 + };
2110 + int i;
2111 +
2112 + for (i = 0; i < ARRAY_SIZE(control_ids); i++) {
2113 + struct v4l2_ctrl *ctrl;
2114 +
2115 + ctrl = v4l2_ctrl_find(&ctx->hdl, control_ids[i]);
2116 + if (ctrl)
2117 + bcm2835_codec_s_ctrl(ctrl);
2118 + }
2119 +
2120 + return 0;
2121 +}
2122 +
2123 +static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
2124 +{
2125 + struct bcm2835_codec_dev *dev = ctx->dev;
2126 + unsigned int enable = 1;
2127 + int ret;
2128 +
2129 + ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
2130 + &ctx->component);
2131 + if (ret < 0) {
2132 + v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
2133 + __func__, components[dev->role]);
2134 + return -ENOMEM;
2135 + }
2136 +
2137 + vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->input[0],
2138 + MMAL_PARAMETER_ZERO_COPY, &enable,
2139 + sizeof(enable));
2140 + vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->output[0],
2141 + MMAL_PARAMETER_ZERO_COPY, &enable,
2142 + sizeof(enable));
2143 +
2144 + if (dev->role == DECODE) {
2145 + /*
2146 + * Disable firmware option that ensures decoded timestamps
2147 + * always increase.
2148 + */
2149 + enable = 0;
2150 + vchiq_mmal_port_parameter_set(dev->instance,
2151 + &ctx->component->output[0],
2152 + MMAL_PARAMETER_VIDEO_VALIDATE_TIMESTAMPS,
2153 + &enable,
2154 + sizeof(enable));
2155 + }
2156 +
2157 + setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
2158 + &ctx->component->input[0]);
2159 +
2160 + setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
2161 + &ctx->component->output[0]);
2162 +
2163 + ret = vchiq_mmal_port_set_format(dev->instance,
2164 + &ctx->component->input[0]);
2165 + if (ret < 0) {
2166 + v4l2_dbg(1, debug, &dev->v4l2_dev,
2167 + "%s: vchiq_mmal_port_set_format ip port failed\n",
2168 + __func__);
2169 + goto destroy_component;
2170 + }
2171 +
2172 + ret = vchiq_mmal_port_set_format(dev->instance,
2173 + &ctx->component->output[0]);
2174 + if (ret < 0) {
2175 + v4l2_dbg(1, debug, &dev->v4l2_dev,
2176 + "%s: vchiq_mmal_port_set_format op port failed\n",
2177 + __func__);
2178 + goto destroy_component;
2179 + }
2180 +
2181 + if (dev->role == ENCODE) {
2182 + u32 param = 1;
2183 +
2184 + if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
2185 + ctx->component->output[0].minimum_buffer.size)
2186 + v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
2187 + ctx->q_data[V4L2_M2M_SRC].sizeimage,
2188 + ctx->component->output[0].minimum_buffer.size);
2189 +
2190 + /* Now we have a component we can set all the ctrls */
2191 + bcm2835_codec_set_ctrls(ctx);
2192 +
2193 + /* Enable SPS Timing header so framerate information is encoded
2194 + * in the H264 header.
2195 + */
2196 + vchiq_mmal_port_parameter_set(ctx->dev->instance,
2197 + &ctx->component->output[0],
2198 + MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
2199 + &param, sizeof(param));
2200 +
2201 + /* Enable inserting headers into the first frame */
2202 + vchiq_mmal_port_parameter_set(ctx->dev->instance,
2203 + &ctx->component->control,
2204 + MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
2205 + &param, sizeof(param));
2206 + /*
2207 + * Avoid fragmenting the buffers over multiple frames (unless
2208 + * the frame is bigger than the whole buffer)
2209 + */
2210 + vchiq_mmal_port_parameter_set(ctx->dev->instance,
2211 + &ctx->component->control,
2212 + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
2213 + &param, sizeof(param));
2214 + } else {
2215 + if (ctx->q_data[V4L2_M2M_DST].sizeimage <
2216 + ctx->component->output[0].minimum_buffer.size)
2217 + v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
2218 + ctx->q_data[V4L2_M2M_DST].sizeimage,
2219 + ctx->component->output[0].minimum_buffer.size);
2220 + }
2221 + v4l2_dbg(2, debug, &dev->v4l2_dev, "%s: component created as %s\n",
2222 + __func__, components[dev->role]);
2223 +
2224 + return 0;
2225 +
2226 +destroy_component:
2227 + vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
2228 + ctx->component = NULL;
2229 +
2230 + return ret;
2231 +}
2232 +
2233 +/*
2234 + * Queue operations
2235 + */
2236 +
2237 +static int bcm2835_codec_queue_setup(struct vb2_queue *vq,
2238 + unsigned int *nbuffers,
2239 + unsigned int *nplanes,
2240 + unsigned int sizes[],
2241 + struct device *alloc_devs[])
2242 +{
2243 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vq);
2244 + struct bcm2835_codec_q_data *q_data;
2245 + struct vchiq_mmal_port *port;
2246 + unsigned int size;
2247 +
2248 + q_data = get_q_data(ctx, vq->type);
2249 + if (!q_data)
2250 + return -EINVAL;
2251 +
2252 + if (!ctx->component)
2253 + if (bcm2835_codec_create_component(ctx))
2254 + return -EINVAL;
2255 +
2256 + port = get_port_data(ctx, vq->type);
2257 +
2258 + size = q_data->sizeimage;
2259 +
2260 + if (*nplanes)
2261 + return sizes[0] < size ? -EINVAL : 0;
2262 +
2263 + *nplanes = 1;
2264 +
2265 + sizes[0] = size;
2266 + port->current_buffer.size = size;
2267 +
2268 + if (*nbuffers < port->minimum_buffer.num)
2269 + *nbuffers = port->minimum_buffer.num;
2270 + /* Add one buffer to take an EOS */
2271 + port->current_buffer.num = *nbuffers + 1;
2272 +
2273 + return 0;
2274 +}
2275 +
2276 +static int bcm2835_codec_mmal_buf_cleanup(struct mmal_buffer *mmal_buf)
2277 +{
2278 + mmal_vchi_buffer_cleanup(mmal_buf);
2279 +
2280 + if (mmal_buf->dma_buf) {
2281 + dma_buf_put(mmal_buf->dma_buf);
2282 + mmal_buf->dma_buf = NULL;
2283 + }
2284 +
2285 + return 0;
2286 +}
2287 +
2288 +static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
2289 +{
2290 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2291 + struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
2292 + struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
2293 + vb);
2294 + struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
2295 + m2m);
2296 +
2297 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
2298 + __func__, ctx, vb);
2299 + buf->mmal.buffer = vb2_plane_vaddr(&buf->m2m.vb.vb2_buf, 0);
2300 + buf->mmal.buffer_size = vb2_plane_size(&buf->m2m.vb.vb2_buf, 0);
2301 +
2302 + mmal_vchi_buffer_init(ctx->dev->instance, &buf->mmal);
2303 +
2304 + return 0;
2305 +}
2306 +
2307 +static int bcm2835_codec_buf_prepare(struct vb2_buffer *vb)
2308 +{
2309 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2310 + struct bcm2835_codec_q_data *q_data;
2311 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
2312 + struct v4l2_m2m_buffer *m2m = container_of(vbuf, struct v4l2_m2m_buffer,
2313 + vb);
2314 + struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
2315 + m2m);
2316 + struct dma_buf *dma_buf;
2317 + int ret;
2318 +
2319 + v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
2320 + __func__, vb->vb2_queue->type, vb);
2321 +
2322 + q_data = get_q_data(ctx, vb->vb2_queue->type);
2323 + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
2324 + if (vbuf->field == V4L2_FIELD_ANY)
2325 + vbuf->field = V4L2_FIELD_NONE;
2326 + if (vbuf->field != V4L2_FIELD_NONE) {
2327 + v4l2_err(&ctx->dev->v4l2_dev, "%s field isn't supported\n",
2328 + __func__);
2329 + return -EINVAL;
2330 + }
2331 + }
2332 +
2333 + if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
2334 + v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
2335 + __func__, vb2_plane_size(vb, 0),
2336 + (long)q_data->sizeimage);
2337 + return -EINVAL;
2338 + }
2339 +
2340 + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
2341 + vb2_set_plane_payload(vb, 0, q_data->sizeimage);
2342 +
2343 + switch (vb->memory) {
2344 + case VB2_MEMORY_DMABUF:
2345 + dma_buf = dma_buf_get(vb->planes[0].m.fd);
2346 +
2347 + if (dma_buf != buf->mmal.dma_buf) {
2348 + /* dmabuf either hasn't already been mapped, or it has
2349 + * changed.
2350 + */
2351 + if (buf->mmal.dma_buf) {
2352 + v4l2_err(&ctx->dev->v4l2_dev,
2353 + "%s Buffer changed - why did the core not call cleanup?\n",
2354 + __func__);
2355 + bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
2356 + }
2357 +
2358 + buf->mmal.dma_buf = dma_buf;
2359 + } else {
2360 + /* We already have a reference count on the dmabuf, so
2361 + * release the one we acquired above.
2362 + */
2363 + dma_buf_put(dma_buf);
2364 + }
2365 + ret = 0;
2366 + break;
2367 + case VB2_MEMORY_MMAP:
2368 + /*
2369 + * We want to do this at init, but vb2_core_expbuf checks that
2370 + * the index < q->num_buffers, and q->num_buffers only gets
2371 + * updated once all the buffers are allocated.
2372 + */
2373 + if (!buf->mmal.dma_buf) {
2374 + ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
2375 + vb->vb2_queue->type,
2376 + vb->index, 0,
2377 + O_CLOEXEC,
2378 + &buf->mmal.dma_buf);
2379 + if (ret)
2380 + v4l2_err(&ctx->dev->v4l2_dev,
2381 + "%s: Failed to expbuf idx %d, ret %d\n",
2382 + __func__, vb->index, ret);
2383 + } else {
2384 + ret = 0;
2385 + }
2386 + break;
2387 + default:
2388 + ret = -EINVAL;
2389 + break;
2390 + }
2391 +
2392 + return ret;
2393 +}
2394 +
2395 +static void bcm2835_codec_buf_queue(struct vb2_buffer *vb)
2396 +{
2397 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
2398 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2399 +
2400 + v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p vbuf->flags %u, seq %u, bytesused %u\n",
2401 + __func__, vb->vb2_queue->type, vb, vbuf->flags, vbuf->sequence,
2402 + vb->planes[0].bytesused);
2403 + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
2404 +}
2405 +
2406 +static void bcm2835_codec_buffer_cleanup(struct vb2_buffer *vb)
2407 +{
2408 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
2409 + struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
2410 + struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
2411 + vb);
2412 + struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
2413 + m2m);
2414 +
2415 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
2416 + __func__, ctx, vb);
2417 +
2418 + bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
2419 +}
2420 +
2421 +static int bcm2835_codec_start_streaming(struct vb2_queue *q,
2422 + unsigned int count)
2423 +{
2424 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
2425 + struct bcm2835_codec_dev *dev = ctx->dev;
2426 + struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
2427 + struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
2428 + int ret;
2429 +
2430 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
2431 + __func__, q->type, count);
2432 + q_data->sequence = 0;
2433 +
2434 + if (!ctx->component_enabled) {
2435 + ret = vchiq_mmal_component_enable(dev->instance,
2436 + ctx->component);
2437 + if (ret)
2438 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
2439 + __func__, ret);
2440 + ctx->component_enabled = true;
2441 + }
2442 +
2443 + if (count < port->minimum_buffer.num)
2444 + count = port->minimum_buffer.num;
2445 +
2446 + if (port->current_buffer.num < count + 1) {
2447 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, buffer count changed %u to %u\n",
2448 + __func__, ctx, port->current_buffer.num, count + 1);
2449 +
2450 + port->current_buffer.num = count + 1;
2451 + ret = vchiq_mmal_port_set_format(dev->instance, port);
2452 + if (ret)
2453 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error updating buffer count, ret %d\n",
2454 + __func__, ret);
2455 + }
2456 +
2457 + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2458 + /*
2459 + * Create the EOS buffer.
2460 + * We only need the MMAL part, and want to NOT attach a memory
2461 + * buffer to it as it should only take flags.
2462 + */
2463 + memset(&q_data->eos_buffer, 0, sizeof(q_data->eos_buffer));
2464 + mmal_vchi_buffer_init(dev->instance,
2465 + &q_data->eos_buffer.mmal);
2466 + q_data->eos_buffer_in_use = false;
2467 +
2468 + port->cb_ctx = ctx;
2469 + ret = vchiq_mmal_port_enable(dev->instance,
2470 + port,
2471 + ip_buffer_cb);
2472 + if (ret)
2473 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
2474 + __func__, ret);
2475 + } else {
2476 + port->cb_ctx = ctx;
2477 + ret = vchiq_mmal_port_enable(dev->instance,
2478 + port,
2479 + op_buffer_cb);
2480 + if (ret)
2481 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
2482 + __func__, ret);
2483 + }
2484 + return ret;
2485 +}
2486 +
2487 +static void bcm2835_codec_stop_streaming(struct vb2_queue *q)
2488 +{
2489 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
2490 + struct bcm2835_codec_dev *dev = ctx->dev;
2491 + struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
2492 + struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
2493 + struct vb2_v4l2_buffer *vbuf;
2494 + int ret;
2495 +
2496 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
2497 + __func__, q->type);
2498 +
2499 + init_completion(&ctx->frame_cmplt);
2500 +
2501 + /* Clear out all buffers held by m2m framework */
2502 + for (;;) {
2503 + if (V4L2_TYPE_IS_OUTPUT(q->type))
2504 + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
2505 + else
2506 + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
2507 + if (!vbuf)
2508 + break;
2509 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: return buffer %p\n",
2510 + __func__, vbuf);
2511 +
2512 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
2513 + }
2514 +
2515 + /* Disable MMAL port - this will flush buffers back */
2516 + ret = vchiq_mmal_port_disable(dev->instance, port);
2517 + if (ret)
2518 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed disabling %s port, ret %d\n",
2519 + __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
2520 + ret);
2521 +
2522 + while (atomic_read(&port->buffers_with_vpu)) {
2523 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
2524 + __func__, atomic_read(&port->buffers_with_vpu));
2525 + ret = wait_for_completion_timeout(&ctx->frame_cmplt,
2526 + COMPLETE_TIMEOUT);
2527 + if (ret <= 0) {
2528 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
2529 + __func__,
2530 + atomic_read(&port->buffers_with_vpu));
2531 + break;
2532 + }
2533 + }
2534 +
2535 + /* If both ports disabled, then disable the component */
2536 + if (ctx->component_enabled &&
2537 + !ctx->component->input[0].enabled &&
2538 + !ctx->component->output[0].enabled) {
2539 + ret = vchiq_mmal_component_disable(dev->instance,
2540 + ctx->component);
2541 + if (ret)
2542 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
2543 + __func__, ret);
2544 + ctx->component_enabled = false;
2545 + }
2546 +
2547 + if (V4L2_TYPE_IS_OUTPUT(q->type))
2548 + mmal_vchi_buffer_cleanup(&q_data->eos_buffer.mmal);
2549 +
2550 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: done\n", __func__);
2551 +}
2552 +
2553 +static const struct vb2_ops bcm2835_codec_qops = {
2554 + .queue_setup = bcm2835_codec_queue_setup,
2555 + .buf_init = bcm2835_codec_buf_init,
2556 + .buf_prepare = bcm2835_codec_buf_prepare,
2557 + .buf_queue = bcm2835_codec_buf_queue,
2558 + .buf_cleanup = bcm2835_codec_buffer_cleanup,
2559 + .start_streaming = bcm2835_codec_start_streaming,
2560 + .stop_streaming = bcm2835_codec_stop_streaming,
2561 + .wait_prepare = vb2_ops_wait_prepare,
2562 + .wait_finish = vb2_ops_wait_finish,
2563 +};
2564 +
2565 +static int queue_init(void *priv, struct vb2_queue *src_vq,
2566 + struct vb2_queue *dst_vq)
2567 +{
2568 + struct bcm2835_codec_ctx *ctx = priv;
2569 + int ret;
2570 +
2571 + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2572 + src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
2573 + src_vq->drv_priv = ctx;
2574 + src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
2575 + src_vq->ops = &bcm2835_codec_qops;
2576 + src_vq->mem_ops = &vb2_dma_contig_memops;
2577 + src_vq->dev = &ctx->dev->pdev->dev;
2578 + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
2579 + src_vq->lock = &ctx->dev->dev_mutex;
2580 +
2581 + ret = vb2_queue_init(src_vq);
2582 + if (ret)
2583 + return ret;
2584 +
2585 + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
2586 + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
2587 + dst_vq->drv_priv = ctx;
2588 + dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
2589 + dst_vq->ops = &bcm2835_codec_qops;
2590 + dst_vq->mem_ops = &vb2_dma_contig_memops;
2591 + dst_vq->dev = &ctx->dev->pdev->dev;
2592 + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
2593 + dst_vq->lock = &ctx->dev->dev_mutex;
2594 +
2595 + return vb2_queue_init(dst_vq);
2596 +}
2597 +
2598 +/*
2599 + * File operations
2600 + */
2601 +static int bcm2835_codec_open(struct file *file)
2602 +{
2603 + struct bcm2835_codec_dev *dev = video_drvdata(file);
2604 + struct bcm2835_codec_ctx *ctx = NULL;
2605 + struct v4l2_ctrl_handler *hdl;
2606 + int rc = 0;
2607 +
2608 + if (mutex_lock_interruptible(&dev->dev_mutex)) {
2609 + v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
2610 + return -ERESTARTSYS;
2611 + }
2612 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
2613 + if (!ctx) {
2614 + rc = -ENOMEM;
2615 + goto open_unlock;
2616 + }
2617 +
2618 + ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
2619 + ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
2620 +
2621 + ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
2622 + ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
2623 + ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
2624 + ctx->q_data[V4L2_M2M_SRC].bytesperline =
2625 + get_bytesperline(DEFAULT_WIDTH,
2626 + ctx->q_data[V4L2_M2M_SRC].fmt);
2627 + ctx->q_data[V4L2_M2M_SRC].sizeimage =
2628 + get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
2629 + ctx->q_data[V4L2_M2M_SRC].crop_width,
2630 + ctx->q_data[V4L2_M2M_SRC].height,
2631 + ctx->q_data[V4L2_M2M_SRC].fmt);
2632 +
2633 + ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
2634 + ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
2635 + ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
2636 + ctx->q_data[V4L2_M2M_DST].bytesperline =
2637 + get_bytesperline(DEFAULT_WIDTH,
2638 + ctx->q_data[V4L2_M2M_DST].fmt);
2639 + ctx->q_data[V4L2_M2M_DST].sizeimage =
2640 + get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
2641 + ctx->q_data[V4L2_M2M_DST].crop_width,
2642 + ctx->q_data[V4L2_M2M_DST].height,
2643 + ctx->q_data[V4L2_M2M_DST].fmt);
2644 +
2645 + ctx->colorspace = V4L2_COLORSPACE_REC709;
2646 + ctx->bitrate = 10 * 1000 * 1000;
2647 +
2648 + ctx->framerate_num = 30;
2649 + ctx->framerate_denom = 1;
2650 +
2651 + /* Initialise V4L2 contexts */
2652 + v4l2_fh_init(&ctx->fh, video_devdata(file));
2653 + file->private_data = &ctx->fh;
2654 + ctx->dev = dev;
2655 + hdl = &ctx->hdl;
2656 + if (dev->role == ENCODE) {
2657 + /* Encode controls */
2658 + v4l2_ctrl_handler_init(hdl, 9);
2659 +
2660 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
2661 + V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
2662 + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
2663 + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
2664 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
2665 + V4L2_CID_MPEG_VIDEO_BITRATE,
2666 + 25 * 1000, 25 * 1000 * 1000,
2667 + 25 * 1000, 10 * 1000 * 1000);
2668 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
2669 + V4L2_CID_MPEG_VIDEO_HEADER_MODE,
2670 + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
2671 + 0, V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
2672 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
2673 + V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
2674 + 0, 1,
2675 + 1, 0);
2676 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
2677 + V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
2678 + 0, 0x7FFFFFFF,
2679 + 1, 60);
2680 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
2681 + V4L2_CID_MPEG_VIDEO_H264_LEVEL,
2682 + V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
2683 + ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
2684 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
2685 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
2686 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
2687 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
2688 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
2689 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
2690 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
2691 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
2692 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
2693 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
2694 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
2695 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
2696 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
2697 + V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
2698 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
2699 + V4L2_CID_MPEG_VIDEO_H264_PROFILE,
2700 + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
2701 + ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
2702 + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
2703 + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
2704 + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
2705 + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
2706 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
2707 + V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
2708 + 0, 0, 0, 0);
2709 + if (hdl->error) {
2710 + rc = hdl->error;
2711 + goto free_ctrl_handler;
2712 + }
2713 + ctx->fh.ctrl_handler = hdl;
2714 + v4l2_ctrl_handler_setup(hdl);
2715 + } else if (dev->role == DECODE) {
2716 + v4l2_ctrl_handler_init(hdl, 1);
2717 +
2718 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
2719 + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
2720 + 1, 1, 1, 1);
2721 + if (hdl->error) {
2722 + rc = hdl->error;
2723 + goto free_ctrl_handler;
2724 + }
2725 + ctx->fh.ctrl_handler = hdl;
2726 + v4l2_ctrl_handler_setup(hdl);
2727 + }
2728 +
2729 + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
2730 +
2731 + if (IS_ERR(ctx->fh.m2m_ctx)) {
2732 + rc = PTR_ERR(ctx->fh.m2m_ctx);
2733 +
2734 + goto free_ctrl_handler;
2735 + }
2736 +
2737 + /* Set both queues as buffered as we have buffering in the VPU. That
2738 + * means that we will be scheduled whenever either an input or output
2739 + * buffer is available (otherwise one of each are required).
2740 + */
2741 + v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
2742 + v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
2743 +
2744 + v4l2_fh_add(&ctx->fh);
2745 + atomic_inc(&dev->num_inst);
2746 +
2747 + mutex_unlock(&dev->dev_mutex);
2748 + return 0;
2749 +
2750 +free_ctrl_handler:
2751 + v4l2_ctrl_handler_free(hdl);
2752 + kfree(ctx);
2753 +open_unlock:
2754 + mutex_unlock(&dev->dev_mutex);
2755 + return rc;
2756 +}
2757 +
2758 +static int bcm2835_codec_release(struct file *file)
2759 +{
2760 + struct bcm2835_codec_dev *dev = video_drvdata(file);
2761 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2762 +
2763 + v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: Releasing instance %p\n",
2764 + __func__, ctx);
2765 +
2766 + v4l2_fh_del(&ctx->fh);
2767 + v4l2_fh_exit(&ctx->fh);
2768 + v4l2_ctrl_handler_free(&ctx->hdl);
2769 + mutex_lock(&dev->dev_mutex);
2770 + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
2771 +
2772 + if (ctx->component)
2773 + vchiq_mmal_component_finalise(dev->instance, ctx->component);
2774 +
2775 + mutex_unlock(&dev->dev_mutex);
2776 + kfree(ctx);
2777 +
2778 + atomic_dec(&dev->num_inst);
2779 +
2780 + return 0;
2781 +}
2782 +
2783 +static const struct v4l2_file_operations bcm2835_codec_fops = {
2784 + .owner = THIS_MODULE,
2785 + .open = bcm2835_codec_open,
2786 + .release = bcm2835_codec_release,
2787 + .poll = v4l2_m2m_fop_poll,
2788 + .unlocked_ioctl = video_ioctl2,
2789 + .mmap = v4l2_m2m_fop_mmap,
2790 +};
2791 +
2792 +static const struct video_device bcm2835_codec_videodev = {
2793 + .name = MEM2MEM_NAME,
2794 + .vfl_dir = VFL_DIR_M2M,
2795 + .fops = &bcm2835_codec_fops,
2796 + .ioctl_ops = &bcm2835_codec_ioctl_ops,
2797 + .minor = -1,
2798 + .release = video_device_release_empty,
2799 +};
2800 +
2801 +static const struct v4l2_m2m_ops m2m_ops = {
2802 + .device_run = device_run,
2803 + .job_ready = job_ready,
2804 + .job_abort = job_abort,
2805 +};
2806 +
2807 +/* Size of the array to provide to the VPU when asking for the list of supported
2808 + * formats.
2809 + * The ISP component currently advertises 44 input formats, so add a small
2810 + * overhead on that.
2811 + */
2812 +#define MAX_SUPPORTED_ENCODINGS 50
2813 +
2814 +/* Populate dev->supported_fmts with the formats supported by those ports. */
2815 +static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
2816 +{
2817 + struct bcm2835_codec_fmt *list;
2818 + struct vchiq_mmal_component *component;
2819 + u32 fourccs[MAX_SUPPORTED_ENCODINGS];
2820 + u32 param_size = sizeof(fourccs);
2821 + unsigned int i, j, num_encodings;
2822 + int ret;
2823 +
2824 + ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
2825 + &component);
2826 + if (ret < 0) {
2827 + v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
2828 + __func__, components[dev->role]);
2829 + return -ENOMEM;
2830 + }
2831 +
2832 + ret = vchiq_mmal_port_parameter_get(dev->instance,
2833 + &component->input[0],
2834 + MMAL_PARAMETER_SUPPORTED_ENCODINGS,
2835 + &fourccs,
2836 + &param_size);
2837 +
2838 + if (ret) {
2839 + if (ret == MMAL_MSG_STATUS_ENOSPC) {
2840 + v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
2841 + __func__);
2842 + num_encodings = MAX_SUPPORTED_ENCODINGS;
2843 + } else {
2844 + v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
2845 + __func__, ret);
2846 + ret = -EINVAL;
2847 + goto destroy_component;
2848 + }
2849 + } else {
2850 + num_encodings = param_size / sizeof(u32);
2851 + }
2852 +
2853 + /* Assume at this stage that all encodings will be supported in V4L2.
2854 + * Any that aren't supported will waste a very small amount of memory.
2855 + */
2856 + list = devm_kzalloc(&dev->pdev->dev,
2857 + sizeof(struct bcm2835_codec_fmt) * num_encodings,
2858 + GFP_KERNEL);
2859 + if (!list) {
2860 + ret = -ENOMEM;
2861 + goto destroy_component;
2862 + }
2863 + dev->supported_fmts[0].list = list;
2864 +
2865 + for (i = 0, j = 0; i < num_encodings; i++) {
2866 + const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
2867 +
2868 + if (fmt) {
2869 + list[j] = *fmt;
2870 + j++;
2871 + }
2872 + }
2873 + dev->supported_fmts[0].num_entries = j;
2874 +
2875 + param_size = sizeof(fourccs);
2876 + ret = vchiq_mmal_port_parameter_get(dev->instance,
2877 + &component->output[0],
2878 + MMAL_PARAMETER_SUPPORTED_ENCODINGS,
2879 + &fourccs,
2880 + &param_size);
2881 +
2882 + if (ret) {
2883 + if (ret == MMAL_MSG_STATUS_ENOSPC) {
2884 + v4l2_err(&dev->v4l2_dev, "%s: port has more encoding than we provided space for. Some are dropped.\n",
2885 + __func__);
2886 + num_encodings = MAX_SUPPORTED_ENCODINGS;
2887 + } else {
2888 + ret = -EINVAL;
2889 + goto destroy_component;
2890 + }
2891 + } else {
2892 + num_encodings = param_size / sizeof(u32);
2893 + }
2894 + /* Assume at this stage that all encodings will be supported in V4L2. */
2895 + list = devm_kzalloc(&dev->pdev->dev,
2896 + sizeof(struct bcm2835_codec_fmt) * num_encodings,
2897 + GFP_KERNEL);
2898 + if (!list) {
2899 + ret = -ENOMEM;
2900 + goto destroy_component;
2901 + }
2902 + dev->supported_fmts[1].list = list;
2903 +
2904 + for (i = 0, j = 0; i < num_encodings; i++) {
2905 + const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
2906 +
2907 + if (fmt) {
2908 + list[j] = *fmt;
2909 + j++;
2910 + }
2911 + }
2912 + dev->supported_fmts[1].num_entries = j;
2913 +
2914 + ret = 0;
2915 +
2916 +destroy_component:
2917 + vchiq_mmal_component_finalise(dev->instance, component);
2918 +
2919 + return ret;
2920 +}
2921 +
2922 +static int bcm2835_codec_create(struct bcm2835_codec_driver *drv,
2923 + struct bcm2835_codec_dev **new_dev,
2924 + enum bcm2835_codec_role role)
2925 +{
2926 + struct platform_device *pdev = drv->pdev;
2927 + struct bcm2835_codec_dev *dev;
2928 + struct video_device *vfd;
2929 + int function;
2930 + int video_nr;
2931 + int ret;
2932 +
2933 + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
2934 + if (!dev)
2935 + return -ENOMEM;
2936 +
2937 + dev->pdev = pdev;
2938 +
2939 + dev->role = role;
2940 +
2941 + ret = vchiq_mmal_init(&dev->instance);
2942 + if (ret)
2943 + return ret;
2944 +
2945 + ret = bcm2835_codec_get_supported_fmts(dev);
2946 + if (ret)
2947 + goto vchiq_finalise;
2948 +
2949 + atomic_set(&dev->num_inst, 0);
2950 + mutex_init(&dev->dev_mutex);
2951 +
2952 + /* Initialise the video device */
2953 + dev->vfd = bcm2835_codec_videodev;
2954 +
2955 + vfd = &dev->vfd;
2956 + vfd->lock = &dev->dev_mutex;
2957 + vfd->v4l2_dev = &dev->v4l2_dev;
2958 + vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
2959 + vfd->v4l2_dev->mdev = &drv->mdev;
2960 +
2961 + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
2962 + if (ret)
2963 + goto vchiq_finalise;
2964 +
2965 + switch (role) {
2966 + case DECODE:
2967 + v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
2968 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
2969 + v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
2970 + v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
2971 + function = MEDIA_ENT_F_PROC_VIDEO_DECODER;
2972 + video_nr = decode_video_nr;
2973 + break;
2974 + case ENCODE:
2975 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
2976 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
2977 + function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
2978 + video_nr = encode_video_nr;
2979 + break;
2980 + case ISP:
2981 + v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
2982 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
2983 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
2984 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
2985 + v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
2986 + v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
2987 + function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
2988 + video_nr = isp_video_nr;
2989 + break;
2990 + default:
2991 + ret = -EINVAL;
2992 + goto unreg_dev;
2993 + }
2994 +
2995 + ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
2996 + if (ret) {
2997 + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
2998 + goto unreg_dev;
2999 + }
3000 +
3001 + video_set_drvdata(vfd, dev);
3002 + snprintf(vfd->name, sizeof(vfd->name), "%s-%s",
3003 + bcm2835_codec_videodev.name, roles[role]);
3004 + v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
3005 + vfd->num);
3006 +
3007 + *new_dev = dev;
3008 +
3009 + dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
3010 + if (IS_ERR(dev->m2m_dev)) {
3011 + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
3012 + ret = PTR_ERR(dev->m2m_dev);
3013 + goto err_m2m;
3014 + }
3015 +
3016 + ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, function);
3017 + if (ret)
3018 + goto err_m2m;
3019 +
3020 + v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
3021 + roles[role]);
3022 + return 0;
3023 +
3024 +err_m2m:
3025 + v4l2_m2m_release(dev->m2m_dev);
3026 + video_unregister_device(&dev->vfd);
3027 +unreg_dev:
3028 + v4l2_device_unregister(&dev->v4l2_dev);
3029 +vchiq_finalise:
3030 + vchiq_mmal_finalise(dev->instance);
3031 + return ret;
3032 +}
3033 +
3034 +static int bcm2835_codec_destroy(struct bcm2835_codec_dev *dev)
3035 +{
3036 + if (!dev)
3037 + return -ENODEV;
3038 +
3039 + v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
3040 + roles[dev->role]);
3041 + v4l2_m2m_unregister_media_controller(dev->m2m_dev);
3042 + v4l2_m2m_release(dev->m2m_dev);
3043 + video_unregister_device(&dev->vfd);
3044 + v4l2_device_unregister(&dev->v4l2_dev);
3045 + vchiq_mmal_finalise(dev->instance);
3046 +
3047 + return 0;
3048 +}
3049 +
3050 +static int bcm2835_codec_probe(struct platform_device *pdev)
3051 +{
3052 + struct bcm2835_codec_driver *drv;
3053 + struct media_device *mdev;
3054 + int ret = 0;
3055 +
3056 + drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
3057 + if (!drv)
3058 + return -ENOMEM;
3059 +
3060 + drv->pdev = pdev;
3061 + mdev = &drv->mdev;
3062 + mdev->dev = &pdev->dev;
3063 +
3064 + strscpy(mdev->model, bcm2835_codec_videodev.name, sizeof(mdev->model));
3065 + strscpy(mdev->serial, "0000", sizeof(mdev->serial));
3066 + snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
3067 + pdev->name);
3068 +
3069 + /* This should return the vgencmd version information or such .. */
3070 + mdev->hw_revision = 1;
3071 + media_device_init(mdev);
3072 +
3073 + ret = bcm2835_codec_create(drv, &drv->decode, DECODE);
3074 + if (ret)
3075 + goto out;
3076 +
3077 + ret = bcm2835_codec_create(drv, &drv->encode, ENCODE);
3078 + if (ret)
3079 + goto out;
3080 +
3081 + ret = bcm2835_codec_create(drv, &drv->isp, ISP);
3082 + if (ret)
3083 + goto out;
3084 +
3085 + /* Register the media device node */
3086 + if (media_device_register(mdev) < 0)
3087 + goto out;
3088 +
3089 + platform_set_drvdata(pdev, drv);
3090 +
3091 + return 0;
3092 +
3093 +out:
3094 + if (drv->isp) {
3095 + bcm2835_codec_destroy(drv->isp);
3096 + drv->isp = NULL;
3097 + }
3098 + if (drv->encode) {
3099 + bcm2835_codec_destroy(drv->encode);
3100 + drv->encode = NULL;
3101 + }
3102 + if (drv->decode) {
3103 + bcm2835_codec_destroy(drv->decode);
3104 + drv->decode = NULL;
3105 + }
3106 + return ret;
3107 +}
3108 +
3109 +static int bcm2835_codec_remove(struct platform_device *pdev)
3110 +{
3111 + struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
3112 +
3113 + media_device_unregister(&drv->mdev);
3114 +
3115 + bcm2835_codec_destroy(drv->isp);
3116 +
3117 + bcm2835_codec_destroy(drv->encode);
3118 +
3119 + bcm2835_codec_destroy(drv->decode);
3120 +
3121 + media_device_cleanup(&drv->mdev);
3122 +
3123 + return 0;
3124 +}
3125 +
3126 +static struct platform_driver bcm2835_v4l2_codec_driver = {
3127 + .probe = bcm2835_codec_probe,
3128 + .remove = bcm2835_codec_remove,
3129 + .driver = {
3130 + .name = "bcm2835-codec",
3131 + .owner = THIS_MODULE,
3132 + },
3133 +};
3134 +
3135 +module_platform_driver(bcm2835_v4l2_codec_driver);
3136 +
3137 +MODULE_DESCRIPTION("BCM2835 codec V4L2 driver");
3138 +MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.com>");
3139 +MODULE_LICENSE("GPL");
3140 +MODULE_VERSION("0.0.1");
3141 +MODULE_ALIAS("platform:bcm2835-codec");
3142 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
3143 +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
3144 @@ -618,6 +618,9 @@ enum mmal_parameter_video_type {
3145
3146 /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T */
3147 MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
3148 +
3149 + /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T */
3150 + MMAL_PARAMETER_VIDEO_VALIDATE_TIMESTAMPS,
3151 };
3152
3153 /** Valid mirror modes */