aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2011-08-29 07:51:49 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-09-06 14:07:20 -0400
commitbd323e28bd82dfd4b72c50ddc4d5fc24e3678b99 (patch)
tree189921e2d10c732f8e439eb38a54f481ea4b05cf /drivers/media
parent8607c42540d0aa61ab562506681d34c245b91fae (diff)
[media] media: vb2: change queue initialization order
This patch changes the order of operations during stream on call. Now the buffers are first queued to the driver and then the start_streaming method is called. This resolves the most common case when the driver needs to know buffer addresses to enable dma engine and start streaming. Additional parameter to start_streaming method have been added to simplify drivers code. The driver are now obliged to check if the number of queued buffers is high enough to enable hardware streaming. If not - it can return an error. In such case all the buffers that have been pre-queued are invalidated. This patch also updates all videobuf2 clients to work properly with the changed order of operations. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> CC: Pawel Osciak <pawel@osciak.com> CC: Guennadi Liakhovetski <g.liakhovetski@gmx.de> CC: Hans Verkuil <hverkuil@xs4all.nl> CC: Tomasz Stanislawski <t.stanislaws@samsung.com> CC: Sylwester Nawrocki <s.nawrocki@samsung.com> CC: Kamil Debski <k.debski@samsung.com> CC: Jonathan Corbet <corbet@lwn.net> CC: Josh Wu <josh.wu@atmel.com> CC: Hans de Goede <hdegoede@redhat.com> CC: Paul Mundt <lethal@linux-sh.org> Tested-by: Josh Wu <josh.wu@atmel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/atmel-isi.c20
-rw-r--r--drivers/media/video/marvell-ccic/mcam-core.c6
-rw-r--r--drivers/media/video/pwc/pwc-if.c2
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c65
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_dec.c2
-rw-r--r--drivers/media/video/s5p-mfc/s5p_mfc_enc.c2
-rw-r--r--drivers/media/video/s5p-tv/mixer.h2
-rw-r--r--drivers/media/video/s5p-tv/mixer_video.c22
-rw-r--r--drivers/media/video/videobuf2-core.c97
-rw-r--r--drivers/media/video/vivi.c2
10 files changed, 118 insertions, 102 deletions
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
index 7e1d7896fc6..774715d2f84 100644
--- a/drivers/media/video/atmel-isi.c
+++ b/drivers/media/video/atmel-isi.c
@@ -404,12 +404,13 @@ static void buffer_queue(struct vb2_buffer *vb)
404 404
405 if (isi->active == NULL) { 405 if (isi->active == NULL) {
406 isi->active = buf; 406 isi->active = buf;
407 start_dma(isi, buf); 407 if (vb2_is_streaming(vb->vb2_queue))
408 start_dma(isi, buf);
408 } 409 }
409 spin_unlock_irqrestore(&isi->lock, flags); 410 spin_unlock_irqrestore(&isi->lock, flags);
410} 411}
411 412
412static int start_streaming(struct vb2_queue *vq) 413static int start_streaming(struct vb2_queue *vq, unsigned int count)
413{ 414{
414 struct soc_camera_device *icd = soc_camera_from_vb2q(vq); 415 struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
415 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 416 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
@@ -431,17 +432,26 @@ static int start_streaming(struct vb2_queue *vq)
431 ret = wait_event_interruptible(isi->vsync_wq, 432 ret = wait_event_interruptible(isi->vsync_wq,
432 isi->state != ISI_STATE_IDLE); 433 isi->state != ISI_STATE_IDLE);
433 if (ret) 434 if (ret)
434 return ret; 435 goto err;
435 436
436 if (isi->state != ISI_STATE_READY) 437 if (isi->state != ISI_STATE_READY) {
437 return -EIO; 438 ret = -EIO;
439 goto err;
440 }
438 441
439 spin_lock_irq(&isi->lock); 442 spin_lock_irq(&isi->lock);
440 isi->state = ISI_STATE_WAIT_SOF; 443 isi->state = ISI_STATE_WAIT_SOF;
441 isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC); 444 isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC);
445 if (count)
446 start_dma(isi, isi->active);
442 spin_unlock_irq(&isi->lock); 447 spin_unlock_irq(&isi->lock);
443 448
444 return 0; 449 return 0;
450err:
451 isi->active = NULL;
452 isi->sequence = 0;
453 INIT_LIST_HEAD(&isi->video_buffer_list);
454 return ret;
445} 455}
446 456
447/* abort streaming and wait for last buffer */ 457/* abort streaming and wait for last buffer */
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c
index 7abe5030724..1141b976dff 100644
--- a/drivers/media/video/marvell-ccic/mcam-core.c
+++ b/drivers/media/video/marvell-ccic/mcam-core.c
@@ -940,12 +940,14 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
940/* 940/*
941 * These need to be called with the mutex held from vb2 941 * These need to be called with the mutex held from vb2
942 */ 942 */
943static int mcam_vb_start_streaming(struct vb2_queue *vq) 943static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
944{ 944{
945 struct mcam_camera *cam = vb2_get_drv_priv(vq); 945 struct mcam_camera *cam = vb2_get_drv_priv(vq);
946 946
947 if (cam->state != S_IDLE) 947 if (cam->state != S_IDLE) {
948 INIT_LIST_HEAD(&cam->buffers);
948 return -EINVAL; 949 return -EINVAL;
950 }
949 cam->sequence = 0; 951 cam->sequence = 0;
950 /* 952 /*
951 * Videobuf2 sneakily hoards all the buffers and won't 953 * Videobuf2 sneakily hoards all the buffers and won't
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index a7e4f561c86..360be226718 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -816,7 +816,7 @@ static void buffer_queue(struct vb2_buffer *vb)
816 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); 816 spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
817} 817}
818 818
819static int start_streaming(struct vb2_queue *vq) 819static int start_streaming(struct vb2_queue *vq, unsigned int count)
820{ 820{
821 struct pwc_device *pdev = vb2_get_drv_priv(vq); 821 struct pwc_device *pdev = vb2_get_drv_priv(vq);
822 822
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index e6afe5f5e24..287d099caf8 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -151,27 +151,11 @@ static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index)
151 return ret; 151 return ret;
152} 152}
153 153
154static int fimc_stop_capture(struct fimc_dev *fimc) 154static void fimc_capture_state_cleanup(struct fimc_dev *fimc)
155{ 155{
156 unsigned long flags; 156 struct fimc_vid_cap *cap = &fimc->vid_cap;
157 struct fimc_vid_cap *cap;
158 struct fimc_vid_buffer *buf; 157 struct fimc_vid_buffer *buf;
159 158 unsigned long flags;
160 cap = &fimc->vid_cap;
161
162 if (!fimc_capture_active(fimc))
163 return 0;
164
165 spin_lock_irqsave(&fimc->slock, flags);
166 set_bit(ST_CAPT_SHUT, &fimc->state);
167 fimc_deactivate_capture(fimc);
168 spin_unlock_irqrestore(&fimc->slock, flags);
169
170 wait_event_timeout(fimc->irq_queue,
171 !test_bit(ST_CAPT_SHUT, &fimc->state),
172 FIMC_SHUTDOWN_TIMEOUT);
173
174 v4l2_subdev_call(cap->sd, video, s_stream, 0);
175 159
176 spin_lock_irqsave(&fimc->slock, flags); 160 spin_lock_irqsave(&fimc->slock, flags);
177 fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | 161 fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
@@ -191,27 +175,50 @@ static int fimc_stop_capture(struct fimc_dev *fimc)
191 } 175 }
192 176
193 spin_unlock_irqrestore(&fimc->slock, flags); 177 spin_unlock_irqrestore(&fimc->slock, flags);
178}
179
180static int fimc_stop_capture(struct fimc_dev *fimc)
181{
182 struct fimc_vid_cap *cap = &fimc->vid_cap;
183 unsigned long flags;
184
185 if (!fimc_capture_active(fimc))
186 return 0;
187
188 spin_lock_irqsave(&fimc->slock, flags);
189 set_bit(ST_CAPT_SHUT, &fimc->state);
190 fimc_deactivate_capture(fimc);
191 spin_unlock_irqrestore(&fimc->slock, flags);
192
193 wait_event_timeout(fimc->irq_queue,
194 !test_bit(ST_CAPT_SHUT, &fimc->state),
195 FIMC_SHUTDOWN_TIMEOUT);
194 196
197 v4l2_subdev_call(cap->sd, video, s_stream, 0);
198
199 fimc_capture_state_cleanup(fimc);
195 dbg("state: 0x%lx", fimc->state); 200 dbg("state: 0x%lx", fimc->state);
196 return 0; 201 return 0;
197} 202}
198 203
199static int start_streaming(struct vb2_queue *q) 204
205static int start_streaming(struct vb2_queue *q, unsigned int count)
200{ 206{
201 struct fimc_ctx *ctx = q->drv_priv; 207 struct fimc_ctx *ctx = q->drv_priv;
202 struct fimc_dev *fimc = ctx->fimc_dev; 208 struct fimc_dev *fimc = ctx->fimc_dev;
203 struct s5p_fimc_isp_info *isp_info; 209 struct s5p_fimc_isp_info *isp_info;
210 int min_bufs;
204 int ret; 211 int ret;
205 212
206 fimc_hw_reset(fimc); 213 fimc_hw_reset(fimc);
207 214
208 ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1); 215 ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
209 if (ret && ret != -ENOIOCTLCMD) 216 if (ret && ret != -ENOIOCTLCMD)
210 return ret; 217 goto error;
211 218
212 ret = fimc_prepare_config(ctx, ctx->state); 219 ret = fimc_prepare_config(ctx, ctx->state);
213 if (ret) 220 if (ret)
214 return ret; 221 goto error;
215 222
216 isp_info = &fimc->pdata->isp_info[fimc->vid_cap.input_index]; 223 isp_info = &fimc->pdata->isp_info[fimc->vid_cap.input_index];
217 fimc_hw_set_camera_type(fimc, isp_info); 224 fimc_hw_set_camera_type(fimc, isp_info);
@@ -222,7 +229,7 @@ static int start_streaming(struct vb2_queue *q)
222 ret = fimc_set_scaler_info(ctx); 229 ret = fimc_set_scaler_info(ctx);
223 if (ret) { 230 if (ret) {
224 err("Scaler setup error"); 231 err("Scaler setup error");
225 return ret; 232 goto error;
226 } 233 }
227 fimc_hw_set_input_path(ctx); 234 fimc_hw_set_input_path(ctx);
228 fimc_hw_set_prescaler(ctx); 235 fimc_hw_set_prescaler(ctx);
@@ -237,13 +244,20 @@ static int start_streaming(struct vb2_queue *q)
237 244
238 INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q); 245 INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
239 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); 246 INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
240 fimc->vid_cap.active_buf_cnt = 0;
241 fimc->vid_cap.frame_count = 0; 247 fimc->vid_cap.frame_count = 0;
242 fimc->vid_cap.buf_index = 0; 248 fimc->vid_cap.buf_index = 0;
243 249
244 set_bit(ST_CAPT_PEND, &fimc->state); 250 set_bit(ST_CAPT_PEND, &fimc->state);
245 251
252 min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1;
253
254 if (fimc->vid_cap.active_buf_cnt >= min_bufs)
255 fimc_activate_capture(ctx);
256
246 return 0; 257 return 0;
258error:
259 fimc_capture_state_cleanup(fimc);
260 return ret;
247} 261}
248 262
249static int stop_streaming(struct vb2_queue *q) 263static int stop_streaming(struct vb2_queue *q)
@@ -341,7 +355,8 @@ static void buffer_queue(struct vb2_buffer *vb)
341 355
342 min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1; 356 min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1;
343 357
344 if (vid_cap->active_buf_cnt >= min_bufs && 358 if (vb2_is_streaming(&vid_cap->vbq) &&
359 vid_cap->active_buf_cnt >= min_bufs &&
345 !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) 360 !test_and_set_bit(ST_CAPT_STREAM, &fimc->state))
346 fimc_activate_capture(ctx); 361 fimc_activate_capture(ctx);
347 362
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index 4540dc2944e..32f89897980 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -864,7 +864,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
864 return 0; 864 return 0;
865} 865}
866 866
867static int s5p_mfc_start_streaming(struct vb2_queue *q) 867static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
868{ 868{
869 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); 869 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
870 struct s5p_mfc_dev *dev = ctx->dev; 870 struct s5p_mfc_dev *dev = ctx->dev;
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
index e11b19a8d71..14ddbd26ebf 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
@@ -1640,7 +1640,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
1640 return 0; 1640 return 0;
1641} 1641}
1642 1642
1643static int s5p_mfc_start_streaming(struct vb2_queue *q) 1643static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
1644{ 1644{
1645 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv); 1645 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
1646 struct s5p_mfc_dev *dev = ctx->dev; 1646 struct s5p_mfc_dev *dev = ctx->dev;
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h
index e2242243f63..51ad59b3035 100644
--- a/drivers/media/video/s5p-tv/mixer.h
+++ b/drivers/media/video/s5p-tv/mixer.h
@@ -111,8 +111,6 @@ struct mxr_buffer {
111enum mxr_layer_state { 111enum mxr_layer_state {
112 /** layers is not shown */ 112 /** layers is not shown */
113 MXR_LAYER_IDLE = 0, 113 MXR_LAYER_IDLE = 0,
114 /** state between STREAMON and hardware start */
115 MXR_LAYER_STREAMING_START,
116 /** layer is shown */ 114 /** layer is shown */
117 MXR_LAYER_STREAMING, 115 MXR_LAYER_STREAMING,
118 /** state before STREAMOFF is finished */ 116 /** state before STREAMOFF is finished */
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index 8bea0f3927f..4917e2c2b32 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -764,19 +764,10 @@ static void buf_queue(struct vb2_buffer *vb)
764 struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue); 764 struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
765 struct mxr_device *mdev = layer->mdev; 765 struct mxr_device *mdev = layer->mdev;
766 unsigned long flags; 766 unsigned long flags;
767 int must_start = 0;
768 767
769 spin_lock_irqsave(&layer->enq_slock, flags); 768 spin_lock_irqsave(&layer->enq_slock, flags);
770 if (layer->state == MXR_LAYER_STREAMING_START) {
771 layer->state = MXR_LAYER_STREAMING;
772 must_start = 1;
773 }
774 list_add_tail(&buffer->list, &layer->enq_list); 769 list_add_tail(&buffer->list, &layer->enq_list);
775 spin_unlock_irqrestore(&layer->enq_slock, flags); 770 spin_unlock_irqrestore(&layer->enq_slock, flags);
776 if (must_start) {
777 layer->ops.stream_set(layer, MXR_ENABLE);
778 mxr_streamer_get(mdev);
779 }
780 771
781 mxr_dbg(mdev, "queuing buffer\n"); 772 mxr_dbg(mdev, "queuing buffer\n");
782} 773}
@@ -797,13 +788,19 @@ static void wait_unlock(struct vb2_queue *vq)
797 mutex_unlock(&layer->mutex); 788 mutex_unlock(&layer->mutex);
798} 789}
799 790
800static int start_streaming(struct vb2_queue *vq) 791static int start_streaming(struct vb2_queue *vq, unsigned int count)
801{ 792{
802 struct mxr_layer *layer = vb2_get_drv_priv(vq); 793 struct mxr_layer *layer = vb2_get_drv_priv(vq);
803 struct mxr_device *mdev = layer->mdev; 794 struct mxr_device *mdev = layer->mdev;
804 unsigned long flags; 795 unsigned long flags;
805 796
806 mxr_dbg(mdev, "%s\n", __func__); 797 mxr_dbg(mdev, "%s\n", __func__);
798
799 if (count == 0) {
800 mxr_dbg(mdev, "no output buffers queued\n");
801 return -EINVAL;
802 }
803
807 /* block any changes in output configuration */ 804 /* block any changes in output configuration */
808 mxr_output_get(mdev); 805 mxr_output_get(mdev);
809 806
@@ -814,9 +811,12 @@ static int start_streaming(struct vb2_queue *vq)
814 layer->ops.format_set(layer); 811 layer->ops.format_set(layer);
815 /* enabling layer in hardware */ 812 /* enabling layer in hardware */
816 spin_lock_irqsave(&layer->enq_slock, flags); 813 spin_lock_irqsave(&layer->enq_slock, flags);
817 layer->state = MXR_LAYER_STREAMING_START; 814 layer->state = MXR_LAYER_STREAMING;
818 spin_unlock_irqrestore(&layer->enq_slock, flags); 815 spin_unlock_irqrestore(&layer->enq_slock, flags);
819 816
817 layer->ops.stream_set(layer, MXR_ENABLE);
818 mxr_streamer_get(mdev);
819
820 return 0; 820 return 0;
821} 821}
822 822
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c
index e89fd53a021..6687ac33726 100644
--- a/drivers/media/video/videobuf2-core.c
+++ b/drivers/media/video/videobuf2-core.c
@@ -1111,6 +1111,43 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
1111EXPORT_SYMBOL_GPL(vb2_dqbuf); 1111EXPORT_SYMBOL_GPL(vb2_dqbuf);
1112 1112
1113/** 1113/**
1114 * __vb2_queue_cancel() - cancel and stop (pause) streaming
1115 *
1116 * Removes all queued buffers from driver's queue and all buffers queued by
1117 * userspace from videobuf's queue. Returns to state after reqbufs.
1118 */
1119static void __vb2_queue_cancel(struct vb2_queue *q)
1120{
1121 unsigned int i;
1122
1123 /*
1124 * Tell driver to stop all transactions and release all queued
1125 * buffers.
1126 */
1127 if (q->streaming)
1128 call_qop(q, stop_streaming, q);
1129 q->streaming = 0;
1130
1131 /*
1132 * Remove all buffers from videobuf's list...
1133 */
1134 INIT_LIST_HEAD(&q->queued_list);
1135 /*
1136 * ...and done list; userspace will not receive any buffers it
1137 * has not already dequeued before initiating cancel.
1138 */
1139 INIT_LIST_HEAD(&q->done_list);
1140 atomic_set(&q->queued_count, 0);
1141 wake_up_all(&q->done_wq);
1142
1143 /*
1144 * Reinitialize all buffers for next use.
1145 */
1146 for (i = 0; i < q->num_buffers; ++i)
1147 q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
1148}
1149
1150/**
1114 * vb2_streamon - start streaming 1151 * vb2_streamon - start streaming
1115 * @q: videobuf2 queue 1152 * @q: videobuf2 queue
1116 * @type: type argument passed from userspace to vidioc_streamon handler 1153 * @type: type argument passed from userspace to vidioc_streamon handler
@@ -1118,7 +1155,7 @@ EXPORT_SYMBOL_GPL(vb2_dqbuf);
1118 * Should be called from vidioc_streamon handler of a driver. 1155 * Should be called from vidioc_streamon handler of a driver.
1119 * This function: 1156 * This function:
1120 * 1) verifies current state 1157 * 1) verifies current state
1121 * 2) starts streaming and passes any previously queued buffers to the driver 1158 * 2) passes any previously queued buffers to the driver and starts streaming
1122 * 1159 *
1123 * The return values from this function are intended to be directly returned 1160 * The return values from this function are intended to be directly returned
1124 * from vidioc_streamon handler in the driver. 1161 * from vidioc_streamon handler in the driver.
@@ -1144,75 +1181,29 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
1144 } 1181 }
1145 1182
1146 /* 1183 /*
1147 * Cannot start streaming on an OUTPUT device if no buffers have 1184 * If any buffers were queued before streamon,
1148 * been queued yet. 1185 * we can now pass them to driver for processing.
1149 */ 1186 */
1150 if (V4L2_TYPE_IS_OUTPUT(q->type)) { 1187 list_for_each_entry(vb, &q->queued_list, queued_entry)
1151 if (list_empty(&q->queued_list)) { 1188 __enqueue_in_driver(vb);
1152 dprintk(1, "streamon: no output buffers queued\n");
1153 return -EINVAL;
1154 }
1155 }
1156 1189
1157 /* 1190 /*
1158 * Let driver notice that streaming state has been enabled. 1191 * Let driver notice that streaming state has been enabled.
1159 */ 1192 */
1160 ret = call_qop(q, start_streaming, q); 1193 ret = call_qop(q, start_streaming, q, atomic_read(&q->queued_count));
1161 if (ret) { 1194 if (ret) {
1162 dprintk(1, "streamon: driver refused to start streaming\n"); 1195 dprintk(1, "streamon: driver refused to start streaming\n");
1196 __vb2_queue_cancel(q);
1163 return ret; 1197 return ret;
1164 } 1198 }
1165 1199
1166 q->streaming = 1; 1200 q->streaming = 1;
1167 1201
1168 /*
1169 * If any buffers were queued before streamon,
1170 * we can now pass them to driver for processing.
1171 */
1172 list_for_each_entry(vb, &q->queued_list, queued_entry)
1173 __enqueue_in_driver(vb);
1174
1175 dprintk(3, "Streamon successful\n"); 1202 dprintk(3, "Streamon successful\n");
1176 return 0; 1203 return 0;
1177} 1204}
1178EXPORT_SYMBOL_GPL(vb2_streamon); 1205EXPORT_SYMBOL_GPL(vb2_streamon);
1179 1206
1180/**
1181 * __vb2_queue_cancel() - cancel and stop (pause) streaming
1182 *
1183 * Removes all queued buffers from driver's queue and all buffers queued by
1184 * userspace from videobuf's queue. Returns to state after reqbufs.
1185 */
1186static void __vb2_queue_cancel(struct vb2_queue *q)
1187{
1188 unsigned int i;
1189
1190 /*
1191 * Tell driver to stop all transactions and release all queued
1192 * buffers.
1193 */
1194 if (q->streaming)
1195 call_qop(q, stop_streaming, q);
1196 q->streaming = 0;
1197
1198 /*
1199 * Remove all buffers from videobuf's list...
1200 */
1201 INIT_LIST_HEAD(&q->queued_list);
1202 /*
1203 * ...and done list; userspace will not receive any buffers it
1204 * has not already dequeued before initiating cancel.
1205 */
1206 INIT_LIST_HEAD(&q->done_list);
1207 atomic_set(&q->queued_count, 0);
1208 wake_up_all(&q->done_wq);
1209
1210 /*
1211 * Reinitialize all buffers for next use.
1212 */
1213 for (i = 0; i < q->num_buffers; ++i)
1214 q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
1215}
1216 1207
1217/** 1208/**
1218 * vb2_streamoff - stop streaming 1209 * vb2_streamoff - stop streaming
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index cfe68325d65..21bb324b701 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -766,7 +766,7 @@ static void buffer_queue(struct vb2_buffer *vb)
766 spin_unlock_irqrestore(&dev->slock, flags); 766 spin_unlock_irqrestore(&dev->slock, flags);
767} 767}
768 768
769static int start_streaming(struct vb2_queue *vq) 769static int start_streaming(struct vb2_queue *vq, unsigned int count)
770{ 770{
771 struct vivi_dev *dev = vb2_get_drv_priv(vq); 771 struct vivi_dev *dev = vb2_get_drv_priv(vq);
772 dprintk(dev, 1, "%s\n", __func__); 772 dprintk(dev, 1, "%s\n", __func__);