diff options
author | Thierry Reding <treding@nvidia.com> | 2017-12-14 15:46:20 +0300 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2017-12-21 16:52:35 +0300 |
commit | ab7d3f5826c55ad23101327eab435660caa83436 (patch) | |
tree | 8d8c77f5c2f8c727bebcd0ba2085a91369b2dee4 /drivers/gpu/drm/tegra/dc.c | |
parent | 363541e8eeed16fdf696252008ddee823730f82c (diff) | |
download | linux-ab7d3f5826c55ad23101327eab435660caa83436.tar.xz |
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 <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/dc.c')
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 94 |
1 files changed, 66 insertions, 28 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, |