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