diff mbox

[3/4] gsc-m2m: report correct format bytesperline and sizeimage

Message ID 1394578325-11298-4-git-send-email-sheu@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

John Sheu March 11, 2014, 10:52 p.m. UTC
Explicitly specify sampling period for subsampled chroma formats, so
stride and image size are properly reported through VIDIOC_{S,G}_FMT.

Signed-off-by: John Sheu <sheu@google.com>
---
 drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++------------
 drivers/media/platform/exynos-gsc/gsc-core.h |  16 +--
 drivers/media/platform/exynos-gsc/gsc-regs.c |  40 +++----
 drivers/media/platform/exynos-gsc/gsc-regs.h |   4 +-
 4 files changed, 116 insertions(+), 98 deletions(-)

Comments

Kamil Debski April 7, 2014, 3:29 p.m. UTC | #1
Hi Shaik, Sungchun,

Exynos-gsc has no maintainers mentioned in the MAINTAINERS file.
I see your activity in the development of this driver. Do you have
any comments on this patch?

Best wishes,
Shaik Ameer Basha April 8, 2014, 6:56 a.m. UTC | #2
Hi John Sheu,

Thanks for the patch.
Please find the review comments inline.

On Wed, Mar 12, 2014 at 4:22 AM, John Sheu <sheu@google.com> wrote:
> Explicitly specify sampling period for subsampled chroma formats, so
> stride and image size are properly reported through VIDIOC_{S,G}_FMT.
>
> Signed-off-by: John Sheu <sheu@google.com>
> ---
>  drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++------------
>  drivers/media/platform/exynos-gsc/gsc-core.h |  16 +--
>  drivers/media/platform/exynos-gsc/gsc-regs.c |  40 +++----
>  drivers/media/platform/exynos-gsc/gsc-regs.h |   4 +-
>  4 files changed, 116 insertions(+), 98 deletions(-)
>
> diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
> index 9d0cc04d..c02addef 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-core.c
> +++ b/drivers/media/platform/exynos-gsc/gsc-core.c
> @@ -34,167 +34,185 @@ static const struct gsc_fmt gsc_formats[] = {
>         {
>                 .name           = "RGB565",
>                 .pixelformat    = V4L2_PIX_FMT_RGB565X,
> -               .depth          = { 16 },
>                 .color          = GSC_RGB,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 16 },
> +               .sampling       = { { 1, 1 } },
>         }, {
>                 .name           = "XRGB-8-8-8-8, 32 bpp",
>                 .pixelformat    = V4L2_PIX_FMT_RGB32,
> -               .depth          = { 32 },
>                 .color          = GSC_RGB,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 32 },
> +               .sampling       = { { 1, 1 } },
>         }, {
>                 .name           = "YUV 4:2:2 packed, YCbYCr",
>                 .pixelformat    = V4L2_PIX_FMT_YUYV,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 16 },
> +               .sampling       = { { 1, 1 } },
>                 .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
>         }, {
>                 .name           = "YUV 4:2:2 packed, CbYCrY",
>                 .pixelformat    = V4L2_PIX_FMT_UYVY,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_C,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 16 },
> +               .sampling       = { { 1, 1 } },
>                 .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
>         }, {
>                 .name           = "YUV 4:2:2 packed, CrYCbY",
>                 .pixelformat    = V4L2_PIX_FMT_VYUY,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_C,
>                 .corder         = GSC_CRCB,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 16 },
> +               .sampling       = { { 1, 1 } },
>                 .mbus_code      = V4L2_MBUS_FMT_VYUY8_2X8,
>         }, {
>                 .name           = "YUV 4:2:2 packed, YCrYCb",
>                 .pixelformat    = V4L2_PIX_FMT_YVYU,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CRCB,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 16 },
> +               .sampling       = { { 1, 1 } },
>                 .mbus_code      = V4L2_MBUS_FMT_YVYU8_2X8,
>         }, {
>                 .name           = "YUV 4:4:4 planar, YCbYCr",
>                 .pixelformat    = V4L2_PIX_FMT_YUV32,
> -               .depth          = { 32 },
>                 .color          = GSC_YUV444,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 1,
> +               .depth          = { 32 },
> +               .sampling       = { { 1, 1 } },
>         }, {
>                 .name           = "YUV 4:2:2 planar, Y/Cb/Cr",
>                 .pixelformat    = V4L2_PIX_FMT_YUV422P,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 3,
> +               .depth          = { 8, 8, 8 },
> +               .sampling       = { { 1, 1 }, { 2, 1 }, { 2, 1 } },
>         }, {
>                 .name           = "YUV 4:2:2 planar, Y/CbCr",
>                 .pixelformat    = V4L2_PIX_FMT_NV16,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 2,
> +               .depth          = { 8, 16 },
> +               .sampling       = { { 1, 1 }, { 2, 1 } },
>         }, {
>                 .name           = "YUV 4:2:2 planar, Y/CrCb",
>                 .pixelformat    = V4L2_PIX_FMT_NV61,
> -               .depth          = { 16 },
>                 .color          = GSC_YUV422,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CRCB,
>                 .num_planes     = 1,
>                 .num_comp       = 2,
> +               .depth          = { 8, 16 },
> +               .sampling       = { { 1, 1 }, { 2, 1 } },
>         }, {
>                 .name           = "YUV 4:2:0 planar, YCbCr",
>                 .pixelformat    = V4L2_PIX_FMT_YUV420,
> -               .depth          = { 12 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 3,
> +               .depth          = { 8, 8, 8 },
> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>         }, {
>                 .name           = "YUV 4:2:0 planar, YCrCb",
>                 .pixelformat    = V4L2_PIX_FMT_YVU420,
> -               .depth          = { 12 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CRCB,
>                 .num_planes     = 1,
>                 .num_comp       = 3,
> -
> +               .depth          = { 8, 8, 8 },
> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>         }, {
>                 .name           = "YUV 4:2:0 planar, Y/CbCr",
>                 .pixelformat    = V4L2_PIX_FMT_NV12,
> -               .depth          = { 12 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 1,
>                 .num_comp       = 2,
> +               .depth          = { 8, 16 },
> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>         }, {
>                 .name           = "YUV 4:2:0 planar, Y/CrCb",
>                 .pixelformat    = V4L2_PIX_FMT_NV21,
> -               .depth          = { 12 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CRCB,
>                 .num_planes     = 1,
>                 .num_comp       = 2,
> +               .depth          = { 8, 16 },
> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>         }, {
> -               .name           = "YUV 4:2:0 non-contig. 2p, Y/CbCr",
> +               .name           = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
>                 .pixelformat    = V4L2_PIX_FMT_NV12M,
> -               .depth          = { 8, 4 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 2,
>                 .num_comp       = 2,
> +               .depth          = { 8, 16 },
> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>         }, {
> -               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
> +               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
>                 .pixelformat    = V4L2_PIX_FMT_YUV420M,
> -               .depth          = { 8, 2, 2 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 3,
>                 .num_comp       = 3,
> +               .depth          = { 8, 8, 8 },
> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>         }, {
> -               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb",
> +               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb",
>                 .pixelformat    = V4L2_PIX_FMT_YVU420M,
> -               .depth          = { 8, 2, 2 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CRCB,
>                 .num_planes     = 3,
>                 .num_comp       = 3,
> +               .depth          = { 8, 8, 8 },
> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>         }, {
> -               .name           = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled",
> +               .name           =
> +                       "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
>                 .pixelformat    = V4L2_PIX_FMT_NV12MT_16X16,
> -               .depth          = { 8, 4 },
>                 .color          = GSC_YUV420,
>                 .yorder         = GSC_LSB_Y,
>                 .corder         = GSC_CBCR,
>                 .num_planes     = 2,
>                 .num_comp       = 2,
> -       }
> +               .depth          = { 8, 16 },
> +               .sampling       = { { 1, 1 }, { 2, 2 } },
> +       },
>  };
>
>  const struct gsc_fmt *get_format(int index)
> @@ -384,6 +402,14 @@ void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)
>                         f_chk_addr, f_chk_len, s_chk_addr, s_chk_len);
>  }
>
> +static void get_format_size(__u32 width, __u32 height,
> +                           const struct gsc_fmt *fmt, int plane,
> +                           __u16 *bytesperline, __u32 *sizeimage) {
> +       __u16 bpl = ((width * fmt->depth[plane]) / fmt->sampling[plane][0]) / 8;
> +       *bytesperline = bpl;
> +       *sizeimage = (height * bpl) / fmt->sampling[plane][0];

should use the height sampling instead ??
*sizeimage = (height * bpl) / fmt->sampling[plane][1];

> +}
> +
>  int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
>  {
>         struct gsc_dev *gsc = ctx->gsc_dev;
> @@ -448,14 +474,16 @@ int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
>         else /* SD */
>                 pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
>
> -
> +       /* V4L2 specifies for contiguous planar formats that bytesperline and
> +          sizeimage are set to values appropriate for the first plane. */
>         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;
> +               get_format_size(pix_mp->width, pix_mp->height, fmt, i,
> +                               &pix_mp->plane_fmt[i].bytesperline,
> +                               &pix_mp->plane_fmt[i].sizeimage);
>
>                 pr_debug("[%d]: bpl: %d, sizeimage: %d",
> -                               i, bpl, pix_mp->plane_fmt[i].sizeimage);
> +                               i, pix_mp->plane_fmt[i].bytesperline,
> +                               pix_mp->plane_fmt[i].sizeimage);
>         }
>
>         return 0;
> @@ -465,26 +493,27 @@ int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
>  {
>         struct gsc_frame *frame;
>         struct v4l2_pix_format_mplane *pix_mp;
> +       const struct gsc_fmt *fmt;
>         int i;
>
>         frame = ctx_get_frame(ctx, f->type);
>         if (IS_ERR(frame))
>                 return PTR_ERR(frame);
> +       fmt = frame->fmt;
>
>         pix_mp = &f->fmt.pix_mp;
>
>         pix_mp->width           = frame->f_width;
>         pix_mp->height          = frame->f_height;
>         pix_mp->field           = V4L2_FIELD_NONE;
> -       pix_mp->pixelformat     = frame->fmt->pixelformat;
> +       pix_mp->pixelformat     = fmt->pixelformat;
>         pix_mp->colorspace      = V4L2_COLORSPACE_REC709;
> -       pix_mp->num_planes      = frame->fmt->num_planes;
> +       pix_mp->num_planes      = fmt->num_planes;
>
>         for (i = 0; i < pix_mp->num_planes; ++i) {
> -               pix_mp->plane_fmt[i].bytesperline = (frame->f_width *
> -                       frame->fmt->depth[i]) / 8;
> -               pix_mp->plane_fmt[i].sizeimage =
> -                        pix_mp->plane_fmt[i].bytesperline * frame->f_height;
> +               get_format_size(pix_mp->width, pix_mp->height, fmt, i,
> +                               &pix_mp->plane_fmt[i].bytesperline,
> +                               &pix_mp->plane_fmt[i].sizeimage);
>         }
>
>         return 0;
> @@ -794,11 +823,12 @@ void gsc_ctrls_delete(struct gsc_ctx *ctx)
>         }
>  }
>
> -/* The color format (num_comp, num_planes) must be already configured. */
> +/* The color format (num_planes, num_comp) must be already configured. */
>  int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
>                         struct gsc_frame *frame, struct gsc_addr *addr)
>  {
>         int ret = 0;
> +       const struct gsc_fmt *fmt = frame->fmt;
>         u32 pix_size;
>
>         if ((vb == NULL) || (frame == NULL))
> @@ -810,46 +840,30 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
>                 frame->fmt->num_planes, frame->fmt->num_comp, pix_size);
>
>         addr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
> -
> -       if (frame->fmt->num_planes == 1) {
> -               switch (frame->fmt->num_comp) {
> -               case 1:
> -                       addr->cb = 0;
> -                       addr->cr = 0;
> -                       break;
> -               case 2:
> -                       /* decompose Y into Y/Cb */
> -                       addr->cb = (dma_addr_t)(addr->y + pix_size);
> -                       addr->cr = 0;
> -                       break;
> -               case 3:
> -                       /* decompose Y into Y/Cb/Cr */
> -                       addr->cb = (dma_addr_t)(addr->y + pix_size);
> -                       if (GSC_YUV420 == frame->fmt->color)
> -                               addr->cr = (dma_addr_t)(addr->cb
> -                                               + (pix_size >> 2));
> -                       else /* 422 */
> -                               addr->cr = (dma_addr_t)(addr->cb
> -                                               + (pix_size >> 1));
> -                       break;
> -               default:
> -                       pr_err("Invalid the number of color planes");
> -                       return -EINVAL;
> +       addr->cb = 0;
> +       addr->cr = 0;
> +
> +       if (fmt->num_planes == 1) {
> +               if (fmt->num_comp >= 2) {
> +                       addr->cb = (dma_addr_t)(addr->y +
> +                               ((pix_size * fmt->depth[0]) /
> +                               (fmt->sampling[0][0] *
> +                                fmt->sampling[0][1]) / 8));
> +               }
> +               if (fmt->num_comp >= 3) {
> +                       addr->cr = (dma_addr_t)(addr->cb +
> +                               ((pix_size * fmt->depth[1]) /
> +                               (fmt->sampling[1][0] *
> +                                fmt->sampling[1][1]) / 8));
>                 }
>         } else {
> -               if (frame->fmt->num_planes >= 2)
> +               if (fmt->num_comp >= 2)
>                         addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
> -
> -               if (frame->fmt->num_planes == 3)
> +               if (fmt->num_comp == 3)
>                         addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
>         }
>
> -       if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) ||
> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) ||
> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) ||
> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) ||
> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) ||
> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M))
> +       if (fmt->corder == GSC_CRCB)

            if ((fmt->corder == GSC_CRCB) && (fmt->num_planes == 3))

