static void buffer_queue(struct vb2_buffer *vb) { struct flite_buffer *buf = container_of(vb, struct flite_buffer, vb); struct fimc_lite *fimc = vb2_get_drv_priv(vb->vb2_queue); unsigned long flags; spin_lock_irqsave(&fimc->slock, flags); buf->paddr = vb2_dma_contig_plane_dma_addr(vb, 0); if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) && !test_bit(ST_FLITE_STREAM, &fimc->state) && list_empty(&fimc->active_buf_q)) { flite_hw_set_output_addr(fimc, buf->paddr); fimc_lite_active_queue_add(fimc, buf); } else { fimc_lite_pending_queue_add(fimc, buf); } if (vb2_is_streaming(&fimc->vb_queue) && !list_empty(&fimc->pending_buf_q) && !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) { flite_hw_capture_start(fimc); spin_unlock_irqrestore(&fimc->slock, flags); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) fimc_pipeline_s_stream(&fimc->pipeline, 1); return; } spin_unlock_irqrestore(&fimc->slock, flags); }
static int start_streaming(struct vb2_queue *q, unsigned int count) { struct fimc_lite *fimc = q->drv_priv; int ret; fimc->frame_count = 0; ret = fimc_lite_hw_init(fimc); if (ret) { fimc_lite_reinit(fimc, false); return ret; } set_bit(ST_FLITE_PENDING, &fimc->state); if (!list_empty(&fimc->active_buf_q) && !test_and_set_bit(ST_FLITE_STREAM, &fimc->state)) { flite_hw_capture_start(fimc); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) fimc_pipeline_s_stream(&fimc->pipeline, 1); } if (debug > 0) flite_hw_dump_regs(fimc, __func__); return 0; }
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 fimc_vid_cap *vid_cap = &fimc->vid_cap; int min_bufs; int ret; vid_cap->frame_count = 0; ret = fimc_init_capture(fimc); if (ret) goto error; set_bit(ST_CAPT_PEND, &fimc->state); min_bufs = fimc->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); if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) fimc_pipeline_s_stream(fimc, 1); } return 0; error: fimc_capture_state_cleanup(fimc, false); return ret; }
static void buffer_queue(struct vb2_buffer *vb) { struct fimc_vid_buffer *buf = container_of(vb, struct fimc_vid_buffer, vb); struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct fimc_dev *fimc = ctx->fimc_dev; 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_SUSPENDED, &fimc->state) && !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; fimc_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 (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); spin_unlock_irqrestore(&fimc->slock, flags); if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) fimc_pipeline_s_stream(fimc, 1); return; } spin_unlock_irqrestore(&fimc->slock, flags); }
/* * Reinitialize the driver so it is ready to start the streaming again. * Set fimc->state to indicate stream off and the hardware shut down state. * If not suspending (@suspend is false), return any buffers to videobuf2. * Otherwise put any owned buffers onto the pending buffers queue, so they * can be re-spun when the device is being resumed. Also perform FIMC * software reset and disable streaming on the whole pipeline if required. */ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) { struct fimc_vid_cap *cap = &fimc->vid_cap; struct fimc_vid_buffer *buf; unsigned long flags; bool streaming; spin_lock_irqsave(&fimc->slock, flags); streaming = fimc->state & (1 << ST_CAPT_ISP_STREAM); fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM); if (suspend) fimc->state |= (1 << ST_CAPT_SUSPENDED); else fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED); /* Release unused buffers */ while (!suspend && !list_empty(&cap->pending_buf_q)) { buf = fimc_pending_queue_pop(cap); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } /* If suspending put unused buffers onto pending queue */ while (!list_empty(&cap->active_buf_q)) { buf = fimc_active_queue_pop(cap); if (suspend) fimc_pending_queue_add(cap, buf); else vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } fimc_hw_reset(fimc); cap->buf_index = 0; spin_unlock_irqrestore(&fimc->slock, flags); if (streaming) return fimc_pipeline_s_stream(&fimc->pipeline, 0); else return 0; }
/* * Reinitialize the driver so it is ready to start the streaming again. * Set fimc->state to indicate stream off and the hardware shut down state. * If not suspending (@suspend is false), return any buffers to videobuf2. * Otherwise put any owned buffers onto the pending buffers queue, so they * can be re-spun when the device is being resumed. Also perform FIMC * software reset and disable streaming on the whole pipeline if required. */ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) { struct flite_buffer *buf; unsigned long flags; bool streaming; spin_lock_irqsave(&fimc->slock, flags); streaming = fimc->state & (1 << ST_SENSOR_STREAM); fimc->state &= ~(1 << ST_FLITE_RUN | 1 << ST_FLITE_OFF | 1 << ST_FLITE_STREAM | 1 << ST_SENSOR_STREAM); if (suspend) fimc->state |= (1 << ST_FLITE_SUSPENDED); else fimc->state &= ~(1 << ST_FLITE_PENDING | 1 << ST_FLITE_SUSPENDED); /* Release unused buffers */ while (!suspend && !list_empty(&fimc->pending_buf_q)) { buf = fimc_lite_pending_queue_pop(fimc); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } /* If suspending put unused buffers onto pending queue */ while (!list_empty(&fimc->active_buf_q)) { buf = fimc_lite_active_queue_pop(fimc); if (suspend) fimc_lite_pending_queue_add(fimc, buf); else vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&fimc->slock, flags); flite_hw_reset(fimc); if (!streaming) return 0; return fimc_pipeline_s_stream(&fimc->pipeline, 0); }