Skip to content

Commit

Permalink
[media] media: vb2: change queue initialization order
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marek Szyprowski authored and Mauro Carvalho Chehab committed Sep 6, 2011
1 parent 8607c42 commit bd323e2
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 106 deletions.
20 changes: 15 additions & 5 deletions drivers/media/video/atmel-isi.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,13 @@ static void buffer_queue(struct vb2_buffer *vb)

if (isi->active == NULL) {
isi->active = buf;
start_dma(isi, buf);
if (vb2_is_streaming(vb->vb2_queue))
start_dma(isi, buf);
}
spin_unlock_irqrestore(&isi->lock, flags);
}

static int start_streaming(struct vb2_queue *vq)
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
Expand All @@ -431,17 +432,26 @@ static int start_streaming(struct vb2_queue *vq)
ret = wait_event_interruptible(isi->vsync_wq,
isi->state != ISI_STATE_IDLE);
if (ret)
return ret;
goto err;

if (isi->state != ISI_STATE_READY)
return -EIO;
if (isi->state != ISI_STATE_READY) {
ret = -EIO;
goto err;
}

spin_lock_irq(&isi->lock);
isi->state = ISI_STATE_WAIT_SOF;
isi_writel(isi, ISI_INTDIS, ISI_SR_VSYNC);
if (count)
start_dma(isi, isi->active);
spin_unlock_irq(&isi->lock);

return 0;
err:
isi->active = NULL;
isi->sequence = 0;
INIT_LIST_HEAD(&isi->video_buffer_list);
return ret;
}

/* abort streaming and wait for last buffer */
Expand Down
6 changes: 4 additions & 2 deletions drivers/media/video/marvell-ccic/mcam-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -940,12 +940,14 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
/*
* These need to be called with the mutex held from vb2
*/
static int mcam_vb_start_streaming(struct vb2_queue *vq)
static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct mcam_camera *cam = vb2_get_drv_priv(vq);

