brcm2708: update to v3.18
[openwrt/svn-archive/archive.git] / target / linux / brcm2708 / patches-3.18 / 0027-bcm2835-add-v4l2-camera-device.patch
1 From 19c1ada1c282d61163b6a24a6ee53517caec094c Mon Sep 17 00:00:00 2001
2 From: Vincent Sanders <vincent.sanders@collabora.co.uk>
3 Date: Wed, 30 Jan 2013 12:45:18 +0000
4 Subject: [PATCH 027/114] bcm2835: add v4l2 camera device
5
6 - Supports raw YUV capture, preview, JPEG and H264.
7 - Uses videobuf2 for data transfer, using dma_buf.
8 - Uses 3.6.10 timestamping
9 - Camera power based on use
10 - Uses immutable input mode on video encoder
11
12 Signed-off-by: Daniel Stone <daniels@collabora.com>
13 Signed-off-by: Luke Diamand <luked@broadcom.com>
14 ---
15 Documentation/video4linux/bcm2835-v4l2.txt | 60 +
16 drivers/media/platform/Kconfig | 1 +
17 drivers/media/platform/Makefile | 2 +
18 drivers/media/platform/bcm2835/Kconfig | 25 +
19 drivers/media/platform/bcm2835/Makefile | 5 +
20 drivers/media/platform/bcm2835/bcm2835-camera.c | 1476 +++++++++++++++++
21 drivers/media/platform/bcm2835/bcm2835-camera.h | 113 ++
22 drivers/media/platform/bcm2835/controls.c | 725 ++++++++
23 drivers/media/platform/bcm2835/mmal-common.h | 51 +
24 drivers/media/platform/bcm2835/mmal-encodings.h | 93 ++
25 drivers/media/platform/bcm2835/mmal-msg-common.h | 50 +
26 drivers/media/platform/bcm2835/mmal-msg-format.h | 81 +
27 drivers/media/platform/bcm2835/mmal-msg-port.h | 107 ++
28 drivers/media/platform/bcm2835/mmal-msg.h | 404 +++++
29 drivers/media/platform/bcm2835/mmal-parameters.h | 539 ++++++
30 drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 ++++++++++++++++++++++
31 drivers/media/platform/bcm2835/mmal-vchiq.h | 178 ++
32 17 files changed, 5826 insertions(+)
33 create mode 100644 Documentation/video4linux/bcm2835-v4l2.txt
34 create mode 100644 drivers/media/platform/bcm2835/Kconfig
35 create mode 100644 drivers/media/platform/bcm2835/Makefile
36 create mode 100644 drivers/media/platform/bcm2835/bcm2835-camera.c
37 create mode 100644 drivers/media/platform/bcm2835/bcm2835-camera.h
38 create mode 100644 drivers/media/platform/bcm2835/controls.c
39 create mode 100644 drivers/media/platform/bcm2835/mmal-common.h
40 create mode 100644 drivers/media/platform/bcm2835/mmal-encodings.h
41 create mode 100644 drivers/media/platform/bcm2835/mmal-msg-common.h
42 create mode 100644 drivers/media/platform/bcm2835/mmal-msg-format.h
43 create mode 100644 drivers/media/platform/bcm2835/mmal-msg-port.h
44 create mode 100644 drivers/media/platform/bcm2835/mmal-msg.h
45 create mode 100644 drivers/media/platform/bcm2835/mmal-parameters.h
46 create mode 100644 drivers/media/platform/bcm2835/mmal-vchiq.c
47 create mode 100644 drivers/media/platform/bcm2835/mmal-vchiq.h
48
49 diff --git a/Documentation/video4linux/bcm2835-v4l2.txt b/Documentation/video4linux/bcm2835-v4l2.txt
50 new file mode 100644
51 index 0000000..c585a8f
52 --- /dev/null
53 +++ b/Documentation/video4linux/bcm2835-v4l2.txt
54 @@ -0,0 +1,60 @@
55 +
56 +BCM2835 (aka Raspberry Pi) V4L2 driver
57 +======================================
58 +
59 +1. Copyright
60 +============
61 +
62 +Copyright © 2013 Raspberry Pi (Trading) Ltd.
63 +
64 +2. License
65 +==========
66 +
67 +This program is free software; you can redistribute it and/or modify
68 +it under the terms of the GNU General Public License as published by
69 +the Free Software Foundation; either version 2 of the License, or
70 +(at your option) any later version.
71 +
72 +This program is distributed in the hope that it will be useful,
73 +but WITHOUT ANY WARRANTY; without even the implied warranty of
74 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75 +GNU General Public License for more details.
76 +
77 +You should have received a copy of the GNU General Public License
78 +along with this program; if not, write to the Free Software
79 +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
80 +
81 +3. Quick Start
82 +==============
83 +
84 +You need a version 1.0 or later of v4l2-ctl, available from:
85 + git://git.linuxtv.org/v4l-utils.git
86 +
87 +$ sudo modprobe bcm2835-v4l2
88 +
89 +Turn on the overlay:
90 +
91 +$ v4l2-ctl --overlay=1
92 +
93 +Turn off the overlay:
94 +
95 +$ v4l2-ctl --overlay=0
96 +
97 +Set the capture format for video:
98 +
99 +$ v4l2-ctl --set-fmt-video=width=1920,height=1088,pixelformat=4
100 +
101 +(Note: 1088 not 1080).
102 +
103 +Capture:
104 +
105 +$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264
106 +
107 +Stills capture:
108 +
109 +$ v4l2-ctl --set-fmt-video=width=2592,height=1944,pixelformat=3
110 +$ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=somefile.jpg
111 +
112 +List of available formats:
113 +
114 +$ v4l2-ctl --list-formats
115 diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
116 index 3aac88f..9bc18aa 100644
117 --- a/drivers/media/platform/Kconfig
118 +++ b/drivers/media/platform/Kconfig
119 @@ -126,6 +126,7 @@ config VIDEO_S3C_CAMIF
120 source "drivers/media/platform/soc_camera/Kconfig"
121 source "drivers/media/platform/exynos4-is/Kconfig"
122 source "drivers/media/platform/s5p-tv/Kconfig"
123 +source "drivers/media/platform/bcm2835/Kconfig"
124
125 endif # V4L_PLATFORM_DRIVERS
126
127 diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
128 index 579046b..9c9cb34 100644
129 --- a/drivers/media/platform/Makefile
130 +++ b/drivers/media/platform/Makefile
131 @@ -49,4 +49,6 @@ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
132
133 obj-y += omap/
134
135 +obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/
136 +
137 ccflags-y += -I$(srctree)/drivers/media/i2c
138 diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig
139 new file mode 100644
140 index 0000000..a8fd172
141 --- /dev/null
142 +++ b/drivers/media/platform/bcm2835/Kconfig
143 @@ -0,0 +1,25 @@
144 +# Broadcom VideoCore IV v4l2 camera support
145 +
146 +config VIDEO_BCM2835
147 + bool "Broadcom BCM2835 camera interface driver"
148 + depends on VIDEO_V4L2 && ARCH_BCM2708
149 + ---help---
150 + Say Y here to enable camera host interface devices for
151 + Broadcom BCM2835 SoC. This operates over the VCHIQ interface
152 + to a service running on VideoCore.
153 +
154 +
155 +if VIDEO_BCM2835
156 +
157 +config VIDEO_BCM2835_MMAL
158 + tristate "Broadcom BM2835 MMAL camera interface driver"
159 + depends on BCM2708_VCHIQ
160 + select VIDEOBUF2_VMALLOC
161 + ---help---
162 + This is a V4L2 driver for the Broadcom BCM2835 MMAL camera host interface
163 +
164 + To compile this driver as a module, choose M here: the
165 + module will be called bcm2835-v4l2.o
166 +
167 +
168 +endif # VIDEO_BM2835
169 diff --git a/drivers/media/platform/bcm2835/Makefile b/drivers/media/platform/bcm2835/Makefile
170 new file mode 100644
171 index 0000000..f17c79c
172 --- /dev/null
173 +++ b/drivers/media/platform/bcm2835/Makefile
174 @@ -0,0 +1,5 @@
175 +bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o
176 +
177 +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o
178 +
179 +ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
180 diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c
181 new file mode 100644
182 index 0000000..1c9d9d5
183 --- /dev/null
184 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c
185 @@ -0,0 +1,1476 @@
186 +/*
187 + * Broadcom BM2835 V4L2 driver
188 + *
189 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
190 + *
191 + * This file is subject to the terms and conditions of the GNU General Public
192 + * License. See the file COPYING in the main directory of this archive
193 + * for more details.
194 + *
195 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
196 + * Dave Stevenson <dsteve@broadcom.com>
197 + * Simon Mellor <simellor@broadcom.com>
198 + * Luke Diamand <luked@broadcom.com>
199 + */
200 +
201 +#include <linux/errno.h>
202 +#include <linux/kernel.h>
203 +#include <linux/module.h>
204 +#include <linux/slab.h>
205 +#include <media/videobuf2-vmalloc.h>
206 +#include <media/videobuf2-dma-contig.h>
207 +#include <media/v4l2-device.h>
208 +#include <media/v4l2-ioctl.h>
209 +#include <media/v4l2-ctrls.h>
210 +#include <media/v4l2-fh.h>
211 +#include <media/v4l2-event.h>
212 +#include <media/v4l2-common.h>
213 +#include <linux/delay.h>
214 +
215 +#include "mmal-common.h"
216 +#include "mmal-encodings.h"
217 +#include "mmal-vchiq.h"
218 +#include "mmal-msg.h"
219 +#include "mmal-parameters.h"
220 +#include "bcm2835-camera.h"
221 +
222 +#define BM2835_MMAL_VERSION "0.0.2"
223 +#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2"
224 +
225 +#define MAX_WIDTH 2592
226 +#define MAX_HEIGHT 1944
227 +#define MIN_BUFFER_SIZE (80*1024)
228 +
229 +#define MAX_VIDEO_MODE_WIDTH 1280
230 +#define MAX_VIDEO_MODE_HEIGHT 720
231 +
232 +MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
233 +MODULE_AUTHOR("Vincent Sanders");
234 +MODULE_LICENSE("GPL");
235 +MODULE_VERSION(BM2835_MMAL_VERSION);
236 +
237 +int bcm2835_v4l2_debug;
238 +module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
239 +MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
240 +
241 +static struct bm2835_mmal_dev *gdev; /* global device data */
242 +
243 +/* video formats */
244 +static struct mmal_fmt formats[] = {
245 + {
246 + .name = "4:2:0, packed YUV",
247 + .fourcc = V4L2_PIX_FMT_YUV420,
248 + .mmal = MMAL_ENCODING_I420,
249 + .depth = 12,
250 + .mmal_component = MMAL_COMPONENT_CAMERA,
251 + },
252 + {
253 + .name = "4:2:2, packed, YUYV",
254 + .fourcc = V4L2_PIX_FMT_YUYV,
255 + .mmal = MMAL_ENCODING_YUYV,
256 + .depth = 16,
257 + .mmal_component = MMAL_COMPONENT_CAMERA,
258 + },
259 + {
260 + .name = "RGB24 (BE)",
261 + .fourcc = V4L2_PIX_FMT_BGR24,
262 + .mmal = MMAL_ENCODING_BGR24,
263 + .depth = 24,
264 + .mmal_component = MMAL_COMPONENT_CAMERA,
265 + },
266 + {
267 + .name = "JPEG",
268 + .fourcc = V4L2_PIX_FMT_JPEG,
269 + .mmal = MMAL_ENCODING_JPEG,
270 + .depth = 8,
271 + .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
272 + },
273 + {
274 + .name = "H264",
275 + .fourcc = V4L2_PIX_FMT_H264,
276 + .mmal = MMAL_ENCODING_H264,
277 + .depth = 8,
278 + .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
279 + }
280 +};
281 +
282 +static struct mmal_fmt *get_format(struct v4l2_format *f)
283 +{
284 + struct mmal_fmt *fmt;
285 + unsigned int k;
286 +
287 + for (k = 0; k < ARRAY_SIZE(formats); k++) {
288 + fmt = &formats[k];
289 + if (fmt->fourcc == f->fmt.pix.pixelformat)
290 + break;
291 + }
292 +
293 + if (k == ARRAY_SIZE(formats))
294 + return NULL;
295 +
296 + return &formats[k];
297 +}
298 +
299 +/* ------------------------------------------------------------------
300 + Videobuf queue operations
301 + ------------------------------------------------------------------*/
302 +
303 +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
304 + unsigned int *nbuffers, unsigned int *nplanes,
305 + unsigned int sizes[], void *alloc_ctxs[])
306 +{
307 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
308 + unsigned long size;
309 +
310 + /* refuse queue setup if port is not configured */
311 + if (dev->capture.port == NULL) {
312 + v4l2_err(&dev->v4l2_dev,
313 + "%s: capture port not configured\n", __func__);
314 + return -EINVAL;
315 + }
316 +
317 + size = dev->capture.port->current_buffer.size;
318 + if (size == 0) {
319 + v4l2_err(&dev->v4l2_dev,
320 + "%s: capture port buffer size is zero\n", __func__);
321 + return -EINVAL;
322 + }
323 +
324 + if (*nbuffers < (dev->capture.port->current_buffer.num + 2))
325 + *nbuffers = (dev->capture.port->current_buffer.num + 2);
326 +
327 + *nplanes = 1;
328 +
329 + sizes[0] = size;
330 +
331 + /*
332 + * videobuf2-vmalloc allocator is context-less so no need to set
333 + * alloc_ctxs array.
334 + */
335 +
336 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
337 + __func__, dev);
338 +
339 + return 0;
340 +}
341 +
342 +static int buffer_prepare(struct vb2_buffer *vb)
343 +{
344 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
345 + unsigned long size;
346 +
347 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
348 + __func__, dev);
349 +
350 + BUG_ON(dev->capture.port == NULL);
351 + BUG_ON(dev->capture.fmt == NULL);
352 +
353 + size = dev->capture.stride * dev->capture.height;
354 + if (vb2_plane_size(vb, 0) < size) {
355 + v4l2_err(&dev->v4l2_dev,
356 + "%s data will not fit into plane (%lu < %lu)\n",
357 + __func__, vb2_plane_size(vb, 0), size);
358 + return -EINVAL;
359 + }
360 +
361 + return 0;
362 +}
363 +
364 +static inline bool is_capturing(struct bm2835_mmal_dev *dev)
365 +{
366 + return dev->capture.camera_port ==
367 + &dev->
368 + component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE];
369 +}
370 +
371 +static void buffer_cb(struct vchiq_mmal_instance *instance,
372 + struct vchiq_mmal_port *port,
373 + int status,
374 + struct mmal_buffer *buf,
375 + unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
376 +{
377 + struct bm2835_mmal_dev *dev = port->cb_ctx;
378 +
379 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
380 + "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
381 + __func__, status, buf, length, mmal_flags, pts);
382 +
383 + if (status != 0) {
384 + /* error in transfer */
385 + if (buf != NULL) {
386 + /* there was a buffer with the error so return it */
387 + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
388 + }
389 + return;
390 + } else if (length == 0) {
391 + /* stream ended */
392 + if (buf != NULL) {
393 + /* this should only ever happen if the port is
394 + * disabled and there are buffers still queued
395 + */
396 + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
397 + pr_debug("Empty buffer");
398 + } else if (dev->capture.frame_count) {
399 + /* grab another frame */
400 + if (is_capturing(dev)) {
401 + pr_debug("Grab another frame");
402 + vchiq_mmal_port_parameter_set(
403 + instance,
404 + dev->capture.
405 + camera_port,
406 + MMAL_PARAMETER_CAPTURE,
407 + &dev->capture.
408 + frame_count,
409 + sizeof(dev->capture.frame_count));
410 + }
411 + } else {
412 + /* signal frame completion */
413 + complete(&dev->capture.frame_cmplt);
414 + }
415 + } else {
416 + if (dev->capture.frame_count) {
417 + if (dev->capture.vc_start_timestamp != -1) {
418 + s64 runtime_us = pts -
419 + dev->capture.vc_start_timestamp;
420 + u32 div = 0;
421 + u32 rem = 0;
422 +
423 + div =
424 + div_u64_rem(runtime_us, USEC_PER_SEC, &rem);
425 + buf->vb.v4l2_buf.timestamp.tv_sec =
426 + dev->capture.kernel_start_ts.tv_sec - 1 +
427 + div;
428 + buf->vb.v4l2_buf.timestamp.tv_usec =
429 + dev->capture.kernel_start_ts.tv_usec + rem;
430 +
431 + if (buf->vb.v4l2_buf.timestamp.tv_usec >=
432 + USEC_PER_SEC) {
433 + buf->vb.v4l2_buf.timestamp.tv_sec++;
434 + buf->vb.v4l2_buf.timestamp.tv_usec -=
435 + USEC_PER_SEC;
436 + }
437 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
438 + "Convert start time %d.%06d and %llu"
439 + "with offset %llu to %d.%06d\n",
440 + (int)dev->capture.kernel_start_ts.
441 + tv_sec,
442 + (int)dev->capture.kernel_start_ts.
443 + tv_usec,
444 + dev->capture.vc_start_timestamp, pts,
445 + (int)buf->vb.v4l2_buf.timestamp.tv_sec,
446 + (int)buf->vb.v4l2_buf.timestamp.
447 + tv_usec);
448 + } else {
449 + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
450 + }
451 +
452 + vb2_set_plane_payload(&buf->vb, 0, length);
453 + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
454 +
455 + if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
456 + is_capturing(dev)) {
457 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
458 + "Grab another frame as buffer has EOS");
459 + vchiq_mmal_port_parameter_set(
460 + instance,
461 + dev->capture.
462 + camera_port,
463 + MMAL_PARAMETER_CAPTURE,
464 + &dev->capture.
465 + frame_count,
466 + sizeof(dev->capture.frame_count));
467 + }
468 + } else {
469 + /* signal frame completion */
470 + complete(&dev->capture.frame_cmplt);
471 + }
472 + }
473 +}
474 +
475 +static int enable_camera(struct bm2835_mmal_dev *dev)
476 +{
477 + int ret;
478 + if (!dev->camera_use_count) {
479 + ret = vchiq_mmal_component_enable(
480 + dev->instance,
481 + dev->component[MMAL_COMPONENT_CAMERA]);
482 + if (ret < 0) {
483 + v4l2_err(&dev->v4l2_dev,
484 + "Failed enabling camera, ret %d\n", ret);
485 + return -EINVAL;
486 + }
487 + }
488 + dev->camera_use_count++;
489 + v4l2_dbg(1, bcm2835_v4l2_debug,
490 + &dev->v4l2_dev, "enabled camera (refcount %d)\n",
491 + dev->camera_use_count);
492 + return 0;
493 +}
494 +
495 +static int disable_camera(struct bm2835_mmal_dev *dev)
496 +{
497 + int ret;
498 + if (!dev->camera_use_count) {
499 + v4l2_err(&dev->v4l2_dev,
500 + "Disabled the camera when already disabled\n");
501 + return -EINVAL;
502 + }
503 + dev->camera_use_count--;
504 + if (!dev->camera_use_count) {
505 + unsigned int i = 0xFFFFFFFF;
506 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
507 + "Disabling camera\n");
508 + ret =
509 + vchiq_mmal_component_disable(
510 + dev->instance,
511 + dev->component[MMAL_COMPONENT_CAMERA]);
512 + if (ret < 0) {
513 + v4l2_err(&dev->v4l2_dev,
514 + "Failed disabling camera, ret %d\n", ret);
515 + return -EINVAL;
516 + }
517 + vchiq_mmal_port_parameter_set(
518 + dev->instance,
519 + &dev->component[MMAL_COMPONENT_CAMERA]->control,
520 + MMAL_PARAMETER_CAMERA_NUM, &i,
521 + sizeof(i));
522 + }
523 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
524 + "Camera refcount now %d\n", dev->camera_use_count);
525 + return 0;
526 +}
527 +
528 +static void buffer_queue(struct vb2_buffer *vb)
529 +{
530 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
531 + struct mmal_buffer *buf = container_of(vb, struct mmal_buffer, vb);
532 + int ret;
533 +
534 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
535 + "%s: dev:%p buf:%p\n", __func__, dev, buf);
536 +
537 + buf->buffer = vb2_plane_vaddr(&buf->vb, 0);
538 + buf->buffer_size = vb2_plane_size(&buf->vb, 0);
539 +
540 + ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
541 + if (ret < 0)
542 + v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
543 + __func__);
544 +}
545 +
546 +static int start_streaming(struct vb2_queue *vq, unsigned int count)
547 +{
548 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
549 + int ret;
550 + int parameter_size;
551 +
552 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
553 + __func__, dev);
554 +
555 + /* ensure a format has actually been set */
556 + if (dev->capture.port == NULL)
557 + return -EINVAL;
558 +
559 + if (enable_camera(dev) < 0) {
560 + v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n");
561 + return -EINVAL;
562 + }
563 +
564 + /*init_completion(&dev->capture.frame_cmplt); */
565 +
566 + /* enable frame capture */
567 + dev->capture.frame_count = 1;
568 +
569 + /* if the preview is not already running, wait for a few frames for AGC
570 + * to settle down.
571 + */
572 + if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled)
573 + msleep(300);
574 +
575 + /* enable the connection from camera to encoder (if applicable) */
576 + if (dev->capture.camera_port != dev->capture.port
577 + && dev->capture.camera_port) {
578 + ret = vchiq_mmal_port_enable(dev->instance,
579 + dev->capture.camera_port, NULL);
580 + if (ret) {
581 + v4l2_err(&dev->v4l2_dev,
582 + "Failed to enable encode tunnel - error %d\n",
583 + ret);
584 + return -1;
585 + }
586 + }
587 +
588 + /* Get VC timestamp at this point in time */
589 + parameter_size = sizeof(dev->capture.vc_start_timestamp);
590 + if (vchiq_mmal_port_parameter_get(dev->instance,
591 + dev->capture.camera_port,
592 + MMAL_PARAMETER_SYSTEM_TIME,
593 + &dev->capture.vc_start_timestamp,
594 + &parameter_size)) {
595 + v4l2_err(&dev->v4l2_dev,
596 + "Failed to get VC start time - update your VC f/w\n");
597 +
598 + /* Flag to indicate just to rely on kernel timestamps */
599 + dev->capture.vc_start_timestamp = -1;
600 + } else
601 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
602 + "Start time %lld size %d\n",
603 + dev->capture.vc_start_timestamp, parameter_size);
604 +
605 + v4l2_get_timestamp(&dev->capture.kernel_start_ts);
606 +
607 + /* enable the camera port */
608 + dev->capture.port->cb_ctx = dev;
609 + ret =
610 + vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
611 + if (ret) {
612 + v4l2_err(&dev->v4l2_dev,
613 + "Failed to enable capture port - error %d\n", ret);
614 + return -1;
615 + }
616 +
617 + /* capture the first frame */
618 + vchiq_mmal_port_parameter_set(dev->instance,
619 + dev->capture.camera_port,
620 + MMAL_PARAMETER_CAPTURE,
621 + &dev->capture.frame_count,
622 + sizeof(dev->capture.frame_count));
623 + return 0;
624 +}
625 +
626 +/* abort streaming and wait for last buffer */
627 +static int stop_streaming(struct vb2_queue *vq)
628 +{
629 + int ret;
630 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
631 +
632 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
633 + __func__, dev);
634 +
635 + init_completion(&dev->capture.frame_cmplt);
636 + dev->capture.frame_count = 0;
637 +
638 + /* ensure a format has actually been set */
639 + if (dev->capture.port == NULL)
640 + return -EINVAL;
641 +
642 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n");
643 +
644 + /* stop capturing frames */
645 + vchiq_mmal_port_parameter_set(dev->instance,
646 + dev->capture.camera_port,
647 + MMAL_PARAMETER_CAPTURE,
648 + &dev->capture.frame_count,
649 + sizeof(dev->capture.frame_count));
650 +
651 + /* wait for last frame to complete */
652 + ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
653 + if (ret <= 0)
654 + v4l2_err(&dev->v4l2_dev,
655 + "error %d waiting for frame completion\n", ret);
656 +
657 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
658 + "disabling connection\n");
659 +
660 + /* disable the connection from camera to encoder */
661 + ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
662 + if (!ret && dev->capture.camera_port != dev->capture.port) {
663 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
664 + "disabling port\n");
665 + ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
666 + } else if (dev->capture.camera_port != dev->capture.port) {
667 + v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
668 + ret);
669 + }
670 +
671 + if (disable_camera(dev) < 0) {
672 + v4l2_err(&dev->v4l2_dev, "Failed to disable camera");
673 + return -EINVAL;
674 + }
675 +
676 + return ret;
677 +}
678 +
679 +static void bm2835_mmal_lock(struct vb2_queue *vq)
680 +{
681 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
682 + mutex_lock(&dev->mutex);
683 +}
684 +
685 +static void bm2835_mmal_unlock(struct vb2_queue *vq)
686 +{
687 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
688 + mutex_unlock(&dev->mutex);
689 +}
690 +
691 +static struct vb2_ops bm2835_mmal_video_qops = {
692 + .queue_setup = queue_setup,
693 + .buf_prepare = buffer_prepare,
694 + .buf_queue = buffer_queue,
695 + .start_streaming = start_streaming,
696 + .stop_streaming = stop_streaming,
697 + .wait_prepare = bm2835_mmal_unlock,
698 + .wait_finish = bm2835_mmal_lock,
699 +};
700 +
701 +/* ------------------------------------------------------------------
702 + IOCTL operations
703 + ------------------------------------------------------------------*/
704 +
705 +/* overlay ioctl */
706 +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
707 + struct v4l2_fmtdesc *f)
708 +{
709 + struct mmal_fmt *fmt;
710 +
711 + if (f->index >= ARRAY_SIZE(formats))
712 + return -EINVAL;
713 +
714 + fmt = &formats[f->index];
715 +
716 + strlcpy(f->description, fmt->name, sizeof(f->description));
717 + f->pixelformat = fmt->fourcc;
718 +
719 + return 0;
720 +}
721 +
722 +static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
723 + struct v4l2_format *f)
724 +{
725 + struct bm2835_mmal_dev *dev = video_drvdata(file);
726 +
727 + f->fmt.win = dev->overlay;
728 +
729 + return 0;
730 +}
731 +
732 +static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
733 + struct v4l2_format *f)
734 +{
735 + /* Only support one format so get the current one. */
736 + vidioc_g_fmt_vid_overlay(file, priv, f);
737 +
738 + /* todo: allow the size and/or offset to be changed. */
739 + return 0;
740 +}
741 +
742 +static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv,
743 + struct v4l2_format *f)
744 +{
745 + struct bm2835_mmal_dev *dev = video_drvdata(file);
746 +
747 + vidioc_try_fmt_vid_overlay(file, priv, f);
748 +
749 + dev->overlay = f->fmt.win;
750 +
751 + /* todo: program the preview port parameters */
752 + return 0;
753 +}
754 +
755 +static int vidioc_overlay(struct file *file, void *f, unsigned int on)
756 +{
757 + int ret;
758 + struct bm2835_mmal_dev *dev = video_drvdata(file);
759 + struct vchiq_mmal_port *src;
760 + struct vchiq_mmal_port *dst;
761 + struct mmal_parameter_displayregion prev_config = {
762 + .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA |
763 + MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN,
764 + .layer = PREVIEW_LAYER,
765 + .alpha = 255,
766 + .fullscreen = 0,
767 + .dest_rect = {
768 + .x = dev->overlay.w.left,
769 + .y = dev->overlay.w.top,
770 + .width = dev->overlay.w.width,
771 + .height = dev->overlay.w.height,
772 + },
773 + };
774 +
775 + if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) ||
776 + (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled))
777 + return 0; /* already in requested state */
778 +
779 + src =
780 + &dev->component[MMAL_COMPONENT_CAMERA]->
781 + output[MMAL_CAMERA_PORT_PREVIEW];
782 +
783 + if (!on) {
784 + /* disconnect preview ports and disable component */
785 + ret = vchiq_mmal_port_disable(dev->instance, src);
786 + if (!ret)
787 + ret =
788 + vchiq_mmal_port_connect_tunnel(dev->instance, src,
789 + NULL);
790 + if (ret >= 0)
791 + ret = vchiq_mmal_component_disable(
792 + dev->instance,
793 + dev->component[MMAL_COMPONENT_PREVIEW]);
794 +
795 + disable_camera(dev);
796 + return ret;
797 + }
798 +
799 + /* set preview port format and connect it to output */
800 + dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0];
801 +
802 + ret = vchiq_mmal_port_set_format(dev->instance, src);
803 + if (ret < 0)
804 + goto error;
805 +
806 + ret = vchiq_mmal_port_parameter_set(dev->instance, dst,
807 + MMAL_PARAMETER_DISPLAYREGION,
808 + &prev_config, sizeof(prev_config));
809 + if (ret < 0)
810 + goto error;
811 +
812 + if (enable_camera(dev) < 0)
813 + goto error;
814 +
815 + ret = vchiq_mmal_component_enable(
816 + dev->instance,
817 + dev->component[MMAL_COMPONENT_PREVIEW]);
818 + if (ret < 0)
819 + goto error;
820 +
821 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n",
822 + src, dst);
823 + ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst);
824 + if (!ret)
825 + ret = vchiq_mmal_port_enable(dev->instance, src, NULL);
826 +error:
827 + return ret;
828 +}
829 +
830 +static int vidioc_g_fbuf(struct file *file, void *fh,
831 + struct v4l2_framebuffer *a)
832 +{
833 + /* The video overlay must stay within the framebuffer and can't be
834 + positioned independently. */
835 + a->flags = V4L2_FBUF_FLAG_OVERLAY;
836 +
837 + /* todo: v4l2_framebuffer still needs more info filling in
838 + * in order to pass the v4l2-compliance test. */
839 +
840 + return 0;
841 +}
842 +
843 +/* input ioctls */
844 +static int vidioc_enum_input(struct file *file, void *priv,
845 + struct v4l2_input *inp)
846 +{
847 + /* only a single camera input */
848 + if (inp->index != 0)
849 + return -EINVAL;
850 +
851 + inp->type = V4L2_INPUT_TYPE_CAMERA;
852 + sprintf(inp->name, "Camera %u", inp->index);
853 + return 0;
854 +}
855 +
856 +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
857 +{
858 + *i = 0;
859 + return 0;
860 +}
861 +
862 +static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
863 +{
864 + if (i != 0)
865 + return -EINVAL;
866 +
867 + return 0;
868 +}
869 +
870 +/* capture ioctls */
871 +static int vidioc_querycap(struct file *file, void *priv,
872 + struct v4l2_capability *cap)
873 +{
874 + struct bm2835_mmal_dev *dev = video_drvdata(file);
875 + u32 major;
876 + u32 minor;
877 +
878 + vchiq_mmal_version(dev->instance, &major, &minor);
879 +
880 + strcpy(cap->driver, "bm2835 mmal");
881 + snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d",
882 + major, minor);
883 +
884 + snprintf(cap->bus_info, sizeof(cap->bus_info),
885 + "platform:%s", dev->v4l2_dev.name);
886 + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
887 + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
888 + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
889 +
890 + return 0;
891 +}
892 +
893 +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
894 + struct v4l2_fmtdesc *f)
895 +{
896 + struct mmal_fmt *fmt;
897 +
898 + if (f->index >= ARRAY_SIZE(formats))
899 + return -EINVAL;
900 +
901 + fmt = &formats[f->index];
902 +
903 + strlcpy(f->description, fmt->name, sizeof(f->description));
904 + f->pixelformat = fmt->fourcc;
905 + return 0;
906 +}
907 +
908 +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
909 + struct v4l2_format *f)
910 +{
911 + struct bm2835_mmal_dev *dev = video_drvdata(file);
912 +
913 + f->fmt.pix.width = dev->capture.width;
914 + f->fmt.pix.height = dev->capture.height;
915 + f->fmt.pix.field = V4L2_FIELD_NONE;
916 + f->fmt.pix.pixelformat = dev->capture.fmt->fourcc;
917 + f->fmt.pix.bytesperline =
918 + (f->fmt.pix.width * dev->capture.fmt->depth) >> 3;
919 + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
920 + if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG
921 + && f->fmt.pix.sizeimage < (100 << 10)) {
922 + /* Need a minimum size for JPEG to account for EXIF. */
923 + f->fmt.pix.sizeimage = (100 << 10);
924 + }
925 +
926 + if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_YUYV ||
927 + dev->capture.fmt->fourcc == V4L2_PIX_FMT_UYVY)
928 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
929 + else
930 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
931 + f->fmt.pix.priv = 0;
932 +
933 + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
934 + __func__);
935 + return 0;
936 +}
937 +
938 +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
939 + struct v4l2_format *f)
940 +{
941 + struct bm2835_mmal_dev *dev = video_drvdata(file);
942 + struct mmal_fmt *mfmt;
943 +
944 + mfmt = get_format(f);
945 + if (!mfmt) {
946 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
947 + "Fourcc format (0x%08x) unknown.\n",
948 + f->fmt.pix.pixelformat);
949 + f->fmt.pix.pixelformat = formats[0].fourcc;
950 + mfmt = get_format(f);
951 + }
952 +
953 + f->fmt.pix.field = V4L2_FIELD_NONE;
954 + /* image must be a multiple of 32 pixels wide and 16 lines high */
955 + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 5,
956 + &f->fmt.pix.height, 32, MAX_HEIGHT, 4, 0);
957 + f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth) >> 3;
958 + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
959 + if (f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
960 + f->fmt.pix.sizeimage = MIN_BUFFER_SIZE;
961 +
962 + if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
963 + mfmt->fourcc == V4L2_PIX_FMT_UYVY)
964 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
965 + else
966 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
967 + f->fmt.pix.priv = 0;
968 +
969 + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
970 + __func__);
971 + return 0;
972 +}
973 +
974 +static int mmal_setup_components(struct bm2835_mmal_dev *dev,
975 + struct v4l2_format *f)
976 +{
977 + int ret;
978 + struct vchiq_mmal_port *port = NULL, *camera_port = NULL;
979 + struct vchiq_mmal_component *encode_component = NULL;
980 + struct mmal_fmt *mfmt = get_format(f);
981 +
982 + BUG_ON(!mfmt);
983 +
984 + if (dev->capture.encode_component) {
985 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
986 + "vid_cap - disconnect previous tunnel\n");
987 +
988 + /* Disconnect any previous connection */
989 + vchiq_mmal_port_connect_tunnel(dev->instance,
990 + dev->capture.camera_port, NULL);
991 + dev->capture.camera_port = NULL;
992 + ret = vchiq_mmal_component_disable(dev->instance,
993 + dev->capture.
994 + encode_component);
995 + if (ret)
996 + v4l2_err(&dev->v4l2_dev,
997 + "Failed to disable encode component %d\n",
998 + ret);
999 +
1000 + dev->capture.encode_component = NULL;
1001 + }
1002 + /* format dependant port setup */
1003 + switch (mfmt->mmal_component) {
1004 + case MMAL_COMPONENT_CAMERA:
1005 + /* Make a further decision on port based on resolution */
1006 + if (f->fmt.pix.width <= MAX_VIDEO_MODE_WIDTH
1007 + && f->fmt.pix.height <= MAX_VIDEO_MODE_HEIGHT)
1008 + camera_port = port =
1009 + &dev->component[MMAL_COMPONENT_CAMERA]->
1010 + output[MMAL_CAMERA_PORT_VIDEO];
1011 + else
1012 + camera_port = port =
1013 + &dev->component[MMAL_COMPONENT_CAMERA]->
1014 + output[MMAL_CAMERA_PORT_CAPTURE];
1015 + break;
1016 + case MMAL_COMPONENT_IMAGE_ENCODE:
1017 + encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE];
1018 + port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
1019 + camera_port =
1020 + &dev->component[MMAL_COMPONENT_CAMERA]->
1021 + output[MMAL_CAMERA_PORT_CAPTURE];
1022 + break;
1023 + case MMAL_COMPONENT_VIDEO_ENCODE:
1024 + encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE];
1025 + port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
1026 + camera_port =
1027 + &dev->component[MMAL_COMPONENT_CAMERA]->
1028 + output[MMAL_CAMERA_PORT_VIDEO];
1029 + break;
1030 + default:
1031 + break;
1032 + }
1033 +
1034 + if (!port)
1035 + return -EINVAL;
1036 +
1037 + if (encode_component)
1038 + camera_port->format.encoding = MMAL_ENCODING_OPAQUE;
1039 + else
1040 + camera_port->format.encoding = mfmt->mmal;
1041 +
1042 + camera_port->format.encoding_variant = 0;
1043 + camera_port->es.video.width = f->fmt.pix.width;
1044 + camera_port->es.video.height = f->fmt.pix.height;
1045 + camera_port->es.video.crop.x = 0;
1046 + camera_port->es.video.crop.y = 0;
1047 + camera_port->es.video.crop.width = f->fmt.pix.width;
1048 + camera_port->es.video.crop.height = f->fmt.pix.height;
1049 + camera_port->es.video.frame_rate.num = 30;
1050 + camera_port->es.video.frame_rate.den = 1;
1051 +
1052 + ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
1053 +
1054 + if (!ret
1055 + && camera_port ==
1056 + &dev->component[MMAL_COMPONENT_CAMERA]->
1057 + output[MMAL_CAMERA_PORT_VIDEO]) {
1058 + bool overlay_enabled =
1059 + !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled;
1060 + struct vchiq_mmal_port *preview_port =
1061 + &dev->component[MMAL_COMPONENT_CAMERA]->
1062 + output[MMAL_CAMERA_PORT_PREVIEW];
1063 + /* Preview and encode ports need to match on resolution */
1064 + if (overlay_enabled) {
1065 + /* Need to disable the overlay before we can update
1066 + * the resolution
1067 + */
1068 + ret =
1069 + vchiq_mmal_port_disable(dev->instance,
1070 + preview_port);
1071 + if (!ret)
1072 + ret =
1073 + vchiq_mmal_port_connect_tunnel(
1074 + dev->instance,
1075 + preview_port,
1076 + NULL);
1077 + }
1078 + preview_port->es.video.width = f->fmt.pix.width;
1079 + preview_port->es.video.height = f->fmt.pix.height;
1080 + preview_port->es.video.crop.x = 0;
1081 + preview_port->es.video.crop.y = 0;
1082 + preview_port->es.video.crop.width = f->fmt.pix.width;
1083 + preview_port->es.video.crop.height = f->fmt.pix.height;
1084 + preview_port->es.video.frame_rate.num = 30;
1085 + preview_port->es.video.frame_rate.den = 1;
1086 + ret = vchiq_mmal_port_set_format(dev->instance, preview_port);
1087 + if (overlay_enabled) {
1088 + ret = vchiq_mmal_port_connect_tunnel(
1089 + dev->instance,
1090 + preview_port,
1091 + &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
1092 + if (!ret)
1093 + ret = vchiq_mmal_port_enable(dev->instance,
1094 + preview_port,
1095 + NULL);
1096 + }
1097 + }
1098 +
1099 + if (ret) {
1100 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1101 + "%s failed to set format\n", __func__);
1102 + /* ensure capture is not going to be tried */
1103 + dev->capture.port = NULL;
1104 + } else {
1105 + if (encode_component) {
1106 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1107 + "vid_cap - set up encode comp\n");
1108 +
1109 + /* configure buffering */
1110 + camera_port->current_buffer.size =
1111 + camera_port->recommended_buffer.size;
1112 + camera_port->current_buffer.num =
1113 + camera_port->recommended_buffer.num;
1114 +
1115 + port->format.encoding = mfmt->mmal;
1116 + port->format.encoding_variant = 0;
1117 + /* Set any encoding specific parameters */
1118 + switch (mfmt->mmal_component) {
1119 + case MMAL_COMPONENT_VIDEO_ENCODE:
1120 + port->format.bitrate =
1121 + dev->capture.encode_bitrate;
1122 + break;
1123 + case MMAL_COMPONENT_IMAGE_ENCODE:
1124 + /* Could set EXIF parameters here */
1125 + break;
1126 + default:
1127 + break;
1128 + }
1129 + ret = vchiq_mmal_port_set_format(dev->instance, port);
1130 +
1131 + if (ret) {
1132 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1133 + "%s failed to set format\n", __func__);
1134 + } else {
1135 + ret = vchiq_mmal_component_enable(
1136 + dev->instance,
1137 + encode_component);
1138 + if (ret) {
1139 + v4l2_dbg(1, bcm2835_v4l2_debug,
1140 + &dev->v4l2_dev,
1141 + "%s Failed to enable encode components\n",
1142 + __func__);
1143 + } else {
1144 + /* configure buffering */
1145 + port->current_buffer.num = 1;
1146 + port->current_buffer.size =
1147 + f->fmt.pix.sizeimage;
1148 + if (port->format.encoding ==
1149 + MMAL_ENCODING_JPEG) {
1150 + v4l2_dbg(1, bcm2835_v4l2_debug,
1151 + &dev->v4l2_dev,
1152 + "JPEG - fiddle buffer size\n");
1153 + port->current_buffer.size =
1154 + (f->fmt.pix.sizeimage <
1155 + (100 << 10))
1156 + ? (100 << 10) : f->fmt.pix.
1157 + sizeimage;
1158 + }
1159 + v4l2_dbg(1, bcm2835_v4l2_debug,
1160 + &dev->v4l2_dev,
1161 + "vid_cap - current_buffer.size being set to %d\n",
1162 + f->fmt.pix.sizeimage);
1163 + port->current_buffer.alignment = 0;
1164 + ret =
1165 + vchiq_mmal_port_connect_tunnel(
1166 + dev->instance,
1167 + camera_port,
1168 + &encode_component->input[0]);
1169 + if (ret) {
1170 + v4l2_dbg(1, bcm2835_v4l2_debug,
1171 + &dev->v4l2_dev,
1172 + "%s failed to create connection\n",
1173 + __func__);
1174 + /* ensure capture is not going to be tried */
1175 + dev->capture.port = NULL;
1176 + }
1177 + }
1178 + }
1179 + } else {
1180 + /* configure buffering */
1181 + camera_port->current_buffer.num = 1;
1182 + camera_port->current_buffer.size = f->fmt.pix.sizeimage;
1183 + camera_port->current_buffer.alignment = 0;
1184 + }
1185 +
1186 + if (!ret) {
1187 + dev->capture.fmt = mfmt;
1188 + dev->capture.stride = f->fmt.pix.bytesperline;
1189 + dev->capture.width = port->es.video.crop.width;
1190 + dev->capture.height = port->es.video.crop.height;
1191 +
1192 + /* select port for capture */
1193 + dev->capture.port = port;
1194 + dev->capture.camera_port = camera_port;
1195 + dev->capture.encode_component = encode_component;
1196 + }
1197 + }
1198 +
1199 + /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */
1200 + return ret;
1201 +}
1202 +
1203 +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1204 + struct v4l2_format *f)
1205 +{
1206 + int ret;
1207 + struct bm2835_mmal_dev *dev = video_drvdata(file);
1208 + struct mmal_fmt *mfmt;
1209 +
1210 + /* try the format to set valid parameters */
1211 + ret = vidioc_try_fmt_vid_cap(file, priv, f);
1212 + if (ret) {
1213 + v4l2_err(&dev->v4l2_dev,
1214 + "vid_cap - vidioc_try_fmt_vid_cap failed\n");
1215 + return ret;
1216 + }
1217 +
1218 + /* if a capture is running refuse to set format */
1219 + if (vb2_is_busy(&dev->capture.vb_vidq)) {
1220 + v4l2_info(&dev->v4l2_dev, "%s device busy\n", __func__);
1221 + return -EBUSY;
1222 + }
1223 +
1224 + /* If the format is unsupported v4l2 says we should switch to
1225 + * a supported one and not return an error. */
1226 + mfmt = get_format(f);
1227 + if (!mfmt) {
1228 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1229 + "Fourcc format (0x%08x) unknown.\n",
1230 + f->fmt.pix.pixelformat);
1231 + f->fmt.pix.pixelformat = formats[0].fourcc;
1232 + mfmt = get_format(f);
1233 + }
1234 +
1235 + ret = mmal_setup_components(dev, f);
1236 + if (ret != 0)
1237 + v4l2_err(&dev->v4l2_dev,
1238 + "%s: failed to setup mmal components: %d\n",
1239 + __func__, ret);
1240 +
1241 + return ret;
1242 +}
1243 +
1244 +static const struct v4l2_ioctl_ops camera0_ioctl_ops = {
1245 + /* overlay */
1246 + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
1247 + .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
1248 + .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
1249 + .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
1250 + .vidioc_overlay = vidioc_overlay,
1251 + .vidioc_g_fbuf = vidioc_g_fbuf,
1252 +
1253 + /* inputs */
1254 + .vidioc_enum_input = vidioc_enum_input,
1255 + .vidioc_g_input = vidioc_g_input,
1256 + .vidioc_s_input = vidioc_s_input,
1257 +
1258 + /* capture */
1259 + .vidioc_querycap = vidioc_querycap,
1260 + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1261 + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1262 + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1263 + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1264 +
1265 + /* buffer management */
1266 + .vidioc_reqbufs = vb2_ioctl_reqbufs,
1267 + .vidioc_create_bufs = vb2_ioctl_create_bufs,
1268 + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1269 + .vidioc_querybuf = vb2_ioctl_querybuf,
1270 + .vidioc_qbuf = vb2_ioctl_qbuf,
1271 + .vidioc_dqbuf = vb2_ioctl_dqbuf,
1272 + .vidioc_streamon = vb2_ioctl_streamon,
1273 + .vidioc_streamoff = vb2_ioctl_streamoff,
1274 +
1275 + .vidioc_log_status = v4l2_ctrl_log_status,
1276 + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1277 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1278 +};
1279 +
1280 +/* ------------------------------------------------------------------
1281 + Driver init/finalise
1282 + ------------------------------------------------------------------*/
1283 +
1284 +static const struct v4l2_file_operations camera0_fops = {
1285 + .owner = THIS_MODULE,
1286 + .open = v4l2_fh_open,
1287 + .release = vb2_fop_release,
1288 + .read = vb2_fop_read,
1289 + .poll = vb2_fop_poll,
1290 + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
1291 + .mmap = vb2_fop_mmap,
1292 +};
1293 +
1294 +static struct video_device vdev_template = {
1295 + .name = "camera0",
1296 + .fops = &camera0_fops,
1297 + .ioctl_ops = &camera0_ioctl_ops,
1298 + .release = video_device_release_empty,
1299 +};
1300 +
1301 +static int set_camera_parameters(struct vchiq_mmal_instance *instance,
1302 + struct vchiq_mmal_component *camera)
1303 +{
1304 + int ret;
1305 + struct mmal_parameter_camera_config cam_config = {
1306 + .max_stills_w = MAX_WIDTH,
1307 + .max_stills_h = MAX_HEIGHT,
1308 + .stills_yuv422 = 1,
1309 + .one_shot_stills = 1,
1310 + .max_preview_video_w = 1920,
1311 + .max_preview_video_h = 1088,
1312 + .num_preview_video_frames = 3,
1313 + .stills_capture_circular_buffer_height = 0,
1314 + .fast_preview_resume = 0,
1315 + .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC
1316 + };
1317 +
1318 + ret = vchiq_mmal_port_parameter_set(instance, &camera->control,
1319 + MMAL_PARAMETER_CAMERA_CONFIG,
1320 + &cam_config, sizeof(cam_config));
1321 + return ret;
1322 +}
1323 +
1324 +/* MMAL instance and component init */
1325 +static int __init mmal_init(struct bm2835_mmal_dev *dev)
1326 +{
1327 + int ret;
1328 + struct mmal_es_format *format;
1329 +
1330 + ret = vchiq_mmal_init(&dev->instance);
1331 + if (ret < 0)
1332 + return ret;
1333 +
1334 + /* get the camera component ready */
1335 + ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
1336 + &dev->component[MMAL_COMPONENT_CAMERA]);
1337 + if (ret < 0)
1338 + goto unreg_mmal;
1339 +
1340 + if (dev->component[MMAL_COMPONENT_CAMERA]->outputs <
1341 + MMAL_CAMERA_PORT_COUNT) {
1342 + ret = -EINVAL;
1343 + goto unreg_camera;
1344 + }
1345 +
1346 + ret = set_camera_parameters(dev->instance,
1347 + dev->component[MMAL_COMPONENT_CAMERA]);
1348 + if (ret < 0)
1349 + goto unreg_camera;
1350 +
1351 + format =
1352 + &dev->component[MMAL_COMPONENT_CAMERA]->
1353 + output[MMAL_CAMERA_PORT_PREVIEW].format;
1354 +
1355 + format->encoding = MMAL_ENCODING_OPAQUE;
1356 + format->encoding_variant = MMAL_ENCODING_I420;
1357 +
1358 + format->es->video.width = 1024;
1359 + format->es->video.height = 768;
1360 + format->es->video.crop.x = 0;
1361 + format->es->video.crop.y = 0;
1362 + format->es->video.crop.width = 1024;
1363 + format->es->video.crop.height = 768;
1364 + format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
1365 + format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
1366 +
1367 + format =
1368 + &dev->component[MMAL_COMPONENT_CAMERA]->
1369 + output[MMAL_CAMERA_PORT_VIDEO].format;
1370 +
1371 + format->encoding = MMAL_ENCODING_OPAQUE;
1372 + format->encoding_variant = MMAL_ENCODING_I420;
1373 +
1374 + format->es->video.width = 1024;
1375 + format->es->video.height = 768;
1376 + format->es->video.crop.x = 0;
1377 + format->es->video.crop.y = 0;
1378 + format->es->video.crop.width = 1024;
1379 + format->es->video.crop.height = 768;
1380 + format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
1381 + format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
1382 +
1383 + format =
1384 + &dev->component[MMAL_COMPONENT_CAMERA]->
1385 + output[MMAL_CAMERA_PORT_CAPTURE].format;
1386 +
1387 + format->encoding = MMAL_ENCODING_OPAQUE;
1388 +
1389 + format->es->video.width = 2592;
1390 + format->es->video.height = 1944;
1391 + format->es->video.crop.x = 0;
1392 + format->es->video.crop.y = 0;
1393 + format->es->video.crop.width = 2592;
1394 + format->es->video.crop.height = 1944;
1395 + format->es->video.frame_rate.num = 30;
1396 + format->es->video.frame_rate.den = 1;
1397 +
1398 + dev->capture.width = format->es->video.width;
1399 + dev->capture.height = format->es->video.height;
1400 + dev->capture.fmt = &formats[0];
1401 + dev->capture.encode_component = NULL;
1402 +
1403 + /* get the preview component ready */
1404 + ret = vchiq_mmal_component_init(
1405 + dev->instance, "ril.video_render",
1406 + &dev->component[MMAL_COMPONENT_PREVIEW]);
1407 + if (ret < 0)
1408 + goto unreg_camera;
1409 +
1410 + if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
1411 + ret = -EINVAL;
1412 + pr_debug("too few input ports %d needed %d\n",
1413 + dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
1414 + goto unreg_preview;
1415 + }
1416 +
1417 + /* get the image encoder component ready */
1418 + ret = vchiq_mmal_component_init(
1419 + dev->instance, "ril.image_encode",
1420 + &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
1421 + if (ret < 0)
1422 + goto unreg_preview;
1423 +
1424 + if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
1425 + ret = -EINVAL;
1426 + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
1427 + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
1428 + 1);
1429 + goto unreg_image_encoder;
1430 + }
1431 +
1432 + /* get the video encoder component ready */
1433 + ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
1434 + &dev->
1435 + component[MMAL_COMPONENT_VIDEO_ENCODE]);
1436 + if (ret < 0)
1437 + goto unreg_image_encoder;
1438 +
1439 + if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
1440 + ret = -EINVAL;
1441 + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
1442 + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
1443 + 1);
1444 + goto unreg_vid_encoder;
1445 + }
1446 +
1447 + {
1448 + unsigned int enable = 1;
1449 + vchiq_mmal_port_parameter_set(
1450 + dev->instance,
1451 + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
1452 + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
1453 + &enable, sizeof(enable));
1454 +
1455 + vchiq_mmal_port_parameter_set(dev->instance,
1456 + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
1457 + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
1458 + &enable,
1459 + sizeof(enable));
1460 + }
1461 + ret = bm2835_mmal_set_all_camera_controls(dev);
1462 + if (ret < 0)
1463 + goto unreg_vid_encoder;
1464 +
1465 + return 0;
1466 +
1467 +unreg_vid_encoder:
1468 + pr_err("Cleanup: Destroy video encoder\n");
1469 + vchiq_mmal_component_finalise(
1470 + dev->instance,
1471 + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]);
1472 +
1473 +unreg_image_encoder:
1474 + pr_err("Cleanup: Destroy image encoder\n");
1475 + vchiq_mmal_component_finalise(
1476 + dev->instance,
1477 + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
1478 +
1479 +unreg_preview:
1480 + pr_err("Cleanup: Destroy video render\n");
1481 + vchiq_mmal_component_finalise(dev->instance,
1482 + dev->component[MMAL_COMPONENT_PREVIEW]);
1483 +
1484 +unreg_camera:
1485 + pr_err("Cleanup: Destroy camera\n");
1486 + vchiq_mmal_component_finalise(dev->instance,
1487 + dev->component[MMAL_COMPONENT_CAMERA]);
1488 +
1489 +unreg_mmal:
1490 + vchiq_mmal_finalise(dev->instance);
1491 + return ret;
1492 +}
1493 +
1494 +static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
1495 + struct video_device *vfd)
1496 +{
1497 + int ret;
1498 +
1499 + *vfd = vdev_template;
1500 +
1501 + vfd->v4l2_dev = &dev->v4l2_dev;
1502 +
1503 + vfd->lock = &dev->mutex;
1504 +
1505 + vfd->queue = &dev->capture.vb_vidq;
1506 +
1507 + /* video device needs to be able to access instance data */
1508 + video_set_drvdata(vfd, dev);
1509 +
1510 + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1511 + if (ret < 0)
1512 + return ret;
1513 +
1514 + v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
1515 + video_device_node_name(vfd));
1516 +
1517 + return 0;
1518 +}
1519 +
1520 +static struct v4l2_format default_v4l2_format = {
1521 + .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG,
1522 + .fmt.pix.width = 1024,
1523 + .fmt.pix.bytesperline = 1024 * 3 / 2,
1524 + .fmt.pix.height = 768,
1525 + .fmt.pix.sizeimage = 1<<18,
1526 +};
1527 +
1528 +static int __init bm2835_mmal_init(void)
1529 +{
1530 + int ret;
1531 + struct bm2835_mmal_dev *dev;
1532 + struct vb2_queue *q;
1533 +
1534 + dev = kzalloc(sizeof(*gdev), GFP_KERNEL);
1535 + if (!dev)
1536 + return -ENOMEM;
1537 +
1538 + /* setup device defaults */
1539 + dev->overlay.w.left = 150;
1540 + dev->overlay.w.top = 50;
1541 + dev->overlay.w.width = 1024;
1542 + dev->overlay.w.height = 768;
1543 + dev->overlay.clipcount = 0;
1544 + dev->overlay.field = V4L2_FIELD_NONE;
1545 +
1546 + dev->capture.fmt = &formats[3]; /* JPEG */
1547 +
1548 + /* v4l device registration */
1549 + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
1550 + "%s", BM2835_MMAL_MODULE_NAME);
1551 + ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1552 + if (ret)
1553 + goto free_dev;
1554 +
1555 + /* setup v4l controls */
1556 + ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
1557 + if (ret < 0)
1558 + goto unreg_dev;
1559 + dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
1560 +
1561 + /* mmal init */
1562 + ret = mmal_init(dev);
1563 + if (ret < 0)
1564 + goto unreg_dev;
1565 +
1566 + /* initialize queue */
1567 + q = &dev->capture.vb_vidq;
1568 + memset(q, 0, sizeof(*q));
1569 + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1570 + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1571 + q->drv_priv = dev;
1572 + q->buf_struct_size = sizeof(struct mmal_buffer);
1573 + q->ops = &bm2835_mmal_video_qops;
1574 + q->mem_ops = &vb2_vmalloc_memops;
1575 + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1576 + ret = vb2_queue_init(q);
1577 + if (ret < 0)
1578 + goto unreg_dev;
1579 +
1580 + /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */
1581 + mutex_init(&dev->mutex);
1582 +
1583 + /* initialise video devices */
1584 + ret = bm2835_mmal_init_device(dev, &dev->vdev);
1585 + if (ret < 0)
1586 + goto unreg_dev;
1587 +
1588 + ret = mmal_setup_components(dev, &default_v4l2_format);
1589 + if (ret < 0) {
1590 + v4l2_err(&dev->v4l2_dev,
1591 + "%s: could not setup components\n", __func__);
1592 + goto unreg_dev;
1593 + }
1594 +
1595 + v4l2_info(&dev->v4l2_dev,
1596 + "Broadcom 2835 MMAL video capture ver %s loaded.\n",
1597 + BM2835_MMAL_VERSION);
1598 +
1599 + gdev = dev;
1600 + return 0;
1601 +
1602 +unreg_dev:
1603 + v4l2_ctrl_handler_free(&dev->ctrl_handler);
1604 + v4l2_device_unregister(&dev->v4l2_dev);
1605 +
1606 +free_dev:
1607 + kfree(dev);
1608 +
1609 + v4l2_err(&dev->v4l2_dev,
1610 + "%s: error %d while loading driver\n",
1611 + BM2835_MMAL_MODULE_NAME, ret);
1612 +
1613 + return ret;
1614 +}
1615 +
1616 +static void __exit bm2835_mmal_exit(void)
1617 +{
1618 + if (!gdev)
1619 + return;
1620 +
1621 + v4l2_info(&gdev->v4l2_dev, "unregistering %s\n",
1622 + video_device_node_name(&gdev->vdev));
1623 +
1624 + video_unregister_device(&gdev->vdev);
1625 +
1626 + if (gdev->capture.encode_component) {
1627 + v4l2_dbg(1, bcm2835_v4l2_debug, &gdev->v4l2_dev,
1628 + "mmal_exit - disconnect tunnel\n");
1629 + vchiq_mmal_port_connect_tunnel(gdev->instance,
1630 + gdev->capture.camera_port, NULL);
1631 + vchiq_mmal_component_disable(gdev->instance,
1632 + gdev->capture.encode_component);
1633 + }
1634 + vchiq_mmal_component_disable(gdev->instance,
1635 + gdev->component[MMAL_COMPONENT_CAMERA]);
1636 +
1637 + vchiq_mmal_component_finalise(gdev->instance,
1638 + gdev->
1639 + component[MMAL_COMPONENT_VIDEO_ENCODE]);
1640 +
1641 + vchiq_mmal_component_finalise(gdev->instance,
1642 + gdev->
1643 + component[MMAL_COMPONENT_IMAGE_ENCODE]);
1644 +
1645 + vchiq_mmal_component_finalise(gdev->instance,
1646 + gdev->component[MMAL_COMPONENT_PREVIEW]);
1647 +
1648 + vchiq_mmal_component_finalise(gdev->instance,
1649 + gdev->component[MMAL_COMPONENT_CAMERA]);
1650 +
1651 + vchiq_mmal_finalise(gdev->instance);
1652 +
1653 + v4l2_ctrl_handler_free(&gdev->ctrl_handler);
1654 +
1655 + v4l2_device_unregister(&gdev->v4l2_dev);
1656 +
1657 + kfree(gdev);
1658 +}
1659 +
1660 +module_init(bm2835_mmal_init);
1661 +module_exit(bm2835_mmal_exit);
1662 diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h
1663 new file mode 100644
1664 index 0000000..883eab7
1665 --- /dev/null
1666 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h
1667 @@ -0,0 +1,113 @@
1668 +/*
1669 + * Broadcom BM2835 V4L2 driver
1670 + *
1671 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
1672 + *
1673 + * This file is subject to the terms and conditions of the GNU General Public
1674 + * License. See the file COPYING in the main directory of this archive
1675 + * for more details.
1676 + *
1677 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
1678 + * Dave Stevenson <dsteve@broadcom.com>
1679 + * Simon Mellor <simellor@broadcom.com>
1680 + * Luke Diamand <luked@broadcom.com>
1681 + *
1682 + * core driver device
1683 + */
1684 +
1685 +#define V4L2_CTRL_COUNT 18 /* number of v4l controls */
1686 +
1687 +enum {
1688 + MMAL_COMPONENT_CAMERA = 0,
1689 + MMAL_COMPONENT_PREVIEW,
1690 + MMAL_COMPONENT_IMAGE_ENCODE,
1691 + MMAL_COMPONENT_VIDEO_ENCODE,
1692 + MMAL_COMPONENT_COUNT
1693 +};
1694 +
1695 +enum {
1696 + MMAL_CAMERA_PORT_PREVIEW = 0,
1697 + MMAL_CAMERA_PORT_VIDEO,
1698 + MMAL_CAMERA_PORT_CAPTURE,
1699 + MMAL_CAMERA_PORT_COUNT
1700 +};
1701 +
1702 +#define PREVIEW_FRAME_RATE_NUM 30
1703 +#define PREVIEW_FRAME_RATE_DEN 1
1704 +
1705 +#define PREVIEW_LAYER 2
1706 +
1707 +extern int bcm2835_v4l2_debug;
1708 +
1709 +struct bm2835_mmal_dev {
1710 + /* v4l2 devices */
1711 + struct v4l2_device v4l2_dev;
1712 + struct video_device vdev;
1713 + struct mutex mutex;
1714 +
1715 + /* controls */
1716 + struct v4l2_ctrl_handler ctrl_handler;
1717 + struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT];
1718 + struct mmal_colourfx colourfx;
1719 + int hflip;
1720 + int vflip;
1721 +
1722 + /* allocated mmal instance and components */
1723 + struct vchiq_mmal_instance *instance;
1724 + struct vchiq_mmal_component *component[MMAL_COMPONENT_COUNT];
1725 + int camera_use_count;
1726 +
1727 + struct v4l2_window overlay;
1728 +
1729 + struct {
1730 + unsigned int width; /* width */
1731 + unsigned int height; /* height */
1732 + unsigned int stride; /* stride */
1733 + struct mmal_fmt *fmt;
1734 +
1735 + /* H264 encode bitrate */
1736 + int encode_bitrate;
1737 + /* H264 bitrate mode. CBR/VBR */
1738 + int encode_bitrate_mode;
1739 + /* JPEG Q-factor */
1740 + int q_factor;
1741 +
1742 + struct vb2_queue vb_vidq;
1743 +
1744 + /* VC start timestamp for streaming */
1745 + s64 vc_start_timestamp;
1746 + /* Kernel start timestamp for streaming */
1747 + struct timeval kernel_start_ts;
1748 +
1749 + struct vchiq_mmal_port *port; /* port being used for capture */
1750 + /* camera port being used for capture */
1751 + struct vchiq_mmal_port *camera_port;
1752 + /* component being used for encode */
1753 + struct vchiq_mmal_component *encode_component;
1754 + /* number of frames remaining which driver should capture */
1755 + unsigned int frame_count;
1756 + /* last frame completion */
1757 + struct completion frame_cmplt;
1758 +
1759 + } capture;
1760 +
1761 +};
1762 +
1763 +int bm2835_mmal_init_controls(
1764 + struct bm2835_mmal_dev *dev,
1765 + struct v4l2_ctrl_handler *hdl);
1766 +
1767 +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev);
1768 +
1769 +
1770 +/* Debug helpers */
1771 +
1772 +#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \
1773 +{ \
1774 + v4l2_dbg(level, debug, dev, \
1775 +"%s: w %u h %u field %u pfmt 0x%x bpl %u sz_img %u colorspace 0x%x priv %u\n", \
1776 + desc == NULL ? "" : desc, \
1777 + (pix_fmt)->width, (pix_fmt)->height, (pix_fmt)->field, \
1778 + (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \
1779 + (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
1780 +}
1781 diff --git a/drivers/media/platform/bcm2835/controls.c b/drivers/media/platform/bcm2835/controls.c
1782 new file mode 100644
1783 index 0000000..d1408e5
1784 --- /dev/null
1785 +++ b/drivers/media/platform/bcm2835/controls.c
1786 @@ -0,0 +1,725 @@
1787 +/*
1788 + * Broadcom BM2835 V4L2 driver
1789 + *
1790 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
1791 + *
1792 + * This file is subject to the terms and conditions of the GNU General Public
1793 + * License. See the file COPYING in the main directory of this archive
1794 + * for more details.
1795 + *
1796 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
1797 + * Dave Stevenson <dsteve@broadcom.com>
1798 + * Simon Mellor <simellor@broadcom.com>
1799 + * Luke Diamand <luked@broadcom.com>
1800 + */
1801 +
1802 +#include <linux/errno.h>
1803 +#include <linux/kernel.h>
1804 +#include <linux/module.h>
1805 +#include <linux/slab.h>
1806 +#include <media/videobuf2-vmalloc.h>
1807 +#include <media/v4l2-device.h>
1808 +#include <media/v4l2-ioctl.h>
1809 +#include <media/v4l2-ctrls.h>
1810 +#include <media/v4l2-fh.h>
1811 +#include <media/v4l2-event.h>
1812 +#include <media/v4l2-common.h>
1813 +
1814 +#include "mmal-common.h"
1815 +#include "mmal-vchiq.h"
1816 +#include "mmal-parameters.h"
1817 +#include "bcm2835-camera.h"
1818 +
1819 +/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -24 to +24.
1820 + * These are in 1/6th increments so the effective range is -4.0EV to +4.0EV.
1821 + */
1822 +static const s64 ev_bias_qmenu[] = {
1823 + -24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 21, 24
1824 +};
1825 +
1826 +/* Supported ISO values
1827 + * ISOO = auto ISO
1828 + */
1829 +static const s64 iso_qmenu[] = {
1830 + 0, 100, 200, 400, 800,
1831 +};
1832 +
1833 +/* Supported video encode modes */
1834 +static const s64 bitrate_mode_qmenu[] = {
1835 + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
1836 + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
1837 +};
1838 +
1839 +
1840 +enum bm2835_mmal_ctrl_type {
1841 + MMAL_CONTROL_TYPE_STD,
1842 + MMAL_CONTROL_TYPE_STD_MENU,
1843 + MMAL_CONTROL_TYPE_INT_MENU,
1844 + MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */
1845 +};
1846 +
1847 +struct bm2835_mmal_v4l2_ctrl;
1848 +
1849 +typedef int(bm2835_mmal_v4l2_ctrl_cb)(
1850 + struct bm2835_mmal_dev *dev,
1851 + struct v4l2_ctrl *ctrl,
1852 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl);
1853 +
1854 +struct bm2835_mmal_v4l2_ctrl {
1855 + u32 id; /* v4l2 control identifier */
1856 + enum bm2835_mmal_ctrl_type type;
1857 + /* control minimum value or
1858 + * mask for MMAL_CONTROL_TYPE_STD_MENU */
1859 + s32 min;
1860 + s32 max; /* maximum value of control */
1861 + s32 def; /* default value of control */
1862 + s32 step; /* step size of the control */
1863 + const s64 *imenu; /* integer menu array */
1864 + u32 mmal_id; /* mmal parameter id */
1865 + bm2835_mmal_v4l2_ctrl_cb *setter;
1866 +};
1867 +
1868 +struct v4l2_to_mmal_effects_setting {
1869 + u32 v4l2_effect;
1870 + u32 mmal_effect;
1871 + s32 col_fx_enable;
1872 + s32 col_fx_fixed_cbcr;
1873 + u32 u;
1874 + u32 v;
1875 + u32 num_effect_params;
1876 + u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS];
1877 +};
1878 +
1879 +static const struct v4l2_to_mmal_effects_setting
1880 + v4l2_to_mmal_effects_values[] = {
1881 + { V4L2_COLORFX_NONE, MMAL_PARAM_IMAGEFX_NONE,
1882 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1883 + { V4L2_COLORFX_BW, MMAL_PARAM_IMAGEFX_NONE,
1884 + 1, 0, 128, 128, 0, {0, 0, 0, 0, 0} },
1885 + { V4L2_COLORFX_SEPIA, MMAL_PARAM_IMAGEFX_NONE,
1886 + 1, 0, 87, 151, 0, {0, 0, 0, 0, 0} },
1887 + { V4L2_COLORFX_NEGATIVE, MMAL_PARAM_IMAGEFX_NEGATIVE,
1888 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1889 + { V4L2_COLORFX_EMBOSS, MMAL_PARAM_IMAGEFX_EMBOSS,
1890 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1891 + { V4L2_COLORFX_SKETCH, MMAL_PARAM_IMAGEFX_SKETCH,
1892 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1893 + { V4L2_COLORFX_SKY_BLUE, MMAL_PARAM_IMAGEFX_PASTEL,
1894 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1895 + { V4L2_COLORFX_GRASS_GREEN, MMAL_PARAM_IMAGEFX_WATERCOLOUR,
1896 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1897 + { V4L2_COLORFX_SKIN_WHITEN, MMAL_PARAM_IMAGEFX_WASHEDOUT,
1898 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1899 + { V4L2_COLORFX_VIVID, MMAL_PARAM_IMAGEFX_SATURATION,
1900 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1901 + { V4L2_COLORFX_AQUA, MMAL_PARAM_IMAGEFX_NONE,
1902 + 1, 0, 171, 121, 0, {0, 0, 0, 0, 0} },
1903 + { V4L2_COLORFX_ART_FREEZE, MMAL_PARAM_IMAGEFX_HATCH,
1904 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1905 + { V4L2_COLORFX_SILHOUETTE, MMAL_PARAM_IMAGEFX_FILM,
1906 + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
1907 + { V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE,
1908 + 0, 0, 0, 0, 5, {1, 128, 160, 160, 48} },
1909 + { V4L2_COLORFX_ANTIQUE, MMAL_PARAM_IMAGEFX_COLOURBALANCE,
1910 + 0, 0, 0, 0, 3, {108, 274, 238, 0, 0} },
1911 + { V4L2_COLORFX_SET_CBCR, MMAL_PARAM_IMAGEFX_NONE,
1912 + 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} }
1913 +};
1914 +
1915 +
1916 +/* control handlers*/
1917 +
1918 +static int ctrl_set_rational(struct bm2835_mmal_dev *dev,
1919 + struct v4l2_ctrl *ctrl,
1920 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1921 +{
1922 + struct {
1923 + s32 num; /**< Numerator */
1924 + s32 den; /**< Denominator */
1925 + } rational_value;
1926 + struct vchiq_mmal_port *control;
1927 +
1928 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
1929 +
1930 + rational_value.num = ctrl->val;
1931 + rational_value.den = 100;
1932 +
1933 + return vchiq_mmal_port_parameter_set(dev->instance, control,
1934 + mmal_ctrl->mmal_id,
1935 + &rational_value,
1936 + sizeof(rational_value));
1937 +}
1938 +
1939 +static int ctrl_set_value(struct bm2835_mmal_dev *dev,
1940 + struct v4l2_ctrl *ctrl,
1941 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1942 +{
1943 + u32 u32_value;
1944 + struct vchiq_mmal_port *control;
1945 +
1946 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
1947 +
1948 + u32_value = ctrl->val;
1949 +
1950 + return vchiq_mmal_port_parameter_set(dev->instance, control,
1951 + mmal_ctrl->mmal_id,
1952 + &u32_value, sizeof(u32_value));
1953 +}
1954 +
1955 +static int ctrl_set_rotate(struct bm2835_mmal_dev *dev,
1956 + struct v4l2_ctrl *ctrl,
1957 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1958 +{
1959 + int ret;
1960 + u32 u32_value;
1961 + struct vchiq_mmal_component *camera;
1962 +
1963 + camera = dev->component[MMAL_COMPONENT_CAMERA];
1964 +
1965 + u32_value = ((ctrl->val % 360) / 90) * 90;
1966 +
1967 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
1968 + mmal_ctrl->mmal_id,
1969 + &u32_value, sizeof(u32_value));
1970 + if (ret < 0)
1971 + return ret;
1972 +
1973 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
1974 + mmal_ctrl->mmal_id,
1975 + &u32_value, sizeof(u32_value));
1976 + if (ret < 0)
1977 + return ret;
1978 +
1979 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
1980 + mmal_ctrl->mmal_id,
1981 + &u32_value, sizeof(u32_value));
1982 +
1983 + return ret;
1984 +}
1985 +
1986 +static int ctrl_set_flip(struct bm2835_mmal_dev *dev,
1987 + struct v4l2_ctrl *ctrl,
1988 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1989 +{
1990 + int ret;
1991 + u32 u32_value;
1992 + struct vchiq_mmal_component *camera;
1993 +
1994 + if (ctrl->id == V4L2_CID_HFLIP)
1995 + dev->hflip = ctrl->val;
1996 + else
1997 + dev->vflip = ctrl->val;
1998 +
1999 + camera = dev->component[MMAL_COMPONENT_CAMERA];
2000 +
2001 + if (dev->hflip && dev->vflip)
2002 + u32_value = MMAL_PARAM_MIRROR_BOTH;
2003 + else if (dev->hflip)
2004 + u32_value = MMAL_PARAM_MIRROR_HORIZONTAL;
2005 + else if (dev->vflip)
2006 + u32_value = MMAL_PARAM_MIRROR_VERTICAL;
2007 + else
2008 + u32_value = MMAL_PARAM_MIRROR_NONE;
2009 +
2010 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
2011 + mmal_ctrl->mmal_id,
2012 + &u32_value, sizeof(u32_value));
2013 + if (ret < 0)
2014 + return ret;
2015 +
2016 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
2017 + mmal_ctrl->mmal_id,
2018 + &u32_value, sizeof(u32_value));
2019 + if (ret < 0)
2020 + return ret;
2021 +
2022 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
2023 + mmal_ctrl->mmal_id,
2024 + &u32_value, sizeof(u32_value));
2025 +
2026 + return ret;
2027 +
2028 +}
2029 +
2030 +static int ctrl_set_exposure(struct bm2835_mmal_dev *dev,
2031 + struct v4l2_ctrl *ctrl,
2032 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2033 +{
2034 + u32 u32_value;
2035 + struct vchiq_mmal_port *control;
2036 +
2037 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2038 +
2039 + switch (ctrl->val) {
2040 + case V4L2_EXPOSURE_AUTO:
2041 + u32_value = MMAL_PARAM_EXPOSUREMODE_AUTO;
2042 + break;
2043 +
2044 + case V4L2_EXPOSURE_MANUAL:
2045 + u32_value = MMAL_PARAM_EXPOSUREMODE_OFF;
2046 + break;
2047 +
2048 + case V4L2_EXPOSURE_SHUTTER_PRIORITY:
2049 + u32_value = MMAL_PARAM_EXPOSUREMODE_SPORTS;
2050 + break;
2051 +
2052 + case V4L2_EXPOSURE_APERTURE_PRIORITY:
2053 + u32_value = MMAL_PARAM_EXPOSUREMODE_NIGHT;
2054 + break;
2055 +
2056 + }
2057 +
2058 + /* todo: what about the other ten modes there are MMAL parameters for */
2059 + return vchiq_mmal_port_parameter_set(dev->instance, control,
2060 + mmal_ctrl->mmal_id,
2061 + &u32_value, sizeof(u32_value));
2062 +}
2063 +
2064 +static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev,
2065 + struct v4l2_ctrl *ctrl,
2066 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2067 +{
2068 + u32 u32_value;
2069 + struct vchiq_mmal_port *control;
2070 +
2071 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2072 +
2073 + switch (ctrl->val) {
2074 + case V4L2_EXPOSURE_METERING_AVERAGE:
2075 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
2076 + break;
2077 +
2078 + case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
2079 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
2080 + break;
2081 +
2082 + case V4L2_EXPOSURE_METERING_SPOT:
2083 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
2084 + break;
2085 +
2086 + /* todo matrix weighting not added to Linux API till 3.9
2087 + case V4L2_EXPOSURE_METERING_MATRIX:
2088 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
2089 + break;
2090 + */
2091 +
2092 + }
2093 +
2094 + return vchiq_mmal_port_parameter_set(dev->instance, control,
2095 + mmal_ctrl->mmal_id,
2096 + &u32_value, sizeof(u32_value));
2097 +}
2098 +
2099 +static int ctrl_set_awb_mode(struct bm2835_mmal_dev *dev,
2100 + struct v4l2_ctrl *ctrl,
2101 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2102 +{
2103 + u32 u32_value;
2104 + struct vchiq_mmal_port *control;
2105 +
2106 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2107 +
2108 + switch (ctrl->val) {
2109 + case V4L2_WHITE_BALANCE_MANUAL:
2110 + u32_value = MMAL_PARAM_AWBMODE_OFF;
2111 + break;
2112 +
2113 + case V4L2_WHITE_BALANCE_AUTO:
2114 + u32_value = MMAL_PARAM_AWBMODE_AUTO;
2115 + break;
2116 +
2117 + case V4L2_WHITE_BALANCE_INCANDESCENT:
2118 + u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT;
2119 + break;
2120 +
2121 + case V4L2_WHITE_BALANCE_FLUORESCENT:
2122 + u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT;
2123 + break;
2124 +
2125 + case V4L2_WHITE_BALANCE_FLUORESCENT_H:
2126 + u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN;
2127 + break;
2128 +
2129 + case V4L2_WHITE_BALANCE_HORIZON:
2130 + u32_value = MMAL_PARAM_AWBMODE_HORIZON;
2131 + break;
2132 +
2133 + case V4L2_WHITE_BALANCE_DAYLIGHT:
2134 + u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT;
2135 + break;
2136 +
2137 + case V4L2_WHITE_BALANCE_FLASH:
2138 + u32_value = MMAL_PARAM_AWBMODE_FLASH;
2139 + break;
2140 +
2141 + case V4L2_WHITE_BALANCE_CLOUDY:
2142 + u32_value = MMAL_PARAM_AWBMODE_CLOUDY;
2143 + break;
2144 +
2145 + case V4L2_WHITE_BALANCE_SHADE:
2146 + u32_value = MMAL_PARAM_AWBMODE_SHADE;
2147 + break;
2148 +
2149 + }
2150 +
2151 + return vchiq_mmal_port_parameter_set(dev->instance, control,
2152 + mmal_ctrl->mmal_id,
2153 + &u32_value, sizeof(u32_value));
2154 +}
2155 +
2156 +static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev,
2157 + struct v4l2_ctrl *ctrl,
2158 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2159 +{
2160 + int ret = -EINVAL;
2161 + int i, j;
2162 + struct vchiq_mmal_port *control;
2163 + struct mmal_parameter_imagefx_parameters imagefx;
2164 +
2165 + for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) {
2166 + if (ctrl->val == v4l2_to_mmal_effects_values[i].v4l2_effect) {
2167 +
2168 + imagefx.effect =
2169 + v4l2_to_mmal_effects_values[i].mmal_effect;
2170 + imagefx.num_effect_params =
2171 + v4l2_to_mmal_effects_values[i].num_effect_params;
2172 +
2173 + if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS)
2174 + imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS;
2175 +
2176 + for (j = 0; j < imagefx.num_effect_params; j++)
2177 + imagefx.effect_parameter[j] =
2178 + v4l2_to_mmal_effects_values[i].effect_params[j];
2179 +
2180 + dev->colourfx.enable =
2181 + v4l2_to_mmal_effects_values[i].col_fx_enable;
2182 + if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) {
2183 + dev->colourfx.u =
2184 + v4l2_to_mmal_effects_values[i].u;
2185 + dev->colourfx.v =
2186 + v4l2_to_mmal_effects_values[i].v;
2187 + }
2188 +
2189 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2190 +
2191 + ret = vchiq_mmal_port_parameter_set(
2192 + dev->instance, control,
2193 + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
2194 + &imagefx, sizeof(imagefx));
2195 + if (ret)
2196 + goto exit;
2197 +
2198 + ret = vchiq_mmal_port_parameter_set(
2199 + dev->instance, control,
2200 + MMAL_PARAMETER_COLOUR_EFFECT,
2201 + &dev->colourfx, sizeof(dev->colourfx));
2202 + }
2203 + }
2204 +
2205 +exit:
2206 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
2207 + "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n",
2208 + mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect,
2209 + dev->colourfx.enable ? "true" : "false",
2210 + dev->colourfx.u, dev->colourfx.v,
2211 + ret, (ret == 0 ? 0 : -EINVAL));
2212 + return (ret == 0 ? 0 : EINVAL);
2213 +}
2214 +
2215 +static int ctrl_set_colfx(struct bm2835_mmal_dev *dev,
2216 + struct v4l2_ctrl *ctrl,
2217 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2218 +{
2219 + int ret = -EINVAL;
2220 + struct vchiq_mmal_port *control;
2221 +
2222 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2223 +
2224 + dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
2225 + dev->colourfx.enable = ctrl->val & 0xff;
2226 +
2227 + ret = vchiq_mmal_port_parameter_set(dev->instance, control,
2228 + MMAL_PARAMETER_COLOUR_EFFECT,
2229 + &dev->colourfx, sizeof(dev->colourfx));
2230 +
2231 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
2232 + "After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
2233 + mmal_ctrl, ctrl->id, ctrl->val, ret,
2234 + (ret == 0 ? 0 : -EINVAL));
2235 + return (ret == 0 ? 0 : EINVAL);
2236 +}
2237 +
2238 +static int ctrl_set_bitrate(struct bm2835_mmal_dev *dev,
2239 + struct v4l2_ctrl *ctrl,
2240 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2241 +{
2242 + int ret;
2243 + struct vchiq_mmal_port *encoder_out;
2244 +
2245 + dev->capture.encode_bitrate = ctrl->val;
2246 +
2247 + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
2248 +
2249 + ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
2250 + mmal_ctrl->mmal_id,
2251 + &ctrl->val, sizeof(ctrl->val));
2252 + ret = 0;
2253 + return ret;
2254 +}
2255 +
2256 +static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev,
2257 + struct v4l2_ctrl *ctrl,
2258 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2259 +{
2260 + u32 bitrate_mode;
2261 + struct vchiq_mmal_port *encoder_out;
2262 +
2263 + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
2264 +
2265 + dev->capture.encode_bitrate_mode = ctrl->val;
2266 + switch (ctrl->val) {
2267 + default:
2268 + case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
2269 + bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
2270 + break;
2271 + case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
2272 + bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
2273 + break;
2274 + }
2275 +
2276 + vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
2277 + mmal_ctrl->mmal_id,
2278 + &bitrate_mode,
2279 + sizeof(bitrate_mode));
2280 + return 0;
2281 +}
2282 +
2283 +static int ctrl_set_q_factor(struct bm2835_mmal_dev *dev,
2284 + struct v4l2_ctrl *ctrl,
2285 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2286 +{
2287 + u32 u32_value;
2288 + struct vchiq_mmal_port *jpeg_out;
2289 +
2290 + jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
2291 +
2292 + u32_value = ctrl->val;
2293 +
2294 + return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out,
2295 + mmal_ctrl->mmal_id,
2296 + &u32_value, sizeof(u32_value));
2297 +}
2298 +
2299 +static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
2300 +{
2301 + struct bm2835_mmal_dev *dev =
2302 + container_of(ctrl->handler, struct bm2835_mmal_dev,
2303 + ctrl_handler);
2304 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv;
2305 +
2306 + if ((mmal_ctrl == NULL) ||
2307 + (mmal_ctrl->id != ctrl->id) ||
2308 + (mmal_ctrl->setter == NULL)) {
2309 + pr_warn("mmal_ctrl:%p ctrl id:%d\n", mmal_ctrl, ctrl->id);
2310 + return -EINVAL;
2311 + }
2312 +
2313 + return mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
2314 +}
2315 +
2316 +static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = {
2317 + .s_ctrl = bm2835_mmal_s_ctrl,
2318 +};
2319 +
2320 +
2321 +
2322 +static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
2323 + {
2324 + V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD,
2325 + -100, 100, 0, 1, NULL,
2326 + MMAL_PARAMETER_SATURATION, &ctrl_set_rational
2327 + },
2328 + {
2329 + V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD,
2330 + -100, 100, 0, 1, NULL,
2331 + MMAL_PARAMETER_SHARPNESS, &ctrl_set_rational
2332 + },
2333 + {
2334 + V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD,
2335 + -100, 100, 0, 1, NULL,
2336 + MMAL_PARAMETER_CONTRAST, &ctrl_set_rational
2337 + },
2338 + {
2339 + V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD,
2340 + 0, 100, 50, 1, NULL,
2341 + MMAL_PARAMETER_BRIGHTNESS, &ctrl_set_rational
2342 + },
2343 + {
2344 + V4L2_CID_ISO_SENSITIVITY, MMAL_CONTROL_TYPE_INT_MENU,
2345 + 0, ARRAY_SIZE(iso_qmenu) - 1, 0, 1, iso_qmenu,
2346 + MMAL_PARAMETER_ISO, &ctrl_set_value
2347 + },
2348 + {
2349 + V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD,
2350 + 0, 1, 0, 1, NULL,
2351 + MMAL_PARAMETER_VIDEO_STABILISATION, &ctrl_set_value
2352 + },
2353 +/* {
2354 + 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
2355 + },
2356 +*/ {
2357 + V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
2358 + ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
2359 + MMAL_PARAMETER_EXPOSURE_MODE, &ctrl_set_exposure
2360 + },
2361 +/* todo this needs mixing in with set exposure
2362 + {
2363 + V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
2364 + },
2365 + */
2366 + {
2367 + V4L2_CID_AUTO_EXPOSURE_BIAS, MMAL_CONTROL_TYPE_INT_MENU,
2368 + 0, ARRAY_SIZE(ev_bias_qmenu) - 1,
2369 + (ARRAY_SIZE(ev_bias_qmenu)+1)/2 - 1, 0, ev_bias_qmenu,
2370 + MMAL_PARAMETER_EXPOSURE_COMP, &ctrl_set_value
2371 + },
2372 + {
2373 + V4L2_CID_EXPOSURE_METERING,
2374 + MMAL_CONTROL_TYPE_STD_MENU,
2375 + ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
2376 + MMAL_PARAMETER_EXP_METERING_MODE, &ctrl_set_metering_mode
2377 + },
2378 + {
2379 + V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
2380 + MMAL_CONTROL_TYPE_STD_MENU,
2381 + ~0x3fe, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
2382 + MMAL_PARAMETER_AWB_MODE, &ctrl_set_awb_mode
2383 + },
2384 + {
2385 + V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
2386 + 0, 15, V4L2_COLORFX_NONE, 0, NULL,
2387 + MMAL_PARAMETER_IMAGE_EFFECT, &ctrl_set_image_effect
2388 + },
2389 + {
2390 + V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD,
2391 + 0, 0xffff, 0x8080, 1, NULL,
2392 + MMAL_PARAMETER_COLOUR_EFFECT, &ctrl_set_colfx
2393 + },
2394 + {
2395 + V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD,
2396 + 0, 360, 0, 90, NULL,
2397 + MMAL_PARAMETER_ROTATION, &ctrl_set_rotate
2398 + },
2399 + {
2400 + V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD,
2401 + 0, 1, 0, 1, NULL,
2402 + MMAL_PARAMETER_MIRROR, &ctrl_set_flip
2403 + },
2404 + {
2405 + V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD,
2406 + 0, 1, 0, 1, NULL,
2407 + MMAL_PARAMETER_MIRROR, &ctrl_set_flip
2408 + },
2409 + {
2410 + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
2411 + 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
2412 + 0, 0, bitrate_mode_qmenu,
2413 + MMAL_PARAMETER_RATECONTROL, &ctrl_set_bitrate_mode
2414 + },
2415 + {
2416 + V4L2_CID_MPEG_VIDEO_BITRATE, MMAL_CONTROL_TYPE_STD,
2417 + 25*1000, 25*1000*1000, 10*1000*1000, 25*1000, NULL,
2418 + MMAL_PARAMETER_VIDEO_BIT_RATE, &ctrl_set_bitrate
2419 + },
2420 + {
2421 + V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD,
2422 + 0, 100,
2423 + 30, 1, NULL,
2424 + MMAL_PARAMETER_JPEG_Q_FACTOR, &ctrl_set_q_factor
2425 + },
2426 +};
2427 +
2428 +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
2429 +{
2430 + int c;
2431 + int ret;
2432 +
2433 + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2434 + if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) {
2435 + ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c],
2436 + &v4l2_ctrls[c]);
2437 + if (ret)
2438 + break;
2439 + }
2440 + }
2441 + return ret;
2442 +}
2443 +
2444 +int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
2445 + struct v4l2_ctrl_handler *hdl)
2446 +{
2447 + int c;
2448 + const struct bm2835_mmal_v4l2_ctrl *ctrl;
2449 +
2450 + v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT);
2451 +
2452 + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2453 + ctrl = &v4l2_ctrls[c];
2454 +
2455 + switch (ctrl->type) {
2456 + case MMAL_CONTROL_TYPE_STD:
2457 + dev->ctrls[c] = v4l2_ctrl_new_std(hdl,
2458 + &bm2835_mmal_ctrl_ops, ctrl->id,
2459 + ctrl->min, ctrl->max, ctrl->step, ctrl->def);
2460 + break;
2461 +
2462 + case MMAL_CONTROL_TYPE_STD_MENU:
2463 + dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
2464 + &bm2835_mmal_ctrl_ops, ctrl->id,
2465 + ctrl->max, ctrl->min, ctrl->def);
2466 + break;
2467 +
2468 + case MMAL_CONTROL_TYPE_INT_MENU:
2469 + dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
2470 + &bm2835_mmal_ctrl_ops, ctrl->id,
2471 + ctrl->max, ctrl->def, ctrl->imenu);
2472 + break;
2473 +
2474 + case MMAL_CONTROL_TYPE_CLUSTER:
2475 + /* skip this entry when constructing controls */
2476 + continue;
2477 + }
2478 +
2479 + if (hdl->error)
2480 + break;
2481 +
2482 + dev->ctrls[c]->priv = (void *)ctrl;
2483 + }
2484 +
2485 + if (hdl->error) {
2486 + pr_err("error adding control %d/%d id 0x%x\n", c,
2487 + V4L2_CTRL_COUNT, ctrl->id);
2488 + return hdl->error;
2489 + }
2490 +
2491 + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2492 + ctrl = &v4l2_ctrls[c];
2493 +
2494 + switch (ctrl->type) {
2495 + case MMAL_CONTROL_TYPE_CLUSTER:
2496 + v4l2_ctrl_auto_cluster(ctrl->min,
2497 + &dev->ctrls[c+1],
2498 + ctrl->max,
2499 + ctrl->def);
2500 + break;
2501 +
2502 + case MMAL_CONTROL_TYPE_STD:
2503 + case MMAL_CONTROL_TYPE_STD_MENU:
2504 + case MMAL_CONTROL_TYPE_INT_MENU:
2505 + break;
2506 + }
2507 +
2508 + }
2509 +
2510 + return 0;
2511 +}
2512 diff --git a/drivers/media/platform/bcm2835/mmal-common.h b/drivers/media/platform/bcm2835/mmal-common.h
2513 new file mode 100644
2514 index 0000000..84abbb3
2515 --- /dev/null
2516 +++ b/drivers/media/platform/bcm2835/mmal-common.h
2517 @@ -0,0 +1,51 @@
2518 +/*
2519 + * Broadcom BM2835 V4L2 driver
2520 + *
2521 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2522 + *
2523 + * This file is subject to the terms and conditions of the GNU General Public
2524 + * License. See the file COPYING in the main directory of this archive
2525 + * for more details.
2526 + *
2527 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2528 + * Dave Stevenson <dsteve@broadcom.com>
2529 + * Simon Mellor <simellor@broadcom.com>
2530 + * Luke Diamand <luked@broadcom.com>
2531 + *
2532 + * MMAL structures
2533 + *
2534 + */
2535 +
2536 +#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
2537 +#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
2538 +
2539 +/** Special value signalling that time is not known */
2540 +#define MMAL_TIME_UNKNOWN (1LL<<63)
2541 +
2542 +/* mapping between v4l and mmal video modes */
2543 +struct mmal_fmt {
2544 + char *name;
2545 + u32 fourcc; /* v4l2 format id */
2546 + u32 mmal;
2547 + int depth;
2548 + u32 mmal_component; /* MMAL component index to be used to encode */
2549 +};
2550 +
2551 +/* buffer for one video frame */
2552 +struct mmal_buffer {
2553 + /* v4l buffer data -- must be first */
2554 + struct vb2_buffer vb;
2555 +
2556 + /* list of buffers available */
2557 + struct list_head list;
2558 +
2559 + void *buffer; /* buffer pointer */
2560 + unsigned long buffer_size; /* size of allocated buffer */
2561 +};
2562 +
2563 +/* */
2564 +struct mmal_colourfx {
2565 + s32 enable;
2566 + u32 u;
2567 + u32 v;
2568 +};
2569 diff --git a/drivers/media/platform/bcm2835/mmal-encodings.h b/drivers/media/platform/bcm2835/mmal-encodings.h
2570 new file mode 100644
2571 index 0000000..856e80e
2572 --- /dev/null
2573 +++ b/drivers/media/platform/bcm2835/mmal-encodings.h
2574 @@ -0,0 +1,93 @@
2575 +/*
2576 + * Broadcom BM2835 V4L2 driver
2577 + *
2578 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2579 + *
2580 + * This file is subject to the terms and conditions of the GNU General Public
2581 + * License. See the file COPYING in the main directory of this archive
2582 + * for more details.
2583 + *
2584 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2585 + * Dave Stevenson <dsteve@broadcom.com>
2586 + * Simon Mellor <simellor@broadcom.com>
2587 + * Luke Diamand <luked@broadcom.com>
2588 + */
2589 +
2590 +#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4')
2591 +#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3')
2592 +#define MMAL_ENCODING_MP4V MMAL_FOURCC('M', 'P', '4', 'V')
2593 +#define MMAL_ENCODING_MP2V MMAL_FOURCC('M', 'P', '2', 'V')
2594 +#define MMAL_ENCODING_MP1V MMAL_FOURCC('M', 'P', '1', 'V')
2595 +#define MMAL_ENCODING_WMV3 MMAL_FOURCC('W', 'M', 'V', '3')
2596 +#define MMAL_ENCODING_WMV2 MMAL_FOURCC('W', 'M', 'V', '2')
2597 +#define MMAL_ENCODING_WMV1 MMAL_FOURCC('W', 'M', 'V', '1')
2598 +#define MMAL_ENCODING_WVC1 MMAL_FOURCC('W', 'V', 'C', '1')
2599 +#define MMAL_ENCODING_VP8 MMAL_FOURCC('V', 'P', '8', ' ')
2600 +#define MMAL_ENCODING_VP7 MMAL_FOURCC('V', 'P', '7', ' ')
2601 +#define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ')
2602 +#define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O')
2603 +#define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K')
2604 +
2605 +#define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G')
2606 +#define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ')
2607 +#define MMAL_ENCODING_PNG MMAL_FOURCC('P', 'N', 'G', ' ')
2608 +#define MMAL_ENCODING_PPM MMAL_FOURCC('P', 'P', 'M', ' ')
2609 +#define MMAL_ENCODING_TGA MMAL_FOURCC('T', 'G', 'A', ' ')
2610 +#define MMAL_ENCODING_BMP MMAL_FOURCC('B', 'M', 'P', ' ')
2611 +
2612 +#define MMAL_ENCODING_I420 MMAL_FOURCC('I', '4', '2', '0')
2613 +#define MMAL_ENCODING_I420_SLICE MMAL_FOURCC('S', '4', '2', '0')
2614 +#define MMAL_ENCODING_YV12 MMAL_FOURCC('Y', 'V', '1', '2')
2615 +#define MMAL_ENCODING_I422 MMAL_FOURCC('I', '4', '2', '2')
2616 +#define MMAL_ENCODING_I422_SLICE MMAL_FOURCC('S', '4', '2', '2')
2617 +#define MMAL_ENCODING_YUYV MMAL_FOURCC('Y', 'U', 'Y', 'V')
2618 +#define MMAL_ENCODING_YVYU MMAL_FOURCC('Y', 'V', 'Y', 'U')
2619 +#define MMAL_ENCODING_UYVY MMAL_FOURCC('U', 'Y', 'V', 'Y')
2620 +#define MMAL_ENCODING_VYUY MMAL_FOURCC('V', 'Y', 'U', 'Y')
2621 +#define MMAL_ENCODING_NV12 MMAL_FOURCC('N', 'V', '1', '2')
2622 +#define MMAL_ENCODING_NV21 MMAL_FOURCC('N', 'V', '2', '1')
2623 +#define MMAL_ENCODING_ARGB MMAL_FOURCC('A', 'R', 'G', 'B')
2624 +#define MMAL_ENCODING_RGBA MMAL_FOURCC('R', 'G', 'B', 'A')
2625 +#define MMAL_ENCODING_ABGR MMAL_FOURCC('A', 'B', 'G', 'R')
2626 +#define MMAL_ENCODING_BGRA MMAL_FOURCC('B', 'G', 'R', 'A')
2627 +#define MMAL_ENCODING_RGB16 MMAL_FOURCC('R', 'G', 'B', '2')
2628 +#define MMAL_ENCODING_RGB24 MMAL_FOURCC('R', 'G', 'B', '3')
2629 +#define MMAL_ENCODING_RGB32 MMAL_FOURCC('R', 'G', 'B', '4')
2630 +#define MMAL_ENCODING_BGR16 MMAL_FOURCC('B', 'G', 'R', '2')
2631 +#define MMAL_ENCODING_BGR24 MMAL_FOURCC('B', 'G', 'R', '3')
2632 +#define MMAL_ENCODING_BGR32 MMAL_FOURCC('B', 'G', 'R', '4')
2633 +
2634 +/** SAND Video (YUVUV128) format, native format understood by VideoCore.
2635 + * This format is *not* opaque - if requested you will receive full frames
2636 + * of YUV_UV video.
2637 + */
2638 +#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S', 'A', 'N', 'D')
2639 +
2640 +/** VideoCore opaque image format, image handles are returned to
2641 + * the host but not the actual image data.
2642 + */
2643 +#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V')
2644 +
2645 +/** An EGL image handle
2646 + */
2647 +#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I')
2648 +
2649 +/* }@ */
2650 +
2651 +/** \name Pre-defined audio encodings */
2652 +/* @{ */
2653 +#define MMAL_ENCODING_PCM_UNSIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'U')
2654 +#define MMAL_ENCODING_PCM_UNSIGNED_LE MMAL_FOURCC('p', 'c', 'm', 'u')
2655 +#define MMAL_ENCODING_PCM_SIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'S')
2656 +#define MMAL_ENCODING_PCM_SIGNED_LE MMAL_FOURCC('p', 'c', 'm', 's')
2657 +#define MMAL_ENCODING_PCM_FLOAT_BE MMAL_FOURCC('P', 'C', 'M', 'F')
2658 +#define MMAL_ENCODING_PCM_FLOAT_LE MMAL_FOURCC('p', 'c', 'm', 'f')
2659 +
2660 +/* Pre-defined H264 encoding variants */
2661 +
2662 +/** ISO 14496-10 Annex B byte stream format */
2663 +#define MMAL_ENCODING_VARIANT_H264_DEFAULT 0
2664 +/** ISO 14496-15 AVC stream format */
2665 +#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1')
2666 +/** Implicitly delineated NAL units without emulation prevention */
2667 +#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ')
2668 diff --git a/drivers/media/platform/bcm2835/mmal-msg-common.h b/drivers/media/platform/bcm2835/mmal-msg-common.h
2669 new file mode 100644
2670 index 0000000..66e8a6e
2671 --- /dev/null
2672 +++ b/drivers/media/platform/bcm2835/mmal-msg-common.h
2673 @@ -0,0 +1,50 @@
2674 +/*
2675 + * Broadcom BM2835 V4L2 driver
2676 + *
2677 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2678 + *
2679 + * This file is subject to the terms and conditions of the GNU General Public
2680 + * License. See the file COPYING in the main directory of this archive
2681 + * for more details.
2682 + *
2683 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2684 + * Dave Stevenson <dsteve@broadcom.com>
2685 + * Simon Mellor <simellor@broadcom.com>
2686 + * Luke Diamand <luked@broadcom.com>
2687 + */
2688 +
2689 +#ifndef MMAL_MSG_COMMON_H
2690 +#define MMAL_MSG_COMMON_H
2691 +
2692 +enum mmal_msg_status {
2693 + MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
2694 + MMAL_MSG_STATUS_ENOMEM, /**< Out of memory */
2695 + MMAL_MSG_STATUS_ENOSPC, /**< Out of resources other than memory */
2696 + MMAL_MSG_STATUS_EINVAL, /**< Argument is invalid */
2697 + MMAL_MSG_STATUS_ENOSYS, /**< Function not implemented */
2698 + MMAL_MSG_STATUS_ENOENT, /**< No such file or directory */
2699 + MMAL_MSG_STATUS_ENXIO, /**< No such device or address */
2700 + MMAL_MSG_STATUS_EIO, /**< I/O error */
2701 + MMAL_MSG_STATUS_ESPIPE, /**< Illegal seek */
2702 + MMAL_MSG_STATUS_ECORRUPT, /**< Data is corrupt \attention */
2703 + MMAL_MSG_STATUS_ENOTREADY, /**< Component is not ready */
2704 + MMAL_MSG_STATUS_ECONFIG, /**< Component is not configured */
2705 + MMAL_MSG_STATUS_EISCONN, /**< Port is already connected */
2706 + MMAL_MSG_STATUS_ENOTCONN, /**< Port is disconnected */
2707 + MMAL_MSG_STATUS_EAGAIN, /**< Resource temporarily unavailable. */
2708 + MMAL_MSG_STATUS_EFAULT, /**< Bad address */
2709 +};
2710 +
2711 +struct mmal_rect {
2712 + s32 x; /**< x coordinate (from left) */
2713 + s32 y; /**< y coordinate (from top) */
2714 + s32 width; /**< width */
2715 + s32 height; /**< height */
2716 +};
2717 +
2718 +struct mmal_rational {
2719 + s32 num; /**< Numerator */
2720 + s32 den; /**< Denominator */
2721 +};
2722 +
2723 +#endif /* MMAL_MSG_COMMON_H */
2724 diff --git a/drivers/media/platform/bcm2835/mmal-msg-format.h b/drivers/media/platform/bcm2835/mmal-msg-format.h
2725 new file mode 100644
2726 index 0000000..123d86e
2727 --- /dev/null
2728 +++ b/drivers/media/platform/bcm2835/mmal-msg-format.h
2729 @@ -0,0 +1,81 @@
2730 +/*
2731 + * Broadcom BM2835 V4L2 driver
2732 + *
2733 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2734 + *
2735 + * This file is subject to the terms and conditions of the GNU General Public
2736 + * License. See the file COPYING in the main directory of this archive
2737 + * for more details.
2738 + *
2739 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2740 + * Dave Stevenson <dsteve@broadcom.com>
2741 + * Simon Mellor <simellor@broadcom.com>
2742 + * Luke Diamand <luked@broadcom.com>
2743 + */
2744 +
2745 +#ifndef MMAL_MSG_FORMAT_H
2746 +#define MMAL_MSG_FORMAT_H
2747 +
2748 +#include "mmal-msg-common.h"
2749 +
2750 +/* MMAL_ES_FORMAT_T */
2751 +
2752 +
2753 +struct mmal_audio_format {
2754 + u32 channels; /**< Number of audio channels */
2755 + u32 sample_rate; /**< Sample rate */
2756 +
2757 + u32 bits_per_sample; /**< Bits per sample */
2758 + u32 block_align; /**< Size of a block of data */
2759 +};
2760 +
2761 +struct mmal_video_format {
2762 + u32 width; /**< Width of frame in pixels */
2763 + u32 height; /**< Height of frame in rows of pixels */
2764 + struct mmal_rect crop; /**< Visible region of the frame */
2765 + struct mmal_rational frame_rate; /**< Frame rate */
2766 + struct mmal_rational par; /**< Pixel aspect ratio */
2767 +
2768 + /* FourCC specifying the color space of the video stream. See the
2769 + * \ref MmalColorSpace "pre-defined color spaces" for some examples.
2770 + */
2771 + u32 color_space;
2772 +};
2773 +
2774 +struct mmal_subpicture_format {
2775 + u32 x_offset;
2776 + u32 y_offset;
2777 +};
2778 +
2779 +union mmal_es_specific_format {
2780 + struct mmal_audio_format audio;
2781 + struct mmal_video_format video;
2782 + struct mmal_subpicture_format subpicture;
2783 +};
2784 +
2785 +/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
2786 +struct mmal_es_format {
2787 + u32 type; /* enum mmal_es_type */
2788 +
2789 + u32 encoding; /* FourCC specifying encoding of the elementary stream.*/
2790 + u32 encoding_variant; /* FourCC specifying the specific
2791 + * encoding variant of the elementary
2792 + * stream.
2793 + */
2794 +
2795 + union mmal_es_specific_format *es; /* TODO: pointers in
2796 + * message serialisation?!?
2797 + */
2798 + /* Type specific
2799 + * information for the
2800 + * elementary stream
2801 + */
2802 +
2803 + u32 bitrate; /**< Bitrate in bits per second */
2804 + u32 flags; /**< Flags describing properties of the elementary stream. */
2805 +
2806 + u32 extradata_size; /**< Size of the codec specific data */
2807 + u8 *extradata; /**< Codec specific data */
2808 +};
2809 +
2810 +#endif /* MMAL_MSG_FORMAT_H */
2811 diff --git a/drivers/media/platform/bcm2835/mmal-msg-port.h b/drivers/media/platform/bcm2835/mmal-msg-port.h
2812 new file mode 100644
2813 index 0000000..a55c1ea
2814 --- /dev/null
2815 +++ b/drivers/media/platform/bcm2835/mmal-msg-port.h
2816 @@ -0,0 +1,107 @@
2817 +/*
2818 + * Broadcom BM2835 V4L2 driver
2819 + *
2820 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2821 + *
2822 + * This file is subject to the terms and conditions of the GNU General Public
2823 + * License. See the file COPYING in the main directory of this archive
2824 + * for more details.
2825 + *
2826 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2827 + * Dave Stevenson <dsteve@broadcom.com>
2828 + * Simon Mellor <simellor@broadcom.com>
2829 + * Luke Diamand <luked@broadcom.com>
2830 + */
2831 +
2832 +/* MMAL_PORT_TYPE_T */
2833 +enum mmal_port_type {
2834 + MMAL_PORT_TYPE_UNKNOWN = 0, /**< Unknown port type */
2835 + MMAL_PORT_TYPE_CONTROL, /**< Control port */
2836 + MMAL_PORT_TYPE_INPUT, /**< Input port */
2837 + MMAL_PORT_TYPE_OUTPUT, /**< Output port */
2838 + MMAL_PORT_TYPE_CLOCK, /**< Clock port */
2839 +};
2840 +
2841 +/** The port is pass-through and doesn't need buffer headers allocated */
2842 +#define MMAL_PORT_CAPABILITY_PASSTHROUGH 0x01
2843 +/** The port wants to allocate the buffer payloads.
2844 + * This signals a preference that payload allocation should be done
2845 + * on this port for efficiency reasons. */
2846 +#define MMAL_PORT_CAPABILITY_ALLOCATION 0x02
2847 +/** The port supports format change events.
2848 + * This applies to input ports and is used to let the client know
2849 + * whether the port supports being reconfigured via a format
2850 + * change event (i.e. without having to disable the port). */
2851 +#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE 0x04
2852 +
2853 +/* mmal port structure (MMAL_PORT_T)
2854 + *
2855 + * most elements are informational only, the pointer values for
2856 + * interogation messages are generally provided as additional
2857 + * strucures within the message. When used to set values only teh
2858 + * buffer_num, buffer_size and userdata parameters are writable.
2859 + */
2860 +struct mmal_port {
2861 + void *priv; /* Private member used by the framework */
2862 + const char *name; /* Port name. Used for debugging purposes (RO) */
2863 +
2864 + u32 type; /* Type of the port (RO) enum mmal_port_type */
2865 + u16 index; /* Index of the port in its type list (RO) */
2866 + u16 index_all; /* Index of the port in the list of all ports (RO) */
2867 +
2868 + u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
2869 + struct mmal_es_format *format; /* Format of the elementary stream */
2870 +
2871 + u32 buffer_num_min; /* Minimum number of buffers the port
2872 + * requires (RO). This is set by the
2873 + * component.
2874 + */
2875 +
2876 + u32 buffer_size_min; /* Minimum size of buffers the port
2877 + * requires (RO). This is set by the
2878 + * component.
2879 + */
2880 +
2881 + u32 buffer_alignment_min; /* Minimum alignment requirement for
2882 + * the buffers (RO). A value of
2883 + * zero means no special alignment
2884 + * requirements. This is set by the
2885 + * component.
2886 + */
2887 +
2888 + u32 buffer_num_recommended; /* Number of buffers the port
2889 + * recommends for optimal
2890 + * performance (RO). A value of
2891 + * zero means no special
2892 + * recommendation. This is set
2893 + * by the component.
2894 + */
2895 +
2896 + u32 buffer_size_recommended; /* Size of buffers the port
2897 + * recommends for optimal
2898 + * performance (RO). A value of
2899 + * zero means no special
2900 + * recommendation. This is set
2901 + * by the component.
2902 + */
2903 +
2904 + u32 buffer_num; /* Actual number of buffers the port will use.
2905 + * This is set by the client.
2906 + */
2907 +
2908 + u32 buffer_size; /* Actual maximum size of the buffers that
2909 + * will be sent to the port. This is set by
2910 + * the client.
2911 + */
2912 +
2913 + void *component; /* Component this port belongs to (Read Only) */
2914 +
2915 + void *userdata; /* Field reserved for use by the client */
2916 +
2917 + u32 capabilities; /* Flags describing the capabilities of a
2918 + * port (RO). Bitwise combination of \ref
2919 + * portcapabilities "Port capabilities"
2920 + * values.
2921 + */
2922 +
2923 +};
2924 diff --git a/drivers/media/platform/bcm2835/mmal-msg.h b/drivers/media/platform/bcm2835/mmal-msg.h
2925 new file mode 100644
2926 index 0000000..67b1076
2927 --- /dev/null
2928 +++ b/drivers/media/platform/bcm2835/mmal-msg.h
2929 @@ -0,0 +1,404 @@
2930 +/*
2931 + * Broadcom BM2835 V4L2 driver
2932 + *
2933 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2934 + *
2935 + * This file is subject to the terms and conditions of the GNU General Public
2936 + * License. See the file COPYING in the main directory of this archive
2937 + * for more details.
2938 + *
2939 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2940 + * Dave Stevenson <dsteve@broadcom.com>
2941 + * Simon Mellor <simellor@broadcom.com>
2942 + * Luke Diamand <luked@broadcom.com>
2943 + */
2944 +
2945 +/* all the data structures which serialise the MMAL protocol. note
2946 + * these are directly mapped onto the recived message data.
2947 + *
2948 + * BEWARE: They seem to *assume* pointers are u32 and that there is no
2949 + * structure padding!
2950 + *
2951 + * NOTE: this implementation uses kernel types to ensure sizes. Rather
2952 + * than assigning values to enums to force their size the
2953 + * implementation uses fixed size types and not the enums (though the
2954 + * comments have the actual enum type
2955 + */
2956 +
2957 +#define VC_MMAL_VER 15
2958 +#define VC_MMAL_MIN_VER 10
2959 +#define VC_MMAL_SERVER_NAME MAKE_FOURCC("mmal")
2960 +
2961 +/* max total message size is 512 bytes */
2962 +#define MMAL_MSG_MAX_SIZE 512
2963 +/* with six 32bit header elements max payload is therefore 488 bytes */
2964 +#define MMAL_MSG_MAX_PAYLOAD 488
2965 +
2966 +#include "mmal-msg-common.h"
2967 +#include "mmal-msg-format.h"
2968 +#include "mmal-msg-port.h"
2969 +
2970 +enum mmal_msg_type {
2971 + MMAL_MSG_TYPE_QUIT = 1,
2972 + MMAL_MSG_TYPE_SERVICE_CLOSED,
2973 + MMAL_MSG_TYPE_GET_VERSION,
2974 + MMAL_MSG_TYPE_COMPONENT_CREATE,
2975 + MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */
2976 + MMAL_MSG_TYPE_COMPONENT_ENABLE,
2977 + MMAL_MSG_TYPE_COMPONENT_DISABLE,
2978 + MMAL_MSG_TYPE_PORT_INFO_GET,
2979 + MMAL_MSG_TYPE_PORT_INFO_SET,
2980 + MMAL_MSG_TYPE_PORT_ACTION, /* 10 */
2981 + MMAL_MSG_TYPE_BUFFER_FROM_HOST,
2982 + MMAL_MSG_TYPE_BUFFER_TO_HOST,
2983 + MMAL_MSG_TYPE_GET_STATS,
2984 + MMAL_MSG_TYPE_PORT_PARAMETER_SET,
2985 + MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */
2986 + MMAL_MSG_TYPE_EVENT_TO_HOST,
2987 + MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
2988 + MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
2989 + MMAL_MSG_TYPE_CONSUME_MEM,
2990 + MMAL_MSG_TYPE_LMK, /* 20 */
2991 + MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
2992 + MMAL_MSG_TYPE_DRM_GET_LHS32,
2993 + MMAL_MSG_TYPE_DRM_GET_TIME,
2994 + MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
2995 + MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */
2996 + MMAL_MSG_TYPE_HOST_LOG,
2997 + MMAL_MSG_TYPE_MSG_LAST
2998 +};
2999 +
3000 +/* port action request messages differ depending on the action type */
3001 +enum mmal_msg_port_action_type {
3002 + MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0, /* Unkown action */
3003 + MMAL_MSG_PORT_ACTION_TYPE_ENABLE, /* Enable a port */
3004 + MMAL_MSG_PORT_ACTION_TYPE_DISABLE, /* Disable a port */
3005 + MMAL_MSG_PORT_ACTION_TYPE_FLUSH, /* Flush a port */
3006 + MMAL_MSG_PORT_ACTION_TYPE_CONNECT, /* Connect ports */
3007 + MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, /* Disconnect ports */
3008 + MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
3009 +};
3010 +
3011 +struct mmal_msg_header {
3012 + u32 magic;
3013 + u32 type; /** enum mmal_msg_type */
3014 +
3015 + /* Opaque handle to the control service */
3016 + struct mmal_control_service *control_service;
3017 +
3018 + struct mmal_msg_context *context; /** a u32 per message context */
3019 + u32 status; /** The status of the vchiq operation */
3020 + u32 padding;
3021 +};
3022 +
3023 +/* Send from VC to host to report version */
3024 +struct mmal_msg_version {
3025 + u32 flags;
3026 + u32 major;
3027 + u32 minor;
3028 + u32 minimum;
3029 +};
3030 +
3031 +/* request to VC to create component */
3032 +struct mmal_msg_component_create {
3033 + void *client_component; /* component context */
3034 + char name[128];
3035 + u32 pid; /* For debug */
3036 +};
3037 +
3038 +/* reply from VC to component creation request */
3039 +struct mmal_msg_component_create_reply {
3040 + u32 status; /** enum mmal_msg_status - how does this differ to
3041 + * the one in the header?
3042 + */
3043 + u32 component_handle; /* VideoCore handle for component */
3044 + u32 input_num; /* Number of input ports */
3045 + u32 output_num; /* Number of output ports */
3046 + u32 clock_num; /* Number of clock ports */
3047 +};
3048 +
3049 +/* request to VC to destroy a component */
3050 +struct mmal_msg_component_destroy {
3051 + u32 component_handle;
3052 +};
3053 +
3054 +struct mmal_msg_component_destroy_reply {
3055 + u32 status; /** The component destruction status */
3056 +};
3057 +
3058 +
3059 +/* request and reply to VC to enable a component */
3060 +struct mmal_msg_component_enable {
3061 + u32 component_handle;
3062 +};
3063 +
3064 +struct mmal_msg_component_enable_reply {
3065 + u32 status; /** The component enable status */
3066 +};
3067 +
3068 +
3069 +/* request and reply to VC to disable a component */
3070 +struct mmal_msg_component_disable {
3071 + u32 component_handle;
3072 +};
3073 +
3074 +struct mmal_msg_component_disable_reply {
3075 + u32 status; /** The component disable status */
3076 +};
3077 +
3078 +/* request to VC to get port information */
3079 +struct mmal_msg_port_info_get {
3080 + u32 component_handle; /* component handle port is associated with */
3081 + u32 port_type; /* enum mmal_msg_port_type */
3082 + u32 index; /* port index to query */
3083 +};
3084 +
3085 +/* reply from VC to get port info request */
3086 +struct mmal_msg_port_info_get_reply {
3087 + u32 status; /** enum mmal_msg_status */
3088 + u32 component_handle; /* component handle port is associated with */
3089 + u32 port_type; /* enum mmal_msg_port_type */
3090 + u32 port_index; /* port indexed in query */
3091 + s32 found; /* unused */
3092 + u32 port_handle; /**< Handle to use for this port */
3093 + struct mmal_port port;
3094 + struct mmal_es_format format; /* elementry stream format */
3095 + union mmal_es_specific_format es; /* es type specific data */
3096 + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
3097 +};
3098 +
3099 +/* request to VC to set port information */
3100 +struct mmal_msg_port_info_set {
3101 + u32 component_handle;
3102 + u32 port_type; /* enum mmal_msg_port_type */
3103 + u32 port_index; /* port indexed in query */
3104 + struct mmal_port port;
3105 + struct mmal_es_format format;
3106 + union mmal_es_specific_format es;
3107 + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
3108 +};
3109 +
3110 +/* reply from VC to port info set request */
3111 +struct mmal_msg_port_info_set_reply {
3112 + u32 status;
3113 + u32 component_handle; /* component handle port is associated with */
3114 + u32 port_type; /* enum mmal_msg_port_type */
3115 + u32 index; /* port indexed in query */
3116 + s32 found; /* unused */
3117 + u32 port_handle; /**< Handle to use for this port */
3118 + struct mmal_port port;
3119 + struct mmal_es_format format;
3120 + union mmal_es_specific_format es;
3121 + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
3122 +};
3123 +
3124 +
3125 +/* port action requests that take a mmal_port as a parameter */
3126 +struct mmal_msg_port_action_port {
3127 + u32 component_handle;
3128 + u32 port_handle;
3129 + u32 action; /* enum mmal_msg_port_action_type */
3130 + struct mmal_port port;
3131 +};
3132 +
3133 +/* port action requests that take handles as a parameter */
3134 +struct mmal_msg_port_action_handle {
3135 + u32 component_handle;
3136 + u32 port_handle;
3137 + u32 action; /* enum mmal_msg_port_action_type */
3138 + u32 connect_component_handle;
3139 + u32 connect_port_handle;
3140 +};
3141 +
3142 +struct mmal_msg_port_action_reply {
3143 + u32 status; /** The port action operation status */
3144 +};
3145 +
3146 +
3147 +
3148 +
3149 +/* MMAL buffer transfer */
3150 +
3151 +/** Size of space reserved in a buffer message for short messages. */
3152 +#define MMAL_VC_SHORT_DATA 128
3153 +
3154 +/** Signals that the current payload is the end of the stream of data */
3155 +#define MMAL_BUFFER_HEADER_FLAG_EOS (1<<0)
3156 +/** Signals that the start of the current payload starts a frame */
3157 +#define MMAL_BUFFER_HEADER_FLAG_FRAME_START (1<<1)
3158 +/** Signals that the end of the current payload ends a frame */
3159 +#define MMAL_BUFFER_HEADER_FLAG_FRAME_END (1<<2)
3160 +/** Signals that the current payload contains only complete frames (>1) */
3161 +#define MMAL_BUFFER_HEADER_FLAG_FRAME \
3162 + (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
3163 +/** Signals that the current payload is a keyframe (i.e. self decodable) */
3164 +#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME (1<<3)
3165 +/** Signals a discontinuity in the stream of data (e.g. after a seek).
3166 + * Can be used for instance by a decoder to reset its state */
3167 +#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY (1<<4)
3168 +/** Signals a buffer containing some kind of config data for the component
3169 + * (e.g. codec config data) */
3170 +#define MMAL_BUFFER_HEADER_FLAG_CONFIG (1<<5)
3171 +/** Signals an encrypted payload */
3172 +#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED (1<<6)
3173 +/** Signals a buffer containing side information */
3174 +#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO (1<<7)
3175 +/** Signals a buffer which is the snapshot/postview image from a stills
3176 + * capture
3177 + */
3178 +#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT (1<<8)
3179 +/** Signals a buffer which contains data known to be corrupted */
3180 +#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED (1<<9)
3181 +/** Signals that a buffer failed to be transmitted */
3182 +#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED (1<<10)
3183 +
3184 +struct mmal_driver_buffer {
3185 + u32 magic;
3186 + u32 component_handle;
3187 + u32 port_handle;
3188 + void *client_context;
3189 +};
3190 +
3191 +/* buffer header */
3192 +struct mmal_buffer_header {
3193 + struct mmal_buffer_header *next; /* next header */
3194 + void *priv; /* framework private data */
3195 + u32 cmd;
3196 + void *data;
3197 + u32 alloc_size;
3198 + u32 length;
3199 + u32 offset;
3200 + u32 flags;
3201 + s64 pts;
3202 + s64 dts;
3203 + void *type;
3204 + void *user_data;
3205 +};
3206 +
3207 +struct mmal_buffer_header_type_specific {
3208 + union {
3209 + struct {
3210 + u32 planes;
3211 + u32 offset[4];
3212 + u32 pitch[4];
3213 + u32 flags;
3214 + } video;
3215 + } u;
3216 +};
3217 +
3218 +struct mmal_msg_buffer_from_host {
3219 + /* The front 32 bytes of the buffer header are copied
3220 + * back to us in the reply to allow for context. This
3221 + * area is used to store two mmal_driver_buffer structures to
3222 + * allow for multiple concurrent service users.
3223 + */
3224 + /* control data */
3225 + struct mmal_driver_buffer drvbuf;
3226 +
3227 + /* referenced control data for passthrough buffer management */
3228 + struct mmal_driver_buffer drvbuf_ref;
3229 + struct mmal_buffer_header buffer_header; /* buffer header itself */
3230 + struct mmal_buffer_header_type_specific buffer_header_type_specific;
3231 + s32 is_zero_copy;
3232 + s32 has_reference;
3233 +
3234 + /** allows short data to be xfered in control message */
3235 + u32 payload_in_message;
3236 + u8 short_data[MMAL_VC_SHORT_DATA];
3237 +};
3238 +
3239 +
3240 +/* port parameter setting */
3241 +
3242 +#define MMAL_WORKER_PORT_PARAMETER_SPACE 96
3243 +