Exemple #1
0
/**
 * fimc_capture_config_update - apply the camera interface configuration
 *
 * To be called from within the interrupt handler with fimc.slock
 * spinlock held. It updates the camera pixel crop, rotation and
 * image flip in H/W.
 */
int fimc_capture_config_update(struct fimc_ctx *ctx)
{
	struct fimc_dev *fimc = ctx->fimc_dev;
	int ret;

	if (!test_bit(ST_CAPT_APPLY_CFG, &fimc->state))
		return 0;

	spin_lock(&ctx->slock);
	fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
	ret = fimc_set_scaler_info(ctx);
	if (ret == 0) {
		fimc_hw_set_prescaler(ctx);
		fimc_hw_set_mainscaler(ctx);
		fimc_hw_set_target_format(ctx);
		fimc_hw_set_rotation(ctx);
		fimc_prepare_dma_offset(ctx, &ctx->d_frame);
		fimc_hw_set_out_dma(ctx);
		if (fimc->variant->has_alpha)
			fimc_hw_set_rgb_alpha(ctx);
		clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
	}
	spin_unlock(&ctx->slock);
	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;
}
Exemple #3
0
static int fimc_capture_hw_init(struct fimc_dev *fimc)
{
	struct fimc_ctx *ctx = fimc->vid_cap.ctx;
	struct fimc_pipeline *p = &fimc->pipeline;
	struct fimc_sensor_info *sensor;
	unsigned long flags;
	int ret = 0;

	if (p->subdevs[IDX_SENSOR] == NULL || ctx == NULL)
		return -ENXIO;
	if (ctx->s_frame.fmt == NULL)
		return -EINVAL;

	sensor = v4l2_get_subdev_hostdata(p->subdevs[IDX_SENSOR]);

	spin_lock_irqsave(&fimc->slock, flags);
	fimc_prepare_dma_offset(ctx, &ctx->d_frame);
	fimc_set_yuv_order(ctx);

	fimc_hw_set_camera_polarity(fimc, &sensor->pdata);
	fimc_hw_set_camera_type(fimc, &sensor->pdata);
	fimc_hw_set_camera_source(fimc, &sensor->pdata);
	fimc_hw_set_camera_offset(fimc, &ctx->s_frame);

	ret = fimc_set_scaler_info(ctx);
	if (!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);
		if (fimc->variant->has_alpha)
			fimc_hw_set_rgb_alpha(ctx);
		clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
	}
	spin_unlock_irqrestore(&fimc->slock, flags);
	return ret;
}
Exemple #4
0
static void fimc_device_run(void *priv)
{
    struct vb2_buffer *src_vb, *dst_vb;
    struct fimc_ctx *ctx = priv;
    struct fimc_frame *sf, *df;
    struct fimc_dev *fimc;
    unsigned long flags;
    int ret;

    if (WARN(!ctx, "Null context\n"))
        return;

    fimc = ctx->fimc_dev;
    spin_lock_irqsave(&fimc->slock, flags);

    set_bit(ST_M2M_PEND, &fimc->state);
    sf = &ctx->s_frame;
    df = &ctx->d_frame;

    if (ctx->state & FIMC_PARAMS) {
        /* Prepare the DMA offsets for scaler */
        fimc_prepare_dma_offset(ctx, sf);
        fimc_prepare_dma_offset(ctx, df);
    }

    src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
    ret = fimc_prepare_addr(ctx, src_vb, sf, &sf->paddr);
    if (ret)
        goto dma_unlock;

    dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
    ret = fimc_prepare_addr(ctx, dst_vb, df, &df->paddr);
    if (ret)
        goto dma_unlock;

    dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;

    /* Reconfigure hardware if the context has changed. */
    if (fimc->m2m.ctx != ctx) {
        ctx->state |= FIMC_PARAMS;
        fimc->m2m.ctx = ctx;
    }

    if (ctx->state & FIMC_PARAMS) {
        fimc_set_yuv_order(ctx);
        fimc_hw_set_input_path(ctx);
        fimc_hw_set_in_dma(ctx);
        ret = fimc_set_scaler_info(ctx);
        if (ret)
            goto dma_unlock;
        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_out_dma(ctx);
        if (fimc->drv_data->alpha_color)
            fimc_hw_set_rgb_alpha(ctx);
        fimc_hw_set_output_path(ctx);
    }
    fimc_hw_set_input_addr(fimc, &sf->paddr);
    fimc_hw_set_output_addr(fimc, &df->paddr, -1);

    fimc_activate_capture(ctx);
    ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP);
    fimc_hw_activate_input_dma(fimc, true);

dma_unlock:
    spin_unlock_irqrestore(&fimc->slock, flags);
}
Exemple #5
0
static int fimc_cap_streamon(struct file *file, void *priv,
			   enum v4l2_buf_type type)
{
	struct s3c_fimc_isp_info *isp_info;
	struct fimc_ctx *ctx = priv;
	struct fimc_dev *fimc = ctx->fimc_dev;
	int ret = -EBUSY;

	if (mutex_lock_interruptible(&fimc->lock))
		return -ERESTARTSYS;

	if (fimc_capture_active(fimc) || !fimc->vid_cap.sd)
		goto s_unlock;

	if (!(ctx->state & FIMC_DST_FMT)) {
		v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n");
		ret = -EINVAL;
		goto s_unlock;
	}

	ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
	if (ret && ret != -ENOIOCTLCMD)
		goto s_unlock;

	ret = fimc_prepare_config(ctx, ctx->state);
	if (ret)
		goto s_unlock;

	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");
			goto s_unlock;
		}
		fimc_hw_set_input_path(ctx);
		fimc_hw_set_scaler(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;

	set_bit(ST_CAPT_PEND, &fimc->state);
	ret = videobuf_streamon(&fimc->vid_cap.vbq);

s_unlock:
	mutex_unlock(&fimc->lock);
	return ret;
}