diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0233-V4L2-driver-updates-1393.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.4/0233-V4L2-driver-updates-1393.patch | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0233-V4L2-driver-updates-1393.patch b/target/linux/brcm2708/patches-4.4/0233-V4L2-driver-updates-1393.patch new file mode 100644 index 0000000000..7f9ec20f8f --- /dev/null +++ b/target/linux/brcm2708/patches-4.4/0233-V4L2-driver-updates-1393.patch @@ -0,0 +1,718 @@ +From 12b8bcf4d6d4a188ad2bcbae564f32fba4166f71 Mon Sep 17 00:00:00 2001 +From: 6by9 <6by9@users.noreply.github.com> +Date: Fri, 8 Apr 2016 18:15:43 +0100 +Subject: [PATCH 233/304] V4L2 driver updates (#1393) + +* BCM2835-V4L2: Correct ISO control and add V4L2_CID_ISO_SENSITIVITY_AUTO + +https://github.com/raspberrypi/linux/issues/1251 + +V4L2_CID_ISO_SENSITIVITY was not advertising ISO*1000 as it should. +V4L2_CID_ISO_SENSITIVITY_AUTO was not implemented, so was taking +V4L2_CID_ISO_SENSITIVITY as 0 for auto mode. +Still accepts 0 for auto, but also abides by the new parameter. + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +* BCM2835-V4L2: Add a video_nr parameter. + +Adds a kernel parameter "video_nr" to specify the preferred +/dev/videoX device node. +https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=136120&p=905545 + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +* BCM2835-V4L2: Add support for multiple cameras + +Ask GPU on load how many cameras have been detected, and +enumerate that number of devices. +Only applicable on the Compute Module as no other device +exposes multiple CSI2 interfaces. + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +* BCM2835-V4L2: Add control of the overlay location and alpha. + +Actually do something useful in vidioc_s_fmt_vid_overlay and +vidioc_try_fmt_vid_overlay, rather than effectively having +read-only fields. + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +* BCM2835-V4L2: V4L2-Compliance failure fix + +VIDIOC_TRY_FMT was failing due to bytesperline not +being set correctly by default. + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> + +* BCM2835-V4L2: Make all module parameters static + +Clean up to correct variable scope + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> +--- + drivers/media/platform/bcm2835/bcm2835-camera.c | 372 +++++++++++++++-------- + drivers/media/platform/bcm2835/bcm2835-camera.h | 19 +- + drivers/media/platform/bcm2835/controls.c | 31 +- + drivers/media/platform/bcm2835/mmal-parameters.h | 33 ++ + 4 files changed, 320 insertions(+), 135 deletions(-) + +--- a/drivers/media/platform/bcm2835/bcm2835-camera.c ++++ b/drivers/media/platform/bcm2835/bcm2835-camera.c +@@ -45,6 +45,8 @@ + #define MAX_VIDEO_MODE_WIDTH 1280 + #define MAX_VIDEO_MODE_HEIGHT 720 + ++#define MAX_BCM2835_CAMERAS 2 ++ + MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture"); + MODULE_AUTHOR("Vincent Sanders"); + MODULE_LICENSE("GPL"); +@@ -54,8 +56,13 @@ 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; ++#define UNSET (-1) ++static int video_nr[] = {[0 ... (MAX_BCM2835_CAMERAS - 1)] = UNSET }; ++module_param_array(video_nr, int, NULL, 0644); ++MODULE_PARM_DESC(video_nr, "videoX start numbers, -1 is autodetect"); ++ ++static int max_video_width = MAX_VIDEO_MODE_WIDTH; ++static 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); +@@ -70,11 +77,12 @@ MODULE_PARM_DESC(max_video_height, "Thre + * our function table list (actually switch to an alternate set, but same + * result). + */ +-int gst_v4l2src_is_broken = 0; ++static int gst_v4l2src_is_broken; + 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 */ ++/* global device data array */ ++static struct bm2835_mmal_dev *gdev[MAX_BCM2835_CAMERAS]; + + #define FPS_MIN 1 + #define FPS_MAX 90 +@@ -413,6 +421,17 @@ static int enable_camera(struct bm2835_m + { + int ret; + if (!dev->camera_use_count) { ++ ret = vchiq_mmal_port_parameter_set( ++ dev->instance, ++ &dev->component[MMAL_COMPONENT_CAMERA]->control, ++ MMAL_PARAMETER_CAMERA_NUM, &dev->camera_num, ++ sizeof(dev->camera_num)); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed setting camera num, ret %d\n", ret); ++ return -EINVAL; ++ } ++ + ret = vchiq_mmal_component_enable( + dev->instance, + dev->component[MMAL_COMPONENT_CAMERA]); +@@ -647,6 +666,30 @@ static struct vb2_ops bm2835_mmal_video_ + IOCTL operations + ------------------------------------------------------------------*/ + ++static int set_overlay_params(struct bm2835_mmal_dev *dev, ++ struct vchiq_mmal_port *port) ++{ ++ int ret; ++ struct mmal_parameter_displayregion prev_config = { ++ .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA | ++ MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN, ++ .layer = PREVIEW_LAYER, ++ .alpha = dev->overlay.global_alpha, ++ .fullscreen = 0, ++ .dest_rect = { ++ .x = dev->overlay.w.left, ++ .y = dev->overlay.w.top, ++ .width = dev->overlay.w.width, ++ .height = dev->overlay.w.height, ++ }, ++ }; ++ ret = vchiq_mmal_port_parameter_set(dev->instance, port, ++ MMAL_PARAMETER_DISPLAYREGION, ++ &prev_config, sizeof(prev_config)); ++ ++ return ret; ++} ++ + /* overlay ioctl */ + static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +@@ -678,10 +721,31 @@ static int vidioc_g_fmt_vid_overlay(stru + static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, + struct v4l2_format *f) + { +- /* Only support one format so get the current one. */ +- vidioc_g_fmt_vid_overlay(file, priv, f); ++ struct bm2835_mmal_dev *dev = video_drvdata(file); + +- /* todo: allow the size and/or offset to be changed. */ ++ f->fmt.win.field = V4L2_FIELD_NONE; ++ f->fmt.win.chromakey = 0; ++ f->fmt.win.clips = NULL; ++ f->fmt.win.clipcount = 0; ++ f->fmt.win.bitmap = NULL; ++ ++ v4l_bound_align_image(&f->fmt.win.w.width, MIN_WIDTH, MAX_WIDTH, 1, ++ &f->fmt.win.w.height, MIN_HEIGHT, MAX_HEIGHT, ++ 1, 0); ++ v4l_bound_align_image(&f->fmt.win.w.left, MIN_WIDTH, MAX_WIDTH, 1, ++ &f->fmt.win.w.top, MIN_HEIGHT, MAX_HEIGHT, ++ 1, 0); ++ ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "Overlay: Now w/h %dx%d l/t %dx%d\n", ++ f->fmt.win.w.width, f->fmt.win.w.height, ++ f->fmt.win.w.left, f->fmt.win.w.top); ++ ++ v4l2_dump_win_format(1, ++ bcm2835_v4l2_debug, ++ &dev->v4l2_dev, ++ &f->fmt.win, ++ __func__); + return 0; + } + +@@ -693,8 +757,11 @@ static int vidioc_s_fmt_vid_overlay(stru + vidioc_try_fmt_vid_overlay(file, priv, f); + + dev->overlay = f->fmt.win; ++ if (dev->component[MMAL_COMPONENT_PREVIEW]->enabled) { ++ set_overlay_params(dev, ++ &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]); ++ } + +- /* todo: program the preview port parameters */ + return 0; + } + +@@ -704,20 +771,6 @@ static int vidioc_overlay(struct file *f + struct bm2835_mmal_dev *dev = video_drvdata(file); + struct vchiq_mmal_port *src; + struct vchiq_mmal_port *dst; +- struct mmal_parameter_displayregion prev_config = { +- .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA | +- MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN, +- .layer = PREVIEW_LAYER, +- .alpha = 255, +- .fullscreen = 0, +- .dest_rect = { +- .x = dev->overlay.w.left, +- .y = dev->overlay.w.top, +- .width = dev->overlay.w.width, +- .height = dev->overlay.w.height, +- }, +- }; +- + if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) || + (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled)) + return 0; /* already in requested state */ +@@ -749,9 +802,7 @@ static int vidioc_overlay(struct file *f + if (ret < 0) + goto error; + +- ret = vchiq_mmal_port_parameter_set(dev->instance, dst, +- MMAL_PARAMETER_DISPLAYREGION, +- &prev_config, sizeof(prev_config)); ++ ret = set_overlay_params(dev, dst); + if (ret < 0) + goto error; + +@@ -782,6 +833,9 @@ static int vidioc_g_fbuf(struct file *fi + struct vchiq_mmal_port *preview_port = + &dev->component[MMAL_COMPONENT_CAMERA]-> + output[MMAL_CAMERA_PORT_PREVIEW]; ++ ++ a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | ++ V4L2_FBUF_CAP_GLOBAL_ALPHA; + a->flags = V4L2_FBUF_FLAG_OVERLAY; + a->fmt.width = preview_port->es.video.width; + a->fmt.height = preview_port->es.video.height; +@@ -1445,6 +1499,34 @@ static struct video_device vdev_template + .release = video_device_release_empty, + }; + ++static int get_num_cameras(struct vchiq_mmal_instance *instance) ++{ ++ int ret; ++ struct vchiq_mmal_component *cam_info_component; ++ struct mmal_parameter_camera_info_t cam_info = {0}; ++ int param_size = sizeof(cam_info); ++ ++ /* create a camera_info component */ ++ ret = vchiq_mmal_component_init(instance, "camera_info", ++ &cam_info_component); ++ if (ret < 0) ++ /* Unusual failure - let's guess one camera. */ ++ return 1; ++ ++ if (vchiq_mmal_port_parameter_get(instance, ++ &cam_info_component->control, ++ MMAL_PARAMETER_CAMERA_INFO, ++ &cam_info, ++ ¶m_size)) { ++ pr_info("Failed to get camera info\n"); ++ } ++ ++ vchiq_mmal_component_finalise(instance, ++ cam_info_component); ++ ++ return cam_info.num_cameras; ++} ++ + static int set_camera_parameters(struct vchiq_mmal_instance *instance, + struct vchiq_mmal_component *camera) + { +@@ -1685,7 +1767,9 @@ static int __init bm2835_mmal_init_devic + /* video device needs to be able to access instance data */ + video_set_drvdata(vfd, dev); + +- ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); ++ ret = video_register_device(vfd, ++ VFL_TYPE_GRABBER, ++ video_nr[dev->camera_num]); + if (ret < 0) + return ret; + +@@ -1696,10 +1780,52 @@ static int __init bm2835_mmal_init_devic + return 0; + } + ++void bcm2835_cleanup_instance(struct bm2835_mmal_dev *dev) ++{ ++ if (!dev) ++ return; ++ ++ v4l2_info(&dev->v4l2_dev, "unregistering %s\n", ++ video_device_node_name(&dev->vdev)); ++ ++ video_unregister_device(&dev->vdev); ++ ++ if (dev->capture.encode_component) { ++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, ++ "mmal_exit - disconnect tunnel\n"); ++ vchiq_mmal_port_connect_tunnel(dev->instance, ++ dev->capture.camera_port, NULL); ++ vchiq_mmal_component_disable(dev->instance, ++ dev->capture.encode_component); ++ } ++ vchiq_mmal_component_disable(dev->instance, ++ dev->component[MMAL_COMPONENT_CAMERA]); ++ ++ vchiq_mmal_component_finalise(dev->instance, ++ dev-> ++ component[MMAL_COMPONENT_VIDEO_ENCODE]); ++ ++ vchiq_mmal_component_finalise(dev->instance, ++ dev-> ++ component[MMAL_COMPONENT_IMAGE_ENCODE]); ++ ++ vchiq_mmal_component_finalise(dev->instance, ++ dev->component[MMAL_COMPONENT_PREVIEW]); ++ ++ vchiq_mmal_component_finalise(dev->instance, ++ dev->component[MMAL_COMPONENT_CAMERA]); ++ ++ v4l2_ctrl_handler_free(&dev->ctrl_handler); ++ ++ v4l2_device_unregister(&dev->v4l2_dev); ++ ++ kfree(dev); ++} ++ + static struct v4l2_format default_v4l2_format = { + .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG, + .fmt.pix.width = 1024, +- .fmt.pix.bytesperline = 1024, ++ .fmt.pix.bytesperline = 0, + .fmt.pix.height = 768, + .fmt.pix.sizeimage = 1024*768, + }; +@@ -1709,76 +1835,93 @@ static int __init bm2835_mmal_init(void) + int ret; + struct bm2835_mmal_dev *dev; + struct vb2_queue *q; ++ int camera; ++ unsigned int num_cameras; ++ struct vchiq_mmal_instance *instance; + +- dev = kzalloc(sizeof(*gdev), GFP_KERNEL); +- if (!dev) +- return -ENOMEM; +- +- /* setup device defaults */ +- dev->overlay.w.left = 150; +- dev->overlay.w.top = 50; +- dev->overlay.w.width = 1024; +- dev->overlay.w.height = 768; +- dev->overlay.clipcount = 0; +- dev->overlay.field = V4L2_FIELD_NONE; +- +- dev->capture.fmt = &formats[3]; /* JPEG */ +- +- /* v4l device registration */ +- snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), +- "%s", BM2835_MMAL_MODULE_NAME); +- ret = v4l2_device_register(NULL, &dev->v4l2_dev); +- if (ret) +- goto free_dev; +- +- /* setup v4l controls */ +- ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler); +- if (ret < 0) +- goto unreg_dev; +- dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; +- +- /* mmal init */ +- ret = mmal_init(dev); ++ ret = vchiq_mmal_init(&instance); + if (ret < 0) +- goto unreg_dev; ++ return ret; + +- /* initialize queue */ +- q = &dev->capture.vb_vidq; +- memset(q, 0, sizeof(*q)); +- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; +- q->drv_priv = dev; +- q->buf_struct_size = sizeof(struct mmal_buffer); +- q->ops = &bm2835_mmal_video_qops; +- q->mem_ops = &vb2_vmalloc_memops; +- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +- ret = vb2_queue_init(q); +- if (ret < 0) +- goto unreg_dev; ++ num_cameras = get_num_cameras(instance); ++ if (num_cameras > MAX_BCM2835_CAMERAS) ++ num_cameras = MAX_BCM2835_CAMERAS; ++ ++ for (camera = 0; camera < num_cameras; camera++) { ++ dev = kzalloc(sizeof(struct bm2835_mmal_dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ dev->camera_num = camera; ++ ++ /* setup device defaults */ ++ dev->overlay.w.left = 150; ++ dev->overlay.w.top = 50; ++ dev->overlay.w.width = 1024; ++ dev->overlay.w.height = 768; ++ dev->overlay.clipcount = 0; ++ dev->overlay.field = V4L2_FIELD_NONE; ++ dev->overlay.global_alpha = 255; ++ ++ dev->capture.fmt = &formats[3]; /* JPEG */ ++ ++ /* v4l device registration */ ++ snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), ++ "%s", BM2835_MMAL_MODULE_NAME); ++ ret = v4l2_device_register(NULL, &dev->v4l2_dev); ++ if (ret) ++ goto free_dev; + +- /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */ +- mutex_init(&dev->mutex); ++ /* setup v4l controls */ ++ ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler); ++ if (ret < 0) ++ goto unreg_dev; ++ dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; ++ ++ /* mmal init */ ++ dev->instance = instance; ++ ret = mmal_init(dev); ++ if (ret < 0) ++ goto unreg_dev; ++ ++ /* initialize queue */ ++ q = &dev->capture.vb_vidq; ++ memset(q, 0, sizeof(*q)); ++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; ++ q->drv_priv = dev; ++ q->buf_struct_size = sizeof(struct mmal_buffer); ++ q->ops = &bm2835_mmal_video_qops; ++ q->mem_ops = &vb2_vmalloc_memops; ++ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ ret = vb2_queue_init(q); ++ if (ret < 0) ++ goto unreg_dev; ++ ++ /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */ ++ mutex_init(&dev->mutex); ++ ++ /* initialise video devices */ ++ ret = bm2835_mmal_init_device(dev, &dev->vdev); ++ 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, ++ "%s: could not setup components\n", __func__); ++ goto unreg_dev; ++ } + +- /* initialise video devices */ +- ret = bm2835_mmal_init_device(dev, &dev->vdev); +- if (ret < 0) +- goto unreg_dev; ++ v4l2_info(&dev->v4l2_dev, ++ "Broadcom 2835 MMAL video capture ver %s loaded.\n", ++ BM2835_MMAL_VERSION); + +- /* 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, +- "%s: could not setup components\n", __func__); +- goto unreg_dev; ++ gdev[camera] = dev; + } +- +- v4l2_info(&dev->v4l2_dev, +- "Broadcom 2835 MMAL video capture ver %s loaded.\n", +- BM2835_MMAL_VERSION); +- +- gdev = dev; + return 0; + + unreg_dev: +@@ -1788,8 +1931,11 @@ unreg_dev: + free_dev: + kfree(dev); + +- v4l2_err(&dev->v4l2_dev, +- "%s: error %d while loading driver\n", ++ for ( ; camera > 0; camera--) { ++ bcm2835_cleanup_instance(gdev[camera]); ++ gdev[camera] = NULL; ++ } ++ pr_info("%s: error %d while loading driver\n", + BM2835_MMAL_MODULE_NAME, ret); + + return ret; +@@ -1797,46 +1943,14 @@ free_dev: + + static void __exit bm2835_mmal_exit(void) + { +- if (!gdev) +- return; +- +- v4l2_info(&gdev->v4l2_dev, "unregistering %s\n", +- video_device_node_name(&gdev->vdev)); ++ int camera; ++ struct vchiq_mmal_instance *instance = gdev[0]->instance; + +- video_unregister_device(&gdev->vdev); +- +- if (gdev->capture.encode_component) { +- v4l2_dbg(1, bcm2835_v4l2_debug, &gdev->v4l2_dev, +- "mmal_exit - disconnect tunnel\n"); +- vchiq_mmal_port_connect_tunnel(gdev->instance, +- gdev->capture.camera_port, NULL); +- vchiq_mmal_component_disable(gdev->instance, +- gdev->capture.encode_component); ++ for (camera = 0; camera < MAX_BCM2835_CAMERAS; camera++) { ++ bcm2835_cleanup_instance(gdev[camera]); ++ gdev[camera] = NULL; + } +- vchiq_mmal_component_disable(gdev->instance, +- gdev->component[MMAL_COMPONENT_CAMERA]); +- +- vchiq_mmal_component_finalise(gdev->instance, +- gdev-> +- component[MMAL_COMPONENT_VIDEO_ENCODE]); +- +- vchiq_mmal_component_finalise(gdev->instance, +- gdev-> +- component[MMAL_COMPONENT_IMAGE_ENCODE]); +- +- vchiq_mmal_component_finalise(gdev->instance, +- gdev->component[MMAL_COMPONENT_PREVIEW]); +- +- vchiq_mmal_component_finalise(gdev->instance, +- gdev->component[MMAL_COMPONENT_CAMERA]); +- +- vchiq_mmal_finalise(gdev->instance); +- +- v4l2_ctrl_handler_free(&gdev->ctrl_handler); +- +- v4l2_device_unregister(&gdev->v4l2_dev); +- +- kfree(gdev); ++ vchiq_mmal_finalise(instance); + } + + module_init(bm2835_mmal_init); +--- 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 28 /* number of v4l controls */ ++#define V4L2_CTRL_COUNT 29 /* number of v4l controls */ + + enum { + MMAL_COMPONENT_CAMERA = 0, +@@ -58,6 +58,8 @@ struct bm2835_mmal_dev { + enum mmal_parameter_exposuremeteringmode metering_mode; + unsigned int manual_shutter_speed; + bool exp_auto_priority; ++ bool manual_iso_enabled; ++ uint32_t iso; + + /* allocated mmal instance and components */ + struct vchiq_mmal_instance *instance; +@@ -104,6 +106,8 @@ struct bm2835_mmal_dev { + + } capture; + ++ unsigned int camera_num; ++ + }; + + int bm2835_mmal_init_controls( +@@ -124,3 +128,16 @@ int set_framerate_params(struct bm2835_m + (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \ + (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \ + } ++#define v4l2_dump_win_format(level, debug, dev, win_fmt, desc) \ ++{ \ ++ v4l2_dbg(level, debug, dev, \ ++"%s: w %u h %u l %u t %u field %u chromakey %06X clip %p " \ ++"clipcount %u bitmap %p\n", \ ++ desc == NULL ? "" : desc, \ ++ (win_fmt)->w.width, (win_fmt)->w.height, \ ++ (win_fmt)->w.left, (win_fmt)->w.top, \ ++ (win_fmt)->field, \ ++ (win_fmt)->chromakey, \ ++ (win_fmt)->clips, (win_fmt)->clipcount, \ ++ (win_fmt)->bitmap); \ ++} +--- a/drivers/media/platform/bcm2835/controls.c ++++ b/drivers/media/platform/bcm2835/controls.c +@@ -49,10 +49,13 @@ static const s64 ev_bias_qmenu[] = { + 4000 + }; + +-/* Supported ISO values ++/* Supported ISO values (*1000) + * ISOO = auto ISO + */ + static const s64 iso_qmenu[] = { ++ 0, 100000, 200000, 400000, 800000, ++}; ++static const uint32_t iso_values[] = { + 0, 100, 200, 400, 800, + }; + +@@ -201,7 +204,7 @@ static int ctrl_set_value(struct bm2835_ + &u32_value, sizeof(u32_value)); + } + +-static int ctrl_set_value_menu(struct bm2835_mmal_dev *dev, ++static int ctrl_set_iso(struct bm2835_mmal_dev *dev, + struct v4l2_ctrl *ctrl, + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) + { +@@ -211,12 +214,23 @@ static int ctrl_set_value_menu(struct bm + if (ctrl->val > mmal_ctrl->max || ctrl->val < mmal_ctrl->min) + return 1; + ++ if (ctrl->id == V4L2_CID_ISO_SENSITIVITY) ++ dev->iso = iso_values[ctrl->val]; ++ else if (ctrl->id == V4L2_CID_ISO_SENSITIVITY_AUTO) ++ dev->manual_iso_enabled = ++ (ctrl->val == V4L2_ISO_SENSITIVITY_MANUAL ? ++ true : ++ false); ++ + control = &dev->component[MMAL_COMPONENT_CAMERA]->control; + +- u32_value = mmal_ctrl->imenu[ctrl->val]; ++ if (dev->manual_iso_enabled) ++ u32_value = dev->iso; ++ else ++ u32_value = 0; + + return vchiq_mmal_port_parameter_set(dev->instance, control, +- mmal_ctrl->mmal_id, ++ MMAL_PARAMETER_ISO, + &u32_value, sizeof(u32_value)); + } + +@@ -956,7 +970,14 @@ static const struct bm2835_mmal_v4l2_ctr + 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_menu, ++ &ctrl_set_iso, ++ false ++ }, ++ { ++ V4L2_CID_ISO_SENSITIVITY_AUTO, MMAL_CONTROL_TYPE_STD_MENU, ++ 0, 1, V4L2_ISO_SENSITIVITY_AUTO, 1, NULL, ++ MMAL_PARAMETER_ISO, ++ &ctrl_set_iso, + false + }, + { +--- a/drivers/media/platform/bcm2835/mmal-parameters.h ++++ b/drivers/media/platform/bcm2835/mmal-parameters.h +@@ -654,3 +654,36 @@ struct mmal_parameter_imagefx_parameters + u32 num_effect_params; + u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS]; + }; ++ ++#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4 ++#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2 ++#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16 ++ ++struct mmal_parameter_camera_info_camera_t { ++ u32 port_id; ++ u32 max_width; ++ u32 max_height; ++ u32 lens_present; ++ u8 camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN]; ++}; ++ ++enum mmal_parameter_camera_info_flash_type_t { ++ /* Make values explicit to ensure they match values in config ini */ ++ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0, ++ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED = 1, ++ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2, ++ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF ++}; ++ ++struct mmal_parameter_camera_info_flash_t { ++ enum mmal_parameter_camera_info_flash_type_t flash_type; ++}; ++ ++struct mmal_parameter_camera_info_t { ++ u32 num_cameras; ++ u32 num_flashes; ++ struct mmal_parameter_camera_info_camera_t ++ cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS]; ++ struct mmal_parameter_camera_info_flash_t ++ flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES]; ++}; |