8e8071db42bd4ac9bb1c338e78c87f796b8af541
[openwrt.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 --- /dev/null
50 +++ b/Documentation/video4linux/bcm2835-v4l2.txt
51 @@ -0,0 +1,60 @@
52 +
53 +BCM2835 (aka Raspberry Pi) V4L2 driver
54 +======================================
55 +
56 +1. Copyright
57 +============
58 +
59 +Copyright © 2013 Raspberry Pi (Trading) Ltd.
60 +
61 +2. License
62 +==========
63 +
64 +This program is free software; you can redistribute it and/or modify
65 +it under the terms of the GNU General Public License as published by
66 +the Free Software Foundation; either version 2 of the License, or
67 +(at your option) any later version.
68 +
69 +This program is distributed in the hope that it will be useful,
70 +but WITHOUT ANY WARRANTY; without even the implied warranty of
71 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
72 +GNU General Public License for more details.
73 +
74 +You should have received a copy of the GNU General Public License
75 +along with this program; if not, write to the Free Software
76 +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
77 +
78 +3. Quick Start
79 +==============
80 +
81 +You need a version 1.0 or later of v4l2-ctl, available from:
82 +       git://git.linuxtv.org/v4l-utils.git
83 +
84 +$ sudo modprobe bcm2835-v4l2
85 +
86 +Turn on the overlay:
87 +
88 +$ v4l2-ctl --overlay=1
89 +
90 +Turn off the overlay:
91 +
92 +$ v4l2-ctl --overlay=0
93 +
94 +Set the capture format for video:
95 +
96 +$ v4l2-ctl  --set-fmt-video=width=1920,height=1088,pixelformat=4
97 +
98 +(Note: 1088 not 1080).
99 +
100 +Capture:
101 +
102 +$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264
103 +
104 +Stills capture:
105 +
106 +$ v4l2-ctl  --set-fmt-video=width=2592,height=1944,pixelformat=3
107 +$ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=somefile.jpg
108 +
109 +List of available formats:
110 +
111 +$ v4l2-ctl --list-formats
112 --- a/drivers/media/platform/Kconfig
113 +++ b/drivers/media/platform/Kconfig
114 @@ -126,6 +126,7 @@ config VIDEO_S3C_CAMIF
115  source "drivers/media/platform/soc_camera/Kconfig"
116  source "drivers/media/platform/exynos4-is/Kconfig"
117  source "drivers/media/platform/s5p-tv/Kconfig"
118 +source "drivers/media/platform/bcm2835/Kconfig"
119  
120  endif # V4L_PLATFORM_DRIVERS
121  
122 --- a/drivers/media/platform/Makefile
123 +++ b/drivers/media/platform/Makefile
124 @@ -49,4 +49,6 @@ obj-$(CONFIG_VIDEO_RENESAS_VSP1)      += vsp1
125  
126  obj-y  += omap/
127  
128 +obj-$(CONFIG_VIDEO_BCM2835)            += bcm2835/
129 +
130  ccflags-y += -I$(srctree)/drivers/media/i2c
131 --- /dev/null
132 +++ b/drivers/media/platform/bcm2835/Kconfig
133 @@ -0,0 +1,25 @@
134 +# Broadcom VideoCore IV v4l2 camera support
135 +
136 +config VIDEO_BCM2835
137 +       bool "Broadcom BCM2835 camera interface driver"
138 +       depends on VIDEO_V4L2 && ARCH_BCM2708
139 +       ---help---
140 +         Say Y here to enable camera host interface devices for
141 +         Broadcom BCM2835 SoC. This operates over the VCHIQ interface
142 +         to a service running on VideoCore.
143 +
144 +
145 +if VIDEO_BCM2835
146 +
147 +config VIDEO_BCM2835_MMAL
148 +       tristate "Broadcom BM2835 MMAL camera interface driver"
149 +       depends on BCM2708_VCHIQ
150 +       select VIDEOBUF2_VMALLOC
151 +       ---help---
152 +         This is a V4L2 driver for the Broadcom BCM2835 MMAL camera host interface
153 +
154 +         To compile this driver as a module, choose M here: the
155 +         module will be called bcm2835-v4l2.o
156 +
157 +
158 +endif # VIDEO_BM2835
159 --- /dev/null
160 +++ b/drivers/media/platform/bcm2835/Makefile
161 @@ -0,0 +1,5 @@
162 +bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o
163 +
164 +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o
165 +
166 +ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
167 --- /dev/null
168 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c
169 @@ -0,0 +1,1476 @@
170 +/*
171 + * Broadcom BM2835 V4L2 driver
172 + *
173 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
174 + *
175 + * This file is subject to the terms and conditions of the GNU General Public
176 + * License.  See the file COPYING in the main directory of this archive
177 + * for more details.
178 + *
179 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
180 + *          Dave Stevenson <dsteve@broadcom.com>
181 + *          Simon Mellor <simellor@broadcom.com>
182 + *          Luke Diamand <luked@broadcom.com>
183 + */
184 +
185 +#include <linux/errno.h>
186 +#include <linux/kernel.h>
187 +#include <linux/module.h>
188 +#include <linux/slab.h>
189 +#include <media/videobuf2-vmalloc.h>
190 +#include <media/videobuf2-dma-contig.h>
191 +#include <media/v4l2-device.h>
192 +#include <media/v4l2-ioctl.h>
193 +#include <media/v4l2-ctrls.h>
194 +#include <media/v4l2-fh.h>
195 +#include <media/v4l2-event.h>
196 +#include <media/v4l2-common.h>
197 +#include <linux/delay.h>
198 +
199 +#include "mmal-common.h"
200 +#include "mmal-encodings.h"
201 +#include "mmal-vchiq.h"
202 +#include "mmal-msg.h"
203 +#include "mmal-parameters.h"
204 +#include "bcm2835-camera.h"
205 +
206 +#define BM2835_MMAL_VERSION "0.0.2"
207 +#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2"
208 +
209 +#define MAX_WIDTH 2592
210 +#define MAX_HEIGHT 1944
211 +#define MIN_BUFFER_SIZE (80*1024)
212 +
213 +#define MAX_VIDEO_MODE_WIDTH 1280
214 +#define MAX_VIDEO_MODE_HEIGHT 720
215 +
216 +MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
217 +MODULE_AUTHOR("Vincent Sanders");
218 +MODULE_LICENSE("GPL");
219 +MODULE_VERSION(BM2835_MMAL_VERSION);
220 +
221 +int bcm2835_v4l2_debug;
222 +module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
223 +MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
224 +
225 +static struct bm2835_mmal_dev *gdev;   /* global device data */
226 +
227 +/* video formats */
228 +static struct mmal_fmt formats[] = {
229 +       {
230 +        .name = "4:2:0, packed YUV",
231 +        .fourcc = V4L2_PIX_FMT_YUV420,
232 +        .mmal = MMAL_ENCODING_I420,
233 +        .depth = 12,
234 +        .mmal_component = MMAL_COMPONENT_CAMERA,
235 +        },
236 +       {
237 +        .name = "4:2:2, packed, YUYV",
238 +        .fourcc = V4L2_PIX_FMT_YUYV,
239 +        .mmal = MMAL_ENCODING_YUYV,
240 +        .depth = 16,
241 +        .mmal_component = MMAL_COMPONENT_CAMERA,
242 +        },
243 +       {
244 +        .name = "RGB24 (BE)",
245 +        .fourcc = V4L2_PIX_FMT_BGR24,
246 +        .mmal = MMAL_ENCODING_BGR24,
247 +        .depth = 24,
248 +        .mmal_component = MMAL_COMPONENT_CAMERA,
249 +        },
250 +       {
251 +        .name = "JPEG",
252 +        .fourcc = V4L2_PIX_FMT_JPEG,
253 +        .mmal = MMAL_ENCODING_JPEG,
254 +        .depth = 8,
255 +        .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
256 +        },
257 +       {
258 +        .name = "H264",
259 +        .fourcc = V4L2_PIX_FMT_H264,
260 +        .mmal = MMAL_ENCODING_H264,
261 +        .depth = 8,
262 +        .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
263 +        }
264 +};
265 +
266 +static struct mmal_fmt *get_format(struct v4l2_format *f)
267 +{
268 +       struct mmal_fmt *fmt;
269 +       unsigned int k;
270 +
271 +       for (k = 0; k < ARRAY_SIZE(formats); k++) {
272 +               fmt = &formats[k];
273 +               if (fmt->fourcc == f->fmt.pix.pixelformat)
274 +                       break;
275 +       }
276 +
277 +       if (k == ARRAY_SIZE(formats))
278 +               return NULL;
279 +
280 +       return &formats[k];
281 +}
282 +
283 +/* ------------------------------------------------------------------
284 +       Videobuf queue operations
285 +   ------------------------------------------------------------------*/
286 +
287 +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
288 +                      unsigned int *nbuffers, unsigned int *nplanes,
289 +                      unsigned int sizes[], void *alloc_ctxs[])
290 +{
291 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
292 +       unsigned long size;
293 +
294 +       /* refuse queue setup if port is not configured */
295 +       if (dev->capture.port == NULL) {
296 +               v4l2_err(&dev->v4l2_dev,
297 +                        "%s: capture port not configured\n", __func__);
298 +               return -EINVAL;
299 +       }
300 +
301 +       size = dev->capture.port->current_buffer.size;
302 +       if (size == 0) {
303 +               v4l2_err(&dev->v4l2_dev,
304 +                        "%s: capture port buffer size is zero\n", __func__);
305 +               return -EINVAL;
306 +       }
307 +
308 +       if (*nbuffers < (dev->capture.port->current_buffer.num + 2))
309 +               *nbuffers = (dev->capture.port->current_buffer.num + 2);
310 +
311 +       *nplanes = 1;
312 +
313 +       sizes[0] = size;
314 +
315 +       /*
316 +        * videobuf2-vmalloc allocator is context-less so no need to set
317 +        * alloc_ctxs array.
318 +        */
319 +
320 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
321 +                __func__, dev);
322 +
323 +       return 0;
324 +}
325 +
326 +static int buffer_prepare(struct vb2_buffer *vb)
327 +{
328 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
329 +       unsigned long size;
330 +
331 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
332 +                __func__, dev);
333 +
334 +       BUG_ON(dev->capture.port == NULL);
335 +       BUG_ON(dev->capture.fmt == NULL);
336 +
337 +       size = dev->capture.stride * dev->capture.height;
338 +       if (vb2_plane_size(vb, 0) < size) {
339 +               v4l2_err(&dev->v4l2_dev,
340 +                        "%s data will not fit into plane (%lu < %lu)\n",
341 +                        __func__, vb2_plane_size(vb, 0), size);
342 +               return -EINVAL;
343 +       }
344 +
345 +       return 0;
346 +}
347 +
348 +static inline bool is_capturing(struct bm2835_mmal_dev *dev)
349 +{
350 +       return dev->capture.camera_port ==
351 +           &dev->
352 +           component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE];
353 +}
354 +
355 +static void buffer_cb(struct vchiq_mmal_instance *instance,
356 +                     struct vchiq_mmal_port *port,
357 +                     int status,
358 +                     struct mmal_buffer *buf,
359 +                     unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
360 +{
361 +       struct bm2835_mmal_dev *dev = port->cb_ctx;
362 +
363 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
364 +                "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
365 +                __func__, status, buf, length, mmal_flags, pts);
366 +
367 +       if (status != 0) {
368 +               /* error in transfer */
369 +               if (buf != NULL) {
370 +                       /* there was a buffer with the error so return it */
371 +                       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
372 +               }
373 +               return;
374 +       } else if (length == 0) {
375 +               /* stream ended */
376 +               if (buf != NULL) {
377 +                       /* this should only ever happen if the port is
378 +                        * disabled and there are buffers still queued
379 +                        */
380 +                       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
381 +                       pr_debug("Empty buffer");
382 +               } else if (dev->capture.frame_count) {
383 +                       /* grab another frame */
384 +                       if (is_capturing(dev)) {
385 +                               pr_debug("Grab another frame");
386 +                               vchiq_mmal_port_parameter_set(
387 +                                       instance,
388 +                                       dev->capture.
389 +                                       camera_port,
390 +                                       MMAL_PARAMETER_CAPTURE,
391 +                                       &dev->capture.
392 +                                       frame_count,
393 +                                       sizeof(dev->capture.frame_count));
394 +                       }
395 +               } else {
396 +                       /* signal frame completion */
397 +                       complete(&dev->capture.frame_cmplt);
398 +               }
399 +       } else {
400 +               if (dev->capture.frame_count) {
401 +                       if (dev->capture.vc_start_timestamp != -1) {
402 +                               s64 runtime_us = pts -
403 +                                   dev->capture.vc_start_timestamp;
404 +                               u32 div = 0;
405 +                               u32 rem = 0;
406 +
407 +                               div =
408 +                                   div_u64_rem(runtime_us, USEC_PER_SEC, &rem);
409 +                               buf->vb.v4l2_buf.timestamp.tv_sec =
410 +                                   dev->capture.kernel_start_ts.tv_sec - 1 +
411 +                                   div;
412 +                               buf->vb.v4l2_buf.timestamp.tv_usec =
413 +                                   dev->capture.kernel_start_ts.tv_usec + rem;
414 +
415 +                               if (buf->vb.v4l2_buf.timestamp.tv_usec >=
416 +                                   USEC_PER_SEC) {
417 +                                       buf->vb.v4l2_buf.timestamp.tv_sec++;
418 +                                       buf->vb.v4l2_buf.timestamp.tv_usec -=
419 +                                           USEC_PER_SEC;
420 +                               }
421 +                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
422 +                                        "Convert start time %d.%06d and %llu"
423 +                                        "with offset %llu to %d.%06d\n",
424 +                                        (int)dev->capture.kernel_start_ts.
425 +                                        tv_sec,
426 +                                        (int)dev->capture.kernel_start_ts.
427 +                                        tv_usec,
428 +                                        dev->capture.vc_start_timestamp, pts,
429 +                                        (int)buf->vb.v4l2_buf.timestamp.tv_sec,
430 +                                        (int)buf->vb.v4l2_buf.timestamp.
431 +                                        tv_usec);
432 +                       } else {
433 +                               v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
434 +                       }
435 +
436 +                       vb2_set_plane_payload(&buf->vb, 0, length);
437 +                       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
438 +
439 +                       if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
440 +                           is_capturing(dev)) {
441 +                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
442 +                                        "Grab another frame as buffer has EOS");
443 +                               vchiq_mmal_port_parameter_set(
444 +                                       instance,
445 +                                       dev->capture.
446 +                                       camera_port,
447 +                                       MMAL_PARAMETER_CAPTURE,
448 +                                       &dev->capture.
449 +                                       frame_count,
450 +                                       sizeof(dev->capture.frame_count));
451 +                       }
452 +               } else {
453 +                       /* signal frame completion */
454 +                       complete(&dev->capture.frame_cmplt);
455 +               }
456 +       }
457 +}
458 +
459 +static int enable_camera(struct bm2835_mmal_dev *dev)
460 +{
461 +       int ret;
462 +       if (!dev->camera_use_count) {
463 +               ret = vchiq_mmal_component_enable(
464 +                               dev->instance,
465 +                               dev->component[MMAL_COMPONENT_CAMERA]);
466 +               if (ret < 0) {
467 +                       v4l2_err(&dev->v4l2_dev,
468 +                                "Failed enabling camera, ret %d\n", ret);
469 +                       return -EINVAL;
470 +               }
471 +       }
472 +       dev->camera_use_count++;
473 +       v4l2_dbg(1, bcm2835_v4l2_debug,
474 +                &dev->v4l2_dev, "enabled camera (refcount %d)\n",
475 +                       dev->camera_use_count);
476 +       return 0;
477 +}
478 +
479 +static int disable_camera(struct bm2835_mmal_dev *dev)
480 +{
481 +       int ret;
482 +       if (!dev->camera_use_count) {
483 +               v4l2_err(&dev->v4l2_dev,
484 +                        "Disabled the camera when already disabled\n");
485 +               return -EINVAL;
486 +       }
487 +       dev->camera_use_count--;
488 +       if (!dev->camera_use_count) {
489 +               unsigned int i = 0xFFFFFFFF;
490 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
491 +                        "Disabling camera\n");
492 +               ret =
493 +                   vchiq_mmal_component_disable(
494 +                               dev->instance,
495 +                               dev->component[MMAL_COMPONENT_CAMERA]);
496 +               if (ret < 0) {
497 +                       v4l2_err(&dev->v4l2_dev,
498 +                                "Failed disabling camera, ret %d\n", ret);
499 +                       return -EINVAL;
500 +               }
501 +               vchiq_mmal_port_parameter_set(
502 +                       dev->instance,
503 +                       &dev->component[MMAL_COMPONENT_CAMERA]->control,
504 +                       MMAL_PARAMETER_CAMERA_NUM, &i,
505 +                       sizeof(i));
506 +       }
507 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
508 +                "Camera refcount now %d\n", dev->camera_use_count);
509 +       return 0;
510 +}
511 +
512 +static void buffer_queue(struct vb2_buffer *vb)
513 +{
514 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
515 +       struct mmal_buffer *buf = container_of(vb, struct mmal_buffer, vb);
516 +       int ret;
517 +
518 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
519 +                "%s: dev:%p buf:%p\n", __func__, dev, buf);
520 +
521 +       buf->buffer = vb2_plane_vaddr(&buf->vb, 0);
522 +       buf->buffer_size = vb2_plane_size(&buf->vb, 0);
523 +
524 +       ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
525 +       if (ret < 0)
526 +               v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
527 +                        __func__);
528 +}
529 +
530 +static int start_streaming(struct vb2_queue *vq, unsigned int count)
531 +{
532 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
533 +       int ret;
534 +       int parameter_size;
535 +
536 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
537 +                __func__, dev);
538 +
539 +       /* ensure a format has actually been set */
540 +       if (dev->capture.port == NULL)
541 +               return -EINVAL;
542 +
543 +       if (enable_camera(dev) < 0) {
544 +               v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n");
545 +               return -EINVAL;
546 +       }
547 +
548 +       /*init_completion(&dev->capture.frame_cmplt); */
549 +
550 +       /* enable frame capture */
551 +       dev->capture.frame_count = 1;
552 +
553 +       /* if the preview is not already running, wait for a few frames for AGC
554 +        * to settle down.
555 +        */
556 +       if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled)
557 +               msleep(300);
558 +
559 +       /* enable the connection from camera to encoder (if applicable) */
560 +       if (dev->capture.camera_port != dev->capture.port
561 +           && dev->capture.camera_port) {
562 +               ret = vchiq_mmal_port_enable(dev->instance,
563 +                                            dev->capture.camera_port, NULL);
564 +               if (ret) {
565 +                       v4l2_err(&dev->v4l2_dev,
566 +                                "Failed to enable encode tunnel - error %d\n",
567 +                                ret);
568 +                       return -1;
569 +               }
570 +       }
571 +
572 +       /* Get VC timestamp at this point in time */
573 +       parameter_size = sizeof(dev->capture.vc_start_timestamp);
574 +       if (vchiq_mmal_port_parameter_get(dev->instance,
575 +                                         dev->capture.camera_port,
576 +                                         MMAL_PARAMETER_SYSTEM_TIME,
577 +                                         &dev->capture.vc_start_timestamp,
578 +                                         &parameter_size)) {
579 +               v4l2_err(&dev->v4l2_dev,
580 +                        "Failed to get VC start time - update your VC f/w\n");
581 +
582 +               /* Flag to indicate just to rely on kernel timestamps */
583 +               dev->capture.vc_start_timestamp = -1;
584 +       } else
585 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
586 +                        "Start time %lld size %d\n",
587 +                        dev->capture.vc_start_timestamp, parameter_size);
588 +
589 +       v4l2_get_timestamp(&dev->capture.kernel_start_ts);
590 +
591 +       /* enable the camera port */
592 +       dev->capture.port->cb_ctx = dev;
593 +       ret =
594 +           vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
595 +       if (ret) {
596 +               v4l2_err(&dev->v4l2_dev,
597 +                        "Failed to enable capture port - error %d\n", ret);
598 +               return -1;
599 +       }
600 +
601 +       /* capture the first frame */
602 +       vchiq_mmal_port_parameter_set(dev->instance,
603 +                                     dev->capture.camera_port,
604 +                                     MMAL_PARAMETER_CAPTURE,
605 +                                     &dev->capture.frame_count,
606 +                                     sizeof(dev->capture.frame_count));
607 +       return 0;
608 +}
609 +
610 +/* abort streaming and wait for last buffer */
611 +static int stop_streaming(struct vb2_queue *vq)
612 +{
613 +       int ret;
614 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
615 +
616 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
617 +                __func__, dev);
618 +
619 +       init_completion(&dev->capture.frame_cmplt);
620 +       dev->capture.frame_count = 0;
621 +
622 +       /* ensure a format has actually been set */
623 +       if (dev->capture.port == NULL)
624 +               return -EINVAL;
625 +
626 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n");
627 +
628 +       /* stop capturing frames */
629 +       vchiq_mmal_port_parameter_set(dev->instance,
630 +                                     dev->capture.camera_port,
631 +                                     MMAL_PARAMETER_CAPTURE,
632 +                                     &dev->capture.frame_count,
633 +                                     sizeof(dev->capture.frame_count));
634 +
635 +       /* wait for last frame to complete */
636 +       ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
637 +       if (ret <= 0)
638 +               v4l2_err(&dev->v4l2_dev,
639 +                        "error %d waiting for frame completion\n", ret);
640 +
641 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
642 +                "disabling connection\n");
643 +
644 +       /* disable the connection from camera to encoder */
645 +       ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
646 +       if (!ret && dev->capture.camera_port != dev->capture.port) {
647 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
648 +                        "disabling port\n");
649 +               ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
650 +       } else if (dev->capture.camera_port != dev->capture.port) {
651 +               v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
652 +                        ret);
653 +       }
654 +
655 +       if (disable_camera(dev) < 0) {
656 +               v4l2_err(&dev->v4l2_dev, "Failed to disable camera");
657 +               return -EINVAL;
658 +       }
659 +
660 +       return ret;
661 +}
662 +
663 +static void bm2835_mmal_lock(struct vb2_queue *vq)
664 +{
665 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
666 +       mutex_lock(&dev->mutex);
667 +}
668 +
669 +static void bm2835_mmal_unlock(struct vb2_queue *vq)
670 +{
671 +       struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
672 +       mutex_unlock(&dev->mutex);
673 +}
674 +
675 +static struct vb2_ops bm2835_mmal_video_qops = {
676 +       .queue_setup = queue_setup,
677 +       .buf_prepare = buffer_prepare,
678 +       .buf_queue = buffer_queue,
679 +       .start_streaming = start_streaming,
680 +       .stop_streaming = stop_streaming,
681 +       .wait_prepare = bm2835_mmal_unlock,
682 +       .wait_finish = bm2835_mmal_lock,
683 +};
684 +
685 +/* ------------------------------------------------------------------
686 +       IOCTL operations
687 +   ------------------------------------------------------------------*/
688 +
689 +/* overlay ioctl */
690 +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
691 +                                      struct v4l2_fmtdesc *f)
692 +{
693 +       struct mmal_fmt *fmt;
694 +
695 +       if (f->index >= ARRAY_SIZE(formats))
696 +               return -EINVAL;
697 +
698 +       fmt = &formats[f->index];
699 +
700 +       strlcpy(f->description, fmt->name, sizeof(f->description));
701 +       f->pixelformat = fmt->fourcc;
702 +
703 +       return 0;
704 +}
705 +
706 +static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
707 +                                   struct v4l2_format *f)
708 +{
709 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
710 +
711 +       f->fmt.win = dev->overlay;
712 +
713 +       return 0;
714 +}
715 +
716 +static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
717 +                                     struct v4l2_format *f)
718 +{
719 +       /* Only support one format so get the current one. */
720 +       vidioc_g_fmt_vid_overlay(file, priv, f);
721 +
722 +       /* todo: allow the size and/or offset to be changed. */
723 +       return 0;
724 +}
725 +
726 +static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv,
727 +                                   struct v4l2_format *f)
728 +{
729 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
730 +
731 +       vidioc_try_fmt_vid_overlay(file, priv, f);
732 +
733 +       dev->overlay = f->fmt.win;
734 +
735 +       /* todo: program the preview port parameters */
736 +       return 0;
737 +}
738 +
739 +static int vidioc_overlay(struct file *file, void *f, unsigned int on)
740 +{
741 +       int ret;
742 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
743 +       struct vchiq_mmal_port *src;
744 +       struct vchiq_mmal_port *dst;
745 +       struct mmal_parameter_displayregion prev_config = {
746 +               .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA |
747 +                   MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN,
748 +               .layer = PREVIEW_LAYER,
749 +               .alpha = 255,
750 +               .fullscreen = 0,
751 +               .dest_rect = {
752 +                             .x = dev->overlay.w.left,
753 +                             .y = dev->overlay.w.top,
754 +                             .width = dev->overlay.w.width,
755 +                             .height = dev->overlay.w.height,
756 +                             },
757 +       };
758 +
759 +       if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) ||
760 +           (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled))
761 +               return 0;       /* already in requested state */
762 +
763 +       src =
764 +           &dev->component[MMAL_COMPONENT_CAMERA]->
765 +           output[MMAL_CAMERA_PORT_PREVIEW];
766 +
767 +       if (!on) {
768 +               /* disconnect preview ports and disable component */
769 +               ret = vchiq_mmal_port_disable(dev->instance, src);
770 +               if (!ret)
771 +                       ret =
772 +                           vchiq_mmal_port_connect_tunnel(dev->instance, src,
773 +                                                          NULL);
774 +               if (ret >= 0)
775 +                       ret = vchiq_mmal_component_disable(
776 +                                       dev->instance,
777 +                                       dev->component[MMAL_COMPONENT_PREVIEW]);
778 +
779 +               disable_camera(dev);
780 +               return ret;
781 +       }
782 +
783 +       /* set preview port format and connect it to output */
784 +       dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0];
785 +
786 +       ret = vchiq_mmal_port_set_format(dev->instance, src);
787 +       if (ret < 0)
788 +               goto error;
789 +
790 +       ret = vchiq_mmal_port_parameter_set(dev->instance, dst,
791 +                                           MMAL_PARAMETER_DISPLAYREGION,
792 +                                           &prev_config, sizeof(prev_config));
793 +       if (ret < 0)
794 +               goto error;
795 +
796 +       if (enable_camera(dev) < 0)
797 +               goto error;
798 +
799 +       ret = vchiq_mmal_component_enable(
800 +                       dev->instance,
801 +                       dev->component[MMAL_COMPONENT_PREVIEW]);
802 +       if (ret < 0)
803 +               goto error;
804 +
805 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n",
806 +                src, dst);
807 +       ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst);
808 +       if (!ret)
809 +               ret = vchiq_mmal_port_enable(dev->instance, src, NULL);
810 +error:
811 +       return ret;
812 +}
813 +
814 +static int vidioc_g_fbuf(struct file *file, void *fh,
815 +                        struct v4l2_framebuffer *a)
816 +{
817 +       /* The video overlay must stay within the framebuffer and can't be
818 +          positioned independently. */
819 +       a->flags = V4L2_FBUF_FLAG_OVERLAY;
820 +
821 +       /* todo: v4l2_framebuffer still needs more info filling in
822 +        *       in order to pass the v4l2-compliance test. */
823 +
824 +       return 0;
825 +}
826 +
827 +/* input ioctls */
828 +static int vidioc_enum_input(struct file *file, void *priv,
829 +                            struct v4l2_input *inp)
830 +{
831 +       /* only a single camera input */
832 +       if (inp->index != 0)
833 +               return -EINVAL;
834 +
835 +       inp->type = V4L2_INPUT_TYPE_CAMERA;
836 +       sprintf(inp->name, "Camera %u", inp->index);
837 +       return 0;
838 +}
839 +
840 +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
841 +{
842 +       *i = 0;
843 +       return 0;
844 +}
845 +
846 +static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
847 +{
848 +       if (i != 0)
849 +               return -EINVAL;
850 +
851 +       return 0;
852 +}
853 +
854 +/* capture ioctls */
855 +static int vidioc_querycap(struct file *file, void *priv,
856 +                          struct v4l2_capability *cap)
857 +{
858 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
859 +       u32 major;
860 +       u32 minor;
861 +
862 +       vchiq_mmal_version(dev->instance, &major, &minor);
863 +
864 +       strcpy(cap->driver, "bm2835 mmal");
865 +       snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d",
866 +                major, minor);
867 +
868 +       snprintf(cap->bus_info, sizeof(cap->bus_info),
869 +                "platform:%s", dev->v4l2_dev.name);
870 +       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
871 +           V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
872 +       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
873 +
874 +       return 0;
875 +}
876 +
877 +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
878 +                                  struct v4l2_fmtdesc *f)
879 +{
880 +       struct mmal_fmt *fmt;
881 +
882 +       if (f->index >= ARRAY_SIZE(formats))
883 +               return -EINVAL;
884 +
885 +       fmt = &formats[f->index];
886 +
887 +       strlcpy(f->description, fmt->name, sizeof(f->description));
888 +       f->pixelformat = fmt->fourcc;
889 +       return 0;
890 +}
891 +
892 +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
893 +                               struct v4l2_format *f)
894 +{
895 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
896 +
897 +       f->fmt.pix.width = dev->capture.width;
898 +       f->fmt.pix.height = dev->capture.height;
899 +       f->fmt.pix.field = V4L2_FIELD_NONE;
900 +       f->fmt.pix.pixelformat = dev->capture.fmt->fourcc;
901 +       f->fmt.pix.bytesperline =
902 +           (f->fmt.pix.width * dev->capture.fmt->depth) >> 3;
903 +       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
904 +       if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG
905 +           && f->fmt.pix.sizeimage < (100 << 10)) {
906 +               /* Need a minimum size for JPEG to account for EXIF. */
907 +               f->fmt.pix.sizeimage = (100 << 10);
908 +       }
909 +
910 +       if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_YUYV ||
911 +           dev->capture.fmt->fourcc == V4L2_PIX_FMT_UYVY)
912 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
913 +       else
914 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
915 +       f->fmt.pix.priv = 0;
916 +
917 +       v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
918 +                            __func__);
919 +       return 0;
920 +}
921 +
922 +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
923 +                                 struct v4l2_format *f)
924 +{
925 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
926 +       struct mmal_fmt *mfmt;
927 +
928 +       mfmt = get_format(f);
929 +       if (!mfmt) {
930 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
931 +                        "Fourcc format (0x%08x) unknown.\n",
932 +                        f->fmt.pix.pixelformat);
933 +               f->fmt.pix.pixelformat = formats[0].fourcc;
934 +               mfmt = get_format(f);
935 +       }
936 +
937 +       f->fmt.pix.field = V4L2_FIELD_NONE;
938 +       /* image must be a multiple of 32 pixels wide and 16 lines high */
939 +       v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 5,
940 +                             &f->fmt.pix.height, 32, MAX_HEIGHT, 4, 0);
941 +       f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth) >> 3;
942 +       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
943 +       if (f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
944 +               f->fmt.pix.sizeimage = MIN_BUFFER_SIZE;
945 +
946 +       if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
947 +           mfmt->fourcc == V4L2_PIX_FMT_UYVY)
948 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
949 +       else
950 +               f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
951 +       f->fmt.pix.priv = 0;
952 +
953 +       v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
954 +                            __func__);
955 +       return 0;
956 +}
957 +
958 +static int mmal_setup_components(struct bm2835_mmal_dev *dev,
959 +                                struct v4l2_format *f)
960 +{
961 +       int ret;
962 +       struct vchiq_mmal_port *port = NULL, *camera_port = NULL;
963 +       struct vchiq_mmal_component *encode_component = NULL;
964 +       struct mmal_fmt *mfmt = get_format(f);
965 +
966 +       BUG_ON(!mfmt);
967 +
968 +       if (dev->capture.encode_component) {
969 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
970 +                        "vid_cap - disconnect previous tunnel\n");
971 +
972 +               /* Disconnect any previous connection */
973 +               vchiq_mmal_port_connect_tunnel(dev->instance,
974 +                                              dev->capture.camera_port, NULL);
975 +               dev->capture.camera_port = NULL;
976 +               ret = vchiq_mmal_component_disable(dev->instance,
977 +                                                  dev->capture.
978 +                                                  encode_component);
979 +               if (ret)
980 +                       v4l2_err(&dev->v4l2_dev,
981 +                                "Failed to disable encode component %d\n",
982 +                                ret);
983 +
984 +               dev->capture.encode_component = NULL;
985 +       }
986 +       /* format dependant port setup */
987 +       switch (mfmt->mmal_component) {
988 +       case MMAL_COMPONENT_CAMERA:
989 +               /* Make a further decision on port based on resolution */
990 +               if (f->fmt.pix.width <= MAX_VIDEO_MODE_WIDTH
991 +                   && f->fmt.pix.height <= MAX_VIDEO_MODE_HEIGHT)
992 +                       camera_port = port =
993 +                           &dev->component[MMAL_COMPONENT_CAMERA]->
994 +                           output[MMAL_CAMERA_PORT_VIDEO];
995 +               else
996 +                       camera_port = port =
997 +                           &dev->component[MMAL_COMPONENT_CAMERA]->
998 +                           output[MMAL_CAMERA_PORT_CAPTURE];
999 +               break;
1000 +       case MMAL_COMPONENT_IMAGE_ENCODE:
1001 +               encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE];
1002 +               port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
1003 +               camera_port =
1004 +                   &dev->component[MMAL_COMPONENT_CAMERA]->
1005 +                   output[MMAL_CAMERA_PORT_CAPTURE];
1006 +               break;
1007 +       case MMAL_COMPONENT_VIDEO_ENCODE:
1008 +               encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE];
1009 +               port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
1010 +               camera_port =
1011 +                   &dev->component[MMAL_COMPONENT_CAMERA]->
1012 +                   output[MMAL_CAMERA_PORT_VIDEO];
1013 +               break;
1014 +       default:
1015 +               break;
1016 +       }
1017 +
1018 +       if (!port)
1019 +               return -EINVAL;
1020 +
1021 +       if (encode_component)
1022 +               camera_port->format.encoding = MMAL_ENCODING_OPAQUE;
1023 +       else
1024 +               camera_port->format.encoding = mfmt->mmal;
1025 +
1026 +       camera_port->format.encoding_variant = 0;
1027 +       camera_port->es.video.width = f->fmt.pix.width;
1028 +       camera_port->es.video.height = f->fmt.pix.height;
1029 +       camera_port->es.video.crop.x = 0;
1030 +       camera_port->es.video.crop.y = 0;
1031 +       camera_port->es.video.crop.width = f->fmt.pix.width;
1032 +       camera_port->es.video.crop.height = f->fmt.pix.height;
1033 +       camera_port->es.video.frame_rate.num = 30;
1034 +       camera_port->es.video.frame_rate.den = 1;
1035 +
1036 +       ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
1037 +
1038 +       if (!ret
1039 +           && camera_port ==
1040 +           &dev->component[MMAL_COMPONENT_CAMERA]->
1041 +           output[MMAL_CAMERA_PORT_VIDEO]) {
1042 +               bool overlay_enabled =
1043 +                   !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled;
1044 +               struct vchiq_mmal_port *preview_port =
1045 +                   &dev->component[MMAL_COMPONENT_CAMERA]->
1046 +                   output[MMAL_CAMERA_PORT_PREVIEW];
1047 +               /* Preview and encode ports need to match on resolution */
1048 +               if (overlay_enabled) {
1049 +                       /* Need to disable the overlay before we can update
1050 +                        * the resolution
1051 +                        */
1052 +                       ret =
1053 +                           vchiq_mmal_port_disable(dev->instance,
1054 +                                                   preview_port);
1055 +                       if (!ret)
1056 +                               ret =
1057 +                                   vchiq_mmal_port_connect_tunnel(
1058 +                                               dev->instance,
1059 +                                               preview_port,
1060 +                                               NULL);
1061 +               }
1062 +               preview_port->es.video.width = f->fmt.pix.width;
1063 +               preview_port->es.video.height = f->fmt.pix.height;
1064 +               preview_port->es.video.crop.x = 0;
1065 +               preview_port->es.video.crop.y = 0;
1066 +               preview_port->es.video.crop.width = f->fmt.pix.width;
1067 +               preview_port->es.video.crop.height = f->fmt.pix.height;
1068 +               preview_port->es.video.frame_rate.num = 30;
1069 +               preview_port->es.video.frame_rate.den = 1;
1070 +               ret = vchiq_mmal_port_set_format(dev->instance, preview_port);
1071 +               if (overlay_enabled) {
1072 +                       ret = vchiq_mmal_port_connect_tunnel(
1073 +                               dev->instance,
1074 +                               preview_port,
1075 +                               &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
1076 +                       if (!ret)
1077 +                               ret = vchiq_mmal_port_enable(dev->instance,
1078 +                                                            preview_port,
1079 +                                                            NULL);
1080 +               }
1081 +       }
1082 +
1083 +       if (ret) {
1084 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1085 +                        "%s failed to set format\n", __func__);
1086 +               /* ensure capture is not going to be tried */
1087 +               dev->capture.port = NULL;
1088 +       } else {
1089 +               if (encode_component) {
1090 +                       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1091 +                                "vid_cap - set up encode comp\n");
1092 +
1093 +                       /* configure buffering */
1094 +                       camera_port->current_buffer.size =
1095 +                           camera_port->recommended_buffer.size;
1096 +                       camera_port->current_buffer.num =
1097 +                           camera_port->recommended_buffer.num;
1098 +
1099 +                       port->format.encoding = mfmt->mmal;
1100 +                       port->format.encoding_variant = 0;
1101 +                       /* Set any encoding specific parameters */
1102 +                       switch (mfmt->mmal_component) {
1103 +                       case MMAL_COMPONENT_VIDEO_ENCODE:
1104 +                               port->format.bitrate =
1105 +                                   dev->capture.encode_bitrate;
1106 +                               break;
1107 +                       case MMAL_COMPONENT_IMAGE_ENCODE:
1108 +                               /* Could set EXIF parameters here */
1109 +                               break;
1110 +                       default:
1111 +                               break;
1112 +                       }
1113 +                       ret = vchiq_mmal_port_set_format(dev->instance, port);
1114 +
1115 +                       if (ret) {
1116 +                               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1117 +                                        "%s failed to set format\n", __func__);
1118 +                       } else {
1119 +                               ret = vchiq_mmal_component_enable(
1120 +                                               dev->instance,
1121 +                                               encode_component);
1122 +                               if (ret) {
1123 +                                       v4l2_dbg(1, bcm2835_v4l2_debug,
1124 +                                                &dev->v4l2_dev,
1125 +                                                "%s Failed to enable encode components\n",
1126 +                                                __func__);
1127 +                               } else {
1128 +                                       /* configure buffering */
1129 +                                       port->current_buffer.num = 1;
1130 +                                       port->current_buffer.size =
1131 +                                           f->fmt.pix.sizeimage;
1132 +                                       if (port->format.encoding ==
1133 +                                           MMAL_ENCODING_JPEG) {
1134 +                                               v4l2_dbg(1, bcm2835_v4l2_debug,
1135 +                                                        &dev->v4l2_dev,
1136 +                                                        "JPEG - fiddle buffer size\n");
1137 +                                               port->current_buffer.size =
1138 +                                                   (f->fmt.pix.sizeimage <
1139 +                                                    (100 << 10))
1140 +                                                   ? (100 << 10) : f->fmt.pix.
1141 +                                                   sizeimage;
1142 +                                       }
1143 +                                       v4l2_dbg(1, bcm2835_v4l2_debug,
1144 +                                                &dev->v4l2_dev,
1145 +                                                "vid_cap - current_buffer.size being set to %d\n",
1146 +                                                f->fmt.pix.sizeimage);
1147 +                                       port->current_buffer.alignment = 0;
1148 +                                       ret =
1149 +                                           vchiq_mmal_port_connect_tunnel(
1150 +                                                       dev->instance,
1151 +                                                       camera_port,
1152 +                                                       &encode_component->input[0]);
1153 +                                       if (ret) {
1154 +                                               v4l2_dbg(1, bcm2835_v4l2_debug,
1155 +                                                        &dev->v4l2_dev,
1156 +                                                        "%s failed to create connection\n",
1157 +                                                        __func__);
1158 +                                               /* ensure capture is not going to be tried */
1159 +                                               dev->capture.port = NULL;
1160 +                                       }
1161 +                               }
1162 +                       }
1163 +               } else {
1164 +                       /* configure buffering */
1165 +                       camera_port->current_buffer.num = 1;
1166 +                       camera_port->current_buffer.size = f->fmt.pix.sizeimage;
1167 +                       camera_port->current_buffer.alignment = 0;
1168 +               }
1169 +
1170 +               if (!ret) {
1171 +                       dev->capture.fmt = mfmt;
1172 +                       dev->capture.stride = f->fmt.pix.bytesperline;
1173 +                       dev->capture.width = port->es.video.crop.width;
1174 +                       dev->capture.height = port->es.video.crop.height;
1175 +
1176 +                       /* select port for capture */
1177 +                       dev->capture.port = port;
1178 +                       dev->capture.camera_port = camera_port;
1179 +                       dev->capture.encode_component = encode_component;
1180 +               }
1181 +       }
1182 +
1183 +       /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */
1184 +       return ret;
1185 +}
1186 +
1187 +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1188 +                               struct v4l2_format *f)
1189 +{
1190 +       int ret;
1191 +       struct bm2835_mmal_dev *dev = video_drvdata(file);
1192 +       struct mmal_fmt *mfmt;
1193 +
1194 +       /* try the format to set valid parameters */
1195 +       ret = vidioc_try_fmt_vid_cap(file, priv, f);
1196 +       if (ret) {
1197 +               v4l2_err(&dev->v4l2_dev,
1198 +                        "vid_cap - vidioc_try_fmt_vid_cap failed\n");
1199 +               return ret;
1200 +       }
1201 +
1202 +       /* if a capture is running refuse to set format */
1203 +       if (vb2_is_busy(&dev->capture.vb_vidq)) {
1204 +               v4l2_info(&dev->v4l2_dev, "%s device busy\n", __func__);
1205 +               return -EBUSY;
1206 +       }
1207 +
1208 +       /* If the format is unsupported v4l2 says we should switch to
1209 +        * a supported one and not return an error. */
1210 +       mfmt = get_format(f);
1211 +       if (!mfmt) {
1212 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1213 +                        "Fourcc format (0x%08x) unknown.\n",
1214 +                        f->fmt.pix.pixelformat);
1215 +               f->fmt.pix.pixelformat = formats[0].fourcc;
1216 +               mfmt = get_format(f);
1217 +       }
1218 +
1219 +       ret = mmal_setup_components(dev, f);
1220 +       if (ret != 0)
1221 +               v4l2_err(&dev->v4l2_dev,
1222 +                        "%s: failed to setup mmal components: %d\n",
1223 +                        __func__, ret);
1224 +
1225 +       return ret;
1226 +}
1227 +
1228 +static const struct v4l2_ioctl_ops camera0_ioctl_ops = {
1229 +       /* overlay */
1230 +       .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
1231 +       .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
1232 +       .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
1233 +       .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
1234 +       .vidioc_overlay = vidioc_overlay,
1235 +       .vidioc_g_fbuf = vidioc_g_fbuf,
1236 +
1237 +       /* inputs */
1238 +       .vidioc_enum_input = vidioc_enum_input,
1239 +       .vidioc_g_input = vidioc_g_input,
1240 +       .vidioc_s_input = vidioc_s_input,
1241 +
1242 +       /* capture */
1243 +       .vidioc_querycap = vidioc_querycap,
1244 +       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1245 +       .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1246 +       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1247 +       .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1248 +
1249 +       /* buffer management */
1250 +       .vidioc_reqbufs = vb2_ioctl_reqbufs,
1251 +       .vidioc_create_bufs = vb2_ioctl_create_bufs,
1252 +       .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1253 +       .vidioc_querybuf = vb2_ioctl_querybuf,
1254 +       .vidioc_qbuf = vb2_ioctl_qbuf,
1255 +       .vidioc_dqbuf = vb2_ioctl_dqbuf,
1256 +       .vidioc_streamon = vb2_ioctl_streamon,
1257 +       .vidioc_streamoff = vb2_ioctl_streamoff,
1258 +
1259 +       .vidioc_log_status = v4l2_ctrl_log_status,
1260 +       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1261 +       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1262 +};
1263 +
1264 +/* ------------------------------------------------------------------
1265 +       Driver init/finalise
1266 +   ------------------------------------------------------------------*/
1267 +
1268 +static const struct v4l2_file_operations camera0_fops = {
1269 +       .owner = THIS_MODULE,
1270 +       .open = v4l2_fh_open,
1271 +       .release = vb2_fop_release,
1272 +       .read = vb2_fop_read,
1273 +       .poll = vb2_fop_poll,
1274 +       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
1275 +       .mmap = vb2_fop_mmap,
1276 +};
1277 +
1278 +static struct video_device vdev_template = {
1279 +       .name = "camera0",
1280 +       .fops = &camera0_fops,
1281 +       .ioctl_ops = &camera0_ioctl_ops,
1282 +       .release = video_device_release_empty,
1283 +};
1284 +
1285 +static int set_camera_parameters(struct vchiq_mmal_instance *instance,
1286 +                                struct vchiq_mmal_component *camera)
1287 +{
1288 +       int ret;
1289 +       struct mmal_parameter_camera_config cam_config = {
1290 +               .max_stills_w = MAX_WIDTH,
1291 +               .max_stills_h = MAX_HEIGHT,
1292 +               .stills_yuv422 = 1,
1293 +               .one_shot_stills = 1,
1294 +               .max_preview_video_w = 1920,
1295 +               .max_preview_video_h = 1088,
1296 +               .num_preview_video_frames = 3,
1297 +               .stills_capture_circular_buffer_height = 0,
1298 +               .fast_preview_resume = 0,
1299 +               .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC
1300 +       };
1301 +
1302 +       ret = vchiq_mmal_port_parameter_set(instance, &camera->control,
1303 +                                           MMAL_PARAMETER_CAMERA_CONFIG,
1304 +                                           &cam_config, sizeof(cam_config));
1305 +       return ret;
1306 +}
1307 +
1308 +/* MMAL instance and component init */
1309 +static int __init mmal_init(struct bm2835_mmal_dev *dev)
1310 +{
1311 +       int ret;
1312 +       struct mmal_es_format *format;
1313 +
1314 +       ret = vchiq_mmal_init(&dev->instance);
1315 +       if (ret < 0)
1316 +               return ret;
1317 +
1318 +       /* get the camera component ready */
1319 +       ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
1320 +                                       &dev->component[MMAL_COMPONENT_CAMERA]);
1321 +       if (ret < 0)
1322 +               goto unreg_mmal;
1323 +
1324 +       if (dev->component[MMAL_COMPONENT_CAMERA]->outputs <
1325 +           MMAL_CAMERA_PORT_COUNT) {
1326 +               ret = -EINVAL;
1327 +               goto unreg_camera;
1328 +       }
1329 +
1330 +       ret = set_camera_parameters(dev->instance,
1331 +                                   dev->component[MMAL_COMPONENT_CAMERA]);
1332 +       if (ret < 0)
1333 +               goto unreg_camera;
1334 +
1335 +       format =
1336 +           &dev->component[MMAL_COMPONENT_CAMERA]->
1337 +           output[MMAL_CAMERA_PORT_PREVIEW].format;
1338 +
1339 +       format->encoding = MMAL_ENCODING_OPAQUE;
1340 +       format->encoding_variant = MMAL_ENCODING_I420;
1341 +
1342 +       format->es->video.width = 1024;
1343 +       format->es->video.height = 768;
1344 +       format->es->video.crop.x = 0;
1345 +       format->es->video.crop.y = 0;
1346 +       format->es->video.crop.width = 1024;
1347 +       format->es->video.crop.height = 768;
1348 +       format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
1349 +       format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
1350 +
1351 +       format =
1352 +           &dev->component[MMAL_COMPONENT_CAMERA]->
1353 +           output[MMAL_CAMERA_PORT_VIDEO].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_CAPTURE].format;
1370 +
1371 +       format->encoding = MMAL_ENCODING_OPAQUE;
1372 +
1373 +       format->es->video.width = 2592;
1374 +       format->es->video.height = 1944;
1375 +       format->es->video.crop.x = 0;
1376 +       format->es->video.crop.y = 0;
1377 +       format->es->video.crop.width = 2592;
1378 +       format->es->video.crop.height = 1944;
1379 +       format->es->video.frame_rate.num = 30;
1380 +       format->es->video.frame_rate.den = 1;
1381 +
1382 +       dev->capture.width = format->es->video.width;
1383 +       dev->capture.height = format->es->video.height;
1384 +       dev->capture.fmt = &formats[0];
1385 +       dev->capture.encode_component = NULL;
1386 +
1387 +       /* get the preview component ready */
1388 +       ret = vchiq_mmal_component_init(
1389 +                       dev->instance, "ril.video_render",
1390 +                       &dev->component[MMAL_COMPONENT_PREVIEW]);
1391 +       if (ret < 0)
1392 +               goto unreg_camera;
1393 +
1394 +       if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
1395 +               ret = -EINVAL;
1396 +               pr_debug("too few input ports %d needed %d\n",
1397 +                        dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
1398 +               goto unreg_preview;
1399 +       }
1400 +
1401 +       /* get the image encoder component ready */
1402 +       ret = vchiq_mmal_component_init(
1403 +               dev->instance, "ril.image_encode",
1404 +               &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
1405 +       if (ret < 0)
1406 +               goto unreg_preview;
1407 +
1408 +       if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
1409 +               ret = -EINVAL;
1410 +               v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
1411 +                        dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
1412 +                        1);
1413 +               goto unreg_image_encoder;
1414 +       }
1415 +
1416 +       /* get the video encoder component ready */
1417 +       ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
1418 +                                       &dev->
1419 +                                       component[MMAL_COMPONENT_VIDEO_ENCODE]);
1420 +       if (ret < 0)
1421 +               goto unreg_image_encoder;
1422 +
1423 +       if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
1424 +               ret = -EINVAL;
1425 +               v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
1426 +                        dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
1427 +                        1);
1428 +               goto unreg_vid_encoder;
1429 +       }
1430 +
1431 +       {
1432 +               unsigned int enable = 1;
1433 +               vchiq_mmal_port_parameter_set(
1434 +                       dev->instance,
1435 +                       &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
1436 +                       MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
1437 +                       &enable, sizeof(enable));
1438 +
1439 +               vchiq_mmal_port_parameter_set(dev->instance,
1440 +                       &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
1441 +                       MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
1442 +                       &enable,
1443 +                       sizeof(enable));
1444 +       }
1445 +       ret = bm2835_mmal_set_all_camera_controls(dev);
1446 +       if (ret < 0)
1447 +               goto unreg_vid_encoder;
1448 +
1449 +       return 0;
1450 +
1451 +unreg_vid_encoder:
1452 +       pr_err("Cleanup: Destroy video encoder\n");
1453 +       vchiq_mmal_component_finalise(
1454 +               dev->instance,
1455 +               dev->component[MMAL_COMPONENT_VIDEO_ENCODE]);
1456 +
1457 +unreg_image_encoder:
1458 +       pr_err("Cleanup: Destroy image encoder\n");
1459 +       vchiq_mmal_component_finalise(
1460 +               dev->instance,
1461 +               dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
1462 +
1463 +unreg_preview:
1464 +       pr_err("Cleanup: Destroy video render\n");
1465 +       vchiq_mmal_component_finalise(dev->instance,
1466 +                                     dev->component[MMAL_COMPONENT_PREVIEW]);
1467 +
1468 +unreg_camera:
1469 +       pr_err("Cleanup: Destroy camera\n");
1470 +       vchiq_mmal_component_finalise(dev->instance,
1471 +                                     dev->component[MMAL_COMPONENT_CAMERA]);
1472 +
1473 +unreg_mmal:
1474 +       vchiq_mmal_finalise(dev->instance);
1475 +       return ret;
1476 +}
1477 +
1478 +static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
1479 +                                         struct video_device *vfd)
1480 +{
1481 +       int ret;
1482 +
1483 +       *vfd = vdev_template;
1484 +
1485 +       vfd->v4l2_dev = &dev->v4l2_dev;
1486 +
1487 +       vfd->lock = &dev->mutex;
1488 +
1489 +       vfd->queue = &dev->capture.vb_vidq;
1490 +
1491 +       /* video device needs to be able to access instance data */
1492 +       video_set_drvdata(vfd, dev);
1493 +
1494 +       ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1495 +       if (ret < 0)
1496 +               return ret;
1497 +
1498 +       v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
1499 +                 video_device_node_name(vfd));
1500 +
1501 +       return 0;
1502 +}
1503 +
1504 +static struct v4l2_format default_v4l2_format = {
1505 +       .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG,
1506 +       .fmt.pix.width = 1024,
1507 +       .fmt.pix.bytesperline = 1024 * 3 / 2,
1508 +       .fmt.pix.height = 768,
1509 +       .fmt.pix.sizeimage = 1<<18,
1510 +};
1511 +
1512 +static int __init bm2835_mmal_init(void)
1513 +{
1514 +       int ret;
1515 +       struct bm2835_mmal_dev *dev;
1516 +       struct vb2_queue *q;
1517 +
1518 +       dev = kzalloc(sizeof(*gdev), GFP_KERNEL);
1519 +       if (!dev)
1520 +               return -ENOMEM;
1521 +
1522 +       /* setup device defaults */
1523 +       dev->overlay.w.left = 150;
1524 +       dev->overlay.w.top = 50;
1525 +       dev->overlay.w.width = 1024;
1526 +       dev->overlay.w.height = 768;
1527 +       dev->overlay.clipcount = 0;
1528 +       dev->overlay.field = V4L2_FIELD_NONE;
1529 +
1530 +       dev->capture.fmt = &formats[3]; /* JPEG */
1531 +
1532 +       /* v4l device registration */
1533 +       snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
1534 +                "%s", BM2835_MMAL_MODULE_NAME);
1535 +       ret = v4l2_device_register(NULL, &dev->v4l2_dev);
1536 +       if (ret)
1537 +               goto free_dev;
1538 +
1539 +       /* setup v4l controls */
1540 +       ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
1541 +       if (ret < 0)
1542 +               goto unreg_dev;
1543 +       dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
1544 +
1545 +       /* mmal init */
1546 +       ret = mmal_init(dev);
1547 +       if (ret < 0)
1548 +               goto unreg_dev;
1549 +
1550 +       /* initialize queue */
1551 +       q = &dev->capture.vb_vidq;
1552 +       memset(q, 0, sizeof(*q));
1553 +       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1554 +       q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
1555 +       q->drv_priv = dev;
1556 +       q->buf_struct_size = sizeof(struct mmal_buffer);
1557 +       q->ops = &bm2835_mmal_video_qops;
1558 +       q->mem_ops = &vb2_vmalloc_memops;
1559 +       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1560 +       ret = vb2_queue_init(q);
1561 +       if (ret < 0)
1562 +               goto unreg_dev;
1563 +
1564 +       /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */
1565 +       mutex_init(&dev->mutex);
1566 +
1567 +       /* initialise video devices */
1568 +       ret = bm2835_mmal_init_device(dev, &dev->vdev);
1569 +       if (ret < 0)
1570 +               goto unreg_dev;
1571 +
1572 +       ret = mmal_setup_components(dev, &default_v4l2_format);
1573 +       if (ret < 0) {
1574 +               v4l2_err(&dev->v4l2_dev,
1575 +                        "%s: could not setup components\n", __func__);
1576 +               goto unreg_dev;
1577 +       }
1578 +
1579 +       v4l2_info(&dev->v4l2_dev,
1580 +                 "Broadcom 2835 MMAL video capture ver %s loaded.\n",
1581 +                 BM2835_MMAL_VERSION);
1582 +
1583 +       gdev = dev;
1584 +       return 0;
1585 +
1586 +unreg_dev:
1587 +       v4l2_ctrl_handler_free(&dev->ctrl_handler);
1588 +       v4l2_device_unregister(&dev->v4l2_dev);
1589 +
1590 +free_dev:
1591 +       kfree(dev);
1592 +
1593 +       v4l2_err(&dev->v4l2_dev,
1594 +                "%s: error %d while loading driver\n",
1595 +                BM2835_MMAL_MODULE_NAME, ret);
1596 +
1597 +       return ret;
1598 +}
1599 +
1600 +static void __exit bm2835_mmal_exit(void)
1601 +{
1602 +       if (!gdev)
1603 +               return;
1604 +
1605 +       v4l2_info(&gdev->v4l2_dev, "unregistering %s\n",
1606 +                 video_device_node_name(&gdev->vdev));
1607 +
1608 +       video_unregister_device(&gdev->vdev);
1609 +
1610 +       if (gdev->capture.encode_component) {
1611 +               v4l2_dbg(1, bcm2835_v4l2_debug, &gdev->v4l2_dev,
1612 +                        "mmal_exit - disconnect tunnel\n");
1613 +               vchiq_mmal_port_connect_tunnel(gdev->instance,
1614 +                                              gdev->capture.camera_port, NULL);
1615 +               vchiq_mmal_component_disable(gdev->instance,
1616 +                                            gdev->capture.encode_component);
1617 +       }
1618 +       vchiq_mmal_component_disable(gdev->instance,
1619 +                                    gdev->component[MMAL_COMPONENT_CAMERA]);
1620 +
1621 +       vchiq_mmal_component_finalise(gdev->instance,
1622 +                                     gdev->
1623 +                                     component[MMAL_COMPONENT_VIDEO_ENCODE]);
1624 +
1625 +       vchiq_mmal_component_finalise(gdev->instance,
1626 +                                     gdev->
1627 +                                     component[MMAL_COMPONENT_IMAGE_ENCODE]);
1628 +
1629 +       vchiq_mmal_component_finalise(gdev->instance,
1630 +                                     gdev->component[MMAL_COMPONENT_PREVIEW]);
1631 +
1632 +       vchiq_mmal_component_finalise(gdev->instance,
1633 +                                     gdev->component[MMAL_COMPONENT_CAMERA]);
1634 +
1635 +       vchiq_mmal_finalise(gdev->instance);
1636 +
1637 +       v4l2_ctrl_handler_free(&gdev->ctrl_handler);
1638 +
1639 +       v4l2_device_unregister(&gdev->v4l2_dev);
1640 +
1641 +       kfree(gdev);
1642 +}
1643 +
1644 +module_init(bm2835_mmal_init);
1645 +module_exit(bm2835_mmal_exit);
1646 --- /dev/null
1647 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h
1648 @@ -0,0 +1,113 @@
1649 +/*
1650 + * Broadcom BM2835 V4L2 driver
1651 + *
1652 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
1653 + *
1654 + * This file is subject to the terms and conditions of the GNU General Public
1655 + * License.  See the file COPYING in the main directory of this archive
1656 + * for more details.
1657 + *
1658 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
1659 + *          Dave Stevenson <dsteve@broadcom.com>
1660 + *          Simon Mellor <simellor@broadcom.com>
1661 + *          Luke Diamand <luked@broadcom.com>
1662 + *
1663 + * core driver device
1664 + */
1665 +
1666 +#define V4L2_CTRL_COUNT 18 /* number of v4l controls */
1667 +
1668 +enum {
1669 +       MMAL_COMPONENT_CAMERA = 0,
1670 +       MMAL_COMPONENT_PREVIEW,
1671 +       MMAL_COMPONENT_IMAGE_ENCODE,
1672 +       MMAL_COMPONENT_VIDEO_ENCODE,
1673 +       MMAL_COMPONENT_COUNT
1674 +};
1675 +
1676 +enum {
1677 +       MMAL_CAMERA_PORT_PREVIEW = 0,
1678 +       MMAL_CAMERA_PORT_VIDEO,
1679 +       MMAL_CAMERA_PORT_CAPTURE,
1680 +       MMAL_CAMERA_PORT_COUNT
1681 +};
1682 +
1683 +#define PREVIEW_FRAME_RATE_NUM 30
1684 +#define PREVIEW_FRAME_RATE_DEN 1
1685 +
1686 +#define PREVIEW_LAYER      2
1687 +
1688 +extern int bcm2835_v4l2_debug;
1689 +
1690 +struct bm2835_mmal_dev {
1691 +       /* v4l2 devices */
1692 +       struct v4l2_device     v4l2_dev;
1693 +       struct video_device    vdev;
1694 +       struct mutex           mutex;
1695 +
1696 +       /* controls */
1697 +       struct v4l2_ctrl_handler  ctrl_handler;
1698 +       struct v4l2_ctrl          *ctrls[V4L2_CTRL_COUNT];
1699 +       struct mmal_colourfx      colourfx;
1700 +       int                       hflip;
1701 +       int                       vflip;
1702 +
1703 +       /* allocated mmal instance and components */
1704 +       struct vchiq_mmal_instance   *instance;
1705 +       struct vchiq_mmal_component  *component[MMAL_COMPONENT_COUNT];
1706 +       int camera_use_count;
1707 +
1708 +       struct v4l2_window overlay;
1709 +
1710 +       struct {
1711 +               unsigned int     width;  /* width */
1712 +               unsigned int     height;  /* height */
1713 +               unsigned int     stride;  /* stride */
1714 +               struct mmal_fmt  *fmt;
1715 +
1716 +               /* H264 encode bitrate */
1717 +               int         encode_bitrate;
1718 +               /* H264 bitrate mode. CBR/VBR */
1719 +               int         encode_bitrate_mode;
1720 +               /* JPEG Q-factor */
1721 +               int         q_factor;
1722 +
1723 +               struct vb2_queue        vb_vidq;
1724 +
1725 +               /* VC start timestamp for streaming */
1726 +               s64         vc_start_timestamp;
1727 +               /* Kernel start timestamp for streaming */
1728 +               struct timeval kernel_start_ts;
1729 +
1730 +               struct vchiq_mmal_port  *port; /* port being used for capture */
1731 +               /* camera port being used for capture */
1732 +               struct vchiq_mmal_port  *camera_port;
1733 +               /* component being used for encode */
1734 +               struct vchiq_mmal_component *encode_component;
1735 +               /* number of frames remaining which driver should capture */
1736 +               unsigned int  frame_count;
1737 +               /* last frame completion */
1738 +               struct completion  frame_cmplt;
1739 +
1740 +       } capture;
1741 +
1742 +};
1743 +
1744 +int bm2835_mmal_init_controls(
1745 +                       struct bm2835_mmal_dev *dev,
1746 +                       struct v4l2_ctrl_handler *hdl);
1747 +
1748 +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev);
1749 +
1750 +
1751 +/* Debug helpers */
1752 +
1753 +#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \
1754 +{      \
1755 +       v4l2_dbg(level, debug, dev,     \
1756 +"%s: w %u h %u field %u pfmt 0x%x bpl %u sz_img %u colorspace 0x%x priv %u\n", \
1757 +               desc == NULL ? "" : desc,       \
1758 +               (pix_fmt)->width, (pix_fmt)->height, (pix_fmt)->field,  \
1759 +               (pix_fmt)->pixelformat, (pix_fmt)->bytesperline,        \
1760 +               (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
1761 +}
1762 --- /dev/null
1763 +++ b/drivers/media/platform/bcm2835/controls.c
1764 @@ -0,0 +1,725 @@
1765 +/*
1766 + * Broadcom BM2835 V4L2 driver
1767 + *
1768 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
1769 + *
1770 + * This file is subject to the terms and conditions of the GNU General Public
1771 + * License.  See the file COPYING in the main directory of this archive
1772 + * for more details.
1773 + *
1774 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
1775 + *          Dave Stevenson <dsteve@broadcom.com>
1776 + *          Simon Mellor <simellor@broadcom.com>
1777 + *          Luke Diamand <luked@broadcom.com>
1778 + */
1779 +
1780 +#include <linux/errno.h>
1781 +#include <linux/kernel.h>
1782 +#include <linux/module.h>
1783 +#include <linux/slab.h>
1784 +#include <media/videobuf2-vmalloc.h>
1785 +#include <media/v4l2-device.h>
1786 +#include <media/v4l2-ioctl.h>
1787 +#include <media/v4l2-ctrls.h>
1788 +#include <media/v4l2-fh.h>
1789 +#include <media/v4l2-event.h>
1790 +#include <media/v4l2-common.h>
1791 +
1792 +#include "mmal-common.h"
1793 +#include "mmal-vchiq.h"
1794 +#include "mmal-parameters.h"
1795 +#include "bcm2835-camera.h"
1796 +
1797 +/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -24 to +24.
1798 + * These are in 1/6th increments so the effective range is -4.0EV to +4.0EV.
1799 + */
1800 +static const s64 ev_bias_qmenu[] = {
1801 +       -24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 21, 24
1802 +};
1803 +
1804 +/* Supported ISO values
1805 + * ISOO = auto ISO
1806 + */
1807 +static const s64 iso_qmenu[] = {
1808 +       0, 100, 200, 400, 800,
1809 +};
1810 +
1811 +/* Supported video encode modes */
1812 +static const s64 bitrate_mode_qmenu[] = {
1813 +       (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
1814 +       (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
1815 +};
1816 +
1817 +
1818 +enum bm2835_mmal_ctrl_type {
1819 +       MMAL_CONTROL_TYPE_STD,
1820 +       MMAL_CONTROL_TYPE_STD_MENU,
1821 +       MMAL_CONTROL_TYPE_INT_MENU,
1822 +       MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */
1823 +};
1824 +
1825 +struct bm2835_mmal_v4l2_ctrl;
1826 +
1827 +typedef        int(bm2835_mmal_v4l2_ctrl_cb)(
1828 +                               struct bm2835_mmal_dev *dev,
1829 +                               struct v4l2_ctrl *ctrl,
1830 +                               const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl);
1831 +
1832 +struct bm2835_mmal_v4l2_ctrl {
1833 +       u32 id; /* v4l2 control identifier */
1834 +       enum bm2835_mmal_ctrl_type type;
1835 +       /* control minimum value or
1836 +        * mask for MMAL_CONTROL_TYPE_STD_MENU */
1837 +       s32 min;
1838 +       s32 max; /* maximum value of control */
1839 +       s32 def;  /* default value of control */
1840 +       s32 step; /* step size of the control */
1841 +       const s64 *imenu; /* integer menu array */
1842 +       u32 mmal_id; /* mmal parameter id */
1843 +       bm2835_mmal_v4l2_ctrl_cb *setter;
1844 +};
1845 +
1846 +struct v4l2_to_mmal_effects_setting {
1847 +       u32 v4l2_effect;
1848 +       u32 mmal_effect;
1849 +       s32 col_fx_enable;
1850 +       s32 col_fx_fixed_cbcr;
1851 +       u32 u;
1852 +       u32 v;
1853 +       u32 num_effect_params;
1854 +       u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS];
1855 +};
1856 +
1857 +static const struct v4l2_to_mmal_effects_setting
1858 +       v4l2_to_mmal_effects_values[] = {
1859 +       {  V4L2_COLORFX_NONE,         MMAL_PARAM_IMAGEFX_NONE,
1860 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1861 +       {  V4L2_COLORFX_BW,           MMAL_PARAM_IMAGEFX_NONE,
1862 +               1,   0,    128,  128, 0, {0, 0, 0, 0, 0} },
1863 +       {  V4L2_COLORFX_SEPIA,        MMAL_PARAM_IMAGEFX_NONE,
1864 +               1,   0,    87,   151, 0, {0, 0, 0, 0, 0} },
1865 +       {  V4L2_COLORFX_NEGATIVE,     MMAL_PARAM_IMAGEFX_NEGATIVE,
1866 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1867 +       {  V4L2_COLORFX_EMBOSS,       MMAL_PARAM_IMAGEFX_EMBOSS,
1868 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1869 +       {  V4L2_COLORFX_SKETCH,       MMAL_PARAM_IMAGEFX_SKETCH,
1870 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1871 +       {  V4L2_COLORFX_SKY_BLUE,     MMAL_PARAM_IMAGEFX_PASTEL,
1872 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1873 +       {  V4L2_COLORFX_GRASS_GREEN,  MMAL_PARAM_IMAGEFX_WATERCOLOUR,
1874 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1875 +       {  V4L2_COLORFX_SKIN_WHITEN,  MMAL_PARAM_IMAGEFX_WASHEDOUT,
1876 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1877 +       {  V4L2_COLORFX_VIVID,        MMAL_PARAM_IMAGEFX_SATURATION,
1878 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1879 +       {  V4L2_COLORFX_AQUA,         MMAL_PARAM_IMAGEFX_NONE,
1880 +               1,   0,    171,  121, 0, {0, 0, 0, 0, 0} },
1881 +       {  V4L2_COLORFX_ART_FREEZE,   MMAL_PARAM_IMAGEFX_HATCH,
1882 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1883 +       {  V4L2_COLORFX_SILHOUETTE,   MMAL_PARAM_IMAGEFX_FILM,
1884 +               0,   0,    0,    0,   0, {0, 0, 0, 0, 0} },
1885 +       {  V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE,
1886 +               0,   0,    0,    0,   5, {1, 128, 160, 160, 48} },
1887 +       {  V4L2_COLORFX_ANTIQUE,      MMAL_PARAM_IMAGEFX_COLOURBALANCE,
1888 +               0,   0,    0,    0,   3, {108, 274, 238, 0, 0} },
1889 +       {  V4L2_COLORFX_SET_CBCR,     MMAL_PARAM_IMAGEFX_NONE,
1890 +               1,   1,    0,    0,   0, {0, 0, 0, 0, 0} }
1891 +};
1892 +
1893 +
1894 +/* control handlers*/
1895 +
1896 +static int ctrl_set_rational(struct bm2835_mmal_dev *dev,
1897 +                     struct v4l2_ctrl *ctrl,
1898 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1899 +{
1900 +       struct  {
1901 +               s32 num;    /**< Numerator */
1902 +               s32 den;    /**< Denominator */
1903 +       } rational_value;
1904 +       struct vchiq_mmal_port *control;
1905 +
1906 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
1907 +
1908 +       rational_value.num = ctrl->val;
1909 +       rational_value.den = 100;
1910 +
1911 +       return vchiq_mmal_port_parameter_set(dev->instance, control,
1912 +                                            mmal_ctrl->mmal_id,
1913 +                                            &rational_value,
1914 +                                            sizeof(rational_value));
1915 +}
1916 +
1917 +static int ctrl_set_value(struct bm2835_mmal_dev *dev,
1918 +                     struct v4l2_ctrl *ctrl,
1919 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1920 +{
1921 +       u32 u32_value;
1922 +       struct vchiq_mmal_port *control;
1923 +
1924 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
1925 +
1926 +       u32_value = ctrl->val;
1927 +
1928 +       return vchiq_mmal_port_parameter_set(dev->instance, control,
1929 +                                            mmal_ctrl->mmal_id,
1930 +                                            &u32_value, sizeof(u32_value));
1931 +}
1932 +
1933 +static int ctrl_set_rotate(struct bm2835_mmal_dev *dev,
1934 +                     struct v4l2_ctrl *ctrl,
1935 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1936 +{
1937 +       int ret;
1938 +       u32 u32_value;
1939 +       struct vchiq_mmal_component *camera;
1940 +
1941 +       camera = dev->component[MMAL_COMPONENT_CAMERA];
1942 +
1943 +       u32_value = ((ctrl->val % 360) / 90) * 90;
1944 +
1945 +       ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
1946 +                                           mmal_ctrl->mmal_id,
1947 +                                           &u32_value, sizeof(u32_value));
1948 +       if (ret < 0)
1949 +               return ret;
1950 +
1951 +       ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
1952 +                                           mmal_ctrl->mmal_id,
1953 +                                           &u32_value, sizeof(u32_value));
1954 +       if (ret < 0)
1955 +               return ret;
1956 +
1957 +       ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
1958 +                                           mmal_ctrl->mmal_id,
1959 +                                           &u32_value, sizeof(u32_value));
1960 +
1961 +       return ret;
1962 +}
1963 +
1964 +static int ctrl_set_flip(struct bm2835_mmal_dev *dev,
1965 +                     struct v4l2_ctrl *ctrl,
1966 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
1967 +{
1968 +       int ret;
1969 +       u32 u32_value;
1970 +       struct vchiq_mmal_component *camera;
1971 +
1972 +       if (ctrl->id == V4L2_CID_HFLIP)
1973 +               dev->hflip = ctrl->val;
1974 +       else
1975 +               dev->vflip = ctrl->val;
1976 +
1977 +       camera = dev->component[MMAL_COMPONENT_CAMERA];
1978 +
1979 +       if (dev->hflip && dev->vflip)
1980 +               u32_value = MMAL_PARAM_MIRROR_BOTH;
1981 +       else if (dev->hflip)
1982 +               u32_value = MMAL_PARAM_MIRROR_HORIZONTAL;
1983 +       else if (dev->vflip)
1984 +               u32_value = MMAL_PARAM_MIRROR_VERTICAL;
1985 +       else
1986 +               u32_value = MMAL_PARAM_MIRROR_NONE;
1987 +
1988 +       ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
1989 +                                           mmal_ctrl->mmal_id,
1990 +                                           &u32_value, sizeof(u32_value));
1991 +       if (ret < 0)
1992 +               return ret;
1993 +
1994 +       ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
1995 +                                           mmal_ctrl->mmal_id,
1996 +                                           &u32_value, sizeof(u32_value));
1997 +       if (ret < 0)
1998 +               return ret;
1999 +
2000 +       ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
2001 +                                           mmal_ctrl->mmal_id,
2002 +                                           &u32_value, sizeof(u32_value));
2003 +
2004 +       return ret;
2005 +
2006 +}
2007 +
2008 +static int ctrl_set_exposure(struct bm2835_mmal_dev *dev,
2009 +                     struct v4l2_ctrl *ctrl,
2010 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2011 +{
2012 +       u32 u32_value;
2013 +       struct vchiq_mmal_port *control;
2014 +
2015 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2016 +
2017 +       switch (ctrl->val) {
2018 +       case V4L2_EXPOSURE_AUTO:
2019 +               u32_value = MMAL_PARAM_EXPOSUREMODE_AUTO;
2020 +               break;
2021 +
2022 +       case V4L2_EXPOSURE_MANUAL:
2023 +               u32_value = MMAL_PARAM_EXPOSUREMODE_OFF;
2024 +               break;
2025 +
2026 +       case V4L2_EXPOSURE_SHUTTER_PRIORITY:
2027 +               u32_value = MMAL_PARAM_EXPOSUREMODE_SPORTS;
2028 +               break;
2029 +
2030 +       case V4L2_EXPOSURE_APERTURE_PRIORITY:
2031 +               u32_value = MMAL_PARAM_EXPOSUREMODE_NIGHT;
2032 +               break;
2033 +
2034 +       }
2035 +
2036 +       /* todo: what about the other ten modes there are MMAL parameters for */
2037 +       return vchiq_mmal_port_parameter_set(dev->instance, control,
2038 +                                            mmal_ctrl->mmal_id,
2039 +                                            &u32_value, sizeof(u32_value));
2040 +}
2041 +
2042 +static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev,
2043 +                          struct v4l2_ctrl *ctrl,
2044 +                          const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2045 +{
2046 +       u32 u32_value;
2047 +       struct vchiq_mmal_port *control;
2048 +
2049 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2050 +
2051 +       switch (ctrl->val) {
2052 +       case V4L2_EXPOSURE_METERING_AVERAGE:
2053 +               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
2054 +               break;
2055 +
2056 +       case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
2057 +               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
2058 +               break;
2059 +
2060 +       case V4L2_EXPOSURE_METERING_SPOT:
2061 +               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
2062 +               break;
2063 +
2064 +       /* todo matrix weighting not added to Linux API till 3.9
2065 +       case V4L2_EXPOSURE_METERING_MATRIX:
2066 +               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
2067 +               break;
2068 +       */
2069 +
2070 +       }
2071 +
2072 +       return vchiq_mmal_port_parameter_set(dev->instance, control,
2073 +                                            mmal_ctrl->mmal_id,
2074 +                                            &u32_value, sizeof(u32_value));
2075 +}
2076 +
2077 +static int ctrl_set_awb_mode(struct bm2835_mmal_dev *dev,
2078 +                     struct v4l2_ctrl *ctrl,
2079 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2080 +{
2081 +       u32 u32_value;
2082 +       struct vchiq_mmal_port *control;
2083 +
2084 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2085 +
2086 +       switch (ctrl->val) {
2087 +       case V4L2_WHITE_BALANCE_MANUAL:
2088 +               u32_value = MMAL_PARAM_AWBMODE_OFF;
2089 +               break;
2090 +
2091 +       case V4L2_WHITE_BALANCE_AUTO:
2092 +               u32_value = MMAL_PARAM_AWBMODE_AUTO;
2093 +               break;
2094 +
2095 +       case V4L2_WHITE_BALANCE_INCANDESCENT:
2096 +               u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT;
2097 +               break;
2098 +
2099 +       case V4L2_WHITE_BALANCE_FLUORESCENT:
2100 +               u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT;
2101 +               break;
2102 +
2103 +       case V4L2_WHITE_BALANCE_FLUORESCENT_H:
2104 +               u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN;
2105 +               break;
2106 +
2107 +       case V4L2_WHITE_BALANCE_HORIZON:
2108 +               u32_value = MMAL_PARAM_AWBMODE_HORIZON;
2109 +               break;
2110 +
2111 +       case V4L2_WHITE_BALANCE_DAYLIGHT:
2112 +               u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT;
2113 +               break;
2114 +
2115 +       case V4L2_WHITE_BALANCE_FLASH:
2116 +               u32_value = MMAL_PARAM_AWBMODE_FLASH;
2117 +               break;
2118 +
2119 +       case V4L2_WHITE_BALANCE_CLOUDY:
2120 +               u32_value = MMAL_PARAM_AWBMODE_CLOUDY;
2121 +               break;
2122 +
2123 +       case V4L2_WHITE_BALANCE_SHADE:
2124 +               u32_value = MMAL_PARAM_AWBMODE_SHADE;
2125 +               break;
2126 +
2127 +       }
2128 +
2129 +       return vchiq_mmal_port_parameter_set(dev->instance, control,
2130 +                                            mmal_ctrl->mmal_id,
2131 +                                            &u32_value, sizeof(u32_value));
2132 +}
2133 +
2134 +static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev,
2135 +                  struct v4l2_ctrl *ctrl,
2136 +                  const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2137 +{
2138 +       int ret = -EINVAL;
2139 +       int i, j;
2140 +       struct vchiq_mmal_port *control;
2141 +       struct mmal_parameter_imagefx_parameters imagefx;
2142 +
2143 +       for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) {
2144 +               if (ctrl->val == v4l2_to_mmal_effects_values[i].v4l2_effect) {
2145 +
2146 +                       imagefx.effect =
2147 +                               v4l2_to_mmal_effects_values[i].mmal_effect;
2148 +                       imagefx.num_effect_params =
2149 +                               v4l2_to_mmal_effects_values[i].num_effect_params;
2150 +
2151 +                       if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS)
2152 +                               imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS;
2153 +
2154 +                       for (j = 0; j < imagefx.num_effect_params; j++)
2155 +                               imagefx.effect_parameter[j] =
2156 +                                       v4l2_to_mmal_effects_values[i].effect_params[j];
2157 +
2158 +                       dev->colourfx.enable =
2159 +                               v4l2_to_mmal_effects_values[i].col_fx_enable;
2160 +                       if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) {
2161 +                               dev->colourfx.u =
2162 +                                       v4l2_to_mmal_effects_values[i].u;
2163 +                               dev->colourfx.v =
2164 +                                       v4l2_to_mmal_effects_values[i].v;
2165 +                       }
2166 +
2167 +                       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2168 +
2169 +                       ret = vchiq_mmal_port_parameter_set(
2170 +                                       dev->instance, control,
2171 +                                       MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
2172 +                                       &imagefx, sizeof(imagefx));
2173 +                       if (ret)
2174 +                               goto exit;
2175 +
2176 +                       ret = vchiq_mmal_port_parameter_set(
2177 +                                       dev->instance, control,
2178 +                                       MMAL_PARAMETER_COLOUR_EFFECT,
2179 +                                       &dev->colourfx, sizeof(dev->colourfx));
2180 +               }
2181 +       }
2182 +
2183 +exit:
2184 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
2185 +                "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n",
2186 +                               mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect,
2187 +                               dev->colourfx.enable ? "true" : "false",
2188 +                               dev->colourfx.u, dev->colourfx.v,
2189 +                               ret, (ret == 0 ? 0 : -EINVAL));
2190 +       return (ret == 0 ? 0 : EINVAL);
2191 +}
2192 +
2193 +static int ctrl_set_colfx(struct bm2835_mmal_dev *dev,
2194 +                  struct v4l2_ctrl *ctrl,
2195 +                  const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2196 +{
2197 +       int ret = -EINVAL;
2198 +       struct vchiq_mmal_port *control;
2199 +
2200 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2201 +
2202 +       dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
2203 +       dev->colourfx.enable = ctrl->val & 0xff;
2204 +
2205 +       ret = vchiq_mmal_port_parameter_set(dev->instance, control,
2206 +                                       MMAL_PARAMETER_COLOUR_EFFECT,
2207 +                                       &dev->colourfx, sizeof(dev->colourfx));
2208 +
2209 +       v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
2210 +                "After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
2211 +                       mmal_ctrl, ctrl->id, ctrl->val, ret,
2212 +                       (ret == 0 ? 0 : -EINVAL));
2213 +       return (ret == 0 ? 0 : EINVAL);
2214 +}
2215 +
2216 +static int ctrl_set_bitrate(struct bm2835_mmal_dev *dev,
2217 +                  struct v4l2_ctrl *ctrl,
2218 +                  const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2219 +{
2220 +       int ret;
2221 +       struct vchiq_mmal_port *encoder_out;
2222 +
2223 +       dev->capture.encode_bitrate = ctrl->val;
2224 +
2225 +       encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
2226 +
2227 +       ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
2228 +                                           mmal_ctrl->mmal_id,
2229 +                                           &ctrl->val, sizeof(ctrl->val));
2230 +       ret = 0;
2231 +       return ret;
2232 +}
2233 +
2234 +static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev,
2235 +                  struct v4l2_ctrl *ctrl,
2236 +                  const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2237 +{
2238 +       u32 bitrate_mode;
2239 +       struct vchiq_mmal_port *encoder_out;
2240 +
2241 +       encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
2242 +
2243 +       dev->capture.encode_bitrate_mode = ctrl->val;
2244 +       switch (ctrl->val) {
2245 +       default:
2246 +       case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
2247 +               bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
2248 +               break;
2249 +       case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
2250 +               bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
2251 +               break;
2252 +       }
2253 +
2254 +       vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
2255 +                                            mmal_ctrl->mmal_id,
2256 +                                            &bitrate_mode,
2257 +                                            sizeof(bitrate_mode));
2258 +       return 0;
2259 +}
2260 +
2261 +static int ctrl_set_q_factor(struct bm2835_mmal_dev *dev,
2262 +                     struct v4l2_ctrl *ctrl,
2263 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
2264 +{
2265 +       u32 u32_value;
2266 +       struct vchiq_mmal_port *jpeg_out;
2267 +
2268 +       jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
2269 +
2270 +       u32_value = ctrl->val;
2271 +
2272 +       return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out,
2273 +                                            mmal_ctrl->mmal_id,
2274 +                                            &u32_value, sizeof(u32_value));
2275 +}
2276 +
2277 +static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
2278 +{
2279 +       struct bm2835_mmal_dev *dev =
2280 +               container_of(ctrl->handler, struct bm2835_mmal_dev,
2281 +                            ctrl_handler);
2282 +       const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv;
2283 +
2284 +       if ((mmal_ctrl == NULL) ||
2285 +           (mmal_ctrl->id != ctrl->id) ||
2286 +           (mmal_ctrl->setter == NULL)) {
2287 +               pr_warn("mmal_ctrl:%p ctrl id:%d\n", mmal_ctrl, ctrl->id);
2288 +               return -EINVAL;
2289 +       }
2290 +
2291 +       return mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
2292 +}
2293 +
2294 +static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = {
2295 +       .s_ctrl = bm2835_mmal_s_ctrl,
2296 +};
2297 +
2298 +
2299 +
2300 +static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
2301 +       {
2302 +               V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD,
2303 +               -100, 100, 0, 1, NULL,
2304 +               MMAL_PARAMETER_SATURATION, &ctrl_set_rational
2305 +       },
2306 +       {
2307 +               V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD,
2308 +               -100, 100, 0, 1, NULL,
2309 +               MMAL_PARAMETER_SHARPNESS, &ctrl_set_rational
2310 +       },
2311 +       {
2312 +               V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD,
2313 +               -100, 100, 0, 1, NULL,
2314 +               MMAL_PARAMETER_CONTRAST, &ctrl_set_rational
2315 +       },
2316 +       {
2317 +               V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD,
2318 +               0, 100, 50, 1, NULL,
2319 +               MMAL_PARAMETER_BRIGHTNESS, &ctrl_set_rational
2320 +       },
2321 +       {
2322 +               V4L2_CID_ISO_SENSITIVITY, MMAL_CONTROL_TYPE_INT_MENU,
2323 +               0, ARRAY_SIZE(iso_qmenu) - 1, 0, 1, iso_qmenu,
2324 +               MMAL_PARAMETER_ISO, &ctrl_set_value
2325 +       },
2326 +       {
2327 +               V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD,
2328 +               0, 1, 0, 1, NULL,
2329 +               MMAL_PARAMETER_VIDEO_STABILISATION, &ctrl_set_value
2330 +       },
2331 +/*     {
2332 +               0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
2333 +       },
2334 +*/     {
2335 +               V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
2336 +               ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
2337 +               MMAL_PARAMETER_EXPOSURE_MODE, &ctrl_set_exposure
2338 +       },
2339 +/* todo this needs mixing in with set exposure
2340 +       {
2341 +              V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
2342 +       },
2343 + */
2344 +       {
2345 +               V4L2_CID_AUTO_EXPOSURE_BIAS, MMAL_CONTROL_TYPE_INT_MENU,
2346 +               0, ARRAY_SIZE(ev_bias_qmenu) - 1,
2347 +               (ARRAY_SIZE(ev_bias_qmenu)+1)/2 - 1, 0, ev_bias_qmenu,
2348 +               MMAL_PARAMETER_EXPOSURE_COMP, &ctrl_set_value
2349 +       },
2350 +       {
2351 +               V4L2_CID_EXPOSURE_METERING,
2352 +               MMAL_CONTROL_TYPE_STD_MENU,
2353 +               ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
2354 +               MMAL_PARAMETER_EXP_METERING_MODE, &ctrl_set_metering_mode
2355 +       },
2356 +       {
2357 +               V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
2358 +               MMAL_CONTROL_TYPE_STD_MENU,
2359 +               ~0x3fe, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
2360 +               MMAL_PARAMETER_AWB_MODE, &ctrl_set_awb_mode
2361 +       },
2362 +       {
2363 +               V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
2364 +               0, 15, V4L2_COLORFX_NONE, 0, NULL,
2365 +               MMAL_PARAMETER_IMAGE_EFFECT, &ctrl_set_image_effect
2366 +       },
2367 +       {
2368 +               V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD,
2369 +               0, 0xffff, 0x8080, 1, NULL,
2370 +               MMAL_PARAMETER_COLOUR_EFFECT, &ctrl_set_colfx
2371 +       },
2372 +       {
2373 +               V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD,
2374 +               0, 360, 0, 90, NULL,
2375 +               MMAL_PARAMETER_ROTATION, &ctrl_set_rotate
2376 +       },
2377 +       {
2378 +               V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD,
2379 +               0, 1, 0, 1, NULL,
2380 +               MMAL_PARAMETER_MIRROR, &ctrl_set_flip
2381 +       },
2382 +       {
2383 +               V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD,
2384 +               0, 1, 0, 1, NULL,
2385 +               MMAL_PARAMETER_MIRROR, &ctrl_set_flip
2386 +       },
2387 +       {
2388 +               V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
2389 +               0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
2390 +               0, 0, bitrate_mode_qmenu,
2391 +               MMAL_PARAMETER_RATECONTROL, &ctrl_set_bitrate_mode
2392 +       },
2393 +       {
2394 +               V4L2_CID_MPEG_VIDEO_BITRATE, MMAL_CONTROL_TYPE_STD,
2395 +               25*1000, 25*1000*1000, 10*1000*1000, 25*1000, NULL,
2396 +               MMAL_PARAMETER_VIDEO_BIT_RATE, &ctrl_set_bitrate
2397 +       },
2398 +       {
2399 +               V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD,
2400 +               0, 100,
2401 +               30, 1, NULL,
2402 +               MMAL_PARAMETER_JPEG_Q_FACTOR, &ctrl_set_q_factor
2403 +       },
2404 +};
2405 +
2406 +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
2407 +{
2408 +       int c;
2409 +       int ret;
2410 +
2411 +       for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2412 +               if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) {
2413 +                       ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c],
2414 +                                                  &v4l2_ctrls[c]);
2415 +                       if (ret)
2416 +                               break;
2417 +               }
2418 +       }
2419 +       return ret;
2420 +}
2421 +
2422 +int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
2423 +                             struct v4l2_ctrl_handler *hdl)
2424 +{
2425 +       int c;
2426 +       const struct bm2835_mmal_v4l2_ctrl *ctrl;
2427 +
2428 +       v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT);
2429 +
2430 +       for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2431 +               ctrl = &v4l2_ctrls[c];
2432 +
2433 +               switch (ctrl->type) {
2434 +               case MMAL_CONTROL_TYPE_STD:
2435 +                       dev->ctrls[c] = v4l2_ctrl_new_std(hdl,
2436 +                               &bm2835_mmal_ctrl_ops, ctrl->id,
2437 +                               ctrl->min, ctrl->max, ctrl->step, ctrl->def);
2438 +                       break;
2439 +
2440 +               case MMAL_CONTROL_TYPE_STD_MENU:
2441 +                       dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
2442 +                       &bm2835_mmal_ctrl_ops, ctrl->id,
2443 +                       ctrl->max, ctrl->min, ctrl->def);
2444 +                       break;
2445 +
2446 +               case MMAL_CONTROL_TYPE_INT_MENU:
2447 +                       dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
2448 +                               &bm2835_mmal_ctrl_ops, ctrl->id,
2449 +                               ctrl->max, ctrl->def, ctrl->imenu);
2450 +                       break;
2451 +
2452 +               case MMAL_CONTROL_TYPE_CLUSTER:
2453 +                       /* skip this entry when constructing controls */
2454 +                       continue;
2455 +               }
2456 +
2457 +               if (hdl->error)
2458 +                       break;
2459 +
2460 +               dev->ctrls[c]->priv = (void *)ctrl;
2461 +       }
2462 +
2463 +       if (hdl->error) {
2464 +               pr_err("error adding control %d/%d id 0x%x\n", c,
2465 +                        V4L2_CTRL_COUNT, ctrl->id);
2466 +               return hdl->error;
2467 +       }
2468 +
2469 +       for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2470 +               ctrl = &v4l2_ctrls[c];
2471 +
2472 +               switch (ctrl->type) {
2473 +               case MMAL_CONTROL_TYPE_CLUSTER:
2474 +                       v4l2_ctrl_auto_cluster(ctrl->min,
2475 +                                              &dev->ctrls[c+1],
2476 +                                              ctrl->max,
2477 +                                              ctrl->def);
2478 +                       break;
2479 +
2480 +               case MMAL_CONTROL_TYPE_STD:
2481 +               case MMAL_CONTROL_TYPE_STD_MENU:
2482 +               case MMAL_CONTROL_TYPE_INT_MENU:
2483 +                       break;
2484 +               }
2485 +
2486 +       }
2487 +
2488 +       return 0;
2489 +}
2490 --- /dev/null
2491 +++ b/drivers/media/platform/bcm2835/mmal-common.h
2492 @@ -0,0 +1,51 @@
2493 +/*
2494 + * Broadcom BM2835 V4L2 driver
2495 + *
2496 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2497 + *
2498 + * This file is subject to the terms and conditions of the GNU General Public
2499 + * License.  See the file COPYING in the main directory of this archive
2500 + * for more details.
2501 + *
2502 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2503 + *          Dave Stevenson <dsteve@broadcom.com>
2504 + *          Simon Mellor <simellor@broadcom.com>
2505 + *          Luke Diamand <luked@broadcom.com>
2506 + *
2507 + * MMAL structures
2508 + *
2509 + */
2510 +
2511 +#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
2512 +#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
2513 +
2514 +/** Special value signalling that time is not known */
2515 +#define MMAL_TIME_UNKNOWN (1LL<<63)
2516 +
2517 +/* mapping between v4l and mmal video modes */
2518 +struct mmal_fmt {
2519 +       char  *name;
2520 +       u32   fourcc;          /* v4l2 format id */
2521 +       u32   mmal;
2522 +       int   depth;
2523 +       u32   mmal_component;  /* MMAL component index to be used to encode */
2524 +};
2525 +
2526 +/* buffer for one video frame */
2527 +struct mmal_buffer {
2528 +       /* v4l buffer data -- must be first */
2529 +       struct vb2_buffer       vb;
2530 +
2531 +       /* list of buffers available */
2532 +       struct list_head        list;
2533 +
2534 +       void *buffer; /* buffer pointer */
2535 +       unsigned long buffer_size; /* size of allocated buffer */
2536 +};
2537 +
2538 +/* */
2539 +struct mmal_colourfx {
2540 +       s32 enable;
2541 +       u32 u;
2542 +       u32 v;
2543 +};
2544 --- /dev/null
2545 +++ b/drivers/media/platform/bcm2835/mmal-encodings.h
2546 @@ -0,0 +1,93 @@
2547 +/*
2548 + * Broadcom BM2835 V4L2 driver
2549 + *
2550 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2551 + *
2552 + * This file is subject to the terms and conditions of the GNU General Public
2553 + * License.  See the file COPYING in the main directory of this archive
2554 + * for more details.
2555 + *
2556 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2557 + *          Dave Stevenson <dsteve@broadcom.com>
2558 + *          Simon Mellor <simellor@broadcom.com>
2559 + *          Luke Diamand <luked@broadcom.com>
2560 + */
2561 +
2562 +#define MMAL_ENCODING_H264             MMAL_FOURCC('H', '2', '6', '4')
2563 +#define MMAL_ENCODING_H263             MMAL_FOURCC('H', '2', '6', '3')
2564 +#define MMAL_ENCODING_MP4V             MMAL_FOURCC('M', 'P', '4', 'V')
2565 +#define MMAL_ENCODING_MP2V             MMAL_FOURCC('M', 'P', '2', 'V')
2566 +#define MMAL_ENCODING_MP1V             MMAL_FOURCC('M', 'P', '1', 'V')
2567 +#define MMAL_ENCODING_WMV3             MMAL_FOURCC('W', 'M', 'V', '3')
2568 +#define MMAL_ENCODING_WMV2             MMAL_FOURCC('W', 'M', 'V', '2')
2569 +#define MMAL_ENCODING_WMV1             MMAL_FOURCC('W', 'M', 'V', '1')
2570 +#define MMAL_ENCODING_WVC1             MMAL_FOURCC('W', 'V', 'C', '1')
2571 +#define MMAL_ENCODING_VP8              MMAL_FOURCC('V', 'P', '8', ' ')
2572 +#define MMAL_ENCODING_VP7              MMAL_FOURCC('V', 'P', '7', ' ')
2573 +#define MMAL_ENCODING_VP6              MMAL_FOURCC('V', 'P', '6', ' ')
2574 +#define MMAL_ENCODING_THEORA           MMAL_FOURCC('T', 'H', 'E', 'O')
2575 +#define MMAL_ENCODING_SPARK            MMAL_FOURCC('S', 'P', 'R', 'K')
2576 +
2577 +#define MMAL_ENCODING_JPEG             MMAL_FOURCC('J', 'P', 'E', 'G')
2578 +#define MMAL_ENCODING_GIF              MMAL_FOURCC('G', 'I', 'F', ' ')
2579 +#define MMAL_ENCODING_PNG              MMAL_FOURCC('P', 'N', 'G', ' ')
2580 +#define MMAL_ENCODING_PPM              MMAL_FOURCC('P', 'P', 'M', ' ')
2581 +#define MMAL_ENCODING_TGA              MMAL_FOURCC('T', 'G', 'A', ' ')
2582 +#define MMAL_ENCODING_BMP              MMAL_FOURCC('B', 'M', 'P', ' ')
2583 +
2584 +#define MMAL_ENCODING_I420             MMAL_FOURCC('I', '4', '2', '0')
2585 +#define MMAL_ENCODING_I420_SLICE       MMAL_FOURCC('S', '4', '2', '0')
2586 +#define MMAL_ENCODING_YV12             MMAL_FOURCC('Y', 'V', '1', '2')
2587 +#define MMAL_ENCODING_I422             MMAL_FOURCC('I', '4', '2', '2')
2588 +#define MMAL_ENCODING_I422_SLICE       MMAL_FOURCC('S', '4', '2', '2')
2589 +#define MMAL_ENCODING_YUYV             MMAL_FOURCC('Y', 'U', 'Y', 'V')
2590 +#define MMAL_ENCODING_YVYU             MMAL_FOURCC('Y', 'V', 'Y', 'U')
2591 +#define MMAL_ENCODING_UYVY             MMAL_FOURCC('U', 'Y', 'V', 'Y')
2592 +#define MMAL_ENCODING_VYUY             MMAL_FOURCC('V', 'Y', 'U', 'Y')
2593 +#define MMAL_ENCODING_NV12             MMAL_FOURCC('N', 'V', '1', '2')
2594 +#define MMAL_ENCODING_NV21             MMAL_FOURCC('N', 'V', '2', '1')
2595 +#define MMAL_ENCODING_ARGB             MMAL_FOURCC('A', 'R', 'G', 'B')
2596 +#define MMAL_ENCODING_RGBA             MMAL_FOURCC('R', 'G', 'B', 'A')
2597 +#define MMAL_ENCODING_ABGR             MMAL_FOURCC('A', 'B', 'G', 'R')
2598 +#define MMAL_ENCODING_BGRA             MMAL_FOURCC('B', 'G', 'R', 'A')
2599 +#define MMAL_ENCODING_RGB16            MMAL_FOURCC('R', 'G', 'B', '2')
2600 +#define MMAL_ENCODING_RGB24            MMAL_FOURCC('R', 'G', 'B', '3')
2601 +#define MMAL_ENCODING_RGB32            MMAL_FOURCC('R', 'G', 'B', '4')
2602 +#define MMAL_ENCODING_BGR16            MMAL_FOURCC('B', 'G', 'R', '2')
2603 +#define MMAL_ENCODING_BGR24            MMAL_FOURCC('B', 'G', 'R', '3')
2604 +#define MMAL_ENCODING_BGR32            MMAL_FOURCC('B', 'G', 'R', '4')
2605 +
2606 +/** SAND Video (YUVUV128) format, native format understood by VideoCore.
2607 + * This format is *not* opaque - if requested you will receive full frames
2608 + * of YUV_UV video.
2609 + */
2610 +#define MMAL_ENCODING_YUVUV128         MMAL_FOURCC('S', 'A', 'N', 'D')
2611 +
2612 +/** VideoCore opaque image format, image handles are returned to
2613 + * the host but not the actual image data.
2614 + */
2615 +#define MMAL_ENCODING_OPAQUE           MMAL_FOURCC('O', 'P', 'Q', 'V')
2616 +
2617 +/** An EGL image handle
2618 + */
2619 +#define MMAL_ENCODING_EGL_IMAGE        MMAL_FOURCC('E', 'G', 'L', 'I')
2620 +
2621 +/* }@ */
2622 +
2623 +/** \name Pre-defined audio encodings */
2624 +/* @{ */
2625 +#define MMAL_ENCODING_PCM_UNSIGNED_BE  MMAL_FOURCC('P', 'C', 'M', 'U')
2626 +#define MMAL_ENCODING_PCM_UNSIGNED_LE  MMAL_FOURCC('p', 'c', 'm', 'u')
2627 +#define MMAL_ENCODING_PCM_SIGNED_BE    MMAL_FOURCC('P', 'C', 'M', 'S')
2628 +#define MMAL_ENCODING_PCM_SIGNED_LE    MMAL_FOURCC('p', 'c', 'm', 's')
2629 +#define MMAL_ENCODING_PCM_FLOAT_BE     MMAL_FOURCC('P', 'C', 'M', 'F')
2630 +#define MMAL_ENCODING_PCM_FLOAT_LE     MMAL_FOURCC('p', 'c', 'm', 'f')
2631 +
2632 +/* Pre-defined H264 encoding variants */
2633 +
2634 +/** ISO 14496-10 Annex B byte stream format */
2635 +#define MMAL_ENCODING_VARIANT_H264_DEFAULT   0
2636 +/** ISO 14496-15 AVC stream format */
2637 +#define MMAL_ENCODING_VARIANT_H264_AVC1      MMAL_FOURCC('A', 'V', 'C', '1')
2638 +/** Implicitly delineated NAL units without emulation prevention */
2639 +#define MMAL_ENCODING_VARIANT_H264_RAW       MMAL_FOURCC('R', 'A', 'W', ' ')
2640 --- /dev/null
2641 +++ b/drivers/media/platform/bcm2835/mmal-msg-common.h
2642 @@ -0,0 +1,50 @@
2643 +/*
2644 + * Broadcom BM2835 V4L2 driver
2645 + *
2646 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2647 + *
2648 + * This file is subject to the terms and conditions of the GNU General Public
2649 + * License.  See the file COPYING in the main directory of this archive
2650 + * for more details.
2651 + *
2652 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2653 + *          Dave Stevenson <dsteve@broadcom.com>
2654 + *          Simon Mellor <simellor@broadcom.com>
2655 + *          Luke Diamand <luked@broadcom.com>
2656 + */
2657 +
2658 +#ifndef MMAL_MSG_COMMON_H
2659 +#define MMAL_MSG_COMMON_H
2660 +
2661 +enum mmal_msg_status {
2662 +       MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
2663 +       MMAL_MSG_STATUS_ENOMEM,      /**< Out of memory */
2664 +       MMAL_MSG_STATUS_ENOSPC,      /**< Out of resources other than memory */
2665 +       MMAL_MSG_STATUS_EINVAL,      /**< Argument is invalid */
2666 +       MMAL_MSG_STATUS_ENOSYS,      /**< Function not implemented */
2667 +       MMAL_MSG_STATUS_ENOENT,      /**< No such file or directory */
2668 +       MMAL_MSG_STATUS_ENXIO,       /**< No such device or address */
2669 +       MMAL_MSG_STATUS_EIO,         /**< I/O error */
2670 +       MMAL_MSG_STATUS_ESPIPE,      /**< Illegal seek */
2671 +       MMAL_MSG_STATUS_ECORRUPT,    /**< Data is corrupt \attention */
2672 +       MMAL_MSG_STATUS_ENOTREADY,   /**< Component is not ready */
2673 +       MMAL_MSG_STATUS_ECONFIG,     /**< Component is not configured */
2674 +       MMAL_MSG_STATUS_EISCONN,     /**< Port is already connected */
2675 +       MMAL_MSG_STATUS_ENOTCONN,    /**< Port is disconnected */
2676 +       MMAL_MSG_STATUS_EAGAIN,      /**< Resource temporarily unavailable. */
2677 +       MMAL_MSG_STATUS_EFAULT,      /**< Bad address */
2678 +};
2679 +
2680 +struct mmal_rect {
2681 +       s32 x;      /**< x coordinate (from left) */
2682 +       s32 y;      /**< y coordinate (from top) */
2683 +       s32 width;  /**< width */
2684 +       s32 height; /**< height */
2685 +};
2686 +
2687 +struct mmal_rational {
2688 +       s32 num;    /**< Numerator */
2689 +       s32 den;    /**< Denominator */
2690 +};
2691 +
2692 +#endif /* MMAL_MSG_COMMON_H */
2693 --- /dev/null
2694 +++ b/drivers/media/platform/bcm2835/mmal-msg-format.h
2695 @@ -0,0 +1,81 @@
2696 +/*
2697 + * Broadcom BM2835 V4L2 driver
2698 + *
2699 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2700 + *
2701 + * This file is subject to the terms and conditions of the GNU General Public
2702 + * License.  See the file COPYING in the main directory of this archive
2703 + * for more details.
2704 + *
2705 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2706 + *          Dave Stevenson <dsteve@broadcom.com>
2707 + *          Simon Mellor <simellor@broadcom.com>
2708 + *          Luke Diamand <luked@broadcom.com>
2709 + */
2710 +
2711 +#ifndef MMAL_MSG_FORMAT_H
2712 +#define MMAL_MSG_FORMAT_H
2713 +
2714 +#include "mmal-msg-common.h"
2715 +
2716 +/* MMAL_ES_FORMAT_T */
2717 +
2718 +
2719 +struct mmal_audio_format {
2720 +       u32 channels;           /**< Number of audio channels */
2721 +       u32 sample_rate;        /**< Sample rate */
2722 +
2723 +       u32 bits_per_sample;    /**< Bits per sample */
2724 +       u32 block_align;        /**< Size of a block of data */
2725 +};
2726 +
2727 +struct mmal_video_format {
2728 +       u32 width;        /**< Width of frame in pixels */
2729 +       u32 height;       /**< Height of frame in rows of pixels */
2730 +       struct mmal_rect crop;         /**< Visible region of the frame */
2731 +       struct mmal_rational frame_rate;   /**< Frame rate */
2732 +       struct mmal_rational par;          /**< Pixel aspect ratio */
2733 +
2734 +       /* FourCC specifying the color space of the video stream. See the
2735 +        * \ref MmalColorSpace "pre-defined color spaces" for some examples.
2736 +        */
2737 +       u32 color_space;
2738 +};
2739 +
2740 +struct mmal_subpicture_format {
2741 +       u32 x_offset;
2742 +       u32 y_offset;
2743 +};
2744 +
2745 +union mmal_es_specific_format {
2746 +       struct mmal_audio_format audio;
2747 +       struct mmal_video_format video;
2748 +       struct mmal_subpicture_format subpicture;
2749 +};
2750 +
2751 +/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
2752 +struct mmal_es_format {
2753 +       u32 type;      /* enum mmal_es_type */
2754 +
2755 +       u32 encoding;  /* FourCC specifying encoding of the elementary stream.*/
2756 +       u32 encoding_variant; /* FourCC specifying the specific
2757 +                              * encoding variant of the elementary
2758 +                              * stream.
2759 +                              */
2760 +
2761 +       union mmal_es_specific_format *es; /* TODO: pointers in
2762 +                                           * message serialisation?!?
2763 +                                           */
2764 +                                           /* Type specific
2765 +                                            * information for the
2766 +                                            * elementary stream
2767 +                                            */
2768 +
2769 +       u32 bitrate;        /**< Bitrate in bits per second */
2770 +       u32 flags; /**< Flags describing properties of the elementary stream. */
2771 +
2772 +       u32 extradata_size;       /**< Size of the codec specific data */
2773 +       u8  *extradata;           /**< Codec specific data */
2774 +};
2775 +
2776 +#endif /* MMAL_MSG_FORMAT_H */
2777 --- /dev/null
2778 +++ b/drivers/media/platform/bcm2835/mmal-msg-port.h
2779 @@ -0,0 +1,107 @@
2780 +/*
2781 + * Broadcom BM2835 V4L2 driver
2782 + *
2783 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2784 + *
2785 + * This file is subject to the terms and conditions of the GNU General Public
2786 + * License.  See the file COPYING in the main directory of this archive
2787 + * for more details.
2788 + *
2789 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2790 + *          Dave Stevenson <dsteve@broadcom.com>
2791 + *          Simon Mellor <simellor@broadcom.com>
2792 + *          Luke Diamand <luked@broadcom.com>
2793 + */
2794 +
2795 +/* MMAL_PORT_TYPE_T */
2796 +enum mmal_port_type {
2797 +       MMAL_PORT_TYPE_UNKNOWN = 0,  /**< Unknown port type */
2798 +       MMAL_PORT_TYPE_CONTROL,      /**< Control port */
2799 +       MMAL_PORT_TYPE_INPUT,        /**< Input port */
2800 +       MMAL_PORT_TYPE_OUTPUT,       /**< Output port */
2801 +       MMAL_PORT_TYPE_CLOCK,        /**< Clock port */
2802 +};
2803 +
2804 +/** The port is pass-through and doesn't need buffer headers allocated */
2805 +#define MMAL_PORT_CAPABILITY_PASSTHROUGH                       0x01
2806 +/** The port wants to allocate the buffer payloads.
2807 + * This signals a preference that payload allocation should be done
2808 + * on this port for efficiency reasons. */
2809 +#define MMAL_PORT_CAPABILITY_ALLOCATION                        0x02
2810 +/** The port supports format change events.
2811 + * This applies to input ports and is used to let the client know
2812 + * whether the port supports being reconfigured via a format
2813 + * change event (i.e. without having to disable the port). */
2814 +#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE      0x04
2815 +
2816 +/* mmal port structure (MMAL_PORT_T)
2817 + *
2818 + * most elements are informational only, the pointer values for
2819 + * interogation messages are generally provided as additional
2820 + * strucures within the message. When used to set values only teh
2821 + * buffer_num, buffer_size and userdata parameters are writable.
2822 + */
2823 +struct mmal_port {
2824 +       void *priv; /* Private member used by the framework */
2825 +       const char *name; /* Port name. Used for debugging purposes (RO) */
2826 +
2827 +       u32 type;      /* Type of the port (RO) enum mmal_port_type */
2828 +       u16 index;     /* Index of the port in its type list (RO) */
2829 +       u16 index_all; /* Index of the port in the list of all ports (RO) */
2830 +
2831 +       u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
2832 +       struct mmal_es_format *format; /* Format of the elementary stream */
2833 +
2834 +       u32 buffer_num_min; /* Minimum number of buffers the port
2835 +                            *   requires (RO).  This is set by the
2836 +                            *   component.
2837 +                            */
2838 +
2839 +       u32 buffer_size_min; /* Minimum size of buffers the port
2840 +                             * requires (RO).  This is set by the
2841 +                             * component.
2842 +                             */
2843 +
2844 +       u32 buffer_alignment_min; /* Minimum alignment requirement for
2845 +                                  * the buffers (RO).  A value of
2846 +                                  * zero means no special alignment
2847 +                                  * requirements.  This is set by the
2848 +                                  * component.
2849 +                                  */
2850 +
2851 +       u32 buffer_num_recommended;  /* Number of buffers the port
2852 +                                     * recommends for optimal
2853 +                                     * performance (RO).  A value of
2854 +                                     * zero means no special
2855 +                                     * recommendation.  This is set
2856 +                                     * by the component.
2857 +                                     */
2858 +
2859 +       u32 buffer_size_recommended; /* Size of buffers the port
2860 +                                     * recommends for optimal
2861 +                                     * performance (RO).  A value of
2862 +                                     * zero means no special
2863 +                                     * recommendation.  This is set
2864 +                                     * by the component.
2865 +                                     */
2866 +
2867 +       u32 buffer_num; /* Actual number of buffers the port will use.
2868 +                        * This is set by the client.
2869 +                        */
2870 +
2871 +       u32 buffer_size; /* Actual maximum size of the buffers that
2872 +                         * will be sent to the port. This is set by
2873 +                         * the client.
2874 +                         */
2875 +
2876 +       void *component; /* Component this port belongs to (Read Only) */
2877 +
2878 +       void *userdata; /* Field reserved for use by the client */
2879 +
2880 +       u32 capabilities; /* Flags describing the capabilities of a
2881 +                          * port (RO).  Bitwise combination of \ref
2882 +                          * portcapabilities "Port capabilities"
2883 +                          * values.
2884 +                          */
2885 +
2886 +};
2887 --- /dev/null
2888 +++ b/drivers/media/platform/bcm2835/mmal-msg.h
2889 @@ -0,0 +1,404 @@
2890 +/*
2891 + * Broadcom BM2835 V4L2 driver
2892 + *
2893 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
2894 + *
2895 + * This file is subject to the terms and conditions of the GNU General Public
2896 + * License.  See the file COPYING in the main directory of this archive
2897 + * for more details.
2898 + *
2899 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
2900 + *          Dave Stevenson <dsteve@broadcom.com>
2901 + *          Simon Mellor <simellor@broadcom.com>
2902 + *          Luke Diamand <luked@broadcom.com>
2903 + */
2904 +
2905 +/* all the data structures which serialise the MMAL protocol. note
2906 + * these are directly mapped onto the recived message data.
2907 + *
2908 + * BEWARE: They seem to *assume* pointers are u32 and that there is no
2909 + * structure padding!
2910 + *
2911 + * NOTE: this implementation uses kernel types to ensure sizes. Rather
2912 + * than assigning values to enums to force their size the
2913 + * implementation uses fixed size types and not the enums (though the
2914 + * comments have the actual enum type
2915 + */
2916 +
2917 +#define VC_MMAL_VER 15
2918 +#define VC_MMAL_MIN_VER 10
2919 +#define VC_MMAL_SERVER_NAME  MAKE_FOURCC("mmal")
2920 +
2921 +/* max total message size is 512 bytes */
2922 +#define MMAL_MSG_MAX_SIZE 512
2923 +/* with six 32bit header elements max payload is therefore 488 bytes */
2924 +#define MMAL_MSG_MAX_PAYLOAD 488
2925 +
2926 +#include "mmal-msg-common.h"
2927 +#include "mmal-msg-format.h"
2928 +#include "mmal-msg-port.h"
2929 +
2930 +enum mmal_msg_type {
2931 +       MMAL_MSG_TYPE_QUIT = 1,
2932 +       MMAL_MSG_TYPE_SERVICE_CLOSED,
2933 +       MMAL_MSG_TYPE_GET_VERSION,
2934 +       MMAL_MSG_TYPE_COMPONENT_CREATE,
2935 +       MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */
2936 +       MMAL_MSG_TYPE_COMPONENT_ENABLE,
2937 +       MMAL_MSG_TYPE_COMPONENT_DISABLE,
2938 +       MMAL_MSG_TYPE_PORT_INFO_GET,
2939 +       MMAL_MSG_TYPE_PORT_INFO_SET,
2940 +       MMAL_MSG_TYPE_PORT_ACTION, /* 10 */
2941 +       MMAL_MSG_TYPE_BUFFER_FROM_HOST,
2942 +       MMAL_MSG_TYPE_BUFFER_TO_HOST,
2943 +       MMAL_MSG_TYPE_GET_STATS,
2944 +       MMAL_MSG_TYPE_PORT_PARAMETER_SET,
2945 +       MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */
2946 +       MMAL_MSG_TYPE_EVENT_TO_HOST,
2947 +       MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
2948 +       MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
2949 +       MMAL_MSG_TYPE_CONSUME_MEM,
2950 +       MMAL_MSG_TYPE_LMK, /* 20 */
2951 +       MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
2952 +       MMAL_MSG_TYPE_DRM_GET_LHS32,
2953 +       MMAL_MSG_TYPE_DRM_GET_TIME,
2954 +       MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
2955 +       MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */
2956 +       MMAL_MSG_TYPE_HOST_LOG,
2957 +       MMAL_MSG_TYPE_MSG_LAST
2958 +};
2959 +
2960 +/* port action request messages differ depending on the action type */
2961 +enum mmal_msg_port_action_type {
2962 +       MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0,      /* Unkown action */
2963 +       MMAL_MSG_PORT_ACTION_TYPE_ENABLE,           /* Enable a port */
2964 +       MMAL_MSG_PORT_ACTION_TYPE_DISABLE,          /* Disable a port */
2965 +       MMAL_MSG_PORT_ACTION_TYPE_FLUSH,            /* Flush a port */
2966 +       MMAL_MSG_PORT_ACTION_TYPE_CONNECT,          /* Connect ports */
2967 +       MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,       /* Disconnect ports */
2968 +       MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
2969 +};
2970 +
2971 +struct mmal_msg_header {
2972 +       u32 magic;
2973 +       u32 type; /** enum mmal_msg_type */
2974 +
2975 +       /* Opaque handle to the control service */
2976 +       struct mmal_control_service *control_service;
2977 +
2978 +       struct mmal_msg_context *context; /** a u32 per message context */
2979 +       u32 status; /** The status of the vchiq operation */
2980 +       u32 padding;
2981 +};
2982 +
2983 +/* Send from VC to host to report version */
2984 +struct mmal_msg_version {
2985 +       u32 flags;
2986 +       u32 major;
2987 +       u32 minor;
2988 +       u32 minimum;
2989 +};
2990 +
2991 +/* request to VC to create component */
2992 +struct mmal_msg_component_create {
2993 +       void *client_component; /* component context */
2994 +       char name[128];
2995 +       u32 pid;                /* For debug */
2996 +};
2997 +
2998 +/* reply from VC to component creation request */
2999 +struct mmal_msg_component_create_reply {
3000 +       u32 status; /** enum mmal_msg_status - how does this differ to
3001 +                    * the one in the header?
3002 +                    */
3003 +       u32 component_handle; /* VideoCore handle for component */
3004 +       u32 input_num;        /* Number of input ports */
3005 +       u32 output_num;       /* Number of output ports */
3006 +       u32 clock_num;        /* Number of clock ports */
3007 +};
3008 +
3009 +/* request to VC to destroy a component */
3010 +struct mmal_msg_component_destroy {
3011 +       u32 component_handle;
3012 +};
3013 +
3014 +struct mmal_msg_component_destroy_reply {
3015 +       u32 status; /** The component destruction status */
3016 +};
3017 +
3018 +
3019 +/* request and reply to VC to enable a component */
3020 +struct mmal_msg_component_enable {
3021 +       u32 component_handle;
3022 +};
3023 +
3024 +struct mmal_msg_component_enable_reply {
3025 +       u32 status; /** The component enable status */
3026 +};
3027 +
3028 +
3029 +/* request and reply to VC to disable a component */
3030 +struct mmal_msg_component_disable {
3031 +       u32 component_handle;
3032 +};
3033 +
3034 +struct mmal_msg_component_disable_reply {
3035 +       u32 status; /** The component disable status */
3036 +};
3037 +
3038 +/* request to VC to get port information */
3039 +struct mmal_msg_port_info_get {
3040 +       u32 component_handle;  /* component handle port is associated with */
3041 +       u32 port_type;         /* enum mmal_msg_port_type */
3042 +       u32 index;             /* port index to query */
3043 +};
3044 +
3045 +/* reply from VC to get port info request */
3046 +struct mmal_msg_port_info_get_reply {
3047 +       u32 status; /** enum mmal_msg_status */
3048 +       u32 component_handle;  /* component handle port is associated with */
3049 +       u32 port_type;         /* enum mmal_msg_port_type */
3050 +       u32 port_index;        /* port indexed in query */
3051 +       s32 found;             /* unused */
3052 +       u32 port_handle;               /**< Handle to use for this port */
3053 +       struct mmal_port port;
3054 +       struct mmal_es_format format; /* elementry stream format */
3055 +       union mmal_es_specific_format es; /* es type specific data */
3056 +       u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
3057 +};
3058 +
3059 +/* request to VC to set port information */
3060 +struct mmal_msg_port_info_set {
3061 +       u32 component_handle;
3062 +       u32 port_type;         /* enum mmal_msg_port_type */
3063 +       u32 port_index;           /* port indexed in query */
3064 +       struct mmal_port port;
3065 +       struct mmal_es_format format;
3066 +       union mmal_es_specific_format es;
3067 +       u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
3068 +};
3069 +
3070 +/* reply from VC to port info set request */
3071 +struct mmal_msg_port_info_set_reply {
3072 +       u32 status;
3073 +       u32 component_handle;  /* component handle port is associated with */
3074 +       u32 port_type;         /* enum mmal_msg_port_type */
3075 +       u32 index;             /* port indexed in query */
3076 +       s32 found;             /* unused */
3077 +       u32 port_handle;               /**< Handle to use for this port */
3078 +       struct mmal_port port;
3079 +       struct mmal_es_format format;
3080 +       union mmal_es_specific_format es;
3081 +       u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
3082 +};
3083 +
3084 +
3085 +/* port action requests that take a mmal_port as a parameter */
3086 +struct mmal_msg_port_action_port {
3087 +       u32 component_handle;
3088 +       u32 port_handle;
3089 +       u32 action; /* enum mmal_msg_port_action_type */
3090 +       struct mmal_port port;
3091 +};
3092 +
3093 +/* port action requests that take handles as a parameter */
3094 +struct mmal_msg_port_action_handle {
3095 +       u32 component_handle;
3096 +       u32 port_handle;
3097 +       u32 action; /* enum mmal_msg_port_action_type */
3098 +       u32 connect_component_handle;
3099 +       u32 connect_port_handle;
3100 +};
3101 +
3102 +struct mmal_msg_port_action_reply {
3103 +       u32 status; /** The port action operation status */
3104 +};
3105 +
3106 +
3107 +
3108 +
3109 +/* MMAL buffer transfer */
3110 +
3111 +/** Size of space reserved in a buffer message for short messages. */
3112 +#define MMAL_VC_SHORT_DATA 128
3113 +
3114 +/** Signals that the current payload is the end of the stream of data */
3115 +#define MMAL_BUFFER_HEADER_FLAG_EOS                    (1<<0)
3116 +/** Signals that the start of the current payload starts a frame */
3117 +#define MMAL_BUFFER_HEADER_FLAG_FRAME_START            (1<<1)
3118 +/** Signals that the end of the current payload ends a frame */
3119 +#define MMAL_BUFFER_HEADER_FLAG_FRAME_END              (1<<2)
3120 +/** Signals that the current payload contains only complete frames (>1) */
3121 +#define MMAL_BUFFER_HEADER_FLAG_FRAME                  \
3122 +       (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
3123 +/** Signals that the current payload is a keyframe (i.e. self decodable) */
3124 +#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME               (1<<3)
3125 +/** Signals a discontinuity in the stream of data (e.g. after a seek).
3126 + * Can be used for instance by a decoder to reset its state */
3127 +#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY          (1<<4)
3128 +/** Signals a buffer containing some kind of config data for the component
3129 + * (e.g. codec config data) */
3130 +#define MMAL_BUFFER_HEADER_FLAG_CONFIG                 (1<<5)
3131 +/** Signals an encrypted payload */
3132 +#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED              (1<<6)
3133 +/** Signals a buffer containing side information */
3134 +#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO          (1<<7)
3135 +/** Signals a buffer which is the snapshot/postview image from a stills
3136 + * capture
3137 + */
3138 +#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT              (1<<8)
3139 +/** Signals a buffer which contains data known to be corrupted */
3140 +#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED              (1<<9)
3141 +/** Signals that a buffer failed to be transmitted */
3142 +#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED    (1<<10)
3143 +
3144 +struct mmal_driver_buffer {
3145 +       u32 magic;
3146 +       u32 component_handle;
3147 +       u32 port_handle;
3148 +       void *client_context;
3149 +};
3150 +
3151 +/* buffer header */
3152 +struct mmal_buffer_header {
3153 +       struct mmal_buffer_header *next; /* next header */
3154 +       void *priv; /* framework private data */
3155 +       u32 cmd;
3156 +       void *data;
3157 +       u32 alloc_size;
3158 +       u32 length;
3159 +       u32 offset;
3160 +       u32 flags;
3161 +       s64 pts;
3162 +       s64 dts;
3163 +       void *type;
3164 +       void *user_data;
3165 +};
3166 +
3167 +struct mmal_buffer_header_type_specific {
3168 +       union {
3169 +               struct {
3170 +               u32 planes;
3171 +               u32 offset[4];
3172 +               u32 pitch[4];
3173 +               u32 flags;
3174 +               } video;
3175 +       } u;
3176 +};
3177 +
3178 +struct mmal_msg_buffer_from_host {
3179 +       /* The front 32 bytes of the buffer header are copied
3180 +        * back to us in the reply to allow for context. This
3181 +        * area is used to store two mmal_driver_buffer structures to
3182 +        * allow for multiple concurrent service users.
3183 +        */
3184 +       /* control data */
3185 +       struct mmal_driver_buffer drvbuf;
3186 +
3187 +       /* referenced control data for passthrough buffer management */
3188 +       struct mmal_driver_buffer drvbuf_ref;
3189 +       struct mmal_buffer_header buffer_header; /* buffer header itself */
3190 +       struct mmal_buffer_header_type_specific buffer_header_type_specific;
3191 +       s32 is_zero_copy;
3192 +       s32 has_reference;
3193 +
3194 +       /** allows short data to be xfered in control message */
3195 +       u32 payload_in_message;
3196 +       u8 short_data[MMAL_VC_SHORT_DATA];
3197 +};
3198 +
3199 +
3200 +/* port parameter setting */
3201 +
3202 +#define MMAL_WORKER_PORT_PARAMETER_SPACE      96
3203 +
3204 +struct mmal_msg_port_parameter_set {
3205 +       u32 component_handle; /* component */
3206 +       u32 port_handle;      /* port */
3207 +       u32 id;     /* Parameter ID  */
3208 +       u32 size;      /* Parameter size */
3209 +       uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
3210 +};
3211 +
3212 +struct mmal_msg_port_parameter_set_reply {
3213 +       u32 status; /** enum mmal_msg_status todo: how does this
3214 +                    * differ to the one in the header?
3215 +                    */
3216 +};
3217 +
3218 +/* port parameter getting */
3219 +
3220 +struct mmal_msg_port_parameter_get {
3221 +       u32 component_handle; /* component */
3222 +       u32 port_handle;      /* port */
3223 +       u32 id;     /* Parameter ID  */
3224 +       u32 size;      /* Parameter size */
3225 +};
3226 +
3227 +struct mmal_msg_port_parameter_get_reply {
3228 +       u32 status;           /* Status of mmal_port_parameter_get call */
3229 +       u32 id;     /* Parameter ID  */
3230 +       u32 size;      /* Parameter size */
3231 +       uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
3232 +};
3233 +
3234 +/* event messages */
3235 +#define MMAL_WORKER_EVENT_SPACE 256
3236 +
3237 +struct mmal_msg_event_to_host {
3238 +       void *client_component; /* component context */
3239 +
3240 +       u32 port_type;
3241 +       u32 port_num;
3242 +
3243 +       u32 cmd;
3244 +       u32 length;
3245 +       u8 data[MMAL_WORKER_EVENT_SPACE];
3246 +       struct mmal_buffer_header *delayed_buffer;
3247 +};
3248 +
3249 +/* all mmal messages are serialised through this structure */
3250 +struct mmal_msg {
3251 +       /* header */
3252 +       struct mmal_msg_header h;
3253 +       /* payload */
3254 +       union {
3255 +               struct mmal_msg_version version;
3256 +
3257 +               struct mmal_msg_component_create component_create;
3258 +               struct mmal_msg_component_create_reply component_create_reply;
3259 +
3260 +               struct mmal_msg_component_destroy component_destroy;
3261 +               struct mmal_msg_component_destroy_reply component_destroy_reply;
3262 +
3263 +               struct mmal_msg_component_enable component_enable;
3264 +               struct mmal_msg_component_enable_reply component_enable_reply;
3265 +
3266 +               struct mmal_msg_component_disable component_disable;
3267 +               struct mmal_msg_component_disable_reply component_disable_reply;
3268 +
3269 +               struct mmal_msg_port_info_get port_info_get;
3270 +               struct mmal_msg_port_info_get_reply port_info_get_reply;
3271 +
3272 +               struct mmal_msg_port_info_set port_info_set;
3273 +               struct mmal_msg_port_info_set_reply port_info_set_reply;
3274 +
3275 +               struct mmal_msg_port_action_port port_action_port;
3276 +               struct mmal_msg_port_action_handle port_action_handle;
3277 +               struct mmal_msg_port_action_reply port_action_reply;
3278 +
3279 +               struct mmal_msg_buffer_from_host buffer_from_host;
3280 +
3281 +               struct mmal_msg_port_parameter_set port_parameter_set;
3282 +               struct mmal_msg_port_parameter_set_reply
3283 +                       port_parameter_set_reply;
3284 +               struct mmal_msg_port_parameter_get
3285 +                       port_parameter_get;
3286 +               struct mmal_msg_port_parameter_get_reply
3287 +                       port_parameter_get_reply;
3288 +
3289 +               struct mmal_msg_event_to_host event_to_host;
3290 +
3291 +               u8 payload[MMAL_MSG_MAX_PAYLOAD];
3292 +       } u;
3293 +};
3294 --- /dev/null
3295 +++ b/drivers/media/platform/bcm2835/mmal-parameters.h
3296 @@ -0,0 +1,539 @@
3297 +/*
3298 + * Broadcom BM2835 V4L2 driver
3299 + *
3300 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
3301 + *
3302 + * This file is subject to the terms and conditions of the GNU General Public
3303 + * License.  See the file COPYING in the main directory of this archive
3304 + * for more details.
3305 + *
3306 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
3307 + *          Dave Stevenson <dsteve@broadcom.com>
3308 + *          Simon Mellor <simellor@broadcom.com>
3309 + *          Luke Diamand <luked@broadcom.com>
3310 + */
3311 +
3312 +/* common parameters */
3313 +
3314 +/** @name Parameter groups
3315 + * Parameters are divided into groups, and then allocated sequentially within
3316 + * a group using an enum.
3317 + * @{
3318 + */
3319 +
3320 +/** Common parameter ID group, used with many types of component. */
3321 +#define MMAL_PARAMETER_GROUP_COMMON            (0<<16)
3322 +/** Camera-specific parameter ID group. */
3323 +#define MMAL_PARAMETER_GROUP_CAMERA            (1<<16)
3324 +/** Video-specific parameter ID group. */
3325 +#define MMAL_PARAMETER_GROUP_VIDEO             (2<<16)
3326 +/** Audio-specific parameter ID group. */
3327 +#define MMAL_PARAMETER_GROUP_AUDIO             (3<<16)
3328 +/** Clock-specific parameter ID group. */
3329 +#define MMAL_PARAMETER_GROUP_CLOCK             (4<<16)
3330 +/** Miracast-specific parameter ID group. */
3331 +#define MMAL_PARAMETER_GROUP_MIRACAST       (5<<16)
3332 +
3333 +/* Common parameters */
3334 +enum mmal_parameter_common_type {
3335 +       MMAL_PARAMETER_UNUSED  /**< Never a valid parameter ID */
3336 +               = MMAL_PARAMETER_GROUP_COMMON,
3337 +       MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< MMAL_PARAMETER_ENCODING_T */
3338 +       MMAL_PARAMETER_URI, /**< MMAL_PARAMETER_URI_T */
3339 +
3340 +       /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
3341 +       MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
3342 +
3343 +       /** MMAL_PARAMETER_BOOLEAN_T */
3344 +       MMAL_PARAMETER_ZERO_COPY,
3345 +
3346 +       /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
3347 +       MMAL_PARAMETER_BUFFER_REQUIREMENTS,
3348 +
3349 +       MMAL_PARAMETER_STATISTICS, /**< MMAL_PARAMETER_STATISTICS_T */
3350 +       MMAL_PARAMETER_CORE_STATISTICS, /**< MMAL_PARAMETER_CORE_STATISTICS_T */
3351 +       MMAL_PARAMETER_MEM_USAGE, /**< MMAL_PARAMETER_MEM_USAGE_T */
3352 +       MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< MMAL_PARAMETER_UINT32_T */
3353 +       MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
3354 +       MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
3355 +       MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
3356 +       MMAL_PARAMETER_SYSTEM_TIME /**< MMAL_PARAMETER_UINT64_T */
3357 +};
3358 +
3359 +/* camera parameters */
3360 +
3361 +enum mmal_parameter_camera_type {
3362 +       /* 0 */
3363 +       /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
3364 +       MMAL_PARAMETER_THUMBNAIL_CONFIGURATION
3365 +               = MMAL_PARAMETER_GROUP_CAMERA,
3366 +       MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */
3367 +       MMAL_PARAMETER_ROTATION, /**< @ref MMAL_PARAMETER_INT32_T */
3368 +       MMAL_PARAMETER_EXIF_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3369 +       MMAL_PARAMETER_EXIF, /**< @ref MMAL_PARAMETER_EXIF_T */
3370 +       MMAL_PARAMETER_AWB_MODE, /**< @ref MMAL_PARAM_AWBMODE_T */
3371 +       MMAL_PARAMETER_IMAGE_EFFECT, /**< @ref MMAL_PARAMETER_IMAGEFX_T */
3372 +       MMAL_PARAMETER_COLOUR_EFFECT, /**< @ref MMAL_PARAMETER_COLOURFX_T */
3373 +       MMAL_PARAMETER_FLICKER_AVOID, /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
3374 +       MMAL_PARAMETER_FLASH, /**< @ref MMAL_PARAMETER_FLASH_T */
3375 +       MMAL_PARAMETER_REDEYE, /**< @ref MMAL_PARAMETER_REDEYE_T */
3376 +       MMAL_PARAMETER_FOCUS, /**< @ref MMAL_PARAMETER_FOCUS_T */
3377 +       MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */
3378 +       MMAL_PARAMETER_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
3379 +       MMAL_PARAMETER_ZOOM, /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
3380 +       MMAL_PARAMETER_MIRROR, /**< @ref MMAL_PARAMETER_MIRROR_T */
3381 +
3382 +       /* 0x10 */
3383 +       MMAL_PARAMETER_CAMERA_NUM, /**< @ref MMAL_PARAMETER_UINT32_T */
3384 +       MMAL_PARAMETER_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3385 +       MMAL_PARAMETER_EXPOSURE_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
3386 +       MMAL_PARAMETER_EXP_METERING_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
3387 +       MMAL_PARAMETER_FOCUS_STATUS, /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
3388 +       MMAL_PARAMETER_CAMERA_CONFIG, /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
3389 +       MMAL_PARAMETER_CAPTURE_STATUS, /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
3390 +       MMAL_PARAMETER_FACE_TRACK, /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
3391 +       MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3392 +       MMAL_PARAMETER_JPEG_Q_FACTOR, /**< @ref MMAL_PARAMETER_UINT32_T */
3393 +       MMAL_PARAMETER_FRAME_RATE, /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
3394 +       MMAL_PARAMETER_USE_STC, /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
3395 +       MMAL_PARAMETER_CAMERA_INFO, /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
3396 +       MMAL_PARAMETER_VIDEO_STABILISATION, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3397 +       MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
3398 +       MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3399 +
3400 +       /* 0x20 */
3401 +       MMAL_PARAMETER_DPF_FILE, /**< @ref MMAL_PARAMETER_URI_T */
3402 +       MMAL_PARAMETER_ENABLE_DPF_FILE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3403 +       MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3404 +       MMAL_PARAMETER_CAPTURE_MODE, /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
3405 +       MMAL_PARAMETER_FOCUS_REGIONS, /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
3406 +       MMAL_PARAMETER_INPUT_CROP, /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
3407 +       MMAL_PARAMETER_SENSOR_INFORMATION, /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
3408 +       MMAL_PARAMETER_FLASH_SELECT, /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
3409 +       MMAL_PARAMETER_FIELD_OF_VIEW, /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
3410 +       MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3411 +       MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< @ref MMAL_PARAMETER_DRC_T */
3412 +       MMAL_PARAMETER_ALGORITHM_CONTROL, /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
3413 +       MMAL_PARAMETER_SHARPNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
3414 +       MMAL_PARAMETER_CONTRAST, /**< @ref MMAL_PARAMETER_RATIONAL_T */
3415 +       MMAL_PARAMETER_BRIGHTNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
3416 +       MMAL_PARAMETER_SATURATION, /**< @ref MMAL_PARAMETER_RATIONAL_T */
3417 +
3418 +       /* 0x30 */
3419 +       MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
3420 +       MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3421 +
3422 +       /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
3423 +       MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
3424 +
3425 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3426 +       MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
3427 +
3428 +       /** @ref MMAL_PARAMETER_UINT32_T */
3429 +       MMAL_PARAMETER_CAMERA_MIN_ISO,
3430 +
3431 +       /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
3432 +       MMAL_PARAMETER_CAMERA_USE_CASE,
3433 +
3434 +       /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3435 +       MMAL_PARAMETER_CAPTURE_STATS_PASS,
3436 +
3437 +       /** @ref MMAL_PARAMETER_UINT32_T */
3438 +       MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
3439 +
3440 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3441 +       MMAL_PARAMETER_ENABLE_REGISTER_FILE,
3442 +
3443 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3444 +       MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
3445 +
3446 +       /** @ref MMAL_PARAMETER_CONFIGFILE_T */
3447 +       MMAL_PARAMETER_CONFIGFILE_REGISTERS,
3448 +
3449 +       /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
3450 +       MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
3451 +       MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3452 +       MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
3453 +       MMAL_PARAMETER_FPS_RANGE, /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
3454 +       MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
3455 +
3456 +       /* 0x40 */
3457 +       MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3458 +       MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3459 +       MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3460 +};
3461 +
3462 +enum mmal_parameter_camera_config_timestamp_mode {
3463 +       MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
3464 +       MMAL_PARAM_TIMESTAMP_MODE_RAW_STC,  /* Use the raw STC value
3465 +                                            * for the frame timestamp
3466 +                                            */
3467 +       MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
3468 +                                             * but subtract the
3469 +                                             * timestamp of the first
3470 +                                             * frame sent to give a
3471 +                                             * zero based timestamp.
3472 +                                             */
3473 +};
3474 +
3475 +/* camera configuration parameter */
3476 +struct mmal_parameter_camera_config {
3477 +       /* Parameters for setting up the image pools */
3478 +       u32 max_stills_w; /* Max size of stills capture */
3479 +       u32 max_stills_h;
3480 +       u32 stills_yuv422; /* Allow YUV422 stills capture */
3481 +       u32 one_shot_stills; /* Continuous or one shot stills captures. */
3482 +
3483 +       u32 max_preview_video_w; /* Max size of the preview or video
3484 +                                 * capture frames
3485 +                                 */
3486 +       u32 max_preview_video_h;
3487 +       u32 num_preview_video_frames;
3488 +
3489 +       /** Sets the height of the circular buffer for stills capture. */
3490 +       u32 stills_capture_circular_buffer_height;
3491 +
3492 +       /** Allows preview/encode to resume as fast as possible after the stills
3493 +        * input frame has been received, and then processes the still frame in
3494 +        * the background whilst preview/encode has resumed.
3495 +        * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
3496 +        */
3497 +       u32 fast_preview_resume;
3498 +
3499 +       /** Selects algorithm for timestamping frames if
3500 +        * there is no clock component connected.
3501 +        * enum mmal_parameter_camera_config_timestamp_mode
3502 +        */
3503 +       s32 use_stc_timestamp;
3504 +};
3505 +
3506 +
3507 +enum mmal_parameter_exposuremode {
3508 +       MMAL_PARAM_EXPOSUREMODE_OFF,
3509 +       MMAL_PARAM_EXPOSUREMODE_AUTO,
3510 +       MMAL_PARAM_EXPOSUREMODE_NIGHT,
3511 +       MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
3512 +       MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
3513 +       MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
3514 +       MMAL_PARAM_EXPOSUREMODE_SPORTS,
3515 +       MMAL_PARAM_EXPOSUREMODE_SNOW,
3516 +       MMAL_PARAM_EXPOSUREMODE_BEACH,
3517 +       MMAL_PARAM_EXPOSUREMODE_VERYLONG,
3518 +       MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
3519 +       MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
3520 +       MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
3521 +};
3522 +
3523 +enum mmal_parameter_exposuremeteringmode {
3524 +       MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
3525 +       MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
3526 +       MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
3527 +       MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
3528 +};
3529 +
3530 +enum mmal_parameter_awbmode {
3531 +       MMAL_PARAM_AWBMODE_OFF,
3532 +       MMAL_PARAM_AWBMODE_AUTO,
3533 +       MMAL_PARAM_AWBMODE_SUNLIGHT,
3534 +       MMAL_PARAM_AWBMODE_CLOUDY,
3535 +       MMAL_PARAM_AWBMODE_SHADE,
3536 +       MMAL_PARAM_AWBMODE_TUNGSTEN,
3537 +       MMAL_PARAM_AWBMODE_FLUORESCENT,
3538 +       MMAL_PARAM_AWBMODE_INCANDESCENT,
3539 +       MMAL_PARAM_AWBMODE_FLASH,
3540 +       MMAL_PARAM_AWBMODE_HORIZON,
3541 +};
3542 +
3543 +enum mmal_parameter_imagefx {
3544 +       MMAL_PARAM_IMAGEFX_NONE,
3545 +       MMAL_PARAM_IMAGEFX_NEGATIVE,
3546 +       MMAL_PARAM_IMAGEFX_SOLARIZE,
3547 +       MMAL_PARAM_IMAGEFX_POSTERIZE,
3548 +       MMAL_PARAM_IMAGEFX_WHITEBOARD,
3549 +       MMAL_PARAM_IMAGEFX_BLACKBOARD,
3550 +       MMAL_PARAM_IMAGEFX_SKETCH,
3551 +       MMAL_PARAM_IMAGEFX_DENOISE,
3552 +       MMAL_PARAM_IMAGEFX_EMBOSS,
3553 +       MMAL_PARAM_IMAGEFX_OILPAINT,
3554 +       MMAL_PARAM_IMAGEFX_HATCH,
3555 +       MMAL_PARAM_IMAGEFX_GPEN,
3556 +       MMAL_PARAM_IMAGEFX_PASTEL,
3557 +       MMAL_PARAM_IMAGEFX_WATERCOLOUR,
3558 +       MMAL_PARAM_IMAGEFX_FILM,
3559 +       MMAL_PARAM_IMAGEFX_BLUR,
3560 +       MMAL_PARAM_IMAGEFX_SATURATION,
3561 +       MMAL_PARAM_IMAGEFX_COLOURSWAP,
3562 +       MMAL_PARAM_IMAGEFX_WASHEDOUT,
3563 +       MMAL_PARAM_IMAGEFX_POSTERISE,
3564 +       MMAL_PARAM_IMAGEFX_COLOURPOINT,
3565 +       MMAL_PARAM_IMAGEFX_COLOURBALANCE,
3566 +       MMAL_PARAM_IMAGEFX_CARTOON,
3567 +};
3568 +
3569 +/** Manner of video rate control */
3570 +enum mmal_parameter_rate_control_mode {
3571 +       MMAL_VIDEO_RATECONTROL_DEFAULT,
3572 +       MMAL_VIDEO_RATECONTROL_VARIABLE,
3573 +       MMAL_VIDEO_RATECONTROL_CONSTANT,
3574 +       MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
3575 +       MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
3576 +};
3577 +
3578 +/* video parameters */
3579 +
3580 +enum mmal_parameter_video_type {
3581 +       /** @ref MMAL_DISPLAYREGION_T */
3582 +       MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
3583 +
3584 +       /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
3585 +       MMAL_PARAMETER_SUPPORTED_PROFILES,
3586 +
3587 +       /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
3588 +       MMAL_PARAMETER_PROFILE,
3589 +
3590 +       /** @ref MMAL_PARAMETER_UINT32_T */
3591 +       MMAL_PARAMETER_INTRAPERIOD,
3592 +
3593 +       /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
3594 +       MMAL_PARAMETER_RATECONTROL,
3595 +
3596 +       /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
3597 +       MMAL_PARAMETER_NALUNITFORMAT,
3598 +
3599 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3600 +       MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
3601 +
3602 +       /** @ref MMAL_PARAMETER_UINT32_T.
3603 +        * Setting the value to zero resets to the default (one slice per frame).
3604 +        */
3605 +       MMAL_PARAMETER_MB_ROWS_PER_SLICE,
3606 +
3607 +       /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
3608 +       MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
3609 +
3610 +       /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
3611 +       MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
3612 +
3613 +       /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
3614 +       MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
3615 +
3616 +       /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
3617 +       MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
3618 +       /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
3619 +       MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
3620 +
3621 +       /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3622 +       MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
3623 +
3624 +       /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
3625 +       MMAL_PARAMETER_VIDEO_BIT_RATE,
3626 +
3627 +       /** @ref MMAL_PARAMETER_FRAME_RATE_T */
3628 +       MMAL_PARAMETER_VIDEO_FRAME_RATE,
3629 +
3630 +       /** @ref MMAL_PARAMETER_UINT32_T. */
3631 +       MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
3632 +
3633 +       /** @ref MMAL_PARAMETER_UINT32_T. */
3634 +       MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
3635 +
3636 +       /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
3637 +       MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
3638 +
3639 +       MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
3640 +       /** @ref MMAL_PARAMETER_UINT32_T.
3641 +        * Changing this parameter from the default can reduce frame rate
3642 +        * because image buffers need to be re-pitched.
3643 +        */
3644 +       MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
3645 +
3646 +       /** @ref MMAL_PARAMETER_UINT32_T.
3647 +        * Changing this parameter from the default can reduce frame rate
3648 +        * because image buffers need to be re-pitched.
3649 +        */
3650 +       MMAL_PARAMETER_VIDEO_ALIGN_VERT,
3651 +
3652 +       /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3653 +       MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
3654 +
3655 +       /** @ref MMAL_PARAMETER_UINT32_T. */
3656 +       MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
3657 +
3658 +       /**< @ref MMAL_PARAMETER_UINT32_T. */
3659 +       MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
3660 +
3661 +       /**< @ref MMAL_PARAMETER_UINT32_T. */
3662 +       MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
3663 +
3664 +       /** @ref MMAL_PARAMETER_UINT32_T */
3665 +       MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
3666 +
3667 +       /** @ref MMAL_PARAMETER_UINT32_T. */
3668 +       MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
3669 +
3670 +       /* H264 specific parameters */
3671 +
3672 +       /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3673 +       MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
3674 +
3675 +       /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3676 +       MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
3677 +
3678 +       /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3679 +       MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
3680 +
3681 +       /** @ref MMAL_PARAMETER_UINT32_T. */
3682 +       MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
3683 +
3684 +       /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
3685 +       MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
3686 +
3687 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3688 +       MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
3689 +
3690 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3691 +       MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
3692 +
3693 +       /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
3694 +       MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
3695 +
3696 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3697 +       MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
3698 +
3699 +       /** @ref MMAL_PARAMETER_BOOLEAN_T */
3700 +       MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
3701 +
3702 +       /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
3703 +       MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
3704 +
3705 +       /** @ref MMAL_PARAMETER_BYTES_T */
3706 +       MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3
3707 +};
3708 +
3709 +/** Valid mirror modes */
3710 +enum mmal_parameter_mirror {
3711 +       MMAL_PARAM_MIRROR_NONE,
3712 +       MMAL_PARAM_MIRROR_VERTICAL,
3713 +       MMAL_PARAM_MIRROR_HORIZONTAL,
3714 +       MMAL_PARAM_MIRROR_BOTH,
3715 +};
3716 +
3717 +enum mmal_parameter_displaytransform {
3718 +       MMAL_DISPLAY_ROT0 = 0,
3719 +       MMAL_DISPLAY_MIRROR_ROT0 = 1,
3720 +       MMAL_DISPLAY_MIRROR_ROT180 = 2,
3721 +       MMAL_DISPLAY_ROT180 = 3,
3722 +       MMAL_DISPLAY_MIRROR_ROT90 = 4,
3723 +       MMAL_DISPLAY_ROT270 = 5,
3724 +       MMAL_DISPLAY_ROT90 = 6,
3725 +       MMAL_DISPLAY_MIRROR_ROT270 = 7,
3726 +};
3727 +
3728 +enum mmal_parameter_displaymode {
3729 +       MMAL_DISPLAY_MODE_FILL = 0,
3730 +       MMAL_DISPLAY_MODE_LETTERBOX = 1,
3731 +};
3732 +
3733 +enum mmal_parameter_displayset {
3734 +       MMAL_DISPLAY_SET_NONE = 0,
3735 +       MMAL_DISPLAY_SET_NUM = 1,
3736 +       MMAL_DISPLAY_SET_FULLSCREEN = 2,
3737 +       MMAL_DISPLAY_SET_TRANSFORM = 4,
3738 +       MMAL_DISPLAY_SET_DEST_RECT = 8,
3739 +       MMAL_DISPLAY_SET_SRC_RECT = 0x10,
3740 +       MMAL_DISPLAY_SET_MODE = 0x20,
3741 +       MMAL_DISPLAY_SET_PIXEL = 0x40,
3742 +       MMAL_DISPLAY_SET_NOASPECT = 0x80,
3743 +       MMAL_DISPLAY_SET_LAYER = 0x100,
3744 +       MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
3745 +       MMAL_DISPLAY_SET_ALPHA = 0x400,
3746 +};
3747 +
3748 +struct mmal_parameter_displayregion {
3749 +       /** Bitfield that indicates which fields are set and should be
3750 +        * used. All other fields will maintain their current value.
3751 +        * \ref MMAL_DISPLAYSET_T defines the bits that can be
3752 +        * combined.
3753 +        */
3754 +       u32 set;
3755 +
3756 +       /** Describes the display output device, with 0 typically
3757 +        * being a directly connected LCD display.  The actual values
3758 +        * will depend on the hardware.  Code using hard-wired numbers
3759 +        * (e.g. 2) is certain to fail.
3760 +        */
3761 +
3762 +       u32 display_num;
3763 +       /** Indicates that we are using the full device screen area,
3764 +        * rather than a window of the display.  If zero, then
3765 +        * dest_rect is used to specify a region of the display to
3766 +        * use.
3767 +        */
3768 +
3769 +       s32 fullscreen;
3770 +       /** Indicates any rotation or flipping used to map frames onto
3771 +        * the natural display orientation.
3772 +        */
3773 +       u32 transform; /* enum mmal_parameter_displaytransform */
3774 +
3775 +       /** Where to display the frame within the screen, if
3776 +        * fullscreen is zero.
3777 +        */
3778 +       struct vchiq_mmal_rect dest_rect;
3779 +
3780 +       /** Indicates which area of the frame to display. If all
3781 +        * values are zero, the whole frame will be used.
3782 +        */
3783 +       struct vchiq_mmal_rect src_rect;
3784 +
3785 +       /** If set to non-zero, indicates that any display scaling
3786 +        * should disregard the aspect ratio of the frame region being
3787 +        * displayed.
3788 +        */
3789 +       s32 noaspect;
3790 +
3791 +       /** Indicates how the image should be scaled to fit the
3792 +        * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
3793 +        * that the image should fill the screen by potentially
3794 +        * cropping the frames.  Setting \code mode \endcode to \code
3795 +        * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
3796 +        * source region should be displayed and black bars added if
3797 +        * necessary.
3798 +        */
3799 +       u32 mode; /* enum mmal_parameter_displaymode */
3800 +
3801 +       /** If non-zero, defines the width of a source pixel relative
3802 +        * to \code pixel_y \endcode.  If zero, then pixels default to
3803 +        * being square.
3804 +        */
3805 +       u32 pixel_x;
3806 +
3807 +       /** If non-zero, defines the height of a source pixel relative
3808 +        * to \code pixel_x \endcode.  If zero, then pixels default to
3809 +        * being square.
3810 +        */
3811 +       u32 pixel_y;
3812 +
3813 +       /** Sets the relative depth of the images, with greater values
3814 +        * being in front of smaller values.
3815 +        */
3816 +       u32 layer;
3817 +
3818 +       /** Set to non-zero to ensure copy protection is used on
3819 +        * output.
3820 +        */
3821 +       s32 copyprotect_required;
3822 +
3823 +       /** Level of opacity of the layer, where zero is fully
3824 +        * transparent and 255 is fully opaque.
3825 +        */
3826 +       u32 alpha;
3827 +};
3828 +
3829 +#define MMAL_MAX_IMAGEFX_PARAMETERS 5
3830 +
3831 +struct mmal_parameter_imagefx_parameters {
3832 +       enum mmal_parameter_imagefx effect;
3833 +       u32 num_effect_params;
3834 +       u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
3835 +};
3836 --- /dev/null
3837 +++ b/drivers/media/platform/bcm2835/mmal-vchiq.c
3838 @@ -0,0 +1,1916 @@
3839 +/*
3840 + * Broadcom BM2835 V4L2 driver
3841 + *
3842 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
3843 + *
3844 + * This file is subject to the terms and conditions of the GNU General Public
3845 + * License.  See the file COPYING in the main directory of this archive
3846 + * for more details.
3847 + *
3848 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
3849 + *          Dave Stevenson <dsteve@broadcom.com>
3850 + *          Simon Mellor <simellor@broadcom.com>
3851 + *          Luke Diamand <luked@broadcom.com>
3852 + *
3853 + * V4L2 driver MMAL vchiq interface code
3854 + */
3855 +
3856 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3857 +
3858 +#include <linux/errno.h>
3859 +#include <linux/kernel.h>
3860 +#include <linux/mutex.h>
3861 +#include <linux/mm.h>
3862 +#include <linux/slab.h>
3863 +#include <linux/completion.h>
3864 +#include <linux/vmalloc.h>
3865 +#include <asm/cacheflush.h>
3866 +#include <media/videobuf2-vmalloc.h>
3867 +
3868 +#include "mmal-common.h"
3869 +#include "mmal-vchiq.h"
3870 +#include "mmal-msg.h"
3871 +
3872 +#define USE_VCHIQ_ARM
3873 +#include "interface/vchi/vchi.h"
3874 +
3875 +/* maximum number of components supported */
3876 +#define VCHIQ_MMAL_MAX_COMPONENTS 4
3877 +
3878 +/*#define FULL_MSG_DUMP 1*/
3879 +
3880 +#ifdef DEBUG
3881 +static const char *const msg_type_names[] = {
3882 +       "UNKNOWN",
3883 +       "QUIT",
3884 +       "SERVICE_CLOSED",
3885 +       "GET_VERSION",
3886 +       "COMPONENT_CREATE",
3887 +       "COMPONENT_DESTROY",
3888 +       "COMPONENT_ENABLE",
3889 +       "COMPONENT_DISABLE",
3890 +       "PORT_INFO_GET",
3891 +       "PORT_INFO_SET",
3892 +       "PORT_ACTION",
3893 +       "BUFFER_FROM_HOST",
3894 +       "BUFFER_TO_HOST",
3895 +       "GET_STATS",
3896 +       "PORT_PARAMETER_SET",
3897 +       "PORT_PARAMETER_GET",
3898 +       "EVENT_TO_HOST",
3899 +       "GET_CORE_STATS_FOR_PORT",
3900 +       "OPAQUE_ALLOCATOR",
3901 +       "CONSUME_MEM",
3902 +       "LMK",
3903 +       "OPAQUE_ALLOCATOR_DESC",
3904 +       "DRM_GET_LHS32",
3905 +       "DRM_GET_TIME",
3906 +       "BUFFER_FROM_HOST_ZEROLEN",
3907 +       "PORT_FLUSH",
3908 +       "HOST_LOG",
3909 +};
3910 +#endif
3911 +
3912 +static const char *const port_action_type_names[] = {
3913 +       "UNKNOWN",
3914 +       "ENABLE",
3915 +       "DISABLE",
3916 +       "FLUSH",
3917 +       "CONNECT",
3918 +       "DISCONNECT",
3919 +       "SET_REQUIREMENTS",
3920 +};
3921 +
3922 +#if defined(DEBUG)
3923 +#if defined(FULL_MSG_DUMP)
3924 +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                              \
3925 +       do {                                                            \
3926 +               pr_debug(TITLE" type:%s(%d) length:%d\n",               \
3927 +                        msg_type_names[(MSG)->h.type],                 \
3928 +                        (MSG)->h.type, (MSG_LEN));                     \
3929 +               print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
3930 +                              16, 4, (MSG),                            \
3931 +                              sizeof(struct mmal_msg_header), 1);      \
3932 +               print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
3933 +                              16, 4,                                   \
3934 +                              ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
3935 +                              (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
3936 +       } while (0)
3937 +#else
3938 +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)                              \
3939 +       {                                                               \
3940 +               pr_debug(TITLE" type:%s(%d) length:%d\n",               \
3941 +                        msg_type_names[(MSG)->h.type],                 \
3942 +                        (MSG)->h.type, (MSG_LEN));                     \
3943 +       }
3944 +#endif
3945 +#else
3946 +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
3947 +#endif
3948 +
3949 +/* normal message context */
3950 +struct mmal_msg_context {
3951 +       union {
3952 +               struct {
3953 +                       /* work struct for defered callback - must come first */
3954 +                       struct work_struct work;
3955 +                       /* mmal instance */
3956 +                       struct vchiq_mmal_instance *instance;
3957 +                       /* mmal port */
3958 +                       struct vchiq_mmal_port *port;
3959 +                       /* actual buffer used to store bulk reply */
3960 +                       struct mmal_buffer *buffer;
3961 +                       /* amount of buffer used */
3962 +                       unsigned long buffer_used;
3963 +                       /* MMAL buffer flags */
3964 +                       u32 mmal_flags;
3965 +                       /* Presentation and Decode timestamps */
3966 +                       s64 pts;
3967 +                       s64 dts;
3968 +
3969 +                       int status;     /* context status */
3970 +
3971 +               } bulk;         /* bulk data */
3972 +
3973 +               struct {
3974 +                       /* message handle to release */
3975 +                       VCHI_HELD_MSG_T msg_handle;
3976 +                       /* pointer to received message */
3977 +                       struct mmal_msg *msg;
3978 +                       /* received message length */
3979 +                       u32 msg_len;
3980 +                       /* completion upon reply */
3981 +                       struct completion cmplt;
3982 +               } sync;         /* synchronous response */
3983 +       } u;
3984 +
3985 +};
3986 +
3987 +struct vchiq_mmal_instance {
3988 +       VCHI_SERVICE_HANDLE_T handle;
3989 +
3990 +       /* ensure serialised access to service */
3991 +       struct mutex vchiq_mutex;
3992 +
3993 +       /* ensure serialised access to bulk operations */
3994 +       struct mutex bulk_mutex;
3995 +
3996 +       /* vmalloc page to receive scratch bulk xfers into */
3997 +       void *bulk_scratch;
3998 +
3999 +       /* component to use next */
4000 +       int component_idx;
4001 +       struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
4002 +};
4003 +
4004 +static struct mmal_msg_context *get_msg_context(struct vchiq_mmal_instance
4005 +                                               *instance)
4006 +{
4007 +       struct mmal_msg_context *msg_context;
4008 +
4009 +       /* todo: should this be allocated from a pool to avoid kmalloc */
4010 +       msg_context = kmalloc(sizeof(*msg_context), GFP_KERNEL);
4011 +       memset(msg_context, 0, sizeof(*msg_context));
4012 +
4013 +       return msg_context;
4014 +}
4015 +
4016 +static void release_msg_context(struct mmal_msg_context *msg_context)
4017 +{
4018 +       kfree(msg_context);
4019 +}
4020 +
4021 +/* deals with receipt of event to host message */
4022 +static void event_to_host_cb(struct vchiq_mmal_instance *instance,
4023 +                            struct mmal_msg *msg, u32 msg_len)
4024 +{
4025 +       pr_debug("unhandled event\n");
4026 +       pr_debug("component:%p port type:%d num:%d cmd:0x%x length:%d\n",
4027 +                msg->u.event_to_host.client_component,
4028 +                msg->u.event_to_host.port_type,
4029 +                msg->u.event_to_host.port_num,
4030 +                msg->u.event_to_host.cmd, msg->u.event_to_host.length);
4031 +}
4032 +
4033 +/* workqueue scheduled callback
4034 + *
4035 + * we do this because it is important we do not call any other vchiq
4036 + * sync calls from witin the message delivery thread
4037 + */
4038 +static void buffer_work_cb(struct work_struct *work)
4039 +{
4040 +       struct mmal_msg_context *msg_context = (struct mmal_msg_context *)work;
4041 +
4042 +       msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
4043 +                                           msg_context->u.bulk.port,
4044 +                                           msg_context->u.bulk.status,
4045 +                                           msg_context->u.bulk.buffer,
4046 +                                           msg_context->u.bulk.buffer_used,
4047 +                                           msg_context->u.bulk.mmal_flags,
4048 +                                           msg_context->u.bulk.dts,
4049 +                                           msg_context->u.bulk.pts);
4050 +
4051 +       /* release message context */
4052 +       release_msg_context(msg_context);
4053 +}
4054 +
4055 +/* enqueue a bulk receive for a given message context */
4056 +static int bulk_receive(struct vchiq_mmal_instance *instance,
4057 +                       struct mmal_msg *msg,
4058 +                       struct mmal_msg_context *msg_context)
4059 +{
4060 +       unsigned long rd_len;
4061 +       unsigned long flags = 0;
4062 +       int ret;
4063 +
4064 +       /* bulk mutex stops other bulk operations while we have a
4065 +        * receive in progress - released in callback
4066 +        */
4067 +       ret = mutex_lock_interruptible(&instance->bulk_mutex);
4068 +       if (ret != 0)
4069 +               return ret;
4070 +
4071 +       rd_len = msg->u.buffer_from_host.buffer_header.length;
4072 +
4073 +       /* take buffer from queue */
4074 +       spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags);
4075 +       if (list_empty(&msg_context->u.bulk.port->buffers)) {
4076 +               spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
4077 +               pr_err("buffer list empty trying to submit bulk receive\n");
4078 +
4079 +               /* todo: this is a serious error, we should never have
4080 +                * commited a buffer_to_host operation to the mmal
4081 +                * port without the buffer to back it up (underflow
4082 +                * handling) and there is no obvious way to deal with
4083 +                * this - how is the mmal servie going to react when
4084 +                * we fail to do the xfer and reschedule a buffer when
4085 +                * it arrives? perhaps a starved flag to indicate a
4086 +                * waiting bulk receive?
4087 +                */
4088 +
4089 +               mutex_unlock(&instance->bulk_mutex);
4090 +
4091 +               return -EINVAL;
4092 +       }
4093 +
4094 +       msg_context->u.bulk.buffer =
4095 +           list_entry(msg_context->u.bulk.port->buffers.next,
4096 +                      struct mmal_buffer, list);
4097 +       list_del(&msg_context->u.bulk.buffer->list);
4098 +
4099 +       spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
4100 +
4101 +       /* ensure we do not overrun the available buffer */
4102 +       if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
4103 +               rd_len = msg_context->u.bulk.buffer->buffer_size;
4104 +               pr_warn("short read as not enough receive buffer space\n");
4105 +               /* todo: is this the correct response, what happens to
4106 +                * the rest of the message data?
4107 +                */
4108 +       }
4109 +
4110 +       /* store length */
4111 +       msg_context->u.bulk.buffer_used = rd_len;
4112 +       msg_context->u.bulk.mmal_flags =
4113 +           msg->u.buffer_from_host.buffer_header.flags;
4114 +       msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
4115 +       msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
4116 +
4117 +       // only need to flush L1 cache here, as VCHIQ takes care of the L2
4118 +       // cache.
4119 +       __cpuc_flush_dcache_area(msg_context->u.bulk.buffer->buffer, rd_len);
4120 +
4121 +       /* queue the bulk submission */
4122 +       vchi_service_use(instance->handle);
4123 +       ret = vchi_bulk_queue_receive(instance->handle,
4124 +                                     msg_context->u.bulk.buffer->buffer,
4125 +                                     /* Actual receive needs to be a multiple
4126 +                                      * of 4 bytes
4127 +                                      */
4128 +                                     (rd_len + 3) & ~3,
4129 +                                     VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
4130 +                                     VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
4131 +                                     msg_context);
4132 +
4133 +       vchi_service_release(instance->handle);
4134 +
4135 +       if (ret != 0) {
4136 +               /* callback will not be clearing the mutex */
4137 +               mutex_unlock(&instance->bulk_mutex);
4138 +       }
4139 +
4140 +       return ret;
4141 +}
4142 +
4143 +/* enque a dummy bulk receive for a given message context */
4144 +static int dummy_bulk_receive(struct vchiq_mmal_instance *instance,
4145 +                             struct mmal_msg_context *msg_context)
4146 +{
4147 +       int ret;
4148 +
4149 +       /* bulk mutex stops other bulk operations while we have a
4150 +        * receive in progress - released in callback
4151 +        */
4152 +       ret = mutex_lock_interruptible(&instance->bulk_mutex);
4153 +       if (ret != 0)
4154 +               return ret;
4155 +
4156 +       /* zero length indicates this was a dummy transfer */
4157 +       msg_context->u.bulk.buffer_used = 0;
4158 +
4159 +       /* queue the bulk submission */
4160 +       vchi_service_use(instance->handle);
4161 +
4162 +       ret = vchi_bulk_queue_receive(instance->handle,
4163 +                                     instance->bulk_scratch,
4164 +                                     8,
4165 +                                     VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
4166 +                                     VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
4167 +                                     msg_context);
4168 +
4169 +       vchi_service_release(instance->handle);
4170 +
4171 +       if (ret != 0) {
4172 +               /* callback will not be clearing the mutex */
4173 +               mutex_unlock(&instance->bulk_mutex);
4174 +       }
4175 +
4176 +       return ret;
4177 +}
4178 +
4179 +/* data in message, memcpy from packet into output buffer */
4180 +static int inline_receive(struct vchiq_mmal_instance *instance,
4181 +                         struct mmal_msg *msg,
4182 +                         struct mmal_msg_context *msg_context)
4183 +{
4184 +       unsigned long flags = 0;
4185 +
4186 +       /* take buffer from queue */
4187 +       spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags);
4188 +       if (list_empty(&msg_context->u.bulk.port->buffers)) {
4189 +               spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
4190 +               pr_err("buffer list empty trying to receive inline\n");
4191 +
4192 +               /* todo: this is a serious error, we should never have
4193 +                * commited a buffer_to_host operation to the mmal
4194 +                * port without the buffer to back it up (with
4195 +                * underflow handling) and there is no obvious way to
4196 +                * deal with this. Less bad than the bulk case as we
4197 +                * can just drop this on the floor but...unhelpful
4198 +                */
4199 +               return -EINVAL;
4200 +       }
4201 +
4202 +       msg_context->u.bulk.buffer =
4203 +           list_entry(msg_context->u.bulk.port->buffers.next,
4204 +                      struct mmal_buffer, list);
4205 +       list_del(&msg_context->u.bulk.buffer->list);
4206 +
4207 +       spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
4208 +
4209 +       memcpy(msg_context->u.bulk.buffer->buffer,
4210 +              msg->u.buffer_from_host.short_data,
4211 +              msg->u.buffer_from_host.payload_in_message);
4212 +
4213 +       msg_context->u.bulk.buffer_used =
4214 +           msg->u.buffer_from_host.payload_in_message;
4215 +
4216 +       return 0;
4217 +}
4218 +
4219 +/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
4220 +static int
4221 +buffer_from_host(struct vchiq_mmal_instance *instance,
4222 +                struct vchiq_mmal_port *port, struct mmal_buffer *buf)
4223 +{
4224 +       struct mmal_msg_context *msg_context;
4225 +       struct mmal_msg m;
4226 +       int ret;
4227 +
4228 +       pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
4229 +
4230 +       /* bulk mutex stops other bulk operations while we
4231 +        * have a receive in progress
4232 +        */
4233 +       if (mutex_lock_interruptible(&instance->bulk_mutex))
4234 +               return -EINTR;
4235 +
4236 +       /* get context */
4237 +       msg_context = get_msg_context(instance);
4238 +       if (msg_context == NULL)
4239 +               return -ENOMEM;
4240 +
4241 +       /* store bulk message context for when data arrives */
4242 +       msg_context->u.bulk.instance = instance;
4243 +       msg_context->u.bulk.port = port;
4244 +       msg_context->u.bulk.buffer = NULL;      /* not valid until bulk xfer */
4245 +       msg_context->u.bulk.buffer_used = 0;
4246 +
4247 +       /* initialise work structure ready to schedule callback */
4248 +       INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
4249 +
4250 +       /* prep the buffer from host message */
4251 +       memset(&m, 0xbc, sizeof(m));    /* just to make debug clearer */
4252 +
4253 +       m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
4254 +       m.h.magic = MMAL_MAGIC;
4255 +       m.h.context = msg_context;
4256 +       m.h.status = 0;
4257 +
4258 +       /* drvbuf is our private data passed back */
4259 +       m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
4260 +       m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
4261 +       m.u.buffer_from_host.drvbuf.port_handle = port->handle;
4262 +       m.u.buffer_from_host.drvbuf.client_context = msg_context;
4263 +
4264 +       /* buffer header */
4265 +       m.u.buffer_from_host.buffer_header.cmd = 0;
4266 +       m.u.buffer_from_host.buffer_header.data = buf->buffer;
4267 +       m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
4268 +       m.u.buffer_from_host.buffer_header.length = 0;  /* nothing used yet */
4269 +       m.u.buffer_from_host.buffer_header.offset = 0;  /* no offset */
4270 +       m.u.buffer_from_host.buffer_header.flags = 0;   /* no flags */
4271 +       m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
4272 +       m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
4273 +
4274 +       /* clear buffer type sepecific data */
4275 +       memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
4276 +              sizeof(m.u.buffer_from_host.buffer_header_type_specific));
4277 +
4278 +       /* no payload in message */
4279 +       m.u.buffer_from_host.payload_in_message = 0;
4280 +
4281 +       vchi_service_use(instance->handle);
4282 +
4283 +       ret = vchi_msg_queue(instance->handle, &m,
4284 +                            sizeof(struct mmal_msg_header) +
4285 +                            sizeof(m.u.buffer_from_host),
4286 +                            VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
4287 +
4288 +       if (ret != 0) {
4289 +               release_msg_context(msg_context);
4290 +               /* todo: is this correct error value? */
4291 +       }
4292 +
4293 +       vchi_service_release(instance->handle);
4294 +
4295 +       mutex_unlock(&instance->bulk_mutex);
4296 +
4297 +       return ret;
4298 +}
4299 +
4300 +/* submit a buffer to the mmal sevice
4301 + *
4302 + * the buffer_from_host uses size data from the ports next available
4303 + * mmal_buffer and deals with there being no buffer available by
4304 + * incrementing the underflow for later
4305 + */
4306 +static int port_buffer_from_host(struct vchiq_mmal_instance *instance,
4307 +                                struct vchiq_mmal_port *port)
4308 +{
4309 +       int ret;
4310 +       struct mmal_buffer *buf;
4311 +       unsigned long flags = 0;
4312 +
4313 +       if (!port->enabled)
4314 +               return -EINVAL;
4315 +
4316 +       /* peek buffer from queue */
4317 +       spin_lock_irqsave(&port->slock, flags);
4318 +       if (list_empty(&port->buffers)) {
4319 +               port->buffer_underflow++;
4320 +               spin_unlock_irqrestore(&port->slock, flags);
4321 +               return -ENOSPC;
4322 +       }
4323 +
4324 +       buf = list_entry(port->buffers.next, struct mmal_buffer, list);
4325 +
4326 +       spin_unlock_irqrestore(&port->slock, flags);
4327 +
4328 +       /* issue buffer to mmal service */
4329 +       ret = buffer_from_host(instance, port, buf);
4330 +       if (ret) {
4331 +               pr_err("adding buffer header failed\n");
4332 +               /* todo: how should this be dealt with */
4333 +       }
4334 +
4335 +       return ret;
4336 +}
4337 +
4338 +/* deals with receipt of buffer to host message */
4339 +static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
4340 +                             struct mmal_msg *msg, u32 msg_len)
4341 +{
4342 +       struct mmal_msg_context *msg_context;
4343 +
4344 +       pr_debug("buffer_to_host_cb: instance:%p msg:%p msg_len:%d\n",
4345 +                instance, msg, msg_len);
4346 +
4347 +       if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
4348 +               msg_context = msg->u.buffer_from_host.drvbuf.client_context;
4349 +       } else {
4350 +               pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
4351 +               return;
4352 +       }
4353 +
4354 +       if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
4355 +               /* message reception had an error */
4356 +               pr_warn("error %d in reply\n", msg->h.status);
4357 +
4358 +               msg_context->u.bulk.status = msg->h.status;
4359 +
4360 +       } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
4361 +               /* empty buffer */
4362 +               if (msg->u.buffer_from_host.buffer_header.flags &
4363 +                   MMAL_BUFFER_HEADER_FLAG_EOS) {
4364 +                       msg_context->u.bulk.status =
4365 +                           dummy_bulk_receive(instance, msg_context);
4366 +                       if (msg_context->u.bulk.status == 0)
4367 +                               return; /* successful bulk submission, bulk
4368 +                                        * completion will trigger callback
4369 +                                        */
4370 +               } else {
4371 +                       /* do callback with empty buffer - not EOS though */
4372 +                       msg_context->u.bulk.status = 0;
4373 +                       msg_context->u.bulk.buffer_used = 0;
4374 +               }
4375 +       } else if (msg->u.buffer_from_host.payload_in_message == 0) {
4376 +               /* data is not in message, queue a bulk receive */
4377 +               msg_context->u.bulk.status =
4378 +                   bulk_receive(instance, msg, msg_context);
4379 +               if (msg_context->u.bulk.status == 0)
4380 +                       return; /* successful bulk submission, bulk
4381 +                                * completion will trigger callback
4382 +                                */
4383 +
4384 +               /* failed to submit buffer, this will end badly */
4385 +               pr_err("error %d on bulk submission\n",
4386 +                      msg_context->u.bulk.status);
4387 +
4388 +       } else if (msg->u.buffer_from_host.payload_in_message <=
4389 +                  MMAL_VC_SHORT_DATA) {
4390 +               /* data payload within message */
4391 +               msg_context->u.bulk.status = inline_receive(instance, msg,
4392 +                                                           msg_context);
4393 +       } else {
4394 +               pr_err("message with invalid short payload\n");
4395 +
4396 +               /* signal error */
4397 +               msg_context->u.bulk.status = -EINVAL;
4398 +               msg_context->u.bulk.buffer_used =
4399 +                   msg->u.buffer_from_host.payload_in_message;
4400 +       }
4401 +
4402 +       /* replace the buffer header */
4403 +       port_buffer_from_host(instance, msg_context->u.bulk.port);
4404 +
4405 +       /* schedule the port callback */
4406 +       schedule_work(&msg_context->u.bulk.work);
4407 +}
4408 +
4409 +static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
4410 +                           struct mmal_msg_context *msg_context)
4411 +{
4412 +       /* bulk receive operation complete */
4413 +       mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex);
4414 +
4415 +       /* replace the buffer header */
4416 +       port_buffer_from_host(msg_context->u.bulk.instance,
4417 +                             msg_context->u.bulk.port);
4418 +
4419 +       msg_context->u.bulk.status = 0;
4420 +
4421 +       /* schedule the port callback */
4422 +       schedule_work(&msg_context->u.bulk.work);
4423 +}
4424 +
4425 +static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
4426 +                         struct mmal_msg_context *msg_context)
4427 +{
4428 +       pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
4429 +
4430 +       /* bulk receive operation complete */
4431 +       mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex);
4432 +
4433 +       /* replace the buffer header */
4434 +       port_buffer_from_host(msg_context->u.bulk.instance,
4435 +                             msg_context->u.bulk.port);
4436 +
4437 +       msg_context->u.bulk.status = -EINTR;
4438 +
4439 +       schedule_work(&msg_context->u.bulk.work);
4440 +}
4441 +
4442 +/* incoming event service callback */
4443 +static void service_callback(void *param,
4444 +                            const VCHI_CALLBACK_REASON_T reason,
4445 +                            void *bulk_ctx)
4446 +{
4447 +       struct vchiq_mmal_instance *instance = param;
4448 +       int status;
4449 +       u32 msg_len;
4450 +       struct mmal_msg *msg;
4451 +       VCHI_HELD_MSG_T msg_handle;
4452 +
4453 +       if (!instance) {
4454 +               pr_err("Message callback passed NULL instance\n");
4455 +               return;
4456 +       }
4457 +
4458 +       switch (reason) {
4459 +       case VCHI_CALLBACK_MSG_AVAILABLE:
4460 +               status = vchi_msg_hold(instance->handle, (void **)&msg,
4461 +                                      &msg_len, VCHI_FLAGS_NONE, &msg_handle);
4462 +               if (status) {
4463 +                       pr_err("Unable to dequeue a message (%d)\n", status);
4464 +                       break;
4465 +               }
4466 +
4467 +               DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
4468 +
4469 +               /* handling is different for buffer messages */
4470 +               switch (msg->h.type) {
4471 +
4472 +               case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
4473 +                       vchi_held_msg_release(&msg_handle);
4474 +                       break;
4475 +
4476 +               case MMAL_MSG_TYPE_EVENT_TO_HOST:
4477 +                       event_to_host_cb(instance, msg, msg_len);
4478 +                       vchi_held_msg_release(&msg_handle);
4479 +
4480 +                       break;
4481 +
4482 +               case MMAL_MSG_TYPE_BUFFER_TO_HOST:
4483 +                       buffer_to_host_cb(instance, msg, msg_len);
4484 +                       vchi_held_msg_release(&msg_handle);
4485 +                       break;
4486 +
4487 +               default:
4488 +                       /* messages dependant on header context to complete */
4489 +
4490 +                       /* todo: the msg.context really ought to be sanity
4491 +                        * checked before we just use it, afaict it comes back
4492 +                        * and is used raw from the videocore. Perhaps it
4493 +                        * should be verified the address lies in the kernel
4494 +                        * address space.
4495 +                        */
4496 +                       if (msg->h.context == NULL) {
4497 +                               pr_err("received message context was null!\n");
4498 +                               vchi_held_msg_release(&msg_handle);
4499 +                               break;
4500 +                       }
4501 +
4502 +                       /* fill in context values */
4503 +                       msg->h.context->u.sync.msg_handle = msg_handle;
4504 +                       msg->h.context->u.sync.msg = msg;
4505 +                       msg->h.context->u.sync.msg_len = msg_len;
4506 +
4507 +                       /* todo: should this check (completion_done()
4508 +                        * == 1) for no one waiting? or do we need a
4509 +                        * flag to tell us the completion has been
4510 +                        * interrupted so we can free the message and
4511 +                        * its context. This probably also solves the
4512 +                        * message arriving after interruption todo
4513 +                        * below
4514 +                        */
4515 +
4516 +                       /* complete message so caller knows it happened */
4517 +                       complete(&msg->h.context->u.sync.cmplt);
4518 +                       break;
4519 +               }
4520 +
4521 +               break;
4522 +
4523 +       case VCHI_CALLBACK_BULK_RECEIVED:
4524 +               bulk_receive_cb(instance, bulk_ctx);
4525 +               break;
4526 +
4527 +       case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
4528 +               bulk_abort_cb(instance, bulk_ctx);
4529 +               break;
4530 +
4531 +       case VCHI_CALLBACK_SERVICE_CLOSED:
4532 +               /* TODO: consider if this requires action if received when
4533 +                * driver is not explicitly closing the service
4534 +                */
4535 +               break;
4536 +
4537 +       default:
4538 +               pr_err("Received unhandled message reason %d\n", reason);
4539 +               break;
4540 +       }
4541 +}
4542 +
4543 +static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
4544 +                                    struct mmal_msg *msg,
4545 +                                    unsigned int payload_len,
4546 +                                    struct mmal_msg **msg_out,
4547 +                                    VCHI_HELD_MSG_T *msg_handle_out)
4548 +{
4549 +       struct mmal_msg_context msg_context;
4550 +       int ret;
4551 +
4552 +       /* payload size must not cause message to exceed max size */
4553 +       if (payload_len >
4554 +           (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
4555 +               pr_err("payload length %d exceeds max:%d\n", payload_len,
4556 +                        (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header)));
4557 +               return -EINVAL;
4558 +       }
4559 +
4560 +       init_completion(&msg_context.u.sync.cmplt);
4561 +
4562 +       msg->h.magic = MMAL_MAGIC;
4563 +       msg->h.context = &msg_context;
4564 +       msg->h.status = 0;
4565 +
4566 +       DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
4567 +                    ">>> sync message");
4568 +
4569 +       vchi_service_use(instance->handle);
4570 +
4571 +       ret = vchi_msg_queue(instance->handle,
4572 +                            msg,
4573 +                            sizeof(struct mmal_msg_header) + payload_len,
4574 +                            VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
4575 +
4576 +       vchi_service_release(instance->handle);
4577 +
4578 +       if (ret) {
4579 +               pr_err("error %d queuing message\n", ret);
4580 +               return ret;
4581 +       }
4582 +
4583 +       ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, HZ);
4584 +       if (ret <= 0) {
4585 +               pr_err("error %d waiting for sync completion\n", ret);
4586 +               if (ret == 0)
4587 +                       ret = -ETIME;
4588 +               /* todo: what happens if the message arrives after aborting */
4589 +               return ret;
4590 +       }
4591 +
4592 +       *msg_out = msg_context.u.sync.msg;
4593 +       *msg_handle_out = msg_context.u.sync.msg_handle;
4594 +
4595 +       return 0;
4596 +}
4597 +
4598 +static void dump_port_info(struct vchiq_mmal_port *port)
4599 +{
4600 +       pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
4601 +
4602 +       pr_debug("buffer minimum num:%d size:%d align:%d\n",
4603 +                port->minimum_buffer.num,
4604 +                port->minimum_buffer.size, port->minimum_buffer.alignment);
4605 +
4606 +       pr_debug("buffer recommended num:%d size:%d align:%d\n",
4607 +                port->recommended_buffer.num,
4608 +                port->recommended_buffer.size,
4609 +                port->recommended_buffer.alignment);
4610 +
4611 +       pr_debug("buffer current values num:%d size:%d align:%d\n",
4612 +                port->current_buffer.num,
4613 +                port->current_buffer.size, port->current_buffer.alignment);
4614 +
4615 +       pr_debug("elementry stream: type:%d encoding:0x%x varient:0x%x\n",
4616 +                port->format.type,
4617 +                port->format.encoding, port->format.encoding_variant);
4618 +
4619 +       pr_debug("                  bitrate:%d flags:0x%x\n",
4620 +                port->format.bitrate, port->format.flags);
4621 +
4622 +       if (port->format.type == MMAL_ES_TYPE_VIDEO) {
4623 +               pr_debug
4624 +                   ("es video format: width:%d height:%d colourspace:0x%x\n",
4625 +                    port->es.video.width, port->es.video.height,
4626 +                    port->es.video.color_space);
4627 +
4628 +               pr_debug("               : crop xywh %d,%d,%d,%d\n",
4629 +                        port->es.video.crop.x,
4630 +                        port->es.video.crop.y,
4631 +                        port->es.video.crop.width, port->es.video.crop.height);
4632 +               pr_debug("               : framerate %d/%d  aspect %d/%d\n",
4633 +                        port->es.video.frame_rate.num,
4634 +                        port->es.video.frame_rate.den,
4635 +                        port->es.video.par.num, port->es.video.par.den);
4636 +       }
4637 +}
4638 +
4639 +static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
4640 +{
4641 +
4642 +       /* todo do readonly fields need setting at all? */
4643 +       p->type = port->type;
4644 +       p->index = port->index;
4645 +       p->index_all = 0;
4646 +       p->is_enabled = port->enabled;
4647 +       p->buffer_num_min = port->minimum_buffer.num;
4648 +       p->buffer_size_min = port->minimum_buffer.size;
4649 +       p->buffer_alignment_min = port->minimum_buffer.alignment;
4650 +       p->buffer_num_recommended = port->recommended_buffer.num;
4651 +       p->buffer_size_recommended = port->recommended_buffer.size;
4652 +
4653 +       /* only three writable fields in a port */
4654 +       p->buffer_num = port->current_buffer.num;
4655 +       p->buffer_size = port->current_buffer.size;
4656 +       p->userdata = port;
4657 +}
4658 +
4659 +static int port_info_set(struct vchiq_mmal_instance *instance,
4660 +                        struct vchiq_mmal_port *port)
4661 +{
4662 +       int ret;
4663 +       struct mmal_msg m;
4664 +       struct mmal_msg *rmsg;
4665 +       VCHI_HELD_MSG_T rmsg_handle;
4666 +
4667 +       pr_debug("setting port info port %p\n", port);
4668 +       if (!port)
4669 +               return -1;
4670 +       dump_port_info(port);
4671 +
4672 +       m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
4673 +
4674 +       m.u.port_info_set.component_handle = port->component->handle;
4675 +       m.u.port_info_set.port_type = port->type;
4676 +       m.u.port_info_set.port_index = port->index;
4677 +
4678 +       port_to_mmal_msg(port, &m.u.port_info_set.port);
4679 +
4680 +       /* elementry stream format setup */
4681 +       m.u.port_info_set.format.type = port->format.type;
4682 +       m.u.port_info_set.format.encoding = port->format.encoding;
4683 +       m.u.port_info_set.format.encoding_variant =
4684 +           port->format.encoding_variant;
4685 +       m.u.port_info_set.format.bitrate = port->format.bitrate;
4686 +       m.u.port_info_set.format.flags = port->format.flags;
4687 +
4688 +       memcpy(&m.u.port_info_set.es, &port->es,
4689 +              sizeof(union mmal_es_specific_format));
4690 +
4691 +       m.u.port_info_set.format.extradata_size = port->format.extradata_size;
4692 +       memcpy(rmsg->u.port_info_set.extradata, port->format.extradata,
4693 +              port->format.extradata_size);
4694 +
4695 +       ret = send_synchronous_mmal_msg(instance, &m,
4696 +                                       sizeof(m.u.port_info_set),
4697 +                                       &rmsg, &rmsg_handle);
4698 +       if (ret)
4699 +               return ret;
4700 +
4701 +       if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
4702 +               /* got an unexpected message type in reply */
4703 +               ret = -EINVAL;
4704 +               goto release_msg;
4705 +       }
4706 +
4707 +       /* return operation status */
4708 +       ret = -rmsg->u.port_info_get_reply.status;
4709 +
4710 +       pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
4711 +                port->component->handle, port->handle);
4712 +
4713 +release_msg:
4714 +       vchi_held_msg_release(&rmsg_handle);
4715 +
4716 +       return ret;
4717 +
4718 +}
4719 +
4720 +/* use port info get message to retrive port information */
4721 +static int port_info_get(struct vchiq_mmal_instance *instance,
4722 +                        struct vchiq_mmal_port *port)
4723 +{
4724 +       int ret;
4725 +       struct mmal_msg m;
4726 +       struct mmal_msg *rmsg;
4727 +       VCHI_HELD_MSG_T rmsg_handle;
4728 +
4729 +       /* port info time */
4730 +       m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
4731 +       m.u.port_info_get.component_handle = port->component->handle;
4732 +       m.u.port_info_get.port_type = port->type;
4733 +       m.u.port_info_get.index = port->index;
4734 +
4735 +       ret = send_synchronous_mmal_msg(instance, &m,
4736 +                                       sizeof(m.u.port_info_get),
4737 +                                       &rmsg, &rmsg_handle);
4738 +       if (ret)
4739 +               return ret;
4740 +
4741 +       if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
4742 +               /* got an unexpected message type in reply */
4743 +               ret = -EINVAL;
4744 +               goto release_msg;
4745 +       }
4746 +
4747 +       /* return operation status */
4748 +       ret = -rmsg->u.port_info_get_reply.status;
4749 +       if (ret != MMAL_MSG_STATUS_SUCCESS)
4750 +               goto release_msg;
4751 +
4752 +       if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
4753 +               port->enabled = false;
4754 +       else
4755 +               port->enabled = true;
4756 +
4757 +       /* copy the values out of the message */
4758 +       port->handle = rmsg->u.port_info_get_reply.port_handle;
4759 +
4760 +       /* port type and index cached to use on port info set becuase
4761 +        * it does not use a port handle
4762 +        */
4763 +       port->type = rmsg->u.port_info_get_reply.port_type;
4764 +       port->index = rmsg->u.port_info_get_reply.port_index;
4765 +
4766 +       port->minimum_buffer.num =
4767 +           rmsg->u.port_info_get_reply.port.buffer_num_min;
4768 +       port->minimum_buffer.size =
4769 +           rmsg->u.port_info_get_reply.port.buffer_size_min;
4770 +       port->minimum_buffer.alignment =
4771 +           rmsg->u.port_info_get_reply.port.buffer_alignment_min;
4772 +
4773 +       port->recommended_buffer.alignment =
4774 +           rmsg->u.port_info_get_reply.port.buffer_alignment_min;
4775 +       port->recommended_buffer.num =
4776 +           rmsg->u.port_info_get_reply.port.buffer_num_recommended;
4777 +
4778 +       port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
4779 +       port->current_buffer.size =
4780 +           rmsg->u.port_info_get_reply.port.buffer_size;
4781 +
4782 +       /* stream format */
4783 +       port->format.type = rmsg->u.port_info_get_reply.format.type;
4784 +       port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
4785 +       port->format.encoding_variant =
4786 +           rmsg->u.port_info_get_reply.format.encoding_variant;
4787 +       port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
4788 +       port->format.flags = rmsg->u.port_info_get_reply.format.flags;
4789 +
4790 +       /* elementry stream format */
4791 +       memcpy(&port->es,
4792 +              &rmsg->u.port_info_get_reply.es,
4793 +              sizeof(union mmal_es_specific_format));
4794 +       port->format.es = &port->es;
4795 +
4796 +       port->format.extradata_size =
4797 +           rmsg->u.port_info_get_reply.format.extradata_size;
4798 +       memcpy(port->format.extradata,
4799 +              rmsg->u.port_info_get_reply.extradata,
4800 +              port->format.extradata_size);
4801 +
4802 +       pr_debug("received port info\n");
4803 +       dump_port_info(port);
4804 +
4805 +release_msg:
4806 +
4807 +       pr_debug("%s:result:%d component:0x%x port:%d\n",
4808 +                __func__, ret, port->component->handle, port->handle);
4809 +
4810 +       vchi_held_msg_release(&rmsg_handle);
4811 +
4812 +       return ret;
4813 +}
4814 +
4815 +/* create comonent on vc */
4816 +static int create_component(struct vchiq_mmal_instance *instance,
4817 +                           struct vchiq_mmal_component *component,
4818 +                           const char *name)
4819 +{
4820 +       int ret;
4821 +       struct mmal_msg m;
4822 +       struct mmal_msg *rmsg;
4823 +       VCHI_HELD_MSG_T rmsg_handle;
4824 +
4825 +       /* build component create message */
4826 +       m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
4827 +       m.u.component_create.client_component = component;
4828 +       strncpy(m.u.component_create.name, name,
4829 +               sizeof(m.u.component_create.name));
4830 +
4831 +       ret = send_synchronous_mmal_msg(instance, &m,
4832 +                                       sizeof(m.u.component_create),
4833 +                                       &rmsg, &rmsg_handle);
4834 +       if (ret)
4835 +               return ret;
4836 +
4837 +       if (rmsg->h.type != m.h.type) {
4838 +               /* got an unexpected message type in reply */
4839 +               ret = -EINVAL;
4840 +               goto release_msg;
4841 +       }
4842 +
4843 +       ret = -rmsg->u.component_create_reply.status;
4844 +       if (ret != MMAL_MSG_STATUS_SUCCESS)
4845 +               goto release_msg;
4846 +
4847 +       /* a valid component response received */
4848 +       component->handle = rmsg->u.component_create_reply.component_handle;
4849 +       component->inputs = rmsg->u.component_create_reply.input_num;
4850 +       component->outputs = rmsg->u.component_create_reply.output_num;
4851 +       component->clocks = rmsg->u.component_create_reply.clock_num;
4852 +
4853 +       pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
4854 +                component->handle,
4855 +                component->inputs, component->outputs, component->clocks);
4856 +
4857 +release_msg:
4858 +       vchi_held_msg_release(&rmsg_handle);
4859 +
4860 +       return ret;
4861 +}
4862 +
4863 +/* destroys a component on vc */
4864 +static int destroy_component(struct vchiq_mmal_instance *instance,
4865 +                            struct vchiq_mmal_component *component)
4866 +{
4867 +       int ret;
4868 +       struct mmal_msg m;
4869 +       struct mmal_msg *rmsg;
4870 +       VCHI_HELD_MSG_T rmsg_handle;
4871 +
4872 +       m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
4873 +       m.u.component_destroy.component_handle = component->handle;
4874 +
4875 +       ret = send_synchronous_mmal_msg(instance, &m,
4876 +                                       sizeof(m.u.component_destroy),
4877 +                                       &rmsg, &rmsg_handle);
4878 +       if (ret)
4879 +               return ret;
4880 +
4881 +       if (rmsg->h.type != m.h.type) {
4882 +               /* got an unexpected message type in reply */
4883 +               ret = -EINVAL;
4884 +               goto release_msg;
4885 +       }
4886 +
4887 +       ret = -rmsg->u.component_destroy_reply.status;
4888 +
4889 +release_msg:
4890 +
4891 +       vchi_held_msg_release(&rmsg_handle);
4892 +
4893 +       return ret;
4894 +}
4895 +
4896 +/* enable a component on vc */
4897 +static int enable_component(struct vchiq_mmal_instance *instance,
4898 +                           struct vchiq_mmal_component *component)
4899 +{
4900 +       int ret;
4901 +       struct mmal_msg m;
4902 +       struct mmal_msg *rmsg;
4903 +       VCHI_HELD_MSG_T rmsg_handle;
4904 +
4905 +       m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
4906 +       m.u.component_enable.component_handle = component->handle;
4907 +
4908 +       ret = send_synchronous_mmal_msg(instance, &m,
4909 +                                       sizeof(m.u.component_enable),
4910 +                                       &rmsg, &rmsg_handle);
4911 +       if (ret)
4912 +               return ret;
4913 +
4914 +       if (rmsg->h.type != m.h.type) {
4915 +               /* got an unexpected message type in reply */
4916 +               ret = -EINVAL;
4917 +               goto release_msg;
4918 +       }
4919 +
4920 +       ret = -rmsg->u.component_enable_reply.status;
4921 +
4922 +release_msg:
4923 +       vchi_held_msg_release(&rmsg_handle);
4924 +
4925 +       return ret;
4926 +}
4927 +
4928 +/* disable a component on vc */
4929 +static int disable_component(struct vchiq_mmal_instance *instance,
4930 +                            struct vchiq_mmal_component *component)
4931 +{
4932 +       int ret;
4933 +       struct mmal_msg m;
4934 +       struct mmal_msg *rmsg;
4935 +       VCHI_HELD_MSG_T rmsg_handle;
4936 +
4937 +       m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
4938 +       m.u.component_disable.component_handle = component->handle;
4939 +
4940 +       ret = send_synchronous_mmal_msg(instance, &m,
4941 +                                       sizeof(m.u.component_disable),
4942 +                                       &rmsg, &rmsg_handle);
4943 +       if (ret)
4944 +               return ret;
4945 +
4946 +       if (rmsg->h.type != m.h.type) {
4947 +               /* got an unexpected message type in reply */
4948 +               ret = -EINVAL;
4949 +               goto release_msg;
4950 +       }
4951 +
4952 +       ret = -rmsg->u.component_disable_reply.status;
4953 +
4954 +release_msg:
4955 +
4956 +       vchi_held_msg_release(&rmsg_handle);
4957 +
4958 +       return ret;
4959 +}
4960 +
4961 +/* get version of mmal implementation */
4962 +static int get_version(struct vchiq_mmal_instance *instance,
4963 +                      u32 *major_out, u32 *minor_out)
4964 +{
4965 +       int ret;
4966 +       struct mmal_msg m;
4967 +       struct mmal_msg *rmsg;
4968 +       VCHI_HELD_MSG_T rmsg_handle;
4969 +
4970 +       m.h.type = MMAL_MSG_TYPE_GET_VERSION;
4971 +
4972 +       ret = send_synchronous_mmal_msg(instance, &m,
4973 +                                       sizeof(m.u.version),
4974 +                                       &rmsg, &rmsg_handle);
4975 +       if (ret)
4976 +               return ret;
4977 +
4978 +       if (rmsg->h.type != m.h.type) {
4979 +               /* got an unexpected message type in reply */
4980 +               ret = -EINVAL;
4981 +               goto release_msg;
4982 +       }
4983 +
4984 +       *major_out = rmsg->u.version.major;
4985 +       *minor_out = rmsg->u.version.minor;
4986 +
4987 +release_msg:
4988 +       vchi_held_msg_release(&rmsg_handle);
4989 +
4990 +       return ret;
4991 +}
4992 +
4993 +/* do a port action with a port as a parameter */
4994 +static int port_action_port(struct vchiq_mmal_instance *instance,
4995 +                           struct vchiq_mmal_port *port,
4996 +                           enum mmal_msg_port_action_type action_type)
4997 +{
4998 +       int ret;
4999 +       struct mmal_msg m;
5000 +       struct mmal_msg *rmsg;
5001 +       VCHI_HELD_MSG_T rmsg_handle;
5002 +
5003 +       m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
5004 +       m.u.port_action_port.component_handle = port->component->handle;
5005 +       m.u.port_action_port.port_handle = port->handle;
5006 +       m.u.port_action_port.action = action_type;
5007 +
5008 +       port_to_mmal_msg(port, &m.u.port_action_port.port);
5009 +
5010 +       ret = send_synchronous_mmal_msg(instance, &m,
5011 +                                       sizeof(m.u.port_action_port),
5012 +                                       &rmsg, &rmsg_handle);
5013 +       if (ret)
5014 +               return ret;
5015 +
5016 +       if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
5017 +               /* got an unexpected message type in reply */
5018 +               ret = -EINVAL;
5019 +               goto release_msg;
5020 +       }
5021 +
5022 +       ret = -rmsg->u.port_action_reply.status;
5023 +
5024 +       pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
5025 +                __func__,
5026 +                ret, port->component->handle, port->handle,
5027 +                port_action_type_names[action_type], action_type);
5028 +
5029 +release_msg:
5030 +       vchi_held_msg_release(&rmsg_handle);
5031 +
5032 +       return ret;
5033 +}
5034 +
5035 +/* do a port action with handles as parameters */
5036 +static int port_action_handle(struct vchiq_mmal_instance *instance,
5037 +                             struct vchiq_mmal_port *port,
5038 +                             enum mmal_msg_port_action_type action_type,
5039 +                             u32 connect_component_handle,
5040 +                             u32 connect_port_handle)
5041 +{
5042 +       int ret;
5043 +       struct mmal_msg m;
5044 +       struct mmal_msg *rmsg;
5045 +       VCHI_HELD_MSG_T rmsg_handle;
5046 +
5047 +       m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
5048 +
5049 +       m.u.port_action_handle.component_handle = port->component->handle;
5050 +       m.u.port_action_handle.port_handle = port->handle;
5051 +       m.u.port_action_handle.action = action_type;
5052 +
5053 +       m.u.port_action_handle.connect_component_handle =
5054 +           connect_component_handle;
5055 +       m.u.port_action_handle.connect_port_handle = connect_port_handle;
5056 +
5057 +       ret = send_synchronous_mmal_msg(instance, &m,
5058 +                                       sizeof(m.u.port_action_handle),
5059 +                                       &rmsg, &rmsg_handle);
5060 +       if (ret)
5061 +               return ret;
5062 +
5063 +       if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
5064 +               /* got an unexpected message type in reply */
5065 +               ret = -EINVAL;
5066 +               goto release_msg;
5067 +       }
5068 +
5069 +       ret = -rmsg->u.port_action_reply.status;
5070 +
5071 +       pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)" \
5072 +                " connect component:0x%x connect port:%d\n",
5073 +                __func__,
5074 +                ret, port->component->handle, port->handle,
5075 +                port_action_type_names[action_type],
5076 +                action_type, connect_component_handle, connect_port_handle);
5077 +
5078 +release_msg:
5079 +       vchi_held_msg_release(&rmsg_handle);
5080 +
5081 +       return ret;
5082 +}
5083 +
5084 +static int port_parameter_set(struct vchiq_mmal_instance *instance,
5085 +                             struct vchiq_mmal_port *port,
5086 +                             u32 parameter_id, void *value, u32 value_size)
5087 +{
5088 +       int ret;
5089 +       struct mmal_msg m;
5090 +       struct mmal_msg *rmsg;
5091 +       VCHI_HELD_MSG_T rmsg_handle;
5092 +
5093 +       m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
5094 +
5095 +       m.u.port_parameter_set.component_handle = port->component->handle;
5096 +       m.u.port_parameter_set.port_handle = port->handle;
5097 +       m.u.port_parameter_set.id = parameter_id;
5098 +       m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
5099 +       memcpy(&m.u.port_parameter_set.value, value, value_size);
5100 +
5101 +       ret = send_synchronous_mmal_msg(instance, &m,
5102 +                                       (4 * sizeof(u32)) + value_size,
5103 +                                       &rmsg, &rmsg_handle);
5104 +       if (ret)
5105 +               return ret;
5106 +
5107 +       if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
5108 +               /* got an unexpected message type in reply */
5109 +               ret = -EINVAL;
5110 +               goto release_msg;
5111 +       }
5112 +
5113 +       ret = -rmsg->u.port_parameter_set_reply.status;
5114 +
5115 +       pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
5116 +                __func__,
5117 +                ret, port->component->handle, port->handle, parameter_id);
5118 +
5119 +release_msg:
5120 +       vchi_held_msg_release(&rmsg_handle);
5121 +
5122 +       return ret;
5123 +}
5124 +
5125 +static int port_parameter_get(struct vchiq_mmal_instance *instance,
5126 +                             struct vchiq_mmal_port *port,
5127 +                             u32 parameter_id, void *value, u32 *value_size)
5128 +{
5129 +       int ret;
5130 +       struct mmal_msg m;
5131 +       struct mmal_msg *rmsg;
5132 +       VCHI_HELD_MSG_T rmsg_handle;
5133 +
5134 +       m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
5135 +
5136 +       m.u.port_parameter_get.component_handle = port->component->handle;
5137 +       m.u.port_parameter_get.port_handle = port->handle;
5138 +       m.u.port_parameter_get.id = parameter_id;
5139 +       m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
5140 +
5141 +       ret = send_synchronous_mmal_msg(instance, &m,
5142 +                                       sizeof(struct
5143 +                                              mmal_msg_port_parameter_get),
5144 +                                       &rmsg, &rmsg_handle);
5145 +       if (ret)
5146 +               return ret;
5147 +
5148 +       if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
5149 +               /* got an unexpected message type in reply */
5150 +               pr_err("Incorrect reply type %d\n", rmsg->h.type);
5151 +               ret = -EINVAL;
5152 +               goto release_msg;
5153 +       }
5154 +
5155 +       ret = -rmsg->u.port_parameter_get_reply.status;
5156 +       if (ret) {
5157 +               /* Copy only as much as we have space for
5158 +                * but report true size of parameter
5159 +                */
5160 +               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
5161 +                      *value_size);
5162 +               *value_size = rmsg->u.port_parameter_get_reply.size;
5163 +       } else
5164 +               memcpy(value, &rmsg->u.port_parameter_get_reply.value,
5165 +                      rmsg->u.port_parameter_get_reply.size);
5166 +
5167 +       pr_info("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
5168 +               ret, port->component->handle, port->handle, parameter_id);
5169 +
5170 +release_msg:
5171 +       vchi_held_msg_release(&rmsg_handle);
5172 +
5173 +       return ret;
5174 +}
5175 +
5176 +/* disables a port and drains buffers from it */
5177 +static int port_disable(struct vchiq_mmal_instance *instance,
5178 +                       struct vchiq_mmal_port *port)
5179 +{
5180 +       int ret;
5181 +       struct list_head *q, *buf_head;
5182 +       unsigned long flags = 0;
5183 +
5184 +       if (!port->enabled)
5185 +               return 0;
5186 +
5187 +       port->enabled = false;
5188 +
5189 +       ret = port_action_port(instance, port,
5190 +                              MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
5191 +       if (ret == 0) {
5192 +
5193 +               /* drain all queued buffers on port */
5194 +               spin_lock_irqsave(&port->slock, flags);
5195 +
5196 +               list_for_each_safe(buf_head, q, &port->buffers) {
5197 +                       struct mmal_buffer *mmalbuf;
5198 +                       mmalbuf = list_entry(buf_head, struct mmal_buffer,
5199 +                                            list);
5200 +                       list_del(buf_head);
5201 +                       if (port->buffer_cb)
5202 +                               port->buffer_cb(instance,
5203 +                                               port, 0, mmalbuf, 0, 0,
5204 +                                               MMAL_TIME_UNKNOWN,
5205 +                                               MMAL_TIME_UNKNOWN);
5206 +               }
5207 +
5208 +               spin_unlock_irqrestore(&port->slock, flags);
5209 +
5210 +               ret = port_info_get(instance, port);
5211 +       }
5212 +
5213 +       return ret;
5214 +}
5215 +
5216 +/* enable a port */
5217 +static int port_enable(struct vchiq_mmal_instance *instance,
5218 +                      struct vchiq_mmal_port *port)
5219 +{
5220 +       unsigned int hdr_count;
5221 +       struct list_head *buf_head;
5222 +       int ret;
5223 +
5224 +       if (port->enabled)
5225 +               return 0;
5226 +
5227 +       /* ensure there are enough buffers queued to cover the buffer headers */
5228 +       if (port->buffer_cb != NULL) {
5229 +               hdr_count = 0;
5230 +               list_for_each(buf_head, &port->buffers) {
5231 +                       hdr_count++;
5232 +               }
5233 +               if (hdr_count < port->current_buffer.num)
5234 +                       return -ENOSPC;
5235 +       }
5236 +
5237 +       ret = port_action_port(instance, port,
5238 +                              MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
5239 +       if (ret)
5240 +               goto done;
5241 +
5242 +       port->enabled = true;
5243 +
5244 +       if (port->buffer_cb) {
5245 +               /* send buffer headers to videocore */
5246 +               hdr_count = 1;
5247 +               list_for_each(buf_head, &port->buffers) {
5248 +                       struct mmal_buffer *mmalbuf;
5249 +                       mmalbuf = list_entry(buf_head, struct mmal_buffer,
5250 +                                            list);
5251 +                       ret = buffer_from_host(instance, port, mmalbuf);
5252 +                       if (ret)
5253 +                               goto done;
5254 +
5255 +                       hdr_count++;
5256 +                       if (hdr_count > port->current_buffer.num)
5257 +                               break;
5258 +               }
5259 +       }
5260 +
5261 +       ret = port_info_get(instance, port);
5262 +
5263 +done:
5264 +       return ret;
5265 +}
5266 +
5267 +/* ------------------------------------------------------------------
5268 + * Exported API
5269 + *------------------------------------------------------------------*/
5270 +
5271 +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
5272 +                              struct vchiq_mmal_port *port)
5273 +{
5274 +       int ret;
5275 +
5276 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5277 +               return -EINTR;
5278 +
5279 +       ret = port_info_set(instance, port);
5280 +       if (ret)
5281 +               goto release_unlock;
5282 +
5283 +       /* read what has actually been set */
5284 +       ret = port_info_get(instance, port);
5285 +
5286 +release_unlock:
5287 +       mutex_unlock(&instance->vchiq_mutex);
5288 +
5289 +       return ret;
5290 +
5291 +}
5292 +
5293 +int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
5294 +                                 struct vchiq_mmal_port *port,
5295 +                                 u32 parameter, void *value, u32 value_size)
5296 +{
5297 +       int ret;
5298 +
5299 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5300 +               return -EINTR;
5301 +
5302 +       ret = port_parameter_set(instance, port, parameter, value, value_size);
5303 +
5304 +       mutex_unlock(&instance->vchiq_mutex);
5305 +
5306 +       return ret;
5307 +}
5308 +
5309 +int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
5310 +                                 struct vchiq_mmal_port *port,
5311 +                                 u32 parameter, void *value, u32 *value_size)
5312 +{
5313 +       int ret;
5314 +
5315 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5316 +               return -EINTR;
5317 +
5318 +       ret = port_parameter_get(instance, port, parameter, value, value_size);
5319 +
5320 +       mutex_unlock(&instance->vchiq_mutex);
5321 +
5322 +       return ret;
5323 +}
5324 +
5325 +/* enable a port
5326 + *
5327 + * enables a port and queues buffers for satisfying callbacks if we
5328 + * provide a callback handler
5329 + */
5330 +int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
5331 +                          struct vchiq_mmal_port *port,
5332 +                          vchiq_mmal_buffer_cb buffer_cb)
5333 +{
5334 +       int ret;
5335 +
5336 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5337 +               return -EINTR;
5338 +
5339 +       /* already enabled - noop */
5340 +       if (port->enabled) {
5341 +               ret = 0;
5342 +               goto unlock;
5343 +       }
5344 +
5345 +       port->buffer_cb = buffer_cb;
5346 +
5347 +       ret = port_enable(instance, port);
5348 +
5349 +unlock:
5350 +       mutex_unlock(&instance->vchiq_mutex);
5351 +
5352 +       return ret;
5353 +}
5354 +
5355 +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
5356 +                           struct vchiq_mmal_port *port)
5357 +{
5358 +       int ret;
5359 +
5360 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5361 +               return -EINTR;
5362 +
5363 +       if (!port->enabled) {
5364 +               mutex_unlock(&instance->vchiq_mutex);
5365 +               return 0;
5366 +       }
5367 +
5368 +       ret = port_disable(instance, port);
5369 +
5370 +       mutex_unlock(&instance->vchiq_mutex);
5371 +
5372 +       return ret;
5373 +}
5374 +
5375 +/* ports will be connected in a tunneled manner so data buffers
5376 + * are not handled by client.
5377 + */
5378 +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
5379 +                                  struct vchiq_mmal_port *src,
5380 +                                  struct vchiq_mmal_port *dst)
5381 +{
5382 +       int ret;
5383 +
5384 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5385 +               return -EINTR;
5386 +
5387 +       /* disconnect ports if connected */
5388 +       if (src->connected != NULL) {
5389 +               ret = port_disable(instance, src);
5390 +               if (ret) {
5391 +                       pr_err("failed disabling src port(%d)\n", ret);
5392 +                       goto release_unlock;
5393 +               }
5394 +
5395 +               /* do not need to disable the destination port as they
5396 +                * are connected and it is done automatically
5397 +                */
5398 +
5399 +               ret = port_action_handle(instance, src,
5400 +                                        MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
5401 +                                        src->connected->component->handle,
5402 +                                        src->connected->handle);
5403 +               if (ret < 0) {
5404 +                       pr_err("failed disconnecting src port\n");
5405 +                       goto release_unlock;
5406 +               }
5407 +               src->connected->enabled = false;
5408 +               src->connected = NULL;
5409 +       }
5410 +
5411 +       if (dst == NULL) {
5412 +               /* do not make new connection */
5413 +               ret = 0;
5414 +               pr_debug("not making new connection\n");
5415 +               goto release_unlock;
5416 +       }
5417 +
5418 +       /* copy src port format to dst */
5419 +       dst->format.encoding = src->format.encoding;
5420 +       dst->es.video.width = src->es.video.width;
5421 +       dst->es.video.height = src->es.video.height;
5422 +       dst->es.video.crop.x = src->es.video.crop.x;
5423 +       dst->es.video.crop.y = src->es.video.crop.y;
5424 +       dst->es.video.crop.width = src->es.video.crop.width;
5425 +       dst->es.video.crop.height = src->es.video.crop.height;
5426 +       dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
5427 +       dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
5428 +
5429 +       /* set new format */
5430 +       ret = port_info_set(instance, dst);
5431 +       if (ret) {
5432 +               pr_debug("setting port info failed\n");
5433 +               goto release_unlock;
5434 +       }
5435 +
5436 +       /* read what has actually been set */
5437 +       ret = port_info_get(instance, dst);
5438 +       if (ret) {
5439 +               pr_debug("read back port info failed\n");
5440 +               goto release_unlock;
5441 +       }
5442 +
5443 +       /* connect two ports together */
5444 +       ret = port_action_handle(instance, src,
5445 +                                MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
5446 +                                dst->component->handle, dst->handle);
5447 +       if (ret < 0) {
5448 +               pr_debug("connecting port %d:%d to %d:%d failed\n",
5449 +                        src->component->handle, src->handle,
5450 +                        dst->component->handle, dst->handle);
5451 +               goto release_unlock;
5452 +       }
5453 +       src->connected = dst;
5454 +
5455 +release_unlock:
5456 +
5457 +       mutex_unlock(&instance->vchiq_mutex);
5458 +
5459 +       return ret;
5460 +}
5461 +
5462 +int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
5463 +                            struct vchiq_mmal_port *port,
5464 +                            struct mmal_buffer *buffer)
5465 +{
5466 +       unsigned long flags = 0;
5467 +
5468 +       spin_lock_irqsave(&port->slock, flags);
5469 +       list_add_tail(&buffer->list, &port->buffers);
5470 +       spin_unlock_irqrestore(&port->slock, flags);
5471 +
5472 +       /* the port previously underflowed because it was missing a
5473 +        * mmal_buffer which has just been added, submit that buffer
5474 +        * to the mmal service.
5475 +        */
5476 +       if (port->buffer_underflow) {
5477 +               port_buffer_from_host(instance, port);
5478 +               port->buffer_underflow--;
5479 +       }
5480 +
5481 +       return 0;
5482 +}
5483 +
5484 +/* Initialise a mmal component and its ports
5485 + *
5486 + */
5487 +int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
5488 +                             const char *name,
5489 +                             struct vchiq_mmal_component **component_out)
5490 +{
5491 +       int ret;
5492 +       int idx;                /* port index */
5493 +       struct vchiq_mmal_component *component;
5494 +
5495 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5496 +               return -EINTR;
5497 +
5498 +       if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
5499 +               ret = -EINVAL;  /* todo is this correct error? */
5500 +               goto unlock;
5501 +       }
5502 +
5503 +       component = &instance->component[instance->component_idx];
5504 +
5505 +       ret = create_component(instance, component, name);
5506 +       if (ret < 0)
5507 +               goto unlock;
5508 +
5509 +       /* ports info needs gathering */
5510 +       component->control.type = MMAL_PORT_TYPE_CONTROL;
5511 +       component->control.index = 0;
5512 +       component->control.component = component;
5513 +       spin_lock_init(&component->control.slock);
5514 +       INIT_LIST_HEAD(&component->control.buffers);
5515 +       ret = port_info_get(instance, &component->control);
5516 +       if (ret < 0)
5517 +               goto release_component;
5518 +
5519 +       for (idx = 0; idx < component->inputs; idx++) {
5520 +               component->input[idx].type = MMAL_PORT_TYPE_INPUT;
5521 +               component->input[idx].index = idx;
5522 +               component->input[idx].component = component;
5523 +               spin_lock_init(&component->input[idx].slock);
5524 +               INIT_LIST_HEAD(&component->input[idx].buffers);
5525 +               ret = port_info_get(instance, &component->input[idx]);
5526 +               if (ret < 0)
5527 +                       goto release_component;
5528 +       }
5529 +
5530 +       for (idx = 0; idx < component->outputs; idx++) {
5531 +               component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
5532 +               component->output[idx].index = idx;
5533 +               component->output[idx].component = component;
5534 +               spin_lock_init(&component->output[idx].slock);
5535 +               INIT_LIST_HEAD(&component->output[idx].buffers);
5536 +               ret = port_info_get(instance, &component->output[idx]);
5537 +               if (ret < 0)
5538 +                       goto release_component;
5539 +       }
5540 +
5541 +       for (idx = 0; idx < component->clocks; idx++) {
5542 +               component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
5543 +               component->clock[idx].index = idx;
5544 +               component->clock[idx].component = component;
5545 +               spin_lock_init(&component->clock[idx].slock);
5546 +               INIT_LIST_HEAD(&component->clock[idx].buffers);
5547 +               ret = port_info_get(instance, &component->clock[idx]);
5548 +               if (ret < 0)
5549 +                       goto release_component;
5550 +       }
5551 +
5552 +       instance->component_idx++;
5553 +
5554 +       *component_out = component;
5555 +
5556 +       mutex_unlock(&instance->vchiq_mutex);
5557 +
5558 +       return 0;
5559 +
5560 +release_component:
5561 +       destroy_component(instance, component);
5562 +unlock:
5563 +       mutex_unlock(&instance->vchiq_mutex);
5564 +
5565 +       return ret;
5566 +}
5567 +
5568 +/*
5569 + * cause a mmal component to be destroyed
5570 + */
5571 +int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
5572 +                                 struct vchiq_mmal_component *component)
5573 +{
5574 +       int ret;
5575 +
5576 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5577 +               return -EINTR;
5578 +
5579 +       if (component->enabled)
5580 +               ret = disable_component(instance, component);
5581 +
5582 +       ret = destroy_component(instance, component);
5583 +
5584 +       mutex_unlock(&instance->vchiq_mutex);
5585 +
5586 +       return ret;
5587 +}
5588 +
5589 +/*
5590 + * cause a mmal component to be enabled
5591 + */
5592 +int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
5593 +                               struct vchiq_mmal_component *component)
5594 +{
5595 +       int ret;
5596 +
5597 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5598 +               return -EINTR;
5599 +
5600 +       if (component->enabled) {
5601 +               mutex_unlock(&instance->vchiq_mutex);
5602 +               return 0;
5603 +       }
5604 +
5605 +       ret = enable_component(instance, component);
5606 +       if (ret == 0)
5607 +               component->enabled = true;
5608 +
5609 +       mutex_unlock(&instance->vchiq_mutex);
5610 +
5611 +       return ret;
5612 +}
5613 +
5614 +/*
5615 + * cause a mmal component to be enabled
5616 + */
5617 +int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
5618 +                                struct vchiq_mmal_component *component)
5619 +{
5620 +       int ret;
5621 +
5622 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5623 +               return -EINTR;
5624 +
5625 +       if (!component->enabled) {
5626 +               mutex_unlock(&instance->vchiq_mutex);
5627 +               return 0;
5628 +       }
5629 +
5630 +       ret = disable_component(instance, component);
5631 +       if (ret == 0)
5632 +               component->enabled = false;
5633 +
5634 +       mutex_unlock(&instance->vchiq_mutex);
5635 +
5636 +       return ret;
5637 +}
5638 +
5639 +int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
5640 +                      u32 *major_out, u32 *minor_out)
5641 +{
5642 +       int ret;
5643 +
5644 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5645 +               return -EINTR;
5646 +
5647 +       ret = get_version(instance, major_out, minor_out);
5648 +
5649 +       mutex_unlock(&instance->vchiq_mutex);
5650 +
5651 +       return ret;
5652 +}
5653 +
5654 +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
5655 +{
5656 +       int status = 0;
5657 +
5658 +       if (instance == NULL)
5659 +               return -EINVAL;
5660 +
5661 +       if (mutex_lock_interruptible(&instance->vchiq_mutex))
5662 +               return -EINTR;
5663 +
5664 +       vchi_service_use(instance->handle);
5665 +
5666 +       status = vchi_service_close(instance->handle);
5667 +       if (status != 0)
5668 +               pr_err("mmal-vchiq: VCHIQ close failed");
5669 +
5670 +       mutex_unlock(&instance->vchiq_mutex);
5671 +
5672 +       vfree(instance->bulk_scratch);
5673 +
5674 +       kfree(instance);
5675 +
5676 +       return status;
5677 +}
5678 +
5679 +int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
5680 +{
5681 +       int status;
5682 +       struct vchiq_mmal_instance *instance;
5683 +       static VCHI_CONNECTION_T *vchi_connection;
5684 +       static VCHI_INSTANCE_T vchi_instance;
5685 +       SERVICE_CREATION_T params = {
5686 +               VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
5687 +               VC_MMAL_SERVER_NAME,
5688 +               vchi_connection,
5689 +               0,              /* rx fifo size (unused) */
5690 +               0,              /* tx fifo size (unused) */
5691 +               service_callback,
5692 +               NULL,           /* service callback parameter */
5693 +               1,              /* unaligned bulk receives */
5694 +               1,              /* unaligned bulk transmits */
5695 +               0               /* want crc check on bulk transfers */
5696 +       };
5697 +
5698 +       /* compile time checks to ensure structure size as they are
5699 +        * directly (de)serialised from memory.
5700 +        */
5701 +
5702 +       /* ensure the header structure has packed to the correct size */
5703 +       BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
5704 +
5705 +       /* ensure message structure does not exceed maximum length */
5706 +       BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
5707 +
5708 +       /* mmal port struct is correct size */
5709 +       BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
5710 +
5711 +       /* create a vchi instance */
5712 +       status = vchi_initialise(&vchi_instance);
5713 +       if (status) {
5714 +               pr_err("Failed to initialise VCHI instance (status=%d)\n",
5715 +                      status);
5716 +               return -EIO;
5717 +       }
5718 +
5719 +       status = vchi_connect(NULL, 0, vchi_instance);
5720 +       if (status) {
5721 +               pr_err("Failed to connect VCHI instance (status=%d)\n", status);
5722 +               return -EIO;
5723 +       }
5724 +
5725 +       instance = kmalloc(sizeof(*instance), GFP_KERNEL);
5726 +       memset(instance, 0, sizeof(*instance));
5727 +
5728 +       mutex_init(&instance->vchiq_mutex);
5729 +       mutex_init(&instance->bulk_mutex);
5730 +
5731 +       instance->bulk_scratch = vmalloc(PAGE_SIZE);
5732 +
5733 +       params.callback_param = instance;
5734 +
5735 +       status = vchi_service_open(vchi_instance, &params, &instance->handle);
5736 +       if (status) {
5737 +               pr_err("Failed to open VCHI service connection (status=%d)\n",
5738 +                      status);
5739 +               goto err_close_services;
5740 +       }
5741 +
5742 +       vchi_service_release(instance->handle);
5743 +
5744 +       *out_instance = instance;
5745 +
5746 +       return 0;
5747 +
5748 +err_close_services:
5749 +
5750 +       vchi_service_close(instance->handle);
5751 +       vfree(instance->bulk_scratch);
5752 +       kfree(instance);
5753 +       return -ENODEV;
5754 +}
5755 --- /dev/null
5756 +++ b/drivers/media/platform/bcm2835/mmal-vchiq.h
5757 @@ -0,0 +1,178 @@
5758 +/*
5759 + * Broadcom BM2835 V4L2 driver
5760 + *
5761 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
5762 + *
5763 + * This file is subject to the terms and conditions of the GNU General Public
5764 + * License.  See the file COPYING in the main directory of this archive
5765 + * for more details.
5766 + *
5767 + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
5768 + *          Dave Stevenson <dsteve@broadcom.com>
5769 + *          Simon Mellor <simellor@broadcom.com>
5770 + *          Luke Diamand <luked@broadcom.com>
5771 + *
5772 + * MMAL interface to VCHIQ message passing
5773 + */
5774 +
5775 +#ifndef MMAL_VCHIQ_H
5776 +#define MMAL_VCHIQ_H
5777 +
5778 +#include "mmal-msg-format.h"
5779 +
5780 +#define MAX_PORT_COUNT 4
5781 +
5782 +/* Maximum size of the format extradata. */
5783 +#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
5784 +
5785 +struct vchiq_mmal_instance;
5786 +
5787 +enum vchiq_mmal_es_type {
5788 +       MMAL_ES_TYPE_UNKNOWN,     /**< Unknown elementary stream type */
5789 +       MMAL_ES_TYPE_CONTROL,     /**< Elementary stream of control commands */
5790 +       MMAL_ES_TYPE_AUDIO,       /**< Audio elementary stream */
5791 +       MMAL_ES_TYPE_VIDEO,       /**< Video elementary stream */
5792 +       MMAL_ES_TYPE_SUBPICTURE   /**< Sub-picture elementary stream */
5793 +};
5794 +
5795 +/* rectangle, used lots so it gets its own struct */
5796 +struct vchiq_mmal_rect {
5797 +       s32 x;
5798 +       s32 y;
5799 +       s32 width;
5800 +       s32 height;
5801 +};
5802 +
5803 +struct vchiq_mmal_port_buffer {
5804 +       unsigned int num; /* number of buffers */
5805 +       u32 size; /* size of buffers */
5806 +       u32 alignment; /* alignment of buffers */
5807 +};
5808 +
5809 +struct vchiq_mmal_port;
5810 +
5811 +typedef void (*vchiq_mmal_buffer_cb)(
5812 +               struct vchiq_mmal_instance  *instance,
5813 +               struct vchiq_mmal_port *port,
5814 +               int status, struct mmal_buffer *buffer,
5815 +               unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
5816 +
5817 +struct vchiq_mmal_port {
5818 +       bool enabled;
5819 +       u32 handle;
5820 +       u32 type; /* port type, cached to use on port info set */
5821 +       u32 index; /* port index, cached to use on port info set */
5822 +
5823 +       /* component port belongs to, allows simple deref */
5824 +       struct vchiq_mmal_component *component;
5825 +
5826 +       struct vchiq_mmal_port *connected; /* port conencted to */
5827 +
5828 +       /* buffer info */
5829 +       struct vchiq_mmal_port_buffer minimum_buffer;
5830 +       struct vchiq_mmal_port_buffer recommended_buffer;
5831 +       struct vchiq_mmal_port_buffer current_buffer;
5832 +
5833 +       /* stream format */
5834 +       struct mmal_es_format format;
5835 +       /* elementry stream format */
5836 +       union mmal_es_specific_format es;
5837 +
5838 +       /* data buffers to fill */
5839 +       struct list_head buffers;
5840 +       /* lock to serialise adding and removing buffers from list */
5841 +       spinlock_t slock;
5842 +       /* count of how many buffer header refils have failed because
5843 +        * there was no buffer to satisfy them
5844 +        */
5845 +       int buffer_underflow;
5846 +       /* callback on buffer completion */
5847 +       vchiq_mmal_buffer_cb buffer_cb;
5848 +       /* callback context */
5849 +       void *cb_ctx;
5850 +};
5851 +
5852 +struct vchiq_mmal_component {
5853 +       bool enabled;
5854 +       u32 handle;  /* VideoCore handle for component */
5855 +       u32 inputs;  /* Number of input ports */
5856 +       u32 outputs; /* Number of output ports */
5857 +       u32 clocks;  /* Number of clock ports */
5858 +       struct vchiq_mmal_port control; /* control port */
5859 +       struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
5860 +       struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
5861 +       struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
5862 +};
5863 +
5864 +
5865 +int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
5866 +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
5867 +
5868 +/* Initialise a mmal component and its ports
5869 +*
5870 +*/
5871 +int vchiq_mmal_component_init(
5872 +               struct vchiq_mmal_instance *instance,
5873 +               const char *name,
5874 +               struct vchiq_mmal_component **component_out);
5875 +
5876 +int vchiq_mmal_component_finalise(
5877 +               struct vchiq_mmal_instance *instance,
5878 +               struct vchiq_mmal_component *component);
5879 +
5880 +int vchiq_mmal_component_enable(
5881 +               struct vchiq_mmal_instance *instance,
5882 +               struct vchiq_mmal_component *component);
5883 +
5884 +int vchiq_mmal_component_disable(
5885 +               struct vchiq_mmal_instance *instance,
5886 +               struct vchiq_mmal_component *component);
5887 +
5888 +
5889 +
5890 +/* enable a mmal port
5891 + *
5892 + * enables a port and if a buffer callback provided enque buffer
5893 + * headers as apropriate for the port.
5894 + */
5895 +int vchiq_mmal_port_enable(
5896 +               struct vchiq_mmal_instance *instance,
5897 +               struct vchiq_mmal_port *port,
5898 +               vchiq_mmal_buffer_cb buffer_cb);
5899 +
5900 +/* disable a port
5901 + *
5902 + * disable a port will dequeue any pending buffers
5903 + */
5904 +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
5905 +                          struct vchiq_mmal_port *port);
5906 +
5907 +
5908 +int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
5909 +                                 struct vchiq_mmal_port *port,
5910 +                                 u32 parameter,
5911 +                                 void *value,
5912 +                                 u32 value_size);
5913 +
5914 +int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
5915 +                                 struct vchiq_mmal_port *port,
5916 +                                 u32 parameter,
5917 +                                 void *value,
5918 +                                 u32 *value_size);
5919 +
5920 +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
5921 +                              struct vchiq_mmal_port *port);
5922 +
5923 +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
5924 +                           struct vchiq_mmal_port *src,
5925 +                           struct vchiq_mmal_port *dst);
5926 +
5927 +int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
5928 +                      u32 *major_out,
5929 +                      u32 *minor_out);
5930 +
5931 +int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
5932 +                            struct vchiq_mmal_port *port,
5933 +                            struct mmal_buffer *buf);
5934 +
5935 +#endif /* MMAL_VCHIQ_H */