예제 #1
0
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;
}
예제 #2
0
static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
                                    struct v4l2_fmtdesc *f)
{
    struct fimc_fmt *fmt;

    fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type),
                           f->index);
    if (!fmt)
        return -EINVAL;

    strncpy(f->description, fmt->name, sizeof(f->description) - 1);
    f->pixelformat = fmt->fourcc;
    return 0;
}
예제 #3
0
static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
{
	struct fimc_dev *fimc = ctx->fimc_dev;
	struct fimc_variant *variant = fimc->variant;
	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
	struct fimc_fmt *fmt;
	u32 max_w, mod_x, mod_y;

	if (!IS_M2M(f->type))
		return -EINVAL;

	dbg("w: %d, h: %d", pix->width, pix->height);

	fmt = fimc_find_format(&pix->pixelformat, NULL,
			       get_m2m_fmt_flags(f->type), 0);
	if (WARN(fmt == NULL, "Pixel format lookup failed"))
		return -EINVAL;

	if (pix->field == V4L2_FIELD_ANY)
		pix->field = V4L2_FIELD_NONE;
	else if (pix->field != V4L2_FIELD_NONE)
		return -EINVAL;

	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		max_w = variant->pix_limit->scaler_dis_w;
		mod_x = ffs(variant->min_inp_pixsize) - 1;
	} else {
		max_w = variant->pix_limit->out_rot_dis_w;
		mod_x = ffs(variant->min_out_pixsize) - 1;
	}

	if (tiled_fmt(fmt)) {
		mod_x = 6; /* 64 x 32 pixels tile */
		mod_y = 5;
	} else {
		if (variant->min_vsize_align == 1)
			mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
		else
			mod_y = ffs(variant->min_vsize_align) - 1;
	}

	v4l_bound_align_image(&pix->width, 16, max_w, mod_x,
		&pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);

	fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp);
	return 0;
}
예제 #4
0
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 fimc_fmt *fmt;
    struct vb2_queue *vq;
    struct fimc_frame *frame;
    int ret;

    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;

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

    __set_frame_format(frame, fmt, &f->fmt.pix_mp);

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

    return 0;
}