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; }
/* 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); }
/* 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; }
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; }