static int fimc_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct v4l2_rect rect = s->r; struct fimc_frame *f; unsigned long flags; unsigned int pad; if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; switch (s->target) { case V4L2_SEL_TGT_COMPOSE_DEFAULT: case V4L2_SEL_TGT_COMPOSE_BOUNDS: case V4L2_SEL_TGT_COMPOSE_ACTIVE: f = &ctx->d_frame; pad = FIMC_SD_PAD_SOURCE; break; case V4L2_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP_ACTIVE: f = &ctx->s_frame; pad = FIMC_SD_PAD_SINK; break; default: return -EINVAL; } fimc_capture_try_crop(ctx, &rect, pad); if (s->flags & V4L2_SEL_FLAG_LE && !enclosed_rectangle(&rect, &s->r)) return -ERANGE; if (s->flags & V4L2_SEL_FLAG_GE && !enclosed_rectangle(&s->r, &rect)) return -ERANGE; s->r = rect; spin_lock_irqsave(&fimc->slock, flags); set_frame_crop(f, s->r.left, s->r.top, s->r.width, s->r.height); spin_unlock_irqrestore(&fimc->slock, flags); set_bit(ST_CAPT_APPLY_CFG, &fimc->state); return 0; }
static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct fimc_frame *ff; unsigned long flags; fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK); ff = &ctx->s_frame; spin_lock_irqsave(&fimc->slock, flags); set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height); set_bit(ST_CAPT_APPLY_CFG, &fimc->state); spin_unlock_irqrestore(&fimc->slock, flags); return 0; }
static int fimc_cap_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct v4l2_rect rect = s->r; struct fimc_frame *f; unsigned long flags; if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; if (s->target == V4L2_SEL_TGT_COMPOSE) f = &ctx->d_frame; else if (s->target == V4L2_SEL_TGT_CROP) f = &ctx->s_frame; else return -EINVAL; fimc_capture_try_selection(ctx, &rect, s->target); if (s->flags & V4L2_SEL_FLAG_LE && !enclosed_rectangle(&rect, &s->r)) return -ERANGE; if (s->flags & V4L2_SEL_FLAG_GE && !enclosed_rectangle(&s->r, &rect)) return -ERANGE; s->r = rect; spin_lock_irqsave(&fimc->slock, flags); set_frame_crop(f, s->r.left, s->r.top, s->r.width, s->r.height); spin_unlock_irqrestore(&fimc->slock, flags); set_bit(ST_CAPT_APPLY_CFG, &fimc->state); 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; }