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; fimc_hw_reset(fimc); 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 int start_streaming(struct vb2_queue *q) { struct fimc_ctx *ctx = q->drv_priv; struct fimc_dev *fimc = ctx->fimc_dev; struct s5p_fimc_isp_info *isp_info; int ret; fimc_hw_reset(fimc); ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1); if (ret && ret != -ENOIOCTLCMD) return ret; ret = fimc_prepare_config(ctx, ctx->state); if (ret) return ret; isp_info = &fimc->pdata->isp_info[fimc->vid_cap.input_index]; fimc_hw_set_camera_type(fimc, isp_info); fimc_hw_set_camera_source(fimc, isp_info); fimc_hw_set_camera_offset(fimc, &ctx->s_frame); if (ctx->state & FIMC_PARAMS) { ret = fimc_set_scaler_info(ctx); if (ret) { err("Scaler setup error"); return ret; } fimc_hw_set_input_path(ctx); fimc_hw_set_prescaler(ctx); fimc_hw_set_mainscaler(ctx); fimc_hw_set_target_format(ctx); fimc_hw_set_rotation(ctx); fimc_hw_set_effect(ctx); } fimc_hw_set_output_path(ctx); fimc_hw_set_out_dma(ctx); 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); 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_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_call(fimc, set_stream, &fimc->pipeline, 0); else return 0; }