361 lines
11 KiB
Diff
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,
|