/* * At least one buffer on the pending_buf_q queue is required. * Locking: The caller holds fimc->slock spinlock. */ int fimc_vid_cap_buf_queue(struct fimc_dev *fimc, struct fimc_vid_buffer *fimc_vb) { struct fimc_vid_cap *cap = &fimc->vid_cap; struct fimc_ctx *ctx = cap->ctx; int ret = 0; BUG_ON(!fimc || !fimc_vb); ret = fimc_prepare_addr(ctx, fimc_vb, &ctx->d_frame, &fimc_vb->paddr); if (ret) return ret; if (test_bit(ST_CAPT_STREAM, &fimc->state)) { fimc_pending_queue_add(cap, fimc_vb); } else { /* Setup the buffer directly for processing. */ int buf_id = (cap->reqbufs_count == 1) ? -1 : cap->buf_index; fimc_hw_set_output_addr(fimc, &fimc_vb->paddr, buf_id); fimc_vb->index = cap->buf_index; active_queue_add(cap, fimc_vb); if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) cap->buf_index = 0; } return ret; }
static void fimc_capture_irq_handler(struct fimc_dev *fimc) { struct fimc_vid_cap *cap = &fimc->vid_cap; struct fimc_vid_buffer *v_buf; struct timeval *tv; struct timespec ts; if (!list_empty(&cap->active_buf_q) && test_bit(ST_CAPT_RUN, &fimc->state)) { ktime_get_real_ts(&ts); v_buf = active_queue_pop(cap); tv = &v_buf->vb.v4l2_buf.timestamp; tv->tv_sec = ts.tv_sec; tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; v_buf->vb.v4l2_buf.sequence = cap->frame_count++; vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE); } if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) { wake_up(&fimc->irq_queue); return; } if (!list_empty(&cap->pending_buf_q)) { v_buf = pending_queue_pop(cap); fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index); v_buf->index = cap->buf_index; /* Move the buffer to the capture active queue */ active_queue_add(cap, v_buf); dbg("next frame: %d, done frame: %d", fimc_hw_get_frame_index(fimc), v_buf->index); if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) cap->buf_index = 0; } if (cap->active_buf_cnt == 0) { clear_bit(ST_CAPT_RUN, &fimc->state); if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) cap->buf_index = 0; } else { set_bit(ST_CAPT_RUN, &fimc->state); } dbg("frame: %d, active_buf_cnt: %d", fimc_hw_get_frame_index(fimc), cap->active_buf_cnt); }
static void fimc_capture_irq_handler(struct fimc_dev *fimc) { struct fimc_vid_cap *cap = &fimc->vid_cap; struct fimc_vid_buffer *v_buf; if (!list_empty(&cap->active_buf_q) && test_bit(ST_CAPT_RUN, &fimc->state)) { v_buf = active_queue_pop(cap); vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE); } if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) { wake_up(&fimc->irq_queue); return; } if (!list_empty(&cap->pending_buf_q)) { v_buf = pending_queue_pop(cap); fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index); v_buf->index = cap->buf_index; /* Move the buffer to the capture active queue */ active_queue_add(cap, v_buf); dbg("next frame: %d, done frame: %d", fimc_hw_get_frame_index(fimc), v_buf->index); if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) cap->buf_index = 0; } if (cap->active_buf_cnt == 0) { clear_bit(ST_CAPT_RUN, &fimc->state); if (++cap->buf_index >= FIMC_MAX_OUT_BUFS) cap->buf_index = 0; } else { set_bit(ST_CAPT_RUN, &fimc->state); } dbg("frame: %d, active_buf_cnt: %d", fimc_hw_get_frame_index(fimc), cap->active_buf_cnt); }
static void buffer_queue(struct vb2_buffer *vb) { struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_vid_buffer *buf = container_of(vb, struct fimc_vid_buffer, vb); struct fimc_vid_cap *vid_cap = &fimc->vid_cap; unsigned long flags; int min_bufs; spin_lock_irqsave(&fimc->slock, flags); fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr); if (!test_bit(ST_CAPT_STREAM, &fimc->state) && vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) { /* Setup the buffer directly for processing. */ int buf_id = (vid_cap->reqbufs_count == 1) ? -1 : vid_cap->buf_index; fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id); buf->index = vid_cap->buf_index; active_queue_add(vid_cap, buf); if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS) vid_cap->buf_index = 0; } else { fimc_pending_queue_add(vid_cap, buf); } min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1; if (vid_cap->active_buf_cnt >= min_bufs && !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) fimc_activate_capture(ctx); spin_unlock_irqrestore(&fimc->slock, flags); }