I think it shoud only applicable to 3 component formats.
for example, Incase of two component formats like V4L2_PIX_FMT_NV61,
chroma base address becomes zero.


Regards,
Shaik Ameer Basha

>                 swap(addr->cb, addr->cr);
>
>         pr_debug("ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
> diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
> index ef0a6564..8fb07e0d 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-core.h
> +++ b/drivers/media/platform/exynos-gsc/gsc-core.h
> @@ -106,27 +106,27 @@ enum gsc_yuv_fmt {
>         container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)
>  /**
>   * struct gsc_fmt - the driver's internal color format data
> - * @mbus_code: Media Bus pixel code, -1 if not applicable
>   * @name: format description
>   * @pixelformat: the fourcc code for this format, 0 if not applicable
>   * @yorder: Y/C order
>   * @corder: Chrominance order control
>   * @num_planes: number of physically non-contiguous data planes
> - * @nr_comp: number of physically contiguous data planes
> - * @depth: per plane driver's private 'number of bits per pixel'
> - * @flags: flags indicating which operation mode format applies to
> + * @num_comp: number of physically contiguous data planes
> + * @depth: bit depth of each component
> + * @sampling: sampling frequency of each components, X and Y
> + * @mbus_code: Media Bus pixel code, -1 if not applicable
>   */
>  struct gsc_fmt {
> -       enum v4l2_mbus_pixelcode mbus_code;
>         char    *name;
>         u32     pixelformat;
>         u32     color;
>         u32     yorder;
>         u32     corder;
> -       u16     num_planes;
> -       u16     num_comp;
> +       u8      num_planes;
> +       u8      num_comp;
>         u8      depth[VIDEO_MAX_PLANES];
> -       u32     flags;
> +       u8      sampling[VIDEO_MAX_PLANES][2];
> +       enum v4l2_mbus_pixelcode mbus_code;
>  };
>
>  /**
> diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c
> index e22d147a..a8d6c90b 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-regs.c
> +++ b/drivers/media/platform/exynos-gsc/gsc-regs.c
> @@ -167,6 +167,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>  {
>         struct gsc_dev *dev = ctx->gsc_dev;
>         struct gsc_frame *frame = &ctx->s_frame;
> +       const struct gsc_fmt *fmt = frame->fmt;
>         u32 i, depth = 0;
>         u32 cfg;
>
> @@ -176,21 +177,22 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>                  GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
>         writel(cfg, dev->regs + GSC_IN_CON);
>
> -       if (is_rgb(frame->fmt->color)) {
> +       if (is_rgb(fmt->color)) {
>                 gsc_hw_set_in_image_rgb(ctx);
>                 return;
>         }
> -       for (i = 0; i < frame->fmt->num_planes; i++)
> -               depth += frame->fmt->depth[i];
> +       for (i = 0; i < fmt->num_comp; i++)
> +               depth += fmt->depth[i] /
> +                       (fmt->sampling[i][0] * fmt->sampling[i][1]);
>
> -       switch (frame->fmt->num_comp) {
> +       switch (fmt->num_comp) {
>         case 1:
>                 cfg |= GSC_IN_YUV422_1P;
> -               if (frame->fmt->yorder == GSC_LSB_Y)
> +               if (fmt->yorder == GSC_LSB_Y)
>                         cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
>                 else
> -                       cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
> -               if (frame->fmt->corder == GSC_CBCR)
> +                       cfg |= GSC_IN_YUV422_1P_ORDER_LSB_C;
> +               if (fmt->corder == GSC_CBCR)
>                         cfg |= GSC_IN_CHROMA_ORDER_CBCR;
>                 else
>                         cfg |= GSC_IN_CHROMA_ORDER_CRCB;
> @@ -200,7 +202,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>                         cfg |= GSC_IN_YUV420_2P;
>                 else
>                         cfg |= GSC_IN_YUV422_2P;
> -               if (frame->fmt->corder == GSC_CBCR)
> +               if (fmt->corder == GSC_CBCR)
>                         cfg |= GSC_IN_CHROMA_ORDER_CBCR;
>                 else
>                         cfg |= GSC_IN_CHROMA_ORDER_CRCB;
> @@ -213,7 +215,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>                 break;
>         }
>
> -       if (is_tiled(frame->fmt))
> +       if (is_tiled(fmt))
>                 cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
>
>         writel(cfg, dev->regs + GSC_IN_CON);
> @@ -287,6 +289,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>  {
>         struct gsc_dev *dev = ctx->gsc_dev;
>         struct gsc_frame *frame = &ctx->d_frame;
> +       const struct gsc_fmt *fmt = frame->fmt;
>         u32 i, depth = 0;
>         u32 cfg;
>
> @@ -296,7 +299,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>                  GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
>         writel(cfg, dev->regs + GSC_OUT_CON);
>
> -       if (is_rgb(frame->fmt->color)) {
> +       if (is_rgb(fmt->color)) {
>                 gsc_hw_set_out_image_rgb(ctx);
>                 return;
>         }
> @@ -306,17 +309,18 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>                 goto end_set;
>         }
>
> -       for (i = 0; i < frame->fmt->num_planes; i++)
> -               depth += frame->fmt->depth[i];
> +       for (i = 0; i < fmt->num_comp; i++)
> +               depth += fmt->depth[i] /
> +                       (fmt->sampling[i][0] * fmt->sampling[i][1]);
>
> -       switch (frame->fmt->num_comp) {
> +       switch (fmt->num_comp) {
>         case 1:
>                 cfg |= GSC_OUT_YUV422_1P;
> -               if (frame->fmt->yorder == GSC_LSB_Y)
> +               if (fmt->yorder == GSC_LSB_Y)
>                         cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
>                 else
> -                       cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
> -               if (frame->fmt->corder == GSC_CBCR)
> +                       cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_C;
> +               if (fmt->corder == GSC_CBCR)
>                         cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
>                 else
>                         cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
> @@ -326,7 +330,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>                         cfg |= GSC_OUT_YUV420_2P;
>                 else
>                         cfg |= GSC_OUT_YUV422_2P;
> -               if (frame->fmt->corder == GSC_CBCR)
> +               if (fmt->corder == GSC_CBCR)
>                         cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
>                 else
>                         cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
> @@ -336,7 +340,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>                 break;
>         }
>
> -       if (is_tiled(frame->fmt))
> +       if (is_tiled(fmt))
>                 cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
>
>  end_set:
> diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.h b/drivers/media/platform/exynos-gsc/gsc-regs.h
> index 4678f9a6..b03401dc 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-regs.h
> +++ b/drivers/media/platform/exynos-gsc/gsc-regs.h
> @@ -46,7 +46,7 @@
>  #define GSC_IN_RGB_SD_WIDE             (0 << 14)
>  #define GSC_IN_YUV422_1P_ORDER_MASK    (1 << 13)
>  #define GSC_IN_YUV422_1P_ORDER_LSB_Y   (0 << 13)
> -#define GSC_IN_YUV422_1P_OEDER_LSB_C   (1 << 13)
> +#define GSC_IN_YUV422_1P_ORDER_LSB_C   (1 << 13)
>  #define GSC_IN_CHROMA_ORDER_MASK       (1 << 12)
>  #define GSC_IN_CHROMA_ORDER_CBCR       (0 << 12)
>  #define GSC_IN_CHROMA_ORDER_CRCB       (1 << 12)
> @@ -91,7 +91,7 @@
>  #define GSC_OUT_RGB_SD_NARROW          (0 << 10)
>  #define GSC_OUT_YUV422_1P_ORDER_MASK   (1 << 9)
>  #define GSC_OUT_YUV422_1P_ORDER_LSB_Y  (0 << 9)
> -#define GSC_OUT_YUV422_1P_OEDER_LSB_C  (1 << 9)
> +#define GSC_OUT_YUV422_1P_ORDER_LSB_C  (1 << 9)
>  #define GSC_OUT_CHROMA_ORDER_MASK      (1 << 8)
>  #define GSC_OUT_CHROMA_ORDER_CBCR      (0 << 8)
>  #define GSC_OUT_CHROMA_ORDER_CRCB      (1 << 8)
> --
> 1.9.0.279.gdc9e3eb
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shaik Ameer Basha April 8, 2014, 7:11 a.m. UTC | #3
On Tue, Apr 8, 2014 at 12:26 PM, Shaik Ameer Basha
<shaik.samsung@gmail.com> wrote:
> Hi John Sheu,
>
> Thanks for the patch.
> Please find the review comments inline.
>
> On Wed, Mar 12, 2014 at 4:22 AM, John Sheu <sheu@google.com> wrote:
>> Explicitly specify sampling period for subsampled chroma formats, so
>> stride and image size are properly reported through VIDIOC_{S,G}_FMT.
>>
>> Signed-off-by: John Sheu <sheu@google.com>
>> ---
>>  drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++------------
>>  drivers/media/platform/exynos-gsc/gsc-core.h |  16 +--
>>  drivers/media/platform/exynos-gsc/gsc-regs.c |  40 +++----
>>  drivers/media/platform/exynos-gsc/gsc-regs.h |   4 +-
>>  4 files changed, 116 insertions(+), 98 deletions(-)
>>
>> diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
>> index 9d0cc04d..c02addef 100644
>> --- a/drivers/media/platform/exynos-gsc/gsc-core.c
>> +++ b/drivers/media/platform/exynos-gsc/gsc-core.c
>> @@ -34,167 +34,185 @@ static const struct gsc_fmt gsc_formats[] = {
>>         {
>>                 .name           = "RGB565",
>>                 .pixelformat    = V4L2_PIX_FMT_RGB565X,
>> -               .depth          = { 16 },
>>                 .color          = GSC_RGB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 16 },
>> +               .sampling       = { { 1, 1 } },
>>         }, {
>>                 .name           = "XRGB-8-8-8-8, 32 bpp",
>>                 .pixelformat    = V4L2_PIX_FMT_RGB32,
>> -               .depth          = { 32 },
>>                 .color          = GSC_RGB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 32 },
>> +               .sampling       = { { 1, 1 } },
>>         }, {
>>                 .name           = "YUV 4:2:2 packed, YCbYCr",
>>                 .pixelformat    = V4L2_PIX_FMT_YUYV,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 16 },
>> +               .sampling       = { { 1, 1 } },
>>                 .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
>>         }, {
>>                 .name           = "YUV 4:2:2 packed, CbYCrY",
>>                 .pixelformat    = V4L2_PIX_FMT_UYVY,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_C,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 16 },
>> +               .sampling       = { { 1, 1 } },
>>                 .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
>>         }, {
>>                 .name           = "YUV 4:2:2 packed, CrYCbY",
>>                 .pixelformat    = V4L2_PIX_FMT_VYUY,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_C,
>>                 .corder         = GSC_CRCB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 16 },
>> +               .sampling       = { { 1, 1 } },
>>                 .mbus_code      = V4L2_MBUS_FMT_VYUY8_2X8,
>>         }, {
>>                 .name           = "YUV 4:2:2 packed, YCrYCb",
>>                 .pixelformat    = V4L2_PIX_FMT_YVYU,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CRCB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 16 },
>> +               .sampling       = { { 1, 1 } },
>>                 .mbus_code      = V4L2_MBUS_FMT_YVYU8_2X8,
>>         }, {
>>                 .name           = "YUV 4:4:4 planar, YCbYCr",
>>                 .pixelformat    = V4L2_PIX_FMT_YUV32,
>> -               .depth          = { 32 },
>>                 .color          = GSC_YUV444,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 1,
>> +               .depth          = { 32 },
>> +               .sampling       = { { 1, 1 } },
>>         }, {
>>                 .name           = "YUV 4:2:2 planar, Y/Cb/Cr",
>>                 .pixelformat    = V4L2_PIX_FMT_YUV422P,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 3,
>> +               .depth          = { 8, 8, 8 },
>> +               .sampling       = { { 1, 1 }, { 2, 1 }, { 2, 1 } },
>>         }, {
>>                 .name           = "YUV 4:2:2 planar, Y/CbCr",
>>                 .pixelformat    = V4L2_PIX_FMT_NV16,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 2,
>> +               .depth          = { 8, 16 },
>> +               .sampling       = { { 1, 1 }, { 2, 1 } },
>>         }, {
>>                 .name           = "YUV 4:2:2 planar, Y/CrCb",
>>                 .pixelformat    = V4L2_PIX_FMT_NV61,
>> -               .depth          = { 16 },
>>                 .color          = GSC_YUV422,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CRCB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 2,
>> +               .depth          = { 8, 16 },
>> +               .sampling       = { { 1, 1 }, { 2, 1 } },
>>         }, {
>>                 .name           = "YUV 4:2:0 planar, YCbCr",
>>                 .pixelformat    = V4L2_PIX_FMT_YUV420,
>> -               .depth          = { 12 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 3,
>> +               .depth          = { 8, 8, 8 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>>         }, {
>>                 .name           = "YUV 4:2:0 planar, YCrCb",
>>                 .pixelformat    = V4L2_PIX_FMT_YVU420,
>> -               .depth          = { 12 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CRCB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 3,
>> -
>> +               .depth          = { 8, 8, 8 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>>         }, {
>>                 .name           = "YUV 4:2:0 planar, Y/CbCr",
>>                 .pixelformat    = V4L2_PIX_FMT_NV12,
>> -               .depth          = { 12 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 1,
>>                 .num_comp       = 2,
>> +               .depth          = { 8, 16 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>>         }, {
>>                 .name           = "YUV 4:2:0 planar, Y/CrCb",
>>                 .pixelformat    = V4L2_PIX_FMT_NV21,
>> -               .depth          = { 12 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CRCB,
>>                 .num_planes     = 1,
>>                 .num_comp       = 2,
>> +               .depth          = { 8, 16 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>>         }, {
>> -               .name           = "YUV 4:2:0 non-contig. 2p, Y/CbCr",
>> +               .name           = "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
>>                 .pixelformat    = V4L2_PIX_FMT_NV12M,
>> -               .depth          = { 8, 4 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 2,
>>                 .num_comp       = 2,
>> +               .depth          = { 8, 16 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>>         }, {
>> -               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
>> +               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
>>                 .pixelformat    = V4L2_PIX_FMT_YUV420M,
>> -               .depth          = { 8, 2, 2 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 3,
>>                 .num_comp       = 3,
>> +               .depth          = { 8, 8, 8 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>>         }, {
>> -               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb",
>> +               .name           = "YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb",
>>                 .pixelformat    = V4L2_PIX_FMT_YVU420M,
>> -               .depth          = { 8, 2, 2 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CRCB,
>>                 .num_planes     = 3,
>>                 .num_comp       = 3,
>> +               .depth          = { 8, 8, 8 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 }, { 2, 2 } },
>>         }, {
>> -               .name           = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled",
>> +               .name           =
>> +                       "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
>>                 .pixelformat    = V4L2_PIX_FMT_NV12MT_16X16,
>> -               .depth          = { 8, 4 },
>>                 .color          = GSC_YUV420,
>>                 .yorder         = GSC_LSB_Y,
>>                 .corder         = GSC_CBCR,
>>                 .num_planes     = 2,
>>                 .num_comp       = 2,
>> -       }
>> +               .depth          = { 8, 16 },
>> +               .sampling       = { { 1, 1 }, { 2, 2 } },
>> +       },
>>  };
>>
>>  const struct gsc_fmt *get_format(int index)
>> @@ -384,6 +402,14 @@ void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)
>>                         f_chk_addr, f_chk_len, s_chk_addr, s_chk_len);
>>  }
>>
>> +static void get_format_size(__u32 width, __u32 height,
>> +                           const struct gsc_fmt *fmt, int plane,
>> +                           __u16 *bytesperline, __u32 *sizeimage) {
>> +       __u16 bpl = ((width * fmt->depth[plane]) / fmt->sampling[plane][0]) / 8;
>> +       *bytesperline = bpl;
>> +       *sizeimage = (height * bpl) / fmt->sampling[plane][0];
>
> should use the height sampling instead ??
> *sizeimage = (height * bpl) / fmt->sampling[plane][1];
>
>> +}
>> +
>>  int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
>>  {
>>         struct gsc_dev *gsc = ctx->gsc_dev;
>> @@ -448,14 +474,16 @@ int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
>>         else /* SD */
>>                 pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
>>
>> -
>> +       /* V4L2 specifies for contiguous planar formats that bytesperline and
>> +          sizeimage are set to values appropriate for the first plane. */
>>         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;
>> +               get_format_size(pix_mp->width, pix_mp->height, fmt, i,
>> +                               &pix_mp->plane_fmt[i].bytesperline,
>> +                               &pix_mp->plane_fmt[i].sizeimage);
>>
>>                 pr_debug("[%d]: bpl: %d, sizeimage: %d",
>> -                               i, bpl, pix_mp->plane_fmt[i].sizeimage);
>> +                               i, pix_mp->plane_fmt[i].bytesperline,
>> +                               pix_mp->plane_fmt[i].sizeimage);
>>         }
>>
>>         return 0;
>> @@ -465,26 +493,27 @@ int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
>>  {
>>         struct gsc_frame *frame;
>>         struct v4l2_pix_format_mplane *pix_mp;
>> +       const struct gsc_fmt *fmt;
>>         int i;
>>
>>         frame = ctx_get_frame(ctx, f->type);
>>         if (IS_ERR(frame))
>>                 return PTR_ERR(frame);
>> +       fmt = frame->fmt;
>>
>>         pix_mp = &f->fmt.pix_mp;
>>
>>         pix_mp->width           = frame->f_width;
>>         pix_mp->height          = frame->f_height;
>>         pix_mp->field           = V4L2_FIELD_NONE;
>> -       pix_mp->pixelformat     = frame->fmt->pixelformat;
>> +       pix_mp->pixelformat     = fmt->pixelformat;
>>         pix_mp->colorspace      = V4L2_COLORSPACE_REC709;
>> -       pix_mp->num_planes      = frame->fmt->num_planes;
>> +       pix_mp->num_planes      = fmt->num_planes;
>>
>>         for (i = 0; i < pix_mp->num_planes; ++i) {
>> -               pix_mp->plane_fmt[i].bytesperline = (frame->f_width *
>> -                       frame->fmt->depth[i]) / 8;
>> -               pix_mp->plane_fmt[i].sizeimage =
>> -                        pix_mp->plane_fmt[i].bytesperline * frame->f_height;
>> +               get_format_size(pix_mp->width, pix_mp->height, fmt, i,
>> +                               &pix_mp->plane_fmt[i].bytesperline,
>> +                               &pix_mp->plane_fmt[i].sizeimage);
>>         }
>>
>>         return 0;
>> @@ -794,11 +823,12 @@ void gsc_ctrls_delete(struct gsc_ctx *ctx)
>>         }
>>  }
>>
>> -/* The color format (num_comp, num_planes) must be already configured. */
>> +/* The color format (num_planes, num_comp) must be already configured. */
>>  int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
>>                         struct gsc_frame *frame, struct gsc_addr *addr)
>>  {
>>         int ret = 0;
>> +       const struct gsc_fmt *fmt = frame->fmt;
>>         u32 pix_size;
>>
>>         if ((vb == NULL) || (frame == NULL))
>> @@ -810,46 +840,30 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
>>                 frame->fmt->num_planes, frame->fmt->num_comp, pix_size);
>>
>>         addr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
>> -
>> -       if (frame->fmt->num_planes == 1) {
>> -               switch (frame->fmt->num_comp) {
>> -               case 1:
>> -                       addr->cb = 0;
>> -                       addr->cr = 0;
>> -                       break;
>> -               case 2:
>> -                       /* decompose Y into Y/Cb */
>> -                       addr->cb = (dma_addr_t)(addr->y + pix_size);
>> -                       addr->cr = 0;
>> -                       break;
>> -               case 3:
>> -                       /* decompose Y into Y/Cb/Cr */
>> -                       addr->cb = (dma_addr_t)(addr->y + pix_size);
>> -                       if (GSC_YUV420 == frame->fmt->color)
>> -                               addr->cr = (dma_addr_t)(addr->cb
>> -                                               + (pix_size >> 2));
>> -                       else /* 422 */
>> -                               addr->cr = (dma_addr_t)(addr->cb
>> -                                               + (pix_size >> 1));
>> -                       break;
>> -               default:
>> -                       pr_err("Invalid the number of color planes");
>> -                       return -EINVAL;
>> +       addr->cb = 0;
>> +       addr->cr = 0;
>> +
>> +       if (fmt->num_planes == 1) {
>> +               if (fmt->num_comp >= 2) {
>> +                       addr->cb = (dma_addr_t)(addr->y +
>> +                               ((pix_size * fmt->depth[0]) /
>> +                               (fmt->sampling[0][0] *
>> +                                fmt->sampling[0][1]) / 8));
>> +               }
>> +               if (fmt->num_comp >= 3) {
>> +                       addr->cr = (dma_addr_t)(addr->cb +
>> +                               ((pix_size * fmt->depth[1]) /
>> +                               (fmt->sampling[1][0] *
>> +                                fmt->sampling[1][1]) / 8));
>>                 }
>>         } else {
>> -               if (frame->fmt->num_planes >= 2)
>> +               if (fmt->num_comp >= 2)
>>                         addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
>> -
>> -               if (frame->fmt->num_planes == 3)
>> +               if (fmt->num_comp == 3)
>>                         addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
>>         }
>>
>> -       if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) ||
>> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) ||
>> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) ||
>> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) ||
>> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) ||
>> -               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M))
>> +       if (fmt->corder == GSC_CRCB)
>
>             if ((fmt->corder == GSC_CRCB) && (fmt->num_planes == 3))

