diff options
Diffstat (limited to 'drivers/media/platform/atmel/atmel-isc-base.c')
| -rw-r--r-- | drivers/media/platform/atmel/atmel-isc-base.c | 34 | 
1 files changed, 28 insertions, 6 deletions
| diff --git a/drivers/media/platform/atmel/atmel-isc-base.c b/drivers/media/platform/atmel/atmel-isc-base.c index db15770d5b88..2f07a50035c8 100644 --- a/drivers/media/platform/atmel/atmel-isc-base.c +++ b/drivers/media/platform/atmel/atmel-isc-base.c @@ -401,6 +401,7 @@ static void isc_stop_streaming(struct vb2_queue *vq)  	struct isc_buffer *buf;  	int ret; +	mutex_lock(&isc->awb_mutex);  	v4l2_ctrl_activate(isc->do_wb_ctrl, false);  	isc->stop = true; @@ -410,6 +411,8 @@ static void isc_stop_streaming(struct vb2_queue *vq)  		v4l2_err(&isc->v4l2_dev,  			 "Timeout waiting for end of the capture\n"); +	mutex_unlock(&isc->awb_mutex); +  	/* Disable DMA interrupt */  	regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE); @@ -442,7 +445,7 @@ static void isc_buffer_queue(struct vb2_buffer *vb)  	spin_lock_irqsave(&isc->dma_queue_lock, flags);  	if (!isc->cur_frm && list_empty(&isc->dma_queue) && -		vb2_is_streaming(vb->vb2_queue)) { +		vb2_start_streaming_called(vb->vb2_queue)) {  		isc->cur_frm = buf;  		isc_start_dma(isc);  	} else @@ -1029,7 +1032,7 @@ static int isc_s_fmt_vid_cap(struct file *file, void *priv,  {  	struct isc_device *isc = video_drvdata(file); -	if (vb2_is_streaming(&isc->vb2_vidq)) +	if (vb2_is_busy(&isc->vb2_vidq))  		return -EBUSY;  	return isc_set_fmt(isc, f); @@ -1397,10 +1400,6 @@ static void isc_awb_work(struct work_struct *w)  	u32 min, max;  	int ret; -	/* streaming is not active anymore */ -	if (isc->stop) -		return; -  	if (ctrls->hist_stat != HIST_ENABLED)  		return; @@ -1455,7 +1454,24 @@ static void isc_awb_work(struct work_struct *w)  	}  	regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,  		     hist_id | baysel | ISC_HIS_CFG_RAR); + +	/* +	 * We have to make sure the streaming has not stopped meanwhile. +	 * ISC requires a frame to clock the internal profile update. +	 * To avoid issues, lock the sequence with a mutex +	 */ +	mutex_lock(&isc->awb_mutex); + +	/* streaming is not active anymore */ +	if (isc->stop) { +		mutex_unlock(&isc->awb_mutex); +		return; +	}; +  	isc_update_profile(isc); + +	mutex_unlock(&isc->awb_mutex); +  	/* if awb has been disabled, we don't need to start another histogram */  	if (ctrls->awb)  		regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ); @@ -1534,6 +1550,7 @@ static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)  		isc_update_awb_ctrls(isc); +		mutex_lock(&isc->awb_mutex);  		if (vb2_is_streaming(&isc->vb2_vidq)) {  			/*  			 * If we are streaming, we can update profile to @@ -1548,6 +1565,7 @@ static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)  			 */  			v4l2_ctrl_activate(isc->do_wb_ctrl, false);  		} +		mutex_unlock(&isc->awb_mutex);  		/* if we have autowhitebalance on, start histogram procedure */  		if (ctrls->awb == ISC_WB_AUTO && @@ -1729,6 +1747,7 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier,  {  	struct isc_device *isc = container_of(notifier->v4l2_dev,  					      struct isc_device, v4l2_dev); +	mutex_destroy(&isc->awb_mutex);  	cancel_work_sync(&isc->awb_work);  	video_unregister_device(&isc->video_dev);  	v4l2_ctrl_handler_free(&isc->ctrls.handler); @@ -1838,6 +1857,8 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)  	isc->current_subdev = container_of(notifier,  					   struct isc_subdev_entity, notifier);  	mutex_init(&isc->lock); +	mutex_init(&isc->awb_mutex); +  	init_completion(&isc->comp);  	/* Initialize videobuf2 queue */ @@ -1906,6 +1927,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)  	return 0;  isc_async_complete_err: +	mutex_destroy(&isc->awb_mutex);  	mutex_destroy(&isc->lock);  	return ret;  } | 
