void gsc_check_src_scale_info(struct gsc_variant *var, struct gsc_frame *s_frame, u32 *wratio, u32 tx, u32 ty, u32 *hratio) { int remainder = 0, walign, halign; if (is_yuv420(s_frame->fmt->color)) { walign = GSC_SC_ALIGN_4; halign = GSC_SC_ALIGN_4; } else if (is_yuv422(s_frame->fmt->color)) { walign = GSC_SC_ALIGN_4; halign = GSC_SC_ALIGN_2; } else { walign = GSC_SC_ALIGN_2; halign = GSC_SC_ALIGN_2; } remainder = s_frame->crop.width % (*wratio * walign); if (remainder) { s_frame->crop.width -= remainder; gsc_cal_prescaler_ratio(var, s_frame->crop.width, tx, wratio); pr_info("cropped src width size is recalculated from %d to %d", s_frame->crop.width + remainder, s_frame->crop.width); } remainder = s_frame->crop.height % (*hratio * halign); if (remainder) { s_frame->crop.height -= remainder; gsc_cal_prescaler_ratio(var, s_frame->crop.height, ty, hratio); pr_info("cropped src height size is recalculated from %d to %d", s_frame->crop.height + remainder, s_frame->crop.height); } }
int gsc_try_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr) { struct gsc_frame *f; struct gsc_dev *gsc = ctx->gsc_dev; struct gsc_variant *variant = gsc->variant; u32 mod_x = 0, mod_y = 0, tmp_w, tmp_h; u32 min_w, min_h, max_w, max_h; if (cr->c.top < 0 || cr->c.left < 0) { pr_err("doesn't support negative values for top & left\n"); return -EINVAL; } pr_debug("user put w: %d, h: %d", cr->c.width, cr->c.height); if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) f = &ctx->d_frame; else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) f = &ctx->s_frame; else return -EINVAL; max_w = f->f_width; max_h = f->f_height; tmp_w = cr->c.width; tmp_h = cr->c.height; if (V4L2_TYPE_IS_OUTPUT(cr->type)) { if ((is_yuv422(f->fmt->color) && f->fmt->num_comp == 1) || is_rgb(f->fmt->color)) min_w = 32; else min_w = 64; if ((is_yuv422(f->fmt->color) && f->fmt->num_comp == 3) || is_yuv420(f->fmt->color)) min_h = 32; else min_h = 16; } else { if (is_yuv420(f->fmt->color) || is_yuv422(f->fmt->color)) mod_x = ffs(variant->pix_align->target_w) - 1; if (is_yuv420(f->fmt->color)) mod_y = ffs(variant->pix_align->target_h) - 1; if (ctx->gsc_ctrls.rotate->val == 90 || ctx->gsc_ctrls.rotate->val == 270) { max_w = f->f_height; max_h = f->f_width; min_w = variant->pix_min->target_rot_en_w; min_h = variant->pix_min->target_rot_en_h; tmp_w = cr->c.height; tmp_h = cr->c.width; } else { min_w = variant->pix_min->target_rot_dis_w; min_h = variant->pix_min->target_rot_dis_h; } } pr_debug("mod_x: %d, mod_y: %d, min_w: %d, min_h = %d", mod_x, mod_y, min_w, min_h); pr_debug("tmp_w : %d, tmp_h : %d", tmp_w, tmp_h); v4l_bound_align_image(&tmp_w, min_w, max_w, mod_x, &tmp_h, min_h, max_h, mod_y, 0); if (!V4L2_TYPE_IS_OUTPUT(cr->type) && (ctx->gsc_ctrls.rotate->val == 90 || ctx->gsc_ctrls.rotate->val == 270)) gsc_check_crop_change(tmp_h, tmp_w, &cr->c.width, &cr->c.height); else gsc_check_crop_change(tmp_w, tmp_h, &cr->c.width, &cr->c.height); /* adjust left/top if cropping rectangle is out of bounds */ /* Need to add code to algin left value with 2's multiple */ if (cr->c.left + tmp_w > max_w) cr->c.left = max_w - tmp_w; if (cr->c.top + tmp_h > max_h) cr->c.top = max_h - tmp_h; if ((is_yuv420(f->fmt->color) || is_yuv422(f->fmt->color)) && cr->c.left & 1) cr->c.left -= 1; pr_debug("Aligned l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d", cr->c.left, cr->c.top, cr->c.width, cr->c.height, max_w, max_h); return 0; }
int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) { struct gsc_dev *gsc = ctx->gsc_dev; struct gsc_variant *variant = gsc->variant; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; const struct gsc_fmt *fmt; u32 max_w, max_h, mod_x, mod_y; u32 min_w, min_h, tmp_w, tmp_h; int i; pr_debug("user put w: %d, h: %d", pix_mp->width, pix_mp->height); fmt = find_fmt(&pix_mp->pixelformat, NULL, 0); if (!fmt) { pr_err("pixelformat format (0x%X) invalid\n", pix_mp->pixelformat); return -EINVAL; } if (pix_mp->field == V4L2_FIELD_ANY) pix_mp->field = V4L2_FIELD_NONE; else if (pix_mp->field != V4L2_FIELD_NONE) { pr_debug("Not supported field order(%d)\n", pix_mp->field); return -EINVAL; } max_w = variant->pix_max->target_rot_dis_w; max_h = variant->pix_max->target_rot_dis_h; mod_x = ffs(variant->pix_align->org_w) - 1; if (is_yuv420(fmt->color)) mod_y = ffs(variant->pix_align->org_h) - 1; else mod_y = ffs(variant->pix_align->org_h) - 2; if (V4L2_TYPE_IS_OUTPUT(f->type)) { min_w = variant->pix_min->org_w; min_h = variant->pix_min->org_h; } else { min_w = variant->pix_min->target_rot_dis_w; min_h = variant->pix_min->target_rot_dis_h; pix_mp->colorspace = ctx->out_colorspace; } pr_debug("mod_x: %d, mod_y: %d, max_w: %d, max_h = %d", mod_x, mod_y, max_w, max_h); /* To check if image size is modified to adjust parameter against hardware abilities */ tmp_w = pix_mp->width; tmp_h = pix_mp->height; v4l_bound_align_image(&pix_mp->width, min_w, max_w, mod_x, &pix_mp->height, min_h, max_h, mod_y, 0); if (tmp_w != pix_mp->width || tmp_h != pix_mp->height) pr_debug("Image size has been modified from %dx%d to %dx%d\n", tmp_w, tmp_h, pix_mp->width, pix_mp->height); pix_mp->num_planes = fmt->num_planes; if (V4L2_TYPE_IS_OUTPUT(f->type)) ctx->out_colorspace = pix_mp->colorspace; for (i = 0; i < pix_mp->num_planes; ++i) { struct v4l2_plane_pix_format *plane_fmt = &pix_mp->plane_fmt[i]; u32 bpl = plane_fmt->bytesperline; if (fmt->num_comp == 1 && /* Packed */ (bpl == 0 || (bpl * 8 / fmt->depth[i]) < pix_mp->width)) bpl = pix_mp->width * fmt->depth[i] / 8; if (fmt->num_comp > 1 && /* Planar */ (bpl == 0 || bpl < pix_mp->width)) bpl = pix_mp->width; if (i != 0 && fmt->num_comp == 3) bpl /= 2; plane_fmt->bytesperline = bpl; plane_fmt->sizeimage = max(pix_mp->width * pix_mp->height * fmt->depth[i] / 8, plane_fmt->sizeimage); pr_debug("[%d]: bpl: %d, sizeimage: %d", i, bpl, pix_mp->plane_fmt[i].sizeimage); } return 0; }
int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) { struct gsc_dev *gsc = ctx->gsc_dev; struct gsc_variant *variant = gsc->variant; struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; struct gsc_fmt *fmt; u32 max_w, max_h, mod_x, mod_y; u32 min_w, min_h, tmp_w, tmp_h; int i; gsc_dbg("user put w: %d, h: %d", pix_mp->width, pix_mp->height); fmt = find_fmt(&pix_mp->pixelformat, NULL, 0); if (!fmt) { gsc_err("pixelformat format (0x%X) invalid\n", pix_mp->pixelformat); return -EINVAL; } if (pix_mp->field == V4L2_FIELD_ANY) pix_mp->field = V4L2_FIELD_NONE; else if (pix_mp->field != V4L2_FIELD_NONE) { gsc_err("Not supported field order(%d)\n", pix_mp->field); return -EINVAL; } max_w = variant->pix_max->target_rot_dis_w; max_h = variant->pix_max->target_rot_dis_h; if (V4L2_TYPE_IS_OUTPUT(f->type)) { mod_x = ffs(variant->pix_align->org_w) - 1; if (is_yuv420(fmt->color)) mod_y = ffs(variant->pix_align->org_h) - 1; else mod_y = ffs(variant->pix_align->org_h) - 2; min_w = variant->pix_min->org_w; min_h = variant->pix_min->org_h; } else { mod_x = ffs(variant->pix_align->org_w) - 1; if (is_yuv420(fmt->color)) mod_y = ffs(variant->pix_align->org_h) - 1; else mod_y = ffs(variant->pix_align->org_h) - 2; min_w = variant->pix_min->target_rot_dis_w; min_h = variant->pix_min->target_rot_dis_h; } gsc_dbg("mod_x: %d, mod_y: %d, max_w: %d, max_h = %d", mod_x, mod_y, max_w, max_h); /* To check if image size is modified to adjust parameter against hardware abilities */ tmp_w = pix_mp->width; tmp_h = pix_mp->height; v4l_bound_align_image(&pix_mp->width, min_w, max_w, mod_x, &pix_mp->height, min_h, max_h, mod_y, 0); if (tmp_w != pix_mp->width || tmp_h != pix_mp->height) gsc_info("Image size has been modified from %dx%d to %dx%d", tmp_w, tmp_h, pix_mp->width, pix_mp->height); pix_mp->num_planes = fmt->num_planes; if (ctx->gsc_ctrls.csc_eq_mode->val) ctx->gsc_ctrls.csc_eq->val = (pix_mp->width >= 1280) ? 1 : 0; if (ctx->gsc_ctrls.csc_eq->val) /* HD */ pix_mp->colorspace = V4L2_COLORSPACE_REC709; else /* SD */ pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M; for (i = 0; i < pix_mp->num_planes; ++i) { int bpl = (pix_mp->width * fmt->depth[i]) >> 3; pix_mp->plane_fmt[i].bytesperline = bpl; pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height; gsc_dbg("[%d]: bpl: %d, sizeimage: %d", i, bpl, pix_mp->plane_fmt[i].sizeimage); } return 0; }