aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-ctrls.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2011-08-26 06:53:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-09-21 09:48:30 -0400
commit5626b8c75bc13aa3287c18d49e92edc84fa85b2d (patch)
tree0c913d7ed98ff0f469f305b5042880a270543c20 /drivers/media/video/v4l2-ctrls.c
parentde2fb698c6fb1e968a5ed9cc449024f119ad3853 (diff)
[media] v4l2-ctrls: implement new volatile autocluster scheme
The problem tackled in this patch is how to handle volatile autoclusters correctly. A volatile autocluster is a cluster of related controls where one control is the control that toggles between manual and auto mode and the other controls are the values for the manual mode. For example autogain and gain, autoexposure and exposure, etc. If the hardware lets you read out the automatically calculated manual values while in automode, then those manual controls should be marked volatile. gain value as calculated by the autogain circuitry, then you would mark the gain control as volatile (i.e. continuously changing). The question in such use cases is what to do when switching from the auto mode to the manual mode. Should we switch to the last set manual values or should the volatile values be copied and used as the initial manual values. For example: suppose the mode is manual gain and gain is set to 5. Then autogain is turned on and the gain is set by the hardware to 2. Finally the user switches back to manual gain. What should the gain be? 2 or 5? After a long discussion the decisions was made to keep the last value as calculated by the auto mode (so 2 in the example above). The reason is that webcams that do such things will adapt themselves to the current light conditions and when you switch back to manual mode you expect that you keep the same picture. If you would switch back to old manual values, then that would give you a suddenly different picture, which is jarring for the user. Additionally, this would be difficult to implement in applications that store and restore the control values at application exit and start. If you want to keep the old manual values when you switch from auto to manual, then there would have to be a way for applications to get hold of those old values while in auto mode, but there isn't. So this patch will do all the heavy lifting in v4l2-ctrls.c: if you go from auto mode to manual mode and the manual controls are volatile, then g_volatile_ctrl will be called to get the current values for the manual controls before switching to manual mode. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/v4l2-ctrls.c')
-rw-r--r--drivers/media/video/v4l2-ctrls.c74
1 files changed, 66 insertions, 8 deletions
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 166762182f8e..fc8666ae408f 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -937,9 +937,14 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
937 break; 937 break;
938 } 938 }
939 if (update_inactive) { 939 if (update_inactive) {
940 ctrl->flags &= ~V4L2_CTRL_FLAG_INACTIVE; 940 /* Note: update_inactive can only be true for auto clusters. */
941 if (!is_cur_manual(ctrl->cluster[0])) 941 ctrl->flags &=
942 ~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE);
943 if (!is_cur_manual(ctrl->cluster[0])) {
942 ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 944 ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
945 if (ctrl->cluster[0]->has_volatiles)
946 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
947 }
943 } 948 }
944 if (changed || update_inactive) { 949 if (changed || update_inactive) {
945 /* If a control was changed that was not one of the controls 950 /* If a control was changed that was not one of the controls
@@ -1489,6 +1494,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_handler);
1489/* Cluster controls */ 1494/* Cluster controls */
1490void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls) 1495void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
1491{ 1496{
1497 bool has_volatiles = false;
1492 int i; 1498 int i;
1493 1499
1494 /* The first control is the master control and it must not be NULL */ 1500 /* The first control is the master control and it must not be NULL */
@@ -1498,8 +1504,11 @@ void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
1498 if (controls[i]) { 1504 if (controls[i]) {
1499 controls[i]->cluster = controls; 1505 controls[i]->cluster = controls;
1500 controls[i]->ncontrols = ncontrols; 1506 controls[i]->ncontrols = ncontrols;
1507 if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE)
1508 has_volatiles = true;
1501 } 1509 }
1502 } 1510 }
1511 controls[0]->has_volatiles = has_volatiles;
1503} 1512}
1504EXPORT_SYMBOL(v4l2_ctrl_cluster); 1513EXPORT_SYMBOL(v4l2_ctrl_cluster);
1505 1514
@@ -1507,18 +1516,21 @@ void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
1507 u8 manual_val, bool set_volatile) 1516 u8 manual_val, bool set_volatile)
1508{ 1517{
1509 struct v4l2_ctrl *master = controls[0]; 1518 struct v4l2_ctrl *master = controls[0];
1510 u32 flag; 1519 u32 flag = 0;
1511 int i; 1520 int i;
1512 1521
1513 v4l2_ctrl_cluster(ncontrols, controls); 1522 v4l2_ctrl_cluster(ncontrols, controls);
1514 WARN_ON(ncontrols <= 1); 1523 WARN_ON(ncontrols <= 1);
1515 WARN_ON(manual_val < master->minimum || manual_val > master->maximum); 1524 WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
1525 WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl));
1516 master->is_auto = true; 1526 master->is_auto = true;
1527 master->has_volatiles = set_volatile;
1517 master->manual_mode_value = manual_val; 1528 master->manual_mode_value = manual_val;
1518 master->flags |= V4L2_CTRL_FLAG_UPDATE; 1529 master->flags |= V4L2_CTRL_FLAG_UPDATE;
1519 flag = is_cur_manual(master) ? 0 : V4L2_CTRL_FLAG_INACTIVE; 1530
1520 if (set_volatile) 1531 if (!is_cur_manual(master))
1521 flag |= V4L2_CTRL_FLAG_VOLATILE; 1532 flag = V4L2_CTRL_FLAG_INACTIVE |
1533 (set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0);
1522 1534
1523 for (i = 1; i < ncontrols; i++) 1535 for (i = 1; i < ncontrols; i++)
1524 if (controls[i]) 1536 if (controls[i])
@@ -1957,7 +1969,8 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
1957 v4l2_ctrl_lock(master); 1969 v4l2_ctrl_lock(master);
1958 1970
1959 /* g_volatile_ctrl will update the new control values */ 1971 /* g_volatile_ctrl will update the new control values */
1960 if (has_op(master, g_volatile_ctrl) && !is_cur_manual(master)) { 1972 if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
1973 (master->has_volatiles && !is_cur_manual(master))) {
1961 for (j = 0; j < master->ncontrols; j++) 1974 for (j = 0; j < master->ncontrols; j++)
1962 cur_to_new(master->cluster[j]); 1975 cur_to_new(master->cluster[j]);
1963 ret = call_op(master, g_volatile_ctrl); 1976 ret = call_op(master, g_volatile_ctrl);
@@ -2002,7 +2015,7 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
2002 2015
2003 v4l2_ctrl_lock(master); 2016 v4l2_ctrl_lock(master);
2004 /* g_volatile_ctrl will update the current control values */ 2017 /* g_volatile_ctrl will update the current control values */
2005 if ((ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) && !is_cur_manual(master)) { 2018 if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
2006 for (i = 0; i < master->ncontrols; i++) 2019 for (i = 0; i < master->ncontrols; i++)
2007 cur_to_new(master->cluster[i]); 2020 cur_to_new(master->cluster[i]);
2008 ret = call_op(master, g_volatile_ctrl); 2021 ret = call_op(master, g_volatile_ctrl);
@@ -2118,6 +2131,20 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
2118 return 0; 2131 return 0;
2119} 2132}
2120 2133
2134/* Obtain the current volatile values of an autocluster and mark them
2135 as new. */
2136static void update_from_auto_cluster(struct v4l2_ctrl *master)
2137{
2138 int i;
2139
2140 for (i = 0; i < master->ncontrols; i++)
2141 cur_to_new(master->cluster[i]);
2142 if (!call_op(master, g_volatile_ctrl))
2143 for (i = 1; i < master->ncontrols; i++)
2144 if (master->cluster[i])
2145 master->cluster[i]->is_new = 1;
2146}
2147
2121/* Try or try-and-set controls */ 2148/* Try or try-and-set controls */
2122static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, 2149static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
2123 struct v4l2_ext_controls *cs, 2150 struct v4l2_ext_controls *cs,
@@ -2163,6 +2190,31 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
2163 if (master->cluster[j]) 2190 if (master->cluster[j])
2164 master->cluster[j]->is_new = 0; 2191 master->cluster[j]->is_new = 0;
2165 2192
2193 /* For volatile autoclusters that are currently in auto mode
2194 we need to discover if it will be set to manual mode.
2195 If so, then we have to copy the current volatile values
2196 first since those will become the new manual values (which
2197 may be overwritten by explicit new values from this set
2198 of controls). */
2199 if (master->is_auto && master->has_volatiles &&
2200 !is_cur_manual(master)) {
2201 /* Pick an initial non-manual value */
2202 s32 new_auto_val = master->manual_mode_value + 1;
2203 u32 tmp_idx = idx;
2204
2205 do {
2206 /* Check if the auto control is part of the
2207 list, and remember the new value. */
2208 if (helpers[tmp_idx].ctrl == master)
2209 new_auto_val = cs->controls[tmp_idx].value;
2210 tmp_idx = helpers[tmp_idx].next;
2211 } while (tmp_idx);
2212 /* If the new value == the manual value, then copy
2213 the current volatile values. */
2214 if (new_auto_val == master->manual_mode_value)
2215 update_from_auto_cluster(master);
2216 }
2217
2166 /* Copy the new caller-supplied control values. 2218 /* Copy the new caller-supplied control values.
2167 user_to_new() sets 'is_new' to 1. */ 2219 user_to_new() sets 'is_new' to 1. */
2168 do { 2220 do {
@@ -2233,6 +2285,12 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
2233 if (master->cluster[i]) 2285 if (master->cluster[i])
2234 master->cluster[i]->is_new = 0; 2286 master->cluster[i]->is_new = 0;
2235 2287
2288 /* For autoclusters with volatiles that are switched from auto to
2289 manual mode we have to update the current volatile values since
2290 those will become the initial manual values after such a switch. */
2291 if (master->is_auto && master->has_volatiles && ctrl == master &&
2292 !is_cur_manual(master) && *val == master->manual_mode_value)
2293 update_from_auto_cluster(master);
2236 ctrl->val = *val; 2294 ctrl->val = *val;
2237 ctrl->is_new = 1; 2295 ctrl->is_new = 1;
2238 ret = try_or_set_cluster(fh, master, true); 2296 ret = try_or_set_cluster(fh, master, true);