From ab7d3f5826c55ad23101327eab435660caa83436 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 14 Dec 2017 13:46:20 +0100 Subject: [PATCH] drm/tegra: Implement zpos property Implement the standard zpos property for planes on Tegra124 and later. Earlier generations have a different blending unit that needs different programming. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 94 ++++++++++++++++++++++++----------- drivers/gpu/drm/tegra/dc.h | 2 + drivers/gpu/drm/tegra/drm.c | 25 +++++++++- drivers/gpu/drm/tegra/hub.c | 5 +- drivers/gpu/drm/tegra/plane.h | 1 - 5 files changed, 95 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index cd84d8514d48..d118094a96c1 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -152,6 +152,55 @@ static inline u32 compute_initial_dda(unsigned int in) return dfixed_frac(inf); } +static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) +{ + /* + * Disable blending and assume Window A is the bottom-most window, + * Window C is the top-most window and Window B is in the middle. + */ + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_NOKEY); + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_1WIN); + + switch (plane->index) { + case 0: + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_X); + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); + break; + + case 1: + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); + break; + + case 2: + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_Y); + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_3WIN_XY); + break; + } +} + +static void tegra_plane_setup_blending(struct tegra_plane *plane, + const struct tegra_dc_window *window) +{ + u32 value; + + value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 | + BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC | + BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; + tegra_plane_writel(plane, value, DC_WIN_BLEND_MATCH_SELECT); + + value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 | + BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC | + BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; + tegra_plane_writel(plane, value, DC_WIN_BLEND_NOMATCH_SELECT); + + value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - window->zpos); + tegra_plane_writel(plane, value, DC_WIN_BLEND_LAYER_CONTROL); +} + static void tegra_dc_setup_window(struct tegra_plane *plane, const struct tegra_dc_window *window) { @@ -291,32 +340,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); - /* - * Disable blending and assume Window A is the bottom-most window, - * Window C is the top-most window and Window B is in the middle. - */ - tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_NOKEY); - tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_1WIN); - - switch (plane->index) { - case 0: - tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_X); - tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); - tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); - break; - - case 1: - tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); - tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); - tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); - break; - - case 2: - tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); - tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_Y); - tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_3WIN_XY); - break; - } + if (dc->soc->supports_blending) + tegra_plane_setup_blending(plane, window); + else + tegra_plane_setup_blending_legacy(plane); } static const u32 tegra20_primary_formats[] = { @@ -467,6 +494,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, window.bottom_up = tegra_fb_is_bottom_up(fb); /* copy from state */ + window.zpos = plane->state->normalized_zpos; window.tiling = state->tiling; window.format = state->format; window.swap = state->swap; @@ -523,7 +551,6 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, /* Always use window A as primary window */ plane->offset = 0xa00; plane->index = 0; - plane->depth = 255; plane->dc = dc; num_formats = dc->soc->num_primary_formats; @@ -539,6 +566,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); + if (dc->soc->supports_blending) + drm_plane_create_zpos_property(&plane->base, 0, 0, 255); + return &plane->base; } @@ -786,7 +816,6 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, plane->offset = 0xa00 + 0x200 * index; plane->index = index; - plane->depth = 0; plane->dc = dc; num_formats = dc->soc->num_overlay_formats; @@ -803,6 +832,9 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); + if (dc->soc->supports_blending) + drm_plane_create_zpos_property(&plane->base, 0, 0, 255); + return &plane->base; } @@ -1834,6 +1866,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .supports_blending = false, .pitch_align = 8, .has_powergate = false, .broken_reset = true, @@ -1849,6 +1882,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .supports_blending = false, .pitch_align = 8, .has_powergate = false, .broken_reset = false, @@ -1864,6 +1898,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .supports_blending = false, .pitch_align = 64, .has_powergate = true, .broken_reset = false, @@ -1879,6 +1914,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_blending = true, .pitch_align = 64, .has_powergate = true, .broken_reset = false, @@ -1894,6 +1930,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_blending = true, .pitch_align = 64, .has_powergate = true, .broken_reset = false, @@ -1943,6 +1980,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .supports_blending = true, .pitch_align = 64, .has_powergate = false, .broken_reset = false, diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 7dd02f07244f..f4568e054a63 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -55,6 +55,7 @@ struct tegra_dc_soc_info { bool supports_interlacing; bool supports_cursor; bool supports_block_linear; + bool supports_blending; unsigned int pitch_align; bool has_powergate; bool broken_reset; @@ -136,6 +137,7 @@ struct tegra_dc_window { unsigned int bits_per_pixel; unsigned int stride[2]; unsigned long base[3]; + unsigned int zpos; bool bottom_up; struct tegra_bo_tiling tiling; diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 2fa1b48e14d2..52468f669277 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -33,6 +33,29 @@ struct tegra_drm_file { struct mutex lock; }; +static int tegra_atomic_check(struct drm_device *drm, + struct drm_atomic_state *state) +{ + int err; + + err = drm_atomic_helper_check_modeset(drm, state); + if (err < 0) + return err; + + err = drm_atomic_normalize_zpos(drm, state); + if (err < 0) + return err; + + err = drm_atomic_helper_check_planes(drm, state); + if (err < 0) + return err; + + if (state->legacy_cursor_update) + state->async_update = !drm_atomic_helper_async_check(drm, state); + + return 0; +} + static struct drm_atomic_state * tegra_atomic_state_alloc(struct drm_device *drm) { @@ -67,7 +90,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = { #ifdef CONFIG_DRM_FBDEV_EMULATION .output_poll_changed = tegra_fb_output_poll_changed, #endif - .atomic_check = drm_atomic_helper_check, + .atomic_check = tegra_atomic_check, .atomic_commit = drm_atomic_helper_commit, .atomic_state_alloc = tegra_atomic_state_alloc, .atomic_state_clear = tegra_atomic_state_clear, diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index 63541dbd864d..90bcf24b1523 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -399,6 +399,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, { struct tegra_plane_state *state = to_tegra_plane_state(plane->state); struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); + unsigned int zpos = plane->state->normalized_zpos; struct drm_framebuffer *fb = plane->state->fb; struct tegra_plane *p = to_tegra_plane(plane); struct tegra_bo *bo; @@ -431,7 +432,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT); - value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(p->depth); + value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - zpos); tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL); /* bypass scaling */ @@ -536,7 +537,6 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, plane->base.offset = 0x0a00 + 0x0300 * index; plane->base.index = index; - plane->base.depth = 0; plane->wgrp = &hub->wgrps[wgrp]; plane->wgrp->parent = dc->dev; @@ -555,6 +555,7 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, } drm_plane_helper_add(p, &tegra_shared_plane_helper_funcs); + drm_plane_create_zpos_property(p, 0, 0, 255); return p; } diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h index 13b900d777e8..dca66cb95d25 100644 --- a/drivers/gpu/drm/tegra/plane.h +++ b/drivers/gpu/drm/tegra/plane.h @@ -19,7 +19,6 @@ struct tegra_plane { struct tegra_dc *dc; unsigned int offset; unsigned int index; - unsigned int depth; }; struct tegra_cursor {