#define DC_WINBUF_START_ADDR_HI                        0x80d
 
+#define DC_WINBUF_START_ADDR_HI_U              0x80f
+#define DC_WINBUF_START_ADDR_HI_V              0x811
+
 #define DC_WINBUF_CDE_CONTROL                  0x82f
 #define  ENABLE_SURFACE (1 << 0)
 
 #define DC_WIN_PLANAR_STORAGE                  0x709
 #define PITCH(x) (((x) >> 6) & 0x1fff)
 
+#define DC_WIN_PLANAR_STORAGE_UV               0x70a
+#define  PITCH_U(x) ((((x) >> 6) & 0x1fff) <<  0)
+#define  PITCH_V(x) ((((x) >> 6) & 0x1fff) << 16)
+
 #define DC_WIN_SET_PARAMS                      0x70d
 #define  CLAMP_BEFORE_BLEND (1 << 15)
 #define  DEGAMMA_NONE (0 << 13)
 
        unsigned int zpos = new_state->normalized_zpos;
        struct drm_framebuffer *fb = new_state->fb;
        struct tegra_plane *p = to_tegra_plane(plane);
-       dma_addr_t base;
+       dma_addr_t base, addr_flag = 0;
+       unsigned int bpc;
+       bool yuv, planar;
        u32 value;
        int err;
 
                return;
        }
 
+       yuv = tegra_plane_format_is_yuv(tegra_plane_state->format, &planar, &bpc);
+
        tegra_dc_assign_shared_plane(dc, p);
 
        tegra_plane_writel(p, VCOUNTER, DC_WIN_CORE_ACT_CONTROL);
        /* disable compression */
        tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL);
 
-       base = tegra_plane_state->iova[0] + fb->offsets[0];
-
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        /*
         * Physical address bit 39 in Tegra194 is used as a switch for special
         * dGPU sector layout.
         */
        if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU)
-               base |= BIT_ULL(39);
+               addr_flag = BIT_ULL(39);
 #endif
 
+       base = tegra_plane_state->iova[0] + fb->offsets[0];
+       base |= addr_flag;
+
        tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);
        tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);
 
        value = PITCH(fb->pitches[0]);
        tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE);
 
-       value = CLAMP_BEFORE_BLEND | DEGAMMA_SRGB | INPUT_RANGE_FULL;
+       if (yuv && planar) {
+               base = tegra_plane_state->iova[1] + fb->offsets[1];
+               base |= addr_flag;
+
+               tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_U);
+               tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_U);
+
+               base = tegra_plane_state->iova[2] + fb->offsets[2];
+               base |= addr_flag;
+
+               tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_V);
+               tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_V);
+
+               value = PITCH_U(fb->pitches[2]) | PITCH_V(fb->pitches[2]);
+               tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE_UV);
+       } else {
+               tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_U);
+               tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_HI_U);
+               tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_V);
+               tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_HI_V);
+               tegra_plane_writel(p, 0, DC_WIN_PLANAR_STORAGE_UV);
+       }
+
+       value = CLAMP_BEFORE_BLEND | INPUT_RANGE_FULL;
+
+       if (yuv) {
+               if (bpc < 12)
+                       value |= DEGAMMA_YUV8_10;
+               else
+                       value |= DEGAMMA_YUV12;
+
+               /* XXX parameterize */
+               value |= COLOR_SPACE_YUV_2020;
+       } else {
+               if (!tegra_plane_format_is_indexed(tegra_plane_state->format))
+                       value |= DEGAMMA_SRGB;
+       }
+
        tegra_plane_writel(p, value, DC_WIN_SET_PARAMS);
 
        value = OFFSET_X(new_state->src_y >> 16) |
 
        return 0;
 }
 
-bool tegra_plane_format_is_yuv(unsigned int format, bool *planar)
+bool tegra_plane_format_is_indexed(unsigned int format)
+{
+       switch (format) {
+       case WIN_COLOR_DEPTH_P1:
+       case WIN_COLOR_DEPTH_P2:
+       case WIN_COLOR_DEPTH_P4:
+       case WIN_COLOR_DEPTH_P8:
+               return true;
+       }
+
+       return false;
+}
+
+bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc)
 {
        switch (format) {
        case WIN_COLOR_DEPTH_YCbCr422:
                if (planar)
                        *planar = false;
 
+               if (bpc)
+                       *bpc = 8;
+
                return true;
 
        case WIN_COLOR_DEPTH_YCbCr420P:
                if (planar)
                        *planar = true;
 
+               if (bpc)
+                       *bpc = 8;
+
                return true;
        }
 
 static int tegra_plane_format_get_alpha(unsigned int opaque,
                                        unsigned int *alpha)
 {
-       if (tegra_plane_format_is_yuv(opaque, NULL)) {
+       if (tegra_plane_format_is_yuv(opaque, NULL, NULL)) {
                *alpha = opaque;
                return 0;
        }