brcm2708: update against latest rpi-3.10.y branch
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0173-V4L2-Initial-pass-at-scene-modes.patch
diff --git a/target/linux/brcm2708/patches-3.10/0173-V4L2-Initial-pass-at-scene-modes.patch b/target/linux/brcm2708/patches-3.10/0173-V4L2-Initial-pass-at-scene-modes.patch
new file mode 100644 (file)
index 0000000..c8c8abf
--- /dev/null
@@ -0,0 +1,360 @@
+From ba09044961948d93db7aa166f2829d46e81e875a Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dsteve@broadcom.com>
+Date: Fri, 14 Feb 2014 17:12:08 +0000
+Subject: [PATCH 173/174] V4L2: Initial pass at scene modes.
+
+Only supports exposure mode and metering modes.
+
+Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
+---
+ drivers/media/platform/bcm2835/bcm2835-camera.h |  10 +-
+ drivers/media/platform/bcm2835/controls.c       | 225 ++++++++++++++++++++----
+ 2 files changed, 199 insertions(+), 36 deletions(-)
+
+--- 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 24 /* number of v4l controls */
++#define V4L2_CTRL_COUNT 25 /* number of v4l controls */
+ enum {
+       MMAL_COMPONENT_CAMERA = 0,
+@@ -45,11 +45,15 @@ 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;
+-      enum mmal_parameter_exposuremode exposure_mode;
+-      enum v4l2_exposure_auto_type exposure_mode_v4l2;
++      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;
+--- a/drivers/media/platform/bcm2835/controls.c
++++ b/drivers/media/platform/bcm2835/controls.c
+@@ -145,6 +145,25 @@ static const struct v4l2_to_mmal_effects
+               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*/
+@@ -296,7 +315,7 @@ static int ctrl_set_exposure(struct bm28
+                     struct v4l2_ctrl *ctrl,
+                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+ {
+-      enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode;
++      enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user;
+       u32 shutter_speed = 0;
+       struct vchiq_mmal_port *control;
+       int ret = 0;
+@@ -317,31 +336,32 @@ static int ctrl_set_exposure(struct bm28
+               case V4L2_EXPOSURE_MANUAL:
+                       exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF;
+                       break;
+-
+-              case V4L2_EXPOSURE_SHUTTER_PRIORITY:
+-                      exp_mode = MMAL_PARAM_EXPOSUREMODE_SPORTS;
+-                      break;
+-
+-              case V4L2_EXPOSURE_APERTURE_PRIORITY:
+-                      exp_mode = MMAL_PARAM_EXPOSUREMODE_NIGHT;
+-                      break;
+-
+               }
+-              dev->exposure_mode = exp_mode;
+-              dev->exposure_mode_v4l2 = ctrl->val;
++              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->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
+-              shutter_speed = dev->manual_shutter_speed;
++      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));
++              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;
+@@ -351,35 +371,38 @@ static int ctrl_set_metering_mode(struct
+                          struct v4l2_ctrl *ctrl,
+                          const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+ {
+-      u32 u32_value;
+-      struct vchiq_mmal_port *control;
+-
+-      control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
+-
+       switch (ctrl->val) {
+       case V4L2_EXPOSURE_METERING_AVERAGE:
+-              u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
++              dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
+               break;
+       case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
+-              u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
++              dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
+               break;
+       case V4L2_EXPOSURE_METERING_SPOT:
+-              u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
++              dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
+               break;
+       /* todo matrix weighting not added to Linux API till 3.9
+       case V4L2_EXPOSURE_METERING_MATRIX:
+-              u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
++              dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
+               break;
+       */
+       }
+-      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_flicker_avoidance(struct bm2835_mmal_dev *dev,
+@@ -738,6 +761,113 @@ static int ctrl_set_video_encode_profile
+       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 =
+@@ -973,6 +1103,15 @@ static const struct bm2835_mmal_v4l2_ctr
+               &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
++      },
+ };
+ int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
+@@ -1000,8 +1139,7 @@ int set_framerate_params(struct bm2835_m
+       struct mmal_parameter_fps_range fps_range;
+       int ret;
+-      if ((dev->exposure_mode_v4l2 == V4L2_EXPOSURE_AUTO ||
+-           dev->exposure_mode_v4l2 == V4L2_EXPOSURE_APERTURE_PRIORITY) &&
++      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.
+@@ -1049,6 +1187,7 @@ int set_framerate_params(struct bm2835_m
+       return ret;
+ }
++
+ int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
+                             struct v4l2_ctrl_handler *hdl)
+ {
+@@ -1068,10 +1207,30 @@ int bm2835_mmal_init_controls(struct bm2
+                       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,