wifipineapple-openwrt/target/linux/brcm2708/patches-3.10/0173-V4L2-Initial-pass-at-s...

361 lines
11 KiB
Diff

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,