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
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
12 Signed-off-by: Daniel Stone <daniels@collabora.com>
13 Signed-off-by: Luke Diamand <luked@broadcom.com>
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
49 diff --git a/Documentation/video4linux/bcm2835-v4l2.txt b/Documentation/video4linux/bcm2835-v4l2.txt
51 index 0000000..c585a8f
53 +++ b/Documentation/video4linux/bcm2835-v4l2.txt
56 +BCM2835 (aka Raspberry Pi) V4L2 driver
57 +======================================
62 +Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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.
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.
84 +You need a version 1.0 or later of v4l2-ctl, available from:
85 + git://git.linuxtv.org/v4l-utils.git
87 +$ sudo modprobe bcm2835-v4l2
91 +$ v4l2-ctl --overlay=1
93 +Turn off the overlay:
95 +$ v4l2-ctl --overlay=0
97 +Set the capture format for video:
99 +$ v4l2-ctl --set-fmt-video=width=1920,height=1088,pixelformat=4
101 +(Note: 1088 not 1080).
105 +$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264
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
112 +List of available formats:
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"
125 endif # V4L_PLATFORM_DRIVERS
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/
133 obj-$(CONFIG_ARCH_OMAP) += omap/
135 +obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/
137 ccflags-y += -I$(srctree)/drivers/media/i2c
138 diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig
140 index 0000000..a8fd172
142 +++ b/drivers/media/platform/bcm2835/Kconfig
144 +# Broadcom VideoCore IV v4l2 camera support
146 +config VIDEO_BCM2835
147 + bool "Broadcom BCM2835 camera interface driver"
148 + depends on VIDEO_V4L2 && ARCH_BCM2708
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.
157 +config VIDEO_BCM2835_MMAL
158 + tristate "Broadcom BM2835 MMAL camera interface driver"
159 + depends on BCM2708_VCHIQ
160 + select VIDEOBUF2_VMALLOC
162 + This is a V4L2 driver for the Broadcom BCM2835 MMAL camera host interface
164 + To compile this driver as a module, choose M here: the
165 + module will be called bcm2835-v4l2.o
168 +endif # VIDEO_BM2835
169 diff --git a/drivers/media/platform/bcm2835/Makefile b/drivers/media/platform/bcm2835/Makefile
171 index 0000000..f17c79c
173 +++ b/drivers/media/platform/bcm2835/Makefile
175 +bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o
177 +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o
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
182 index 0000000..47fe45d
184 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c
187 + * Broadcom BM2835 V4L2 driver
189 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
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>
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"
222 +#define BM2835_MMAL_VERSION "0.0.2"
223 +#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2"
225 +#define MAX_WIDTH 2592
226 +#define MAX_HEIGHT 1944
227 +#define MIN_BUFFER_SIZE (80*1024)
229 +#define MAX_VIDEO_MODE_WIDTH 1280
230 +#define MAX_VIDEO_MODE_HEIGHT 720
232 +MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
233 +MODULE_AUTHOR("Vincent Sanders");
234 +MODULE_LICENSE("GPL");
235 +MODULE_VERSION(BM2835_MMAL_VERSION);
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");
241 +static struct bm2835_mmal_dev *gdev; /* global device data */
244 +static struct mmal_fmt formats[] = {
246 + .name = "4:2:0, packed YUV",
247 + .fourcc = V4L2_PIX_FMT_YUV420,
248 + .mmal = MMAL_ENCODING_I420,
250 + .mmal_component = MMAL_COMPONENT_CAMERA,
253 + .name = "4:2:2, packed, YUYV",
254 + .fourcc = V4L2_PIX_FMT_YUYV,
255 + .mmal = MMAL_ENCODING_YUYV,
257 + .mmal_component = MMAL_COMPONENT_CAMERA,
260 + .name = "RGB24 (BE)",
261 + .fourcc = V4L2_PIX_FMT_BGR24,
262 + .mmal = MMAL_ENCODING_BGR24,
264 + .mmal_component = MMAL_COMPONENT_CAMERA,
268 + .fourcc = V4L2_PIX_FMT_JPEG,
269 + .mmal = MMAL_ENCODING_JPEG,
271 + .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
275 + .fourcc = V4L2_PIX_FMT_H264,
276 + .mmal = MMAL_ENCODING_H264,
278 + .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
282 +static struct mmal_fmt *get_format(struct v4l2_format *f)
284 + struct mmal_fmt *fmt;
287 + for (k = 0; k < ARRAY_SIZE(formats); k++) {
289 + if (fmt->fourcc == f->fmt.pix.pixelformat)
293 + if (k == ARRAY_SIZE(formats))
296 + return &formats[k];
299 +/* ------------------------------------------------------------------
300 + Videobuf queue operations
301 + ------------------------------------------------------------------*/
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[])
307 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
308 + unsigned long size;
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__);
317 + size = dev->capture.port->current_buffer.size;
319 + v4l2_err(&dev->v4l2_dev,
320 + "%s: capture port buffer size is zero\n", __func__);
324 + if (*nbuffers < (dev->capture.port->current_buffer.num + 2))
325 + *nbuffers = (dev->capture.port->current_buffer.num + 2);
332 + * videobuf2-vmalloc allocator is context-less so no need to set
333 + * alloc_ctxs array.
336 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
342 +static int buffer_prepare(struct vb2_buffer *vb)
344 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
345 + unsigned long size;
347 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
350 + BUG_ON(dev->capture.port == NULL);
351 + BUG_ON(dev->capture.fmt == NULL);
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);
364 +static inline bool is_capturing(struct bm2835_mmal_dev *dev)
366 + return dev->capture.camera_port ==
368 + component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE];
371 +static void buffer_cb(struct vchiq_mmal_instance *instance,
372 + struct vchiq_mmal_port *port,
374 + struct mmal_buffer *buf,
375 + unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
377 + struct bm2835_mmal_dev *dev = port->cb_ctx;
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);
384 + /* error in transfer */
386 + /* there was a buffer with the error so return it */
387 + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
390 + } else if (length == 0) {
393 + /* this should only ever happen if the port is
394 + * disabled and there are buffers still queued
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(
406 + MMAL_PARAMETER_CAPTURE,
409 + sizeof(dev->capture.frame_count));
412 + /* signal frame completion */
413 + complete(&dev->capture.frame_cmplt);
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;
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 +
428 + buf->vb.v4l2_buf.timestamp.tv_usec =
429 + dev->capture.kernel_start_ts.tv_usec + rem;
431 + if (buf->vb.v4l2_buf.timestamp.tv_usec >=
433 + buf->vb.v4l2_buf.timestamp.tv_sec++;
434 + buf->vb.v4l2_buf.timestamp.tv_usec -=
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.
442 + (int)dev->capture.kernel_start_ts.
444 + dev->capture.vc_start_timestamp, pts,
445 + (int)buf->vb.v4l2_buf.timestamp.tv_sec,
446 + (int)buf->vb.v4l2_buf.timestamp.
449 + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
452 + vb2_set_plane_payload(&buf->vb, 0, length);
453 + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
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(
463 + MMAL_PARAMETER_CAPTURE,
466 + sizeof(dev->capture.frame_count));
469 + /* signal frame completion */
470 + complete(&dev->capture.frame_cmplt);
475 +static int enable_camera(struct bm2835_mmal_dev *dev)
478 + if (!dev->camera_use_count) {
479 + ret = vchiq_mmal_component_enable(
481 + dev->component[MMAL_COMPONENT_CAMERA]);
483 + v4l2_err(&dev->v4l2_dev,
484 + "Failed enabling camera, ret %d\n", ret);
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);
495 +static int disable_camera(struct bm2835_mmal_dev *dev)
498 + if (!dev->camera_use_count) {
499 + v4l2_err(&dev->v4l2_dev,
500 + "Disabled the camera when already disabled\n");
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");
509 + vchiq_mmal_component_disable(
511 + dev->component[MMAL_COMPONENT_CAMERA]);
513 + v4l2_err(&dev->v4l2_dev,
514 + "Failed disabling camera, ret %d\n", ret);
517 + vchiq_mmal_port_parameter_set(
519 + &dev->component[MMAL_COMPONENT_CAMERA]->control,
520 + MMAL_PARAMETER_CAMERA_NUM, &i,
523 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
524 + "Camera refcount now %d\n", dev->camera_use_count);
528 +static void buffer_queue(struct vb2_buffer *vb)
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);
534 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
535 + "%s: dev:%p buf:%p\n", __func__, dev, buf);
537 + buf->buffer = vb2_plane_vaddr(&buf->vb, 0);
538 + buf->buffer_size = vb2_plane_size(&buf->vb, 0);
540 + ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
542 + v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
546 +static int start_streaming(struct vb2_queue *vq, unsigned int count)
548 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
550 + int parameter_size;
552 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
555 + /* ensure a format has actually been set */
556 + if (dev->capture.port == NULL)
559 + if (enable_camera(dev) < 0) {
560 + v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n");
564 + /*init_completion(&dev->capture.frame_cmplt); */
566 + /* enable frame capture */
567 + dev->capture.frame_count = 1;
569 + /* if the preview is not already running, wait for a few frames for AGC
572 + if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled)
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);
581 + v4l2_err(&dev->v4l2_dev,
582 + "Failed to enable encode tunnel - error %d\n",
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 + ¶meter_size)) {
595 + v4l2_err(&dev->v4l2_dev,
596 + "Failed to get VC start time - update your VC f/w\n");
598 + /* Flag to indicate just to rely on kernel timestamps */
599 + dev->capture.vc_start_timestamp = -1;
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);
605 + v4l2_get_timestamp(&dev->capture.kernel_start_ts);
607 + /* enable the camera port */
608 + dev->capture.port->cb_ctx = dev;
610 + vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
612 + v4l2_err(&dev->v4l2_dev,
613 + "Failed to enable capture port - error %d\n", ret);
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));
626 +/* abort streaming and wait for last buffer */
627 +static int stop_streaming(struct vb2_queue *vq)
630 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
632 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
635 + init_completion(&dev->capture.frame_cmplt);
636 + dev->capture.frame_count = 0;
638 + /* ensure a format has actually been set */
639 + if (dev->capture.port == NULL)
642 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n");
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));
651 + /* wait for last frame to complete */
652 + ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
654 + v4l2_err(&dev->v4l2_dev,
655 + "error %d waiting for frame completion\n", ret);
657 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
658 + "disabling connection\n");
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",
671 + if (disable_camera(dev) < 0) {
672 + v4l2_err(&dev->v4l2_dev, "Failed to disable camera");
679 +static void bm2835_mmal_lock(struct vb2_queue *vq)
681 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
682 + mutex_lock(&dev->mutex);
685 +static void bm2835_mmal_unlock(struct vb2_queue *vq)
687 + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
688 + mutex_unlock(&dev->mutex);
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,
701 +/* ------------------------------------------------------------------
703 + ------------------------------------------------------------------*/
706 +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
707 + struct v4l2_fmtdesc *f)
709 + struct mmal_fmt *fmt;
711 + if (f->index >= ARRAY_SIZE(formats))
714 + fmt = &formats[f->index];
716 + strlcpy(f->description, fmt->name, sizeof(f->description));
717 + f->pixelformat = fmt->fourcc;
722 +static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
723 + struct v4l2_format *f)
725 + struct bm2835_mmal_dev *dev = video_drvdata(file);
727 + f->fmt.win = dev->overlay;
732 +static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
733 + struct v4l2_format *f)
735 + /* Only support one format so get the current one. */
736 + vidioc_g_fmt_vid_overlay(file, priv, f);
738 + /* todo: allow the size and/or offset to be changed. */
742 +static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv,
743 + struct v4l2_format *f)
745 + struct bm2835_mmal_dev *dev = video_drvdata(file);
747 + vidioc_try_fmt_vid_overlay(file, priv, f);
749 + dev->overlay = f->fmt.win;
751 + /* todo: program the preview port parameters */
755 +static int vidioc_overlay(struct file *file, void *f, unsigned int on)
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,
768 + .x = dev->overlay.w.left,
769 + .y = dev->overlay.w.top,
770 + .width = dev->overlay.w.width,
771 + .height = dev->overlay.w.height,
775 + if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) ||
776 + (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled))
777 + return 0; /* already in requested state */
780 + &dev->component[MMAL_COMPONENT_CAMERA]->
781 + output[MMAL_CAMERA_PORT_PREVIEW];
784 + /* disconnect preview ports and disable component */
785 + ret = vchiq_mmal_port_disable(dev->instance, src);
788 + vchiq_mmal_port_connect_tunnel(dev->instance, src,
791 + ret = vchiq_mmal_component_disable(
793 + dev->component[MMAL_COMPONENT_PREVIEW]);
795 + disable_camera(dev);
799 + /* set preview port format and connect it to output */
800 + dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0];
802 + ret = vchiq_mmal_port_set_format(dev->instance, src);
806 + ret = vchiq_mmal_port_parameter_set(dev->instance, dst,
807 + MMAL_PARAMETER_DISPLAYREGION,
808 + &prev_config, sizeof(prev_config));
812 + if (enable_camera(dev) < 0)
815 + ret = vchiq_mmal_component_enable(
817 + dev->component[MMAL_COMPONENT_PREVIEW]);
821 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n",
823 + ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst);
825 + ret = vchiq_mmal_port_enable(dev->instance, src, NULL);
830 +static int vidioc_g_fbuf(struct file *file, void *fh,
831 + struct v4l2_framebuffer *a)
833 + /* The video overlay must stay within the framebuffer and can't be
834 + positioned independently. */
835 + a->flags = V4L2_FBUF_FLAG_OVERLAY;
837 + /* todo: v4l2_framebuffer still needs more info filling in
838 + * in order to pass the v4l2-compliance test. */
844 +static int vidioc_enum_input(struct file *file, void *priv,
845 + struct v4l2_input *inp)
847 + /* only a single camera input */
848 + if (inp->index != 0)
851 + inp->type = V4L2_INPUT_TYPE_CAMERA;
852 + sprintf(inp->name, "Camera %u", inp->index);
856 +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
862 +static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
870 +/* capture ioctls */
871 +static int vidioc_querycap(struct file *file, void *priv,
872 + struct v4l2_capability *cap)
874 + struct bm2835_mmal_dev *dev = video_drvdata(file);
878 + vchiq_mmal_version(dev->instance, &major, &minor);
880 + strcpy(cap->driver, "bm2835 mmal");
881 + snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d",
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;
893 +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
894 + struct v4l2_fmtdesc *f)
896 + struct mmal_fmt *fmt;
898 + if (f->index >= ARRAY_SIZE(formats))
901 + fmt = &formats[f->index];
903 + strlcpy(f->description, fmt->name, sizeof(f->description));
904 + f->pixelformat = fmt->fourcc;
908 +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
909 + struct v4l2_format *f)
911 + struct bm2835_mmal_dev *dev = video_drvdata(file);
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);
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;
930 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
931 + f->fmt.pix.priv = 0;
933 + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
938 +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
939 + struct v4l2_format *f)
941 + struct bm2835_mmal_dev *dev = video_drvdata(file);
942 + struct mmal_fmt *mfmt;
944 + mfmt = get_format(f);
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);
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;
962 + if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
963 + mfmt->fourcc == V4L2_PIX_FMT_UYVY)
964 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
966 + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
967 + f->fmt.pix.priv = 0;
969 + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
974 +static int mmal_setup_components(struct bm2835_mmal_dev *dev,
975 + struct v4l2_format *f)
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);
984 + if (dev->capture.encode_component) {
985 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
986 + "vid_cap - disconnect previous tunnel\n");
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,
996 + v4l2_err(&dev->v4l2_dev,
997 + "Failed to disable encode component %d\n",
1000 + dev->capture.encode_component = NULL;
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];
1012 + camera_port = port =
1013 + &dev->component[MMAL_COMPONENT_CAMERA]->
1014 + output[MMAL_CAMERA_PORT_CAPTURE];
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];
1020 + &dev->component[MMAL_COMPONENT_CAMERA]->
1021 + output[MMAL_CAMERA_PORT_CAPTURE];
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];
1027 + &dev->component[MMAL_COMPONENT_CAMERA]->
1028 + output[MMAL_CAMERA_PORT_VIDEO];
1037 + if (encode_component)
1038 + camera_port->format.encoding = MMAL_ENCODING_OPAQUE;
1040 + camera_port->format.encoding = mfmt->mmal;
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;
1052 + ret = vchiq_mmal_port_set_format(dev->instance, 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
1069 + vchiq_mmal_port_disable(dev->instance,
1073 + vchiq_mmal_port_connect_tunnel(
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(
1091 + &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
1093 + ret = vchiq_mmal_port_enable(dev->instance,
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;
1105 + if (encode_component) {
1106 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1107 + "vid_cap - set up encode comp\n");
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;
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;
1123 + case MMAL_COMPONENT_IMAGE_ENCODE:
1124 + /* Could set EXIF parameters here */
1129 + ret = vchiq_mmal_port_set_format(dev->instance, port);
1132 + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
1133 + "%s failed to set format\n", __func__);
1135 + ret = vchiq_mmal_component_enable(
1137 + encode_component);
1139 + v4l2_dbg(1, bcm2835_v4l2_debug,
1141 + "%s Failed to enable encode components\n",
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,
1152 + "JPEG - fiddle buffer size\n");
1153 + port->current_buffer.size =
1154 + (f->fmt.pix.sizeimage <
1156 + ? (100 << 10) : f->fmt.pix.
1159 + v4l2_dbg(1, bcm2835_v4l2_debug,
1161 + "vid_cap - current_buffer.size being set to %d\n",
1162 + f->fmt.pix.sizeimage);
1163 + port->current_buffer.alignment = 0;
1165 + vchiq_mmal_port_connect_tunnel(
1168 + &encode_component->input[0]);
1170 + v4l2_dbg(1, bcm2835_v4l2_debug,
1172 + "%s failed to create connection\n",
1174 + /* ensure capture is not going to be tried */
1175 + dev->capture.port = NULL;
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;
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;
1192 + /* select port for capture */
1193 + dev->capture.port = port;
1194 + dev->capture.camera_port = camera_port;
1195 + dev->capture.encode_component = encode_component;
1199 + /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */
1203 +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1204 + struct v4l2_format *f)
1207 + struct bm2835_mmal_dev *dev = video_drvdata(file);
1208 + struct mmal_fmt *mfmt;
1210 + /* try the format to set valid parameters */
1211 + ret = vidioc_try_fmt_vid_cap(file, priv, f);
1213 + v4l2_err(&dev->v4l2_dev,
1214 + "vid_cap - vidioc_try_fmt_vid_cap failed\n");
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__);
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);
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);
1235 + ret = mmal_setup_components(dev, f);
1237 + v4l2_err(&dev->v4l2_dev,
1238 + "%s: failed to setup mmal components: %d\n",
1244 +static const struct v4l2_ioctl_ops camera0_ioctl_ops = {
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,
1254 + .vidioc_enum_input = vidioc_enum_input,
1255 + .vidioc_g_input = vidioc_g_input,
1256 + .vidioc_s_input = vidioc_s_input,
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,
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,
1275 + .vidioc_log_status = v4l2_ctrl_log_status,
1276 + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1277 + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1280 +/* ------------------------------------------------------------------
1281 + Driver init/finalise
1282 + ------------------------------------------------------------------*/
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,
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,
1301 +static int set_camera_parameters(struct vchiq_mmal_instance *instance,
1302 + struct vchiq_mmal_component *camera)
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
1318 + ret = vchiq_mmal_port_parameter_set(instance, &camera->control,
1319 + MMAL_PARAMETER_CAMERA_CONFIG,
1320 + &cam_config, sizeof(cam_config));
1324 +/* MMAL instance and component init */
1325 +static int __init mmal_init(struct bm2835_mmal_dev *dev)
1328 + struct mmal_es_format *format;
1330 + ret = vchiq_mmal_init(&dev->instance);
1334 + /* get the camera component ready */
1335 + ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
1336 + &dev->component[MMAL_COMPONENT_CAMERA]);
1340 + if (dev->component[MMAL_COMPONENT_CAMERA]->outputs <
1341 + MMAL_CAMERA_PORT_COUNT) {
1343 + goto unreg_camera;
1346 + ret = set_camera_parameters(dev->instance,
1347 + dev->component[MMAL_COMPONENT_CAMERA]);
1349 + goto unreg_camera;
1352 + &dev->component[MMAL_COMPONENT_CAMERA]->
1353 + output[MMAL_CAMERA_PORT_PREVIEW].format;
1355 + format->encoding = MMAL_ENCODING_OPAQUE;
1356 + format->encoding_variant = MMAL_ENCODING_I420;
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;
1368 + &dev->component[MMAL_COMPONENT_CAMERA]->
1369 + output[MMAL_CAMERA_PORT_VIDEO].format;
1371 + format->encoding = MMAL_ENCODING_OPAQUE;
1372 + format->encoding_variant = MMAL_ENCODING_I420;
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;
1384 + &dev->component[MMAL_COMPONENT_CAMERA]->
1385 + output[MMAL_CAMERA_PORT_CAPTURE].format;
1387 + format->encoding = MMAL_ENCODING_OPAQUE;
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;
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;
1403 + /* get the preview component ready */
1404 + ret = vchiq_mmal_component_init(
1405 + dev->instance, "ril.video_render",
1406 + &dev->component[MMAL_COMPONENT_PREVIEW]);
1408 + goto unreg_camera;
1410 + if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
1412 + pr_debug("too few input ports %d needed %d\n",
1413 + dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
1414 + goto unreg_preview;
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]);
1422 + goto unreg_preview;
1424 + if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
1426 + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
1427 + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
1429 + goto unreg_image_encoder;
1432 + /* get the video encoder component ready */
1433 + ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
1435 + component[MMAL_COMPONENT_VIDEO_ENCODE]);
1437 + goto unreg_image_encoder;
1439 + if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
1441 + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
1442 + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
1444 + goto unreg_vid_encoder;
1448 + unsigned int enable = 1;
1449 + vchiq_mmal_port_parameter_set(
1451 + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
1452 + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
1453 + &enable, sizeof(enable));
1455 + vchiq_mmal_port_parameter_set(dev->instance,
1456 + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
1457 + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
1461 + ret = bm2835_mmal_set_all_camera_controls(dev);
1463 + goto unreg_vid_encoder;
1468 + pr_err("Cleanup: Destroy video encoder\n");
1469 + vchiq_mmal_component_finalise(
1471 + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]);
1473 +unreg_image_encoder:
1474 + pr_err("Cleanup: Destroy image encoder\n");
1475 + vchiq_mmal_component_finalise(
1477 + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
1480 + pr_err("Cleanup: Destroy video render\n");
1481 + vchiq_mmal_component_finalise(dev->instance,
1482 + dev->component[MMAL_COMPONENT_PREVIEW]);
1485 + pr_err("Cleanup: Destroy camera\n");
1486 + vchiq_mmal_component_finalise(dev->instance,
1487 + dev->component[MMAL_COMPONENT_CAMERA]);
1490 + vchiq_mmal_finalise(dev->instance);
1494 +static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
1495 + struct video_device *vfd)
1499 + *vfd = vdev_template;
1501 + vfd->v4l2_dev = &dev->v4l2_dev;
1503 + vfd->lock = &dev->mutex;
1505 + vfd->queue = &dev->capture.vb_vidq;
1507 + set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
1509 + /* video device needs to be able to access instance data */
1510 + video_set_drvdata(vfd, dev);
1512 + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
1516 + v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
1517 + video_device_node_name(vfd));
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,
1530 +static int __init bm2835_mmal_init(void)
1533 + struct bm2835_mmal_dev *dev;
1534 + struct vb2_queue *q;
1536 + dev = kzalloc(sizeof(*gdev), GFP_KERNEL);
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;
1548 + dev->capture.fmt = &formats[3]; /* JPEG */
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);
1557 + /* setup v4l controls */
1558 + ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
1561 + dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
1564 + ret = mmal_init(dev);
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);
1582 + /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */
1583 + mutex_init(&dev->mutex);
1585 + /* initialise video devices */
1586 + ret = bm2835_mmal_init_device(dev, &dev->vdev);
1590 + ret = mmal_setup_components(dev, &default_v4l2_format);
1592 + v4l2_err(&dev->v4l2_dev,
1593 + "%s: could not setup components\n", __func__);
1597 + v4l2_info(&dev->v4l2_dev,
1598 + "Broadcom 2835 MMAL video capture ver %s loaded.\n",
1599 + BM2835_MMAL_VERSION);
1605 + v4l2_ctrl_handler_free(&dev->ctrl_handler);
1606 + v4l2_device_unregister(&dev->v4l2_dev);
1611 + v4l2_err(&dev->v4l2_dev,
1612 + "%s: error %d while loading driver\n",
1613 + BM2835_MMAL_MODULE_NAME, ret);
1618 +static void __exit bm2835_mmal_exit(void)
1623 + v4l2_info(&gdev->v4l2_dev, "unregistering %s\n",
1624 + video_device_node_name(&gdev->vdev));
1626 + video_unregister_device(&gdev->vdev);
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);
1636 + vchiq_mmal_component_disable(gdev->instance,
1637 + gdev->component[MMAL_COMPONENT_CAMERA]);
1639 + vchiq_mmal_component_finalise(gdev->instance,
1641 + component[MMAL_COMPONENT_VIDEO_ENCODE]);
1643 + vchiq_mmal_component_finalise(gdev->instance,
1645 + component[MMAL_COMPONENT_IMAGE_ENCODE]);
1647 + vchiq_mmal_component_finalise(gdev->instance,
1648 + gdev->component[MMAL_COMPONENT_PREVIEW]);
1650 + vchiq_mmal_component_finalise(gdev->instance,
1651 + gdev->component[MMAL_COMPONENT_CAMERA]);
1653 + vchiq_mmal_finalise(gdev->instance);
1655 + v4l2_ctrl_handler_free(&gdev->ctrl_handler);
1657 + v4l2_device_unregister(&gdev->v4l2_dev);
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
1668 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h
1671 + * Broadcom BM2835 V4L2 driver
1673 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
1684 + * core driver device
1687 +#define V4L2_CTRL_COUNT 18 /* number of v4l controls */
1690 + MMAL_COMPONENT_CAMERA = 0,
1691 + MMAL_COMPONENT_PREVIEW,
1692 + MMAL_COMPONENT_IMAGE_ENCODE,
1693 + MMAL_COMPONENT_VIDEO_ENCODE,
1694 + MMAL_COMPONENT_COUNT
1698 + MMAL_CAMERA_PORT_PREVIEW = 0,
1699 + MMAL_CAMERA_PORT_VIDEO,
1700 + MMAL_CAMERA_PORT_CAPTURE,
1701 + MMAL_CAMERA_PORT_COUNT
1704 +#define PREVIEW_FRAME_RATE_NUM 30
1705 +#define PREVIEW_FRAME_RATE_DEN 1
1707 +#define PREVIEW_LAYER 2
1709 +extern int bcm2835_v4l2_debug;
1711 +struct bm2835_mmal_dev {
1712 + /* v4l2 devices */
1713 + struct v4l2_device v4l2_dev;
1714 + struct video_device vdev;
1715 + struct mutex mutex;
1718 + struct v4l2_ctrl_handler ctrl_handler;
1719 + struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT];
1720 + struct mmal_colourfx colourfx;
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;
1729 + struct v4l2_window overlay;
1732 + unsigned int width; /* width */
1733 + unsigned int height; /* height */
1734 + unsigned int stride; /* stride */
1735 + struct mmal_fmt *fmt;
1737 + /* H264 encode bitrate */
1738 + int encode_bitrate;
1739 + /* H264 bitrate mode. CBR/VBR */
1740 + int encode_bitrate_mode;
1741 + /* JPEG Q-factor */
1744 + struct vb2_queue vb_vidq;
1746 + /* VC start timestamp for streaming */
1747 + s64 vc_start_timestamp;
1748 + /* Kernel start timestamp for streaming */
1749 + struct timeval kernel_start_ts;
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;
1765 +int bm2835_mmal_init_controls(
1766 + struct bm2835_mmal_dev *dev,
1767 + struct v4l2_ctrl_handler *hdl);
1769 +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev);
1772 +/* Debug helpers */
1774 +#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \
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); \
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
1787 +++ b/drivers/media/platform/bcm2835/controls.c
1790 + * Broadcom BM2835 V4L2 driver
1792 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
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>
1816 +#include "mmal-common.h"
1817 +#include "mmal-vchiq.h"
1818 +#include "mmal-parameters.h"
1819 +#include "bcm2835-camera.h"
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.
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
1828 +/* Supported ISO values
1831 +static const s64 iso_qmenu[] = {
1832 + 0, 100, 200, 400, 800,
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,
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 */
1849 +struct bm2835_mmal_v4l2_ctrl;
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);
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 */
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;
1870 +struct v4l2_to_mmal_effects_setting {
1873 + s32 col_fx_enable;
1874 + s32 col_fx_fixed_cbcr;
1877 + u32 num_effect_params;
1878 + u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS];
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} }
1918 +/* control handlers*/
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)
1925 + s32 num; /**< Numerator */
1926 + s32 den; /**< Denominator */
1928 + struct vchiq_mmal_port *control;
1930 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
1932 + rational_value.num = ctrl->val;
1933 + rational_value.den = 100;
1935 + return vchiq_mmal_port_parameter_set(dev->instance, control,
1936 + mmal_ctrl->mmal_id,
1938 + sizeof(rational_value));
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)
1946 + struct vchiq_mmal_port *control;
1948 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
1950 + u32_value = ctrl->val;
1952 + return vchiq_mmal_port_parameter_set(dev->instance, control,
1953 + mmal_ctrl->mmal_id,
1954 + &u32_value, sizeof(u32_value));
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)
1963 + struct vchiq_mmal_component *camera;
1965 + camera = dev->component[MMAL_COMPONENT_CAMERA];
1967 + u32_value = ((ctrl->val % 360) / 90) * 90;
1969 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
1970 + mmal_ctrl->mmal_id,
1971 + &u32_value, sizeof(u32_value));
1975 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
1976 + mmal_ctrl->mmal_id,
1977 + &u32_value, sizeof(u32_value));
1981 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
1982 + mmal_ctrl->mmal_id,
1983 + &u32_value, sizeof(u32_value));
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)
1994 + struct vchiq_mmal_component *camera;
1996 + if (ctrl->id == V4L2_CID_HFLIP)
1997 + dev->hflip = ctrl->val;
1999 + dev->vflip = ctrl->val;
2001 + camera = dev->component[MMAL_COMPONENT_CAMERA];
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;
2010 + u32_value = MMAL_PARAM_MIRROR_NONE;
2012 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
2013 + mmal_ctrl->mmal_id,
2014 + &u32_value, sizeof(u32_value));
2018 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
2019 + mmal_ctrl->mmal_id,
2020 + &u32_value, sizeof(u32_value));
2024 + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
2025 + mmal_ctrl->mmal_id,
2026 + &u32_value, sizeof(u32_value));
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)
2037 + struct vchiq_mmal_port *control;
2039 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2041 + switch (ctrl->val) {
2042 + case V4L2_EXPOSURE_AUTO:
2043 + u32_value = MMAL_PARAM_EXPOSUREMODE_AUTO;
2046 + case V4L2_EXPOSURE_MANUAL:
2047 + u32_value = MMAL_PARAM_EXPOSUREMODE_OFF;
2050 + case V4L2_EXPOSURE_SHUTTER_PRIORITY:
2051 + u32_value = MMAL_PARAM_EXPOSUREMODE_SPORTS;
2054 + case V4L2_EXPOSURE_APERTURE_PRIORITY:
2055 + u32_value = MMAL_PARAM_EXPOSUREMODE_NIGHT;
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));
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)
2071 + struct vchiq_mmal_port *control;
2073 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2075 + switch (ctrl->val) {
2076 + case V4L2_EXPOSURE_METERING_AVERAGE:
2077 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
2080 + case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
2081 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
2084 + case V4L2_EXPOSURE_METERING_SPOT:
2085 + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
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;
2096 + return vchiq_mmal_port_parameter_set(dev->instance, control,
2097 + mmal_ctrl->mmal_id,
2098 + &u32_value, sizeof(u32_value));
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)
2106 + struct vchiq_mmal_port *control;
2108 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2110 + switch (ctrl->val) {
2111 + case V4L2_WHITE_BALANCE_MANUAL:
2112 + u32_value = MMAL_PARAM_AWBMODE_OFF;
2115 + case V4L2_WHITE_BALANCE_AUTO:
2116 + u32_value = MMAL_PARAM_AWBMODE_AUTO;
2119 + case V4L2_WHITE_BALANCE_INCANDESCENT:
2120 + u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT;
2123 + case V4L2_WHITE_BALANCE_FLUORESCENT:
2124 + u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT;
2127 + case V4L2_WHITE_BALANCE_FLUORESCENT_H:
2128 + u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN;
2131 + case V4L2_WHITE_BALANCE_HORIZON:
2132 + u32_value = MMAL_PARAM_AWBMODE_HORIZON;
2135 + case V4L2_WHITE_BALANCE_DAYLIGHT:
2136 + u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT;
2139 + case V4L2_WHITE_BALANCE_FLASH:
2140 + u32_value = MMAL_PARAM_AWBMODE_FLASH;
2143 + case V4L2_WHITE_BALANCE_CLOUDY:
2144 + u32_value = MMAL_PARAM_AWBMODE_CLOUDY;
2147 + case V4L2_WHITE_BALANCE_SHADE:
2148 + u32_value = MMAL_PARAM_AWBMODE_SHADE;
2153 + return vchiq_mmal_port_parameter_set(dev->instance, control,
2154 + mmal_ctrl->mmal_id,
2155 + &u32_value, sizeof(u32_value));
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)
2162 + int ret = -EINVAL;
2164 + struct vchiq_mmal_port *control;
2165 + struct mmal_parameter_imagefx_parameters imagefx;
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) {
2171 + v4l2_to_mmal_effects_values[i].mmal_effect;
2172 + imagefx.num_effect_params =
2173 + v4l2_to_mmal_effects_values[i].num_effect_params;
2175 + if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS)
2176 + imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS;
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];
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) {
2186 + v4l2_to_mmal_effects_values[i].u;
2188 + v4l2_to_mmal_effects_values[i].v;
2191 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2193 + ret = vchiq_mmal_port_parameter_set(
2194 + dev->instance, control,
2195 + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
2196 + &imagefx, sizeof(imagefx));
2200 + ret = vchiq_mmal_port_parameter_set(
2201 + dev->instance, control,
2202 + MMAL_PARAMETER_COLOUR_EFFECT,
2203 + &dev->colourfx, sizeof(dev->colourfx));
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);
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)
2221 + int ret = -EINVAL;
2222 + struct vchiq_mmal_port *control;
2224 + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
2226 + dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
2227 + dev->colourfx.enable = ctrl->val & 0xff;
2229 + ret = vchiq_mmal_port_parameter_set(dev->instance, control,
2230 + MMAL_PARAMETER_COLOUR_EFFECT,
2231 + &dev->colourfx, sizeof(dev->colourfx));
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);
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)
2245 + struct vchiq_mmal_port *encoder_out;
2247 + dev->capture.encode_bitrate = ctrl->val;
2249 + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
2251 + ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
2252 + mmal_ctrl->mmal_id,
2253 + &ctrl->val, sizeof(ctrl->val));
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)
2263 + struct vchiq_mmal_port *encoder_out;
2265 + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
2267 + dev->capture.encode_bitrate_mode = ctrl->val;
2268 + switch (ctrl->val) {
2270 + case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
2271 + bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
2273 + case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
2274 + bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
2278 + vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
2279 + mmal_ctrl->mmal_id,
2281 + sizeof(bitrate_mode));
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)
2290 + struct vchiq_mmal_port *jpeg_out;
2292 + jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
2294 + u32_value = ctrl->val;
2296 + return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out,
2297 + mmal_ctrl->mmal_id,
2298 + &u32_value, sizeof(u32_value));
2301 +static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
2303 + struct bm2835_mmal_dev *dev =
2304 + container_of(ctrl->handler, struct bm2835_mmal_dev,
2306 + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv;
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);
2315 + return mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
2318 +static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = {
2319 + .s_ctrl = bm2835_mmal_s_ctrl,
2324 +static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
2326 + V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD,
2327 + -100, 100, 0, 1, NULL,
2328 + MMAL_PARAMETER_SATURATION, &ctrl_set_rational
2331 + V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD,
2332 + -100, 100, 0, 1, NULL,
2333 + MMAL_PARAMETER_SHARPNESS, &ctrl_set_rational
2336 + V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD,
2337 + -100, 100, 0, 1, NULL,
2338 + MMAL_PARAMETER_CONTRAST, &ctrl_set_rational
2341 + V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD,
2342 + 0, 100, 50, 1, NULL,
2343 + MMAL_PARAMETER_BRIGHTNESS, &ctrl_set_rational
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
2351 + V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD,
2353 + MMAL_PARAMETER_VIDEO_STABILISATION, &ctrl_set_value
2356 + 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
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
2363 +/* todo this needs mixing in with set exposure
2365 + V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
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
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
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
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
2392 + V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD,
2393 + 0, 0xffff, 0x8080, 1, NULL,
2394 + MMAL_PARAMETER_COLOUR_EFFECT, &ctrl_set_colfx
2397 + V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD,
2398 + 0, 360, 0, 90, NULL,
2399 + MMAL_PARAMETER_ROTATION, &ctrl_set_rotate
2402 + V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD,
2404 + MMAL_PARAMETER_MIRROR, &ctrl_set_flip
2407 + V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD,
2409 + MMAL_PARAMETER_MIRROR, &ctrl_set_flip
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
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
2423 + V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD,
2426 + MMAL_PARAMETER_JPEG_Q_FACTOR, &ctrl_set_q_factor
2430 +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
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],
2446 +int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
2447 + struct v4l2_ctrl_handler *hdl)
2450 + const struct bm2835_mmal_v4l2_ctrl *ctrl;
2452 + v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT);
2454 + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2455 + ctrl = &v4l2_ctrls[c];
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);
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);
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);
2476 + case MMAL_CONTROL_TYPE_CLUSTER:
2477 + /* skip this entry when constructing controls */
2484 + dev->ctrls[c]->priv = (void *)ctrl;
2488 + pr_err("error adding control %d/%d id 0x%x\n", c,
2489 + V4L2_CTRL_COUNT, ctrl->id);
2490 + return hdl->error;
2493 + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
2494 + ctrl = &v4l2_ctrls[c];
2496 + switch (ctrl->type) {
2497 + case MMAL_CONTROL_TYPE_CLUSTER:
2498 + v4l2_ctrl_auto_cluster(ctrl->min,
2504 + case MMAL_CONTROL_TYPE_STD:
2505 + case MMAL_CONTROL_TYPE_STD_MENU:
2506 + case MMAL_CONTROL_TYPE_INT_MENU:
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
2518 +++ b/drivers/media/platform/bcm2835/mmal-common.h
2521 + * Broadcom BM2835 V4L2 driver
2523 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
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')
2541 +/** Special value signalling that time is not known */
2542 +#define MMAL_TIME_UNKNOWN (1LL<<63)
2544 +/* mapping between v4l and mmal video modes */
2547 + u32 fourcc; /* v4l2 format id */
2550 + u32 mmal_component; /* MMAL component index to be used to encode */
2553 +/* buffer for one video frame */
2554 +struct mmal_buffer {
2555 + /* v4l buffer data -- must be first */
2556 + struct vb2_buffer vb;
2558 + /* list of buffers available */
2559 + struct list_head list;
2561 + void *buffer; /* buffer pointer */
2562 + unsigned long buffer_size; /* size of allocated buffer */
2566 +struct mmal_colourfx {
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
2576 +++ b/drivers/media/platform/bcm2835/mmal-encodings.h
2579 + * Broadcom BM2835 V4L2 driver
2581 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
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')
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', ' ')
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')
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.
2641 +#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S', 'A', 'N', 'D')
2643 +/** VideoCore opaque image format, image handles are returned to
2644 + * the host but not the actual image data.
2646 +#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V')
2648 +/** An EGL image handle
2650 +#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I')
2654 +/** \name Pre-defined audio encodings */
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')
2663 +/* Pre-defined H264 encoding variants */
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
2675 +++ b/drivers/media/platform/bcm2835/mmal-msg-common.h
2678 + * Broadcom BM2835 V4L2 driver
2680 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
2692 +#ifndef MMAL_MSG_COMMON_H
2693 +#define MMAL_MSG_COMMON_H
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 */
2715 + s32 x; /**< x coordinate (from left) */
2716 + s32 y; /**< y coordinate (from top) */
2717 + s32 width; /**< width */
2718 + s32 height; /**< height */
2721 +struct mmal_rational {
2722 + s32 num; /**< Numerator */
2723 + s32 den; /**< Denominator */
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
2731 +++ b/drivers/media/platform/bcm2835/mmal-msg-format.h
2734 + * Broadcom BM2835 V4L2 driver
2736 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
2748 +#ifndef MMAL_MSG_FORMAT_H
2749 +#define MMAL_MSG_FORMAT_H
2751 +#include "mmal-msg-common.h"
2753 +/* MMAL_ES_FORMAT_T */
2756 +struct mmal_audio_format {
2757 + u32 channels; /**< Number of audio channels */
2758 + u32 sample_rate; /**< Sample rate */
2760 + u32 bits_per_sample; /**< Bits per sample */
2761 + u32 block_align; /**< Size of a block of data */
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 */
2771 + /* FourCC specifying the color space of the video stream. See the
2772 + * \ref MmalColorSpace "pre-defined color spaces" for some examples.
2777 +struct mmal_subpicture_format {
2782 +union mmal_es_specific_format {
2783 + struct mmal_audio_format audio;
2784 + struct mmal_video_format video;
2785 + struct mmal_subpicture_format subpicture;
2788 +/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
2789 +struct mmal_es_format {
2790 + u32 type; /* enum mmal_es_type */
2792 + u32 encoding; /* FourCC specifying encoding of the elementary stream.*/
2793 + u32 encoding_variant; /* FourCC specifying the specific
2794 + * encoding variant of the elementary
2798 + union mmal_es_specific_format *es; /* TODO: pointers in
2799 + * message serialisation?!?
2802 + * information for the
2803 + * elementary stream
2806 + u32 bitrate; /**< Bitrate in bits per second */
2807 + u32 flags; /**< Flags describing properties of the elementary stream. */
2809 + u32 extradata_size; /**< Size of the codec specific data */
2810 + u8 *extradata; /**< Codec specific data */
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
2818 +++ b/drivers/media/platform/bcm2835/mmal-msg-port.h
2821 + * Broadcom BM2835 V4L2 driver
2823 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
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 */
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
2856 +/* mmal port structure (MMAL_PORT_T)
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.
2864 + void *priv; /* Private member used by the framework */
2865 + const char *name; /* Port name. Used for debugging purposes (RO) */
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) */
2871 + u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
2872 + struct mmal_es_format *format; /* Format of the elementary stream */
2874 + u32 buffer_num_min; /* Minimum number of buffers the port
2875 + * requires (RO). This is set by the
2879 + u32 buffer_size_min; /* Minimum size of buffers the port
2880 + * requires (RO). This is set by the
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
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.
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.
2907 + u32 buffer_num; /* Actual number of buffers the port will use.
2908 + * This is set by the client.
2911 + u32 buffer_size; /* Actual maximum size of the buffers that
2912 + * will be sent to the port. This is set by
2916 + void *component; /* Component this port belongs to (Read Only) */
2918 + void *userdata; /* Field reserved for use by the client */
2920 + u32 capabilities; /* Flags describing the capabilities of a
2921 + * port (RO). Bitwise combination of \ref
2922 + * portcapabilities "Port capabilities"
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
2931 +++ b/drivers/media/platform/bcm2835/mmal-msg.h
2934 + * Broadcom BM2835 V4L2 driver
2936 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
2948 +/* all the data structures which serialise the MMAL protocol. note
2949 + * these are directly mapped onto the recived message data.
2951 + * BEWARE: They seem to *assume* pointers are u32 and that there is no
2952 + * structure padding!
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
2960 +#define VC_MMAL_VER 15
2961 +#define VC_MMAL_MIN_VER 10
2962 +#define VC_MMAL_SERVER_NAME MAKE_FOURCC("mmal")
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
2969 +#include "mmal-msg-common.h"
2970 +#include "mmal-msg-format.h"
2971 +#include "mmal-msg-port.h"
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
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*/
3014 +struct mmal_msg_header {
3016 + u32 type; /** enum mmal_msg_type */
3018 + /* Opaque handle to the control service */
3019 + struct mmal_control_service *control_service;
3021 + struct mmal_msg_context *context; /** a u32 per message context */
3022 + u32 status; /** The status of the vchiq operation */
3026 +/* Send from VC to host to report version */
3027 +struct mmal_msg_version {
3034 +/* request to VC to create component */
3035 +struct mmal_msg_component_create {
3036 + void *client_component; /* component context */
3038 + u32 pid; /* For debug */
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?
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 */
3052 +/* request to VC to destroy a component */
3053 +struct mmal_msg_component_destroy {
3054 + u32 component_handle;
3057 +struct mmal_msg_component_destroy_reply {
3058 + u32 status; /** The component destruction status */
3062 +/* request and reply to VC to enable a component */
3063 +struct mmal_msg_component_enable {
3064 + u32 component_handle;
3067 +struct mmal_msg_component_enable_reply {
3068 + u32 status; /** The component enable status */
3072 +/* request and reply to VC to disable a component */
3073 +struct mmal_msg_component_disable {
3074 + u32 component_handle;
3077 +struct mmal_msg_component_disable_reply {
3078 + u32 status; /** The component disable status */
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 */
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 */
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];
3113 +/* reply from VC to port info set request */
3114 +struct mmal_msg_port_info_set_reply {
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];
3128 +/* port action requests that take a mmal_port as a parameter */
3129 +struct mmal_msg_port_action_port {
3130 + u32 component_handle;
3132 + u32 action; /* enum mmal_msg_port_action_type */
3133 + struct mmal_port port;
3136 +/* port action requests that take handles as a parameter */
3137 +struct mmal_msg_port_action_handle {
3138 + u32 component_handle;
3140 + u32 action; /* enum mmal_msg_port_action_type */
3141 + u32 connect_component_handle;
3142 + u32 connect_port_handle;
3145 +struct mmal_msg_port_action_reply {
3146 + u32 status; /** The port action operation status */
3152 +/* MMAL buffer transfer */
3154 +/** Size of space reserved in a buffer message for short messages. */
3155 +#define MMAL_VC_SHORT_DATA 128
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
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)
3187 +struct mmal_driver_buffer {
3189 + u32 component_handle;
3191 + void *client_context;
3194 +/* buffer header */
3195 +struct mmal_buffer_header {
3196 + struct mmal_buffer_header *next; /* next header */
3197 + void *priv; /* framework private data */
3210 +struct mmal_buffer_header_type_specific {
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.
3227 + /* control data */
3228 + struct mmal_driver_buffer drvbuf;
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;
3235 + s32 has_reference;
3237 + /** allows short data to be xfered in control message */
3238 + u32 payload_in_message;
3239 + u8 short_data[MMAL_VC_SHORT_DATA];
3243 +/* port parameter setting */
3245 +#define MMAL_WORKER_PORT_PARAMETER_SPACE 96
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];
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?
3261 +/* port parameter getting */
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 */
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];
3277 +/* event messages */
3278 +#define MMAL_WORKER_EVENT_SPACE 256
3280 +struct mmal_msg_event_to_host {
3281 + void *client_component; /* component context */
3288 + u8 data[MMAL_WORKER_EVENT_SPACE];
3289 + struct mmal_buffer_header *delayed_buffer;
3292 +/* all mmal messages are serialised through this structure */
3295 + struct mmal_msg_header h;
3298 + struct mmal_msg_version version;
3300 + struct mmal_msg_component_create component_create;
3301 + struct mmal_msg_component_create_reply component_create_reply;
3303 + struct mmal_msg_component_destroy component_destroy;
3304 + struct mmal_msg_component_destroy_reply component_destroy_reply;
3306 + struct mmal_msg_component_enable component_enable;
3307 + struct mmal_msg_component_enable_reply component_enable_reply;
3309 + struct mmal_msg_component_disable component_disable;
3310 + struct mmal_msg_component_disable_reply component_disable_reply;
3312 + struct mmal_msg_port_info_get port_info_get;
3313 + struct mmal_msg_port_info_get_reply port_info_get_reply;
3315 + struct mmal_msg_port_info_set port_info_set;
3316 + struct mmal_msg_port_info_set_reply port_info_set_reply;
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;
3322 + struct mmal_msg_buffer_from_host buffer_from_host;
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;
3332 + struct mmal_msg_event_to_host event_to_host;
3334 + u8 payload[MMAL_MSG_MAX_PAYLOAD];
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
3341 +++ b/drivers/media/platform/bcm2835/mmal-parameters.h
3344 + * Broadcom BM2835 V4L2 driver
3346 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
3358 +/* common parameters */
3360 +/** @name Parameter groups
3361 + * Parameters are divided into groups, and then allocated sequentially within
3362 + * a group using an enum.
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)
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 */
3386 + /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
3387 + MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
3389 + /** MMAL_PARAMETER_BOOLEAN_T */
3390 + MMAL_PARAMETER_ZERO_COPY,
3392 + /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
3393 + MMAL_PARAMETER_BUFFER_REQUIREMENTS,
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 */
3405 +/* camera parameters */
3407 +enum mmal_parameter_camera_type {
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 */
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 */
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 */
3465 + MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
3466 + MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3468 + /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
3469 + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
3471 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3472 + MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
3474 + /** @ref MMAL_PARAMETER_UINT32_T */
3475 + MMAL_PARAMETER_CAMERA_MIN_ISO,
3477 + /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
3478 + MMAL_PARAMETER_CAMERA_USE_CASE,
3480 + /**< @ref MMAL_PARAMETER_BOOLEAN_T */
3481 + MMAL_PARAMETER_CAPTURE_STATS_PASS,
3483 + /** @ref MMAL_PARAMETER_UINT32_T */
3484 + MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
3486 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3487 + MMAL_PARAMETER_ENABLE_REGISTER_FILE,
3489 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3490 + MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
3492 + /** @ref MMAL_PARAMETER_CONFIGFILE_T */
3493 + MMAL_PARAMETER_CONFIGFILE_REGISTERS,
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 */
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 */
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
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.
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 */
3526 + u32 stills_yuv422; /* Allow YUV422 stills capture */
3527 + u32 one_shot_stills; /* Continuous or one shot stills captures. */
3529 + u32 max_preview_video_w; /* Max size of the preview or video
3532 + u32 max_preview_video_h;
3533 + u32 num_preview_video_frames;
3535 + /** Sets the height of the circular buffer for stills capture. */
3536 + u32 stills_capture_circular_buffer_height;
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.
3543 + u32 fast_preview_resume;
3545 + /** Selects algorithm for timestamping frames if
3546 + * there is no clock component connected.
3547 + * enum mmal_parameter_camera_config_timestamp_mode
3549 + s32 use_stc_timestamp;
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,
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,
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,
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,
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
3624 +/* video parameters */
3626 +enum mmal_parameter_video_type {
3627 + /** @ref MMAL_DISPLAYREGION_T */
3628 + MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
3630 + /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
3631 + MMAL_PARAMETER_SUPPORTED_PROFILES,
3633 + /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
3634 + MMAL_PARAMETER_PROFILE,
3636 + /** @ref MMAL_PARAMETER_UINT32_T */
3637 + MMAL_PARAMETER_INTRAPERIOD,
3639 + /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
3640 + MMAL_PARAMETER_RATECONTROL,
3642 + /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
3643 + MMAL_PARAMETER_NALUNITFORMAT,
3645 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3646 + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
3648 + /** @ref MMAL_PARAMETER_UINT32_T.
3649 + * Setting the value to zero resets to the default (one slice per frame).
3651 + MMAL_PARAMETER_MB_ROWS_PER_SLICE,
3653 + /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
3654 + MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
3656 + /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
3657 + MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
3659 + /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
3660 + MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
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,
3667 + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3668 + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
3670 + /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
3671 + MMAL_PARAMETER_VIDEO_BIT_RATE,
3673 + /** @ref MMAL_PARAMETER_FRAME_RATE_T */
3674 + MMAL_PARAMETER_VIDEO_FRAME_RATE,
3676 + /** @ref MMAL_PARAMETER_UINT32_T. */
3677 + MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
3679 + /** @ref MMAL_PARAMETER_UINT32_T. */
3680 + MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
3682 + /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
3683 + MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
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.
3690 + MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
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.
3696 + MMAL_PARAMETER_VIDEO_ALIGN_VERT,
3698 + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3699 + MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
3701 + /** @ref MMAL_PARAMETER_UINT32_T. */
3702 + MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
3704 + /**< @ref MMAL_PARAMETER_UINT32_T. */
3705 + MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
3707 + /**< @ref MMAL_PARAMETER_UINT32_T. */
3708 + MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
3710 + /** @ref MMAL_PARAMETER_UINT32_T */
3711 + MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
3713 + /** @ref MMAL_PARAMETER_UINT32_T. */
3714 + MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
3716 + /* H264 specific parameters */
3718 + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3719 + MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
3721 + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3722 + MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
3724 + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
3725 + MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
3727 + /** @ref MMAL_PARAMETER_UINT32_T. */
3728 + MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
3730 + /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
3731 + MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
3733 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3734 + MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
3736 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3737 + MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
3739 + /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
3740 + MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
3742 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3743 + MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
3745 + /** @ref MMAL_PARAMETER_BOOLEAN_T */
3746 + MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
3748 + /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
3749 + MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
3751 + /** @ref MMAL_PARAMETER_BYTES_T */
3752 + MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3
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,
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,
3774 +enum mmal_parameter_displaymode {
3775 + MMAL_DISPLAY_MODE_FILL = 0,
3776 + MMAL_DISPLAY_MODE_LETTERBOX = 1,
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,
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
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.
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
3816 + /** Indicates any rotation or flipping used to map frames onto
3817 + * the natural display orientation.
3819 + u32 transform; /* enum mmal_parameter_displaytransform */
3821 + /** Where to display the frame within the screen, if
3822 + * fullscreen is zero.
3824 + struct vchiq_mmal_rect dest_rect;
3826 + /** Indicates which area of the frame to display. If all
3827 + * values are zero, the whole frame will be used.
3829 + struct vchiq_mmal_rect src_rect;
3831 + /** If set to non-zero, indicates that any display scaling
3832 + * should disregard the aspect ratio of the frame region being
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
3845 + u32 mode; /* enum mmal_parameter_displaymode */
3847 + /** If non-zero, defines the width of a source pixel relative
3848 + * to \code pixel_y \endcode. If zero, then pixels default to
3853 + /** If non-zero, defines the height of a source pixel relative
3854 + * to \code pixel_x \endcode. If zero, then pixels default to
3859 + /** Sets the relative depth of the images, with greater values
3860 + * being in front of smaller values.
3864 + /** Set to non-zero to ensure copy protection is used on
3867 + s32 copyprotect_required;
3869 + /** Level of opacity of the layer, where zero is fully
3870 + * transparent and 255 is fully opaque.
3875 +#define MMAL_MAX_IMAGEFX_PARAMETERS 5
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];
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
3886 +++ b/drivers/media/platform/bcm2835/mmal-vchiq.c
3889 + * Broadcom BM2835 V4L2 driver
3891 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
3902 + * V4L2 driver MMAL vchiq interface code
3905 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
3917 +#include "mmal-common.h"
3918 +#include "mmal-vchiq.h"
3919 +#include "mmal-msg.h"
3921 +#define USE_VCHIQ_ARM
3922 +#include "interface/vchi/vchi.h"
3924 +/* maximum number of components supported */
3925 +#define VCHIQ_MMAL_MAX_COMPONENTS 4
3927 +/*#define FULL_MSG_DUMP 1*/
3930 +static const char *const msg_type_names[] = {
3935 + "COMPONENT_CREATE",
3936 + "COMPONENT_DESTROY",
3937 + "COMPONENT_ENABLE",
3938 + "COMPONENT_DISABLE",
3942 + "BUFFER_FROM_HOST",
3945 + "PORT_PARAMETER_SET",
3946 + "PORT_PARAMETER_GET",
3948 + "GET_CORE_STATS_FOR_PORT",
3949 + "OPAQUE_ALLOCATOR",
3952 + "OPAQUE_ALLOCATOR_DESC",
3955 + "BUFFER_FROM_HOST_ZEROLEN",
3961 +static const char *const port_action_type_names[] = {
3968 + "SET_REQUIREMENTS",
3972 +#if defined(FULL_MSG_DUMP)
3973 +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
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, \
3980 + sizeof(struct mmal_msg_header), 1); \
3981 + print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
3983 + ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
3984 + (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
3987 +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
3989 + pr_debug(TITLE" type:%s(%d) length:%d\n", \
3990 + msg_type_names[(MSG)->h.type], \
3991 + (MSG)->h.type, (MSG_LEN)); \
3995 +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
3998 +/* normal message context */
3999 +struct mmal_msg_context {
4002 + /* work struct for defered callback - must come first */
4003 + struct work_struct work;
4004 + /* mmal instance */
4005 + struct vchiq_mmal_instance *instance;
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 */
4014 + /* Presentation and Decode timestamps */
4018 + int status; /* context status */
4020 + } bulk; /* bulk data */
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 */
4029 + /* completion upon reply */
4030 + struct completion cmplt;
4031 + } sync; /* synchronous response */
4036 +struct vchiq_mmal_instance {
4037 + VCHI_SERVICE_HANDLE_T handle;
4039 + /* ensure serialised access to service */
4040 + struct mutex vchiq_mutex;
4042 + /* ensure serialised access to bulk operations */
4043 + struct mutex bulk_mutex;
4045 + /* vmalloc page to receive scratch bulk xfers into */
4046 + void *bulk_scratch;
4048 + /* component to use next */
4049 + int component_idx;
4050 + struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
4053 +static struct mmal_msg_context *get_msg_context(struct vchiq_mmal_instance
4056 + struct mmal_msg_context *msg_context;
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));
4062 + return msg_context;
4065 +static void release_msg_context(struct mmal_msg_context *msg_context)
4067 + kfree(msg_context);
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)
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);
4082 +/* workqueue scheduled callback
4084 + * we do this because it is important we do not call any other vchiq
4085 + * sync calls from witin the message delivery thread
4087 +static void buffer_work_cb(struct work_struct *work)
4089 + struct mmal_msg_context *msg_context = (struct mmal_msg_context *)work;
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);
4100 + /* release message context */
4101 + release_msg_context(msg_context);
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)
4109 + unsigned long rd_len;
4110 + unsigned long flags = 0;
4113 + /* bulk mutex stops other bulk operations while we have a
4114 + * receive in progress - released in callback
4116 + ret = mutex_lock_interruptible(&instance->bulk_mutex);
4120 + rd_len = msg->u.buffer_from_host.buffer_header.length;
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");
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?
4138 + mutex_unlock(&instance->bulk_mutex);
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);
4148 + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
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?
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;
4166 + // only need to flush L1 cache here, as VCHIQ takes care of the L2
4168 + __cpuc_flush_dcache_area(msg_context->u.bulk.buffer->buffer, rd_len);
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
4177 + (rd_len + 3) & ~3,
4178 + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
4179 + VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
4182 + vchi_service_release(instance->handle);
4185 + /* callback will not be clearing the mutex */
4186 + mutex_unlock(&instance->bulk_mutex);
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)
4198 + /* bulk mutex stops other bulk operations while we have a
4199 + * receive in progress - released in callback
4201 + ret = mutex_lock_interruptible(&instance->bulk_mutex);
4205 + /* zero length indicates this was a dummy transfer */
4206 + msg_context->u.bulk.buffer_used = 0;
4208 + /* queue the bulk submission */
4209 + vchi_service_use(instance->handle);
4211 + ret = vchi_bulk_queue_receive(instance->handle,
4212 + instance->bulk_scratch,
4214 + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
4215 + VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
4218 + vchi_service_release(instance->handle);
4221 + /* callback will not be clearing the mutex */
4222 + mutex_unlock(&instance->bulk_mutex);
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)
4233 + unsigned long flags = 0;
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");
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
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);
4256 + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
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);
4262 + msg_context->u.bulk.buffer_used =
4263 + msg->u.buffer_from_host.payload_in_message;
4268 +/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
4270 +buffer_from_host(struct vchiq_mmal_instance *instance,
4271 + struct vchiq_mmal_port *port, struct mmal_buffer *buf)
4273 + struct mmal_msg_context *msg_context;
4274 + struct mmal_msg m;
4277 + pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
4279 + /* bulk mutex stops other bulk operations while we
4280 + * have a receive in progress
4282 + if (mutex_lock_interruptible(&instance->bulk_mutex))
4286 + msg_context = get_msg_context(instance);
4287 + if (msg_context == NULL)
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;
4296 + /* initialise work structure ready to schedule callback */
4297 + INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
4299 + /* prep the buffer from host message */
4300 + memset(&m, 0xbc, sizeof(m)); /* just to make debug clearer */
4302 + m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
4303 + m.h.magic = MMAL_MAGIC;
4304 + m.h.context = msg_context;
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;
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;
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));
4327 + /* no payload in message */
4328 + m.u.buffer_from_host.payload_in_message = 0;
4330 + vchi_service_use(instance->handle);
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);
4338 + release_msg_context(msg_context);
4339 + /* todo: is this correct error value? */
4342 + vchi_service_release(instance->handle);
4344 + mutex_unlock(&instance->bulk_mutex);
4349 +/* submit a buffer to the mmal sevice
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
4355 +static int port_buffer_from_host(struct vchiq_mmal_instance *instance,
4356 + struct vchiq_mmal_port *port)
4359 + struct mmal_buffer *buf;
4360 + unsigned long flags = 0;
4362 + if (!port->enabled)
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);
4373 + buf = list_entry(port->buffers.next, struct mmal_buffer, list);
4375 + spin_unlock_irqrestore(&port->slock, flags);
4377 + /* issue buffer to mmal service */
4378 + ret = buffer_from_host(instance, port, buf);
4380 + pr_err("adding buffer header failed\n");
4381 + /* todo: how should this be dealt with */
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)
4391 + struct mmal_msg_context *msg_context;
4393 + pr_debug("buffer_to_host_cb: instance:%p msg:%p msg_len:%d\n",
4394 + instance, msg, msg_len);
4396 + if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
4397 + msg_context = msg->u.buffer_from_host.drvbuf.client_context;
4399 + pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
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);
4407 + msg_context->u.bulk.status = msg->h.status;
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
4420 + /* do callback with empty buffer - not EOS though */
4421 + msg_context->u.bulk.status = 0;
4422 + msg_context->u.bulk.buffer_used = 0;
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
4433 + /* failed to submit buffer, this will end badly */
4434 + pr_err("error %d on bulk submission\n",
4435 + msg_context->u.bulk.status);
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,
4443 + pr_err("message with invalid short payload\n");
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;
4451 + /* replace the buffer header */
4452 + port_buffer_from_host(instance, msg_context->u.bulk.port);
4454 + /* schedule the port callback */
4455 + schedule_work(&msg_context->u.bulk.work);
4458 +static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
4459 + struct mmal_msg_context *msg_context)
4461 + /* bulk receive operation complete */
4462 + mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex);
4464 + /* replace the buffer header */
4465 + port_buffer_from_host(msg_context->u.bulk.instance,
4466 + msg_context->u.bulk.port);
4468 + msg_context->u.bulk.status = 0;
4470 + /* schedule the port callback */
4471 + schedule_work(&msg_context->u.bulk.work);
4474 +static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
4475 + struct mmal_msg_context *msg_context)
4477 + pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
4479 + /* bulk receive operation complete */
4480 + mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex);
4482 + /* replace the buffer header */
4483 + port_buffer_from_host(msg_context->u.bulk.instance,
4484 + msg_context->u.bulk.port);
4486 + msg_context->u.bulk.status = -EINTR;
4488 + schedule_work(&msg_context->u.bulk.work);
4491 +/* incoming event service callback */
4492 +static void service_callback(void *param,
4493 + const VCHI_CALLBACK_REASON_T reason,
4496 + struct vchiq_mmal_instance *instance = param;
4499 + struct mmal_msg *msg;
4500 + VCHI_HELD_MSG_T msg_handle;
4503 + pr_err("Message callback passed NULL instance\n");
4508 + case VCHI_CALLBACK_MSG_AVAILABLE:
4509 + status = vchi_msg_hold(instance->handle, (void **)&msg,
4510 + &msg_len, VCHI_FLAGS_NONE, &msg_handle);
4512 + pr_err("Unable to dequeue a message (%d)\n", status);
4516 + DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
4518 + /* handling is different for buffer messages */
4519 + switch (msg->h.type) {
4521 + case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
4522 + vchi_held_msg_release(&msg_handle);
4525 + case MMAL_MSG_TYPE_EVENT_TO_HOST:
4526 + event_to_host_cb(instance, msg, msg_len);
4527 + vchi_held_msg_release(&msg_handle);
4531 + case MMAL_MSG_TYPE_BUFFER_TO_HOST:
4532 + buffer_to_host_cb(instance, msg, msg_len);
4533 + vchi_held_msg_release(&msg_handle);
4537 + /* messages dependant on header context to complete */
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
4545 + if (msg->h.context == NULL) {
4546 + pr_err("received message context was null!\n");
4547 + vchi_held_msg_release(&msg_handle);
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;
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
4565 + /* complete message so caller knows it happened */
4566 + complete(&msg->h.context->u.sync.cmplt);
4572 + case VCHI_CALLBACK_BULK_RECEIVED:
4573 + bulk_receive_cb(instance, bulk_ctx);
4576 + case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
4577 + bulk_abort_cb(instance, bulk_ctx);
4580 + case VCHI_CALLBACK_SERVICE_CLOSED:
4581 + /* TODO: consider if this requires action if received when
4582 + * driver is not explicitly closing the service
4587 + pr_err("Received unhandled message reason %d\n", reason);
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)
4598 + struct mmal_msg_context msg_context;
4601 + /* payload size must not cause message to exceed max size */
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)));
4609 + init_completion(&msg_context.u.sync.cmplt);
4611 + msg->h.magic = MMAL_MAGIC;
4612 + msg->h.context = &msg_context;
4613 + msg->h.status = 0;
4615 + DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
4616 + ">>> sync message");
4618 + vchi_service_use(instance->handle);
4620 + ret = vchi_msg_queue(instance->handle,
4622 + sizeof(struct mmal_msg_header) + payload_len,
4623 + VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
4625 + vchi_service_release(instance->handle);
4628 + pr_err("error %d queuing message\n", ret);
4632 + ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, HZ);
4634 + pr_err("error %d waiting for sync completion\n", ret);
4637 + /* todo: what happens if the message arrives after aborting */
4641 + *msg_out = msg_context.u.sync.msg;
4642 + *msg_handle_out = msg_context.u.sync.msg_handle;
4647 +static void dump_port_info(struct vchiq_mmal_port *port)
4649 + pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
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);
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);
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);
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);
4668 + pr_debug(" bitrate:%d flags:0x%x\n",
4669 + port->format.bitrate, port->format.flags);
4671 + if (port->format.type == MMAL_ES_TYPE_VIDEO) {
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);
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);
4688 +static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
4691 + /* todo do readonly fields need setting at all? */
4692 + p->type = port->type;
4693 + p->index = port->index;
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;
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;
4708 +static int port_info_set(struct vchiq_mmal_instance *instance,
4709 + struct vchiq_mmal_port *port)
4712 + struct mmal_msg m;
4713 + struct mmal_msg *rmsg;
4714 + VCHI_HELD_MSG_T rmsg_handle;
4716 + pr_debug("setting port info port %p\n", port);
4719 + dump_port_info(port);
4721 + m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
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;
4727 + port_to_mmal_msg(port, &m.u.port_info_set.port);
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;
4737 + memcpy(&m.u.port_info_set.es, &port->es,
4738 + sizeof(union mmal_es_specific_format));
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);
4744 + ret = send_synchronous_mmal_msg(instance, &m,
4745 + sizeof(m.u.port_info_set),
4746 + &rmsg, &rmsg_handle);
4750 + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
4751 + /* got an unexpected message type in reply */
4756 + /* return operation status */
4757 + ret = -rmsg->u.port_info_get_reply.status;
4759 + pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
4760 + port->component->handle, port->handle);
4763 + vchi_held_msg_release(&rmsg_handle);
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)
4774 + struct mmal_msg m;
4775 + struct mmal_msg *rmsg;
4776 + VCHI_HELD_MSG_T rmsg_handle;
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;
4784 + ret = send_synchronous_mmal_msg(instance, &m,
4785 + sizeof(m.u.port_info_get),
4786 + &rmsg, &rmsg_handle);
4790 + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
4791 + /* got an unexpected message type in reply */
4796 + /* return operation status */
4797 + ret = -rmsg->u.port_info_get_reply.status;
4798 + if (ret != MMAL_MSG_STATUS_SUCCESS)
4801 + if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
4802 + port->enabled = false;
4804 + port->enabled = true;
4806 + /* copy the values out of the message */
4807 + port->handle = rmsg->u.port_info_get_reply.port_handle;
4809 + /* port type and index cached to use on port info set becuase
4810 + * it does not use a port handle
4812 + port->type = rmsg->u.port_info_get_reply.port_type;
4813 + port->index = rmsg->u.port_info_get_reply.port_index;
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;
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;
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;
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;
4839 + /* elementry stream format */
4841 + &rmsg->u.port_info_get_reply.es,
4842 + sizeof(union mmal_es_specific_format));
4843 + port->format.es = &port->es;
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);
4851 + pr_debug("received port info\n");
4852 + dump_port_info(port);
4856 + pr_debug("%s:result:%d component:0x%x port:%d\n",
4857 + __func__, ret, port->component->handle, port->handle);
4859 + vchi_held_msg_release(&rmsg_handle);
4864 +/* create comonent on vc */
4865 +static int create_component(struct vchiq_mmal_instance *instance,
4866 + struct vchiq_mmal_component *component,
4870 + struct mmal_msg m;
4871 + struct mmal_msg *rmsg;
4872 + VCHI_HELD_MSG_T rmsg_handle;
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));
4880 + ret = send_synchronous_mmal_msg(instance, &m,
4881 + sizeof(m.u.component_create),
4882 + &rmsg, &rmsg_handle);
4886 + if (rmsg->h.type != m.h.type) {
4887 + /* got an unexpected message type in reply */
4892 + ret = -rmsg->u.component_create_reply.status;
4893 + if (ret != MMAL_MSG_STATUS_SUCCESS)
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;
4902 + pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
4903 + component->handle,
4904 + component->inputs, component->outputs, component->clocks);
4907 + vchi_held_msg_release(&rmsg_handle);
4912 +/* destroys a component on vc */
4913 +static int destroy_component(struct vchiq_mmal_instance *instance,
4914 + struct vchiq_mmal_component *component)
4917 + struct mmal_msg m;
4918 + struct mmal_msg *rmsg;
4919 + VCHI_HELD_MSG_T rmsg_handle;
4921 + m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
4922 + m.u.component_destroy.component_handle = component->handle;
4924 + ret = send_synchronous_mmal_msg(instance, &m,
4925 + sizeof(m.u.component_destroy),
4926 + &rmsg, &rmsg_handle);
4930 + if (rmsg->h.type != m.h.type) {
4931 + /* got an unexpected message type in reply */
4936 + ret = -rmsg->u.component_destroy_reply.status;
4940 + vchi_held_msg_release(&rmsg_handle);
4945 +/* enable a component on vc */
4946 +static int enable_component(struct vchiq_mmal_instance *instance,
4947 + struct vchiq_mmal_component *component)
4950 + struct mmal_msg m;
4951 + struct mmal_msg *rmsg;
4952 + VCHI_HELD_MSG_T rmsg_handle;
4954 + m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
4955 + m.u.component_enable.component_handle = component->handle;
4957 + ret = send_synchronous_mmal_msg(instance, &m,
4958 + sizeof(m.u.component_enable),
4959 + &rmsg, &rmsg_handle);
4963 + if (rmsg->h.type != m.h.type) {
4964 + /* got an unexpected message type in reply */
4969 + ret = -rmsg->u.component_enable_reply.status;
4972 + vchi_held_msg_release(&rmsg_handle);
4977 +/* disable a component on vc */
4978 +static int disable_component(struct vchiq_mmal_instance *instance,
4979 + struct vchiq_mmal_component *component)
4982 + struct mmal_msg m;
4983 + struct mmal_msg *rmsg;
4984 + VCHI_HELD_MSG_T rmsg_handle;
4986 + m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
4987 + m.u.component_disable.component_handle = component->handle;
4989 + ret = send_synchronous_mmal_msg(instance, &m,
4990 + sizeof(m.u.component_disable),
4991 + &rmsg, &rmsg_handle);
4995 + if (rmsg->h.type != m.h.type) {
4996 + /* got an unexpected message type in reply */
5001 + ret = -rmsg->u.component_disable_reply.status;
5005 + vchi_held_msg_release(&rmsg_handle);
5010 +/* get version of mmal implementation */
5011 +static int get_version(struct vchiq_mmal_instance *instance,
5012 + u32 *major_out, u32 *minor_out)
5015 + struct mmal_msg m;
5016 + struct mmal_msg *rmsg;
5017 + VCHI_HELD_MSG_T rmsg_handle;
5019 + m.h.type = MMAL_MSG_TYPE_GET_VERSION;
5021 + ret = send_synchronous_mmal_msg(instance, &m,
5022 + sizeof(m.u.version),
5023 + &rmsg, &rmsg_handle);
5027 + if (rmsg->h.type != m.h.type) {
5028 + /* got an unexpected message type in reply */
5033 + *major_out = rmsg->u.version.major;
5034 + *minor_out = rmsg->u.version.minor;
5037 + vchi_held_msg_release(&rmsg_handle);
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)
5048 + struct mmal_msg m;
5049 + struct mmal_msg *rmsg;
5050 + VCHI_HELD_MSG_T rmsg_handle;
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;
5057 + port_to_mmal_msg(port, &m.u.port_action_port.port);
5059 + ret = send_synchronous_mmal_msg(instance, &m,
5060 + sizeof(m.u.port_action_port),
5061 + &rmsg, &rmsg_handle);
5065 + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
5066 + /* got an unexpected message type in reply */
5071 + ret = -rmsg->u.port_action_reply.status;
5073 + pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
5075 + ret, port->component->handle, port->handle,
5076 + port_action_type_names[action_type], action_type);
5079 + vchi_held_msg_release(&rmsg_handle);
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)
5092 + struct mmal_msg m;
5093 + struct mmal_msg *rmsg;
5094 + VCHI_HELD_MSG_T rmsg_handle;
5096 + m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
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;
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;
5106 + ret = send_synchronous_mmal_msg(instance, &m,
5107 + sizeof(m.u.port_action_handle),
5108 + &rmsg, &rmsg_handle);
5112 + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
5113 + /* got an unexpected message type in reply */
5118 + ret = -rmsg->u.port_action_reply.status;
5120 + pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)" \
5121 + " connect component:0x%x connect port:%d\n",
5123 + ret, port->component->handle, port->handle,
5124 + port_action_type_names[action_type],
5125 + action_type, connect_component_handle, connect_port_handle);
5128 + vchi_held_msg_release(&rmsg_handle);
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)
5138 + struct mmal_msg m;
5139 + struct mmal_msg *rmsg;
5140 + VCHI_HELD_MSG_T rmsg_handle;
5142 + m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
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);
5150 + ret = send_synchronous_mmal_msg(instance, &m,
5151 + (4 * sizeof(u32)) + value_size,
5152 + &rmsg, &rmsg_handle);
5156 + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
5157 + /* got an unexpected message type in reply */
5162 + ret = -rmsg->u.port_parameter_set_reply.status;
5164 + pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
5166 + ret, port->component->handle, port->handle, parameter_id);
5169 + vchi_held_msg_release(&rmsg_handle);
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)
5179 + struct mmal_msg m;
5180 + struct mmal_msg *rmsg;
5181 + VCHI_HELD_MSG_T rmsg_handle;
5183 + m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
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;
5190 + ret = send_synchronous_mmal_msg(instance, &m,
5192 + mmal_msg_port_parameter_get),
5193 + &rmsg, &rmsg_handle);
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);
5204 + ret = -rmsg->u.port_parameter_get_reply.status;
5206 + /* Copy only as much as we have space for
5207 + * but report true size of parameter
5209 + memcpy(value, &rmsg->u.port_parameter_get_reply.value,
5211 + *value_size = rmsg->u.port_parameter_get_reply.size;
5213 + memcpy(value, &rmsg->u.port_parameter_get_reply.value,
5214 + rmsg->u.port_parameter_get_reply.size);
5216 + pr_info("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
5217 + ret, port->component->handle, port->handle, parameter_id);
5220 + vchi_held_msg_release(&rmsg_handle);
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)
5230 + struct list_head *q, *buf_head;
5231 + unsigned long flags = 0;
5233 + if (!port->enabled)
5236 + port->enabled = false;
5238 + ret = port_action_port(instance, port,
5239 + MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
5242 + /* drain all queued buffers on port */
5243 + spin_lock_irqsave(&port->slock, flags);
5245 + list_for_each_safe(buf_head, q, &port->buffers) {
5246 + struct mmal_buffer *mmalbuf;
5247 + mmalbuf = list_entry(buf_head, struct mmal_buffer,
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);
5257 + spin_unlock_irqrestore(&port->slock, flags);
5259 + ret = port_info_get(instance, port);
5265 +/* enable a port */
5266 +static int port_enable(struct vchiq_mmal_instance *instance,
5267 + struct vchiq_mmal_port *port)
5269 + unsigned int hdr_count;
5270 + struct list_head *buf_head;
5273 + if (port->enabled)
5276 + /* ensure there are enough buffers queued to cover the buffer headers */
5277 + if (port->buffer_cb != NULL) {
5279 + list_for_each(buf_head, &port->buffers) {
5282 + if (hdr_count < port->current_buffer.num)
5286 + ret = port_action_port(instance, port,
5287 + MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
5291 + port->enabled = true;
5293 + if (port->buffer_cb) {
5294 + /* send buffer headers to videocore */
5296 + list_for_each(buf_head, &port->buffers) {
5297 + struct mmal_buffer *mmalbuf;
5298 + mmalbuf = list_entry(buf_head, struct mmal_buffer,
5300 + ret = buffer_from_host(instance, port, mmalbuf);
5305 + if (hdr_count > port->current_buffer.num)
5310 + ret = port_info_get(instance, port);
5316 +/* ------------------------------------------------------------------
5318 + *------------------------------------------------------------------*/
5320 +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
5321 + struct vchiq_mmal_port *port)
5325 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5328 + ret = port_info_set(instance, port);
5330 + goto release_unlock;
5332 + /* read what has actually been set */
5333 + ret = port_info_get(instance, port);
5336 + mutex_unlock(&instance->vchiq_mutex);
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)
5348 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5351 + ret = port_parameter_set(instance, port, parameter, value, value_size);
5353 + mutex_unlock(&instance->vchiq_mutex);
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)
5364 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5367 + ret = port_parameter_get(instance, port, parameter, value, value_size);
5369 + mutex_unlock(&instance->vchiq_mutex);
5376 + * enables a port and queues buffers for satisfying callbacks if we
5377 + * provide a callback handler
5379 +int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
5380 + struct vchiq_mmal_port *port,
5381 + vchiq_mmal_buffer_cb buffer_cb)
5385 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5388 + /* already enabled - noop */
5389 + if (port->enabled) {
5394 + port->buffer_cb = buffer_cb;
5396 + ret = port_enable(instance, port);
5399 + mutex_unlock(&instance->vchiq_mutex);
5404 +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
5405 + struct vchiq_mmal_port *port)
5409 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5412 + if (!port->enabled) {
5413 + mutex_unlock(&instance->vchiq_mutex);
5417 + ret = port_disable(instance, port);
5419 + mutex_unlock(&instance->vchiq_mutex);
5424 +/* ports will be connected in a tunneled manner so data buffers
5425 + * are not handled by client.
5427 +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
5428 + struct vchiq_mmal_port *src,
5429 + struct vchiq_mmal_port *dst)
5433 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5436 + /* disconnect ports if connected */
5437 + if (src->connected != NULL) {
5438 + ret = port_disable(instance, src);
5440 + pr_err("failed disabling src port(%d)\n", ret);
5441 + goto release_unlock;
5444 + /* do not need to disable the destination port as they
5445 + * are connected and it is done automatically
5448 + ret = port_action_handle(instance, src,
5449 + MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
5450 + src->connected->component->handle,
5451 + src->connected->handle);
5453 + pr_err("failed disconnecting src port\n");
5454 + goto release_unlock;
5456 + src->connected->enabled = false;
5457 + src->connected = NULL;
5460 + if (dst == NULL) {
5461 + /* do not make new connection */
5463 + pr_debug("not making new connection\n");
5464 + goto release_unlock;
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;
5478 + /* set new format */
5479 + ret = port_info_set(instance, dst);
5481 + pr_debug("setting port info failed\n");
5482 + goto release_unlock;
5485 + /* read what has actually been set */
5486 + ret = port_info_get(instance, dst);
5488 + pr_debug("read back port info failed\n");
5489 + goto release_unlock;
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);
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;
5502 + src->connected = dst;
5506 + mutex_unlock(&instance->vchiq_mutex);
5511 +int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
5512 + struct vchiq_mmal_port *port,
5513 + struct mmal_buffer *buffer)
5515 + unsigned long flags = 0;
5517 + spin_lock_irqsave(&port->slock, flags);
5518 + list_add_tail(&buffer->list, &port->buffers);
5519 + spin_unlock_irqrestore(&port->slock, flags);
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.
5525 + if (port->buffer_underflow) {
5526 + port_buffer_from_host(instance, port);
5527 + port->buffer_underflow--;
5533 +/* Initialise a mmal component and its ports
5536 +int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
5538 + struct vchiq_mmal_component **component_out)
5541 + int idx; /* port index */
5542 + struct vchiq_mmal_component *component;
5544 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5547 + if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
5548 + ret = -EINVAL; /* todo is this correct error? */
5552 + component = &instance->component[instance->component_idx];
5554 + ret = create_component(instance, component, name);
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);
5566 + goto release_component;
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]);
5576 + goto release_component;
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]);
5587 + goto release_component;
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]);
5598 + goto release_component;
5601 + instance->component_idx++;
5603 + *component_out = component;
5605 + mutex_unlock(&instance->vchiq_mutex);
5610 + destroy_component(instance, component);
5612 + mutex_unlock(&instance->vchiq_mutex);
5618 + * cause a mmal component to be destroyed
5620 +int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
5621 + struct vchiq_mmal_component *component)
5625 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5628 + if (component->enabled)
5629 + ret = disable_component(instance, component);
5631 + ret = destroy_component(instance, component);
5633 + mutex_unlock(&instance->vchiq_mutex);
5639 + * cause a mmal component to be enabled
5641 +int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
5642 + struct vchiq_mmal_component *component)
5646 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5649 + if (component->enabled) {
5650 + mutex_unlock(&instance->vchiq_mutex);
5654 + ret = enable_component(instance, component);
5656 + component->enabled = true;
5658 + mutex_unlock(&instance->vchiq_mutex);
5664 + * cause a mmal component to be enabled
5666 +int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
5667 + struct vchiq_mmal_component *component)
5671 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5674 + if (!component->enabled) {
5675 + mutex_unlock(&instance->vchiq_mutex);
5679 + ret = disable_component(instance, component);
5681 + component->enabled = false;
5683 + mutex_unlock(&instance->vchiq_mutex);
5688 +int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
5689 + u32 *major_out, u32 *minor_out)
5693 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5696 + ret = get_version(instance, major_out, minor_out);
5698 + mutex_unlock(&instance->vchiq_mutex);
5703 +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
5707 + if (instance == NULL)
5710 + if (mutex_lock_interruptible(&instance->vchiq_mutex))
5713 + vchi_service_use(instance->handle);
5715 + status = vchi_service_close(instance->handle);
5717 + pr_err("mmal-vchiq: VCHIQ close failed");
5719 + mutex_unlock(&instance->vchiq_mutex);
5721 + vfree(instance->bulk_scratch);
5728 +int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
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,
5738 + 0, /* rx fifo size (unused) */
5739 + 0, /* tx fifo size (unused) */
5741 + NULL, /* service callback parameter */
5742 + 1, /* unaligned bulk receives */
5743 + 1, /* unaligned bulk transmits */
5744 + 0 /* want crc check on bulk transfers */
5747 + /* compile time checks to ensure structure size as they are
5748 + * directly (de)serialised from memory.
5751 + /* ensure the header structure has packed to the correct size */
5752 + BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
5754 + /* ensure message structure does not exceed maximum length */
5755 + BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
5757 + /* mmal port struct is correct size */
5758 + BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
5760 + /* create a vchi instance */
5761 + status = vchi_initialise(&vchi_instance);
5763 + pr_err("Failed to initialise VCHI instance (status=%d)\n",
5768 + status = vchi_connect(NULL, 0, vchi_instance);
5770 + pr_err("Failed to connect VCHI instance (status=%d)\n", status);
5774 + instance = kmalloc(sizeof(*instance), GFP_KERNEL);
5775 + memset(instance, 0, sizeof(*instance));
5777 + mutex_init(&instance->vchiq_mutex);
5778 + mutex_init(&instance->bulk_mutex);
5780 + instance->bulk_scratch = vmalloc(PAGE_SIZE);
5782 + params.callback_param = instance;
5784 + status = vchi_service_open(vchi_instance, ¶ms, &instance->handle);
5786 + pr_err("Failed to open VCHI service connection (status=%d)\n",
5788 + goto err_close_services;
5791 + vchi_service_release(instance->handle);
5793 + *out_instance = instance;
5797 +err_close_services:
5799 + vchi_service_close(instance->handle);
5800 + vfree(instance->bulk_scratch);
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
5808 +++ b/drivers/media/platform/bcm2835/mmal-vchiq.h
5811 + * Broadcom BM2835 V4L2 driver
5813 + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
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.
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>
5824 + * MMAL interface to VCHIQ message passing
5827 +#ifndef MMAL_VCHIQ_H
5828 +#define MMAL_VCHIQ_H
5830 +#include "mmal-msg-format.h"
5832 +#define MAX_PORT_COUNT 4
5834 +/* Maximum size of the format extradata. */
5835 +#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
5837 +struct vchiq_mmal_instance;
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 */
5847 +/* rectangle, used lots so it gets its own struct */
5848 +struct vchiq_mmal_rect {
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 */
5861 +struct vchiq_mmal_port;
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);
5869 +struct vchiq_mmal_port {
5872 + u32 type; /* port type, cached to use on port info set */
5873 + u32 index; /* port index, cached to use on port info set */
5875 + /* component port belongs to, allows simple deref */
5876 + struct vchiq_mmal_component *component;
5878 + struct vchiq_mmal_port *connected; /* port conencted to */
5881 + struct vchiq_mmal_port_buffer minimum_buffer;
5882 + struct vchiq_mmal_port_buffer recommended_buffer;
5883 + struct vchiq_mmal_port_buffer current_buffer;
5885 + /* stream format */
5886 + struct mmal_es_format format;
5887 + /* elementry stream format */
5888 + union mmal_es_specific_format es;
5890 + /* data buffers to fill */
5891 + struct list_head buffers;
5892 + /* lock to serialise adding and removing buffers from list */
5894 + /* count of how many buffer header refils have failed because
5895 + * there was no buffer to satisfy them
5897 + int buffer_underflow;
5898 + /* callback on buffer completion */
5899 + vchiq_mmal_buffer_cb buffer_cb;
5900 + /* callback context */
5904 +struct vchiq_mmal_component {
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 */
5917 +int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
5918 +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
5920 +/* Initialise a mmal component and its ports
5923 +int vchiq_mmal_component_init(
5924 + struct vchiq_mmal_instance *instance,
5926 + struct vchiq_mmal_component **component_out);
5928 +int vchiq_mmal_component_finalise(
5929 + struct vchiq_mmal_instance *instance,
5930 + struct vchiq_mmal_component *component);
5932 +int vchiq_mmal_component_enable(
5933 + struct vchiq_mmal_instance *instance,
5934 + struct vchiq_mmal_component *component);
5936 +int vchiq_mmal_component_disable(
5937 + struct vchiq_mmal_instance *instance,
5938 + struct vchiq_mmal_component *component);
5942 +/* enable a mmal port
5944 + * enables a port and if a buffer callback provided enque buffer
5945 + * headers as apropriate for the port.
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);
5954 + * disable a port will dequeue any pending buffers
5956 +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
5957 + struct vchiq_mmal_port *port);
5960 +int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
5961 + struct vchiq_mmal_port *port,
5966 +int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
5967 + struct vchiq_mmal_port *port,
5972 +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
5973 + struct vchiq_mmal_port *port);
5975 +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
5976 + struct vchiq_mmal_port *src,
5977 + struct vchiq_mmal_port *dst);
5979 +int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
5983 +int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
5984 + struct vchiq_mmal_port *port,
5985 + struct mmal_buffer *buf);
5987 +#endif /* MMAL_VCHIQ_H */