sorry, it is....
               if ((fmt->corder == GSC_CRCB) && (fmt->num_comp == 3))

>
> I think it shoud only applicable to 3 component formats.
> for example, Incase of two component formats like V4L2_PIX_FMT_NV61,
> chroma base address becomes zero.
>
>
> Regards,
> Shaik Ameer Basha
>
>>                 swap(addr->cb, addr->cr);
>>
>>         pr_debug("ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
>> diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
>> index ef0a6564..8fb07e0d 100644
>> --- a/drivers/media/platform/exynos-gsc/gsc-core.h
>> +++ b/drivers/media/platform/exynos-gsc/gsc-core.h
>> @@ -106,27 +106,27 @@ enum gsc_yuv_fmt {
>>         container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)
>>  /**
>>   * struct gsc_fmt - the driver's internal color format data
>> - * @mbus_code: Media Bus pixel code, -1 if not applicable
>>   * @name: format description
>>   * @pixelformat: the fourcc code for this format, 0 if not applicable
>>   * @yorder: Y/C order
>>   * @corder: Chrominance order control
>>   * @num_planes: number of physically non-contiguous data planes
>> - * @nr_comp: number of physically contiguous data planes
>> - * @depth: per plane driver's private 'number of bits per pixel'
>> - * @flags: flags indicating which operation mode format applies to
>> + * @num_comp: number of physically contiguous data planes
>> + * @depth: bit depth of each component
>> + * @sampling: sampling frequency of each components, X and Y
>> + * @mbus_code: Media Bus pixel code, -1 if not applicable
>>   */
>>  struct gsc_fmt {
>> -       enum v4l2_mbus_pixelcode mbus_code;
>>         char    *name;
>>         u32     pixelformat;
>>         u32     color;
>>         u32     yorder;
>>         u32     corder;
>> -       u16     num_planes;
>> -       u16     num_comp;
>> +       u8      num_planes;
>> +       u8      num_comp;
>>         u8      depth[VIDEO_MAX_PLANES];
>> -       u32     flags;
>> +       u8      sampling[VIDEO_MAX_PLANES][2];
>> +       enum v4l2_mbus_pixelcode mbus_code;
>>  };
>>
>>  /**
>> diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c
>> index e22d147a..a8d6c90b 100644
>> --- a/drivers/media/platform/exynos-gsc/gsc-regs.c
>> +++ b/drivers/media/platform/exynos-gsc/gsc-regs.c
>> @@ -167,6 +167,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>>  {
>>         struct gsc_dev *dev = ctx->gsc_dev;
>>         struct gsc_frame *frame = &ctx->s_frame;
>> +       const struct gsc_fmt *fmt = frame->fmt;
>>         u32 i, depth = 0;
>>         u32 cfg;
>>
>> @@ -176,21 +177,22 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>>                  GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
>>         writel(cfg, dev->regs + GSC_IN_CON);
>>
>> -       if (is_rgb(frame->fmt->color)) {
>> +       if (is_rgb(fmt->color)) {
>>                 gsc_hw_set_in_image_rgb(ctx);
>>                 return;
>>         }
>> -       for (i = 0; i < frame->fmt->num_planes; i++)
>> -               depth += frame->fmt->depth[i];
>> +       for (i = 0; i < fmt->num_comp; i++)
>> +               depth += fmt->depth[i] /
>> +                       (fmt->sampling[i][0] * fmt->sampling[i][1]);
>>
>> -       switch (frame->fmt->num_comp) {
>> +       switch (fmt->num_comp) {
>>         case 1:
>>                 cfg |= GSC_IN_YUV422_1P;
>> -               if (frame->fmt->yorder == GSC_LSB_Y)
>> +               if (fmt->yorder == GSC_LSB_Y)
>>                         cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
>>                 else
>> -                       cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
>> -               if (frame->fmt->corder == GSC_CBCR)
>> +                       cfg |= GSC_IN_YUV422_1P_ORDER_LSB_C;
>> +               if (fmt->corder == GSC_CBCR)
>>                         cfg |= GSC_IN_CHROMA_ORDER_CBCR;
>>                 else
>>                         cfg |= GSC_IN_CHROMA_ORDER_CRCB;
>> @@ -200,7 +202,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>>                         cfg |= GSC_IN_YUV420_2P;
>>                 else
>>                         cfg |= GSC_IN_YUV422_2P;
>> -               if (frame->fmt->corder == GSC_CBCR)
>> +               if (fmt->corder == GSC_CBCR)
>>                         cfg |= GSC_IN_CHROMA_ORDER_CBCR;
>>                 else
>>                         cfg |= GSC_IN_CHROMA_ORDER_CRCB;
>> @@ -213,7 +215,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
>>                 break;
>>         }
>>
>> -       if (is_tiled(frame->fmt))
>> +       if (is_tiled(fmt))
>>                 cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
>>
>>         writel(cfg, dev->regs + GSC_IN_CON);
>> @@ -287,6 +289,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>>  {
>>         struct gsc_dev *dev = ctx->gsc_dev;
>>         struct gsc_frame *frame = &ctx->d_frame;
>> +       const struct gsc_fmt *fmt = frame->fmt;
>>         u32 i, depth = 0;
>>         u32 cfg;
>>
>> @@ -296,7 +299,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>>                  GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
>>         writel(cfg, dev->regs + GSC_OUT_CON);
>>
>> -       if (is_rgb(frame->fmt->color)) {
>> +       if (is_rgb(fmt->color)) {
>>                 gsc_hw_set_out_image_rgb(ctx);
>>                 return;
>>         }
>> @@ -306,17 +309,18 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>>                 goto end_set;
>>         }
>>
>> -       for (i = 0; i < frame->fmt->num_planes; i++)
>> -               depth += frame->fmt->depth[i];
>> +       for (i = 0; i < fmt->num_comp; i++)
>> +               depth += fmt->depth[i] /
>> +                       (fmt->sampling[i][0] * fmt->sampling[i][1]);
>>
>> -       switch (frame->fmt->num_comp) {
>> +       switch (fmt->num_comp) {
>>         case 1:
>>                 cfg |= GSC_OUT_YUV422_1P;
>> -               if (frame->fmt->yorder == GSC_LSB_Y)
>> +               if (fmt->yorder == GSC_LSB_Y)
>>                         cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
>>                 else
>> -                       cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
>> -               if (frame->fmt->corder == GSC_CBCR)
>> +                       cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_C;
>> +               if (fmt->corder == GSC_CBCR)
>>                         cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
>>                 else
>>                         cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
>> @@ -326,7 +330,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>>                         cfg |= GSC_OUT_YUV420_2P;
>>                 else
>>                         cfg |= GSC_OUT_YUV422_2P;
>> -               if (frame->fmt->corder == GSC_CBCR)
>> +               if (fmt->corder == GSC_CBCR)
>>                         cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
>>                 else
>>                         cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
>> @@ -336,7 +340,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
>>                 break;
>>         }
>>
>> -       if (is_tiled(frame->fmt))
>> +       if (is_tiled(fmt))
>>                 cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
>>
>>  end_set:
>> diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.h b/drivers/media/platform/exynos-gsc/gsc-regs.h
>> index 4678f9a6..b03401dc 100644
>> --- a/drivers/media/platform/exynos-gsc/gsc-regs.h
>> +++ b/drivers/media/platform/exynos-gsc/gsc-regs.h
>> @@ -46,7 +46,7 @@
>>  #define GSC_IN_RGB_SD_WIDE             (0 << 14)
>>  #define GSC_IN_YUV422_1P_ORDER_MASK    (1 << 13)
>>  #define GSC_IN_YUV422_1P_ORDER_LSB_Y   (0 << 13)
>> -#define GSC_IN_YUV422_1P_OEDER_LSB_C   (1 << 13)
>> +#define GSC_IN_YUV422_1P_ORDER_LSB_C   (1 << 13)
>>  #define GSC_IN_CHROMA_ORDER_MASK       (1 << 12)
>>  #define GSC_IN_CHROMA_ORDER_CBCR       (0 << 12)
>>  #define GSC_IN_CHROMA_ORDER_CRCB       (1 << 12)
>> @@ -91,7 +91,7 @@
>>  #define GSC_OUT_RGB_SD_NARROW          (0 << 10)
>>  #define GSC_OUT_YUV422_1P_ORDER_MASK   (1 << 9)
>>  #define GSC_OUT_YUV422_1P_ORDER_LSB_Y  (0 << 9)
>> -#define GSC_OUT_YUV422_1P_OEDER_LSB_C  (1 << 9)
>> +#define GSC_OUT_YUV422_1P_ORDER_LSB_C  (1 << 9)
>>  #define GSC_OUT_CHROMA_ORDER_MASK      (1 << 8)
>>  #define GSC_OUT_CHROMA_ORDER_CBCR      (0 << 8)
>>  #define GSC_OUT_CHROMA_ORDER_CRCB      (1 << 8)
>> --
>> 1.9.0.279.gdc9e3eb
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index 9d0cc04d..c02addef 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -34,167 +34,185 @@  static const struct gsc_fmt gsc_formats[] = {
 	{
 		.name		= "RGB565",
 		.pixelformat	= V4L2_PIX_FMT_RGB565X,
-		.depth		= { 16 },
 		.color		= GSC_RGB,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 16 },
+		.sampling	= { { 1, 1 } },
 	}, {
 		.name		= "XRGB-8-8-8-8, 32 bpp",
 		.pixelformat	= V4L2_PIX_FMT_RGB32,
-		.depth		= { 32 },
 		.color		= GSC_RGB,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 32 },
+		.sampling	= { { 1, 1 } },
 	}, {
 		.name		= "YUV 4:2:2 packed, YCbYCr",
 		.pixelformat	= V4L2_PIX_FMT_YUYV,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 16 },
+		.sampling	= { { 1, 1 } },
 		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
 	}, {
 		.name		= "YUV 4:2:2 packed, CbYCrY",
 		.pixelformat	= V4L2_PIX_FMT_UYVY,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_C,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 16 },
+		.sampling	= { { 1, 1 } },
 		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
 	}, {
 		.name		= "YUV 4:2:2 packed, CrYCbY",
 		.pixelformat	= V4L2_PIX_FMT_VYUY,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_C,
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 16 },
+		.sampling	= { { 1, 1 } },
 		.mbus_code	= V4L2_MBUS_FMT_VYUY8_2X8,
 	}, {
 		.name		= "YUV 4:2:2 packed, YCrYCb",
 		.pixelformat	= V4L2_PIX_FMT_YVYU,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 16 },
+		.sampling	= { { 1, 1 } },
 		.mbus_code	= V4L2_MBUS_FMT_YVYU8_2X8,
 	}, {
 		.name		= "YUV 4:4:4 planar, YCbYCr",
 		.pixelformat	= V4L2_PIX_FMT_YUV32,
-		.depth		= { 32 },
 		.color		= GSC_YUV444,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 1,
+		.depth		= { 32 },
+		.sampling	= { { 1, 1 } },
 	}, {
 		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
 		.pixelformat	= V4L2_PIX_FMT_YUV422P,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 3,
+		.depth		= { 8, 8, 8 },
+		.sampling	= { { 1, 1 }, { 2, 1 }, { 2, 1 } },
 	}, {
 		.name		= "YUV 4:2:2 planar, Y/CbCr",
 		.pixelformat	= V4L2_PIX_FMT_NV16,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 2,
+		.depth		= { 8, 16 },
+		.sampling	= { { 1, 1 }, { 2, 1 } },
 	}, {
 		.name		= "YUV 4:2:2 planar, Y/CrCb",
 		.pixelformat	= V4L2_PIX_FMT_NV61,
-		.depth		= { 16 },
 		.color		= GSC_YUV422,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 2,
+		.depth		= { 8, 16 },
+		.sampling	= { { 1, 1 }, { 2, 1 } },
 	}, {
 		.name		= "YUV 4:2:0 planar, YCbCr",
 		.pixelformat	= V4L2_PIX_FMT_YUV420,
-		.depth		= { 12 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 3,
+		.depth		= { 8, 8, 8 },
+		.sampling	= { { 1, 1 }, { 2, 2 }, { 2, 2 } },
 	}, {
 		.name		= "YUV 4:2:0 planar, YCrCb",
 		.pixelformat	= V4L2_PIX_FMT_YVU420,
-		.depth		= { 12 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 3,
-
+		.depth		= { 8, 8, 8 },
+		.sampling	= { { 1, 1 }, { 2, 2 }, { 2, 2 } },
 	}, {
 		.name		= "YUV 4:2:0 planar, Y/CbCr",
 		.pixelformat	= V4L2_PIX_FMT_NV12,
-		.depth		= { 12 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 1,
 		.num_comp	= 2,
+		.depth		= { 8, 16 },
+		.sampling	= { { 1, 1 }, { 2, 2 } },
 	}, {
 		.name		= "YUV 4:2:0 planar, Y/CrCb",
 		.pixelformat	= V4L2_PIX_FMT_NV21,
-		.depth		= { 12 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CRCB,
 		.num_planes	= 1,
 		.num_comp	= 2,
+		.depth		= { 8, 16 },
+		.sampling	= { { 1, 1 }, { 2, 2 } },
 	}, {
-		.name		= "YUV 4:2:0 non-contig. 2p, Y/CbCr",
+		.name		= "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
 		.pixelformat	= V4L2_PIX_FMT_NV12M,
-		.depth		= { 8, 4 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 2,
 		.num_comp	= 2,
+		.depth		= { 8, 16 },
+		.sampling	= { { 1, 1 }, { 2, 2 } },
 	}, {
-		.name		= "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
+		.name		= "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
 		.pixelformat	= V4L2_PIX_FMT_YUV420M,
-		.depth		= { 8, 2, 2 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 3,
 		.num_comp	= 3,
+		.depth		= { 8, 8, 8 },
+		.sampling	= { { 1, 1 }, { 2, 2 }, { 2, 2 } },
 	}, {
-		.name		= "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb",
+		.name		= "YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb",
 		.pixelformat	= V4L2_PIX_FMT_YVU420M,
-		.depth		= { 8, 2, 2 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CRCB,
 		.num_planes	= 3,
 		.num_comp	= 3,
+		.depth		= { 8, 8, 8 },
+		.sampling	= { { 1, 1 }, { 2, 2 }, { 2, 2 } },
 	}, {
-		.name		= "YUV 4:2:0 n.c. 2p, Y/CbCr tiled",
+		.name		=
+			"YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
 		.pixelformat	= V4L2_PIX_FMT_NV12MT_16X16,
-		.depth		= { 8, 4 },
 		.color		= GSC_YUV420,
 		.yorder		= GSC_LSB_Y,
 		.corder		= GSC_CBCR,
 		.num_planes	= 2,
 		.num_comp	= 2,
-	}
+		.depth		= { 8, 16 },
+		.sampling	= { { 1, 1 }, { 2, 2 } },
+	},
 };
 
 const struct gsc_fmt *get_format(int index)
@@ -384,6 +402,14 @@  void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)
 			f_chk_addr, f_chk_len, s_chk_addr, s_chk_len);
 }
 
+static void get_format_size(__u32 width, __u32 height,
+			    const struct gsc_fmt *fmt, int plane,
+			    __u16 *bytesperline, __u32 *sizeimage) {
+	__u16 bpl = ((width * fmt->depth[plane]) / fmt->sampling[plane][0]) / 8;
+	*bytesperline = bpl;
+	*sizeimage = (height * bpl) / fmt->sampling[plane][0];
+}
+
 int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
 {
 	struct gsc_dev *gsc = ctx->gsc_dev;
@@ -448,14 +474,16 @@  int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
 	else /* SD */
 		pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-
+	/* V4L2 specifies for contiguous planar formats that bytesperline and
+	   sizeimage are set to values appropriate for the first plane. */
 	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;
+		get_format_size(pix_mp->width, pix_mp->height, fmt, i,
+				&pix_mp->plane_fmt[i].bytesperline,
+				&pix_mp->plane_fmt[i].sizeimage);
 
 		pr_debug("[%d]: bpl: %d, sizeimage: %d",
-				i, bpl, pix_mp->plane_fmt[i].sizeimage);
+				i, pix_mp->plane_fmt[i].bytesperline,
+				pix_mp->plane_fmt[i].sizeimage);
 	}
 
 	return 0;
