diff options
author | Sungchun Kang <sungchun.kang@samsung.com> | 2011-02-07 13:59:46 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-22 03:54:13 -0400 |
commit | 8ec737ffccd7fab629e28427b4d0581ce62ffedd (patch) | |
tree | 5f6539a5dad7db0b78f6270e0bafdfe53111777c /drivers/media/video/s5p-fimc/fimc-capture.c | |
parent | 4174ebf5ebd7a09589ff8ff3bc3246ea0a9bd356 (diff) |
[media] s5p-fimc: fix ISR and buffer handling for fimc-capture
In some cases fimc H/W did not stop although there were no output
buffers available. So the capture deactivation interrupt routine
is modified and the state of ST_CAPT_RUN is cleared only
in the LAST-IRQ call.
After LAST-IRQ is generated, H/W pointer will be skipped by 1 frame.
(reference by user manual) So, S/W pointer should be increased too.
Reviewed-by Jonghun Han <jonghun.han@samsung.com>
Signed-off-by: Sungchun Kang <sungchun.kang@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.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.c | 70 |
1 files changed, 26 insertions, 44 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 5159cc8a0e1c..6b6f72e4066c 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c | |||
@@ -153,40 +153,6 @@ static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index) | |||
153 | return ret; | 153 | return ret; |
154 | } | 154 | } |
155 | 155 | ||
156 | /* | ||
157 | * At least one buffer on the pending_buf_q queue is required. | ||
158 | * Locking: The caller holds fimc->slock spinlock. | ||
159 | */ | ||
160 | int fimc_vid_cap_buf_queue(struct fimc_dev *fimc, | ||
161 | struct fimc_vid_buffer *fimc_vb) | ||
162 | { | ||
163 | struct fimc_vid_cap *cap = &fimc->vid_cap; | ||
164 | struct fimc_ctx *ctx = cap->ctx; | ||
165 | int ret = 0; | ||
166 | |||
167 | BUG_ON(!fimc || !fimc_vb); | ||
168 | |||
169 | ret = fimc_prepare_addr(ctx, &fimc_vb->vb, &ctx->d_frame, | ||
170 | &fimc_vb->paddr); | ||
171 | if (ret) | ||
172 | return ret; | ||
173 | |||
174 | if (test_bit(ST_CAPT_STREAM, &fimc->state)) { | ||
175 | fimc_pending_queue_add(cap, fimc_vb); | ||
176 | } else { | ||
177 | /* Setup the buffer directly for processing. */ | ||
178 | int buf_id = (cap->reqbufs_count == 1) ? -1 : cap->buf_index; | ||
179 | fimc_hw_set_output_addr(fimc, &fimc_vb->paddr, buf_id); | ||
180 | |||
181 | fimc_vb->index = cap->buf_index; | ||
182 | active_queue_add(cap, fimc_vb); | ||
183 | |||
184 | if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) | ||
185 | cap->buf_index = 0; | ||
186 | } | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int fimc_stop_capture(struct fimc_dev *fimc) | 156 | static int fimc_stop_capture(struct fimc_dev *fimc) |
191 | { | 157 | { |
192 | unsigned long flags; | 158 | unsigned long flags; |
@@ -211,7 +177,7 @@ static int fimc_stop_capture(struct fimc_dev *fimc) | |||
211 | 177 | ||
212 | spin_lock_irqsave(&fimc->slock, flags); | 178 | spin_lock_irqsave(&fimc->slock, flags); |
213 | fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | | 179 | fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND | |
214 | 1 << ST_CAPT_STREAM); | 180 | 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM); |
215 | 181 | ||
216 | fimc->vid_cap.active_buf_cnt = 0; | 182 | fimc->vid_cap.active_buf_cnt = 0; |
217 | 183 | ||
@@ -239,6 +205,8 @@ static int start_streaming(struct vb2_queue *q) | |||
239 | struct s5p_fimc_isp_info *isp_info; | 205 | struct s5p_fimc_isp_info *isp_info; |
240 | int ret; | 206 | int ret; |
241 | 207 | ||
208 | fimc_hw_reset(fimc); | ||
209 | |||
242 | ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1); | 210 | ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1); |
243 | if (ret && ret != -ENOIOCTLCMD) | 211 | if (ret && ret != -ENOIOCTLCMD) |
244 | return ret; | 212 | return ret; |
@@ -273,7 +241,7 @@ static int start_streaming(struct vb2_queue *q) | |||
273 | INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); | 241 | INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); |
274 | fimc->vid_cap.active_buf_cnt = 0; | 242 | fimc->vid_cap.active_buf_cnt = 0; |
275 | fimc->vid_cap.frame_count = 0; | 243 | fimc->vid_cap.frame_count = 0; |
276 | fimc->vid_cap.buf_index = fimc_hw_get_frame_index(fimc); | 244 | fimc->vid_cap.buf_index = 0; |
277 | 245 | ||
278 | set_bit(ST_CAPT_PEND, &fimc->state); | 246 | set_bit(ST_CAPT_PEND, &fimc->state); |
279 | 247 | ||
@@ -372,19 +340,33 @@ static void buffer_queue(struct vb2_buffer *vb) | |||
372 | = container_of(vb, struct fimc_vid_buffer, vb); | 340 | = container_of(vb, struct fimc_vid_buffer, vb); |
373 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; | 341 | struct fimc_vid_cap *vid_cap = &fimc->vid_cap; |
374 | unsigned long flags; | 342 | unsigned long flags; |
343 | int min_bufs; | ||
375 | 344 | ||
376 | spin_lock_irqsave(&fimc->slock, flags); | 345 | spin_lock_irqsave(&fimc->slock, flags); |
377 | fimc_vid_cap_buf_queue(fimc, buf); | 346 | fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr); |
347 | |||
348 | if (!test_bit(ST_CAPT_STREAM, &fimc->state) | ||
349 | && vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) { | ||
350 | /* Setup the buffer directly for processing. */ | ||
351 | int buf_id = (vid_cap->reqbufs_count == 1) ? -1 : | ||
352 | vid_cap->buf_index; | ||
378 | 353 | ||
379 | dbg("active_buf_cnt: %d", fimc->vid_cap.active_buf_cnt); | 354 | fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id); |
355 | buf->index = vid_cap->buf_index; | ||
356 | active_queue_add(vid_cap, buf); | ||
380 | 357 | ||
381 | if (vid_cap->active_buf_cnt >= vid_cap->reqbufs_count || | 358 | if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS) |
382 | vid_cap->active_buf_cnt >= FIMC_MAX_OUT_BUFS) { | 359 | vid_cap->buf_index = 0; |
383 | if (!test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) { | 360 | } else { |
384 | fimc_activate_capture(ctx); | 361 | fimc_pending_queue_add(vid_cap, buf); |
385 | dbg(""); | ||
386 | } | ||
387 | } | 362 | } |
363 | |||
364 | min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1; | ||
365 | |||
366 | if (vid_cap->active_buf_cnt >= min_bufs && | ||
367 | !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) | ||
368 | fimc_activate_capture(ctx); | ||
369 | |||
388 | spin_unlock_irqrestore(&fimc->slock, flags); | 370 | spin_unlock_irqrestore(&fimc->slock, flags); |
389 | } | 371 | } |
390 | 372 | ||