kernel: bump 6.1 to 6.1.66
[openwrt/staging/stintel.git] / target / linux / bcm27xx / patches-6.1 / 950-0277-staging-vc04_services-Add-a-V4L2-M2M-codec-driver.patch
1 From 118b44fa3c1c3de2c8330324f6acfc8c921f3878 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 vc04_services: bcm2835-codec: Switch to s32fract
61
62 staging/bcm2835-codec: Add the unpacked (16bpp) raw formats
63
64 Now that the firmware supports the unpacked (16bpp) variants
65 of the MIPI raw formats, add the mappings.
66
67 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
68
69 staging/bcm2835-codec: Log the number of excess supported formats
70
71 When logging that the firmware has provided more supported formats
72 than we had allocated storage for, log the number allocated and
73 returned.
74
75 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
76
77 staging/bcm2835-codec: Add support for pixel aspect ratio
78
79 If the format is detected by the driver and a V4L2_EVENT_SOURCE_CHANGE
80 event is generated, then pass on the pixel aspect ratio as well.
81
82 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
83
84 staging/bcm2835-codec: Implement additional g_selection calls for decode
85
86 v4l_cropcap calls our vidioc_g_pixelaspect function to get the pixel
87 aspect ratio, but also calls g_selection for V4L2_SEL_TGT_CROP_BOUNDS
88 and V4L2_SEL_TGT_CROP_DEFAULT. Whilst it allows for vidioc_g_pixelaspect
89 not to be implemented, it doesn't allow for either of the other two.
90
91 Add in support for the additional selection targets.
92
93 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
94
95 staging/bcm2835-codec: Add VC-1 support.
96
97 Providing the relevant licence has been purchased, then Pi0-3
98 can decode VC-1.
99
100 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
101
102 staging/bcm2835-codec: Fix support for levels 4.1 and 4.2
103
104 The driver said it supported H264 levels 4.1 and 4.2, but
105 was missing the V4L2 to MMAL mappings.
106
107 Add in those mappings.
108
109 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
110
111 staging/bcm2835-codec: Set the colourspace appropriately for RGB formats
112
113 Video decode supports YUV and RGB formats. YUV needs to report SMPTE170M
114 or REC709 appropriately, whilst RGB should report SRGB.
115
116 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
117
118 staging/bcm2835-codec: Pass corrupt frame flag.
119
120 MMAL has the flag MMAL_BUFFER_HEADER_FLAG_CORRUPTED but that
121 wasn't being passed through, so add it.
122
123 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
124
125 staging/bcm2835-codec: Do not update crop from S_FMT after res change
126
127 During decode, setting the CAPTURE queue format was setting the crop
128 rectangle to the requested height before aligning up the format to
129 cater for simple clients that weren't expecting to deal with cropping
130 and the SELECTION API.
131 This caused problems on some resolution change events if the client
132 didn't also then use the selection API.
133
134 Disable the crop update after a resolution change.
135
136 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
137
138 bcm2835: Allow compressed frames to set sizeimage (#4386)
139
140 Allow the user to set sizeimage in TRY_FMT and S_FMT if the format
141 flags have V4L2_FMT_FLAG_COMPRESSED set
142
143 Signed-off-by: John Cox <jc@kynesim.co.uk>
144
145 staging/bcm2835-codec: Change the default codec res to 32x32
146
147 In order to effectively guarantee that a V4L2_EVENT_SOURCE_CHANGE
148 event occurs, adopt a default resolution of 32x32 so that it
149 is incredibly unlikely to be decoding a stream of that resolution
150 and therefore failing to note a "change" requiring the event.
151
152 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
153
154 staging/bcm2835-codec: Add support for decoding interlaced streams
155
156 The video decoder can support decoding interlaced streams, so add
157 the required plumbing to signal this correctly.
158
159 The encoder and ISP do NOT support interlaced data, so trying to
160 configure an interlaced format on those nodes will be rejected.
161
162 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
163
164 staging/bcm2835-codec: Correct ENUM_FRAMESIZES stepsize to 2
165
166 Being YUV420 formats, the step size is always 2 to avoid part
167 chroma subsampling.
168
169 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
170
171 staging/bcm2835-codec: Return buffers to QUEUED not ERROR state
172
173 Should start_streaming fail, or buffers be queued during
174 stop_streaming, they should be returned to the core as QUEUED
175 and not (as currently) as ERROR.
176
177 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
178
179 staging/bcm2835_codec: Log MMAL flags in hex
180
181 The flags is a bitmask, so it's far easier to interpret as hex
182 data instead of decimal.
183
184 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
185
186 staging: bcm2835-codec: Allow custom specified strides/bytesperline.
187
188 If the client provides a bytesperline value in try_fmt/s_fmt then
189 validate it and correct if necessary.
190
191 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
192
193 staging/bcm2835_codec: Add support for image_fx to deinterlace
194
195 Adds another /dev/video node wrapping image_fx doing deinterlace.
196
197 Co-developed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
198 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
199
200 staging/bcm2835-v4l2_codec: Fix for encode selection API
201
202 Matches correct behaviour from DECODE and DEINTERLACE
203
204 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
205
206 staging: bcm2835-codec: Allow decode res changed before STREAMON(CAPTURE)
207
208 The V4L2 stateful video decoder API requires that you can STREAMON
209 on only the OUTPUT queue, feed in buffers, and wait for the
210 SOURCE_CHANGE event.
211 This requires that we enable the MMAL output port at the same time
212 as the input port, because the output port is the one that creates
213 the SOURCE_CHANGED event.
214
215 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
216
217 staging/bcm2835-codec: Do not send buffers to the VPU unless streaming
218
219 With video decode we now enable both input and output ports on
220 the component. This means that buffers will get passed to the VPU
221 earlier than desired if they are queued befoer STREAMON.
222
223 Check that the queue is streaming before sending buffers to the VPU.
224
225 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
226
227 staging: bcm2835-codec: Format changed should trigger drain
228
229 When a format changed event occurs, the spec says that it
230 triggers an implicit drain, and that needs to be signalled
231 via -EPIPE.
232
233 For BCM2835, the format changed event happens at the point
234 the format change occurs, so no further buffers exist from
235 before the resolution changed point. We therefore signal the
236 last buffer immediately.
237 We don't have a V4L2 available to us at this point, so set
238 the videobuf2 queue last_buffer_dequeued flag directly.
239
240 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
241
242 staging: bcm2835-codec: Signal the firmware to stop on all changes
243
244 The firmware defaults to not stopping video decode if only the
245 pixel aspect ratio or colourspace change. V4L2 requires us
246 to stop decoding on any change, therefore tell the firmware
247 of the desire for this alternate behaviour.
248
249 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
250
251 staging: bcm2835-codec: Queue flushed buffers instead of completing
252
253 When a buffer is returned on a port that is disabled, return it
254 to the videobuf2 QUEUED state instead of DONE which returns it
255 to the client.
256
257 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
258
259 staging: bcm2835_codec: Correct flushing code for refcounting
260
261 Completions don't reference count, so setting the completion
262 on the first buffer returned and then not reinitialising it
263 means that the flush function doesn't behave as intended.
264
265 Signal the completion when the last buffer is returned.
266
267 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
268
269 staging: bcm2835-codec: Ensure all ctrls are set on streamon
270
271 Currently the code was only setting some controls from
272 bcm2835_codec_set_ctrls, but it's simpler to use
273 v4l2_ctrl_handler_setup to avoid forgetting to adding new
274 controls to the list.
275
276 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
277
278 staging: bcm2835-codec: Add support for H&V Flips to ISP
279
280 The ISP can do H & V flips whilst resizing or converting
281 the image, so expose that via V4L2_CID_[H|V]FLIP.
282
283 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
284
285 bcm2835-v4l2-codec: Remove advertised support of VP8
286
287 The support for this format by firmware is very limited
288 and won't be faster than the arm.
289
290 Signed-off-by: Dom Cobley <popcornmix@gmail.com>
291
292 Pass V4L2_CID_MPEG_VIDEO_H264_MIN_QP/MAX_QP to bcm2835-v4l2-codec
293
294 Following raspberrypi/linux#4704. This is necessary to set up
295 quantization for variable bitrate to avoid video flickering.
296
297 staging/bcm2835-codec: bytesperline for YUV420/YVU420 needs to be 64
298
299 Matching https://github.com/raspberrypi/linux/pull/4419, the ISP
300 block (which is also used on the input of the encoder, and output
301 of the decoder) needs the base address of all planes to be aligned
302 to multiples of 32. This includes the chroma planes of YUV420 and
303 YVU420.
304 If the height is only a multiple of 2 (not 4), then you get an odd
305 number of lines in the second plane, which means the 3rd plane
306 starts at a multiple of bytesperline/2.
307
308 Set the minimum bytesperline alignment to 64 for those formats
309 so that the plane alignment is always right.
310
311 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
312
313 staging/bcm2835-codec: Allow a different stride alignment per role
314
315 Deinterlace and decode aren't affected in the same way as encode
316 and ISP by the alignment requirement on 3 plane YUV420.
317 Decode would be affected, but it always aligns the height up to
318 a macroblock, and uses the selection API to reflect that.
319
320 Add in the facility to set the bytesperline alignment per role.
321
322 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
323
324 staging: vc04_services: codec: Add support for V4L2_PIX_FMT_RGBA32 format
325
326 We already support V4L2_PIX_FMT_BGR32 which is the same thing with red
327 and blue swapped, so it makes sense to include this variant as well.
328
329 Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
330
331 bcm2835-codec: Return empty buffers to the VPU instead of queueing to vbuf2
332
333 The encoder can skip frames totally should rate control overshoot
334 the target bitrate too far. In this situation it generates an
335 output buffer of length 0.
336 V4L2 treats a buffer of length 0 as an end of stream flag, which is
337 not appropriate in this case, therefore we can not return that buffer
338 to the client.
339
340 The driver was returning the buffer to videobuf2 in the QUEUED state,
341 however that buffer was then not dequeued again, so the number of
342 buffers was reduced each time this happened. In the pathological
343 case of using GStreamer's videotestsrc in mode 1 for noise, this happens
344 sufficiently frequently to totally stall the pipeline.
345
346 If the port is still enabled then return the buffer straight back to
347 the VPU rather than to videobuf2.
348
349 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
350
351 vc04_services: bcm2835-codec: Add support for V4L2_PIX_FMT_NV12_COL128
352
353 V4L2_PIX_FMT_NV12_COL128 is supported by the ISP and the input of
354 video_encode, output of video_decode, and both input and output
355 of the ISP.
356
357 Add in the plumbing to support the format on those ports.
358
359 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
360
361 vc04_services: bcm2835-codec: Set crop_height for compressed formats
362
363 In particular for the encoder where the CAPTURE format dictates
364 the parameters given to the codec we need to be able to set the
365 value passed as the crop_height for the compressed format.
366 There's no crop available for cropped modes, so always set
367 crop_height to the requested height.
368
369 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
370
371 vc04_services: bcm2835-codec: Set port format from s_selection
372
373 s_selection allows the crop region of an uncompressed pixel
374 format to be specified, but it wasn't passing the setting on to
375 the firmware. Depending on call order this would potentially
376 mean that the crop wasn't actioned.
377
378 Set the port format on s_selection if we have a component created.
379
380 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
381
382 bcm2835-codec: /dev/video31 as interface to image_encode JPEG encoder
383
384 Signed-off-by: Maxim Devaev <mdevaev@gmail.com>
385
386 bcm2835-v4l2-codec: support H.264 5.0 and 5.1 levels
387
388 vc04_services: bcm2835-codec: Remove redundant role check
389
390 vidioc_try_encoder_cmd checks the role, but the ioctl is disabled
391 for any roles in which it is invalid.
392
393 Remove the redundant check.
394
395 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
396
397 vc04_services: bcm2835-codec: Allow encoder_cmd on ISP and deinterlace
398
399 ISP and deinterlace also need a mechanism for passing effectively
400 an EOS through the pipeline to signal when all buffers have been
401 processed.
402
403 VIDIOC_ENCODER_CMD does exactly this for encoders, so reuse the same
404 function for ISP and deinterlace.
405 (VIDIOC_DECODER_CMD is slightly different in that it also passes
406 details of when and how to stop, so is not as relevant).
407
408 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
409 ---
410 drivers/staging/vc04_services/Kconfig | 1 +
411 drivers/staging/vc04_services/Makefile | 1 +
412 .../vc04_services/bcm2835-codec/Kconfig | 11 +
413 .../vc04_services/bcm2835-codec/Makefile | 8 +
414 .../staging/vc04_services/bcm2835-codec/TODO | 1 +
415 .../bcm2835-codec/bcm2835-v4l2-codec.c | 3834 +++++++++++++++++
416 .../vchiq-mmal/mmal-parameters.h | 8 +
417 7 files changed, 3864 insertions(+)
418 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Kconfig
419 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/Makefile
420 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/TODO
421 create mode 100644 drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
422
423 --- a/drivers/staging/vc04_services/Kconfig
424 +++ b/drivers/staging/vc04_services/Kconfig
425 @@ -45,6 +45,7 @@ source "drivers/staging/vc04_services/bc
426 source "drivers/staging/vc04_services/bcm2835-camera/Kconfig"
427
428 source "drivers/staging/vc04_services/vc-sm-cma/Kconfig"
429 +source "drivers/staging/vc04_services/bcm2835-codec/Kconfig"
430
431 source "drivers/staging/vc04_services/vchiq-mmal/Kconfig"
432
433 --- a/drivers/staging/vc04_services/Makefile
434 +++ b/drivers/staging/vc04_services/Makefile
435 @@ -15,6 +15,7 @@ obj-$(CONFIG_SND_BCM2835) += bcm2835-au
436 obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/
437 obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/
438 obj-$(CONFIG_BCM_VC_SM_CMA) += vc-sm-cma/
439 +obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec/
440
441 ccflags-y += -I $(srctree)/$(src)/include
442
443 --- /dev/null
444 +++ b/drivers/staging/vc04_services/bcm2835-codec/Kconfig
445 @@ -0,0 +1,11 @@
446 +config VIDEO_CODEC_BCM2835
447 + tristate "BCM2835 Video codec support"
448 + depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
449 + depends on VIDEO_DEV && (ARCH_BCM2835 || COMPILE_TEST)
450 + select BCM2835_VCHIQ_MMAL
451 + select VIDEOBUF2_DMA_CONTIG
452 + select V4L2_MEM2MEM_DEV
453 + help
454 + Say Y here to enable the V4L2 video codecs for
455 + Broadcom BCM2835 SoC. This operates over the VCHIQ interface
456 + to a service running on VideoCore.
457 --- /dev/null
458 +++ b/drivers/staging/vc04_services/bcm2835-codec/Makefile
459 @@ -0,0 +1,8 @@
460 +# SPDX-License-Identifier: GPL-2.0
461 +bcm2835-codec-objs := bcm2835-v4l2-codec.o
462 +
463 +obj-$(CONFIG_VIDEO_CODEC_BCM2835) += bcm2835-codec.o
464 +
465 +ccflags-y += \
466 + -I$(srctree)/drivers/staging/vc04_services \
467 + -D__VCCOREVER__=0x04000000
468 --- /dev/null
469 +++ b/drivers/staging/vc04_services/bcm2835-codec/TODO
470 @@ -0,0 +1 @@
471 +No issues. Depends on VCHIQ which is in staging.
472 \ No newline at end of file
473 --- /dev/null
474 +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c
475 @@ -0,0 +1,3834 @@
476 +// SPDX-License-Identifier: GPL-2.0
477 +
478 +/*
479 + * A v4l2-mem2mem device that wraps the video codec MMAL component.
480 + *
481 + * Copyright 2018 Raspberry Pi (Trading) Ltd.
482 + * Author: Dave Stevenson (dave.stevenson@raspberrypi.com)
483 + *
484 + * Loosely based on the vim2m virtual driver by Pawel Osciak
485 + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
486 + * Pawel Osciak, <pawel@osciak.com>
487 + * Marek Szyprowski, <m.szyprowski@samsung.com>
488 + *
489 + * Whilst this driver uses the v4l2_mem2mem framework, it does not need the
490 + * scheduling aspects, so will always take the buffers, pass them to the VPU,
491 + * and then signal the job as complete.
492 + *
493 + * This program is free software; you can redistribute it and/or modify
494 + * it under the terms of the GNU General Public License as published by the
495 + * Free Software Foundation; either version 2 of the
496 + * License, or (at your option) any later version
497 + */
498 +#include <linux/module.h>
499 +#include <linux/delay.h>
500 +#include <linux/fs.h>
501 +#include <linux/timer.h>
502 +#include <linux/sched.h>
503 +#include <linux/slab.h>
504 +#include <linux/platform_device.h>
505 +#include <linux/syscalls.h>
506 +
507 +#include <media/v4l2-mem2mem.h>
508 +#include <media/v4l2-device.h>
509 +#include <media/v4l2-ioctl.h>
510 +#include <media/v4l2-ctrls.h>
511 +#include <media/v4l2-event.h>
512 +#include <media/videobuf2-dma-contig.h>
513 +
514 +#include "vchiq-mmal/mmal-encodings.h"
515 +#include "vchiq-mmal/mmal-msg.h"
516 +#include "vchiq-mmal/mmal-parameters.h"
517 +#include "vchiq-mmal/mmal-vchiq.h"
518 +
519 +MODULE_IMPORT_NS(DMA_BUF);
520 +
521 +/*
522 + * Default /dev/videoN node numbers for decode and encode.
523 + * Deliberately avoid the very low numbers as these are often taken by webcams
524 + * etc, and simple apps tend to only go for /dev/video0.
525 + */
526 +static int decode_video_nr = 10;
527 +module_param(decode_video_nr, int, 0644);
528 +MODULE_PARM_DESC(decode_video_nr, "decoder video device number");
529 +
530 +static int encode_video_nr = 11;
531 +module_param(encode_video_nr, int, 0644);
532 +MODULE_PARM_DESC(encode_video_nr, "encoder video device number");
533 +
534 +static int isp_video_nr = 12;
535 +module_param(isp_video_nr, int, 0644);
536 +MODULE_PARM_DESC(isp_video_nr, "isp video device number");
537 +
538 +static int deinterlace_video_nr = 18;
539 +module_param(deinterlace_video_nr, int, 0644);
540 +MODULE_PARM_DESC(deinterlace_video_nr, "deinterlace video device number");
541 +
542 +static int encode_image_nr = 31;
543 +module_param(encode_image_nr, int, 0644);
544 +MODULE_PARM_DESC(encode_image_nr, "encoder image device number");
545 +
546 +/*
547 + * Workaround for GStreamer v4l2convert component not considering Bayer formats
548 + * as raw, and therefore not considering a V4L2 device that supports them as
549 + * a suitable candidate.
550 + */
551 +static bool disable_bayer;
552 +module_param(disable_bayer, bool, 0644);
553 +MODULE_PARM_DESC(disable_bayer, "Disable support for Bayer formats");
554 +
555 +static unsigned int debug;
556 +module_param(debug, uint, 0644);
557 +MODULE_PARM_DESC(debug, "activates debug info (0-3)");
558 +
559 +static bool advanced_deinterlace = true;
560 +module_param(advanced_deinterlace, bool, 0644);
561 +MODULE_PARM_DESC(advanced_deinterlace, "Use advanced deinterlace");
562 +
563 +static int field_override;
564 +module_param(field_override, int, 0644);
565 +MODULE_PARM_DESC(field_override, "force TB(8)/BT(9) field");
566 +
567 +enum bcm2835_codec_role {
568 + DECODE,
569 + ENCODE,
570 + ISP,
571 + DEINTERLACE,
572 + ENCODE_IMAGE,
573 + NUM_ROLES
574 +};
575 +
576 +static const char * const roles[] = {
577 + "decode",
578 + "encode",
579 + "isp",
580 + "image_fx",
581 + "encode_image",
582 +};
583 +
584 +static const char * const components[] = {
585 + "ril.video_decode",
586 + "ril.video_encode",
587 + "ril.isp",
588 + "ril.image_fx",
589 + "ril.image_encode",
590 +};
591 +
592 +/* Timeout for stop_streaming to allow all buffers to return */
593 +#define COMPLETE_TIMEOUT (2 * HZ)
594 +
595 +#define MIN_W 32
596 +#define MIN_H 32
597 +#define MAX_W 1920
598 +#define MAX_H 1920
599 +#define BPL_ALIGN 32
600 +/*
601 + * The decoder spec supports the V4L2_EVENT_SOURCE_CHANGE event, but the docs
602 + * seem to want it to always be generated on startup, which prevents the client
603 + * from configuring the CAPTURE queue based on any parsing it has already done
604 + * which may save time and allow allocation of CAPTURE buffers early. Surely
605 + * SOURCE_CHANGE means something has changed, not just "always notify".
606 + *
607 + * For those clients that don't set the CAPTURE resolution, adopt a default
608 + * resolution that is seriously unlikely to be correct, therefore almost
609 + * guaranteed to get the SOURCE_CHANGE event.
610 + */
611 +#define DEFAULT_WIDTH 32
612 +#define DEFAULT_HEIGHT 32
613 +/*
614 + * The unanswered question - what is the maximum size of a compressed frame?
615 + * V4L2 mandates that the encoded frame must fit in a single buffer. Sizing
616 + * that buffer is a compromise between wasting memory and risking not fitting.
617 + * The 1080P version of Big Buck Bunny has some frames that exceed 512kB.
618 + * Adopt a moderately arbitrary split at 720P for switching between 512 and
619 + * 768kB buffers.
620 + */
621 +#define DEF_COMP_BUF_SIZE_GREATER_720P (768 << 10)
622 +#define DEF_COMP_BUF_SIZE_720P_OR_LESS (512 << 10)
623 +/* JPEG image can be very large. For paranoid reasons 4MB is used */
624 +#define DEF_COMP_BUF_SIZE_JPEG (4096 << 10)
625 +
626 +/* Flags that indicate a format can be used for capture/output */
627 +#define MEM2MEM_CAPTURE BIT(0)
628 +#define MEM2MEM_OUTPUT BIT(1)
629 +
630 +#define MEM2MEM_NAME "bcm2835-codec"
631 +
632 +struct bcm2835_codec_fmt {
633 + u32 fourcc;
634 + int depth;
635 + u8 bytesperline_align[NUM_ROLES];
636 + u32 flags;
637 + u32 mmal_fmt;
638 + int size_multiplier_x2;
639 + bool is_bayer;
640 +};
641 +
642 +static const struct bcm2835_codec_fmt supported_formats[] = {
643 + {
644 + /* YUV formats */
645 + .fourcc = V4L2_PIX_FMT_YUV420,
646 + .depth = 8,
647 + .bytesperline_align = { 32, 64, 64, 32, 32 },
648 + .flags = 0,
649 + .mmal_fmt = MMAL_ENCODING_I420,
650 + .size_multiplier_x2 = 3,
651 + }, {
652 + .fourcc = V4L2_PIX_FMT_YVU420,
653 + .depth = 8,
654 + .bytesperline_align = { 32, 64, 64, 32, 32 },
655 + .flags = 0,
656 + .mmal_fmt = MMAL_ENCODING_YV12,
657 + .size_multiplier_x2 = 3,
658 + }, {
659 + .fourcc = V4L2_PIX_FMT_NV12,
660 + .depth = 8,
661 + .bytesperline_align = { 32, 32, 32, 32, 32 },
662 + .flags = 0,
663 + .mmal_fmt = MMAL_ENCODING_NV12,
664 + .size_multiplier_x2 = 3,
665 + }, {
666 + .fourcc = V4L2_PIX_FMT_NV21,
667 + .depth = 8,
668 + .bytesperline_align = { 32, 32, 32, 32, 32 },
669 + .flags = 0,
670 + .mmal_fmt = MMAL_ENCODING_NV21,
671 + .size_multiplier_x2 = 3,
672 + }, {
673 + .fourcc = V4L2_PIX_FMT_RGB565,
674 + .depth = 16,
675 + .bytesperline_align = { 32, 32, 32, 32, 32 },
676 + .flags = 0,
677 + .mmal_fmt = MMAL_ENCODING_RGB16,
678 + .size_multiplier_x2 = 2,
679 + }, {
680 + .fourcc = V4L2_PIX_FMT_YUYV,
681 + .depth = 16,
682 + .bytesperline_align = { 32, 32, 32, 32, 32 },
683 + .flags = 0,
684 + .mmal_fmt = MMAL_ENCODING_YUYV,
685 + .size_multiplier_x2 = 2,
686 + }, {
687 + .fourcc = V4L2_PIX_FMT_UYVY,
688 + .depth = 16,
689 + .bytesperline_align = { 32, 32, 32, 32, 32 },
690 + .flags = 0,
691 + .mmal_fmt = MMAL_ENCODING_UYVY,
692 + .size_multiplier_x2 = 2,
693 + }, {
694 + .fourcc = V4L2_PIX_FMT_YVYU,
695 + .depth = 16,
696 + .bytesperline_align = { 32, 32, 32, 32, 32 },
697 + .flags = 0,
698 + .mmal_fmt = MMAL_ENCODING_YVYU,
699 + .size_multiplier_x2 = 2,
700 + }, {
701 + .fourcc = V4L2_PIX_FMT_VYUY,
702 + .depth = 16,
703 + .bytesperline_align = { 32, 32, 32, 32, 32 },
704 + .flags = 0,
705 + .mmal_fmt = MMAL_ENCODING_VYUY,
706 + .size_multiplier_x2 = 2,
707 + }, {
708 + .fourcc = V4L2_PIX_FMT_NV12_COL128,
709 + .depth = 8,
710 + .bytesperline_align = { 32, 32, 32, 32, 32 },
711 + .flags = 0,
712 + .mmal_fmt = MMAL_ENCODING_YUVUV128,
713 + .size_multiplier_x2 = 3,
714 + }, {
715 + /* RGB formats */
716 + .fourcc = V4L2_PIX_FMT_RGB24,
717 + .depth = 24,
718 + .bytesperline_align = { 32, 32, 32, 32, 32 },
719 + .flags = 0,
720 + .mmal_fmt = MMAL_ENCODING_RGB24,
721 + .size_multiplier_x2 = 2,
722 + }, {
723 + .fourcc = V4L2_PIX_FMT_BGR24,
724 + .depth = 24,
725 + .bytesperline_align = { 32, 32, 32, 32, 32 },
726 + .flags = 0,
727 + .mmal_fmt = MMAL_ENCODING_BGR24,
728 + .size_multiplier_x2 = 2,
729 + }, {
730 + .fourcc = V4L2_PIX_FMT_BGR32,
731 + .depth = 32,
732 + .bytesperline_align = { 32, 32, 32, 32, 32 },
733 + .flags = 0,
734 + .mmal_fmt = MMAL_ENCODING_BGRA,
735 + .size_multiplier_x2 = 2,
736 + }, {
737 + .fourcc = V4L2_PIX_FMT_RGBA32,
738 + .depth = 32,
739 + .bytesperline_align = { 32, 32, 32, 32 },
740 + .flags = 0,
741 + .mmal_fmt = MMAL_ENCODING_RGBA,
742 + .size_multiplier_x2 = 2,
743 + }, {
744 + /* Bayer formats */
745 + /* 8 bit */
746 + .fourcc = V4L2_PIX_FMT_SRGGB8,
747 + .depth = 8,
748 + .bytesperline_align = { 32, 32, 32, 32, 32 },
749 + .flags = 0,
750 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB8,
751 + .size_multiplier_x2 = 2,
752 + .is_bayer = true,
753 + }, {
754 + .fourcc = V4L2_PIX_FMT_SBGGR8,
755 + .depth = 8,
756 + .bytesperline_align = { 32, 32, 32, 32, 32 },
757 + .flags = 0,
758 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR8,
759 + .size_multiplier_x2 = 2,
760 + .is_bayer = true,
761 + }, {
762 + .fourcc = V4L2_PIX_FMT_SGRBG8,
763 + .depth = 8,
764 + .bytesperline_align = { 32, 32, 32, 32, 32 },
765 + .flags = 0,
766 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG8,
767 + .size_multiplier_x2 = 2,
768 + .is_bayer = true,
769 + }, {
770 + .fourcc = V4L2_PIX_FMT_SGBRG8,
771 + .depth = 8,
772 + .bytesperline_align = { 32, 32, 32, 32, 32 },
773 + .flags = 0,
774 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG8,
775 + .size_multiplier_x2 = 2,
776 + .is_bayer = true,
777 + }, {
778 + /* 10 bit */
779 + .fourcc = V4L2_PIX_FMT_SRGGB10P,
780 + .depth = 10,
781 + .bytesperline_align = { 32, 32, 32, 32, 32 },
782 + .flags = 0,
783 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10P,
784 + .size_multiplier_x2 = 2,
785 + .is_bayer = true,
786 + }, {
787 + .fourcc = V4L2_PIX_FMT_SBGGR10P,
788 + .depth = 10,
789 + .bytesperline_align = { 32, 32, 32, 32, 32 },
790 + .flags = 0,
791 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10P,
792 + .size_multiplier_x2 = 2,
793 + .is_bayer = true,
794 + }, {
795 + .fourcc = V4L2_PIX_FMT_SGRBG10P,
796 + .depth = 10,
797 + .bytesperline_align = { 32, 32, 32, 32, 32 },
798 + .flags = 0,
799 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10P,
800 + .size_multiplier_x2 = 2,
801 + .is_bayer = true,
802 + }, {
803 + .fourcc = V4L2_PIX_FMT_SGBRG10P,
804 + .depth = 10,
805 + .bytesperline_align = { 32, 32, 32, 32, 32 },
806 + .flags = 0,
807 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10P,
808 + .size_multiplier_x2 = 2,
809 + .is_bayer = true,
810 + }, {
811 + /* 12 bit */
812 + .fourcc = V4L2_PIX_FMT_SRGGB12P,
813 + .depth = 12,
814 + .bytesperline_align = { 32, 32, 32, 32, 32 },
815 + .flags = 0,
816 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12P,
817 + .size_multiplier_x2 = 2,
818 + .is_bayer = true,
819 + }, {
820 + .fourcc = V4L2_PIX_FMT_SBGGR12P,
821 + .depth = 12,
822 + .bytesperline_align = { 32, 32, 32, 32, 32 },
823 + .flags = 0,
824 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12P,
825 + .size_multiplier_x2 = 2,
826 + .is_bayer = true,
827 + }, {
828 + .fourcc = V4L2_PIX_FMT_SGRBG12P,
829 + .depth = 12,
830 + .bytesperline_align = { 32, 32, 32, 32, 32 },
831 + .flags = 0,
832 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12P,
833 + .size_multiplier_x2 = 2,
834 + .is_bayer = true,
835 + }, {
836 + .fourcc = V4L2_PIX_FMT_SGBRG12P,
837 + .depth = 12,
838 + .bytesperline_align = { 32, 32, 32, 32, 32 },
839 + .flags = 0,
840 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12P,
841 + .size_multiplier_x2 = 2,
842 + .is_bayer = true,
843 + }, {
844 + /* 14 bit */
845 + .fourcc = V4L2_PIX_FMT_SRGGB14P,
846 + .depth = 14,
847 + .bytesperline_align = { 32, 32, 32, 32, 32 },
848 + .flags = 0,
849 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB14P,
850 + .size_multiplier_x2 = 2,
851 + .is_bayer = true,
852 + }, {
853 + .fourcc = V4L2_PIX_FMT_SBGGR14P,
854 + .depth = 14,
855 + .bytesperline_align = { 32, 32, 32, 32, 32 },
856 + .flags = 0,
857 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR14P,
858 + .size_multiplier_x2 = 2,
859 + .is_bayer = true,
860 +
861 + }, {
862 + .fourcc = V4L2_PIX_FMT_SGRBG14P,
863 + .depth = 14,
864 + .bytesperline_align = { 32, 32, 32, 32, 32 },
865 + .flags = 0,
866 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG14P,
867 + .size_multiplier_x2 = 2,
868 + .is_bayer = true,
869 + }, {
870 + .fourcc = V4L2_PIX_FMT_SGBRG14P,
871 + .depth = 14,
872 + .bytesperline_align = { 32, 32, 32, 32, 32 },
873 + .flags = 0,
874 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG14P,
875 + .size_multiplier_x2 = 2,
876 + .is_bayer = true,
877 + }, {
878 + /* 16 bit */
879 + .fourcc = V4L2_PIX_FMT_SRGGB16,
880 + .depth = 16,
881 + .bytesperline_align = { 32, 32, 32, 32, 32 },
882 + .flags = 0,
883 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB16,
884 + .size_multiplier_x2 = 2,
885 + .is_bayer = true,
886 + }, {
887 + .fourcc = V4L2_PIX_FMT_SBGGR16,
888 + .depth = 16,
889 + .bytesperline_align = { 32, 32, 32, 32, 32 },
890 + .flags = 0,
891 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR16,
892 + .size_multiplier_x2 = 2,
893 + .is_bayer = true,
894 + }, {
895 + .fourcc = V4L2_PIX_FMT_SGRBG16,
896 + .depth = 16,
897 + .bytesperline_align = { 32, 32, 32, 32, 32 },
898 + .flags = 0,
899 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG16,
900 + .size_multiplier_x2 = 2,
901 + .is_bayer = true,
902 + }, {
903 + .fourcc = V4L2_PIX_FMT_SGBRG16,
904 + .depth = 16,
905 + .bytesperline_align = { 32, 32, 32, 32, 32 },
906 + .flags = 0,
907 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG16,
908 + .size_multiplier_x2 = 2,
909 + .is_bayer = true,
910 + }, {
911 + /* Bayer formats unpacked to 16bpp */
912 + /* 10 bit */
913 + .fourcc = V4L2_PIX_FMT_SRGGB10,
914 + .depth = 16,
915 + .bytesperline_align = { 32, 32, 32, 32, 32 },
916 + .flags = 0,
917 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB10,
918 + .size_multiplier_x2 = 2,
919 + .is_bayer = true,
920 + }, {
921 + .fourcc = V4L2_PIX_FMT_SBGGR10,
922 + .depth = 16,
923 + .bytesperline_align = { 32, 32, 32, 32, 32 },
924 + .flags = 0,
925 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR10,
926 + .size_multiplier_x2 = 2,
927 + .is_bayer = true,
928 + }, {
929 + .fourcc = V4L2_PIX_FMT_SGRBG10,
930 + .depth = 16,
931 + .bytesperline_align = { 32, 32, 32, 32, 32 },
932 + .flags = 0,
933 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG10,
934 + .size_multiplier_x2 = 2,
935 + .is_bayer = true,
936 + }, {
937 + .fourcc = V4L2_PIX_FMT_SGBRG10,
938 + .depth = 16,
939 + .bytesperline_align = { 32, 32, 32, 32, 32 },
940 + .flags = 0,
941 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG10,
942 + .size_multiplier_x2 = 2,
943 + .is_bayer = true,
944 + }, {
945 + /* 12 bit */
946 + .fourcc = V4L2_PIX_FMT_SRGGB12,
947 + .depth = 16,
948 + .bytesperline_align = { 32, 32, 32, 32, 32 },
949 + .flags = 0,
950 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB12,
951 + .size_multiplier_x2 = 2,
952 + .is_bayer = true,
953 + }, {
954 + .fourcc = V4L2_PIX_FMT_SBGGR12,
955 + .depth = 16,
956 + .bytesperline_align = { 32, 32, 32, 32, 32 },
957 + .flags = 0,
958 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR12,
959 + .size_multiplier_x2 = 2,
960 + .is_bayer = true,
961 + }, {
962 + .fourcc = V4L2_PIX_FMT_SGRBG12,
963 + .depth = 16,
964 + .bytesperline_align = { 32, 32, 32, 32, 32 },
965 + .flags = 0,
966 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG12,
967 + .size_multiplier_x2 = 2,
968 + .is_bayer = true,
969 + }, {
970 + .fourcc = V4L2_PIX_FMT_SGBRG12,
971 + .depth = 16,
972 + .bytesperline_align = { 32, 32, 32, 32, 32 },
973 + .flags = 0,
974 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG12,
975 + .size_multiplier_x2 = 2,
976 + .is_bayer = true,
977 + }, {
978 + /* 14 bit */
979 + .fourcc = V4L2_PIX_FMT_SRGGB14,
980 + .depth = 16,
981 + .bytesperline_align = { 32, 32, 32, 32, 32 },
982 + .flags = 0,
983 + .mmal_fmt = MMAL_ENCODING_BAYER_SRGGB14,
984 + .size_multiplier_x2 = 2,
985 + .is_bayer = true,
986 + }, {
987 + .fourcc = V4L2_PIX_FMT_SBGGR14,
988 + .depth = 16,
989 + .bytesperline_align = { 32, 32, 32, 32, 32 },
990 + .flags = 0,
991 + .mmal_fmt = MMAL_ENCODING_BAYER_SBGGR14,
992 + .size_multiplier_x2 = 2,
993 + .is_bayer = true,
994 + }, {
995 + .fourcc = V4L2_PIX_FMT_SGRBG14,
996 + .depth = 16,
997 + .bytesperline_align = { 32, 32, 32, 32, 32 },
998 + .flags = 0,
999 + .mmal_fmt = MMAL_ENCODING_BAYER_SGRBG14,
1000 + .size_multiplier_x2 = 2,
1001 + .is_bayer = true,
1002 + }, {
1003 + .fourcc = V4L2_PIX_FMT_SGBRG14,
1004 + .depth = 16,
1005 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1006 + .flags = 0,
1007 + .mmal_fmt = MMAL_ENCODING_BAYER_SGBRG14,
1008 + .size_multiplier_x2 = 2,
1009 + .is_bayer = true,
1010 + }, {
1011 + /* Monochrome MIPI formats */
1012 + /* 8 bit */
1013 + .fourcc = V4L2_PIX_FMT_GREY,
1014 + .depth = 8,
1015 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1016 + .flags = 0,
1017 + .mmal_fmt = MMAL_ENCODING_GREY,
1018 + .size_multiplier_x2 = 2,
1019 + }, {
1020 + /* 10 bit */
1021 + .fourcc = V4L2_PIX_FMT_Y10P,
1022 + .depth = 10,
1023 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1024 + .flags = 0,
1025 + .mmal_fmt = MMAL_ENCODING_Y10P,
1026 + .size_multiplier_x2 = 2,
1027 + }, {
1028 + /* 12 bit */
1029 + .fourcc = V4L2_PIX_FMT_Y12P,
1030 + .depth = 12,
1031 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1032 + .flags = 0,
1033 + .mmal_fmt = MMAL_ENCODING_Y12P,
1034 + .size_multiplier_x2 = 2,
1035 + }, {
1036 + /* 14 bit */
1037 + .fourcc = V4L2_PIX_FMT_Y14P,
1038 + .depth = 14,
1039 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1040 + .flags = 0,
1041 + .mmal_fmt = MMAL_ENCODING_Y14P,
1042 + .size_multiplier_x2 = 2,
1043 + }, {
1044 + /* 16 bit */
1045 + .fourcc = V4L2_PIX_FMT_Y16,
1046 + .depth = 16,
1047 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1048 + .flags = 0,
1049 + .mmal_fmt = MMAL_ENCODING_Y16,
1050 + .size_multiplier_x2 = 2,
1051 + }, {
1052 + /* 10 bit as 16bpp */
1053 + .fourcc = V4L2_PIX_FMT_Y10,
1054 + .depth = 16,
1055 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1056 + .flags = 0,
1057 + .mmal_fmt = MMAL_ENCODING_Y10,
1058 + .size_multiplier_x2 = 2,
1059 + }, {
1060 + /* 12 bit as 16bpp */
1061 + .fourcc = V4L2_PIX_FMT_Y12,
1062 + .depth = 16,
1063 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1064 + .flags = 0,
1065 + .mmal_fmt = MMAL_ENCODING_Y12,
1066 + .size_multiplier_x2 = 2,
1067 + }, {
1068 + /* 14 bit as 16bpp */
1069 + .fourcc = V4L2_PIX_FMT_Y14,
1070 + .depth = 16,
1071 + .bytesperline_align = { 32, 32, 32, 32, 32 },
1072 + .flags = 0,
1073 + .mmal_fmt = MMAL_ENCODING_Y14,
1074 + .size_multiplier_x2 = 2,
1075 + }, {
1076 + /* Compressed formats */
1077 + .fourcc = V4L2_PIX_FMT_H264,
1078 + .depth = 0,
1079 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1080 + .mmal_fmt = MMAL_ENCODING_H264,
1081 + }, {
1082 + .fourcc = V4L2_PIX_FMT_JPEG,
1083 + .depth = 0,
1084 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1085 + .mmal_fmt = MMAL_ENCODING_JPEG,
1086 + }, {
1087 + .fourcc = V4L2_PIX_FMT_MJPEG,
1088 + .depth = 0,
1089 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1090 + .mmal_fmt = MMAL_ENCODING_MJPEG,
1091 + }, {
1092 + .fourcc = V4L2_PIX_FMT_MPEG4,
1093 + .depth = 0,
1094 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1095 + .mmal_fmt = MMAL_ENCODING_MP4V,
1096 + }, {
1097 + .fourcc = V4L2_PIX_FMT_H263,
1098 + .depth = 0,
1099 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1100 + .mmal_fmt = MMAL_ENCODING_H263,
1101 + }, {
1102 + .fourcc = V4L2_PIX_FMT_MPEG2,
1103 + .depth = 0,
1104 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1105 + .mmal_fmt = MMAL_ENCODING_MP2V,
1106 + }, {
1107 + .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
1108 + .depth = 0,
1109 + .flags = V4L2_FMT_FLAG_COMPRESSED,
1110 + .mmal_fmt = MMAL_ENCODING_WVC1,
1111 + }
1112 +};
1113 +
1114 +struct bcm2835_codec_fmt_list {
1115 + struct bcm2835_codec_fmt *list;
1116 + unsigned int num_entries;
1117 +};
1118 +
1119 +struct m2m_mmal_buffer {
1120 + struct v4l2_m2m_buffer m2m;
1121 + struct mmal_buffer mmal;
1122 +};
1123 +
1124 +/* Per-queue, driver-specific private data */
1125 +struct bcm2835_codec_q_data {
1126 + /*
1127 + * These parameters should be treated as gospel, with everything else
1128 + * being determined from them.
1129 + */
1130 + /* Buffer width/height */
1131 + unsigned int bytesperline;
1132 + unsigned int height;
1133 + /* Crop size used for selection handling */
1134 + unsigned int crop_width;
1135 + unsigned int crop_height;
1136 + bool selection_set;
1137 + struct v4l2_fract aspect_ratio;
1138 + enum v4l2_field field;
1139 +
1140 + unsigned int sizeimage;
1141 + unsigned int sequence;
1142 + struct bcm2835_codec_fmt *fmt;
1143 +
1144 + /* One extra buffer header so we can send an EOS. */
1145 + struct m2m_mmal_buffer eos_buffer;
1146 + bool eos_buffer_in_use; /* debug only */
1147 +};
1148 +
1149 +struct bcm2835_codec_dev {
1150 + struct platform_device *pdev;
1151 +
1152 + /* v4l2 devices */
1153 + struct v4l2_device v4l2_dev;
1154 + struct video_device vfd;
1155 + /* mutex for the v4l2 device */
1156 + struct mutex dev_mutex;
1157 + atomic_t num_inst;
1158 +
1159 + /* allocated mmal instance and components */
1160 + enum bcm2835_codec_role role;
1161 + /* The list of formats supported on input and output queues. */
1162 + struct bcm2835_codec_fmt_list supported_fmts[2];
1163 +
1164 + struct vchiq_mmal_instance *instance;
1165 +
1166 + struct v4l2_m2m_dev *m2m_dev;
1167 +};
1168 +
1169 +struct bcm2835_codec_ctx {
1170 + struct v4l2_fh fh;
1171 + struct bcm2835_codec_dev *dev;
1172 +
1173 + struct v4l2_ctrl_handler hdl;
1174 +
1175 + struct vchiq_mmal_component *component;
1176 + bool component_enabled;
1177 +
1178 + enum v4l2_colorspace colorspace;
1179 + enum v4l2_ycbcr_encoding ycbcr_enc;
1180 + enum v4l2_xfer_func xfer_func;
1181 + enum v4l2_quantization quant;
1182 +
1183 + int hflip;
1184 + int vflip;
1185 +
1186 + /* Source and destination queue data */
1187 + struct bcm2835_codec_q_data q_data[2];
1188 + s32 bitrate;
1189 + unsigned int framerate_num;
1190 + unsigned int framerate_denom;
1191 +
1192 + bool aborting;
1193 + int num_ip_buffers;
1194 + int num_op_buffers;
1195 + struct completion frame_cmplt;
1196 +};
1197 +
1198 +struct bcm2835_codec_driver {
1199 + struct platform_device *pdev;
1200 + struct media_device mdev;
1201 +
1202 + struct bcm2835_codec_dev *encode;
1203 + struct bcm2835_codec_dev *decode;
1204 + struct bcm2835_codec_dev *isp;
1205 + struct bcm2835_codec_dev *deinterlace;
1206 + struct bcm2835_codec_dev *encode_image;
1207 +};
1208 +
1209 +enum {
1210 + V4L2_M2M_SRC = 0,
1211 + V4L2_M2M_DST = 1,
1212 +};
1213 +
1214 +static const struct bcm2835_codec_fmt *get_fmt(u32 mmal_fmt)
1215 +{
1216 + unsigned int i;
1217 +
1218 + for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
1219 + if (supported_formats[i].mmal_fmt == mmal_fmt &&
1220 + (!disable_bayer || !supported_formats[i].is_bayer))
1221 + return &supported_formats[i];
1222 + }
1223 + return NULL;
1224 +}
1225 +
1226 +static inline
1227 +struct bcm2835_codec_fmt_list *get_format_list(struct bcm2835_codec_dev *dev,
1228 + bool capture)
1229 +{
1230 + return &dev->supported_fmts[capture ? 1 : 0];
1231 +}
1232 +
1233 +static
1234 +struct bcm2835_codec_fmt *get_default_format(struct bcm2835_codec_dev *dev,
1235 + bool capture)
1236 +{
1237 + return &dev->supported_fmts[capture ? 1 : 0].list[0];
1238 +}
1239 +
1240 +static
1241 +struct bcm2835_codec_fmt *find_format_pix_fmt(u32 pix_fmt,
1242 + struct bcm2835_codec_dev *dev,
1243 + bool capture)
1244 +{
1245 + struct bcm2835_codec_fmt *fmt;
1246 + unsigned int k;
1247 + struct bcm2835_codec_fmt_list *fmts =
1248 + &dev->supported_fmts[capture ? 1 : 0];
1249 +
1250 + for (k = 0; k < fmts->num_entries; k++) {
1251 + fmt = &fmts->list[k];
1252 + if (fmt->fourcc == pix_fmt)
1253 + break;
1254 + }
1255 + if (k == fmts->num_entries)
1256 + return NULL;
1257 +
1258 + return &fmts->list[k];
1259 +}
1260 +
1261 +static inline
1262 +struct bcm2835_codec_fmt *find_format(struct v4l2_format *f,
1263 + struct bcm2835_codec_dev *dev,
1264 + bool capture)
1265 +{
1266 + return find_format_pix_fmt(f->fmt.pix_mp.pixelformat, dev, capture);
1267 +}
1268 +
1269 +static inline struct bcm2835_codec_ctx *file2ctx(struct file *file)
1270 +{
1271 + return container_of(file->private_data, struct bcm2835_codec_ctx, fh);
1272 +}
1273 +
1274 +static struct bcm2835_codec_q_data *get_q_data(struct bcm2835_codec_ctx *ctx,
1275 + enum v4l2_buf_type type)
1276 +{
1277 + switch (type) {
1278 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1279 + return &ctx->q_data[V4L2_M2M_SRC];
1280 + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1281 + return &ctx->q_data[V4L2_M2M_DST];
1282 + default:
1283 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
1284 + __func__, type);
1285 + break;
1286 + }
1287 + return NULL;
1288 +}
1289 +
1290 +static struct vchiq_mmal_port *get_port_data(struct bcm2835_codec_ctx *ctx,
1291 + enum v4l2_buf_type type)
1292 +{
1293 + if (!ctx->component)
1294 + return NULL;
1295 +
1296 + switch (type) {
1297 + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1298 + return &ctx->component->input[0];
1299 + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1300 + return &ctx->component->output[0];
1301 + default:
1302 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Invalid queue type %u\n",
1303 + __func__, type);
1304 + break;
1305 + }
1306 + return NULL;
1307 +}
1308 +
1309 +/*
1310 + * mem2mem callbacks
1311 + */
1312 +
1313 +/*
1314 + * job_ready() - check whether an instance is ready to be scheduled to run
1315 + */
1316 +static int job_ready(void *priv)
1317 +{
1318 + struct bcm2835_codec_ctx *ctx = priv;
1319 +
1320 + if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
1321 + !v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx))
1322 + return 0;
1323 +
1324 + return 1;
1325 +}
1326 +
1327 +static void job_abort(void *priv)
1328 +{
1329 + struct bcm2835_codec_ctx *ctx = priv;
1330 +
1331 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s\n", __func__);
1332 + /* Will cancel the transaction in the next interrupt handler */
1333 + ctx->aborting = 1;
1334 +}
1335 +
1336 +static inline unsigned int get_sizeimage(int bpl, int width, int height,
1337 + struct bcm2835_codec_fmt *fmt)
1338 +{
1339 + if (fmt->flags & V4L2_FMT_FLAG_COMPRESSED) {
1340 + if (fmt->fourcc == V4L2_PIX_FMT_JPEG)
1341 + return DEF_COMP_BUF_SIZE_JPEG;
1342 +
1343 + if (width * height > 1280 * 720)
1344 + return DEF_COMP_BUF_SIZE_GREATER_720P;
1345 + else
1346 + return DEF_COMP_BUF_SIZE_720P_OR_LESS;
1347 + }
1348 +
1349 + if (fmt->fourcc != V4L2_PIX_FMT_NV12_COL128)
1350 + return (bpl * height * fmt->size_multiplier_x2) >> 1;
1351 +
1352 + /*
1353 + * V4L2_PIX_FMT_NV12_COL128 is 128 pixel wide columns.
1354 + * bytesperline is the column stride in lines, so multiply by
1355 + * the number of columns and 128.
1356 + */
1357 + return (ALIGN(width, 128) * bpl);
1358 +}
1359 +
1360 +static inline unsigned int get_bytesperline(int width, int height,
1361 + struct bcm2835_codec_fmt *fmt,
1362 + enum bcm2835_codec_role role)
1363 +{
1364 + if (fmt->fourcc != V4L2_PIX_FMT_NV12_COL128)
1365 + return ALIGN((width * fmt->depth) >> 3,
1366 + fmt->bytesperline_align[role]);
1367 +
1368 + /*
1369 + * V4L2_PIX_FMT_NV12_COL128 passes the column stride in lines via
1370 + * bytesperline.
1371 + * The minimum value for this is sufficient for the base luma and chroma
1372 + * with no padding.
1373 + */
1374 + return (height * 3) >> 1;
1375 +}
1376 +
1377 +static void setup_mmal_port_format(struct bcm2835_codec_ctx *ctx,
1378 + struct bcm2835_codec_q_data *q_data,
1379 + struct vchiq_mmal_port *port)
1380 +{
1381 + port->format.encoding = q_data->fmt->mmal_fmt;
1382 + port->format.flags = 0;
1383 +
1384 + if (!(q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
1385 + if (q_data->fmt->mmal_fmt != MMAL_ENCODING_YUVUV128) {
1386 + /* Raw image format - set width/height */
1387 + port->es.video.width = (q_data->bytesperline << 3) /
1388 + q_data->fmt->depth;
1389 + port->es.video.height = q_data->height;
1390 + port->es.video.crop.width = q_data->crop_width;
1391 + port->es.video.crop.height = q_data->crop_height;
1392 + } else {
1393 + /* NV12_COL128 / YUVUV128 column format */
1394 + /* Column stride in lines */
1395 + port->es.video.width = q_data->bytesperline;
1396 + port->es.video.height = q_data->height;
1397 + port->es.video.crop.width = q_data->crop_width;
1398 + port->es.video.crop.height = q_data->crop_height;
1399 + port->format.flags = MMAL_ES_FORMAT_FLAG_COL_FMTS_WIDTH_IS_COL_STRIDE;
1400 + }
1401 + port->es.video.frame_rate.numerator = ctx->framerate_num;
1402 + port->es.video.frame_rate.denominator = ctx->framerate_denom;
1403 + } else {
1404 + /* Compressed format - leave resolution as 0 for decode */
1405 + if (ctx->dev->role == DECODE) {
1406 + port->es.video.width = 0;
1407 + port->es.video.height = 0;
1408 + port->es.video.crop.width = 0;
1409 + port->es.video.crop.height = 0;
1410 + } else {
1411 + port->es.video.width = q_data->crop_width;
1412 + port->es.video.height = q_data->height;
1413 + port->es.video.crop.width = q_data->crop_width;
1414 + port->es.video.crop.height = q_data->crop_height;
1415 + port->format.bitrate = ctx->bitrate;
1416 + port->es.video.frame_rate.numerator = ctx->framerate_num;
1417 + port->es.video.frame_rate.denominator = ctx->framerate_denom;
1418 + }
1419 + }
1420 + port->es.video.crop.x = 0;
1421 + port->es.video.crop.y = 0;
1422 +
1423 + port->current_buffer.size = q_data->sizeimage;
1424 +};
1425 +
1426 +static void ip_buffer_cb(struct vchiq_mmal_instance *instance,
1427 + struct vchiq_mmal_port *port, int status,
1428 + struct mmal_buffer *mmal_buf)
1429 +{
1430 + struct bcm2835_codec_ctx *ctx = port->cb_ctx/*, *curr_ctx*/;
1431 + struct m2m_mmal_buffer *buf =
1432 + container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
1433 +
1434 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: port %p buf %p length %lu, flags %x\n",
1435 + __func__, port, mmal_buf, mmal_buf->length,
1436 + mmal_buf->mmal_flags);
1437 +
1438 + if (buf == &ctx->q_data[V4L2_M2M_SRC].eos_buffer) {
1439 + /* Do we need to add lcoking to prevent multiple submission of
1440 + * the EOS, and therefore handle mutliple return here?
1441 + */
1442 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: eos buffer returned.\n",
1443 + __func__);
1444 + ctx->q_data[V4L2_M2M_SRC].eos_buffer_in_use = false;
1445 + return;
1446 + }
1447 +
1448 + if (status) {
1449 + /* error in transfer */
1450 + if (buf)
1451 + /* there was a buffer with the error so return it */
1452 + vb2_buffer_done(&buf->m2m.vb.vb2_buf,
1453 + VB2_BUF_STATE_ERROR);
1454 + return;
1455 + }
1456 + if (mmal_buf->cmd) {
1457 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Not expecting cmd msgs on ip callback - %08x\n",
1458 + __func__, mmal_buf->cmd);
1459 + /*
1460 + * CHECKME: Should we return here. The buffer shouldn't have a
1461 + * message context or vb2 buf associated.
1462 + */
1463 + }
1464 +
1465 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: no error. Return buffer %p\n",
1466 + __func__, &buf->m2m.vb.vb2_buf);
1467 + vb2_buffer_done(&buf->m2m.vb.vb2_buf,
1468 + port->enabled ? VB2_BUF_STATE_DONE :
1469 + VB2_BUF_STATE_QUEUED);
1470 +
1471 + ctx->num_ip_buffers++;
1472 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d input buffers\n",
1473 + __func__, ctx->num_ip_buffers);
1474 +
1475 + if (!port->enabled && atomic_read(&port->buffers_with_vpu))
1476 + complete(&ctx->frame_cmplt);
1477 +}
1478 +
1479 +static void queue_res_chg_event(struct bcm2835_codec_ctx *ctx)
1480 +{
1481 + static const struct v4l2_event ev_src_ch = {
1482 + .type = V4L2_EVENT_SOURCE_CHANGE,
1483 + .u.src_change.changes =
1484 + V4L2_EVENT_SRC_CH_RESOLUTION,
1485 + };
1486 +
1487 + v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
1488 +}
1489 +
1490 +static void send_eos_event(struct bcm2835_codec_ctx *ctx)
1491 +{
1492 + static const struct v4l2_event ev = {
1493 + .type = V4L2_EVENT_EOS,
1494 + };
1495 +
1496 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Sending EOS event\n");
1497 +
1498 + v4l2_event_queue_fh(&ctx->fh, &ev);
1499 +}
1500 +
1501 +static void color_mmal2v4l(struct bcm2835_codec_ctx *ctx, u32 encoding,
1502 + u32 color_space)
1503 +{
1504 + int is_rgb;
1505 +
1506 + switch (encoding) {
1507 + case MMAL_ENCODING_I420:
1508 + case MMAL_ENCODING_YV12:
1509 + case MMAL_ENCODING_NV12:
1510 + case MMAL_ENCODING_NV21:
1511 + case V4L2_PIX_FMT_YUYV:
1512 + case V4L2_PIX_FMT_YVYU:
1513 + case V4L2_PIX_FMT_UYVY:
1514 + case V4L2_PIX_FMT_VYUY:
1515 + /* YUV based colourspaces */
1516 + switch (color_space) {
1517 + case MMAL_COLOR_SPACE_ITUR_BT601:
1518 + ctx->colorspace = V4L2_COLORSPACE_SMPTE170M;
1519 + break;
1520 +
1521 + case MMAL_COLOR_SPACE_ITUR_BT709:
1522 + ctx->colorspace = V4L2_COLORSPACE_REC709;
1523 + break;
1524 + default:
1525 + break;
1526 + }
1527 + break;
1528 + default:
1529 + /* RGB based colourspaces */
1530 + ctx->colorspace = V4L2_COLORSPACE_SRGB;
1531 + break;
1532 + }
1533 + ctx->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(ctx->colorspace);
1534 + ctx->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(ctx->colorspace);
1535 + is_rgb = ctx->colorspace == V4L2_COLORSPACE_SRGB;
1536 + ctx->quant = V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, ctx->colorspace,
1537 + ctx->ycbcr_enc);
1538 +}
1539 +
1540 +static void handle_fmt_changed(struct bcm2835_codec_ctx *ctx,
1541 + struct mmal_buffer *mmal_buf)
1542 +{
1543 + struct bcm2835_codec_q_data *q_data;
1544 + struct mmal_msg_event_format_changed *format =
1545 + (struct mmal_msg_event_format_changed *)mmal_buf->buffer;
1546 + struct mmal_parameter_video_interlace_type interlace;
1547 + int interlace_size = sizeof(interlace);
1548 + struct vb2_queue *vq;
1549 + int ret;
1550 +
1551 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed: buff size min %u, rec %u, buff num min %u, rec %u\n",
1552 + __func__,
1553 + format->buffer_size_min,
1554 + format->buffer_size_recommended,
1555 + format->buffer_num_min,
1556 + format->buffer_num_recommended
1557 + );
1558 + if (format->format.type != MMAL_ES_TYPE_VIDEO) {
1559 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed but not video %u\n",
1560 + __func__, format->format.type);
1561 + return;
1562 + }
1563 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format changed to %ux%u, crop %ux%u, colourspace %08X\n",
1564 + __func__, format->es.video.width, format->es.video.height,
1565 + format->es.video.crop.width, format->es.video.crop.height,
1566 + format->es.video.color_space);
1567 +
1568 + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1569 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Format was %ux%u, crop %ux%u\n",
1570 + __func__, q_data->bytesperline, q_data->height,
1571 + q_data->crop_width, q_data->crop_height);
1572 +
1573 + q_data->crop_width = format->es.video.crop.width;
1574 + q_data->crop_height = format->es.video.crop.height;
1575 + /*
1576 + * Stop S_FMT updating crop_height should it be unaligned.
1577 + * Client can still update the crop region via S_SELECTION should it
1578 + * really want to, but the decoder is likely to complain that the
1579 + * format then doesn't match.
1580 + */
1581 + q_data->selection_set = true;
1582 + q_data->bytesperline = get_bytesperline(format->es.video.width,
1583 + format->es.video.height,
1584 + q_data->fmt, ctx->dev->role);
1585 +
1586 + q_data->height = format->es.video.height;
1587 + q_data->sizeimage = format->buffer_size_min;
1588 + if (format->es.video.color_space)
1589 + color_mmal2v4l(ctx, format->format.encoding,
1590 + format->es.video.color_space);
1591 +
1592 + q_data->aspect_ratio.numerator = format->es.video.par.numerator;
1593 + q_data->aspect_ratio.denominator = format->es.video.par.denominator;
1594 +
1595 + ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
1596 + &ctx->component->output[0],
1597 + MMAL_PARAMETER_VIDEO_INTERLACE_TYPE,
1598 + &interlace,
1599 + &interlace_size);
1600 + if (!ret) {
1601 + switch (interlace.mode) {
1602 + case MMAL_INTERLACE_PROGRESSIVE:
1603 + default:
1604 + q_data->field = V4L2_FIELD_NONE;
1605 + break;
1606 + case MMAL_INTERLACE_FIELDS_INTERLEAVED_UPPER_FIRST:
1607 + q_data->field = V4L2_FIELD_INTERLACED_TB;
1608 + break;
1609 + case MMAL_INTERLACE_FIELDS_INTERLEAVED_LOWER_FIRST:
1610 + q_data->field = V4L2_FIELD_INTERLACED_BT;
1611 + break;
1612 + }
1613 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: interlace mode %u, v4l2 field %u\n",
1614 + __func__, interlace.mode, q_data->field);
1615 + } else {
1616 + q_data->field = V4L2_FIELD_NONE;
1617 + }
1618 +
1619 + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1620 + if (vq->streaming)
1621 + vq->last_buffer_dequeued = true;
1622 +
1623 + queue_res_chg_event(ctx);
1624 +}
1625 +
1626 +static void op_buffer_cb(struct vchiq_mmal_instance *instance,
1627 + struct vchiq_mmal_port *port, int status,
1628 + struct mmal_buffer *mmal_buf)
1629 +{
1630 + struct bcm2835_codec_ctx *ctx = port->cb_ctx;
1631 + enum vb2_buffer_state buf_state = VB2_BUF_STATE_DONE;
1632 + struct m2m_mmal_buffer *buf;
1633 + struct vb2_v4l2_buffer *vb2;
1634 +
1635 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev,
1636 + "%s: status:%d, buf:%p, length:%lu, flags %04x, pts %lld\n",
1637 + __func__, status, mmal_buf, mmal_buf->length,
1638 + mmal_buf->mmal_flags, mmal_buf->pts);
1639 +
1640 + buf = container_of(mmal_buf, struct m2m_mmal_buffer, mmal);
1641 + vb2 = &buf->m2m.vb;
1642 +
1643 + if (status) {
1644 + /* error in transfer */
1645 + if (vb2) {
1646 + /* there was a buffer with the error so return it */
1647 + vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_ERROR);
1648 + }
1649 + return;
1650 + }
1651 +
1652 + if (mmal_buf->cmd) {
1653 + switch (mmal_buf->cmd) {
1654 + case MMAL_EVENT_FORMAT_CHANGED:
1655 + {
1656 + handle_fmt_changed(ctx, mmal_buf);
1657 + break;
1658 + }
1659 + default:
1660 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Unexpected event on output callback - %08x\n",
1661 + __func__, mmal_buf->cmd);
1662 + break;
1663 + }
1664 + return;
1665 + }
1666 +
1667 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: length %lu, flags %x, idx %u\n",
1668 + __func__, mmal_buf->length, mmal_buf->mmal_flags,
1669 + vb2->vb2_buf.index);
1670 +
1671 + if (mmal_buf->length == 0) {
1672 + /* stream ended, or buffer being returned during disable. */
1673 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: Empty buffer - flags %04x",
1674 + __func__, mmal_buf->mmal_flags);
1675 + if (!(mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS)) {
1676 + if (!port->enabled) {
1677 + vb2_buffer_done(&vb2->vb2_buf, VB2_BUF_STATE_QUEUED);
1678 + if (atomic_read(&port->buffers_with_vpu))
1679 + complete(&ctx->frame_cmplt);
1680 + } else {
1681 + vchiq_mmal_submit_buffer(ctx->dev->instance,
1682 + &ctx->component->output[0],
1683 + mmal_buf);
1684 + }
1685 + return;
1686 + }
1687 + }
1688 + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS) {
1689 + /* EOS packet from the VPU */
1690 + send_eos_event(ctx);
1691 + vb2->flags |= V4L2_BUF_FLAG_LAST;
1692 + }
1693 +
1694 + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_CORRUPTED)
1695 + buf_state = VB2_BUF_STATE_ERROR;
1696 +
1697 + /* vb2 timestamps in nsecs, mmal in usecs */
1698 + vb2->vb2_buf.timestamp = mmal_buf->pts * 1000;
1699 +
1700 + vb2_set_plane_payload(&vb2->vb2_buf, 0, mmal_buf->length);
1701 + switch (mmal_buf->mmal_flags &
1702 + (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
1703 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST)) {
1704 + case 0:
1705 + case MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST: /* Bogus */
1706 + vb2->field = V4L2_FIELD_NONE;
1707 + break;
1708 + case MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED:
1709 + vb2->field = V4L2_FIELD_INTERLACED_BT;
1710 + break;
1711 + case (MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
1712 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST):
1713 + vb2->field = V4L2_FIELD_INTERLACED_TB;
1714 + break;
1715 + }
1716 +
1717 + if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
1718 + vb2->flags |= V4L2_BUF_FLAG_KEYFRAME;
1719 +
1720 + vb2_buffer_done(&vb2->vb2_buf, buf_state);
1721 + ctx->num_op_buffers++;
1722 +
1723 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: done %d output buffers\n",
1724 + __func__, ctx->num_op_buffers);
1725 +
1726 + if (!port->enabled && atomic_read(&port->buffers_with_vpu))
1727 + complete(&ctx->frame_cmplt);
1728 +}
1729 +
1730 +/* vb2_to_mmal_buffer() - converts vb2 buffer header to MMAL
1731 + *
1732 + * Copies all the required fields from a VB2 buffer to the MMAL buffer header,
1733 + * ready for sending to the VPU.
1734 + */
1735 +static void vb2_to_mmal_buffer(struct m2m_mmal_buffer *buf,
1736 + struct vb2_v4l2_buffer *vb2)
1737 +{
1738 + u64 pts;
1739 +
1740 + buf->mmal.mmal_flags = 0;
1741 + if (vb2->flags & V4L2_BUF_FLAG_KEYFRAME)
1742 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_KEYFRAME;
1743 +
1744 + /*
1745 + * Adding this means that the data must be framed correctly as one frame
1746 + * per buffer. The underlying decoder has no such requirement, but it
1747 + * will reduce latency as the bistream parser will be kicked immediately
1748 + * to parse the frame, rather than relying on its own heuristics for
1749 + * when to wake up.
1750 + */
1751 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
1752 +
1753 + buf->mmal.length = vb2->vb2_buf.planes[0].bytesused;
1754 + /*
1755 + * Minor ambiguity in the V4L2 spec as to whether passing in a 0 length
1756 + * buffer, or one with V4L2_BUF_FLAG_LAST set denotes end of stream.
1757 + * Handle either.
1758 + */
1759 + if (!buf->mmal.length || vb2->flags & V4L2_BUF_FLAG_LAST)
1760 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
1761 +
1762 + /* vb2 timestamps in nsecs, mmal in usecs */
1763 + pts = vb2->vb2_buf.timestamp;
1764 + do_div(pts, 1000);
1765 + buf->mmal.pts = pts;
1766 + buf->mmal.dts = MMAL_TIME_UNKNOWN;
1767 +
1768 + switch (field_override ? field_override : vb2->field) {
1769 + default:
1770 + case V4L2_FIELD_NONE:
1771 + break;
1772 + case V4L2_FIELD_INTERLACED_BT:
1773 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED;
1774 + break;
1775 + case V4L2_FIELD_INTERLACED_TB:
1776 + buf->mmal.mmal_flags |= MMAL_BUFFER_HEADER_VIDEO_FLAG_INTERLACED |
1777 + MMAL_BUFFER_HEADER_VIDEO_FLAG_TOP_FIELD_FIRST;
1778 + break;
1779 + }
1780 +}
1781 +
1782 +/* device_run() - prepares and starts the device
1783 + *
1784 + * This simulates all the immediate preparations required before starting
1785 + * a device. This will be called by the framework when it decides to schedule
1786 + * a particular instance.
1787 + */
1788 +static void device_run(void *priv)
1789 +{
1790 + struct bcm2835_codec_ctx *ctx = priv;
1791 + struct bcm2835_codec_dev *dev = ctx->dev;
1792 + struct vb2_v4l2_buffer *src_buf, *dst_buf;
1793 + struct m2m_mmal_buffer *src_m2m_buf = NULL, *dst_m2m_buf = NULL;
1794 + struct v4l2_m2m_buffer *m2m;
1795 + int ret;
1796 +
1797 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: off we go\n", __func__);
1798 +
1799 + if (ctx->fh.m2m_ctx->out_q_ctx.q.streaming) {
1800 + src_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->out_q_ctx);
1801 + if (src_buf) {
1802 + m2m = container_of(src_buf, struct v4l2_m2m_buffer, vb);
1803 + src_m2m_buf = container_of(m2m, struct m2m_mmal_buffer,
1804 + m2m);
1805 + vb2_to_mmal_buffer(src_m2m_buf, src_buf);
1806 +
1807 + ret = vchiq_mmal_submit_buffer(dev->instance,
1808 + &ctx->component->input[0],
1809 + &src_m2m_buf->mmal);
1810 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev,
1811 + "%s: Submitted ip buffer len %lu, pts %llu, flags %04x\n",
1812 + __func__, src_m2m_buf->mmal.length,
1813 + src_m2m_buf->mmal.pts,
1814 + src_m2m_buf->mmal.mmal_flags);
1815 + if (ret)
1816 + v4l2_err(&ctx->dev->v4l2_dev,
1817 + "%s: Failed submitting ip buffer\n",
1818 + __func__);
1819 + }
1820 + }
1821 +
1822 + if (ctx->fh.m2m_ctx->cap_q_ctx.q.streaming) {
1823 + dst_buf = v4l2_m2m_buf_remove(&ctx->fh.m2m_ctx->cap_q_ctx);
1824 + if (dst_buf) {
1825 + m2m = container_of(dst_buf, struct v4l2_m2m_buffer, vb);
1826 + dst_m2m_buf = container_of(m2m, struct m2m_mmal_buffer,
1827 + m2m);
1828 + vb2_to_mmal_buffer(dst_m2m_buf, dst_buf);
1829 +
1830 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev,
1831 + "%s: Submitted op buffer\n", __func__);
1832 + ret = vchiq_mmal_submit_buffer(dev->instance,
1833 + &ctx->component->output[0],
1834 + &dst_m2m_buf->mmal);
1835 + if (ret)
1836 + v4l2_err(&ctx->dev->v4l2_dev,
1837 + "%s: Failed submitting op buffer\n",
1838 + __func__);
1839 + }
1840 + }
1841 +
1842 + v4l2_dbg(3, debug, &ctx->dev->v4l2_dev, "%s: Submitted src %p, dst %p\n",
1843 + __func__, src_m2m_buf, dst_m2m_buf);
1844 +
1845 + /* Complete the job here. */
1846 + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
1847 +}
1848 +
1849 +/*
1850 + * video ioctls
1851 + */
1852 +static int vidioc_querycap(struct file *file, void *priv,
1853 + struct v4l2_capability *cap)
1854 +{
1855 + struct bcm2835_codec_dev *dev = video_drvdata(file);
1856 +
1857 + strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
1858 + strncpy(cap->card, dev->vfd.name, sizeof(cap->card) - 1);
1859 + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
1860 + MEM2MEM_NAME);
1861 + return 0;
1862 +}
1863 +
1864 +static int enum_fmt(struct v4l2_fmtdesc *f, struct bcm2835_codec_ctx *ctx,
1865 + bool capture)
1866 +{
1867 + struct bcm2835_codec_fmt *fmt;
1868 + struct bcm2835_codec_fmt_list *fmts =
1869 + get_format_list(ctx->dev, capture);
1870 +
1871 + if (f->index < fmts->num_entries) {
1872 + /* Format found */
1873 + fmt = &fmts->list[f->index];
1874 + f->pixelformat = fmt->fourcc;
1875 + f->flags = fmt->flags;
1876 + return 0;
1877 + }
1878 +
1879 + /* Format not found */
1880 + return -EINVAL;
1881 +}
1882 +
1883 +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1884 + struct v4l2_fmtdesc *f)
1885 +{
1886 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1887 +
1888 + return enum_fmt(f, ctx, true);
1889 +}
1890 +
1891 +static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
1892 + struct v4l2_fmtdesc *f)
1893 +{
1894 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
1895 +
1896 + return enum_fmt(f, ctx, false);
1897 +}
1898 +
1899 +static int vidioc_g_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f)
1900 +{
1901 + struct vb2_queue *vq;
1902 + struct bcm2835_codec_q_data *q_data;
1903 +
1904 + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
1905 + if (!vq)
1906 + return -EINVAL;
1907 +
1908 + q_data = get_q_data(ctx, f->type);
1909 +
1910 + f->fmt.pix_mp.width = q_data->crop_width;
1911 + f->fmt.pix_mp.height = q_data->height;
1912 + f->fmt.pix_mp.pixelformat = q_data->fmt->fourcc;
1913 + f->fmt.pix_mp.field = q_data->field;
1914 + f->fmt.pix_mp.colorspace = ctx->colorspace;
1915 + f->fmt.pix_mp.plane_fmt[0].sizeimage = q_data->sizeimage;
1916 + f->fmt.pix_mp.plane_fmt[0].bytesperline = q_data->bytesperline;
1917 + f->fmt.pix_mp.num_planes = 1;
1918 + f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
1919 + f->fmt.pix_mp.quantization = ctx->quant;
1920 + f->fmt.pix_mp.xfer_func = ctx->xfer_func;
1921 +
1922 + memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
1923 + sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
1924 +
1925 + return 0;
1926 +}
1927 +
1928 +static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
1929 + struct v4l2_format *f)
1930 +{
1931 + return vidioc_g_fmt(file2ctx(file), f);
1932 +}
1933 +
1934 +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1935 + struct v4l2_format *f)
1936 +{
1937 + return vidioc_g_fmt(file2ctx(file), f);
1938 +}
1939 +
1940 +static int vidioc_try_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
1941 + struct bcm2835_codec_fmt *fmt)
1942 +{
1943 + unsigned int sizeimage, min_bytesperline;
1944 +
1945 + /*
1946 + * The V4L2 specification requires the driver to correct the format
1947 + * struct if any of the dimensions is unsupported
1948 + */
1949 + if (f->fmt.pix_mp.width > MAX_W)
1950 + f->fmt.pix_mp.width = MAX_W;
1951 + if (f->fmt.pix_mp.height > MAX_H)
1952 + f->fmt.pix_mp.height = MAX_H;
1953 +
1954 + if (!(fmt->flags & V4L2_FMT_FLAG_COMPRESSED)) {
1955 + /* Only clip min w/h on capture. Treat 0x0 as unknown. */
1956 + if (f->fmt.pix_mp.width < MIN_W)
1957 + f->fmt.pix_mp.width = MIN_W;
1958 + if (f->fmt.pix_mp.height < MIN_H)
1959 + f->fmt.pix_mp.height = MIN_H;
1960 +
1961 + /*
1962 + * For decoders and image encoders the buffer must have
1963 + * a vertical alignment of 16 lines.
1964 + * The selection will reflect any cropping rectangle when only
1965 + * some of the pixels are active.
1966 + */
1967 + if (ctx->dev->role == DECODE || ctx->dev->role == ENCODE_IMAGE)
1968 + f->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
1969 + }
1970 + f->fmt.pix_mp.num_planes = 1;
1971 + min_bytesperline = get_bytesperline(f->fmt.pix_mp.width,
1972 + f->fmt.pix_mp.height,
1973 + fmt, ctx->dev->role);
1974 + if (f->fmt.pix_mp.plane_fmt[0].bytesperline < min_bytesperline)
1975 + f->fmt.pix_mp.plane_fmt[0].bytesperline = min_bytesperline;
1976 + f->fmt.pix_mp.plane_fmt[0].bytesperline =
1977 + ALIGN(f->fmt.pix_mp.plane_fmt[0].bytesperline,
1978 + fmt->bytesperline_align[ctx->dev->role]);
1979 +
1980 + sizeimage = get_sizeimage(f->fmt.pix_mp.plane_fmt[0].bytesperline,
1981 + f->fmt.pix_mp.width, f->fmt.pix_mp.height,
1982 + fmt);
1983 + /*
1984 + * Drivers must set sizeimage for uncompressed formats
1985 + * Compressed formats allow the client to request an alternate
1986 + * size for the buffer.
1987 + */
1988 + if (!(fmt->flags & V4L2_FMT_FLAG_COMPRESSED) ||
1989 + f->fmt.pix_mp.plane_fmt[0].sizeimage < sizeimage)
1990 + f->fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage;
1991 +
1992 + memset(f->fmt.pix_mp.plane_fmt[0].reserved, 0,
1993 + sizeof(f->fmt.pix_mp.plane_fmt[0].reserved));
1994 +
1995 + if (ctx->dev->role == DECODE || ctx->dev->role == DEINTERLACE) {
1996 + switch (f->fmt.pix_mp.field) {
1997 + /*
1998 + * All of this is pretty much guesswork as we'll set the
1999 + * interlace format correctly come format changed, and signal
2000 + * it appropriately on each buffer.
2001 + */
2002 + default:
2003 + case V4L2_FIELD_NONE:
2004 + case V4L2_FIELD_ANY:
2005 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
2006 + break;
2007 + case V4L2_FIELD_INTERLACED:
2008 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED;
2009 + break;
2010 + case V4L2_FIELD_TOP:
2011 + case V4L2_FIELD_BOTTOM:
2012 + case V4L2_FIELD_INTERLACED_TB:
2013 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_TB;
2014 + break;
2015 + case V4L2_FIELD_INTERLACED_BT:
2016 + f->fmt.pix_mp.field = V4L2_FIELD_INTERLACED_BT;
2017 + break;
2018 + }
2019 + } else {
2020 + f->fmt.pix_mp.field = V4L2_FIELD_NONE;
2021 + }
2022 +
2023 + return 0;
2024 +}
2025 +
2026 +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
2027 + struct v4l2_format *f)
2028 +{
2029 + struct bcm2835_codec_fmt *fmt;
2030 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2031 +
2032 + fmt = find_format(f, ctx->dev, true);
2033 + if (!fmt) {
2034 + f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
2035 + true)->fourcc;
2036 + fmt = find_format(f, ctx->dev, true);
2037 + }
2038 +
2039 + return vidioc_try_fmt(ctx, f, fmt);
2040 +}
2041 +
2042 +static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
2043 + struct v4l2_format *f)
2044 +{
2045 + struct bcm2835_codec_fmt *fmt;
2046 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2047 +
2048 + fmt = find_format(f, ctx->dev, false);
2049 + if (!fmt) {
2050 + f->fmt.pix_mp.pixelformat = get_default_format(ctx->dev,
2051 + false)->fourcc;
2052 + fmt = find_format(f, ctx->dev, false);
2053 + }
2054 +
2055 + if (!f->fmt.pix_mp.colorspace)
2056 + f->fmt.pix_mp.colorspace = ctx->colorspace;
2057 +
2058 + return vidioc_try_fmt(ctx, f, fmt);
2059 +}
2060 +
2061 +static int vidioc_s_fmt(struct bcm2835_codec_ctx *ctx, struct v4l2_format *f,
2062 + unsigned int requested_height)
2063 +{
2064 + struct bcm2835_codec_q_data *q_data;
2065 + struct vb2_queue *vq;
2066 + struct vchiq_mmal_port *port;
2067 + bool update_capture_port = false;
2068 + bool reenable_port = false;
2069 + int ret;
2070 +
2071 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
2072 + f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
2073 + f->fmt.pix_mp.pixelformat,
2074 + f->fmt.pix_mp.plane_fmt[0].sizeimage);
2075 +
2076 + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
2077 + if (!vq)
2078 + return -EINVAL;
2079 +
2080 + q_data = get_q_data(ctx, f->type);
2081 + if (!q_data)
2082 + return -EINVAL;
2083 +
2084 + if (vb2_is_busy(vq)) {
2085 + v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
2086 + return -EBUSY;
2087 + }
2088 +
2089 + q_data->fmt = find_format(f, ctx->dev,
2090 + f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
2091 + q_data->crop_width = f->fmt.pix_mp.width;
2092 + q_data->height = f->fmt.pix_mp.height;
2093 + if (!q_data->selection_set ||
2094 + (q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED))
2095 + q_data->crop_height = requested_height;
2096 +
2097 + /*
2098 + * Copying the behaviour of vicodec which retains a single set of
2099 + * colorspace parameters for both input and output.
2100 + */
2101 + ctx->colorspace = f->fmt.pix_mp.colorspace;
2102 + ctx->xfer_func = f->fmt.pix_mp.xfer_func;
2103 + ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
2104 + ctx->quant = f->fmt.pix_mp.quantization;
2105 +
2106 + q_data->field = f->fmt.pix_mp.field;
2107 +
2108 + /* All parameters should have been set correctly by try_fmt */
2109 + q_data->bytesperline = f->fmt.pix_mp.plane_fmt[0].bytesperline;
2110 + q_data->sizeimage = f->fmt.pix_mp.plane_fmt[0].sizeimage;
2111 +
2112 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Calculated bpl as %u, size %u\n",
2113 + q_data->bytesperline, q_data->sizeimage);
2114 +
2115 + if ((ctx->dev->role == DECODE || ctx->dev->role == ENCODE_IMAGE) &&
2116 + q_data->fmt->flags & V4L2_FMT_FLAG_COMPRESSED &&
2117 + q_data->crop_width && q_data->height) {
2118 + /*
2119 + * On the decoder or image encoder, if provided with
2120 + * a resolution on the input side, then replicate that
2121 + * to the output side.
2122 + * GStreamer appears not to support V4L2_EVENT_SOURCE_CHANGE,
2123 + * nor set up a resolution on the output side, therefore
2124 + * we can't decode anything at a resolution other than the
2125 + * default one.
2126 + */
2127 + struct bcm2835_codec_q_data *q_data_dst =
2128 + &ctx->q_data[V4L2_M2M_DST];
2129 +
2130 + q_data_dst->crop_width = q_data->crop_width;
2131 + q_data_dst->crop_height = q_data->crop_height;
2132 + q_data_dst->height = ALIGN(q_data->crop_height, 16);
2133 +
2134 + q_data_dst->bytesperline =
2135 + get_bytesperline(f->fmt.pix_mp.width,
2136 + f->fmt.pix_mp.height,
2137 + q_data_dst->fmt, ctx->dev->role);
2138 + q_data_dst->sizeimage = get_sizeimage(q_data_dst->bytesperline,
2139 + q_data_dst->crop_width,
2140 + q_data_dst->height,
2141 + q_data_dst->fmt);
2142 + update_capture_port = true;
2143 + }
2144 +
2145 + /* If we have a component then setup the port as well */
2146 + port = get_port_data(ctx, vq->type);
2147 + if (!port)
2148 + return 0;
2149 +
2150 + if (port->enabled) {
2151 + unsigned int num_buffers;
2152 +
2153 + /*
2154 + * This should only ever happen with DECODE and the MMAL output
2155 + * port that has been enabled for resolution changed events.
2156 + * In this case no buffers have been allocated or sent to the
2157 + * component, so warn on that.
2158 + */
2159 + WARN_ON(ctx->dev->role != DECODE ||
2160 + f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
2161 + atomic_read(&port->buffers_with_vpu));
2162 +
2163 + /*
2164 + * Disable will reread the port format, so retain buffer count.
2165 + */
2166 + num_buffers = port->current_buffer.num;
2167 +
2168 + ret = vchiq_mmal_port_disable(ctx->dev->instance, port);
2169 + if (ret)
2170 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error disabling port update buffer count, ret %d\n",
2171 + __func__, ret);
2172 +
2173 + port->current_buffer.num = num_buffers;
2174 +
2175 + reenable_port = true;
2176 + }
2177 +
2178 + setup_mmal_port_format(ctx, q_data, port);
2179 + ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
2180 + if (ret) {
2181 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
2182 + __func__, ret);
2183 + ret = -EINVAL;
2184 + }
2185 +
2186 + if (q_data->sizeimage < port->minimum_buffer.size) {
2187 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Current buffer size of %u < min buf size %u - driver mismatch to MMAL\n",
2188 + __func__, q_data->sizeimage,
2189 + port->minimum_buffer.size);
2190 + }
2191 +
2192 + if (reenable_port) {
2193 + ret = vchiq_mmal_port_enable(ctx->dev->instance,
2194 + port,
2195 + op_buffer_cb);
2196 + if (ret)
2197 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
2198 + __func__, ret);
2199 + }
2200 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "Set format for type %d, wxh: %dx%d, fmt: %08x, size %u\n",
2201 + f->type, q_data->crop_width, q_data->height,
2202 + q_data->fmt->fourcc, q_data->sizeimage);
2203 +
2204 + if (update_capture_port) {
2205 + struct vchiq_mmal_port *port_dst = &ctx->component->output[0];
2206 + struct bcm2835_codec_q_data *q_data_dst =
2207 + &ctx->q_data[V4L2_M2M_DST];
2208 +
2209 + setup_mmal_port_format(ctx, q_data_dst, port_dst);
2210 + ret = vchiq_mmal_port_set_format(ctx->dev->instance, port_dst);
2211 + if (ret) {
2212 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on output port, ret %d\n",
2213 + __func__, ret);
2214 + ret = -EINVAL;
2215 + }
2216 + }
2217 + return ret;
2218 +}
2219 +
2220 +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
2221 + struct v4l2_format *f)
2222 +{
2223 + unsigned int height = f->fmt.pix_mp.height;
2224 + int ret;
2225 +
2226 + ret = vidioc_try_fmt_vid_cap(file, priv, f);
2227 + if (ret)
2228 + return ret;
2229 +
2230 + return vidioc_s_fmt(file2ctx(file), f, height);
2231 +}
2232 +
2233 +static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
2234 + struct v4l2_format *f)
2235 +{
2236 + unsigned int height = f->fmt.pix_mp.height;
2237 + int ret;
2238 +
2239 + ret = vidioc_try_fmt_vid_out(file, priv, f);
2240 + if (ret)
2241 + return ret;
2242 +
2243 + ret = vidioc_s_fmt(file2ctx(file), f, height);
2244 + return ret;
2245 +}
2246 +
2247 +static int vidioc_g_selection(struct file *file, void *priv,
2248 + struct v4l2_selection *s)
2249 +{
2250 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2251 + struct bcm2835_codec_q_data *q_data;
2252 +
2253 + /*
2254 + * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
2255 + * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
2256 + * API. The V4L2 core will have converted the MPLANE variants to
2257 + * non-MPLANE.
2258 + * Open code this instead of using get_q_data in this case.
2259 + */
2260 + switch (s->type) {
2261 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2262 + /* CAPTURE on encoder is not valid. */
2263 + if (ctx->dev->role == ENCODE || ctx->dev->role == ENCODE_IMAGE)
2264 + return -EINVAL;
2265 + q_data = &ctx->q_data[V4L2_M2M_DST];
2266 + break;
2267 + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2268 + /* OUTPUT on deoder is not valid. */
2269 + if (ctx->dev->role == DECODE)
2270 + return -EINVAL;
2271 + q_data = &ctx->q_data[V4L2_M2M_SRC];
2272 + break;
2273 + default:
2274 + return -EINVAL;
2275 + }
2276 +
2277 + switch (ctx->dev->role) {
2278 + case DECODE:
2279 + switch (s->target) {
2280 + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
2281 + case V4L2_SEL_TGT_COMPOSE:
2282 + s->r.left = 0;
2283 + s->r.top = 0;
2284 + s->r.width = q_data->crop_width;
2285 + s->r.height = q_data->crop_height;
2286 + break;
2287 + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
2288 + s->r.left = 0;
2289 + s->r.top = 0;
2290 + s->r.width = q_data->crop_width;
2291 + s->r.height = q_data->crop_height;
2292 + break;
2293 + case V4L2_SEL_TGT_CROP_BOUNDS:
2294 + case V4L2_SEL_TGT_CROP_DEFAULT:
2295 + s->r.left = 0;
2296 + s->r.top = 0;
2297 + s->r.width = (q_data->bytesperline << 3) /
2298 + q_data->fmt->depth;
2299 + s->r.height = q_data->height;
2300 + break;
2301 + default:
2302 + return -EINVAL;
2303 + }
2304 + break;
2305 + case ENCODE:
2306 + case ENCODE_IMAGE:
2307 + switch (s->target) {
2308 + case V4L2_SEL_TGT_CROP_DEFAULT:
2309 + case V4L2_SEL_TGT_CROP_BOUNDS:
2310 + s->r.top = 0;
2311 + s->r.left = 0;
2312 + s->r.width = q_data->bytesperline;
2313 + s->r.height = q_data->height;
2314 + break;
2315 + case V4L2_SEL_TGT_CROP:
2316 + s->r.top = 0;
2317 + s->r.left = 0;
2318 + s->r.width = q_data->crop_width;
2319 + s->r.height = q_data->crop_height;
2320 + break;
2321 + default:
2322 + return -EINVAL;
2323 + }
2324 + break;
2325 + case ISP:
2326 + break;
2327 + case DEINTERLACE:
2328 + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2329 + switch (s->target) {
2330 + case V4L2_SEL_TGT_COMPOSE_DEFAULT:
2331 + case V4L2_SEL_TGT_COMPOSE:
2332 + s->r.left = 0;
2333 + s->r.top = 0;
2334 + s->r.width = q_data->crop_width;
2335 + s->r.height = q_data->crop_height;
2336 + break;
2337 + case V4L2_SEL_TGT_COMPOSE_BOUNDS:
2338 + s->r.left = 0;
2339 + s->r.top = 0;
2340 + s->r.width = q_data->crop_width;
2341 + s->r.height = q_data->crop_height;
2342 + break;
2343 + default:
2344 + return -EINVAL;
2345 + }
2346 + } else {
2347 + /* must be V4L2_BUF_TYPE_VIDEO_OUTPUT */
2348 + switch (s->target) {
2349 + case V4L2_SEL_TGT_CROP_DEFAULT:
2350 + case V4L2_SEL_TGT_CROP_BOUNDS:
2351 + s->r.top = 0;
2352 + s->r.left = 0;
2353 + s->r.width = q_data->bytesperline;
2354 + s->r.height = q_data->height;
2355 + break;
2356 + case V4L2_SEL_TGT_CROP:
2357 + s->r.top = 0;
2358 + s->r.left = 0;
2359 + s->r.width = q_data->crop_width;
2360 + s->r.height = q_data->crop_height;
2361 + break;
2362 + default:
2363 + return -EINVAL;
2364 + }
2365 + }
2366 + break;
2367 + case NUM_ROLES:
2368 + break;
2369 + }
2370 +
2371 + return 0;
2372 +}
2373 +
2374 +static int vidioc_s_selection(struct file *file, void *priv,
2375 + struct v4l2_selection *s)
2376 +{
2377 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2378 + struct bcm2835_codec_q_data *q_data = NULL;
2379 + struct vchiq_mmal_port *port = NULL;
2380 + int ret;
2381 +
2382 + /*
2383 + * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
2384 + * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
2385 + * API. The V4L2 core will have converted the MPLANE variants to
2386 + * non-MPLANE.
2387 + *
2388 + * Open code this instead of using get_q_data in this case.
2389 + */
2390 + switch (s->type) {
2391 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2392 + /* CAPTURE on encoder is not valid. */
2393 + if (ctx->dev->role == ENCODE || ctx->dev->role == ENCODE_IMAGE)
2394 + return -EINVAL;
2395 + q_data = &ctx->q_data[V4L2_M2M_DST];
2396 + if (ctx->component)
2397 + port = &ctx->component->output[0];
2398 + break;
2399 + case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2400 + /* OUTPUT on deoder is not valid. */
2401 + if (ctx->dev->role == DECODE)
2402 + return -EINVAL;
2403 + q_data = &ctx->q_data[V4L2_M2M_SRC];
2404 + if (ctx->component)
2405 + port = &ctx->component->input[0];
2406 + break;
2407 + default:
2408 + return -EINVAL;
2409 + }
2410 +
2411 + 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",
2412 + __func__, ctx, s->type, q_data, s->target, s->r.left, s->r.top,
2413 + s->r.width, s->r.height);
2414 +
2415 + switch (ctx->dev->role) {
2416 + case DECODE:
2417 + switch (s->target) {
2418 + case V4L2_SEL_TGT_COMPOSE:
2419 + /* Accept cropped image */
2420 + s->r.left = 0;
2421 + s->r.top = 0;
2422 + s->r.width = min(s->r.width, q_data->crop_width);
2423 + s->r.height = min(s->r.height, q_data->height);
2424 + q_data->crop_width = s->r.width;
2425 + q_data->crop_height = s->r.height;
2426 + q_data->selection_set = true;
2427 + break;
2428 + default:
2429 + return -EINVAL;
2430 + }
2431 + break;
2432 + case ENCODE:
2433 + case ENCODE_IMAGE:
2434 + switch (s->target) {
2435 + case V4L2_SEL_TGT_CROP:
2436 + /* Only support crop from (0,0) */
2437 + s->r.top = 0;
2438 + s->r.left = 0;
2439 + s->r.width = min(s->r.width, q_data->crop_width);
2440 + s->r.height = min(s->r.height, q_data->height);
2441 + q_data->crop_width = s->r.width;
2442 + q_data->crop_height = s->r.height;
2443 + q_data->selection_set = true;
2444 + break;
2445 + default:
2446 + return -EINVAL;
2447 + }
2448 + break;
2449 + case ISP:
2450 + break;
2451 + case DEINTERLACE:
2452 + if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2453 + switch (s->target) {
2454 + case V4L2_SEL_TGT_COMPOSE:
2455 + /* Accept cropped image */
2456 + s->r.left = 0;
2457 + s->r.top = 0;
2458 + s->r.width = min(s->r.width, q_data->crop_width);
2459 + s->r.height = min(s->r.height, q_data->height);
2460 + q_data->crop_width = s->r.width;
2461 + q_data->crop_height = s->r.height;
2462 + q_data->selection_set = true;
2463 + break;
2464 + default:
2465 + return -EINVAL;
2466 + }
2467 + break;
2468 + } else {
2469 + /* must be V4L2_BUF_TYPE_VIDEO_OUTPUT */
2470 + switch (s->target) {
2471 + case V4L2_SEL_TGT_CROP:
2472 + /* Only support crop from (0,0) */
2473 + s->r.top = 0;
2474 + s->r.left = 0;
2475 + s->r.width = min(s->r.width, q_data->crop_width);
2476 + s->r.height = min(s->r.height, q_data->height);
2477 + q_data->crop_width = s->r.width;
2478 + q_data->crop_height = s->r.height;
2479 + q_data->selection_set = true;
2480 + break;
2481 + default:
2482 + return -EINVAL;
2483 + }
2484 + break;
2485 + }
2486 + case NUM_ROLES:
2487 + break;
2488 + }
2489 +
2490 + if (!port)
2491 + return 0;
2492 +
2493 + setup_mmal_port_format(ctx, q_data, port);
2494 + ret = vchiq_mmal_port_set_format(ctx->dev->instance, port);
2495 + if (ret) {
2496 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed vchiq_mmal_port_set_format on port, ret %d\n",
2497 + __func__, ret);
2498 + return -EINVAL;
2499 + }
2500 +
2501 + return 0;
2502 +}
2503 +
2504 +static int vidioc_s_parm(struct file *file, void *priv,
2505 + struct v4l2_streamparm *parm)
2506 +{
2507 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2508 +
2509 + if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
2510 + return -EINVAL;
2511 +
2512 + if (!parm->parm.output.timeperframe.denominator ||
2513 + !parm->parm.output.timeperframe.numerator)
2514 + return -EINVAL;
2515 +
2516 + ctx->framerate_num =
2517 + parm->parm.output.timeperframe.denominator;
2518 + ctx->framerate_denom =
2519 + parm->parm.output.timeperframe.numerator;
2520 +
2521 + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
2522 +
2523 + return 0;
2524 +}
2525 +
2526 +static int vidioc_g_parm(struct file *file, void *priv,
2527 + struct v4l2_streamparm *parm)
2528 +{
2529 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2530 +
2531 + if (parm->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
2532 + return -EINVAL;
2533 +
2534 + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
2535 + parm->parm.output.timeperframe.denominator =
2536 + ctx->framerate_num;
2537 + parm->parm.output.timeperframe.numerator =
2538 + ctx->framerate_denom;
2539 +
2540 + return 0;
2541 +}
2542 +
2543 +static int vidioc_g_pixelaspect(struct file *file, void *fh, int type,
2544 + struct v4l2_fract *f)
2545 +{
2546 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2547 +
2548 + /*
2549 + * The selection API takes V4L2_BUF_TYPE_VIDEO_CAPTURE and
2550 + * V4L2_BUF_TYPE_VIDEO_OUTPUT, even if the device implements the MPLANE
2551 + * API. The V4L2 core will have converted the MPLANE variants to
2552 + * non-MPLANE.
2553 + * Open code this instead of using get_q_data in this case.
2554 + */
2555 + if (ctx->dev->role != DECODE)
2556 + return -ENOIOCTLCMD;
2557 +
2558 + if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2559 + return -EINVAL;
2560 +
2561 + *f = ctx->q_data[V4L2_M2M_DST].aspect_ratio;
2562 +
2563 + return 0;
2564 +}
2565 +
2566 +static int vidioc_subscribe_evt(struct v4l2_fh *fh,
2567 + const struct v4l2_event_subscription *sub)
2568 +{
2569 + switch (sub->type) {
2570 + case V4L2_EVENT_EOS:
2571 + return v4l2_event_subscribe(fh, sub, 2, NULL);
2572 + case V4L2_EVENT_SOURCE_CHANGE:
2573 + return v4l2_src_change_event_subscribe(fh, sub);
2574 + default:
2575 + return v4l2_ctrl_subscribe_event(fh, sub);
2576 + }
2577 +}
2578 +
2579 +static int bcm2835_codec_set_level_profile(struct bcm2835_codec_ctx *ctx,
2580 + struct v4l2_ctrl *ctrl)
2581 +{
2582 + struct mmal_parameter_video_profile param;
2583 + int param_size = sizeof(param);
2584 + int ret;
2585 +
2586 + /*
2587 + * Level and Profile are set via the same MMAL parameter.
2588 + * Retrieve the current settings and amend the one that has changed.
2589 + */
2590 + ret = vchiq_mmal_port_parameter_get(ctx->dev->instance,
2591 + &ctx->component->output[0],
2592 + MMAL_PARAMETER_PROFILE,
2593 + &param,
2594 + &param_size);
2595 + if (ret)
2596 + return ret;
2597 +
2598 + switch (ctrl->id) {
2599 + case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
2600 + switch (ctrl->val) {
2601 + case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
2602 + param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
2603 + break;
2604 + case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
2605 + param.profile =
2606 + MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
2607 + break;
2608 + case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
2609 + param.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
2610 + break;
2611 + case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
2612 + param.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
2613 + break;
2614 + default:
2615 + /* Should never get here */
2616 + break;
2617 + }
2618 + break;
2619 +
2620 + case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
2621 + switch (ctrl->val) {
2622 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
2623 + param.level = MMAL_VIDEO_LEVEL_H264_1;
2624 + break;
2625 + case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
2626 + param.level = MMAL_VIDEO_LEVEL_H264_1b;
2627 + break;
2628 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
2629 + param.level = MMAL_VIDEO_LEVEL_H264_11;
2630 + break;
2631 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
2632 + param.level = MMAL_VIDEO_LEVEL_H264_12;
2633 + break;
2634 + case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
2635 + param.level = MMAL_VIDEO_LEVEL_H264_13;
2636 + break;
2637 + case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
2638 + param.level = MMAL_VIDEO_LEVEL_H264_2;
2639 + break;
2640 + case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
2641 + param.level = MMAL_VIDEO_LEVEL_H264_21;
2642 + break;
2643 + case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
2644 + param.level = MMAL_VIDEO_LEVEL_H264_22;
2645 + break;
2646 + case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
2647 + param.level = MMAL_VIDEO_LEVEL_H264_3;
2648 + break;
2649 + case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
2650 + param.level = MMAL_VIDEO_LEVEL_H264_31;
2651 + break;
2652 + case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
2653 + param.level = MMAL_VIDEO_LEVEL_H264_32;
2654 + break;
2655 + case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
2656 + param.level = MMAL_VIDEO_LEVEL_H264_4;
2657 + break;
2658 + /*
2659 + * Note that the hardware spec is level 4.0. Levels above that
2660 + * are there for correctly encoding the headers and may not
2661 + * be able to keep up with real-time.
2662 + */
2663 + case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
2664 + param.level = MMAL_VIDEO_LEVEL_H264_41;
2665 + break;
2666 + case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
2667 + param.level = MMAL_VIDEO_LEVEL_H264_42;
2668 + break;
2669 + case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
2670 + param.level = MMAL_VIDEO_LEVEL_H264_5;
2671 + break;
2672 + case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
2673 + param.level = MMAL_VIDEO_LEVEL_H264_51;
2674 + break;
2675 + default:
2676 + /* Should never get here */
2677 + break;
2678 + }
2679 + }
2680 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2681 + &ctx->component->output[0],
2682 + MMAL_PARAMETER_PROFILE,
2683 + &param,
2684 + param_size);
2685 +
2686 + return ret;
2687 +}
2688 +
2689 +static int bcm2835_codec_s_ctrl(struct v4l2_ctrl *ctrl)
2690 +{
2691 + struct bcm2835_codec_ctx *ctx =
2692 + container_of(ctrl->handler, struct bcm2835_codec_ctx, hdl);
2693 + int ret = 0;
2694 +
2695 + switch (ctrl->id) {
2696 + case V4L2_CID_MPEG_VIDEO_BITRATE:
2697 + ctx->bitrate = ctrl->val;
2698 + if (!ctx->component)
2699 + break;
2700 +
2701 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2702 + &ctx->component->output[0],
2703 + MMAL_PARAMETER_VIDEO_BIT_RATE,
2704 + &ctrl->val,
2705 + sizeof(ctrl->val));
2706 + break;
2707 +
2708 + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: {
2709 + u32 bitrate_mode;
2710 +
2711 + if (!ctx->component)
2712 + break;
2713 +
2714 + switch (ctrl->val) {
2715 + default:
2716 + case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
2717 + bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
2718 + break;
2719 + case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
2720 + bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
2721 + break;
2722 + }
2723 +
2724 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2725 + &ctx->component->output[0],
2726 + MMAL_PARAMETER_RATECONTROL,
2727 + &bitrate_mode,
2728 + sizeof(bitrate_mode));
2729 + break;
2730 + }
2731 + case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:
2732 + if (!ctx->component)
2733 + break;
2734 +
2735 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2736 + &ctx->component->output[0],
2737 + MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
2738 + &ctrl->val,
2739 + sizeof(ctrl->val));
2740 + break;
2741 +
2742 + case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
2743 + if (!ctx->component)
2744 + break;
2745 +
2746 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2747 + &ctx->component->output[0],
2748 + MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
2749 + &ctrl->val,
2750 + sizeof(ctrl->val));
2751 + break;
2752 +
2753 + case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
2754 + if (!ctx->component)
2755 + break;
2756 +
2757 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2758 + &ctx->component->output[0],
2759 + MMAL_PARAMETER_INTRAPERIOD,
2760 + &ctrl->val,
2761 + sizeof(ctrl->val));
2762 + break;
2763 +
2764 + case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
2765 + case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
2766 + if (!ctx->component)
2767 + break;
2768 +
2769 + ret = bcm2835_codec_set_level_profile(ctx, ctrl);
2770 + break;
2771 +
2772 + case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
2773 + if (!ctx->component)
2774 + break;
2775 +
2776 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2777 + &ctx->component->output[0],
2778 + MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
2779 + &ctrl->val,
2780 + sizeof(ctrl->val));
2781 + break;
2782 +
2783 + case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
2784 + if (!ctx->component)
2785 + break;
2786 +
2787 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2788 + &ctx->component->output[0],
2789 + MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
2790 + &ctrl->val,
2791 + sizeof(ctrl->val));
2792 + break;
2793 +
2794 + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: {
2795 + u32 mmal_bool = 1;
2796 +
2797 + if (!ctx->component)
2798 + break;
2799 +
2800 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2801 + &ctx->component->output[0],
2802 + MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
2803 + &mmal_bool,
2804 + sizeof(mmal_bool));
2805 + break;
2806 + }
2807 + case V4L2_CID_HFLIP:
2808 + case V4L2_CID_VFLIP: {
2809 + u32 u32_value;
2810 +
2811 + if (ctrl->id == V4L2_CID_HFLIP)
2812 + ctx->hflip = ctrl->val;
2813 + else
2814 + ctx->vflip = ctrl->val;
2815 +
2816 + if (!ctx->component)
2817 + break;
2818 +
2819 + if (ctx->hflip && ctx->vflip)
2820 + u32_value = MMAL_PARAM_MIRROR_BOTH;
2821 + else if (ctx->hflip)
2822 + u32_value = MMAL_PARAM_MIRROR_HORIZONTAL;
2823 + else if (ctx->vflip)
2824 + u32_value = MMAL_PARAM_MIRROR_VERTICAL;
2825 + else
2826 + u32_value = MMAL_PARAM_MIRROR_NONE;
2827 +
2828 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2829 + &ctx->component->input[0],
2830 + MMAL_PARAMETER_MIRROR,
2831 + &u32_value,
2832 + sizeof(u32_value));
2833 + break;
2834 + }
2835 + case V4L2_CID_JPEG_COMPRESSION_QUALITY:
2836 + if (!ctx->component)
2837 + break;
2838 +
2839 + ret = vchiq_mmal_port_parameter_set(ctx->dev->instance,
2840 + &ctx->component->output[0],
2841 + MMAL_PARAMETER_JPEG_Q_FACTOR,
2842 + &ctrl->val,
2843 + sizeof(ctrl->val));
2844 + break;
2845 +
2846 + default:
2847 + v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
2848 + return -EINVAL;
2849 + }
2850 +
2851 + if (ret)
2852 + v4l2_err(&ctx->dev->v4l2_dev, "Failed setting ctrl %08x, ret %d\n",
2853 + ctrl->id, ret);
2854 + return ret ? -EINVAL : 0;
2855 +}
2856 +
2857 +static const struct v4l2_ctrl_ops bcm2835_codec_ctrl_ops = {
2858 + .s_ctrl = bcm2835_codec_s_ctrl,
2859 +};
2860 +
2861 +static int vidioc_try_decoder_cmd(struct file *file, void *priv,
2862 + struct v4l2_decoder_cmd *cmd)
2863 +{
2864 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2865 +
2866 + if (ctx->dev->role != DECODE)
2867 + return -EINVAL;
2868 +
2869 + switch (cmd->cmd) {
2870 + case V4L2_DEC_CMD_STOP:
2871 + if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) {
2872 + v4l2_err(&ctx->dev->v4l2_dev, "%s: DEC cmd->flags=%u stop to black not supported",
2873 + __func__, cmd->flags);
2874 + return -EINVAL;
2875 + }
2876 + break;
2877 + case V4L2_DEC_CMD_START:
2878 + break;
2879 + default:
2880 + return -EINVAL;
2881 + }
2882 + return 0;
2883 +}
2884 +
2885 +static int vidioc_decoder_cmd(struct file *file, void *priv,
2886 + struct v4l2_decoder_cmd *cmd)
2887 +{
2888 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2889 + struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
2890 + struct vb2_queue *dst_vq;
2891 + int ret;
2892 +
2893 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
2894 + cmd->cmd);
2895 + ret = vidioc_try_decoder_cmd(file, priv, cmd);
2896 + if (ret)
2897 + return ret;
2898 +
2899 + switch (cmd->cmd) {
2900 + case V4L2_DEC_CMD_STOP:
2901 + if (q_data->eos_buffer_in_use)
2902 + v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
2903 + q_data->eos_buffer_in_use = true;
2904 +
2905 + q_data->eos_buffer.mmal.buffer_size = 0;
2906 + q_data->eos_buffer.mmal.length = 0;
2907 + q_data->eos_buffer.mmal.mmal_flags =
2908 + MMAL_BUFFER_HEADER_FLAG_EOS;
2909 + q_data->eos_buffer.mmal.pts = 0;
2910 + q_data->eos_buffer.mmal.dts = 0;
2911 +
2912 + if (!ctx->component)
2913 + break;
2914 +
2915 + ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
2916 + &ctx->component->input[0],
2917 + &q_data->eos_buffer.mmal);
2918 + if (ret)
2919 + v4l2_err(&ctx->dev->v4l2_dev,
2920 + "%s: EOS buffer submit failed %d\n",
2921 + __func__, ret);
2922 +
2923 + break;
2924 +
2925 + case V4L2_DEC_CMD_START:
2926 + dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
2927 + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
2928 + vb2_clear_last_buffer_dequeued(dst_vq);
2929 + break;
2930 +
2931 + default:
2932 + return -EINVAL;
2933 + }
2934 +
2935 + return 0;
2936 +}
2937 +
2938 +static int vidioc_try_encoder_cmd(struct file *file, void *priv,
2939 + struct v4l2_encoder_cmd *cmd)
2940 +{
2941 + switch (cmd->cmd) {
2942 + case V4L2_ENC_CMD_STOP:
2943 + break;
2944 +
2945 + case V4L2_ENC_CMD_START:
2946 + /* Do we need to do anything here? */
2947 + break;
2948 + default:
2949 + return -EINVAL;
2950 + }
2951 + return 0;
2952 +}
2953 +
2954 +static int vidioc_encoder_cmd(struct file *file, void *priv,
2955 + struct v4l2_encoder_cmd *cmd)
2956 +{
2957 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
2958 + struct bcm2835_codec_q_data *q_data = &ctx->q_data[V4L2_M2M_SRC];
2959 + int ret;
2960 +
2961 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s, cmd %u", __func__,
2962 + cmd->cmd);
2963 + ret = vidioc_try_encoder_cmd(file, priv, cmd);
2964 + if (ret)
2965 + return ret;
2966 +
2967 + switch (cmd->cmd) {
2968 + case V4L2_ENC_CMD_STOP:
2969 + if (q_data->eos_buffer_in_use)
2970 + v4l2_err(&ctx->dev->v4l2_dev, "EOS buffers already in use\n");
2971 + q_data->eos_buffer_in_use = true;
2972 +
2973 + q_data->eos_buffer.mmal.buffer_size = 0;
2974 + q_data->eos_buffer.mmal.length = 0;
2975 + q_data->eos_buffer.mmal.mmal_flags =
2976 + MMAL_BUFFER_HEADER_FLAG_EOS;
2977 + q_data->eos_buffer.mmal.pts = 0;
2978 + q_data->eos_buffer.mmal.dts = 0;
2979 +
2980 + if (!ctx->component)
2981 + break;
2982 +
2983 + ret = vchiq_mmal_submit_buffer(ctx->dev->instance,
2984 + &ctx->component->input[0],
2985 + &q_data->eos_buffer.mmal);
2986 + if (ret)
2987 + v4l2_err(&ctx->dev->v4l2_dev,
2988 + "%s: EOS buffer submit failed %d\n",
2989 + __func__, ret);
2990 +
2991 + break;
2992 + case V4L2_ENC_CMD_START:
2993 + /* Do we need to do anything here? */
2994 + break;
2995 +
2996 + default:
2997 + return -EINVAL;
2998 + }
2999 +
3000 + return 0;
3001 +}
3002 +
3003 +static int vidioc_enum_framesizes(struct file *file, void *fh,
3004 + struct v4l2_frmsizeenum *fsize)
3005 +{
3006 + struct bcm2835_codec_fmt *fmt;
3007 +
3008 + fmt = find_format_pix_fmt(fsize->pixel_format, file2ctx(file)->dev,
3009 + true);
3010 + if (!fmt)
3011 + fmt = find_format_pix_fmt(fsize->pixel_format,
3012 + file2ctx(file)->dev,
3013 + false);
3014 +
3015 + if (!fmt)
3016 + return -EINVAL;
3017 +
3018 + if (fsize->index)
3019 + return -EINVAL;
3020 +
3021 + fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
3022 +
3023 + fsize->stepwise.min_width = MIN_W;
3024 + fsize->stepwise.max_width = MAX_W;
3025 + fsize->stepwise.step_width = 2;
3026 + fsize->stepwise.min_height = MIN_H;
3027 + fsize->stepwise.max_height = MAX_H;
3028 + fsize->stepwise.step_height = 2;
3029 +
3030 + return 0;
3031 +}
3032 +
3033 +static const struct v4l2_ioctl_ops bcm2835_codec_ioctl_ops = {
3034 + .vidioc_querycap = vidioc_querycap,
3035 +
3036 + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
3037 + .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt_vid_cap,
3038 + .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap,
3039 + .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt_vid_cap,
3040 +
3041 + .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
3042 + .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt_vid_out,
3043 + .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_out,
3044 + .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt_vid_out,
3045 +
3046 + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
3047 + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
3048 + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
3049 + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
3050 + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
3051 + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
3052 + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
3053 +
3054 + .vidioc_streamon = v4l2_m2m_ioctl_streamon,
3055 + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
3056 +
3057 + .vidioc_g_selection = vidioc_g_selection,
3058 + .vidioc_s_selection = vidioc_s_selection,
3059 +
3060 + .vidioc_g_parm = vidioc_g_parm,
3061 + .vidioc_s_parm = vidioc_s_parm,
3062 +
3063 + .vidioc_g_pixelaspect = vidioc_g_pixelaspect,
3064 +
3065 + .vidioc_subscribe_event = vidioc_subscribe_evt,
3066 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
3067 +
3068 + .vidioc_decoder_cmd = vidioc_decoder_cmd,
3069 + .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
3070 + .vidioc_encoder_cmd = vidioc_encoder_cmd,
3071 + .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
3072 + .vidioc_enum_framesizes = vidioc_enum_framesizes,
3073 +};
3074 +
3075 +static int bcm2835_codec_create_component(struct bcm2835_codec_ctx *ctx)
3076 +{
3077 + struct bcm2835_codec_dev *dev = ctx->dev;
3078 + unsigned int enable = 1;
3079 + int ret;
3080 +
3081 + ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
3082 + &ctx->component);
3083 + if (ret < 0) {
3084 + v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
3085 + __func__, components[dev->role]);
3086 + return -ENOMEM;
3087 + }
3088 +
3089 + vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->input[0],
3090 + MMAL_PARAMETER_ZERO_COPY, &enable,
3091 + sizeof(enable));
3092 + vchiq_mmal_port_parameter_set(dev->instance, &ctx->component->output[0],
3093 + MMAL_PARAMETER_ZERO_COPY, &enable,
3094 + sizeof(enable));
3095 +
3096 + if (dev->role == DECODE) {
3097 + /*
3098 + * Disable firmware option that ensures decoded timestamps
3099 + * always increase.
3100 + */
3101 + enable = 0;
3102 + vchiq_mmal_port_parameter_set(dev->instance,
3103 + &ctx->component->output[0],
3104 + MMAL_PARAMETER_VIDEO_VALIDATE_TIMESTAMPS,
3105 + &enable,
3106 + sizeof(enable));
3107 + /*
3108 + * Enable firmware option to stop on colourspace and pixel
3109 + * aspect ratio changed
3110 + */
3111 + enable = 1;
3112 + vchiq_mmal_port_parameter_set(dev->instance,
3113 + &ctx->component->control,
3114 + MMAL_PARAMETER_VIDEO_STOP_ON_PAR_COLOUR_CHANGE,
3115 + &enable,
3116 + sizeof(enable));
3117 + } else if (dev->role == DEINTERLACE) {
3118 + /* Select the default deinterlace algorithm. */
3119 + int half_framerate = 0;
3120 + int default_frame_interval = -1; /* don't interpolate */
3121 + int frame_type = 5; /* 0=progressive, 3=TFF, 4=BFF, 5=see frame */
3122 + int use_qpus = 0;
3123 + enum mmal_parameter_imagefx effect =
3124 + advanced_deinterlace && ctx->q_data[V4L2_M2M_SRC].crop_width <= 800 ?
3125 + MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV :
3126 + MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST;
3127 + struct mmal_parameter_imagefx_parameters params = {
3128 + .effect = effect,
3129 + .num_effect_params = 4,
3130 + .effect_parameter = { frame_type,
3131 + default_frame_interval,
3132 + half_framerate,
3133 + use_qpus },
3134 + };
3135 +
3136 + vchiq_mmal_port_parameter_set(dev->instance,
3137 + &ctx->component->output[0],
3138 + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
3139 + &params,
3140 + sizeof(params));
3141 +
3142 + } else if (dev->role == ENCODE_IMAGE) {
3143 + enable = 0;
3144 + vchiq_mmal_port_parameter_set(dev->instance,
3145 + &ctx->component->control,
3146 + MMAL_PARAMETER_EXIF_DISABLE,
3147 + &enable,
3148 + sizeof(enable));
3149 + enable = 1;
3150 + vchiq_mmal_port_parameter_set(dev->instance,
3151 + &ctx->component->output[0],
3152 + MMAL_PARAMETER_JPEG_IJG_SCALING,
3153 + &enable,
3154 + sizeof(enable));
3155 + }
3156 +
3157 + setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_SRC],
3158 + &ctx->component->input[0]);
3159 + ctx->component->input[0].cb_ctx = ctx;
3160 +
3161 + setup_mmal_port_format(ctx, &ctx->q_data[V4L2_M2M_DST],
3162 + &ctx->component->output[0]);
3163 + ctx->component->output[0].cb_ctx = ctx;
3164 +
3165 + ret = vchiq_mmal_port_set_format(dev->instance,
3166 + &ctx->component->input[0]);
3167 + if (ret < 0) {
3168 + v4l2_dbg(1, debug, &dev->v4l2_dev,
3169 + "%s: vchiq_mmal_port_set_format ip port failed\n",
3170 + __func__);
3171 + goto destroy_component;
3172 + }
3173 +
3174 + ret = vchiq_mmal_port_set_format(dev->instance,
3175 + &ctx->component->output[0]);
3176 + if (ret < 0) {
3177 + v4l2_dbg(1, debug, &dev->v4l2_dev,
3178 + "%s: vchiq_mmal_port_set_format op port failed\n",
3179 + __func__);
3180 + goto destroy_component;
3181 + }
3182 +
3183 + if (dev->role == ENCODE || dev->role == ENCODE_IMAGE) {
3184 + u32 param = 1;
3185 +
3186 + if (ctx->q_data[V4L2_M2M_SRC].sizeimage <
3187 + ctx->component->output[0].minimum_buffer.size)
3188 + v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
3189 + ctx->q_data[V4L2_M2M_SRC].sizeimage,
3190 + ctx->component->output[0].minimum_buffer.size);
3191 +
3192 + if (dev->role == ENCODE) {
3193 + /* Enable SPS Timing header so framerate information is encoded
3194 + * in the H264 header.
3195 + */
3196 + vchiq_mmal_port_parameter_set(ctx->dev->instance,
3197 + &ctx->component->output[0],
3198 + MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING,
3199 + &param, sizeof(param));
3200 +
3201 + /* Enable inserting headers into the first frame */
3202 + vchiq_mmal_port_parameter_set(ctx->dev->instance,
3203 + &ctx->component->control,
3204 + MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
3205 + &param, sizeof(param));
3206 + /*
3207 + * Avoid fragmenting the buffers over multiple frames (unless
3208 + * the frame is bigger than the whole buffer)
3209 + */
3210 + vchiq_mmal_port_parameter_set(ctx->dev->instance,
3211 + &ctx->component->control,
3212 + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
3213 + &param, sizeof(param));
3214 + }
3215 + } else {
3216 + if (ctx->q_data[V4L2_M2M_DST].sizeimage <
3217 + ctx->component->output[0].minimum_buffer.size)
3218 + v4l2_err(&dev->v4l2_dev, "buffer size mismatch sizeimage %u < min size %u\n",
3219 + ctx->q_data[V4L2_M2M_DST].sizeimage,
3220 + ctx->component->output[0].minimum_buffer.size);
3221 + }
3222 +
3223 + /* Now we have a component we can set all the ctrls */
3224 + ret = v4l2_ctrl_handler_setup(&ctx->hdl);
3225 +
3226 + v4l2_dbg(2, debug, &dev->v4l2_dev, "%s: component created as %s\n",
3227 + __func__, components[dev->role]);
3228 +
3229 + return 0;
3230 +
3231 +destroy_component:
3232 + vchiq_mmal_component_finalise(ctx->dev->instance, ctx->component);
3233 + ctx->component = NULL;
3234 +
3235 + return ret;
3236 +}
3237 +
3238 +/*
3239 + * Queue operations
3240 + */
3241 +
3242 +static int bcm2835_codec_queue_setup(struct vb2_queue *vq,
3243 + unsigned int *nbuffers,
3244 + unsigned int *nplanes,
3245 + unsigned int sizes[],
3246 + struct device *alloc_devs[])
3247 +{
3248 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vq);
3249 + struct bcm2835_codec_q_data *q_data;
3250 + struct vchiq_mmal_port *port;
3251 + unsigned int size;
3252 +
3253 + q_data = get_q_data(ctx, vq->type);
3254 + if (!q_data)
3255 + return -EINVAL;
3256 +
3257 + if (!ctx->component)
3258 + if (bcm2835_codec_create_component(ctx))
3259 + return -EINVAL;
3260 +
3261 + port = get_port_data(ctx, vq->type);
3262 +
3263 + size = q_data->sizeimage;
3264 +
3265 + if (*nplanes)
3266 + return sizes[0] < size ? -EINVAL : 0;
3267 +
3268 + *nplanes = 1;
3269 +
3270 + sizes[0] = size;
3271 + port->current_buffer.size = size;
3272 +
3273 + if (*nbuffers < port->minimum_buffer.num)
3274 + *nbuffers = port->minimum_buffer.num;
3275 + /* Add one buffer to take an EOS */
3276 + port->current_buffer.num = *nbuffers + 1;
3277 +
3278 + return 0;
3279 +}
3280 +
3281 +static int bcm2835_codec_mmal_buf_cleanup(struct mmal_buffer *mmal_buf)
3282 +{
3283 + mmal_vchi_buffer_cleanup(mmal_buf);
3284 +
3285 + if (mmal_buf->dma_buf) {
3286 + dma_buf_put(mmal_buf->dma_buf);
3287 + mmal_buf->dma_buf = NULL;
3288 + }
3289 +
3290 + return 0;
3291 +}
3292 +
3293 +static int bcm2835_codec_buf_init(struct vb2_buffer *vb)
3294 +{
3295 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
3296 + struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
3297 + struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
3298 + vb);
3299 + struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
3300 + m2m);
3301 +
3302 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
3303 + __func__, ctx, vb);
3304 + buf->mmal.buffer = vb2_plane_vaddr(&buf->m2m.vb.vb2_buf, 0);
3305 + buf->mmal.buffer_size = vb2_plane_size(&buf->m2m.vb.vb2_buf, 0);
3306 +
3307 + mmal_vchi_buffer_init(ctx->dev->instance, &buf->mmal);
3308 +
3309 + return 0;
3310 +}
3311 +
3312 +static int bcm2835_codec_buf_prepare(struct vb2_buffer *vb)
3313 +{
3314 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
3315 + struct bcm2835_codec_q_data *q_data;
3316 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
3317 + struct v4l2_m2m_buffer *m2m = container_of(vbuf, struct v4l2_m2m_buffer,
3318 + vb);
3319 + struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
3320 + m2m);
3321 + struct dma_buf *dma_buf;
3322 + int ret;
3323 +
3324 + v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p\n",
3325 + __func__, vb->vb2_queue->type, vb);
3326 +
3327 + q_data = get_q_data(ctx, vb->vb2_queue->type);
3328 + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
3329 + if (vbuf->field == V4L2_FIELD_ANY)
3330 + vbuf->field = V4L2_FIELD_NONE;
3331 + }
3332 +
3333 + if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
3334 + v4l2_err(&ctx->dev->v4l2_dev, "%s data will not fit into plane (%lu < %lu)\n",
3335 + __func__, vb2_plane_size(vb, 0),
3336 + (long)q_data->sizeimage);
3337 + return -EINVAL;
3338 + }
3339 +
3340 + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
3341 + vb2_set_plane_payload(vb, 0, q_data->sizeimage);
3342 +
3343 + switch (vb->memory) {
3344 + case VB2_MEMORY_DMABUF:
3345 + dma_buf = dma_buf_get(vb->planes[0].m.fd);
3346 +
3347 + if (dma_buf != buf->mmal.dma_buf) {
3348 + /* dmabuf either hasn't already been mapped, or it has
3349 + * changed.
3350 + */
3351 + if (buf->mmal.dma_buf) {
3352 + v4l2_err(&ctx->dev->v4l2_dev,
3353 + "%s Buffer changed - why did the core not call cleanup?\n",
3354 + __func__);
3355 + bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
3356 + }
3357 +
3358 + buf->mmal.dma_buf = dma_buf;
3359 + } else {
3360 + /* We already have a reference count on the dmabuf, so
3361 + * release the one we acquired above.
3362 + */
3363 + dma_buf_put(dma_buf);
3364 + }
3365 + ret = 0;
3366 + break;
3367 + case VB2_MEMORY_MMAP:
3368 + /*
3369 + * We want to do this at init, but vb2_core_expbuf checks that
3370 + * the index < q->num_buffers, and q->num_buffers only gets
3371 + * updated once all the buffers are allocated.
3372 + */
3373 + if (!buf->mmal.dma_buf) {
3374 + ret = vb2_core_expbuf_dmabuf(vb->vb2_queue,
3375 + vb->vb2_queue->type,
3376 + vb->index, 0,
3377 + O_CLOEXEC,
3378 + &buf->mmal.dma_buf);
3379 + if (ret)
3380 + v4l2_err(&ctx->dev->v4l2_dev,
3381 + "%s: Failed to expbuf idx %d, ret %d\n",
3382 + __func__, vb->index, ret);
3383 + } else {
3384 + ret = 0;
3385 + }
3386 + break;
3387 + default:
3388 + ret = -EINVAL;
3389 + break;
3390 + }
3391 +
3392 + return ret;
3393 +}
3394 +
3395 +static void bcm2835_codec_buf_queue(struct vb2_buffer *vb)
3396 +{
3397 + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
3398 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
3399 +
3400 + v4l2_dbg(4, debug, &ctx->dev->v4l2_dev, "%s: type: %d ptr %p vbuf->flags %u, seq %u, bytesused %u\n",
3401 + __func__, vb->vb2_queue->type, vb, vbuf->flags, vbuf->sequence,
3402 + vb->planes[0].bytesused);
3403 + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
3404 +}
3405 +
3406 +static void bcm2835_codec_buffer_cleanup(struct vb2_buffer *vb)
3407 +{
3408 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
3409 + struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
3410 + struct v4l2_m2m_buffer *m2m = container_of(vb2, struct v4l2_m2m_buffer,
3411 + vb);
3412 + struct m2m_mmal_buffer *buf = container_of(m2m, struct m2m_mmal_buffer,
3413 + m2m);
3414 +
3415 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, vb %p\n",
3416 + __func__, ctx, vb);
3417 +
3418 + bcm2835_codec_mmal_buf_cleanup(&buf->mmal);
3419 +}
3420 +
3421 +static void bcm2835_codec_flush_buffers(struct bcm2835_codec_ctx *ctx,
3422 + struct vchiq_mmal_port *port)
3423 +{
3424 + int ret;
3425 +
3426 + if (atomic_read(&port->buffers_with_vpu)) {
3427 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Waiting for buffers to be returned - %d outstanding\n",
3428 + __func__, atomic_read(&port->buffers_with_vpu));
3429 + ret = wait_for_completion_timeout(&ctx->frame_cmplt,
3430 + COMPLETE_TIMEOUT);
3431 + if (ret <= 0) {
3432 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n",
3433 + __func__,
3434 + atomic_read(&port->buffers_with_vpu));
3435 + }
3436 + }
3437 +}
3438 +static int bcm2835_codec_start_streaming(struct vb2_queue *q,
3439 + unsigned int count)
3440 +{
3441 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
3442 + struct bcm2835_codec_dev *dev = ctx->dev;
3443 + struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
3444 + struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
3445 + int ret = 0;
3446 +
3447 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n",
3448 + __func__, q->type, count);
3449 + q_data->sequence = 0;
3450 +
3451 + if (!ctx->component_enabled) {
3452 + ret = vchiq_mmal_component_enable(dev->instance,
3453 + ctx->component);
3454 + if (ret)
3455 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
3456 + __func__, ret);
3457 + ctx->component_enabled = true;
3458 + }
3459 +
3460 + if (port->enabled) {
3461 + unsigned int num_buffers;
3462 +
3463 + init_completion(&ctx->frame_cmplt);
3464 +
3465 + /*
3466 + * This should only ever happen with DECODE and the MMAL output
3467 + * port that has been enabled for resolution changed events.
3468 + * In this case no buffers have been allocated or sent to the
3469 + * component, so warn on that.
3470 + */
3471 + WARN_ON(ctx->dev->role != DECODE);
3472 + WARN_ON(q->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
3473 + WARN_ON(atomic_read(&port->buffers_with_vpu));
3474 +
3475 + /*
3476 + * Disable will reread the port format, so retain buffer count.
3477 + */
3478 + num_buffers = port->current_buffer.num;
3479 +
3480 + ret = vchiq_mmal_port_disable(dev->instance, port);
3481 + if (ret)
3482 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error disabling port update buffer count, ret %d\n",
3483 + __func__, ret);
3484 + bcm2835_codec_flush_buffers(ctx, port);
3485 + port->current_buffer.num = num_buffers;
3486 + }
3487 +
3488 + if (count < port->minimum_buffer.num)
3489 + count = port->minimum_buffer.num;
3490 +
3491 + if (port->current_buffer.num < count + 1) {
3492 + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, buffer count changed %u to %u\n",
3493 + __func__, ctx, port->current_buffer.num, count + 1);
3494 +
3495 + port->current_buffer.num = count + 1;
3496 + ret = vchiq_mmal_port_set_format(dev->instance, port);
3497 + if (ret)
3498 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error updating buffer count, ret %d\n",
3499 + __func__, ret);
3500 + }
3501 +
3502 + if (dev->role == DECODE &&
3503 + q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
3504 + !ctx->component->output[0].enabled) {
3505 + /*
3506 + * Decode needs to enable the MMAL output/V4L2 CAPTURE
3507 + * port at this point too so that we have everything
3508 + * set up for dynamic resolution changes.
3509 + */
3510 + ret = vchiq_mmal_port_enable(dev->instance,
3511 + &ctx->component->output[0],
3512 + op_buffer_cb);
3513 + if (ret)
3514 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
3515 + __func__, ret);
3516 + }
3517 +
3518 + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
3519 + /*
3520 + * Create the EOS buffer.
3521 + * We only need the MMAL part, and want to NOT attach a memory
3522 + * buffer to it as it should only take flags.
3523 + */
3524 + memset(&q_data->eos_buffer, 0, sizeof(q_data->eos_buffer));
3525 + mmal_vchi_buffer_init(dev->instance,
3526 + &q_data->eos_buffer.mmal);
3527 + q_data->eos_buffer_in_use = false;
3528 +
3529 + ret = vchiq_mmal_port_enable(dev->instance,
3530 + port,
3531 + ip_buffer_cb);
3532 + if (ret)
3533 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n",
3534 + __func__, ret);
3535 + } else {
3536 + if (!port->enabled) {
3537 + ret = vchiq_mmal_port_enable(dev->instance,
3538 + port,
3539 + op_buffer_cb);
3540 + if (ret)
3541 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
3542 + __func__, ret);
3543 + }
3544 + }
3545 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: Done, ret %d\n",
3546 + __func__, ret);
3547 + return ret;
3548 +}
3549 +
3550 +static void bcm2835_codec_stop_streaming(struct vb2_queue *q)
3551 +{
3552 + struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q);
3553 + struct bcm2835_codec_dev *dev = ctx->dev;
3554 + struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type);
3555 + struct vchiq_mmal_port *port = get_port_data(ctx, q->type);
3556 + struct vb2_v4l2_buffer *vbuf;
3557 + int ret;
3558 +
3559 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n",
3560 + __func__, q->type);
3561 +
3562 + init_completion(&ctx->frame_cmplt);
3563 +
3564 + /* Clear out all buffers held by m2m framework */
3565 + for (;;) {
3566 + if (V4L2_TYPE_IS_OUTPUT(q->type))
3567 + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
3568 + else
3569 + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
3570 + if (!vbuf)
3571 + break;
3572 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: return buffer %p\n",
3573 + __func__, vbuf);
3574 +
3575 + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED);
3576 + }
3577 +
3578 + /* Disable MMAL port - this will flush buffers back */
3579 + ret = vchiq_mmal_port_disable(dev->instance, port);
3580 + if (ret)
3581 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed disabling %s port, ret %d\n",
3582 + __func__, V4L2_TYPE_IS_OUTPUT(q->type) ? "i/p" : "o/p",
3583 + ret);
3584 +
3585 + bcm2835_codec_flush_buffers(ctx, port);
3586 +
3587 + if (dev->role == DECODE &&
3588 + q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
3589 + ctx->component->input[0].enabled) {
3590 + /*
3591 + * For decode we need to keep the MMAL output port enabled for
3592 + * resolution changed events whenever the input is enabled.
3593 + */
3594 + ret = vchiq_mmal_port_enable(dev->instance,
3595 + &ctx->component->output[0],
3596 + op_buffer_cb);
3597 + if (ret)
3598 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n",
3599 + __func__, ret);
3600 + }
3601 +
3602 + /* If both ports disabled, then disable the component */
3603 + if (ctx->component_enabled &&
3604 + !ctx->component->input[0].enabled &&
3605 + !ctx->component->output[0].enabled) {
3606 + ret = vchiq_mmal_component_disable(dev->instance,
3607 + ctx->component);
3608 + if (ret)
3609 + v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n",
3610 + __func__, ret);
3611 + ctx->component_enabled = false;
3612 + }
3613 +
3614 + if (V4L2_TYPE_IS_OUTPUT(q->type))
3615 + mmal_vchi_buffer_cleanup(&q_data->eos_buffer.mmal);
3616 +
3617 + v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: done\n", __func__);
3618 +}
3619 +
3620 +static const struct vb2_ops bcm2835_codec_qops = {
3621 + .queue_setup = bcm2835_codec_queue_setup,
3622 + .buf_init = bcm2835_codec_buf_init,
3623 + .buf_prepare = bcm2835_codec_buf_prepare,
3624 + .buf_queue = bcm2835_codec_buf_queue,
3625 + .buf_cleanup = bcm2835_codec_buffer_cleanup,
3626 + .start_streaming = bcm2835_codec_start_streaming,
3627 + .stop_streaming = bcm2835_codec_stop_streaming,
3628 + .wait_prepare = vb2_ops_wait_prepare,
3629 + .wait_finish = vb2_ops_wait_finish,
3630 +};
3631 +
3632 +static int queue_init(void *priv, struct vb2_queue *src_vq,
3633 + struct vb2_queue *dst_vq)
3634 +{
3635 + struct bcm2835_codec_ctx *ctx = priv;
3636 + int ret;
3637 +
3638 + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
3639 + src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
3640 + src_vq->drv_priv = ctx;
3641 + src_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
3642 + src_vq->ops = &bcm2835_codec_qops;
3643 + src_vq->mem_ops = &vb2_dma_contig_memops;
3644 + src_vq->dev = &ctx->dev->pdev->dev;
3645 + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
3646 + src_vq->lock = &ctx->dev->dev_mutex;
3647 +
3648 + ret = vb2_queue_init(src_vq);
3649 + if (ret)
3650 + return ret;
3651 +
3652 + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
3653 + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
3654 + dst_vq->drv_priv = ctx;
3655 + dst_vq->buf_struct_size = sizeof(struct m2m_mmal_buffer);
3656 + dst_vq->ops = &bcm2835_codec_qops;
3657 + dst_vq->mem_ops = &vb2_dma_contig_memops;
3658 + dst_vq->dev = &ctx->dev->pdev->dev;
3659 + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
3660 + dst_vq->lock = &ctx->dev->dev_mutex;
3661 +
3662 + return vb2_queue_init(dst_vq);
3663 +}
3664 +
3665 +/*
3666 + * File operations
3667 + */
3668 +static int bcm2835_codec_open(struct file *file)
3669 +{
3670 + struct bcm2835_codec_dev *dev = video_drvdata(file);
3671 + struct bcm2835_codec_ctx *ctx = NULL;
3672 + struct v4l2_ctrl_handler *hdl;
3673 + int rc = 0;
3674 +
3675 + if (mutex_lock_interruptible(&dev->dev_mutex)) {
3676 + v4l2_err(&dev->v4l2_dev, "Mutex fail\n");
3677 + return -ERESTARTSYS;
3678 + }
3679 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
3680 + if (!ctx) {
3681 + rc = -ENOMEM;
3682 + goto open_unlock;
3683 + }
3684 +
3685 + ctx->q_data[V4L2_M2M_SRC].fmt = get_default_format(dev, false);
3686 + ctx->q_data[V4L2_M2M_DST].fmt = get_default_format(dev, true);
3687 +
3688 + ctx->q_data[V4L2_M2M_SRC].crop_width = DEFAULT_WIDTH;
3689 + ctx->q_data[V4L2_M2M_SRC].crop_height = DEFAULT_HEIGHT;
3690 + ctx->q_data[V4L2_M2M_SRC].height = DEFAULT_HEIGHT;
3691 + ctx->q_data[V4L2_M2M_SRC].bytesperline =
3692 + get_bytesperline(DEFAULT_WIDTH, DEFAULT_HEIGHT,
3693 + ctx->q_data[V4L2_M2M_SRC].fmt,
3694 + dev->role);
3695 + ctx->q_data[V4L2_M2M_SRC].sizeimage =
3696 + get_sizeimage(ctx->q_data[V4L2_M2M_SRC].bytesperline,
3697 + ctx->q_data[V4L2_M2M_SRC].crop_width,
3698 + ctx->q_data[V4L2_M2M_SRC].height,
3699 + ctx->q_data[V4L2_M2M_SRC].fmt);
3700 + ctx->q_data[V4L2_M2M_SRC].field = V4L2_FIELD_NONE;
3701 +
3702 + ctx->q_data[V4L2_M2M_DST].crop_width = DEFAULT_WIDTH;
3703 + ctx->q_data[V4L2_M2M_DST].crop_height = DEFAULT_HEIGHT;
3704 + ctx->q_data[V4L2_M2M_DST].height = DEFAULT_HEIGHT;
3705 + ctx->q_data[V4L2_M2M_DST].bytesperline =
3706 + get_bytesperline(DEFAULT_WIDTH, DEFAULT_HEIGHT,
3707 + ctx->q_data[V4L2_M2M_DST].fmt,
3708 + dev->role);
3709 + ctx->q_data[V4L2_M2M_DST].sizeimage =
3710 + get_sizeimage(ctx->q_data[V4L2_M2M_DST].bytesperline,
3711 + ctx->q_data[V4L2_M2M_DST].crop_width,
3712 + ctx->q_data[V4L2_M2M_DST].height,
3713 + ctx->q_data[V4L2_M2M_DST].fmt);
3714 + ctx->q_data[V4L2_M2M_DST].aspect_ratio.numerator = 1;
3715 + ctx->q_data[V4L2_M2M_DST].aspect_ratio.denominator = 1;
3716 + ctx->q_data[V4L2_M2M_DST].field = V4L2_FIELD_NONE;
3717 +
3718 + ctx->colorspace = V4L2_COLORSPACE_REC709;
3719 + ctx->bitrate = 10 * 1000 * 1000;
3720 +
3721 + ctx->framerate_num = 30;
3722 + ctx->framerate_denom = 1;
3723 +
3724 + /* Initialise V4L2 contexts */
3725 + v4l2_fh_init(&ctx->fh, video_devdata(file));
3726 + file->private_data = &ctx->fh;
3727 + ctx->dev = dev;
3728 + hdl = &ctx->hdl;
3729 + switch (dev->role) {
3730 + case ENCODE:
3731 + {
3732 + /* Encode controls */
3733 + v4l2_ctrl_handler_init(hdl, 11);
3734 +
3735 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
3736 + V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
3737 + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
3738 + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
3739 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3740 + V4L2_CID_MPEG_VIDEO_BITRATE,
3741 + 25 * 1000, 25 * 1000 * 1000,
3742 + 25 * 1000, 10 * 1000 * 1000);
3743 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
3744 + V4L2_CID_MPEG_VIDEO_HEADER_MODE,
3745 + V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
3746 + 0, V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
3747 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3748 + V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER,
3749 + 0, 1,
3750 + 1, 0);
3751 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3752 + V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
3753 + 0, 0x7FFFFFFF,
3754 + 1, 60);
3755 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
3756 + V4L2_CID_MPEG_VIDEO_H264_LEVEL,
3757 + V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
3758 + ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
3759 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
3760 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
3761 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
3762 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
3763 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
3764 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
3765 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
3766 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
3767 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
3768 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
3769 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
3770 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
3771 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) |
3772 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) |
3773 + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1)),
3774 + V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
3775 + v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops,
3776 + V4L2_CID_MPEG_VIDEO_H264_PROFILE,
3777 + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
3778 + ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
3779 + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
3780 + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
3781 + BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
3782 + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
3783 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3784 + V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
3785 + 0, 51,
3786 + 1, 20);
3787 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3788 + V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
3789 + 0, 51,
3790 + 1, 51);
3791 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3792 + V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
3793 + 0, 0, 0, 0);
3794 + if (hdl->error) {
3795 + rc = hdl->error;
3796 + goto free_ctrl_handler;
3797 + }
3798 + ctx->fh.ctrl_handler = hdl;
3799 + v4l2_ctrl_handler_setup(hdl);
3800 + }
3801 + break;
3802 + case DECODE:
3803 + {
3804 + v4l2_ctrl_handler_init(hdl, 1);
3805 +
3806 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3807 + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
3808 + 1, 1, 1, 1);
3809 + if (hdl->error) {
3810 + rc = hdl->error;
3811 + goto free_ctrl_handler;
3812 + }
3813 + ctx->fh.ctrl_handler = hdl;
3814 + v4l2_ctrl_handler_setup(hdl);
3815 + }
3816 + break;
3817 + case ISP:
3818 + {
3819 + v4l2_ctrl_handler_init(hdl, 2);
3820 +
3821 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3822 + V4L2_CID_HFLIP,
3823 + 1, 0, 1, 0);
3824 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3825 + V4L2_CID_VFLIP,
3826 + 1, 0, 1, 0);
3827 + if (hdl->error) {
3828 + rc = hdl->error;
3829 + goto free_ctrl_handler;
3830 + }
3831 + ctx->fh.ctrl_handler = hdl;
3832 + v4l2_ctrl_handler_setup(hdl);
3833 + }
3834 + break;
3835 + case DEINTERLACE:
3836 + {
3837 + v4l2_ctrl_handler_init(hdl, 0);
3838 + }
3839 + break;
3840 + case ENCODE_IMAGE:
3841 + {
3842 + /* Encode image controls */
3843 + v4l2_ctrl_handler_init(hdl, 1);
3844 +
3845 + v4l2_ctrl_new_std(hdl, &bcm2835_codec_ctrl_ops,
3846 + V4L2_CID_JPEG_COMPRESSION_QUALITY,
3847 + 1, 100,
3848 + 1, 80);
3849 + if (hdl->error) {
3850 + rc = hdl->error;
3851 + goto free_ctrl_handler;
3852 + }
3853 + ctx->fh.ctrl_handler = hdl;
3854 + v4l2_ctrl_handler_setup(hdl);
3855 + }
3856 + break;
3857 + case NUM_ROLES:
3858 + break;
3859 + }
3860 +
3861 + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
3862 +
3863 + if (IS_ERR(ctx->fh.m2m_ctx)) {
3864 + rc = PTR_ERR(ctx->fh.m2m_ctx);
3865 +
3866 + goto free_ctrl_handler;
3867 + }
3868 +
3869 + /* Set both queues as buffered as we have buffering in the VPU. That
3870 + * means that we will be scheduled whenever either an input or output
3871 + * buffer is available (otherwise one of each are required).
3872 + */
3873 + v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
3874 + v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
3875 +
3876 + v4l2_fh_add(&ctx->fh);
3877 + atomic_inc(&dev->num_inst);
3878 +
3879 + mutex_unlock(&dev->dev_mutex);
3880 + return 0;
3881 +
3882 +free_ctrl_handler:
3883 + v4l2_ctrl_handler_free(hdl);
3884 + kfree(ctx);
3885 +open_unlock:
3886 + mutex_unlock(&dev->dev_mutex);
3887 + return rc;
3888 +}
3889 +
3890 +static int bcm2835_codec_release(struct file *file)
3891 +{
3892 + struct bcm2835_codec_dev *dev = video_drvdata(file);
3893 + struct bcm2835_codec_ctx *ctx = file2ctx(file);
3894 +
3895 + v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: Releasing instance %p\n",
3896 + __func__, ctx);
3897 +
3898 + v4l2_fh_del(&ctx->fh);
3899 + v4l2_fh_exit(&ctx->fh);
3900 + v4l2_ctrl_handler_free(&ctx->hdl);
3901 + mutex_lock(&dev->dev_mutex);
3902 + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
3903 +
3904 + if (ctx->component)
3905 + vchiq_mmal_component_finalise(dev->instance, ctx->component);
3906 +
3907 + mutex_unlock(&dev->dev_mutex);
3908 + kfree(ctx);
3909 +
3910 + atomic_dec(&dev->num_inst);
3911 +
3912 + return 0;
3913 +}
3914 +
3915 +static const struct v4l2_file_operations bcm2835_codec_fops = {
3916 + .owner = THIS_MODULE,
3917 + .open = bcm2835_codec_open,
3918 + .release = bcm2835_codec_release,
3919 + .poll = v4l2_m2m_fop_poll,
3920 + .unlocked_ioctl = video_ioctl2,
3921 + .mmap = v4l2_m2m_fop_mmap,
3922 +};
3923 +
3924 +static const struct video_device bcm2835_codec_videodev = {
3925 + .name = MEM2MEM_NAME,
3926 + .vfl_dir = VFL_DIR_M2M,
3927 + .fops = &bcm2835_codec_fops,
3928 + .ioctl_ops = &bcm2835_codec_ioctl_ops,
3929 + .minor = -1,
3930 + .release = video_device_release_empty,
3931 +};
3932 +
3933 +static const struct v4l2_m2m_ops m2m_ops = {
3934 + .device_run = device_run,
3935 + .job_ready = job_ready,
3936 + .job_abort = job_abort,
3937 +};
3938 +
3939 +/* Size of the array to provide to the VPU when asking for the list of supported
3940 + * formats.
3941 + * The ISP component currently advertises 62 input formats, so add a small
3942 + * overhead on that.
3943 + */
3944 +#define MAX_SUPPORTED_ENCODINGS 70
3945 +
3946 +/* Populate dev->supported_fmts with the formats supported by those ports. */
3947 +static int bcm2835_codec_get_supported_fmts(struct bcm2835_codec_dev *dev)
3948 +{
3949 + struct bcm2835_codec_fmt *list;
3950 + struct vchiq_mmal_component *component;
3951 + u32 fourccs[MAX_SUPPORTED_ENCODINGS];
3952 + u32 param_size = sizeof(fourccs);
3953 + unsigned int i, j, num_encodings;
3954 + int ret;
3955 +
3956 + ret = vchiq_mmal_component_init(dev->instance, components[dev->role],
3957 + &component);
3958 + if (ret < 0) {
3959 + v4l2_err(&dev->v4l2_dev, "%s: failed to create component %s\n",
3960 + __func__, components[dev->role]);
3961 + return -ENOMEM;
3962 + }
3963 +
3964 + ret = vchiq_mmal_port_parameter_get(dev->instance,
3965 + &component->input[0],
3966 + MMAL_PARAMETER_SUPPORTED_ENCODINGS,
3967 + &fourccs,
3968 + &param_size);
3969 +
3970 + if (ret) {
3971 + if (ret == MMAL_MSG_STATUS_ENOSPC) {
3972 + v4l2_err(&dev->v4l2_dev,
3973 + "%s: port has more encodings than we provided space for. Some are dropped (%zu vs %u).\n",
3974 + __func__, param_size / sizeof(u32),
3975 + MAX_SUPPORTED_ENCODINGS);
3976 + num_encodings = MAX_SUPPORTED_ENCODINGS;
3977 + } else {
3978 + v4l2_err(&dev->v4l2_dev, "%s: get_param ret %u.\n",
3979 + __func__, ret);
3980 + ret = -EINVAL;
3981 + goto destroy_component;
3982 + }
3983 + } else {
3984 + num_encodings = param_size / sizeof(u32);
3985 + }
3986 +
3987 + /* Assume at this stage that all encodings will be supported in V4L2.
3988 + * Any that aren't supported will waste a very small amount of memory.
3989 + */
3990 + list = devm_kzalloc(&dev->pdev->dev,
3991 + sizeof(struct bcm2835_codec_fmt) * num_encodings,
3992 + GFP_KERNEL);
3993 + if (!list) {
3994 + ret = -ENOMEM;
3995 + goto destroy_component;
3996 + }
3997 + dev->supported_fmts[0].list = list;
3998 +
3999 + for (i = 0, j = 0; i < num_encodings; i++) {
4000 + const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
4001 +
4002 + if (fmt) {
4003 + list[j] = *fmt;
4004 + j++;
4005 + }
4006 + }
4007 + dev->supported_fmts[0].num_entries = j;
4008 +
4009 + param_size = sizeof(fourccs);
4010 + ret = vchiq_mmal_port_parameter_get(dev->instance,
4011 + &component->output[0],
4012 + MMAL_PARAMETER_SUPPORTED_ENCODINGS,
4013 + &fourccs,
4014 + &param_size);
4015 +
4016 + if (ret) {
4017 + if (ret == MMAL_MSG_STATUS_ENOSPC) {
4018 + v4l2_err(&dev->v4l2_dev,
4019 + "%s: port has more encodings than we provided space for. Some are dropped (%zu vs %u).\n",
4020 + __func__, param_size / sizeof(u32),
4021 + MAX_SUPPORTED_ENCODINGS);
4022 + num_encodings = MAX_SUPPORTED_ENCODINGS;
4023 + } else {
4024 + ret = -EINVAL;
4025 + goto destroy_component;
4026 + }
4027 + } else {
4028 + num_encodings = param_size / sizeof(u32);
4029 + }
4030 + /* Assume at this stage that all encodings will be supported in V4L2. */
4031 + list = devm_kzalloc(&dev->pdev->dev,
4032 + sizeof(struct bcm2835_codec_fmt) * num_encodings,
4033 + GFP_KERNEL);
4034 + if (!list) {
4035 + ret = -ENOMEM;
4036 + goto destroy_component;
4037 + }
4038 + dev->supported_fmts[1].list = list;
4039 +
4040 + for (i = 0, j = 0; i < num_encodings; i++) {
4041 + const struct bcm2835_codec_fmt *fmt = get_fmt(fourccs[i]);
4042 +
4043 + if (fmt) {
4044 + list[j] = *fmt;
4045 + j++;
4046 + }
4047 + }
4048 + dev->supported_fmts[1].num_entries = j;
4049 +
4050 + ret = 0;
4051 +
4052 +destroy_component:
4053 + vchiq_mmal_component_finalise(dev->instance, component);
4054 +
4055 + return ret;
4056 +}
4057 +
4058 +static int bcm2835_codec_create(struct bcm2835_codec_driver *drv,
4059 + struct bcm2835_codec_dev **new_dev,
4060 + enum bcm2835_codec_role role)
4061 +{
4062 + struct platform_device *pdev = drv->pdev;
4063 + struct bcm2835_codec_dev *dev;
4064 + struct video_device *vfd;
4065 + int function;
4066 + int video_nr;
4067 + int ret;
4068 +
4069 + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
4070 + if (!dev)
4071 + return -ENOMEM;
4072 +
4073 + dev->pdev = pdev;
4074 +
4075 + dev->role = role;
4076 +
4077 + ret = vchiq_mmal_init(&dev->instance);
4078 + if (ret)
4079 + return ret;
4080 +
4081 + ret = bcm2835_codec_get_supported_fmts(dev);
4082 + if (ret)
4083 + goto vchiq_finalise;
4084 +
4085 + atomic_set(&dev->num_inst, 0);
4086 + mutex_init(&dev->dev_mutex);
4087 +
4088 + /* Initialise the video device */
4089 + dev->vfd = bcm2835_codec_videodev;
4090 +
4091 + vfd = &dev->vfd;
4092 + vfd->lock = &dev->dev_mutex;
4093 + vfd->v4l2_dev = &dev->v4l2_dev;
4094 + vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
4095 + vfd->v4l2_dev->mdev = &drv->mdev;
4096 +
4097 + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
4098 + if (ret)
4099 + goto vchiq_finalise;
4100 +
4101 + switch (role) {
4102 + case DECODE:
4103 + v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
4104 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
4105 + v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
4106 + v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
4107 + function = MEDIA_ENT_F_PROC_VIDEO_DECODER;
4108 + video_nr = decode_video_nr;
4109 + break;
4110 + case ENCODE:
4111 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
4112 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
4113 + function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
4114 + video_nr = encode_video_nr;
4115 + break;
4116 + case ISP:
4117 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
4118 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
4119 + v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
4120 + v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
4121 + function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
4122 + video_nr = isp_video_nr;
4123 + break;
4124 + case DEINTERLACE:
4125 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
4126 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
4127 + v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
4128 + v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
4129 + function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
4130 + video_nr = deinterlace_video_nr;
4131 + break;
4132 + case ENCODE_IMAGE:
4133 + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
4134 + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
4135 + function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
4136 + video_nr = encode_image_nr;
4137 + break;
4138 + default:
4139 + ret = -EINVAL;
4140 + goto unreg_dev;
4141 + }
4142 +
4143 + ret = video_register_device(vfd, VFL_TYPE_VIDEO, video_nr);
4144 + if (ret) {
4145 + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
4146 + goto unreg_dev;
4147 + }
4148 +
4149 + video_set_drvdata(vfd, dev);
4150 + snprintf(vfd->name, sizeof(vfd->name), "%s-%s",
4151 + bcm2835_codec_videodev.name, roles[role]);
4152 + v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n",
4153 + vfd->num);
4154 +
4155 + *new_dev = dev;
4156 +
4157 + dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
4158 + if (IS_ERR(dev->m2m_dev)) {
4159 + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
4160 + ret = PTR_ERR(dev->m2m_dev);
4161 + goto err_m2m;
4162 + }
4163 +
4164 + ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, function);
4165 + if (ret)
4166 + goto err_m2m;
4167 +
4168 + v4l2_info(&dev->v4l2_dev, "Loaded V4L2 %s\n",
4169 + roles[role]);
4170 + return 0;
4171 +
4172 +err_m2m:
4173 + v4l2_m2m_release(dev->m2m_dev);
4174 + video_unregister_device(&dev->vfd);
4175 +unreg_dev:
4176 + v4l2_device_unregister(&dev->v4l2_dev);
4177 +vchiq_finalise:
4178 + vchiq_mmal_finalise(dev->instance);
4179 + return ret;
4180 +}
4181 +
4182 +static int bcm2835_codec_destroy(struct bcm2835_codec_dev *dev)
4183 +{
4184 + if (!dev)
4185 + return -ENODEV;
4186 +
4187 + v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME ", %s\n",
4188 + roles[dev->role]);
4189 + v4l2_m2m_unregister_media_controller(dev->m2m_dev);
4190 + v4l2_m2m_release(dev->m2m_dev);
4191 + video_unregister_device(&dev->vfd);
4192 + v4l2_device_unregister(&dev->v4l2_dev);
4193 + vchiq_mmal_finalise(dev->instance);
4194 +
4195 + return 0;
4196 +}
4197 +
4198 +static int bcm2835_codec_probe(struct platform_device *pdev)
4199 +{
4200 + struct bcm2835_codec_driver *drv;
4201 + struct media_device *mdev;
4202 + int ret = 0;
4203 +
4204 + drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
4205 + if (!drv)
4206 + return -ENOMEM;
4207 +
4208 + drv->pdev = pdev;
4209 + mdev = &drv->mdev;
4210 + mdev->dev = &pdev->dev;
4211 +
4212 + strscpy(mdev->model, bcm2835_codec_videodev.name, sizeof(mdev->model));
4213 + strscpy(mdev->serial, "0000", sizeof(mdev->serial));
4214 + snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
4215 + pdev->name);
4216 +
4217 + /* This should return the vgencmd version information or such .. */
4218 + mdev->hw_revision = 1;
4219 + media_device_init(mdev);
4220 +
4221 + ret = bcm2835_codec_create(drv, &drv->decode, DECODE);
4222 + if (ret)
4223 + goto out;
4224 +
4225 + ret = bcm2835_codec_create(drv, &drv->encode, ENCODE);
4226 + if (ret)
4227 + goto out;
4228 +
4229 + ret = bcm2835_codec_create(drv, &drv->isp, ISP);
4230 + if (ret)
4231 + goto out;
4232 +
4233 + ret = bcm2835_codec_create(drv, &drv->deinterlace, DEINTERLACE);
4234 + if (ret)
4235 + goto out;
4236 +
4237 + ret = bcm2835_codec_create(drv, &drv->encode_image, ENCODE_IMAGE);
4238 + if (ret)
4239 + goto out;
4240 +
4241 + /* Register the media device node */
4242 + if (media_device_register(mdev) < 0)
4243 + goto out;
4244 +
4245 + platform_set_drvdata(pdev, drv);
4246 +
4247 + return 0;
4248 +
4249 +out:
4250 + if (drv->encode_image) {
4251 + bcm2835_codec_destroy(drv->encode_image);
4252 + drv->encode_image = NULL;
4253 + }
4254 + if (drv->deinterlace) {
4255 + bcm2835_codec_destroy(drv->deinterlace);
4256 + drv->deinterlace = NULL;
4257 + }
4258 + if (drv->isp) {
4259 + bcm2835_codec_destroy(drv->isp);
4260 + drv->isp = NULL;
4261 + }
4262 + if (drv->encode) {
4263 + bcm2835_codec_destroy(drv->encode);
4264 + drv->encode = NULL;
4265 + }
4266 + if (drv->decode) {
4267 + bcm2835_codec_destroy(drv->decode);
4268 + drv->decode = NULL;
4269 + }
4270 + return ret;
4271 +}
4272 +
4273 +static int bcm2835_codec_remove(struct platform_device *pdev)
4274 +{
4275 + struct bcm2835_codec_driver *drv = platform_get_drvdata(pdev);
4276 +
4277 + media_device_unregister(&drv->mdev);
4278 +
4279 + bcm2835_codec_destroy(drv->encode_image);
4280 +
4281 + bcm2835_codec_destroy(drv->deinterlace);
4282 +
4283 + bcm2835_codec_destroy(drv->isp);
4284 +
4285 + bcm2835_codec_destroy(drv->encode);
4286 +
4287 + bcm2835_codec_destroy(drv->decode);
4288 +
4289 + media_device_cleanup(&drv->mdev);
4290 +
4291 + return 0;
4292 +}
4293 +
4294 +static struct platform_driver bcm2835_v4l2_codec_driver = {
4295 + .probe = bcm2835_codec_probe,
4296 + .remove = bcm2835_codec_remove,
4297 + .driver = {
4298 + .name = "bcm2835-codec",
4299 + .owner = THIS_MODULE,
4300 + },
4301 +};
4302 +
4303 +module_platform_driver(bcm2835_v4l2_codec_driver);
4304 +
4305 +MODULE_DESCRIPTION("BCM2835 codec V4L2 driver");
4306 +MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.com>");
4307 +MODULE_LICENSE("GPL");
4308 +MODULE_VERSION("0.0.1");
4309 +MODULE_ALIAS("platform:bcm2835-codec");
4310 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
4311 +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h
4312 @@ -223,6 +223,8 @@ enum mmal_parameter_camera_type {
4313 MMAL_PARAMETER_SHUTTER_SPEED,
4314 /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
4315 MMAL_PARAMETER_CUSTOM_AWB_GAINS,
4316 + /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
4317 + MMAL_PARAMETER_JPEG_IJG_SCALING,
4318 };
4319
4320 enum mmal_parameter_camera_config_timestamp_mode {
4321 @@ -615,6 +617,12 @@ enum mmal_parameter_video_type {
4322
4323 /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T */
4324 MMAL_PARAMETER_VIDEO_ENCODE_HEADERS_WITH_FRAME,
4325 +
4326 + /**< Take a @ref MMAL_PARAMETER_BOOLEAN_T */
4327 + MMAL_PARAMETER_VIDEO_VALIDATE_TIMESTAMPS,
4328 +
4329 + /**< Takes a @ref MMAL_PARAMETER_BOOLEAN_T */
4330 + MMAL_PARAMETER_VIDEO_STOP_ON_PAR_COLOUR_CHANGE,
4331 };
4332
4333 /** Valid mirror modes */