Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 271844
b: refs/heads/master
c: 5626b8c
h: refs/heads/master
v: v3
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Sep 21, 2011
1 parent 63f4091 commit a518600
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: de2fb698c6fb1e968a5ed9cc449024f119ad3853
refs/heads/master: 5626b8c75bc13aa3287c18d49e92edc84fa85b2d
74 changes: 66 additions & 8 deletions trunk/drivers/media/video/v4l2-ctrls.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,9 +937,14 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
break;
}
if (update_inactive) {
ctrl->flags &= ~V4L2_CTRL_FLAG_INACTIVE;
if (!is_cur_manual(ctrl->cluster[0]))
/* Note: update_inactive can only be true for auto clusters. */
ctrl->flags &=
~(V4L2_CTRL_FLAG_INACTIVE | V4L2_CTRL_FLAG_VOLATILE);
if (!is_cur_manual(ctrl->cluster[0])) {
ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
if (ctrl->cluster[0]->has_volatiles)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
}
}
if (changed || update_inactive) {
/* If a control was changed that was not one of the controls
Expand Down Expand Up @@ -1489,6 +1494,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_handler);
/* Cluster controls */
void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
{
bool has_volatiles = false;
int i;

/* The first control is the master control and it must not be NULL */
Expand All @@ -1498,27 +1504,33 @@ void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
if (controls[i]) {
controls[i]->cluster = controls;
controls[i]->ncontrols = ncontrols;
if (controls[i]->flags & V4L2_CTRL_FLAG_VOLATILE)
has_volatiles = true;
}
}
controls[0]->has_volatiles = has_volatiles;
}
EXPORT_SYMBOL(v4l2_ctrl_cluster);

void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
u8 manual_val, bool set_volatile)
{
struct v4l2_ctrl *master = controls[0];
u32 flag;
u32 flag = 0;
int i;

v4l2_ctrl_cluster(ncontrols, controls);
WARN_ON(ncontrols <= 1);
WARN_ON(manual_val < master->minimum || manual_val > master->maximum);
WARN_ON(set_volatile && !has_op(master, g_volatile_ctrl));
master->is_auto = true;
master->has_volatiles = set_volatile;
master->manual_mode_value = manual_val;
master->flags |= V4L2_CTRL_FLAG_UPDATE;
flag = is_cur_manual(master) ? 0 : V4L2_CTRL_FLAG_INACTIVE;
if (set_volatile)
flag |= V4L2_CTRL_FLAG_VOLATILE;

if (!is_cur_manual(master))
flag = V4L2_CTRL_FLAG_INACTIVE |
(set_volatile ? V4L2_CTRL_FLAG_VOLATILE : 0);

for (i = 1; i < ncontrols; i++)
if (controls[i])
Expand Down Expand Up @@ -1957,7 +1969,8 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
v4l2_ctrl_lock(master);

/* g_volatile_ctrl will update the new control values */
if (has_op(master, g_volatile_ctrl) && !is_cur_manual(master)) {
if ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
(master->has_volatiles && !is_cur_manual(master))) {
for (j = 0; j < master->ncontrols; j++)
cur_to_new(master->cluster[j]);
ret = call_op(master, g_volatile_ctrl);
Expand Down Expand Up @@ -2002,7 +2015,7 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)

v4l2_ctrl_lock(master);
/* g_volatile_ctrl will update the current control values */
if ((ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) && !is_cur_manual(master)) {
if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
for (i = 0; i < master->ncontrols; i++)
cur_to_new(master->cluster[i]);
ret = call_op(master, g_volatile_ctrl);
Expand Down Expand Up @@ -2118,6 +2131,20 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
return 0;
}

/* Obtain the current volatile values of an autocluster and mark them
as new. */
static void update_from_auto_cluster(struct v4l2_ctrl *master)
{
int i;

for (i = 0; i < master->ncontrols; i++)
cur_to_new(master->cluster[i]);
if (!call_op(master, g_volatile_ctrl))
for (i = 1; i < master->ncontrols; i++)
if (master->cluster[i])
master->cluster[i]->is_new = 1;
}

/* Try or try-and-set controls */
static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_controls *cs,
Expand Down Expand Up @@ -2163,6 +2190,31 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
if (master->cluster[j])
master->cluster[j]->is_new = 0;

/* For volatile autoclusters that are currently in auto mode
we need to discover if it will be set to manual mode.
If so, then we have to copy the current volatile values
first since those will become the new manual values (which
may be overwritten by explicit new values from this set
of controls). */
if (master->is_auto && master->has_volatiles &&
!is_cur_manual(master)) {
/* Pick an initial non-manual value */
s32 new_auto_val = master->manual_mode_value + 1;
u32 tmp_idx = idx;

do {
/* Check if the auto control is part of the
list, and remember the new value. */
if (helpers[tmp_idx].ctrl == master)
new_auto_val = cs->controls[tmp_idx].value;
tmp_idx = helpers[tmp_idx].next;
} while (tmp_idx);
/* If the new value == the manual value, then copy
the current volatile values. */
if (new_auto_val == master->manual_mode_value)
update_from_auto_cluster(master);
}

/* Copy the new caller-supplied control values.
user_to_new() sets 'is_new' to 1. */
do {
Expand Down Expand Up @@ -2233,6 +2285,12 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
if (master->cluster[i])
master->cluster[i]->is_new = 0;

/* For autoclusters with volatiles that are switched from auto to
manual mode we have to update the current volatile values since
those will become the initial manual values after such a switch. */
if (master->is_auto && master->has_volatiles && ctrl == master &&
!is_cur_manual(master) && *val == master->manual_mode_value)
update_from_auto_cluster(master);
ctrl->val = *val;
ctrl->is_new = 1;
ret = try_or_set_cluster(fh, master, true);
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/media/v4l2-ctrls.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ struct v4l2_ctrl_ops {
* members are in 'automatic' mode or 'manual' mode. This is
* used for autogain/gain type clusters. Drivers should never
* set this flag directly.
* @has_volatiles: If set, then one or more members of the cluster are volatile.
* Drivers should never touch this flag.
* @manual_mode_value: If the is_auto flag is set, then this is the value
* of the auto control that determines if that control is in
* manual mode. So if the value of the auto control equals this
Expand Down Expand Up @@ -115,6 +117,7 @@ struct v4l2_ctrl {
unsigned int is_new:1;
unsigned int is_private:1;
unsigned int is_auto:1;
unsigned int has_volatiles:1;
unsigned int manual_mode_value:8;

const struct v4l2_ctrl_ops *ops;
Expand Down

0 comments on commit a518600

Please sign in to comment.