aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc/fimc-capture.c
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/video/s5p-fimc/fimc-capture.c
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/fimc-capture.c')
-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 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
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