@@ -465,26 +493,27 @@  int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
 {
 	struct gsc_frame *frame;
 	struct v4l2_pix_format_mplane *pix_mp;
+	const struct gsc_fmt *fmt;
 	int i;
 
 	frame = ctx_get_frame(ctx, f->type);
 	if (IS_ERR(frame))
 		return PTR_ERR(frame);
+	fmt = frame->fmt;
 
 	pix_mp = &f->fmt.pix_mp;
 
 	pix_mp->width		= frame->f_width;
 	pix_mp->height		= frame->f_height;
 	pix_mp->field		= V4L2_FIELD_NONE;
-	pix_mp->pixelformat	= frame->fmt->pixelformat;
+	pix_mp->pixelformat	= fmt->pixelformat;
 	pix_mp->colorspace	= V4L2_COLORSPACE_REC709;
-	pix_mp->num_planes	= frame->fmt->num_planes;
+	pix_mp->num_planes	= fmt->num_planes;
 
 	for (i = 0; i < pix_mp->num_planes; ++i) {
-		pix_mp->plane_fmt[i].bytesperline = (frame->f_width *
-			frame->fmt->depth[i]) / 8;
-		pix_mp->plane_fmt[i].sizeimage =
-			 pix_mp->plane_fmt[i].bytesperline * frame->f_height;
+		get_format_size(pix_mp->width, pix_mp->height, fmt, i,
+				&pix_mp->plane_fmt[i].bytesperline,
+				&pix_mp->plane_fmt[i].sizeimage);
 	}
 
 	return 0;
@@ -794,11 +823,12 @@  void gsc_ctrls_delete(struct gsc_ctx *ctx)
 	}
 }
 
