static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
				 struct v4l2_format *f)
{
	struct fimc_ctx *ctx = fh_to_ctx(fh);
	struct fimc_dev *fimc = ctx->fimc_dev;
	struct vb2_queue *vq;
	struct fimc_frame *frame;
	struct v4l2_pix_format_mplane *pix;
	int i, ret = 0;

	ret = fimc_try_fmt_mplane(ctx, f);
	if (ret)
		return ret;

	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);

	if (vb2_is_busy(vq)) {
		v4l2_err(fimc->m2m.vfd, "queue (%d) busy\n", f->type);
		return -EBUSY;
	}

	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
		frame = &ctx->s_frame;
	else
		frame = &ctx->d_frame;

	pix = &f->fmt.pix_mp;
	frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
				      get_m2m_fmt_flags(f->type), 0);
	if (!frame->fmt)
		return -EINVAL;

	/* Update RGB Alpha control state and value range */
	fimc_alpha_ctrl_update(ctx);

	for (i = 0; i < frame->fmt->colplanes; i++) {
		frame->payload[i] =
			(pix->width * pix->height * frame->fmt->depth[i]) / 8;
	}

	fimc_fill_frame(frame, f);

	ctx->scaler.enabled = 1;

	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
		fimc_ctx_state_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
	else
		fimc_ctx_state_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx);

	dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height);

	return 0;
}
Beispiel #2
0
/* Complete the transaction which has been scheduled for execution. */
static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
{
	struct fimc_dev *fimc = ctx->fimc_dev;

	if (!fimc_m2m_pending(fimc))
		return;

	fimc_ctx_state_set(FIMC_CTX_SHUT, ctx);

	wait_event_timeout(fimc->irq_queue,
			!fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
			FIMC_SHUTDOWN_TIMEOUT);
}
Beispiel #3
0
/* Complete the transaction which has been scheduled for execution. */
static int fimc_m2m_shutdown(struct fimc_ctx *ctx)
{
    struct fimc_dev *fimc = ctx->fimc_dev;
    int ret;

    if (!fimc_m2m_pending(fimc))
        return 0;

    fimc_ctx_state_set(FIMC_CTX_SHUT, ctx);

    ret = wait_event_timeout(fimc->irq_queue,
                             !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
                             FIMC_SHUTDOWN_TIMEOUT);

    return ret == 0 ? -ETIMEDOUT : ret;
}
Beispiel #4
0
static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
{
	struct fimc_ctx *ctx = fh_to_ctx(fh);
	struct fimc_dev *fimc = ctx->fimc_dev;
	struct v4l2_crop cr = *crop;
	struct fimc_frame *f;
	int ret;

	ret = fimc_m2m_try_crop(ctx, &cr);
	if (ret)
		return ret;

	f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
		&ctx->s_frame : &ctx->d_frame;

	/* Check to see if scaling ratio is within supported range */
	if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
		if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
			ret = fimc_check_scaler_ratio(ctx, cr.c.width,
					cr.c.height, ctx->d_frame.width,
					ctx->d_frame.height, ctx->rotation);
		} else {
			ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
					ctx->s_frame.height, cr.c.width,
					cr.c.height, ctx->rotation);
		}
		if (ret) {
			v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
			return -EINVAL;
		}
	}

	f->offs_h = cr.c.left;
	f->offs_v = cr.c.top;
	f->width  = cr.c.width;
	f->height = cr.c.height;

	fimc_ctx_state_set(FIMC_PARAMS, ctx);

	return 0;
}