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; }
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; }
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; }
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; }