-/* The color format (num_comp, num_planes) must be already configured. */
+/* The color format (num_planes, num_comp) must be already configured. */
 int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
 			struct gsc_frame *frame, struct gsc_addr *addr)
 {
 	int ret = 0;
+	const struct gsc_fmt *fmt = frame->fmt;
 	u32 pix_size;
 
 	if ((vb == NULL) || (frame == NULL))
@@ -810,46 +840,30 @@  int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
 		frame->fmt->num_planes, frame->fmt->num_comp, pix_size);
 
 	addr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
-
-	if (frame->fmt->num_planes == 1) {
-		switch (frame->fmt->num_comp) {
-		case 1:
-			addr->cb = 0;
-			addr->cr = 0;
-			break;
-		case 2:
-			/* decompose Y into Y/Cb */
-			addr->cb = (dma_addr_t)(addr->y + pix_size);
-			addr->cr = 0;
-			break;
-		case 3:
-			/* decompose Y into Y/Cb/Cr */
-			addr->cb = (dma_addr_t)(addr->y + pix_size);
-			if (GSC_YUV420 == frame->fmt->color)
-				addr->cr = (dma_addr_t)(addr->cb
-						+ (pix_size >> 2));
-			else /* 422 */
-				addr->cr = (dma_addr_t)(addr->cb
-						+ (pix_size >> 1));
-			break;
-		default:
-			pr_err("Invalid the number of color planes");
-			return -EINVAL;
+	addr->cb = 0;
+	addr->cr = 0;
+
+	if (fmt->num_planes == 1) {
+		if (fmt->num_comp >= 2) {
+			addr->cb = (dma_addr_t)(addr->y +
+				((pix_size * fmt->depth[0]) /
+				(fmt->sampling[0][0] *
+				 fmt->sampling[0][1]) / 8));
+		}
+		if (fmt->num_comp >= 3) {
+			addr->cr = (dma_addr_t)(addr->cb +
+				((pix_size * fmt->depth[1]) /
+				(fmt->sampling[1][0] *
+				 fmt->sampling[1][1]) / 8));
 		}
 	} else {
-		if (frame->fmt->num_planes >= 2)
+		if (fmt->num_comp >= 2)
 			addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
-
-		if (frame->fmt->num_planes == 3)
+		if (fmt->num_comp == 3)
 			addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
 	}
 
-	if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) ||
-		(frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) ||
-		(frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) ||
-		(frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) ||
-		(frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) ||
-		(frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M))
+	if (fmt->corder == GSC_CRCB)
 		swap(addr->cb, addr->cr);
 
 	pr_debug("ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index ef0a6564..8fb07e0d 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -106,27 +106,27 @@  enum gsc_yuv_fmt {
 	container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)
 /**
  * struct gsc_fmt - the driver's internal color format data
- * @mbus_code: Media Bus pixel code, -1 if not applicable
  * @name: format description
  * @pixelformat: the fourcc code for this format, 0 if not applicable
  * @yorder: Y/C order
  * @corder: Chrominance order control
  * @num_planes: number of physically non-contiguous data planes
- * @nr_comp: number of physically contiguous data planes
- * @depth: per plane driver's private 'number of bits per pixel'
- * @flags: flags indicating which operation mode format applies to
+ * @num_comp: number of physically contiguous data planes
+ * @depth: bit depth of each component
+ * @sampling: sampling frequency of each components, X and Y
+ * @mbus_code: Media Bus pixel code, -1 if not applicable
  */
 struct gsc_fmt {
-	enum v4l2_mbus_pixelcode mbus_code;
 	char	*name;
 	u32	pixelformat;
 	u32	color;
 	u32	yorder;
 	u32	corder;
-	u16	num_planes;
-	u16	num_comp;
+	u8	num_planes;
+	u8	num_comp;
 	u8	depth[VIDEO_MAX_PLANES];
-	u32	flags;
+	u8	sampling[VIDEO_MAX_PLANES][2];
+	enum v4l2_mbus_pixelcode mbus_code;
 };
 
 /**
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c
index e22d147a..a8d6c90b 100644
--- a/drivers/media/platform/exynos-gsc/gsc-regs.c
+++ b/drivers/media/platform/exynos-gsc/gsc-regs.c
@@ -167,6 +167,7 @@  void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
 {
 	struct gsc_dev *dev = ctx->gsc_dev;
 	struct gsc_frame *frame = &ctx->s_frame;
+	const struct gsc_fmt *fmt = frame->fmt;
 	u32 i, depth = 0;
 	u32 cfg;
 
@@ -176,21 +177,22 @@  void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
 		 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
 	writel(cfg, dev->regs + GSC_IN_CON);
 
-	if (is_rgb(frame->fmt->color)) {
+	if (is_rgb(fmt->color)) {
 		gsc_hw_set_in_image_rgb(ctx);
 		return;
 	}
-	for (i = 0; i < frame->fmt->num_planes; i++)
-		depth += frame->fmt->depth[i];
+	for (i = 0; i < fmt->num_comp; i++)
+		depth += fmt->depth[i] /
+			(fmt->sampling[i][0] * fmt->sampling[i][1]);
 
-	switch (frame->fmt->num_comp) {
+	switch (fmt->num_comp) {
 	case 1:
 		cfg |= GSC_IN_YUV422_1P;
-		if (frame->fmt->yorder == GSC_LSB_Y)
+		if (fmt->yorder == GSC_LSB_Y)
 			cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
 		else
-			cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
-		if (frame->fmt->corder == GSC_CBCR)
+			cfg |= GSC_IN_YUV422_1P_ORDER_LSB_C;
+		if (fmt->corder == GSC_CBCR)
 			cfg |= GSC_IN_CHROMA_ORDER_CBCR;
 		else
 			cfg |= GSC_IN_CHROMA_ORDER_CRCB;
@@ -200,7 +202,7 @@  void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
 			cfg |= GSC_IN_YUV420_2P;
 		else
 			cfg |= GSC_IN_YUV422_2P;
-		if (frame->fmt->corder == GSC_CBCR)
+		if (fmt->corder == GSC_CBCR)
 			cfg |= GSC_IN_CHROMA_ORDER_CBCR;
 		else
 			cfg |= GSC_IN_CHROMA_ORDER_CRCB;
@@ -213,7 +215,7 @@  void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
 		break;
 	}
 
-	if (is_tiled(frame->fmt))
+	if (is_tiled(fmt))
 		cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
 
 	writel(cfg, dev->regs + GSC_IN_CON);
@@ -287,6 +289,7 @@  void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
 {
 	struct gsc_dev *dev = ctx->gsc_dev;
 	struct gsc_frame *frame = &ctx->d_frame;
+	const struct gsc_fmt *fmt = frame->fmt;
 	u32 i, depth = 0;
 	u32 cfg;
 
@@ -296,7 +299,7 @@  void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
 		 GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
 	writel(cfg, dev->regs + GSC_OUT_CON);
 
-	if (is_rgb(frame->fmt->color)) {
+	if (is_rgb(fmt->color)) {
 		gsc_hw_set_out_image_rgb(ctx);
 		return;
 	}
@@ -306,17 +309,18 @@  void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
 		goto end_set;
 	}
 
-	for (i = 0; i < frame->fmt->num_planes; i++)
-		depth += frame->fmt->depth[i];
+	for (i = 0; i < fmt->num_comp; i++)
+		depth += fmt->depth[i] /
+			(fmt->sampling[i][0] * fmt->sampling[i][1]);
 
-	switch (frame->fmt->num_comp) {
+	switch (fmt->num_comp) {
 	case 1:
 		cfg |= GSC_OUT_YUV422_1P;
-		if (frame->fmt->yorder == GSC_LSB_Y)
+		if (fmt->yorder == GSC_LSB_Y)
 			cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
 		else
-			cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
-		if (frame->fmt->corder == GSC_CBCR)
+			cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_C;
+		if (fmt->corder == GSC_CBCR)
 			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
 		else
 			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
@@ -326,7 +330,7 @@  void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
 			cfg |= GSC_OUT_YUV420_2P;
 		else
 			cfg |= GSC_OUT_YUV422_2P;
-		if (frame->fmt->corder == GSC_CBCR)
+		if (fmt->corder == GSC_CBCR)
 			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
 		else
 			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
@@ -336,7 +340,7 @@  void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
 		break;
 	}
 
-	if (is_tiled(frame->fmt))
+	if (is_tiled(fmt))
 		cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
 
 end_set:
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.h b/drivers/media/platform/exynos-gsc/gsc-regs.h
index 4678f9a6..b03401dc 100644
--- a/drivers/media/platform/exynos-gsc/gsc-regs.h
+++ b/drivers/media/platform/exynos-gsc/gsc-regs.h
@@ -46,7 +46,7 @@ 
 #define GSC_IN_RGB_SD_WIDE		(0 << 14)
 #define GSC_IN_YUV422_1P_ORDER_MASK	(1 << 13)
 #define GSC_IN_YUV422_1P_ORDER_LSB_Y	(0 << 13)
-#define GSC_IN_YUV422_1P_OEDER_LSB_C	(1 << 13)
+#define GSC_IN_YUV422_1P_ORDER_LSB_C	(1 << 13)
 #define GSC_IN_CHROMA_ORDER_MASK	(1 << 12)
 #define GSC_IN_CHROMA_ORDER_CBCR	(0 << 12)
 #define GSC_IN_CHROMA_ORDER_CRCB	(1 << 12)
@@ -91,7 +91,7 @@ 
 #define GSC_OUT_RGB_SD_NARROW		(0 << 10)
 #define GSC_OUT_YUV422_1P_ORDER_MASK	(1 << 9)
 #define GSC_OUT_YUV422_1P_ORDER_LSB_Y	(0 << 9)
-#define GSC_OUT_YUV422_1P_OEDER_LSB_C	(1 << 9)
+#define GSC_OUT_YUV422_1P_ORDER_LSB_C	(1 << 9)
 #define GSC_OUT_CHROMA_ORDER_MASK	(1 << 8)
 #define GSC_OUT_CHROMA_ORDER_CBCR	(0 << 8)
 #define GSC_OUT_CHROMA_ORDER_CRCB	(1 << 8)