summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/tegra/dc.c2
-rw-r--r--drivers/gpu/drm/tegra/dc.h7
-rw-r--r--drivers/gpu/drm/tegra/hub.c52
-rw-r--r--drivers/gpu/drm/tegra/plane.c23
-rw-r--r--drivers/gpu/drm/tegra/plane.h3
5 files changed, 78 insertions, 9 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index f9120dc24682..c5ea88a686d1 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -348,7 +348,7 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
* For YUV planar modes, the number of bytes per pixel takes into
* account only the luma component and therefore is 1.
*/
- yuv = tegra_plane_format_is_yuv(window->format, &planar);
+ yuv = tegra_plane_format_is_yuv(window->format, &planar, NULL);
if (!yuv)
bpp = window->bits_per_pixel / 8;
else
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 29f19c3c6149..455c3fdef8dc 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -696,6 +696,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#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)
@@ -720,6 +723,10 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#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)
diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c
index bfae8a02f55b..94e1ccfb6235 100644
--- a/drivers/gpu/drm/tegra/hub.c
+++ b/drivers/gpu/drm/tegra/hub.c
@@ -454,7 +454,9 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
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;
@@ -473,6 +475,8 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
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);
@@ -501,8 +505,6 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
/* 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
@@ -510,9 +512,12 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
* 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);
@@ -535,7 +540,44 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
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) |
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 2e11b4b1f702..2e65b4075ce6 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -375,7 +375,20 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
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:
@@ -383,6 +396,9 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar)
if (planar)
*planar = false;
+ if (bpc)
+ *bpc = 8;
+
return true;
case WIN_COLOR_DEPTH_YCbCr420P:
@@ -396,6 +412,9 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar)
if (planar)
*planar = true;
+ if (bpc)
+ *bpc = 8;
+
return true;
}
@@ -421,7 +440,7 @@ static bool __drm_format_has_alpha(u32 format)
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;
}
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index c691dd79b27b..1785c1559c0c 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -74,7 +74,8 @@ int tegra_plane_state_add(struct tegra_plane *plane,
struct drm_plane_state *state);
int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);
-bool tegra_plane_format_is_yuv(unsigned int format, bool *planar);
+bool tegra_plane_format_is_indexed(unsigned int format);
+bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc);
int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
struct tegra_plane_state *state);