From: Won Jung Date: Wed, 25 Nov 2015 08:04:05 +0000 (+0900) Subject: [8895] media: smfc: add cropping window X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=b44a86dc427debc4be7f567eee369104308ab2f7;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [8895] media: smfc: add cropping window cropping window feature is added for encoding and inefficient codes are removed Change-Id: I975b57199124ed5c32b6030e2b4d9314fba9653f Signed-off-by: Won Jung --- diff --git a/drivers/media/platform/exynos/smfc/smfc-regs.c b/drivers/media/platform/exynos/smfc/smfc-regs.c index 9ed95af186a3..ff7a82a1ee64 100644 --- a/drivers/media/platform/exynos/smfc/smfc-regs.c +++ b/drivers/media/platform/exynos/smfc/smfc-regs.c @@ -370,16 +370,28 @@ void smfc_hwconfigure_image(struct smfc_ctx *ctx, struct vb2_v4l2_buffer *vb2buf_img, *vb2buf_jpg; u32 stream_address; u32 format = ctx->img_fmt->regcfg; + unsigned char num_plane = ctx->img_fmt->num_planes; u32 burstlen = 1 << ctx->smfc->devdata->burstlenth_bits; - - __raw_writel(ctx->width | (ctx->height << 16), - ctx->smfc->reg + REG_MAIN_IMAGE_SIZE); + unsigned int i; if (!(ctx->flags & SMFC_CTX_COMPRESS)) { + __raw_writel(ctx->width | (ctx->height << 16), + ctx->smfc->reg + REG_MAIN_IMAGE_SIZE); + vb2buf_img = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); vb2buf_jpg = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); format |= smfc_get_jpeg_format(hfactor, vfactor); } else { + __raw_writel(ctx->crop.width | (ctx->crop.height << 16), + ctx->smfc->reg + REG_MAIN_IMAGE_SIZE); + + for (i = 0; i < num_plane; i++) { + __raw_writel(ctx->crop.po[i], + ctx->smfc->reg + REG_MAIN_IMAGE_PO_PLANE(i)); + __raw_writel(ctx->crop.so[i], + ctx->smfc->reg + REG_MAIN_IMAGE_SO_PLANE(i)); + } + vb2buf_img = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); vb2buf_jpg = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); /* diff --git a/drivers/media/platform/exynos/smfc/smfc-regs.h b/drivers/media/platform/exynos/smfc/smfc-regs.h index e6db4a0b3b70..6448d8037731 100644 --- a/drivers/media/platform/exynos/smfc/smfc-regs.h +++ b/drivers/media/platform/exynos/smfc/smfc-regs.h @@ -51,6 +51,10 @@ #define REG_MAIN_IMAGE_SIZE 0x014 #define REG_MAIN_JPEG_BASE 0x010 #define REG_MAIN_IMAGE_BASE 0x018 +#define REG_MAIN_IMAGE_SO_PLANE1 0x01C +#define REG_MAIN_IMAGE_PO_PLANE1 0x020 +#define REG_MAIN_IMAGE_SO_PLANE(n) (REG_MAIN_IMAGE_SO_PLANE1 + (n) * 12) +#define REG_MAIN_IMAGE_PO_PLANE(n) (REG_MAIN_IMAGE_PO_PLANE1 + (n) * 12) #define REG_SEC_JPEG_CNTL 0x080 #define REG_SEC_JPEG_BASE 0x088 #define REG_SEC_IMAGE_BASE 0x090 diff --git a/drivers/media/platform/exynos/smfc/smfc-v4l2-ioctls.c b/drivers/media/platform/exynos/smfc/smfc-v4l2-ioctls.c index c7faeeed2522..0c4bc5b02ca0 100644 --- a/drivers/media/platform/exynos/smfc/smfc-v4l2-ioctls.c +++ b/drivers/media/platform/exynos/smfc/smfc-v4l2-ioctls.c @@ -604,6 +604,35 @@ static bool smfc_check_capable_of_decompression(const struct smfc_dev *smfc, return false; } +static int smfc_calc_crop(struct smfc_ctx *ctx, const struct v4l2_crop *cr) +{ + u32 left = cr->c.left; + u32 top = cr->c.top; + u32 frame_width = ctx->width; + u32 crop_width = cr->c.width; + unsigned char bpp_pix = ctx->img_fmt->bpp_pix[0]/8; + unsigned char chroma_hfactor = ctx->img_fmt->chroma_hfactor; + unsigned char chroma_vfactor = ctx->img_fmt->chroma_vfactor; + unsigned int i; + + ctx->crop.po[0] = (frame_width * top + left) * bpp_pix; + ctx->crop.so[0] = (frame_width - crop_width) * bpp_pix; + + for(i = 1; i < ctx->img_fmt->num_planes; i++) { + ctx->crop.po[i] = (frame_width * top / chroma_vfactor + left ) + * bpp_pix * 2 / chroma_hfactor / i; + ctx->crop.so[i] = (frame_width - crop_width) * bpp_pix + * 2 / chroma_hfactor / i; + + if(i == 2) { + ctx->crop.po[i-1] = ctx->crop.po[i]; + ctx->crop.so[i-1] = ctx->crop.so[i]; + } + } + + return 0; +} + static bool smfc_v4l2_init_fmt_mplane(const struct smfc_ctx *ctx, const struct smfc_image_format *smfc_fmt, __u32 type, struct v4l2_pix_format_mplane *pix_mp) @@ -720,10 +749,17 @@ static int smfc_v4l2_s_fmt_mplane(struct file *filp, void *fh, if (!smfc_v4l2_init_fmt_mplane(ctx, smfc_fmt, f->type, &f->fmt.pix_mp)) return -EINVAL; - ctx->width = SMFC_FMT_MAIN_SIZE(f->fmt.pix_mp.width); - ctx->height = SMFC_FMT_MAIN_SIZE(f->fmt.pix_mp.height); - ctx->thumb_width = SMFC_FMT_SEC_SIZE(f->fmt.pix_mp.width); - ctx->thumb_height = SMFC_FMT_SEC_SIZE(f->fmt.pix_mp.height); + if(!is_jpeg(smfc_fmt)) { + ctx->width = SMFC_FMT_MAIN_SIZE(f->fmt.pix_mp.width); + ctx->height = SMFC_FMT_MAIN_SIZE(f->fmt.pix_mp.height); + ctx->thumb_width = SMFC_FMT_SEC_SIZE(f->fmt.pix_mp.width); + ctx->thumb_height = SMFC_FMT_SEC_SIZE(f->fmt.pix_mp.height); + + memset(&ctx->crop, 0, sizeof(ctx->crop)); + + ctx->crop.width = ctx->width; + ctx->crop.height = ctx->height; + } if (ctx->thumb_width && ctx->thumb_height) { if (!smfc_is_capable(ctx->smfc, @@ -801,11 +837,18 @@ static int smfc_v4l2_s_fmt(struct file *filp, void *fh, struct v4l2_format *f) if (!smfc_v4l2_init_fmt(ctx, smfc_fmt, f->type, &f->fmt.pix)) return -EINVAL; - ctx->width = SMFC_FMT_MAIN_SIZE(f->fmt.pix.width); - ctx->height = SMFC_FMT_MAIN_SIZE(f->fmt.pix.height); - /* back-to-back compression is not supported with single plane */ - ctx->thumb_width = 0; - ctx->thumb_height = 0; + if(!is_jpeg(smfc_fmt)) { + ctx->width = SMFC_FMT_MAIN_SIZE(f->fmt.pix.width); + ctx->height = SMFC_FMT_MAIN_SIZE(f->fmt.pix.height); + /* back-to-back compression is not supported with single plane */ + ctx->thumb_width = 0; + ctx->thumb_height = 0; + + memset(&ctx->crop, 0, sizeof(ctx->crop)); + + ctx->crop.width = ctx->width; + ctx->crop.height = ctx->height; + } if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) ctx->img_fmt = smfc_fmt; @@ -813,6 +856,63 @@ static int smfc_v4l2_s_fmt(struct file *filp, void *fh, struct v4l2_format *f) return 0; } +static int smfc_v4l2_cropcap(struct file *file, void *fh, + struct v4l2_cropcap *cr) +{ + cr->bounds.left = 0; + cr->bounds.top = 0; + cr->bounds.width = SMFC_MAX_WIDTH; + cr->bounds.height = SMFC_MAX_HEIGHT; + cr->defrect = cr->bounds; + + return 0; +} + +static int smfc_v4l2_s_crop(struct file *file, void *fh, + const struct v4l2_crop *cr) +{ + struct smfc_ctx *ctx = v4l2_fh_to_smfc_ctx(fh); + unsigned int i; + int ret = 0; + + if ((cr->c.left < 0) || (cr->c.top < 0) || + (cr->c.width < 16) || (cr->c.height < 16)) { + v4l2_err(&ctx->smfc->v4l2_dev, + "Invalid crop region (%d,%d):%dx%d\n", + cr->c.left, cr->c.top, cr->c.width, cr->c.height); + + return -EINVAL; + } + + if (((cr->c.left + cr->c.width) > ctx->width) || + ((cr->c.top + cr->c.height) > ctx->height)) { + v4l2_err(&ctx->smfc->v4l2_dev, + "Crop (%d,%d):%dx%d overflows the image %dx%d\n", + cr->c.left, cr->c.top, cr->c.width, cr->c.height, + ctx->width, ctx->height); + return -EINVAL; + } + + if(!V4L2_TYPE_IS_OUTPUT(cr->type)) { + v4l2_err(&ctx->smfc->v4l2_dev, + "Cropping on the capture buffer is not supported\n"); + return -EINVAL; + } + + ctx->crop.width = cr->c.width; + ctx->crop.height = cr->c.height; + + for (i = 0 ; i < SMFC_MAX_NUM_COMP; i++) { + ctx->crop.po[i] = 0; + ctx->crop.so[i] = 0; + } + + if (!!smfc_calc_crop(ctx, cr)) + return -EINVAL; + + return ret; +} + const struct v4l2_ioctl_ops smfc_v4l2_ioctl_ops = { .vidioc_querycap = smfc_v4l2_querycap, .vidioc_enum_fmt_vid_cap = smfc_v4l2_enum_fmt, @@ -831,6 +931,8 @@ const struct v4l2_ioctl_ops smfc_v4l2_ioctl_ops = { .vidioc_s_fmt_vid_out = smfc_v4l2_s_fmt, .vidioc_s_fmt_vid_cap_mplane = smfc_v4l2_s_fmt_mplane, .vidioc_s_fmt_vid_out_mplane = smfc_v4l2_s_fmt_mplane, + .vidioc_cropcap = smfc_v4l2_cropcap, + .vidioc_s_crop = smfc_v4l2_s_crop, .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, diff --git a/drivers/media/platform/exynos/smfc/smfc.h b/drivers/media/platform/exynos/smfc/smfc.h index a0caee204ff0..9b3ff8fa1df3 100644 --- a/drivers/media/platform/exynos/smfc/smfc.h +++ b/drivers/media/platform/exynos/smfc/smfc.h @@ -151,6 +151,13 @@ struct smfc_decomp_qtable { char compsel[SMFC_MAX_QTBL_COUNT]; }; +struct smfc_crop { + u32 width; + u32 height; + u32 po[SMFC_MAX_NUM_COMP]; + u32 so[SMFC_MAX_NUM_COMP]; +}; + struct smfc_ctx { struct v4l2_fh fh; struct v4l2_ctrl_handler v4l2_ctrlhdlr; @@ -162,6 +169,9 @@ struct smfc_ctx { __u32 width; __u32 height; + /* cropping size settings */ + struct smfc_crop crop; + /* Compression settings */ unsigned char chroma_hfactor; /* horizontal chroma subsampling factor */ unsigned char chroma_vfactor; /* vertical chroma subsampling factor */