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_cap_try_fmt_mplane(struct file *file, void *fh, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct v4l2_mbus_framefmt mf; struct fimc_fmt *ffmt = NULL; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SINK); ctx->s_frame.f_width = pix->width; ctx->s_frame.f_height = pix->height; } ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SOURCE); if (!ffmt) return -EINVAL; if (!fimc->vid_cap.user_subdev_api) { mf.width = pix->width; mf.height = pix->height; mf.code = ffmt->mbus_code; fimc_md_graph_lock(fimc); fimc_pipeline_try_format(ctx, &mf, &ffmt, false); fimc_md_graph_unlock(fimc); pix->width = mf.width; pix->height = mf.height; if (ffmt) pix->pixelformat = ffmt->fourcc; } fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); return 0; }
static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) { struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.mf; struct fimc_frame *ff = &ctx->d_frame; struct fimc_fmt *s_fmt = NULL; int ret, i; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; if (vb2_is_busy(&fimc->vid_cap.vbq)) return -EBUSY; /* Pre-configure format at camera interface input, for JPEG only */ if (pix->pixelformat == V4L2_PIX_FMT_JPEG) { fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SINK); ctx->s_frame.f_width = pix->width; ctx->s_frame.f_height = pix->height; } /* Try the format at the scaler and the DMA output */ ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SOURCE); if (!ff->fmt) return -EINVAL; /* Update RGB Alpha control state and value range */ fimc_alpha_ctrl_update(ctx); /* Try to match format at the host and the sensor */ if (!fimc->vid_cap.user_subdev_api) { mf->code = ff->fmt->mbus_code; mf->width = pix->width; mf->height = pix->height; fimc_md_graph_lock(fimc); ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true); fimc_md_graph_unlock(fimc); if (ret) return ret; pix->width = mf->width; pix->height = mf->height; } fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); for (i = 0; i < ff->fmt->colplanes; i++) ff->payload[i] = (pix->width * pix->height * ff->fmt->depth[i]) / 8; set_frame_bounds(ff, pix->width, pix->height); /* Reset the composition rectangle if not yet configured */ if (!(ctx->state & FIMC_DST_CROP)) set_frame_crop(ff, 0, 0, pix->width, pix->height); fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color)); /* Reset cropping and set format at the camera interface input */ if (!fimc->vid_cap.user_subdev_api) { ctx->s_frame.fmt = s_fmt; set_frame_bounds(&ctx->s_frame, pix->width, pix->height); set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height); } return ret; }