static int gsc_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct gsc_ctx *ctx = fh_to_ctx(fh); struct gsc_dev *gsc = ctx->gsc_dev; struct exynos_platform_gscaler *pdata = gsc->pdata; /* The source and target color format need to be set */ if (V4L2_TYPE_IS_OUTPUT(type)) { if (!gsc_ctx_state_is_set(GSC_SRC_FMT, ctx)) return -EINVAL; } else if (!gsc_ctx_state_is_set(GSC_DST_FMT, ctx)) { return -EINVAL; } gsc_pm_qos_ctrl(gsc, GSC_QOS_ON, pdata->mif_min, pdata->int_min); if (gsc->protected_content) { int id = gsc->id + 3; exynos_smc(SMC_PROTECTION_SET, 0, id, 1); gsc_dbg("DRM enable"); } return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); }
static int gsc_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct gsc_ctx *ctx = fh_to_ctx(fh); /* The source and target color format need to be set */ if (V4L2_TYPE_IS_OUTPUT(type)) { if (!gsc_ctx_state_is_set(GSC_SRC_FMT, ctx)) return -EINVAL; } else if (!gsc_ctx_state_is_set(GSC_DST_FMT, ctx)) { return -EINVAL; } return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); }
static int gsc_m2m_streamon(struct file *file, void *fh, enum v4l2_buf_type type) { struct gsc_ctx *ctx = fh_to_ctx(fh); struct gsc_dev *gsc = ctx->gsc_dev; struct exynos_platform_gscaler *pdata = gsc->pdata; /* The source and target color format need to be set */ if (V4L2_TYPE_IS_OUTPUT(type)) { if (!gsc_ctx_state_is_set(GSC_SRC_FMT, ctx)) return -EINVAL; } else if (!gsc_ctx_state_is_set(GSC_DST_FMT, ctx)) { return -EINVAL; } gsc_pm_qos_ctrl(gsc, GSC_QOS_ON, pdata->mif_min, pdata->int_min); return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); }
static int gsc_m2m_ctx_stop_req(struct gsc_ctx *ctx) { struct gsc_ctx *curr_ctx; struct gsc_dev *gsc = ctx->gsc_dev; int ret; curr_ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); if (!gsc_m2m_pending(gsc) || (curr_ctx != ctx)) return 0; gsc_ctx_state_lock_set(GSC_CTX_STOP_REQ, ctx); ret = wait_event_timeout(gsc->irq_queue, !gsc_ctx_state_is_set(GSC_CTX_STOP_REQ, ctx), GSC_SHUTDOWN_TIMEOUT); return ret == 0 ? -ETIMEDOUT : ret; }
static int gsc_ctx_stop_req(struct gsc_ctx *ctx) { struct gsc_ctx *curr_ctx; struct gsc_dev *gsc = ctx->gsc_dev; int ret = 0; curr_ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); if (!gsc_m2m_run(gsc) || (curr_ctx != ctx)) return 0; ctx->state |= GSC_CTX_STOP_REQ; ret = wait_event_timeout(gsc->irq_queue, !gsc_ctx_state_is_set(GSC_CTX_STOP_REQ, ctx), GSC_SHUTDOWN_TIMEOUT); if (!ret) ret = -EBUSY; return ret; }
static int gsc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) { struct gsc_ctx *ctx = fh_to_ctx(fh); struct gsc_variant *variant = ctx->gsc_dev->variant; struct gsc_frame *f; int ret; ret = gsc_try_crop(ctx, cr); if (ret) return ret; f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? &ctx->s_frame : &ctx->d_frame; /* Default is input rotator */ ctx->scaler.is_scaled_down = false; /* Check to see if scaling ratio is within supported range */ if (gsc_ctx_state_is_set(GSC_DST_FMT | GSC_SRC_FMT, ctx)) { if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ret = gsc_check_scaler_ratio(ctx, variant, cr->c.width, cr->c.height, ctx->d_frame.crop.width,ctx->d_frame.crop.height, ctx->gsc_ctrls.rotate->val, ctx->out_path); } else { ret = gsc_check_scaler_ratio(ctx, variant, ctx->s_frame.crop.width, ctx->s_frame.crop.height, cr->c.width, cr->c.height, ctx->gsc_ctrls.rotate->val, ctx->out_path); } if (ret) { gsc_err("Out of scaler range"); return -EINVAL; } } f->crop.left = cr->c.left; f->crop.top = cr->c.top; f->crop.width = cr->c.width; f->crop.height = cr->c.height; gsc_ctx_state_lock_set(GSC_PARAMS, ctx); return 0; }
static int gsc_ctx_stop_req(struct gsc_ctx *ctx) { struct gsc_ctx *curr_ctx; struct gsc_dev *gsc = ctx->gsc_dev; int ret = 0; unsigned long flags; curr_ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev); if (!gsc_m2m_run(gsc) || (curr_ctx != ctx)) return 0; spin_lock_irqsave(&ctx->slock, flags); ctx->state |= GSC_CTX_STOP_REQ; spin_unlock_irqrestore(&ctx->slock, flags); ret = wait_event_timeout(gsc->irq_queue, !gsc_ctx_state_is_set(GSC_CTX_STOP_REQ, ctx), GSC_SHUTDOWN_TIMEOUT); if (!ret) ret = -EBUSY; return ret; }
static int gsc_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s) { struct gsc_frame *frame; struct gsc_ctx *ctx = fh_to_ctx(fh); struct gsc_variant *variant = ctx->gsc_dev->variant; struct v4l2_selection sel = *s; int ret; if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)) return -EINVAL; ret = gsc_try_selection(ctx, &sel); if (ret) return ret; if (s->flags & V4L2_SEL_FLAG_LE && !is_rectangle_enclosed(&sel.r, &s->r)) return -ERANGE; if (s->flags & V4L2_SEL_FLAG_GE && !is_rectangle_enclosed(&s->r, &sel.r)) return -ERANGE; s->r = sel.r; switch (s->target) { case V4L2_SEL_TGT_COMPOSE_BOUNDS: case V4L2_SEL_TGT_COMPOSE_DEFAULT: case V4L2_SEL_TGT_COMPOSE: frame = &ctx->s_frame; break; case V4L2_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP: case V4L2_SEL_TGT_CROP_DEFAULT: frame = &ctx->d_frame; break; default: return -EINVAL; } /* Check to see if scaling ratio is within supported range */ if (gsc_ctx_state_is_set(GSC_DST_FMT | GSC_SRC_FMT, ctx)) { if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ret = gsc_check_scaler_ratio(variant, sel.r.width, sel.r.height, ctx->d_frame.crop.width, ctx->d_frame.crop.height, ctx->gsc_ctrls.rotate->val, ctx->out_path); } else { ret = gsc_check_scaler_ratio(variant, ctx->s_frame.crop.width, ctx->s_frame.crop.height, sel.r.width, sel.r.height, ctx->gsc_ctrls.rotate->val, ctx->out_path); } if (ret) { pr_err("Out of scaler range"); return -EINVAL; } } frame->crop = sel.r; gsc_ctx_state_lock_set(GSC_PARAMS, ctx); return 0; }