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