[8895] media: smfc: add cropping window
authorWon Jung <w00.jung@samsung.com>
Wed, 25 Nov 2015 08:04:05 +0000 (17:04 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:31:18 +0000 (14:31 +0900)
cropping window feature is added for encoding
and inefficient codes are removed

Change-Id: I975b57199124ed5c32b6030e2b4d9314fba9653f
Signed-off-by: Won Jung <w00.jung@samsung.com>
drivers/media/platform/exynos/smfc/smfc-regs.c
drivers/media/platform/exynos/smfc/smfc-regs.h
drivers/media/platform/exynos/smfc/smfc-v4l2-ioctls.c
drivers/media/platform/exynos/smfc/smfc.h

index 9ed95af186a3f9c71cbfa89ec6896711feaf7292..ff7a82a1ee64088dfa3c685f161ca8ba001e5c10 100644 (file)
@@ -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);
                /*
index e6db4a0b3b70daf57e932e4483a1c9fb16d0c9b2..6448d80377318897f36fcac1890caaf290ea519f 100644 (file)
 #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
index c7faeeed2522be5541763078eb7a8108246a89e7..0c4bc5b02ca0b6d68a1fb09cbc825f2c9462f2e8 100644 (file)
@@ -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,
index a0caee204ff0d1841165cbfcd80a63eff8735563..9b3ff8fa1df3b5d4f4fd7fd1c934b408205c04cd 100644 (file)
@@ -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 */