YVU420 requires swapping addresses of U and V planes.

Signed-off-by: Andrzej Hajda <a.ha...@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_gsc.c | 52 ++++++++++++++++++-------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c 
b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index c7a97d053ab1..f75739e8bc55 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -535,10 +535,8 @@ static void gsc_src_set_fmt(struct gsc_context *ctx, u32 
fmt, bool tiled)
                cfg |= GSC_IN_YUV422_3P;
                break;
        case DRM_FORMAT_YUV420:
-               cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P);
-               break;
        case DRM_FORMAT_YVU420:
-               cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_3P);
+               cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P);
                break;
        case DRM_FORMAT_NV12:
                cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P);
@@ -658,13 +656,32 @@ static void gsc_src_set_buf_seq(struct gsc_context *ctx, 
u32 buf_id,
        gsc_write(cfg, GSC_IN_BASE_ADDR_CR_MASK);
 }
 
+/* returns HW plane index based on pixel format */
+static int gsc_hw_plane_index(int index, u32 format)
+{
+       switch (format) {
+       case DRM_FORMAT_YVU420:
+               switch (index) {
+               case 0: return 0;
+               case 1: return 2;
+               case 2: return 1;
+               }
+       default:
+               return index;
+       }
+}
+
 static void gsc_src_set_addr(struct gsc_context *ctx, u32 buf_id,
                            struct exynos_drm_ipp_buffer *buf)
 {
+       int idx;
+
        /* address register set */
        gsc_write(buf->dma_addr[0], GSC_IN_BASE_ADDR_Y(buf_id));
-       gsc_write(buf->dma_addr[1], GSC_IN_BASE_ADDR_CB(buf_id));
-       gsc_write(buf->dma_addr[2], GSC_IN_BASE_ADDR_CR(buf_id));
+       idx = gsc_hw_plane_index(1, buf->format->format);
+       gsc_write(buf->dma_addr[idx], GSC_IN_BASE_ADDR_CB(buf_id));
+       idx = gsc_hw_plane_index(2, buf->format->format);
+       gsc_write(buf->dma_addr[idx], GSC_IN_BASE_ADDR_CR(buf_id));
 
        gsc_src_set_buf_seq(ctx, buf_id, true);
 }
@@ -722,10 +739,8 @@ static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 
fmt, bool tiled)
                cfg |= GSC_OUT_YUV422_3P;
                break;
        case DRM_FORMAT_YUV420:
-               cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P);
-               break;
        case DRM_FORMAT_YVU420:
-               cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_3P);
+               cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P);
                break;
        case DRM_FORMAT_NV12:
                cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P);
@@ -985,10 +1000,13 @@ static void gsc_dst_set_buf_seq(struct gsc_context *ctx, 
u32 buf_id,
 static void gsc_dst_set_addr(struct gsc_context *ctx,
                             u32 buf_id, struct exynos_drm_ipp_buffer *buf)
 {
-       /* address register set */
+       int i;
+
        gsc_write(buf->dma_addr[0], GSC_OUT_BASE_ADDR_Y(buf_id));
-       gsc_write(buf->dma_addr[1], GSC_OUT_BASE_ADDR_CB(buf_id));
-       gsc_write(buf->dma_addr[2], GSC_OUT_BASE_ADDR_CR(buf_id));
+       i = gsc_hw_plane_index(1, buf->format->format);
+       gsc_write(buf->dma_addr[i], GSC_OUT_BASE_ADDR_CB(buf_id));
+       i = gsc_hw_plane_index(2, buf->format->format);
+       gsc_write(buf->dma_addr[i], GSC_OUT_BASE_ADDR_CR(buf_id));
 
        gsc_dst_set_buf_seq(ctx, buf_id, true);
 }
@@ -1238,10 +1256,14 @@ static void gsc_update_plane(struct exynos_drm_plane 
*plane)
        gsc_write(BIT(16) * cropped_w / scaled_w, GSC_MAIN_H_RATIO);
        gsc_write(BIT(16) * cropped_h / scaled_h, GSC_MAIN_V_RATIO);
        gsc_write(exynos_drm_fb_dma_addr(fb, 0), GSC_IN_BASE_ADDR_Y(0));
-       if (fb->format->num_planes > 1)
-               gsc_write(exynos_drm_fb_dma_addr(fb, 1), 
GSC_IN_BASE_ADDR_CB(0));
-       if (fb->format->num_planes > 2)
-               gsc_write(exynos_drm_fb_dma_addr(fb, 2), 
GSC_IN_BASE_ADDR_CR(0));
+       if (fb->format->num_planes > 1) {
+               i = gsc_hw_plane_index(1, fb->format->format);
+               gsc_write(exynos_drm_fb_dma_addr(fb, i), 
GSC_IN_BASE_ADDR_CB(0));
+       }
+       if (fb->format->num_planes > 2) {
+               i = gsc_hw_plane_index(2, fb->format->format);
+               gsc_write(exynos_drm_fb_dma_addr(fb, i), 
GSC_IN_BASE_ADDR_CR(0));
+       }
        gsc_src_set_fmt(ctx, fb->format->format, fb->modifier);
        gsc_write(scaled_w * scaled_h, GSC_SMART_IF_PIXEL_NUM);
        gsc_write(GSC_ENABLE_SFR_UPDATE | GSC_ENABLE_ON, GSC_ENABLE);
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to