if (cam->state != S_IDLE)
if (cam->state != S_IDLE) {
INIT_LIST_HEAD(&cam->buffers);
return -EINVAL;
}
cam->sequence = 0;
/*
* Videobuf2 sneakily hoards all the buffers and won't
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/pwc/pwc-if.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ static void buffer_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}

static int start_streaming(struct vb2_queue *vq)
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);

Expand Down
65 changes: 40 additions & 25 deletions drivers/media/video/s5p-fimc/fimc-capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,27 +151,11 @@ static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index)
return ret;
}

static int fimc_stop_capture(struct fimc_dev *fimc)
static void fimc_capture_state_cleanup(struct fimc_dev *fimc)
{
unsigned long flags;
struct fimc_vid_cap *cap;
struct fimc_vid_cap *cap = &fimc->vid_cap;
struct fimc_vid_buffer *buf;

cap = &fimc->vid_cap;

if (!fimc_capture_active(fimc))
return 0;

spin_lock_irqsave(&fimc->slock, flags);
set_bit(ST_CAPT_SHUT, &fimc->state);
fimc_deactivate_capture(fimc);
spin_unlock_irqrestore(&fimc->slock, flags);

wait_event_timeout(fimc->irq_queue,
!test_bit(ST_CAPT_SHUT, &fimc->state),
FIMC_SHUTDOWN_TIMEOUT);

v4l2_subdev_call(cap->sd, video, s_stream, 0);
unsigned long flags;

spin_lock_irqsave(&fimc->slock, flags);
fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
Expand All @@ -191,27 +175,50 @@ static int fimc_stop_capture(struct fimc_dev *fimc)
}

spin_unlock_irqrestore(&fimc->slock, flags);
}

static int fimc_stop_capture(struct fimc_dev *fimc)
{
struct fimc_vid_cap *cap = &fimc->vid_cap;
unsigned long flags;

if (!fimc_capture_active(fimc))
return 0;

spin_lock_irqsave(&fimc->slock, flags);
set_bit(ST_CAPT_SHUT, &fimc->state);
fimc_deactivate_capture(fimc);
spin_unlock_irqrestore(&fimc->slock, flags);

wait_event_timeout(fimc->irq_queue,
!test_bit(ST_CAPT_SHUT, &fimc->state),
FIMC_SHUTDOWN_TIMEOUT);

v4l2_subdev_call(cap->sd, video, s_stream, 0);

fimc_capture_state_cleanup(fimc);
dbg("state: 0x%lx", fimc->state);
return 0;
}

static int start_streaming(struct vb2_queue *q)

static int start_streaming(struct vb2_queue *q, unsigned int count)
{
struct fimc_ctx *ctx = q->drv_priv;
struct fimc_dev *fimc = ctx->fimc_dev;
struct s5p_fimc_isp_info *isp_info;
int min_bufs;
int ret;

fimc_hw_reset(fimc);

ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
if (ret && ret != -ENOIOCTLCMD)
return ret;
goto error;

ret = fimc_prepare_config(ctx, ctx->state);
if (ret)
return ret;
goto error;

isp_info = &fimc->pdata->isp_info[fimc->vid_cap.input_index];
fimc_hw_set_camera_type(fimc, isp_info);
Expand All @@ -222,7 +229,7 @@ static int start_streaming(struct vb2_queue *q)
ret = fimc_set_scaler_info(ctx);
if (ret) {
err("Scaler setup error");
return ret;
goto error;
}
fimc_hw_set_input_path(ctx);
fimc_hw_set_prescaler(ctx);
Expand All @@ -237,13 +244,20 @@ static int start_streaming(struct vb2_queue *q)

INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
fimc->vid_cap.active_buf_cnt = 0;
fimc->vid_cap.frame_count = 0;
fimc->vid_cap.buf_index = 0;

set_bit(ST_CAPT_PEND, &fimc->state);

min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1;

if (fimc->vid_cap.active_buf_cnt >= min_bufs)
fimc_activate_capture(ctx);

return 0;
error:
fimc_capture_state_cleanup(fimc);
return ret;
}

static int stop_streaming(struct vb2_queue *q)
Expand Down Expand Up @@ -341,7 +355,8 @@ static void buffer_queue(struct vb2_buffer *vb)

min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1;

if (vid_cap->active_buf_cnt >= min_bufs &&
if (vb2_is_streaming(&vid_cap->vbq) &&
vid_cap->active_buf_cnt >= min_bufs &&
!test_and_set_bit(ST_CAPT_STREAM, &fimc->state))
fimc_activate_capture(ctx);

Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/s5p-mfc/s5p_mfc_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ static int s5p_mfc_buf_init(struct vb2_buffer *vb)
return 0;
}

static int s5p_mfc_start_streaming(struct vb2_queue *q)
static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
struct s5p_mfc_dev *dev = ctx->dev;
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/s5p-mfc/s5p_mfc_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
return 0;
}

static int s5p_mfc_start_streaming(struct vb2_queue *q)
static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
struct s5p_mfc_dev *dev = ctx->dev;
Expand Down
2 changes: 0 additions & 2 deletions drivers/media/video/s5p-tv/mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ struct mxr_buffer {
enum mxr_layer_state {
/** layers is not shown */
MXR_LAYER_IDLE = 0,
/** state between STREAMON and hardware start */
MXR_LAYER_STREAMING_START,
/** layer is shown */
MXR_LAYER_STREAMING,
/** state before STREAMOFF is finished */
Expand Down
22 changes: 11 additions & 11 deletions drivers/media/video/s5p-tv/mixer_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,19 +764,10 @@ static void buf_queue(struct vb2_buffer *vb)
struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
struct mxr_device *mdev = layer->mdev;
unsigned long flags;
int must_start = 0;

spin_lock_irqsave(&layer->enq_slock, flags);
if (layer->state == MXR_LAYER_STREAMING_START) {
layer->state = MXR_LAYER_STREAMING;
must_start = 1;
}
list_add_tail(&buffer->list, &layer->enq_list);
spin_unlock_irqrestore(&layer->enq_slock, flags);
if (must_start) {
layer->ops.stream_set(layer, MXR_ENABLE);
mxr_streamer_get(mdev);
}

mxr_dbg(mdev, "queuing buffer\n");
}
Expand All @@ -797,13 +788,19 @@ static void wait_unlock(struct vb2_queue *vq)
mutex_unlock(&layer->mutex);
}

static int start_streaming(struct vb2_queue *vq)
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct mxr_layer *layer = vb2_get_drv_priv(vq);
struct mxr_device *mdev = layer->mdev;
unsigned long flags;

mxr_dbg(mdev, "%s\n", __func__);

if (count == 0) {
mxr_dbg(mdev, "no output buffers queued\n");
return -EINVAL;
}

/* block any changes in output configuration */
mxr_output_get(mdev);

Expand All @@ -814,9 +811,12 @@ static int start_streaming(struct vb2_queue *vq)
layer->ops.format_set(layer);
/* enabling layer in hardware */
spin_lock_irqsave(&layer->enq_slock, flags);
layer->state = MXR_LAYER_STREAMING_START;
layer->state = MXR_LAYER_STREAMING;
spin_unlock_irqrestore(&layer->enq_slock, flags);

layer->ops.stream_set(layer, MXR_ENABLE);
mxr_streamer_get(mdev);

return 0;
}

Expand Down
Loading

0 comments on commit bd323e2

Please sign in to comment.