aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/s5p-fimc
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2011-08-29 08:51:49 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-09-06 15:07:20 -0300
commitbd323e28bd82dfd4b72c50ddc4d5fc24e3678b99 (patch)
tree189921e2d10c732f8e439eb38a54f481ea4b05cf /drivers/media/video/s5p-fimc
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/video/s5p-fimc')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c65
1 files changed, 40 insertions, 25 deletions
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)
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 |
@@ -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);
@@ -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);
@@ -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)
@@ -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);