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