aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2015-02-11 10:17:55 +0000
committerJohn Crispin <blogic@openwrt.org>2015-02-11 10:17:55 +0000
commitc291f76d24a4190551a42b7b77a2cfeb3f4d36f9 (patch)
tree8f9211217d7e2cbaa78d10b596d81e646b3b9aad /target/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch
parent0e26998162921c65cbfe2814e500c81ca7b50dad (diff)
downloadupstream-c291f76d24a4190551a42b7b77a2cfeb3f4d36f9.tar.gz
upstream-c291f76d24a4190551a42b7b77a2cfeb3f4d36f9.tar.bz2
upstream-c291f76d24a4190551a42b7b77a2cfeb3f4d36f9.zip
brcm2708: update to v3.18
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@44392 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch')
-rwxr-xr-xtarget/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch2417
1 files changed, 2417 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch b/target/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch
new file mode 100755
index 0000000000..bd554a9f96
--- /dev/null
+++ b/target/linux/brcm2708/patches-3.18/0028-V4L2-Fixes-from-6by9.patch
@@ -0,0 +1,2417 @@
+From c8fb291144efa1ab7f0628119894a1e72f08bce4 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dsteve@broadcom.com>
+Date: Mon, 9 Dec 2013 10:58:01 +0000
+Subject: [PATCH 028/114] V4L2: Fixes from 6by9
+
+V4L2: Fix EV values. Add manual shutter speed control
+
+V4L2 EV values should be in units of 1/1000. Corrected.
+Add support for V4L2_CID_EXPOSURE_ABSOLUTE which should
+give manual shutter control. Requires manual exposure mode
+to be selected first.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Correct JPEG Q-factor range
+
+Should be 1-100, not 0-100
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Fix issue of driver jamming if STREAMON failed.
+
+Fix issue where the driver was left in a partially enabled
+state if STREAMON failed, and would then reject many IOCTLs
+as it thought it was streaming.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Fix ISO controls.
+
+Driver was passing the index to the GPU, and not the desired
+ISO value.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add flicker avoidance controls
+
+Add support for V4L2_CID_POWER_LINE_FREQUENCY to set flicker
+avoidance frequencies.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add support for frame rate control.
+
+Add support for frame rate (or time per frame as V4L2
+inverts it) control via s_parm.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Improve G_FBUF handling so we pass conformance
+
+Return some sane numbers for get framebuffer so that
+we pass conformance.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Fix information advertised through g_vidfmt
+
+Width and height were being stored based on incorrect
+values.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add support for inline H264 headers
+
+Add support for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER
+to control H264 inline headers.
+Requires firmware fix to work correctly, otherwise format
+has to be set to H264 before this parameter is set.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Fix JPEG timestamp issue
+
+JPEG images were coming through from the GPU with timestamp
+of 0. Detect this and give current system time instead
+of some invalid value.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Fix issue when switching down JPEG resolution.
+
+JPEG buffer size calculation is based on input resolution.
+Input resolution was being configured after output port
+format. Caused failures if switching from one JPEG resolution
+to a smaller one.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Enable MJPEG encoding
+
+Requires GPU firmware update to support MJPEG encoder.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Correct flag settings for compressed formats
+
+Set flags field correctly on enum_fmt_vid_cap for compressed
+image formats.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: H264 profile & level ctrls, FPS control and auto exp pri
+
+Several control handling updates.
+H264 profile and level controls.
+Timeperframe/FPS reworked to add V4L2_CID_EXPOSURE_AUTO_PRIORITY to
+select whether AE is allowed to override the framerate specified.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Correct BGR24 to RGB24 in format table
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add additional pixel formats. Correct colourspace
+
+Adds the other flavours of YUYV, and NV12.
+Corrects the overlay advertised colourspace.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Drop logging msg from info to debug
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Initial pass at scene modes.
+
+Only supports exposure mode and metering modes.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add manual white balance control.
+
+Adds support for V4L2_CID_RED_BALANCE and
+V4L2_CID_BLUE_BALANCE. Only has an effect if
+V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE has
+V4L2_WHITE_BALANCE_MANUAL selected.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+config: Enable V4L / MMAL driver
+
+V4L2: Increase the MMAL timeout to 3sec
+
+MJPEG codec flush is now taking longer and results
+in a kernel panic if the driver has stopped waiting for
+the result when it finally completes.
+Increase the timeout value from 1 to 3secs.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add support for setting H264_I_PERIOD
+
+Adds support for the parameter V4L2_CID_MPEG_VIDEO_H264_I_PERIOD
+to set the frequency with which I frames are produced.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Enable GPU function for removing padding from images.
+
+GPU can now support arbitrary strides, although may require
+additional processing to achieve it. Enable this feature
+so that the images delivered are the size requested.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add support for V4L2_PIX_FMT_BGR32
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Set the colourspace to avoid odd YUV-RGB conversions
+
+Removes the amiguity from the conversion routines and stops
+them dropping back to the SD vs HD choice of coeffs.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Make video/still threshold a run-time param
+
+Move the define for at what resolution the driver
+switches from a video mode capture to a stills mode
+capture to module parameters.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Fix incorrect pool sizing
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add option to disable enum_framesizes.
+
+Gstreamer's handling of a driver that advertises
+V4L2_FRMSIZE_TYPE_STEPWISE to define the supported
+resolutions is broken. See bug
+https://bugzilla.gnome.org/show_bug.cgi?id=726521
+
+Optional parameter of gst_v4l2src_is_broken added.
+If non-zero, the driver claims not to support that
+ioctl, and gstreamer should be happy again (it
+guesses a set of defaults for itself).
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Add support for more image formats
+
+Adds YVU420 (YV12), YVU420SP (NV21), and BGR888.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+V4L2: Extend range for V4L2_CID_MPEG_VIDEO_H264_I_PERIOD
+
+Request to extend the range from the fairly arbitrary
+1000 frames (33 seconds at 30fps). Extend out to the
+max range supported (int32 value).
+Also allow 0, which is handled by the codec as only
+send an I-frame on the first frame and never again.
+There may be an exception if it detects a significant
+scene change, but there's no easy way around that.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+
+bcm2835-camera: stop_streaming now has a void return
+---
+ arch/arm/configs/bcmrpi_defconfig | 3 +
+ drivers/media/platform/bcm2835/bcm2835-camera.c | 578 ++++++++++++++----
+ drivers/media/platform/bcm2835/bcm2835-camera.h | 23 +-
+ drivers/media/platform/bcm2835/controls.c | 723 +++++++++++++++++++++--
+ drivers/media/platform/bcm2835/mmal-common.h | 1 +
+ drivers/media/platform/bcm2835/mmal-encodings.h | 34 ++
+ drivers/media/platform/bcm2835/mmal-parameters.h | 121 +++-
+ drivers/media/platform/bcm2835/mmal-vchiq.c | 4 +-
+ 8 files changed, 1300 insertions(+), 187 deletions(-)
+
+diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig
+index 897616c..3f99687 100644
+--- a/arch/arm/configs/bcmrpi_defconfig
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -708,6 +708,9 @@ CONFIG_DVB_AS102=m
+ CONFIG_VIDEO_EM28XX=m
+ CONFIG_VIDEO_EM28XX_ALSA=m
+ CONFIG_VIDEO_EM28XX_DVB=m
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_VIDEO_BCM2835=y
++CONFIG_VIDEO_BCM2835_MMAL=m
+ CONFIG_RADIO_SI470X=y
+ CONFIG_USB_SI470X=m
+ CONFIG_I2C_SI470X=m
+diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c
+index 1c9d9d5..e5a0010 100644
+--- a/drivers/media/platform/bcm2835/bcm2835-camera.c
++++ b/drivers/media/platform/bcm2835/bcm2835-camera.c
+@@ -36,7 +36,8 @@
+
+ #define BM2835_MMAL_VERSION "0.0.2"
+ #define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2"
+-
++#define MIN_WIDTH 16
++#define MIN_HEIGHT 16
+ #define MAX_WIDTH 2592
+ #define MAX_HEIGHT 1944
+ #define MIN_BUFFER_SIZE (80*1024)
+@@ -53,13 +54,43 @@ int bcm2835_v4l2_debug;
+ module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
+ MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
+
++int max_video_width = MAX_VIDEO_MODE_WIDTH;
++int max_video_height = MAX_VIDEO_MODE_HEIGHT;
++module_param(max_video_width, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(max_video_width, "Threshold for video mode");
++module_param(max_video_height, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(max_video_height, "Threshold for video mode");
++
++/* Gstreamer bug https://bugzilla.gnome.org/show_bug.cgi?id=726521
++ * v4l2src does bad (and actually wrong) things when the vidioc_enum_framesizes
++ * function says type V4L2_FRMSIZE_TYPE_STEPWISE, which we do by default.
++ * It's happier if we just don't say anything at all, when it then
++ * sets up a load of defaults that it thinks might work.
++ * If gst_v4l2src_is_broken is non-zero, then we remove the function from
++ * our function table list (actually switch to an alternate set, but same
++ * result).
++ */
++int gst_v4l2src_is_broken = 0;
++module_param(gst_v4l2src_is_broken, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(gst_v4l2src_is_broken, "If non-zero, enable workaround for Gstreamer");
++
+ static struct bm2835_mmal_dev *gdev; /* global device data */
+
++#define FPS_MIN 1
++#define FPS_MAX 90
++
++/* timeperframe: min/max and default */
++static const struct v4l2_fract
++ tpf_min = {.numerator = 1, .denominator = FPS_MAX},
++ tpf_max = {.numerator = 1, .denominator = FPS_MIN},
++ tpf_default = {.numerator = 1000, .denominator = 30000};
++
+ /* video formats */
+ static struct mmal_fmt formats[] = {
+ {
+ .name = "4:2:0, packed YUV",
+ .fourcc = V4L2_PIX_FMT_YUV420,
++ .flags = 0,
+ .mmal = MMAL_ENCODING_I420,
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+@@ -67,13 +98,15 @@ static struct mmal_fmt formats[] = {
+ {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
++ .flags = 0,
+ .mmal = MMAL_ENCODING_YUYV,
+ .depth = 16,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ },
+ {
+- .name = "RGB24 (BE)",
+- .fourcc = V4L2_PIX_FMT_BGR24,
++ .name = "RGB24 (LE)",
++ .fourcc = V4L2_PIX_FMT_RGB24,
++ .flags = 0,
+ .mmal = MMAL_ENCODING_BGR24,
+ .depth = 24,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+@@ -81,6 +114,7 @@ static struct mmal_fmt formats[] = {
+ {
+ .name = "JPEG",
+ .fourcc = V4L2_PIX_FMT_JPEG,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_JPEG,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
+@@ -88,10 +122,83 @@ static struct mmal_fmt formats[] = {
+ {
+ .name = "H264",
+ .fourcc = V4L2_PIX_FMT_H264,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_H264,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
+- }
++ },
++ {
++ .name = "MJPEG",
++ .fourcc = V4L2_PIX_FMT_MJPEG,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal = MMAL_ENCODING_MJPEG,
++ .depth = 8,
++ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
++ },
++ {
++ .name = "4:2:2, packed, YVYU",
++ .fourcc = V4L2_PIX_FMT_YVYU,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_YVYU,
++ .depth = 16,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:2, packed, VYUY",
++ .fourcc = V4L2_PIX_FMT_VYUY,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_VYUY,
++ .depth = 16,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:2, packed, UYVY",
++ .fourcc = V4L2_PIX_FMT_UYVY,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_UYVY,
++ .depth = 16,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:0, packed, NV12",
++ .fourcc = V4L2_PIX_FMT_NV12,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_NV12,
++ .depth = 12,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "RGB24 (BE)",
++ .fourcc = V4L2_PIX_FMT_BGR24,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_RGB24,
++ .depth = 24,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:0, packed YVU",
++ .fourcc = V4L2_PIX_FMT_YVU420,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_YV12,
++ .depth = 12,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:0, packed, NV21",
++ .fourcc = V4L2_PIX_FMT_NV21,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_NV21,
++ .depth = 12,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "RGB32 (BE)",
++ .fourcc = V4L2_PIX_FMT_BGR32,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_BGRA,
++ .depth = 32,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
+ };
+
+ static struct mmal_fmt *get_format(struct v4l2_format *f)
+@@ -229,7 +336,8 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
+ }
+ } else {
+ if (dev->capture.frame_count) {
+- if (dev->capture.vc_start_timestamp != -1) {
++ if (dev->capture.vc_start_timestamp != -1 &&
++ pts != 0) {
+ s64 runtime_us = pts -
+ dev->capture.vc_start_timestamp;
+ u32 div = 0;
+@@ -250,7 +358,7 @@ static void buffer_cb(struct vchiq_mmal_instance *instance,
+ USEC_PER_SEC;
+ }
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+- "Convert start time %d.%06d and %llu"
++ "Convert start time %d.%06d and %llu "
+ "with offset %llu to %d.%06d\n",
+ (int)dev->capture.kernel_start_ts.
+ tv_sec,
+@@ -425,7 +533,15 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
+ vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev,
+- "Failed to enable capture port - error %d\n", ret);
++ "Failed to enable capture port - error %d. "
++ "Disabling camera port again\n", ret);
++
++ vchiq_mmal_port_disable(dev->instance,
++ dev->capture.camera_port);
++ if (disable_camera(dev) < 0) {
++ v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n");
++ return -EINVAL;
++ }
+ return -1;
+ }
+
+@@ -439,7 +555,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
+ }
+
+ /* abort streaming and wait for last buffer */
+-static int stop_streaming(struct vb2_queue *vq)
++static void stop_streaming(struct vb2_queue *vq)
+ {
+ int ret;
+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
+@@ -451,8 +567,11 @@ static int stop_streaming(struct vb2_queue *vq)
+ dev->capture.frame_count = 0;
+
+ /* ensure a format has actually been set */
+- if (dev->capture.port == NULL)
+- return -EINVAL;
++ if (dev->capture.port == NULL) {
++ v4l2_err(&dev->v4l2_dev,
++ "no capture port - stream not started?\n");
++ return;
++ }
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n");
+
+@@ -483,12 +602,8 @@ static int stop_streaming(struct vb2_queue *vq)
+ ret);
+ }
+
+- if (disable_camera(dev) < 0) {
+- v4l2_err(&dev->v4l2_dev, "Failed to disable camera");
+- return -EINVAL;
+- }
+-
+- return ret;
++ if (disable_camera(dev) < 0)
++ v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n");
+ }
+
+ static void bm2835_mmal_lock(struct vb2_queue *vq)
+@@ -530,6 +645,7 @@ static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
++ f->flags = fmt->flags;
+
+ return 0;
+ }
+@@ -647,10 +763,18 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
+ {
+ /* The video overlay must stay within the framebuffer and can't be
+ positioned independently. */
++ struct bm2835_mmal_dev *dev = video_drvdata(file);
++ struct vchiq_mmal_port *preview_port =
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_PREVIEW];
+ a->flags = V4L2_FBUF_FLAG_OVERLAY;
+-
+- /* todo: v4l2_framebuffer still needs more info filling in
+- * in order to pass the v4l2-compliance test. */
++ a->fmt.width = preview_port->es.video.width;
++ a->fmt.height = preview_port->es.video.height;
++ a->fmt.pixelformat = V4L2_PIX_FMT_YUV420;
++ a->fmt.bytesperline = (preview_port->es.video.width * 3)>>1;
++ a->fmt.sizeimage = (preview_port->es.video.width *
++ preview_port->es.video.height * 3)>>1;
++ a->fmt.colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+ }
+@@ -717,6 +841,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
++ f->flags = fmt->flags;
++
+ return 0;
+ }
+
+@@ -729,20 +855,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ f->fmt.pix.height = dev->capture.height;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.pixelformat = dev->capture.fmt->fourcc;
+- f->fmt.pix.bytesperline =
+- (f->fmt.pix.width * dev->capture.fmt->depth) >> 3;
+- f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+- if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG
+- && f->fmt.pix.sizeimage < (100 << 10)) {
+- /* Need a minimum size for JPEG to account for EXIF. */
+- f->fmt.pix.sizeimage = (100 << 10);
+- }
++ f->fmt.pix.bytesperline = dev->capture.stride;
++ f->fmt.pix.sizeimage = dev->capture.buffersize;
+
+- if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_YUYV ||
+- dev->capture.fmt->fourcc == V4L2_PIX_FMT_UYVY)
+- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+- else
++ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
++ else
++ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+ f->fmt.pix.priv = 0;
+
+ v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
+@@ -766,21 +885,35 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ }
+
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+- /* image must be a multiple of 32 pixels wide and 16 lines high */
+- v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 5,
+- &f->fmt.pix.height, 32, MAX_HEIGHT, 4, 0);
+- f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth) >> 3;
+- f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+- if (f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
++
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Clipping/aligning %dx%d format %08X\n",
++ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat);
++
++ v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, MAX_WIDTH, 1,
++ &f->fmt.pix.height, MIN_HEIGHT, MAX_HEIGHT, 1, 0);
++ f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth)>>3;
++
++ /* Image buffer has to be padded to allow for alignment, even though
++ * we then remove that padding before delivering the buffer.
++ */
++ f->fmt.pix.sizeimage = ((f->fmt.pix.height+15)&~15) *
++ (((f->fmt.pix.width+31)&~31) * mfmt->depth) >> 3;
++
++ if ((mfmt->flags & V4L2_FMT_FLAG_COMPRESSED) &&
++ f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
+ f->fmt.pix.sizeimage = MIN_BUFFER_SIZE;
+
+- if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
+- mfmt->fourcc == V4L2_PIX_FMT_UYVY)
+- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+- else
++ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
++ else
++ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+ f->fmt.pix.priv = 0;
+
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Now %dx%d format %08X\n",
++ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat);
++
+ v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
+ __func__);
+ return 0;
+@@ -818,8 +951,8 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
+ switch (mfmt->mmal_component) {
+ case MMAL_COMPONENT_CAMERA:
+ /* Make a further decision on port based on resolution */
+- if (f->fmt.pix.width <= MAX_VIDEO_MODE_WIDTH
+- && f->fmt.pix.height <= MAX_VIDEO_MODE_HEIGHT)
++ if (f->fmt.pix.width <= max_video_width
++ && f->fmt.pix.height <= max_video_height)
+ camera_port = port =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+ output[MMAL_CAMERA_PORT_VIDEO];
+@@ -861,8 +994,9 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
+ camera_port->es.video.crop.y = 0;
+ camera_port->es.video.crop.width = f->fmt.pix.width;
+ camera_port->es.video.crop.height = f->fmt.pix.height;
+- camera_port->es.video.frame_rate.num = 30;
++ camera_port->es.video.frame_rate.num = 0;
+ camera_port->es.video.frame_rate.den = 1;
++ camera_port->es.video.color_space = MMAL_COLOR_SPACE_JPEG_JFIF;
+
+ ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
+
+@@ -896,8 +1030,10 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
+ preview_port->es.video.crop.y = 0;
+ preview_port->es.video.crop.width = f->fmt.pix.width;
+ preview_port->es.video.crop.height = f->fmt.pix.height;
+- preview_port->es.video.frame_rate.num = 30;
+- preview_port->es.video.frame_rate.den = 1;
++ preview_port->es.video.frame_rate.num =
++ dev->capture.timeperframe.denominator;
++ preview_port->es.video.frame_rate.den =
++ dev->capture.timeperframe.numerator;
+ ret = vchiq_mmal_port_set_format(dev->instance, preview_port);
+ if (overlay_enabled) {
+ ret = vchiq_mmal_port_connect_tunnel(
+@@ -913,7 +1049,9 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
+
+ if (ret) {
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+- "%s failed to set format\n", __func__);
++ "%s failed to set format %dx%d %08X\n", __func__,
++ f->fmt.pix.width, f->fmt.pix.height,
++ f->fmt.pix.pixelformat);
+ /* ensure capture is not going to be tried */
+ dev->capture.port = NULL;
+ } else {
+@@ -927,69 +1065,91 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
+ camera_port->current_buffer.num =
+ camera_port->recommended_buffer.num;
+
+- port->format.encoding = mfmt->mmal;
+- port->format.encoding_variant = 0;
+- /* Set any encoding specific parameters */
+- switch (mfmt->mmal_component) {
+- case MMAL_COMPONENT_VIDEO_ENCODE:
+- port->format.bitrate =
+- dev->capture.encode_bitrate;
+- break;
+- case MMAL_COMPONENT_IMAGE_ENCODE:
+- /* Could set EXIF parameters here */
+- break;
+- default:
+- break;
+- }
+- ret = vchiq_mmal_port_set_format(dev->instance, port);
+-
++ ret =
++ vchiq_mmal_port_connect_tunnel(
++ dev->instance,
++ camera_port,
++ &encode_component->input[0]);
+ if (ret) {
+- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+- "%s failed to set format\n", __func__);
++ v4l2_dbg(1, bcm2835_v4l2_debug,
++ &dev->v4l2_dev,
++ "%s failed to create connection\n",
++ __func__);
++ /* ensure capture is not going to be tried */
++ dev->capture.port = NULL;
+ } else {
++ port->es.video.width = f->fmt.pix.width;
++ port->es.video.height = f->fmt.pix.height;
++ port->es.video.crop.x = 0;
++ port->es.video.crop.y = 0;
++ port->es.video.crop.width = f->fmt.pix.width;
++ port->es.video.crop.height = f->fmt.pix.height;
++ port->es.video.frame_rate.num =
++ dev->capture.timeperframe.denominator;
++ port->es.video.frame_rate.den =
++ dev->capture.timeperframe.numerator;
++
++ port->format.encoding = mfmt->mmal;
++ port->format.encoding_variant = 0;
++ /* Set any encoding specific parameters */
++ switch (mfmt->mmal_component) {
++ case MMAL_COMPONENT_VIDEO_ENCODE:
++ port->format.bitrate =
++ dev->capture.encode_bitrate;
++ break;
++ case MMAL_COMPONENT_IMAGE_ENCODE:
++ /* Could set EXIF parameters here */
++ break;
++ default:
++ break;
++ }
++ ret = vchiq_mmal_port_set_format(dev->instance,
++ port);
++ if (ret)
++ v4l2_dbg(1, bcm2835_v4l2_debug,
++ &dev->v4l2_dev,
++ "%s failed to set format %dx%d fmt %08X\n",
++ __func__,
++ f->fmt.pix.width,
++ f->fmt.pix.height,
++ f->fmt.pix.pixelformat
++ );
++ }
++
++ if (!ret) {
+ ret = vchiq_mmal_component_enable(
+ dev->instance,
+ encode_component);
+ if (ret) {
+ v4l2_dbg(1, bcm2835_v4l2_debug,
+- &dev->v4l2_dev,
+- "%s Failed to enable encode components\n",
+- __func__);
+- } else {
+- /* configure buffering */
+- port->current_buffer.num = 1;
+- port->current_buffer.size =
+- f->fmt.pix.sizeimage;
+- if (port->format.encoding ==
+- MMAL_ENCODING_JPEG) {
+- v4l2_dbg(1, bcm2835_v4l2_debug,
+- &dev->v4l2_dev,
+- "JPEG - fiddle buffer size\n");
+- port->current_buffer.size =
+- (f->fmt.pix.sizeimage <
+- (100 << 10))
+- ? (100 << 10) : f->fmt.pix.
+- sizeimage;
+- }
++ &dev->v4l2_dev,
++ "%s Failed to enable encode components\n",
++ __func__);
++ }
++ }
++ if (!ret) {
++ /* configure buffering */
++ port->current_buffer.num = 1;
++ port->current_buffer.size =
++ f->fmt.pix.sizeimage;
++ if (port->format.encoding ==
++ MMAL_ENCODING_JPEG) {
+ v4l2_dbg(1, bcm2835_v4l2_debug,
+- &dev->v4l2_dev,
+- "vid_cap - current_buffer.size being set to %d\n",
+- f->fmt.pix.sizeimage);
+- port->current_buffer.alignment = 0;
+- ret =
+- vchiq_mmal_port_connect_tunnel(
+- dev->instance,
+- camera_port,
+- &encode_component->input[0]);
+- if (ret) {
+- v4l2_dbg(1, bcm2835_v4l2_debug,
+- &dev->v4l2_dev,
+- "%s failed to create connection\n",
+- __func__);
+- /* ensure capture is not going to be tried */
+- dev->capture.port = NULL;
+- }
++ &dev->v4l2_dev,
++ "JPG - buf size now %d was %d\n",
++ f->fmt.pix.sizeimage,
++ port->current_buffer.size);
++ port->current_buffer.size =
++ (f->fmt.pix.sizeimage <
++ (100 << 10))
++ ? (100 << 10) : f->fmt.pix.
++ sizeimage;
+ }
++ v4l2_dbg(1, bcm2835_v4l2_debug,
++ &dev->v4l2_dev,
++ "vid_cap - cur_buf.size set to %d\n",
++ f->fmt.pix.sizeimage);
++ port->current_buffer.alignment = 0;
+ }
+ } else {
+ /* configure buffering */
+@@ -1001,13 +1161,20 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
+ if (!ret) {
+ dev->capture.fmt = mfmt;
+ dev->capture.stride = f->fmt.pix.bytesperline;
+- dev->capture.width = port->es.video.crop.width;
+- dev->capture.height = port->es.video.crop.height;
++ dev->capture.width = camera_port->es.video.crop.width;
++ dev->capture.height = camera_port->es.video.crop.height;
++ dev->capture.buffersize = port->current_buffer.size;
+
+ /* select port for capture */
+ dev->capture.port = port;
+ dev->capture.camera_port = camera_port;
+ dev->capture.encode_component = encode_component;
++ v4l2_dbg(1, bcm2835_v4l2_debug,
++ &dev->v4l2_dev,
++ "Set dev->capture.fmt %08X, %dx%d, stride %d, size %d",
++ port->format.encoding,
++ dev->capture.width, dev->capture.height,
++ dev->capture.stride, dev->capture.buffersize);
+ }
+ }
+
+@@ -1048,14 +1215,115 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ }
+
+ ret = mmal_setup_components(dev, f);
+- if (ret != 0)
++ if (ret != 0) {
+ v4l2_err(&dev->v4l2_dev,
+ "%s: failed to setup mmal components: %d\n",
+ __func__, ret);
++ ret = -EINVAL;
++ }
+
+ return ret;
+ }
+
++int vidioc_enum_framesizes(struct file *file, void *fh,
++ struct v4l2_frmsizeenum *fsize)
++{
++ static const struct v4l2_frmsize_stepwise sizes = {
++ MIN_WIDTH, MAX_WIDTH, 2,
++ MIN_HEIGHT, MAX_HEIGHT, 2
++ };
++ int i;
++
++ if (fsize->index)
++ return -EINVAL;
++ for (i = 0; i < ARRAY_SIZE(formats); i++)
++ if (formats[i].fourcc == fsize->pixel_format)
++ break;
++ if (i == ARRAY_SIZE(formats))
++ return -EINVAL;
++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
++ fsize->stepwise = sizes;
++ return 0;
++}
++
++/* timeperframe is arbitrary and continous */
++static int vidioc_enum_frameintervals(struct file *file, void *priv,
++ struct v4l2_frmivalenum *fival)
++{
++ int i;
++
++ if (fival->index)
++ return -EINVAL;
++
++ for (i = 0; i < ARRAY_SIZE(formats); i++)
++ if (formats[i].fourcc == fival->pixel_format)
++ break;
++ if (i == ARRAY_SIZE(formats))
++ return -EINVAL;
++
++ /* regarding width & height - we support any within range */
++ if (fival->width < MIN_WIDTH || fival->width > MAX_WIDTH ||
++ fival->height < MIN_HEIGHT || fival->height > MAX_HEIGHT)
++ return -EINVAL;
++
++ fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
++
++ /* fill in stepwise (step=1.0 is requred by V4L2 spec) */
++ fival->stepwise.min = tpf_min;
++ fival->stepwise.max = tpf_max;
++ fival->stepwise.step = (struct v4l2_fract) {1, 1};
++
++ return 0;
++}
++
++static int vidioc_g_parm(struct file *file, void *priv,
++ struct v4l2_streamparm *parm)
++{
++ struct bm2835_mmal_dev *dev = video_drvdata(file);
++
++ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
++ parm->parm.capture.timeperframe = dev->capture.timeperframe;
++ parm->parm.capture.readbuffers = 1;
++ return 0;
++}
++
++#define FRACT_CMP(a, OP, b) \
++ ((u64)(a).numerator * (b).denominator OP \
++ (u64)(b).numerator * (a).denominator)
++
++static int vidioc_s_parm(struct file *file, void *priv,
++ struct v4l2_streamparm *parm)
++{
++ struct bm2835_mmal_dev *dev = video_drvdata(file);
++ struct v4l2_fract tpf;
++ struct mmal_parameter_rational fps_param;
++
++ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ tpf = parm->parm.capture.timeperframe;
++
++ /* tpf: {*, 0} resets timing; clip to [min, max]*/
++ tpf = tpf.denominator ? tpf : tpf_default;
++ tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf;
++ tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf;
++
++ dev->capture.timeperframe = tpf;
++ parm->parm.capture.timeperframe = tpf;
++ parm->parm.capture.readbuffers = 1;
++
++ fps_param.num = 0; /* Select variable fps, and then use
++ * FPS_RANGE to select the actual limits.
++ */
++ fps_param.den = 1;
++ set_framerate_params(dev);
++
++ return 0;
++}
++
+ static const struct v4l2_ioctl_ops camera0_ioctl_ops = {
+ /* overlay */
+ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
+@@ -1084,6 +1352,51 @@ static const struct v4l2_ioctl_ops camera0_ioctl_ops = {
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
++ .vidioc_enum_framesizes = vidioc_enum_framesizes,
++ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
++ .vidioc_g_parm = vidioc_g_parm,
++ .vidioc_s_parm = vidioc_s_parm,
++ .vidioc_streamon = vb2_ioctl_streamon,
++ .vidioc_streamoff = vb2_ioctl_streamoff,
++
++ .vidioc_log_status = v4l2_ctrl_log_status,
++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
++};
++
++static const struct v4l2_ioctl_ops camera0_ioctl_ops_gstreamer = {
++ /* overlay */
++ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
++ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
++ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
++ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
++ .vidioc_overlay = vidioc_overlay,
++ .vidioc_g_fbuf = vidioc_g_fbuf,
++
++ /* inputs */
++ .vidioc_enum_input = vidioc_enum_input,
++ .vidioc_g_input = vidioc_g_input,
++ .vidioc_s_input = vidioc_s_input,
++
++ /* capture */
++ .vidioc_querycap = vidioc_querycap,
++ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
++ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
++ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
++ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
++
++ /* buffer management */
++ .vidioc_reqbufs = vb2_ioctl_reqbufs,
++ .vidioc_create_bufs = vb2_ioctl_create_bufs,
++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
++ .vidioc_querybuf = vb2_ioctl_querybuf,
++ .vidioc_qbuf = vb2_ioctl_qbuf,
++ .vidioc_dqbuf = vb2_ioctl_dqbuf,
++ /* Remove this function ptr to fix gstreamer bug
++ .vidioc_enum_framesizes = vidioc_enum_framesizes, */
++ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
++ .vidioc_g_parm = vidioc_g_parm,
++ .vidioc_s_parm = vidioc_s_parm,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+
+@@ -1122,8 +1435,10 @@ static int set_camera_parameters(struct vchiq_mmal_instance *instance,
+ .max_stills_h = MAX_HEIGHT,
+ .stills_yuv422 = 1,
+ .one_shot_stills = 1,
+- .max_preview_video_w = 1920,
+- .max_preview_video_h = 1088,
++ .max_preview_video_w = (max_video_width > 1920) ?
++ max_video_width : 1920,
++ .max_preview_video_h = (max_video_height > 1088) ?
++ max_video_height : 1088,
+ .num_preview_video_frames = 3,
+ .stills_capture_circular_buffer_height = 0,
+ .fast_preview_resume = 0,
+@@ -1141,6 +1456,7 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
+ {
+ int ret;
+ struct mmal_es_format *format;
++ u32 bool_true = 1;
+
+ ret = vchiq_mmal_init(&dev->instance);
+ if (ret < 0)
+@@ -1176,8 +1492,8 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
+ format->es->video.crop.y = 0;
+ format->es->video.crop.width = 1024;
+ format->es->video.crop.height = 768;
+- format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
+- format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
++ format->es->video.frame_rate.den = 1;
+
+ format =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+@@ -1192,8 +1508,14 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
+ format->es->video.crop.y = 0;
+ format->es->video.crop.width = 1024;
+ format->es->video.crop.height = 768;
+- format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
+- format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
++ format->es->video.frame_rate.den = 1;
++
++ vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_VIDEO],
++ MMAL_PARAMETER_NO_IMAGE_PADDING,
++ &bool_true, sizeof(bool_true));
+
+ format =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
+@@ -1207,13 +1529,22 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
+ format->es->video.crop.y = 0;
+ format->es->video.crop.width = 2592;
+ format->es->video.crop.height = 1944;
+- format->es->video.frame_rate.num = 30;
++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
+ format->es->video.frame_rate.den = 1;
+
+ dev->capture.width = format->es->video.width;
+ dev->capture.height = format->es->video.height;
+ dev->capture.fmt = &formats[0];
+ dev->capture.encode_component = NULL;
++ dev->capture.timeperframe = tpf_default;
++ dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
++ dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
++
++ vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_CAPTURE],
++ MMAL_PARAMETER_NO_IMAGE_PADDING,
++ &bool_true, sizeof(bool_true));
+
+ /* get the preview component ready */
+ ret = vchiq_mmal_component_init(
+@@ -1260,6 +1591,14 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
+ }
+
+ {
++ struct vchiq_mmal_port *encoder_port =
++ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++ encoder_port->format.encoding = MMAL_ENCODING_H264;
++ ret = vchiq_mmal_port_set_format(dev->instance,
++ encoder_port);
++ }
++
++ {
+ unsigned int enable = 1;
+ vchiq_mmal_port_parameter_set(
+ dev->instance,
+@@ -1312,6 +1651,11 @@ static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
+ int ret;
+
+ *vfd = vdev_template;
++ if (gst_v4l2src_is_broken) {
++ v4l2_info(&dev->v4l2_dev,
++ "Work-around for gstreamer issue is active.\n");
++ vfd->ioctl_ops = &camera0_ioctl_ops_gstreamer;
++ }
+
+ vfd->v4l2_dev = &dev->v4l2_dev;
+
+@@ -1326,8 +1670,9 @@ static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
+ if (ret < 0)
+ return ret;
+
+- v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
+- video_device_node_name(vfd));
++ v4l2_info(vfd->v4l2_dev,
++ "V4L2 device registered as %s - stills mode > %dx%d\n",
++ video_device_node_name(vfd), max_video_width, max_video_height);
+
+ return 0;
+ }
+@@ -1335,9 +1680,9 @@ static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
+ static struct v4l2_format default_v4l2_format = {
+ .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG,
+ .fmt.pix.width = 1024,
+- .fmt.pix.bytesperline = 1024 * 3 / 2,
++ .fmt.pix.bytesperline = 1024,
+ .fmt.pix.height = 768,
+- .fmt.pix.sizeimage = 1<<18,
++ .fmt.pix.sizeimage = 1024*768,
+ };
+
+ static int __init bm2835_mmal_init(void)
+@@ -1400,6 +1745,9 @@ static int __init bm2835_mmal_init(void)
+ if (ret < 0)
+ goto unreg_dev;
+
++ /* Really want to call vidioc_s_fmt_vid_cap with the default
++ * format, but currently the APIs don't join up.
++ */
+ ret = mmal_setup_components(dev, &default_v4l2_format);
+ if (ret < 0) {
+ v4l2_err(&dev->v4l2_dev,
+diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h
+index 883eab7..7fe9f65 100644
+--- a/drivers/media/platform/bcm2835/bcm2835-camera.h
++++ b/drivers/media/platform/bcm2835/bcm2835-camera.h
+@@ -15,7 +15,7 @@
+ * core driver device
+ */
+
+-#define V4L2_CTRL_COUNT 18 /* number of v4l controls */
++#define V4L2_CTRL_COUNT 28 /* number of v4l controls */
+
+ enum {
+ MMAL_COMPONENT_CAMERA = 0,
+@@ -32,9 +32,6 @@ enum {
+ MMAL_CAMERA_PORT_COUNT
+ };
+
+-#define PREVIEW_FRAME_RATE_NUM 30
+-#define PREVIEW_FRAME_RATE_DEN 1
+-
+ #define PREVIEW_LAYER 2
+
+ extern int bcm2835_v4l2_debug;
+@@ -48,9 +45,19 @@ struct bm2835_mmal_dev {
+ /* controls */
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT];
++ enum v4l2_scene_mode scene_mode;
+ struct mmal_colourfx colourfx;
+ int hflip;
+ int vflip;
++ int red_gain;
++ int blue_gain;
++ enum mmal_parameter_exposuremode exposure_mode_user;
++ enum v4l2_exposure_auto_type exposure_mode_v4l2_user;
++ /* active exposure mode may differ if selected via a scene mode */
++ enum mmal_parameter_exposuremode exposure_mode_active;
++ enum mmal_parameter_exposuremeteringmode metering_mode;
++ unsigned int manual_shutter_speed;
++ bool exp_auto_priority;
+
+ /* allocated mmal instance and components */
+ struct vchiq_mmal_instance *instance;
+@@ -63,12 +70,18 @@ struct bm2835_mmal_dev {
+ unsigned int width; /* width */
+ unsigned int height; /* height */
+ unsigned int stride; /* stride */
++ unsigned int buffersize; /* buffer size with padding */
+ struct mmal_fmt *fmt;
++ struct v4l2_fract timeperframe;
+
+ /* H264 encode bitrate */
+ int encode_bitrate;
+ /* H264 bitrate mode. CBR/VBR */
+ int encode_bitrate_mode;
++ /* H264 profile */
++ enum v4l2_mpeg_video_h264_profile enc_profile;
++ /* H264 level */
++ enum v4l2_mpeg_video_h264_level enc_level;
+ /* JPEG Q-factor */
+ int q_factor;
+
+@@ -98,7 +111,7 @@ int bm2835_mmal_init_controls(
+ struct v4l2_ctrl_handler *hdl);
+
+ int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev);
+-
++int set_framerate_params(struct bm2835_mmal_dev *dev);
+
+ /* Debug helpers */
+
+diff --git a/drivers/media/platform/bcm2835/controls.c b/drivers/media/platform/bcm2835/controls.c
+index d1408e5..3017b94 100644
+--- a/drivers/media/platform/bcm2835/controls.c
++++ b/drivers/media/platform/bcm2835/controls.c
+@@ -30,11 +30,23 @@
+ #include "mmal-parameters.h"
+ #include "bcm2835-camera.h"
+
+-/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -24 to +24.
+- * These are in 1/6th increments so the effective range is -4.0EV to +4.0EV.
++/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -4.0 to +4.0.
++ * MMAL values are in 1/6th increments so the MMAL range is -24 to +24.
++ * V4L2 docs say value "is expressed in terms of EV, drivers should interpret
++ * the values as 0.001 EV units, where the value 1000 stands for +1 EV."
++ * V4L2 is limited to a max of 32 values in a menu, so count in 1/3rds from
++ * -4 to +4
+ */
+ static const s64 ev_bias_qmenu[] = {
+- -24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 21, 24
++ -4000, -3667, -3333,
++ -3000, -2667, -2333,
++ -2000, -1667, -1333,
++ -1000, -667, -333,
++ 0, 333, 667,
++ 1000, 1333, 1667,
++ 2000, 2333, 2667,
++ 3000, 3333, 3667,
++ 4000
+ };
+
+ /* Supported ISO values
+@@ -44,13 +56,19 @@ static const s64 iso_qmenu[] = {
+ 0, 100, 200, 400, 800,
+ };
+
++static const s64 mains_freq_qmenu[] = {
++ V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
++ V4L2_CID_POWER_LINE_FREQUENCY_50HZ,
++ V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
++ V4L2_CID_POWER_LINE_FREQUENCY_AUTO
++};
++
+ /* Supported video encode modes */
+ static const s64 bitrate_mode_qmenu[] = {
+ (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+ };
+
+-
+ enum bm2835_mmal_ctrl_type {
+ MMAL_CONTROL_TYPE_STD,
+ MMAL_CONTROL_TYPE_STD_MENU,
+@@ -77,6 +95,7 @@ struct bm2835_mmal_v4l2_ctrl {
+ const s64 *imenu; /* integer menu array */
+ u32 mmal_id; /* mmal parameter id */
+ bm2835_mmal_v4l2_ctrl_cb *setter;
++ bool ignore_errors;
+ };
+
+ struct v4l2_to_mmal_effects_setting {
+@@ -126,6 +145,25 @@ static const struct v4l2_to_mmal_effects_setting
+ 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} }
+ };
+
++struct v4l2_mmal_scene_config {
++ enum v4l2_scene_mode v4l2_scene;
++ enum mmal_parameter_exposuremode exposure_mode;
++ enum mmal_parameter_exposuremeteringmode metering_mode;
++};
++
++static const struct v4l2_mmal_scene_config scene_configs[] = {
++ /* V4L2_SCENE_MODE_NONE automatically added */
++ {
++ V4L2_SCENE_MODE_NIGHT,
++ MMAL_PARAM_EXPOSUREMODE_NIGHT,
++ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE
++ },
++ {
++ V4L2_SCENE_MODE_SPORTS,
++ MMAL_PARAM_EXPOSUREMODE_SPORTS,
++ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE
++ },
++};
+
+ /* control handlers*/
+
+@@ -133,10 +171,7 @@ static int ctrl_set_rational(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+ {
+- struct {
+- s32 num; /**< Numerator */
+- s32 den; /**< Denominator */
+- } rational_value;
++ struct mmal_parameter_rational rational_value;
+ struct vchiq_mmal_port *control;
+
+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
+@@ -166,6 +201,41 @@ static int ctrl_set_value(struct bm2835_mmal_dev *dev,
+ &u32_value, sizeof(u32_value));
+ }
+
++static int ctrl_set_value_menu(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ u32 u32_value;
++ struct vchiq_mmal_port *control;
++
++ if (ctrl->val > mmal_ctrl->max || ctrl->val < mmal_ctrl->min)
++ return 1;
++
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ u32_value = mmal_ctrl->imenu[ctrl->val];
++
++ return vchiq_mmal_port_parameter_set(dev->instance, control,
++ mmal_ctrl->mmal_id,
++ &u32_value, sizeof(u32_value));
++}
++
++static int ctrl_set_value_ev(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ s32 s32_value;
++ struct vchiq_mmal_port *control;
++
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ s32_value = (ctrl->val-12)*2; /* Convert from index to 1/6ths */
++
++ return vchiq_mmal_port_parameter_set(dev->instance, control,
++ mmal_ctrl->mmal_id,
++ &s32_value, sizeof(s32_value));
++}
++
+ static int ctrl_set_rotate(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+@@ -245,37 +315,97 @@ static int ctrl_set_exposure(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+ {
+- u32 u32_value;
++ enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user;
++ u32 shutter_speed = 0;
+ struct vchiq_mmal_port *control;
++ int ret = 0;
+
+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
+
++ if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) {
++ /* V4L2 is in 100usec increments.
++ * MMAL is 1usec.
++ */
++ dev->manual_shutter_speed = ctrl->val * 100;
++ } else if (mmal_ctrl->mmal_id == MMAL_PARAMETER_EXPOSURE_MODE) {
++ switch (ctrl->val) {
++ case V4L2_EXPOSURE_AUTO:
++ exp_mode = MMAL_PARAM_EXPOSUREMODE_AUTO;
++ break;
++
++ case V4L2_EXPOSURE_MANUAL:
++ exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF;
++ break;
++ }
++ dev->exposure_mode_user = exp_mode;
++ dev->exposure_mode_v4l2_user = ctrl->val;
++ } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) {
++ dev->exp_auto_priority = ctrl->val;
++ }
++
++ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) {
++ if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
++ shutter_speed = dev->manual_shutter_speed;
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &shutter_speed,
++ sizeof(shutter_speed));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &exp_mode,
++ sizeof(u32));
++ dev->exposure_mode_active = exp_mode;
++ }
++ /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should
++ * always apply irrespective of scene mode.
++ */
++ ret += set_framerate_params(dev);
++
++ return ret;
++}
++
++static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
+ switch (ctrl->val) {
+- case V4L2_EXPOSURE_AUTO:
+- u32_value = MMAL_PARAM_EXPOSUREMODE_AUTO;
++ case V4L2_EXPOSURE_METERING_AVERAGE:
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
+ break;
+
+- case V4L2_EXPOSURE_MANUAL:
+- u32_value = MMAL_PARAM_EXPOSUREMODE_OFF;
++ case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
+ break;
+
+- case V4L2_EXPOSURE_SHUTTER_PRIORITY:
+- u32_value = MMAL_PARAM_EXPOSUREMODE_SPORTS;
++ case V4L2_EXPOSURE_METERING_SPOT:
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
+ break;
+
+- case V4L2_EXPOSURE_APERTURE_PRIORITY:
+- u32_value = MMAL_PARAM_EXPOSUREMODE_NIGHT;
++ /* todo matrix weighting not added to Linux API till 3.9
++ case V4L2_EXPOSURE_METERING_MATRIX:
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
+ break;
++ */
+
+ }
+
+- /* todo: what about the other ten modes there are MMAL parameters for */
+- return vchiq_mmal_port_parameter_set(dev->instance, control,
++ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) {
++ struct vchiq_mmal_port *control;
++ u32 u32_value = dev->metering_mode;
++
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ return vchiq_mmal_port_parameter_set(dev->instance, control,
+ mmal_ctrl->mmal_id,
+ &u32_value, sizeof(u32_value));
++ } else
++ return 0;
+ }
+
+-static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev,
++static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+ {
+@@ -285,24 +415,18 @@ static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev,
+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
+
+ switch (ctrl->val) {
+- case V4L2_EXPOSURE_METERING_AVERAGE:
+- u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
++ case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
++ u32_value = MMAL_PARAM_FLICKERAVOID_OFF;
+ break;
+-
+- case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
+- u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
++ case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
++ u32_value = MMAL_PARAM_FLICKERAVOID_50HZ;
+ break;
+-
+- case V4L2_EXPOSURE_METERING_SPOT:
+- u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
++ case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
++ u32_value = MMAL_PARAM_FLICKERAVOID_60HZ;
+ break;
+-
+- /* todo matrix weighting not added to Linux API till 3.9
+- case V4L2_EXPOSURE_METERING_MATRIX:
+- u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
++ case V4L2_CID_POWER_LINE_FREQUENCY_AUTO:
++ u32_value = MMAL_PARAM_FLICKERAVOID_AUTO;
+ break;
+- */
+-
+ }
+
+ return vchiq_mmal_port_parameter_set(dev->instance, control,
+@@ -367,6 +491,29 @@ static int ctrl_set_awb_mode(struct bm2835_mmal_dev *dev,
+ &u32_value, sizeof(u32_value));
+ }
+
++static int ctrl_set_awb_gains(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ struct vchiq_mmal_port *control;
++ struct mmal_parameter_awbgains gains;
++
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ if (ctrl->id == V4L2_CID_RED_BALANCE)
++ dev->red_gain = ctrl->val;
++ else if (ctrl->id == V4L2_CID_BLUE_BALANCE)
++ dev->blue_gain = ctrl->val;
++
++ gains.r_gain.num = dev->red_gain;
++ gains.b_gain.num = dev->blue_gain;
++ gains.r_gain.den = gains.b_gain.den = 1000;
++
++ return vchiq_mmal_port_parameter_set(dev->instance, control,
++ mmal_ctrl->mmal_id,
++ &gains, sizeof(gains));
++}
++
+ static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+@@ -443,8 +590,8 @@ static int ctrl_set_colfx(struct bm2835_mmal_dev *dev,
+ &dev->colourfx, sizeof(dev->colourfx));
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+- "After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
+- mmal_ctrl, ctrl->id, ctrl->val, ret,
++ "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
++ __func__, mmal_ctrl, ctrl->id, ctrl->val, ret,
+ (ret == 0 ? 0 : -EINVAL));
+ return (ret == 0 ? 0 : EINVAL);
+ }
+@@ -494,7 +641,7 @@ static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev,
+ return 0;
+ }
+
+-static int ctrl_set_q_factor(struct bm2835_mmal_dev *dev,
++static int ctrl_set_image_encode_output(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+ {
+@@ -510,12 +657,247 @@ static int ctrl_set_q_factor(struct bm2835_mmal_dev *dev,
+ &u32_value, sizeof(u32_value));
+ }
+
++static int ctrl_set_video_encode_param_output(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ u32 u32_value;
++ struct vchiq_mmal_port *vid_enc_ctl;
++
++ vid_enc_ctl = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++
++ u32_value = ctrl->val;
++
++ return vchiq_mmal_port_parameter_set(dev->instance, vid_enc_ctl,
++ mmal_ctrl->mmal_id,
++ &u32_value, sizeof(u32_value));
++}
++
++static int ctrl_set_video_encode_profile_level(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ struct mmal_parameter_video_profile param;
++ int ret = 0;
++
++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
++ switch (ctrl->val) {
++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
++ dev->capture.enc_profile = ctrl->val;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
++ switch (ctrl->val) {
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
++ dev->capture.enc_level = ctrl->val;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ }
++
++ if (!ret) {
++ switch (dev->capture.enc_profile) {
++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
++ param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
++ break;
++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
++ param.profile =
++ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
++ break;
++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
++ param.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
++ break;
++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
++ param.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
++ break;
++ default:
++ /* Should never get here */
++ break;
++ }
++
++ switch (dev->capture.enc_level) {
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_1;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
++ param.level = MMAL_VIDEO_LEVEL_H264_1b;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
++ param.level = MMAL_VIDEO_LEVEL_H264_11;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
++ param.level = MMAL_VIDEO_LEVEL_H264_12;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
++ param.level = MMAL_VIDEO_LEVEL_H264_13;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_2;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
++ param.level = MMAL_VIDEO_LEVEL_H264_21;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
++ param.level = MMAL_VIDEO_LEVEL_H264_22;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_3;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
++ param.level = MMAL_VIDEO_LEVEL_H264_31;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
++ param.level = MMAL_VIDEO_LEVEL_H264_32;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_4;
++ break;
++ default:
++ /* Should never get here */
++ break;
++ }
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0],
++ mmal_ctrl->mmal_id,
++ &param, sizeof(param));
++ }
++ return ret;
++}
++
++static int ctrl_set_scene_mode(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ int ret = 0;
++ int shutter_speed;
++ struct vchiq_mmal_port *control;
++
++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "scene mode selected %d, was %d\n", ctrl->val,
++ dev->scene_mode);
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ if (ctrl->val == dev->scene_mode)
++ return 0;
++
++ if (ctrl->val == V4L2_SCENE_MODE_NONE) {
++ /* Restore all user selections */
++ dev->scene_mode = V4L2_SCENE_MODE_NONE;
++
++ if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF)
++ shutter_speed = dev->manual_shutter_speed;
++ else
++ shutter_speed = 0;
++
++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n",
++ __func__, shutter_speed, dev->exposure_mode_user,
++ dev->metering_mode);
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &shutter_speed,
++ sizeof(shutter_speed));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &dev->exposure_mode_user,
++ sizeof(u32));
++ dev->exposure_mode_active = dev->exposure_mode_user;
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ &dev->metering_mode,
++ sizeof(u32));
++ ret += set_framerate_params(dev);
++ } else {
++ /* Set up scene mode */
++ int i;
++ const struct v4l2_mmal_scene_config *scene = NULL;
++ int shutter_speed;
++ enum mmal_parameter_exposuremode exposure_mode;
++ enum mmal_parameter_exposuremeteringmode metering_mode;
++
++ for (i = 0; i < ARRAY_SIZE(scene_configs); i++) {
++ if (scene_configs[i].v4l2_scene ==
++ ctrl->val) {
++ scene = &scene_configs[i];
++ break;
++ }
++ }
++ if (i >= ARRAY_SIZE(scene_configs))
++ return -EINVAL;
++
++ /* Set all the values */
++ dev->scene_mode = ctrl->val;
++
++ if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
++ shutter_speed = dev->manual_shutter_speed;
++ else
++ shutter_speed = 0;
++ exposure_mode = scene->exposure_mode;
++ metering_mode = scene->metering_mode;
++
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n",
++ __func__, shutter_speed, exposure_mode, metering_mode);
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance, control,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &shutter_speed,
++ sizeof(shutter_speed));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &exposure_mode,
++ sizeof(u32));
++ dev->exposure_mode_active = exposure_mode;
++ ret += vchiq_mmal_port_parameter_set(dev->instance, control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &exposure_mode,
++ sizeof(u32));
++ ret += vchiq_mmal_port_parameter_set(dev->instance, control,
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ &metering_mode,
++ sizeof(u32));
++ ret += set_framerate_params(dev);
++ }
++ if (ret) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: Setting scene to %d, ret=%d\n",
++ __func__, ctrl->val, ret);
++ ret = -EINVAL;
++ }
++ return 0;
++}
++
+ static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
+ {
+ struct bm2835_mmal_dev *dev =
+ container_of(ctrl->handler, struct bm2835_mmal_dev,
+ ctrl_handler);
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv;
++ int ret;
+
+ if ((mmal_ctrl == NULL) ||
+ (mmal_ctrl->id != ctrl->id) ||
+@@ -524,7 +906,13 @@ static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
+ return -EINVAL;
+ }
+
+- return mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
++ ret = mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
++ if (ret)
++ pr_warn("ctrl id:%d/MMAL param %08X- returned ret %d\n",
++ ctrl->id, mmal_ctrl->mmal_id, ret);
++ if (mmal_ctrl->ignore_errors)
++ ret = 0;
++ return ret;
+ }
+
+ static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = {
+@@ -537,40 +925,54 @@ static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
+ {
+ V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD,
+ -100, 100, 0, 1, NULL,
+- MMAL_PARAMETER_SATURATION, &ctrl_set_rational
++ MMAL_PARAMETER_SATURATION,
++ &ctrl_set_rational,
++ false
+ },
+ {
+ V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD,
+ -100, 100, 0, 1, NULL,
+- MMAL_PARAMETER_SHARPNESS, &ctrl_set_rational
++ MMAL_PARAMETER_SHARPNESS,
++ &ctrl_set_rational,
++ false
+ },
+ {
+ V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD,
+ -100, 100, 0, 1, NULL,
+- MMAL_PARAMETER_CONTRAST, &ctrl_set_rational
++ MMAL_PARAMETER_CONTRAST,
++ &ctrl_set_rational,
++ false
+ },
+ {
+ V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD,
+ 0, 100, 50, 1, NULL,
+- MMAL_PARAMETER_BRIGHTNESS, &ctrl_set_rational
++ MMAL_PARAMETER_BRIGHTNESS,
++ &ctrl_set_rational,
++ false
+ },
+ {
+ V4L2_CID_ISO_SENSITIVITY, MMAL_CONTROL_TYPE_INT_MENU,
+ 0, ARRAY_SIZE(iso_qmenu) - 1, 0, 1, iso_qmenu,
+- MMAL_PARAMETER_ISO, &ctrl_set_value
++ MMAL_PARAMETER_ISO,
++ &ctrl_set_value_menu,
++ false
+ },
+ {
+ V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD,
+ 0, 1, 0, 1, NULL,
+- MMAL_PARAMETER_VIDEO_STABILISATION, &ctrl_set_value
++ MMAL_PARAMETER_VIDEO_STABILISATION,
++ &ctrl_set_value,
++ false
+ },
+ /* {
+ 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
+- },
+-*/ {
++ }, */
++ {
+ V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
+ ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
+- MMAL_PARAMETER_EXPOSURE_MODE, &ctrl_set_exposure
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &ctrl_set_exposure,
++ false
+ },
+ /* todo this needs mixing in with set exposure
+ {
+@@ -578,83 +980,258 @@ static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
+ },
+ */
+ {
++ V4L2_CID_EXPOSURE_ABSOLUTE, MMAL_CONTROL_TYPE_STD,
++ /* Units of 100usecs */
++ 1, 1*1000*10, 100*10, 1, NULL,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &ctrl_set_exposure,
++ false
++ },
++ {
+ V4L2_CID_AUTO_EXPOSURE_BIAS, MMAL_CONTROL_TYPE_INT_MENU,
+ 0, ARRAY_SIZE(ev_bias_qmenu) - 1,
+ (ARRAY_SIZE(ev_bias_qmenu)+1)/2 - 1, 0, ev_bias_qmenu,
+- MMAL_PARAMETER_EXPOSURE_COMP, &ctrl_set_value
++ MMAL_PARAMETER_EXPOSURE_COMP,
++ &ctrl_set_value_ev,
++ false
++ },
++ {
++ V4L2_CID_EXPOSURE_AUTO_PRIORITY, MMAL_CONTROL_TYPE_STD,
++ 0, 1,
++ 0, 1, NULL,
++ 0, /* Dummy MMAL ID as it gets mapped into FPS range*/
++ &ctrl_set_exposure,
++ false
+ },
+ {
+ V4L2_CID_EXPOSURE_METERING,
+ MMAL_CONTROL_TYPE_STD_MENU,
+ ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
+- MMAL_PARAMETER_EXP_METERING_MODE, &ctrl_set_metering_mode
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ &ctrl_set_metering_mode,
++ false
+ },
+ {
+ V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+ MMAL_CONTROL_TYPE_STD_MENU,
+- ~0x3fe, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
+- MMAL_PARAMETER_AWB_MODE, &ctrl_set_awb_mode
++ ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
++ MMAL_PARAMETER_AWB_MODE,
++ &ctrl_set_awb_mode,
++ false
++ },
++ {
++ V4L2_CID_RED_BALANCE, MMAL_CONTROL_TYPE_STD,
++ 1, 7999, 1000, 1, NULL,
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++ &ctrl_set_awb_gains,
++ false
++ },
++ {
++ V4L2_CID_BLUE_BALANCE, MMAL_CONTROL_TYPE_STD,
++ 1, 7999, 1000, 1, NULL,
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++ &ctrl_set_awb_gains,
++ false
+ },
+ {
+ V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
+ 0, 15, V4L2_COLORFX_NONE, 0, NULL,
+- MMAL_PARAMETER_IMAGE_EFFECT, &ctrl_set_image_effect
++ MMAL_PARAMETER_IMAGE_EFFECT,
++ &ctrl_set_image_effect,
++ false
+ },
+ {
+ V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD,
+ 0, 0xffff, 0x8080, 1, NULL,
+- MMAL_PARAMETER_COLOUR_EFFECT, &ctrl_set_colfx
++ MMAL_PARAMETER_COLOUR_EFFECT,
++ &ctrl_set_colfx,
++ false
+ },
+ {
+ V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD,
+ 0, 360, 0, 90, NULL,
+- MMAL_PARAMETER_ROTATION, &ctrl_set_rotate
++ MMAL_PARAMETER_ROTATION,
++ &ctrl_set_rotate,
++ false
+ },
+ {
+ V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD,
+ 0, 1, 0, 1, NULL,
+- MMAL_PARAMETER_MIRROR, &ctrl_set_flip
++ MMAL_PARAMETER_MIRROR,
++ &ctrl_set_flip,
++ false
+ },
+ {
+ V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD,
+ 0, 1, 0, 1, NULL,
+- MMAL_PARAMETER_MIRROR, &ctrl_set_flip
++ MMAL_PARAMETER_MIRROR,
++ &ctrl_set_flip,
++ false
+ },
+ {
+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
+ 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
+ 0, 0, bitrate_mode_qmenu,
+- MMAL_PARAMETER_RATECONTROL, &ctrl_set_bitrate_mode
++ MMAL_PARAMETER_RATECONTROL,
++ &ctrl_set_bitrate_mode,
++ false
+ },
+ {
+ V4L2_CID_MPEG_VIDEO_BITRATE, MMAL_CONTROL_TYPE_STD,
+ 25*1000, 25*1000*1000, 10*1000*1000, 25*1000, NULL,
+- MMAL_PARAMETER_VIDEO_BIT_RATE, &ctrl_set_bitrate
++ MMAL_PARAMETER_VIDEO_BIT_RATE,
++ &ctrl_set_bitrate,
++ false
+ },
+ {
+ V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD,
+- 0, 100,
++ 1, 100,
+ 30, 1, NULL,
+- MMAL_PARAMETER_JPEG_Q_FACTOR, &ctrl_set_q_factor
++ MMAL_PARAMETER_JPEG_Q_FACTOR,
++ &ctrl_set_image_encode_output,
++ false
++ },
++ {
++ V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU,
++ 0, ARRAY_SIZE(mains_freq_qmenu) - 1,
++ 1, 1, NULL,
++ MMAL_PARAMETER_FLICKER_AVOID,
++ &ctrl_set_flicker_avoidance,
++ false
++ },
++ {
++ V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, MMAL_CONTROL_TYPE_STD,
++ 0, 1,
++ 0, 1, NULL,
++ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER,
++ &ctrl_set_video_encode_param_output,
++ true /* Errors ignored as requires latest firmware to work */
++ },
++ {
++ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
++ MMAL_CONTROL_TYPE_STD_MENU,
++ ~((1<<V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, 1, NULL,
++ MMAL_PARAMETER_PROFILE,
++ &ctrl_set_video_encode_profile_level,
++ false
++ },
++ {
++ V4L2_CID_MPEG_VIDEO_H264_LEVEL, MMAL_CONTROL_TYPE_STD_MENU,
++ ~((1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 1, NULL,
++ MMAL_PARAMETER_PROFILE,
++ &ctrl_set_video_encode_profile_level,
++ false
++ },
++ {
++ V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
++ -1, /* Min is computed at runtime */
++ V4L2_SCENE_MODE_TEXT,
++ V4L2_SCENE_MODE_NONE, 1, NULL,
++ MMAL_PARAMETER_PROFILE,
++ &ctrl_set_scene_mode,
++ false
++ },
++ {
++ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, MMAL_CONTROL_TYPE_STD,
++ 0, 0x7FFFFFFF, 60, 1, NULL,
++ MMAL_PARAMETER_INTRAPERIOD,
++ &ctrl_set_video_encode_param_output,
++ false
+ },
+ };
+
+ int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
+ {
+ int c;
+- int ret;
++ int ret = 0;
+
+ for (c = 0; c < V4L2_CTRL_COUNT; c++) {
+ if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) {
+ ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c],
+ &v4l2_ctrls[c]);
+- if (ret)
++ if (!v4l2_ctrls[c].ignore_errors && ret) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Failed when setting default values for ctrl %d\n",
++ c);
+ break;
++ }
+ }
+ }
+ return ret;
+ }
+
++int set_framerate_params(struct bm2835_mmal_dev *dev)
++{
++ struct mmal_parameter_fps_range fps_range;
++ int ret;
++
++ if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) &&
++ (dev->exp_auto_priority)) {
++ /* Variable FPS. Define min FPS as 1fps.
++ * Max as max defined FPS.
++ */
++ fps_range.fps_low.num = 1;
++ fps_range.fps_low.den = 1;
++ fps_range.fps_high.num = dev->capture.timeperframe.denominator;
++ fps_range.fps_high.den = dev->capture.timeperframe.numerator;
++ } else {
++ /* Fixed FPS - set min and max to be the same */
++ fps_range.fps_low.num = fps_range.fps_high.num =
++ dev->capture.timeperframe.denominator;
++ fps_range.fps_low.den = fps_range.fps_high.den =
++ dev->capture.timeperframe.numerator;
++ }
++
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Set fps range to %d/%d to %d/%d\n",
++ fps_range.fps_low.num,
++ fps_range.fps_low.den,
++ fps_range.fps_high.num,
++ fps_range.fps_high.den
++ );
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_PREVIEW],
++ MMAL_PARAMETER_FPS_RANGE,
++ &fps_range, sizeof(fps_range));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_VIDEO],
++ MMAL_PARAMETER_FPS_RANGE,
++ &fps_range, sizeof(fps_range));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_CAPTURE],
++ MMAL_PARAMETER_FPS_RANGE,
++ &fps_range, sizeof(fps_range));
++ if (ret)
++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Failed to set fps ret %d\n",
++ ret);
++
++ return ret;
++
++}
++
+ int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl_handler *hdl)
+ {
+@@ -674,10 +1251,30 @@ int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
+ break;
+
+ case MMAL_CONTROL_TYPE_STD_MENU:
++ {
++ int mask = ctrl->min;
++
++ if (ctrl->id == V4L2_CID_SCENE_MODE) {
++ /* Special handling to work out the mask
++ * value based on the scene_configs array
++ * at runtime. Reduces the chance of
++ * mismatches.
++ */
++ int i;
++ mask = 1<<V4L2_SCENE_MODE_NONE;
++ for (i = 0;
++ i < ARRAY_SIZE(scene_configs);
++ i++) {
++ mask |= 1<<scene_configs[i].v4l2_scene;
++ }
++ mask = ~mask;
++ }
++
+ dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
+ &bm2835_mmal_ctrl_ops, ctrl->id,
+- ctrl->max, ctrl->min, ctrl->def);
++ ctrl->max, mask, ctrl->def);
+ break;
++ }
+
+ case MMAL_CONTROL_TYPE_INT_MENU:
+ dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
+diff --git a/drivers/media/platform/bcm2835/mmal-common.h b/drivers/media/platform/bcm2835/mmal-common.h
+index 84abbb3..35698c8 100644
+--- a/drivers/media/platform/bcm2835/mmal-common.h
++++ b/drivers/media/platform/bcm2835/mmal-common.h
+@@ -26,6 +26,7 @@
+ struct mmal_fmt {
+ char *name;
+ u32 fourcc; /* v4l2 format id */
++ int flags; /* v4l2 flags field */
+ u32 mmal;
+ int depth;
+ u32 mmal_component; /* MMAL component index to be used to encode */
+diff --git a/drivers/media/platform/bcm2835/mmal-encodings.h b/drivers/media/platform/bcm2835/mmal-encodings.h
+index 856e80e..024d620 100644
+--- a/drivers/media/platform/bcm2835/mmal-encodings.h
++++ b/drivers/media/platform/bcm2835/mmal-encodings.h
+@@ -12,6 +12,8 @@
+ * Simon Mellor <simellor@broadcom.com>
+ * Luke Diamand <luked@broadcom.com>
+ */
++#ifndef MMAL_ENCODINGS_H
++#define MMAL_ENCODINGS_H
+
+ #define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4')
+ #define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3')
+@@ -27,6 +29,7 @@
+ #define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ')
+ #define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O')
+ #define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K')
++#define MMAL_ENCODING_MJPEG MMAL_FOURCC('M', 'J', 'P', 'G')
+
+ #define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G')
+ #define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ')
+@@ -91,3 +94,34 @@
+ #define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1')
+ /** Implicitly delineated NAL units without emulation prevention */
+ #define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ')
++
++
++/** \defgroup MmalColorSpace List of pre-defined video color spaces
++ * This defines a list of common color spaces. This list isn't exhaustive and
++ * is only provided as a convenience to avoid clients having to use FourCC
++ * codes directly. However components are allowed to define and use their own
++ * FourCC codes.
++ */
++/* @{ */
++
++/** Unknown color space */
++#define MMAL_COLOR_SPACE_UNKNOWN 0
++/** ITU-R BT.601-5 [SDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y', '6', '0', '1')
++/** ITU-R BT.709-3 [HDTV] */
++#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y', '7', '0', '9')
++/** JPEG JFIF */
++#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y', 'J', 'F', 'I')
++/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */
++#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y', 'F', 'C', 'C')
++/** Society of Motion Picture and Television Engineers 240M (1999) */
++#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y', '2', '4', '0')
++/** ITU-R BT.470-2 System M */
++#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y', '_', '_', 'M')
++/** ITU-R BT.470-2 System BG */
++#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y', '_', 'B', 'G')
++/** JPEG JFIF, but with 16..255 luma */
++#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y', 'Y', '1', '6')
++/* @} MmalColorSpace List */
++
++#endif /* MMAL_ENCODINGS_H */
+diff --git a/drivers/media/platform/bcm2835/mmal-parameters.h b/drivers/media/platform/bcm2835/mmal-parameters.h
+index c611b58..aa0fd18 100644
+--- a/drivers/media/platform/bcm2835/mmal-parameters.h
++++ b/drivers/media/platform/bcm2835/mmal-parameters.h
+@@ -57,7 +57,8 @@ enum mmal_parameter_common_type {
+ MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
+ MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
+- MMAL_PARAMETER_SYSTEM_TIME /**< MMAL_PARAMETER_UINT64_T */
++ MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */
++ MMAL_PARAMETER_NO_IMAGE_PADDING /**< MMAL_PARAMETER_BOOLEAN_T */
+ };
+
+ /* camera parameters */
+@@ -161,6 +162,13 @@ enum mmal_parameter_camera_type {
+ MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_SHUTTER_SPEED, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS, /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
++};
++
++struct mmal_parameter_rational {
++ s32 num; /**< Numerator */
++ s32 den; /**< Denominator */
+ };
+
+ enum mmal_parameter_camera_config_timestamp_mode {
+@@ -176,6 +184,14 @@ enum mmal_parameter_camera_config_timestamp_mode {
+ */
+ };
+
++struct mmal_parameter_fps_range {
++ /**< Low end of the permitted framerate range */
++ struct mmal_parameter_rational fps_low;
++ /**< High end of the permitted framerate range */
++ struct mmal_parameter_rational fps_high;
++};
++
++
+ /* camera configuration parameter */
+ struct mmal_parameter_camera_config {
+ /* Parameters for setting up the image pools */
+@@ -270,6 +286,19 @@ enum mmal_parameter_imagefx {
+ MMAL_PARAM_IMAGEFX_CARTOON,
+ };
+
++enum MMAL_PARAM_FLICKERAVOID_T {
++ MMAL_PARAM_FLICKERAVOID_OFF,
++ MMAL_PARAM_FLICKERAVOID_AUTO,
++ MMAL_PARAM_FLICKERAVOID_50HZ,
++ MMAL_PARAM_FLICKERAVOID_60HZ,
++ MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
++};
++
++struct mmal_parameter_awbgains {
++ struct mmal_parameter_rational r_gain; /**< Red gain */
++ struct mmal_parameter_rational b_gain; /**< Blue gain */
++};
++
+ /** Manner of video rate control */
+ enum mmal_parameter_rate_control_mode {
+ MMAL_VIDEO_RATECONTROL_DEFAULT,
+@@ -279,6 +308,85 @@ enum mmal_parameter_rate_control_mode {
+ MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
+ };
+
++enum mmal_video_profile {
++ MMAL_VIDEO_PROFILE_H263_BASELINE,
++ MMAL_VIDEO_PROFILE_H263_H320CODING,
++ MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
++ MMAL_VIDEO_PROFILE_H263_ISWV2,
++ MMAL_VIDEO_PROFILE_H263_ISWV3,
++ MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
++ MMAL_VIDEO_PROFILE_H263_INTERNET,
++ MMAL_VIDEO_PROFILE_H263_INTERLACE,
++ MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
++ MMAL_VIDEO_PROFILE_MP4V_CORE,
++ MMAL_VIDEO_PROFILE_MP4V_MAIN,
++ MMAL_VIDEO_PROFILE_MP4V_NBIT,
++ MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
++ MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
++ MMAL_VIDEO_PROFILE_MP4V_HYBRID,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
++ MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
++ MMAL_VIDEO_PROFILE_H264_BASELINE,
++ MMAL_VIDEO_PROFILE_H264_MAIN,
++ MMAL_VIDEO_PROFILE_H264_EXTENDED,
++ MMAL_VIDEO_PROFILE_H264_HIGH,
++ MMAL_VIDEO_PROFILE_H264_HIGH10,
++ MMAL_VIDEO_PROFILE_H264_HIGH422,
++ MMAL_VIDEO_PROFILE_H264_HIGH444,
++ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
++ MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
++};
++
++enum mmal_video_level {
++ MMAL_VIDEO_LEVEL_H263_10,
++ MMAL_VIDEO_LEVEL_H263_20,
++ MMAL_VIDEO_LEVEL_H263_30,
++ MMAL_VIDEO_LEVEL_H263_40,
++ MMAL_VIDEO_LEVEL_H263_45,
++ MMAL_VIDEO_LEVEL_H263_50,
++ MMAL_VIDEO_LEVEL_H263_60,
++ MMAL_VIDEO_LEVEL_H263_70,
++ MMAL_VIDEO_LEVEL_MP4V_0,
++ MMAL_VIDEO_LEVEL_MP4V_0b,
++ MMAL_VIDEO_LEVEL_MP4V_1,
++ MMAL_VIDEO_LEVEL_MP4V_2,
++ MMAL_VIDEO_LEVEL_MP4V_3,
++ MMAL_VIDEO_LEVEL_MP4V_4,
++ MMAL_VIDEO_LEVEL_MP4V_4a,
++ MMAL_VIDEO_LEVEL_MP4V_5,
++ MMAL_VIDEO_LEVEL_MP4V_6,
++ MMAL_VIDEO_LEVEL_H264_1,
++ MMAL_VIDEO_LEVEL_H264_1b,
++ MMAL_VIDEO_LEVEL_H264_11,
++ MMAL_VIDEO_LEVEL_H264_12,
++ MMAL_VIDEO_LEVEL_H264_13,
++ MMAL_VIDEO_LEVEL_H264_2,
++ MMAL_VIDEO_LEVEL_H264_21,
++ MMAL_VIDEO_LEVEL_H264_22,
++ MMAL_VIDEO_LEVEL_H264_3,
++ MMAL_VIDEO_LEVEL_H264_31,
++ MMAL_VIDEO_LEVEL_H264_32,
++ MMAL_VIDEO_LEVEL_H264_4,
++ MMAL_VIDEO_LEVEL_H264_41,
++ MMAL_VIDEO_LEVEL_H264_42,
++ MMAL_VIDEO_LEVEL_H264_5,
++ MMAL_VIDEO_LEVEL_H264_51,
++ MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
++};
++
++struct mmal_parameter_video_profile {
++ enum mmal_video_profile profile;
++ enum mmal_video_level level;
++};
++
+ /* video parameters */
+
+ enum mmal_parameter_video_type {
+@@ -407,7 +515,16 @@ enum mmal_parameter_video_type {
+ MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
+
+ /** @ref MMAL_PARAMETER_BYTES_T */
+- MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3
++ MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3,
++
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS,
++
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG,
++
++ /**< @ref MMAL_PARAMETER_BOOLEAN_T */
++ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER
+ };
+
+ /** Valid mirror modes */
+diff --git a/drivers/media/platform/bcm2835/mmal-vchiq.c b/drivers/media/platform/bcm2835/mmal-vchiq.c
+index a06fb44..76f249e 100644
+--- a/drivers/media/platform/bcm2835/mmal-vchiq.c
++++ b/drivers/media/platform/bcm2835/mmal-vchiq.c
+@@ -742,7 +742,7 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
+ return ret;
+ }
+
+- ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, HZ);
++ ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, 3*HZ);
+ if (ret <= 0) {
+ pr_err("error %d waiting for sync completion\n", ret);
+ if (ret == 0)
+@@ -1326,7 +1326,7 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance,
+ memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+ rmsg->u.port_parameter_get_reply.size);
+
+- pr_info("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
++ pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
+ ret, port->component->handle, port->handle, parameter_id);
+
+ release_msg:
+--
+1.8.3.2
+