media: gpu: ipu-v3: Add planar support to interlaced scan
authorSteve Longerbeam <slongerbeam@gmail.com>
Wed, 9 Jan 2019 18:30:06 +0000 (13:30 -0500)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Wed, 16 Jan 2019 19:12:20 +0000 (14:12 -0500)
To support interlaced scan with planar formats, cpmem SLUV must
be programmed with the correct chroma line stride. For full and
partial planar 4:2:2 (YUV422P, NV16), chroma line stride must
be doubled. For full and partial planar 4:2:0 (YUV420, YVU420, NV12),
chroma line stride must _not_ be doubled, since a single chroma line
is shared by two luma lines.

Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/gpu/ipu-v3/ipu-cpmem.c
drivers/staging/media/imx/imx-ic-prpencvf.c
drivers/staging/media/imx/imx-media-csi.c
include/video/imx-ipu-v3.h

index 163fadb..d047a68 100644 (file)
@@ -277,9 +277,10 @@ void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
 
-void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
+void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
+                              u32 pixelformat)
 {
-       u32 ilo, sly;
+       u32 ilo, sly, sluv;
 
        if (stride < 0) {
                stride = -stride;
@@ -290,9 +291,30 @@ void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
 
        sly = (stride * 2) - 1;
 
+       switch (pixelformat) {
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_YVU420:
+               sluv = stride / 2 - 1;
+               break;
+       case V4L2_PIX_FMT_NV12:
+               sluv = stride - 1;
+               break;
+       case V4L2_PIX_FMT_YUV422P:
+               sluv = stride - 1;
+               break;
+       case V4L2_PIX_FMT_NV16:
+               sluv = stride * 2 - 1;
+               break;
+       default:
+               sluv = 0;
+               break;
+       }
+
        ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
        ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
        ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
+       if (sluv)
+               ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
 };
 EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
 
index 28f41ca..af72248 100644 (file)
@@ -412,7 +412,8 @@ static int prp_setup_channel(struct prp_priv *priv,
        if (image.pix.field == V4L2_FIELD_NONE &&
            V4L2_FIELD_HAS_BOTH(infmt->field) &&
            channel == priv->out_ch)
-               ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline);
+               ipu_cpmem_interlaced_scan(channel, image.pix.bytesperline,
+                                         image.pix.pixelformat);
 
        ret = ipu_ic_task_idma_init(priv->ic, channel,
                                    image.pix.width, image.pix.height,
index c2a8d9c..da48083 100644 (file)
@@ -512,7 +512,8 @@ static int csi_idmac_setup_channel(struct csi_priv *priv)
        if (image.pix.field == V4L2_FIELD_NONE &&
            V4L2_FIELD_HAS_BOTH(infmt->field))
                ipu_cpmem_interlaced_scan(priv->idmac_ch,
-                                         image.pix.bytesperline);
+                                         image.pix.bytesperline,
+                                         image.pix.pixelformat);
 
        ipu_idmac_set_double_buffer(priv->idmac_ch, true);
 
index bbc8481..c887f4b 100644 (file)
@@ -258,7 +258,8 @@ void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride);
 void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch);
 void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf);
 void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off);
-void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride);
+void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
+                              u32 pixelformat);
 void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id);
 int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch);
 void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize);