diff options
-rw-r--r-- | drivers/media/video/v4l2-ctrls.c | 74 | ||||
-rw-r--r-- | include/media/v4l2-ctrls.h | 3 |
2 files changed, 69 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 */ |
1490 | void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls) | 1495 | void 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 | } |
1504 | EXPORT_SYMBOL(v4l2_ctrl_cluster); | 1513 | EXPORT_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. */ | ||
2136 | static 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 */ |
2122 | static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, | 2149 | static 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); |
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index bd6a4a7370df..eeb3df637144 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h | |||
@@ -69,6 +69,8 @@ struct v4l2_ctrl_ops { | |||
69 | * members are in 'automatic' mode or 'manual' mode. This is | 69 | * members are in 'automatic' mode or 'manual' mode. This is |
70 | * used for autogain/gain type clusters. Drivers should never | 70 | * used for autogain/gain type clusters. Drivers should never |
71 | * set this flag directly. | 71 | * set this flag directly. |
72 | * @has_volatiles: If set, then one or more members of the cluster are volatile. | ||
73 | * Drivers should never touch this flag. | ||
72 | * @manual_mode_value: If the is_auto flag is set, then this is the value | 74 | * @manual_mode_value: If the is_auto flag is set, then this is the value |
73 | * of the auto control that determines if that control is in | 75 | * of the auto control that determines if that control is in |
74 | * manual mode. So if the value of the auto control equals this | 76 | * manual mode. So if the value of the auto control equals this |
@@ -115,6 +117,7 @@ struct v4l2_ctrl { | |||
115 | unsigned int is_new:1; | 117 | unsigned int is_new:1; |
116 | unsigned int is_private:1; | 118 | unsigned int is_private:1; |
117 | unsigned int is_auto:1; | 119 | unsigned int is_auto:1; |
120 | unsigned int has_volatiles:1; | ||
118 | unsigned int manual_mode_value:8; | 121 | unsigned int manual_mode_value:8; |
119 | 122 | ||
120 | const struct v4l2_ctrl_ops *ops; | 123 | const struct v4l2_ctrl_ops *ops; |