diff options
-rw-r--r-- | drivers/media/video/atmel-isi.c | 20 | ||||
-rw-r--r-- | drivers/media/video/marvell-ccic/mcam-core.c | 6 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 2 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-capture.c | 65 | ||||
-rw-r--r-- | drivers/media/video/s5p-mfc/s5p_mfc_dec.c | 2 | ||||
-rw-r--r-- | drivers/media/video/s5p-mfc/s5p_mfc_enc.c | 2 | ||||
-rw-r--r-- | drivers/media/video/s5p-tv/mixer.h | 2 | ||||
-rw-r--r-- | drivers/media/video/s5p-tv/mixer_video.c | 22 | ||||
-rw-r--r-- | drivers/media/video/videobuf2-core.c | 97 | ||||
-rw-r--r-- | drivers/media/video/vivi.c | 2 | ||||
-rw-r--r-- | include/media/videobuf2-core.h | 17 |
11 files changed, 131 insertions, 106 deletions
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c index 7e1d7896fc6e..774715d2f84f 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 | ||
412 | static int start_streaming(struct vb2_queue *vq) | 413 | static 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; |
450 | err: | ||
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 7abe5030724e..1141b976dff4 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 | */ |
943 | static int mcam_vb_start_streaming(struct vb2_queue *vq) | 943 | static 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 a7e4f561c860..360be226718d 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 | ||
819 | static int start_streaming(struct vb2_queue *vq) | 819 | static 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 e6afe5f5e24a..287d099caf83 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 | ||
154 | static int fimc_stop_capture(struct fimc_dev *fimc) | 154 | static 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 | |||
180 | static 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 | ||
199 | static int start_streaming(struct vb2_queue *q) | 204 | |
205 | static 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; |
258 | error: | ||
259 | fimc_capture_state_cleanup(fimc); | ||
260 | return ret; | ||
247 | } | 261 | } |
248 | 262 | ||
249 | static int stop_streaming(struct vb2_queue *q) | 263 | static 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 4540dc2944e0..32f898979809 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 | ||
867 | static int s5p_mfc_start_streaming(struct vb2_queue *q) | 867 | static 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 e11b19a8d71a..14ddbd26ebf4 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 | ||
1643 | static int s5p_mfc_start_streaming(struct vb2_queue *q) | 1643 | static 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 e2242243f63d..51ad59b30358 100644 --- a/drivers/media/video/s5p-tv/mixer.h +++ b/drivers/media/video/s5p-tv/mixer.h | |||
@@ -111,8 +111,6 @@ struct mxr_buffer { | |||
111 | enum mxr_layer_state { | 111 | enum 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 8bea0f3927fb..4917e2c2b321 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 | ||
800 | static int start_streaming(struct vb2_queue *vq) | 791 | static 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 e89fd53a021a..6687ac33726a 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) | |||
1111 | EXPORT_SYMBOL_GPL(vb2_dqbuf); | 1111 | EXPORT_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 | */ | ||
1119 | static 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 | } |
1178 | EXPORT_SYMBOL_GPL(vb2_streamon); | 1205 | EXPORT_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 | */ | ||
1186 | static 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 cfe68325d659..21bb324b701a 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 | ||
769 | static int start_streaming(struct vb2_queue *vq) | 769 | static 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__); |
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 5287e901e17b..ea55c08eddfb 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h | |||
@@ -196,15 +196,24 @@ struct vb2_buffer { | |||
196 | * before userspace accesses the buffer; optional | 196 | * before userspace accesses the buffer; optional |
197 | * @buf_cleanup: called once before the buffer is freed; drivers may | 197 | * @buf_cleanup: called once before the buffer is freed; drivers may |
198 | * perform any additional cleanup; optional | 198 | * perform any additional cleanup; optional |
199 | * @start_streaming: called once before entering 'streaming' state; enables | 199 | * @start_streaming: called once to enter 'streaming' state; the driver may |
200 | * driver to receive buffers over buf_queue() callback | 200 | * receive buffers with @buf_queue callback before |
201 | * @start_streaming is called; the driver gets the number | ||
202 | * of already queued buffers in count parameter; driver | ||
203 | * can return an error if hardware fails or not enough | ||
204 | * buffers has been queued, in such case all buffers that | ||
205 | * have been already given by the @buf_queue callback are | ||
206 | * invalidated. | ||
201 | * @stop_streaming: called when 'streaming' state must be disabled; driver | 207 | * @stop_streaming: called when 'streaming' state must be disabled; driver |
202 | * should stop any DMA transactions or wait until they | 208 | * should stop any DMA transactions or wait until they |
203 | * finish and give back all buffers it got from buf_queue() | 209 | * finish and give back all buffers it got from buf_queue() |
204 | * callback; may use vb2_wait_for_all_buffers() function | 210 | * callback; may use vb2_wait_for_all_buffers() function |
205 | * @buf_queue: passes buffer vb to the driver; driver may start | 211 | * @buf_queue: passes buffer vb to the driver; driver may start |
206 | * hardware operation on this buffer; driver should give | 212 | * hardware operation on this buffer; driver should give |
207 | * the buffer back by calling vb2_buffer_done() function | 213 | * the buffer back by calling vb2_buffer_done() function; |
214 | * it is allways called after calling STREAMON ioctl; | ||
215 | * might be called before start_streaming callback if user | ||
216 | * pre-queued buffers before calling STREAMON | ||
208 | */ | 217 | */ |
209 | struct vb2_ops { | 218 | struct vb2_ops { |
210 | int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers, | 219 | int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers, |
@@ -219,7 +228,7 @@ struct vb2_ops { | |||
219 | int (*buf_finish)(struct vb2_buffer *vb); | 228 | int (*buf_finish)(struct vb2_buffer *vb); |
220 | void (*buf_cleanup)(struct vb2_buffer *vb); | 229 | void (*buf_cleanup)(struct vb2_buffer *vb); |
221 | 230 | ||
222 | int (*start_streaming)(struct vb2_queue *q); | 231 | int (*start_streaming)(struct vb2_queue *q, unsigned int count); |
223 | int (*stop_streaming)(struct vb2_queue *q); | 232 | int (*stop_streaming)(struct vb2_queue *q); |
224 | 233 | ||
225 | void (*buf_queue)(struct vb2_buffer *vb); | 234 | void (*buf_queue)(struct vb2_buffer *vb); |