Commit ab7d3f58 authored by Thierry Reding's avatar Thierry Reding

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: default avatarThierry Reding <treding@nvidia.com>
parent 363541e8
...@@ -152,6 +152,55 @@ static inline u32 compute_initial_dda(unsigned int in) ...@@ -152,6 +152,55 @@ static inline u32 compute_initial_dda(unsigned int in)
return dfixed_frac(inf); 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, static void tegra_dc_setup_window(struct tegra_plane *plane,
const struct tegra_dc_window *window) const struct tegra_dc_window *window)
{ {
...@@ -291,32 +340,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, ...@@ -291,32 +340,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS);
/* if (dc->soc->supports_blending)
* Disable blending and assume Window A is the bottom-most window, tegra_plane_setup_blending(plane, window);
* Window C is the top-most window and Window B is in the middle. else
*/ tegra_plane_setup_blending_legacy(plane);
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 const u32 tegra20_primary_formats[] = { static const u32 tegra20_primary_formats[] = {
...@@ -467,6 +494,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, ...@@ -467,6 +494,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
window.bottom_up = tegra_fb_is_bottom_up(fb); window.bottom_up = tegra_fb_is_bottom_up(fb);
/* copy from state */ /* copy from state */
window.zpos = plane->state->normalized_zpos;
window.tiling = state->tiling; window.tiling = state->tiling;
window.format = state->format; window.format = state->format;
window.swap = state->swap; window.swap = state->swap;
...@@ -523,7 +551,6 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, ...@@ -523,7 +551,6 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
/* Always use window A as primary window */ /* Always use window A as primary window */
plane->offset = 0xa00; plane->offset = 0xa00;
plane->index = 0; plane->index = 0;
plane->depth = 255;
plane->dc = dc; plane->dc = dc;
num_formats = dc->soc->num_primary_formats; num_formats = dc->soc->num_primary_formats;
...@@ -539,6 +566,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, ...@@ -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); 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; return &plane->base;
} }
...@@ -786,7 +816,6 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, ...@@ -786,7 +816,6 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
plane->offset = 0xa00 + 0x200 * index; plane->offset = 0xa00 + 0x200 * index;
plane->index = index; plane->index = index;
plane->depth = 0;
plane->dc = dc; plane->dc = dc;
num_formats = dc->soc->num_overlay_formats; num_formats = dc->soc->num_overlay_formats;
...@@ -803,6 +832,9 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, ...@@ -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); 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; return &plane->base;
} }
...@@ -1834,6 +1866,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { ...@@ -1834,6 +1866,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.supports_interlacing = false, .supports_interlacing = false,
.supports_cursor = false, .supports_cursor = false,
.supports_block_linear = false, .supports_block_linear = false,
.supports_blending = false,
.pitch_align = 8, .pitch_align = 8,
.has_powergate = false, .has_powergate = false,
.broken_reset = true, .broken_reset = true,
...@@ -1849,6 +1882,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = { ...@@ -1849,6 +1882,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.supports_interlacing = false, .supports_interlacing = false,
.supports_cursor = false, .supports_cursor = false,
.supports_block_linear = false, .supports_block_linear = false,
.supports_blending = false,
.pitch_align = 8, .pitch_align = 8,
.has_powergate = false, .has_powergate = false,
.broken_reset = false, .broken_reset = false,
...@@ -1864,6 +1898,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = { ...@@ -1864,6 +1898,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
.supports_interlacing = false, .supports_interlacing = false,
.supports_cursor = false, .supports_cursor = false,
.supports_block_linear = false, .supports_block_linear = false,
.supports_blending = false,
.pitch_align = 64, .pitch_align = 64,
.has_powergate = true, .has_powergate = true,
.broken_reset = false, .broken_reset = false,
...@@ -1879,6 +1914,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { ...@@ -1879,6 +1914,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.supports_interlacing = true, .supports_interlacing = true,
.supports_cursor = true, .supports_cursor = true,
.supports_block_linear = true, .supports_block_linear = true,
.supports_blending = true,
.pitch_align = 64, .pitch_align = 64,
.has_powergate = true, .has_powergate = true,
.broken_reset = false, .broken_reset = false,
...@@ -1894,6 +1930,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = { ...@@ -1894,6 +1930,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
.supports_interlacing = true, .supports_interlacing = true,
.supports_cursor = true, .supports_cursor = true,
.supports_block_linear = true, .supports_block_linear = true,
.supports_blending = true,
.pitch_align = 64, .pitch_align = 64,
.has_powergate = true, .has_powergate = true,
.broken_reset = false, .broken_reset = false,
...@@ -1943,6 +1980,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = { ...@@ -1943,6 +1980,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
.supports_interlacing = true, .supports_interlacing = true,
.supports_cursor = true, .supports_cursor = true,
.supports_block_linear = true, .supports_block_linear = true,
.supports_blending = true,
.pitch_align = 64, .pitch_align = 64,
.has_powergate = false, .has_powergate = false,
.broken_reset = false, .broken_reset = false,
......
...@@ -55,6 +55,7 @@ struct tegra_dc_soc_info { ...@@ -55,6 +55,7 @@ struct tegra_dc_soc_info {
bool supports_interlacing; bool supports_interlacing;
bool supports_cursor; bool supports_cursor;
bool supports_block_linear; bool supports_block_linear;
bool supports_blending;
unsigned int pitch_align; unsigned int pitch_align;
bool has_powergate; bool has_powergate;
bool broken_reset; bool broken_reset;
...@@ -136,6 +137,7 @@ struct tegra_dc_window { ...@@ -136,6 +137,7 @@ struct tegra_dc_window {
unsigned int bits_per_pixel; unsigned int bits_per_pixel;
unsigned int stride[2]; unsigned int stride[2];
unsigned long base[3]; unsigned long base[3];
unsigned int zpos;
bool bottom_up; bool bottom_up;
struct tegra_bo_tiling tiling; struct tegra_bo_tiling tiling;
......
...@@ -33,6 +33,29 @@ struct tegra_drm_file { ...@@ -33,6 +33,29 @@ struct tegra_drm_file {
struct mutex lock; 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 * static struct drm_atomic_state *
tegra_atomic_state_alloc(struct drm_device *drm) tegra_atomic_state_alloc(struct drm_device *drm)
{ {
...@@ -67,7 +90,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = { ...@@ -67,7 +90,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
#ifdef CONFIG_DRM_FBDEV_EMULATION #ifdef CONFIG_DRM_FBDEV_EMULATION
.output_poll_changed = tegra_fb_output_poll_changed, .output_poll_changed = tegra_fb_output_poll_changed,
#endif #endif
.atomic_check = drm_atomic_helper_check, .atomic_check = tegra_atomic_check,
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
.atomic_state_alloc = tegra_atomic_state_alloc, .atomic_state_alloc = tegra_atomic_state_alloc,
.atomic_state_clear = tegra_atomic_state_clear, .atomic_state_clear = tegra_atomic_state_clear,
......
...@@ -399,6 +399,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, ...@@ -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_plane_state *state = to_tegra_plane_state(plane->state);
struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); 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 drm_framebuffer *fb = plane->state->fb;
struct tegra_plane *p = to_tegra_plane(plane); struct tegra_plane *p = to_tegra_plane(plane);
struct tegra_bo *bo; struct tegra_bo *bo;
...@@ -431,7 +432,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, ...@@ -431,7 +432,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC;
tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT); 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); tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL);
/* bypass scaling */ /* bypass scaling */
...@@ -536,7 +537,6 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, ...@@ -536,7 +537,6 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm,
plane->base.offset = 0x0a00 + 0x0300 * index; plane->base.offset = 0x0a00 + 0x0300 * index;
plane->base.index = index; plane->base.index = index;
plane->base.depth = 0;
plane->wgrp = &hub->wgrps[wgrp]; plane->wgrp = &hub->wgrps[wgrp];
plane->wgrp->parent = dc->dev; plane->wgrp->parent = dc->dev;
...@@ -555,6 +555,7 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, ...@@ -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_helper_add(p, &tegra_shared_plane_helper_funcs);
drm_plane_create_zpos_property(p, 0, 0, 255);
return p; return p;
} }
......
...@@ -19,7 +19,6 @@ struct tegra_plane { ...@@ -19,7 +19,6 @@ struct tegra_plane {
struct tegra_dc *dc; struct tegra_dc *dc;
unsigned int offset; unsigned int offset;
unsigned int index; unsigned int index;
unsigned int depth;
}; };
struct tegra_cursor { struct tegra_cursor {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment