Re: [RFC PATCH] Modify volatile auto cluster handling as per earlier discussions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thursday, August 25, 2011 22:22:28 Hans de Goede wrote:
> Hi,
> 
> First of all thanks for doing this! Overall it looks good,
> see below for several (small) remarks which I have.


Thanks for the review!

> On 08/09/2011 06:40 PM, Hans Verkuil wrote:
> > This patch modifies the way autoclusters work when the 'foo' controls are
> > volatile if autofoo is on.
> >
> > E.g.: if autogain is true, then gain returns the gain set by the autogain
> > circuitry.
> >
> > This patch makes the following changes:
> >
> > 1) The V4L2_CTRL_FLAG_VOLATILE flag is added to let userspace know that a certain
> >     control is volatile. Currently this is internal information only.
> >
> > 2) If v4l2_ctrl_auto_cluster() is called with the last 'set_volatile' argument set
> >     to true, then the cluster has the following behavior:
> >
> >     - when in manual mode you can set the manual values normally.
> >     - when in auto mode any new manual values will be ignored. When you
> >       read the manual values you will get those as determined by the auto mode.
> >     - when switching from auto to manual mode the manual values from the auto
> >       mode are obtained through g_volatile_ctrl first. Any manual values explicitly
> >       set by the application will replace those obtained from the automode and the
> >       final set of values is sent to the driver with s_ctrl.
> >     - when in auto mode the V4L2_CTRL_FLAG_VOLATILE and INACTIVE flags are set for
> >       the 'foo' controls. These flags are cleared when in manual mode.
> >
> > This patch modifies existing users of is_volatile and simplifies the pwc driver
> > that required this behavior.
> >
> > The only thing missing is the documentation update and some code comments.
> >
> > I have to admit that it works quite well.
> >
> > Hans, can you verify that this does what you wanted it to do?
> >
> > Regards,
> >
> > 	Hans
> >
> 
> <snip>
> 
> > diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
> > index e9a0e94..4ce00bf 100644
> > --- a/drivers/media/video/pwc/pwc-v4l.c
> > +++ b/drivers/media/video/pwc/pwc-v4l.c
> 
> <snip>
> 
> > @@ -632,52 +634,28 @@ static int pwc_set_awb(struct pwc_device *pdev)
> >   {
> >   	int ret = 0;
> >
> > -	if (pdev->auto_white_balance->is_new) {
> > +	if (pdev->auto_white_balance->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
> > -				      WB_MODE_FORMATTER,
> > -				      pdev->auto_white_balance->val);
> > -		if (ret)
> > -			return ret;
> > +			WB_MODE_FORMATTER,
> > +			pdev->auto_white_balance->val);
> > +	if (ret)
> > +		return ret;
> >
> > -		/* Update val when coming from auto or going to a preset */
> > -		if (pdev->red_balance->is_volatile ||
> > -		    pdev->auto_white_balance->val == awb_indoor ||
> > -		    pdev->auto_white_balance->val == awb_outdoor ||
> > -		    pdev->auto_white_balance->val == awb_fl) {
> > -			if (!pdev->red_balance->is_new)
> > -				pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
> > -					READ_RED_GAIN_FORMATTER,
> > -					&pdev->red_balance->val);
> > -			if (!pdev->blue_balance->is_new)
> > -				pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
> > -					READ_BLUE_GAIN_FORMATTER,
> > -					&pdev->blue_balance->val);
> > -		}
> > -		if (pdev->auto_white_balance->val == awb_auto) {
> > -			pdev->red_balance->is_volatile = true;
> > -			pdev->blue_balance->is_volatile = true;
> > -			pdev->color_bal_valid = false; /* Force cache update */
> > -		} else {
> > -			pdev->red_balance->is_volatile = false;
> > -			pdev->blue_balance->is_volatile = false;
> > -		}
> > +	if (pdev->auto_white_balance->val != awb_manual) {
> > +		pdev->color_bal_valid = false; /* Force cache update */
> > +		return 0;
> >   	}
> >
> 
> The setting of pdev->color_bal_valid = false should happen inside
> the "if (pdev->auto_white_balance->is_new)" block (under the same
> pdev->auto_white_balance->val != awb_manual condition), the way it
> is now if someone tries to say write blue bal while in awb mode, not
> only will the write get ignored (good), but this will also invalidate
> the cached values (bad).

True. 

> > -	if (ret == 0&&  pdev->red_balance->is_new) {
> > -		if (pdev->auto_white_balance->val != awb_manual)
> > -			return -EBUSY;
> > +	if (pdev->red_balance->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
> > -				      PRESET_MANUAL_RED_GAIN_FORMATTER,
> > -				      pdev->red_balance->val);
> > -	}
> > -
> > -	if (ret == 0&&  pdev->blue_balance->is_new) {
> > -		if (pdev->auto_white_balance->val != awb_manual)
> > -			return -EBUSY;
> > +			PRESET_MANUAL_RED_GAIN_FORMATTER,
> > +			pdev->red_balance->val);
> > +	if (ret)
> > +		return ret;
> > +	if (pdev->blue_balance->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
> > -				      PRESET_MANUAL_BLUE_GAIN_FORMATTER,
> > -				      pdev->blue_balance->val);
> > -	}
> > +			PRESET_MANUAL_BLUE_GAIN_FORMATTER,
> > +			pdev->blue_balance->val);
> >   	return ret;
> >   }
> >
> 
> Nitpick: I'm also not happy with moving the error return checks outside
> of the is_new blocks, I know the end result is the same, but it just
> feels a bit wrong to me, because it makes less clear what the actual
> intend of the check is (to check the pwc_set_u8_ctrl result).

I'm fine with either approach.

> This how I would like pwc_set_awb to look after this patch:
> 
> {
>   	int ret;
> 
> 	if (pdev->auto_white_balance->is_new)
>   		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
> 				      WB_MODE_FORMATTER,
> 				      pdev->auto_white_balance->val);
> 		if (ret)
> 			return ret;
> 
> 		if (pdev->auto_white_balance->val != awb_manual)
> 			pdev->color_bal_valid = false; /* Force cache update */
> 	}
> 
> 	if (pdev->auto_white_balance->val != awb_manual)
> 		return 0;
> 
> 	if (pdev->red_balance->is_new) {
>   		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
> 			PRESET_MANUAL_RED_GAIN_FORMATTER,
> 			pdev->red_balance->val);
> 		if (ret)
> 			return ret;
> 	}
> 
> 	if (pdev->blue_balance->is_new) {
>   		ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
> 			PRESET_MANUAL_BLUE_GAIN_FORMATTER,
> 			pdev->blue_balance->val);
> 		if (ret)
> 			return ret;
> 	}
> 
>   	return 0;
> }
> 
> 
> > @@ -686,26 +664,18 @@ static int pwc_set_autogain(struct pwc_device *pdev)
> >   {
> >   	int ret = 0;
> >
> > -	if (pdev->autogain->is_new) {
> > +	if (pdev->autogain->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> > -				      AGC_MODE_FORMATTER,
> > -				      pdev->autogain->val ? 0 : 0xff);
> > -		if (ret)
> > -			return ret;
> > -		if (pdev->autogain->val)
> > -			pdev->gain_valid = false; /* Force cache update */
> > -		else if (!pdev->gain->is_new)
> > -			pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
> > -					READ_AGC_FORMATTER,
> > -					&pdev->gain->val);
> > -	}
> > -	if (ret == 0&&  pdev->gain->is_new) {
> > -		if (pdev->autogain->val)
> > -			return -EBUSY;
> > +			AGC_MODE_FORMATTER,
> > +			pdev->autogain->val ? 0 : 0xff);
> > +	if (ret)
> > +		return ret;
> > +	if (pdev->autogain->val)
> > +		pdev->gain_valid = false; /* Force cache update */
> > +	else if (pdev->gain->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> >   				      PRESET_AGC_FORMATTER,
> >   				      pdev->gain->val);
> > -	}
> >   	return ret;
> >   }
> 
> Same old, same old, invalidation of the cache should be inside
> the is_new block. Move error checks into is_new blocks, ie:
> 
> {
>     	int ret;
> 
> 	if (pdev->autogain->is_new) {
>     		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> 				      AGC_MODE_FORMATTER,
> -				      pdev->autogain->val ? 0 : 0xff);
> 		if (ret)
> 			return ret;
> 		if (pdev->autogain->val)
> 			pdev->gain_valid = false; /* Force cache update */
> 	}
> 
> 	if (pdev->autogain->val)
> 		return 0;
> 
> 	if (pdev->gain->is_new) {
>    		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
>    				      PRESET_AGC_FORMATTER,
>    				      pdev->gain->val);
> 		if (ret)
> 			return ret;
> 	}
> 
> 	return 0;
> }
> 
> 
> 
> >
> > @@ -715,26 +685,18 @@ static int pwc_set_exposure_auto(struct pwc_device *pdev)
> >   	int ret = 0;
> >   	int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
> >
> > -	if (pdev->exposure_auto->is_new) {
> > +	if (pdev->exposure_auto->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> > -				      SHUTTER_MODE_FORMATTER,
> > -				      is_auto ? 0 : 0xff);
> > -		if (ret)
> > -			return ret;
> > -		if (is_auto)
> > -			pdev->exposure_valid = false; /* Force cache update */
> > -		else if (!pdev->exposure->is_new)
> > -			pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
> > -					 READ_SHUTTER_FORMATTER,
> > -					&pdev->exposure->val);
> > -	}
> > -	if (ret == 0&&  pdev->exposure->is_new) {
> > -		if (is_auto)
> > -			return -EBUSY;
> > +			SHUTTER_MODE_FORMATTER,
> > +			is_auto ? 0 : 0xff);
> > +	if (ret)
> > +		return ret;
> > +	if (is_auto)
> > +		pdev->exposure_valid = false; /* Force cache update */
> > +	else if (pdev->exposure->is_new)
> >   		ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
> >   				       PRESET_SHUTTER_FORMATTER,
> >   				       pdev->exposure->val);
> > -	}
> >   	return ret;
> >   }
> >
> 
> Idem.
> 
> > @@ -743,39 +705,26 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
> >   {
> >   	int ret = 0;
> >
> > -	if (pdev->autogain->is_new) {
> > +	if (pdev->autogain->is_new)
> >   		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> >   				      AGC_MODE_FORMATTER,
> >   				      pdev->autogain->val ? 0 : 0xff);
> > +	if (ret)
> > +		return ret;
> > +	if (pdev->autogain->val) {
> > +		pdev->gain_valid     = false; /* Force cache update */
> > +		pdev->exposure_valid = false; /* Force cache update */
> > +	} else {
> > +		if (pdev->gain->is_new)
> > +			ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> > +					PRESET_AGC_FORMATTER,
> > +					pdev->gain->val);
> >   		if (ret)
> >   			return ret;
> > -		if (pdev->autogain->val) {
> > -			pdev->gain_valid     = false; /* Force cache update */
> > -			pdev->exposure_valid = false; /* Force cache update */
> > -		} else {
> > -			if (!pdev->gain->is_new)
> > -				pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
> > -						READ_AGC_FORMATTER,
> > -						&pdev->gain->val);
> > -			if (!pdev->exposure->is_new)
> > -				pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
> > -						 READ_SHUTTER_FORMATTER,
> > -						&pdev->exposure->val);
> > -		}
> > -	}
> > -	if (ret == 0&&  pdev->gain->is_new) {
> > -		if (pdev->autogain->val)
> > -			return -EBUSY;
> > -		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> > -				      PRESET_AGC_FORMATTER,
> > -				      pdev->gain->val);
> > -	}
> > -	if (ret == 0&&  pdev->exposure->is_new) {
> > -		if (pdev->autogain->val)
> > -			return -EBUSY;
> > -		ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
> > -				       PRESET_SHUTTER_FORMATTER,
> > -				       pdev->exposure->val);
> > +		if (pdev->exposure->is_new)
> > +			ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
> > +					PRESET_SHUTTER_FORMATTER,
> > +					pdev->exposure->val);
> >   	}
> >   	return ret;
> >   }
> 
> Idem
> 
> > @@ -872,20 +821,13 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
> >   				      ctrl->val ? 0 : 0xff);
> >   		break;
> >   	case PWC_CID_CUSTOM(autocontour):
> > -		if (pdev->autocontour->is_new) {
> > -			ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> > -					AUTO_CONTOUR_FORMATTER,
> > -					pdev->autocontour->val ? 0 : 0xff);
> > -		}
> > -		if (ret == 0&&  pdev->contour->is_new) {
> > -			if (pdev->autocontour->val) {
> > -				ret = -EBUSY;
> > -				break;
> > -			}
> > +		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> > +				AUTO_CONTOUR_FORMATTER,
> > +				pdev->autocontour->val ? 0 : 0xff);
> > +		if (ret == 0&&  pdev->autocontour->val)
> >   			ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> >   					      PRESET_CONTOUR_FORMATTER,
> >   					      pdev->contour->val);
> > -		}
> >   		break;
> >   	case V4L2_CID_BACKLIGHT_COMPENSATION:
> >   		ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
> 
> 2 things:
> 1) Why not use is_new before setting ?

No idea :-)

I think this may have been a left-over from an earlier attempt.

> 2) contour is not volatile, you can set it to $random value while
>     auto is on, and then when you turn auto off, it will "jump"
>     to $random setting you last did, so there should be no
>     pdev->autocontour->val check (and if there should be it should be
>     inverted.
> 
> I've attached a revised version of the patch addrressing all
> my concerns / code style request wrt the pwc driver.

Thanks! I'll use that for my pull request.

> 
> > @@ -1099,6 +1041,14 @@ static int pwc_enum_frameintervals(struct file *file, void *fh,
> >   	return 0;
> >   }
> >
> > +static int pwc_log_status(struct file *file, void *priv)
> > +{
> > +	struct pwc_device *pdev = video_drvdata(file);
> > +
> > +	v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME);
> > +	return 0;
> > +}
> > +
> >   static long pwc_default(struct file *file, void *fh, bool valid_prio,
> >   			int cmd, void *arg)
> >   {
> > @@ -1122,6 +1072,7 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = {
> >   	.vidioc_dqbuf			    = pwc_dqbuf,
> >   	.vidioc_streamon		    = pwc_streamon,
> >   	.vidioc_streamoff		    = pwc_streamoff,
> > +	.vidioc_log_status		    = pwc_log_status,
> >   	.vidioc_enum_framesizes		    = pwc_enum_framesizes,
> >   	.vidioc_enum_frameintervals	    = pwc_enum_frameintervals,
> >   	.vidioc_default		    = pwc_default,
> 
> <snip>
> 
> > diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
> > index 06b6014..b29f3d8 100644
> > --- a/drivers/media/video/v4l2-ctrls.c
> > +++ b/drivers/media/video/v4l2-ctrls.c
> > @@ -43,7 +43,7 @@ struct v4l2_ctrl_helper {
> >   };
> >
> >   /* Small helper function to determine if the autocluster is set to manual
> > -   mode. In that case the is_volatile flag should be ignored. */
> > +   mode. */
> >   static bool is_cur_manual(const struct v4l2_ctrl *master)
> >   {
> >   	return master->is_auto&&  master->cur.val == master->manual_mode_value;
> > @@ -937,9 +937,13 @@ 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]))
> > +		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]->is_auto_volatile)
> > +				ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
> > +		}
> >   	}
> >   	if (changed || update_inactive) {
> >   		/* If a control was changed that was not one of the controls
> > @@ -1394,10 +1398,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
> >   			type, min, max,
> >   			is_menu ? cfg->menu_skip_mask : step,
> >   			def, flags, qmenu, priv);
> > -	if (ctrl) {
> > +	if (ctrl)
> >   		ctrl->is_private = cfg->is_private;
> > -		ctrl->is_volatile = cfg->is_volatile;
> > -	}
> >   	return ctrl;
> >   }
> >   EXPORT_SYMBOL(v4l2_ctrl_new_custom);
> > @@ -1491,6 +1493,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_handler);
> >   /* Cluster controls */
> >   void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
> >   {
> > +	bool is_auto_volatile = false;
> >   	int i;
> >
> >   	/* The first control is the master control and it must not be NULL */
> > @@ -1500,8 +1503,11 @@ 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)
> > +				is_auto_volatile = true;
> >   		}
> >   	}
> > +	controls[0]->is_auto_volatile = is_auto_volatile;
> >   }
> >   EXPORT_SYMBOL(v4l2_ctrl_cluster);
> >
> 
> I see that you are setting is_auto_volatile for regular (non auto
> clusters) here. First of all given its name that seems weird.
> 
> I can see that this then gets used in v4l2_g_ext_ctrls
> to call g_volatile_ctrl in the case were the master is
> not volatile, but some other controls in the cluster are.
> 
> However it also leads to calling update_from_auto_cluster
> from try_set_ext_ctrls and set_ctrl in the same case, which I
> personally consider an undesirable side-effect, but maybe
> you see things differently?

I agree, this can be improved. I'll work on this.

> > @@ -1509,22 +1515,25 @@ 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->is_auto_volatile = 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 (!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]) {
> > -			controls[i]->is_volatile = set_volatile;
> > +		if (controls[i])
> >   			controls[i]->flags |= flag;
> > -		}
> >   }
> >   EXPORT_SYMBOL(v4l2_ctrl_auto_cluster);
> >
> > @@ -1579,9 +1588,6 @@ EXPORT_SYMBOL(v4l2_ctrl_grab);
> >   static void log_ctrl(const struct v4l2_ctrl *ctrl,
> >   		     const char *prefix, const char *colon)
> >   {
> > -	int fl_inact = ctrl->flags&  V4L2_CTRL_FLAG_INACTIVE;
> > -	int fl_grabbed = ctrl->flags&  V4L2_CTRL_FLAG_GRABBED;
> > -
> >   	if (ctrl->flags&  (V4L2_CTRL_FLAG_DISABLED | V4L2_CTRL_FLAG_WRITE_ONLY))
> >   		return;
> >   	if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
> > @@ -1612,14 +1618,17 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
> >   		printk(KERN_CONT "unknown type %d", ctrl->type);
> >   		break;
> >   	}
> > -	if (fl_inact&&  fl_grabbed)
> > -		printk(KERN_CONT " (inactive, grabbed)\n");
> > -	else if (fl_inact)
> > -		printk(KERN_CONT " (inactive)\n");
> > -	else if (fl_grabbed)
> > -		printk(KERN_CONT " (grabbed)\n");
> > -	else
> > -		printk(KERN_CONT "\n");
> > +	if (ctrl->flags&  (V4L2_CTRL_FLAG_INACTIVE |
> > +			   V4L2_CTRL_FLAG_GRABBED |
> > +			   V4L2_CTRL_FLAG_VOLATILE)) {
> > +		if (ctrl->flags&  V4L2_CTRL_FLAG_INACTIVE)
> > +			printk(KERN_CONT " inactive");
> > +		if (ctrl->flags&  V4L2_CTRL_FLAG_GRABBED)
> > +			printk(KERN_CONT " grabbed");
> > +		if (ctrl->flags&  V4L2_CTRL_FLAG_VOLATILE)
> > +			printk(KERN_CONT " volatile");
> > +	}
> > +	printk(KERN_CONT "\n");
> >   }
> >
> >   /* Log all controls owned by the handler */
> > @@ -1959,7 +1968,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->is_auto_volatile&&  !is_cur_manual(master))) {
> >   			for (j = 0; j<  master->ncontrols; j++)
> >   				cur_to_new(master->cluster[j]);
> >   			ret = call_op(master, g_volatile_ctrl);
> > @@ -2004,7 +2014,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->is_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);
> > @@ -2120,6 +2130,18 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
> >   	return 0;
> >   }
> >
> > +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,
> > @@ -2165,6 +2187,9 @@ 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;
> >
> > +		if (master->is_auto_volatile&&  !is_cur_manual(master))
> > +			update_from_auto_cluster(master);
> > +
> >   		/* Copy the new caller-supplied control values.
> >   		   user_to_new() sets 'is_new' to 1. */
> >   		do {
> > @@ -2235,6 +2260,8 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
> >   		if (master->cluster[i])
> >   			master->cluster[i]->is_new = 0;
> >
> > +	if (master->is_auto_volatile&&  !is_cur_manual(master))
> > +		update_from_auto_cluster(master);
> >   	ctrl->val = *val;
> >   	ctrl->is_new = 1;
> >   	ret = try_or_set_cluster(fh, master, true);
> 
> <snip>
> 
> > diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
> > index 13fe4d7..d1a77cd 100644
> > --- a/include/media/v4l2-ctrls.h
> > +++ b/include/media/v4l2-ctrls.h
> > @@ -118,8 +118,8 @@ struct v4l2_ctrl {
> >
> >   	unsigned int is_new:1;
> >   	unsigned int is_private:1;
> > -	unsigned int is_volatile:1;
> >   	unsigned int is_auto:1;
> > +	unsigned int is_auto_volatile:1;
> >   	unsigned int manual_mode_value:8;
> >
> >   	const struct v4l2_ctrl_ops *ops;
> > @@ -208,9 +208,9 @@ struct v4l2_ctrl_handler {
> >     *		must be NULL.
> >     * @is_private: If set, then this control is private to its handler and it
> >     *		will not be added to any other handlers.
> > -  * @is_volatile: If set, then this control is volatile. This means that the
> > -  *		control's current value cannot be cached and needs to be
> > -  *		retrieved through the g_volatile_ctrl op.
> > +  * @is_volatile: If set, then this autocluster control is volatile. This means
> > +  *		that the control's current value cannot be cached and needs to
> > +  *		be retrieved through the g_volatile_ctrl op.
> >     */
> >   struct v4l2_ctrl_config {
> >   	const struct v4l2_ctrl_ops *ops;
> 
> Typo: adds docstring for is_volatile, should be is_auto_volatile

Actually, it should be removed altogether. is_volatile is now marked by the
VOLATILE flag.

> 
> > @@ -225,7 +225,6 @@ struct v4l2_ctrl_config {
> >   	u32 menu_skip_mask;
> >   	const char * const *qmenu;
> >   	unsigned int is_private:1;
> > -	unsigned int is_volatile:1;
> >   };
> >
> >   /** v4l2_ctrl_fill() - Fill in the control fields based on the control ID.
> 
> Regards,
> 
> Hans
> 

Thanks!

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux