diff options
author | Thierry Reding <treding@nvidia.com> | 2017-12-14 07:46:20 -0500 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2017-12-21 08:52:35 -0500 |
commit | ab7d3f5826c55ad23101327eab435660caa83436 (patch) | |
tree | 8d8c77f5c2f8c727bebcd0ba2085a91369b2dee4 | |
parent | 363541e8eeed16fdf696252008ddee823730f82c (diff) |
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>
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 94 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hub.c | 5 | ||||
-rw-r--r-- | 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) | |||
152 | return dfixed_frac(inf); | 152 | return dfixed_frac(inf); |
153 | } | 153 | } |
154 | 154 | ||
155 | static void tegra_plane_setup_blending_legacy(struct tegra_plane *plane) | ||
156 | { | ||
157 | /* | ||
158 | * Disable blending and assume Window A is the bottom-most window, | ||
159 | * Window C is the top-most window and Window B is in the middle. | ||
160 | */ | ||
161 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_NOKEY); | ||
162 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_1WIN); | ||
163 | |||
164 | switch (plane->index) { | ||
165 | case 0: | ||
166 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_X); | ||
167 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); | ||
168 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); | ||
169 | break; | ||
170 | |||
171 | case 1: | ||
172 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); | ||
173 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); | ||
174 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); | ||
175 | break; | ||
176 | |||
177 | case 2: | ||
178 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); | ||
179 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_Y); | ||
180 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_3WIN_XY); | ||
181 | break; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static void tegra_plane_setup_blending(struct tegra_plane *plane, | ||
186 | const struct tegra_dc_window *window) | ||
187 | { | ||
188 | u32 value; | ||
189 | |||
190 | value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 | | ||
191 | BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC | | ||
192 | BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; | ||
193 | tegra_plane_writel(plane, value, DC_WIN_BLEND_MATCH_SELECT); | ||
194 | |||
195 | value = BLEND_FACTOR_DST_ALPHA_ZERO | BLEND_FACTOR_SRC_ALPHA_K2 | | ||
196 | BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC | | ||
197 | BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; | ||
198 | tegra_plane_writel(plane, value, DC_WIN_BLEND_NOMATCH_SELECT); | ||
199 | |||
200 | value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - window->zpos); | ||
201 | tegra_plane_writel(plane, value, DC_WIN_BLEND_LAYER_CONTROL); | ||
202 | } | ||
203 | |||
155 | static void tegra_dc_setup_window(struct tegra_plane *plane, | 204 | static void tegra_dc_setup_window(struct tegra_plane *plane, |
156 | const struct tegra_dc_window *window) | 205 | const struct tegra_dc_window *window) |
157 | { | 206 | { |
@@ -291,32 +340,10 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, | |||
291 | 340 | ||
292 | tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); | 341 | tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); |
293 | 342 | ||
294 | /* | 343 | if (dc->soc->supports_blending) |
295 | * Disable blending and assume Window A is the bottom-most window, | 344 | tegra_plane_setup_blending(plane, window); |
296 | * Window C is the top-most window and Window B is in the middle. | 345 | else |
297 | */ | 346 | tegra_plane_setup_blending_legacy(plane); |
298 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_NOKEY); | ||
299 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_1WIN); | ||
300 | |||
301 | switch (plane->index) { | ||
302 | case 0: | ||
303 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_X); | ||
304 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); | ||
305 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); | ||
306 | break; | ||
307 | |||
308 | case 1: | ||
309 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); | ||
310 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); | ||
311 | tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); | ||
312 | break; | ||
313 | |||
314 | case 2: | ||
315 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); | ||
316 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_Y); | ||
317 | tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_3WIN_XY); | ||
318 | break; | ||
319 | } | ||
320 | } | 347 | } |
321 | 348 | ||
322 | static const u32 tegra20_primary_formats[] = { | 349 | static const u32 tegra20_primary_formats[] = { |
@@ -467,6 +494,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, | |||
467 | window.bottom_up = tegra_fb_is_bottom_up(fb); | 494 | window.bottom_up = tegra_fb_is_bottom_up(fb); |
468 | 495 | ||
469 | /* copy from state */ | 496 | /* copy from state */ |
497 | window.zpos = plane->state->normalized_zpos; | ||
470 | window.tiling = state->tiling; | 498 | window.tiling = state->tiling; |
471 | window.format = state->format; | 499 | window.format = state->format; |
472 | window.swap = state->swap; | 500 | window.swap = state->swap; |
@@ -523,7 +551,6 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, | |||
523 | /* Always use window A as primary window */ | 551 | /* Always use window A as primary window */ |
524 | plane->offset = 0xa00; | 552 | plane->offset = 0xa00; |
525 | plane->index = 0; | 553 | plane->index = 0; |
526 | plane->depth = 255; | ||
527 | plane->dc = dc; | 554 | plane->dc = dc; |
528 | 555 | ||
529 | num_formats = dc->soc->num_primary_formats; | 556 | num_formats = dc->soc->num_primary_formats; |
@@ -539,6 +566,9 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, | |||
539 | 566 | ||
540 | drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); | 567 | drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); |
541 | 568 | ||
569 | if (dc->soc->supports_blending) | ||
570 | drm_plane_create_zpos_property(&plane->base, 0, 0, 255); | ||
571 | |||
542 | return &plane->base; | 572 | return &plane->base; |
543 | } | 573 | } |
544 | 574 | ||
@@ -786,7 +816,6 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, | |||
786 | 816 | ||
787 | plane->offset = 0xa00 + 0x200 * index; | 817 | plane->offset = 0xa00 + 0x200 * index; |
788 | plane->index = index; | 818 | plane->index = index; |
789 | plane->depth = 0; | ||
790 | plane->dc = dc; | 819 | plane->dc = dc; |
791 | 820 | ||
792 | num_formats = dc->soc->num_overlay_formats; | 821 | 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 | 832 | ||
804 | drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); | 833 | drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); |
805 | 834 | ||
835 | if (dc->soc->supports_blending) | ||
836 | drm_plane_create_zpos_property(&plane->base, 0, 0, 255); | ||
837 | |||
806 | return &plane->base; | 838 | return &plane->base; |
807 | } | 839 | } |
808 | 840 | ||
@@ -1834,6 +1866,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { | |||
1834 | .supports_interlacing = false, | 1866 | .supports_interlacing = false, |
1835 | .supports_cursor = false, | 1867 | .supports_cursor = false, |
1836 | .supports_block_linear = false, | 1868 | .supports_block_linear = false, |
1869 | .supports_blending = false, | ||
1837 | .pitch_align = 8, | 1870 | .pitch_align = 8, |
1838 | .has_powergate = false, | 1871 | .has_powergate = false, |
1839 | .broken_reset = true, | 1872 | .broken_reset = true, |
@@ -1849,6 +1882,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = { | |||
1849 | .supports_interlacing = false, | 1882 | .supports_interlacing = false, |
1850 | .supports_cursor = false, | 1883 | .supports_cursor = false, |
1851 | .supports_block_linear = false, | 1884 | .supports_block_linear = false, |
1885 | .supports_blending = false, | ||
1852 | .pitch_align = 8, | 1886 | .pitch_align = 8, |
1853 | .has_powergate = false, | 1887 | .has_powergate = false, |
1854 | .broken_reset = false, | 1888 | .broken_reset = false, |
@@ -1864,6 +1898,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = { | |||
1864 | .supports_interlacing = false, | 1898 | .supports_interlacing = false, |
1865 | .supports_cursor = false, | 1899 | .supports_cursor = false, |
1866 | .supports_block_linear = false, | 1900 | .supports_block_linear = false, |
1901 | .supports_blending = false, | ||
1867 | .pitch_align = 64, | 1902 | .pitch_align = 64, |
1868 | .has_powergate = true, | 1903 | .has_powergate = true, |
1869 | .broken_reset = false, | 1904 | .broken_reset = false, |
@@ -1879,6 +1914,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | |||
1879 | .supports_interlacing = true, | 1914 | .supports_interlacing = true, |
1880 | .supports_cursor = true, | 1915 | .supports_cursor = true, |
1881 | .supports_block_linear = true, | 1916 | .supports_block_linear = true, |
1917 | .supports_blending = true, | ||
1882 | .pitch_align = 64, | 1918 | .pitch_align = 64, |
1883 | .has_powergate = true, | 1919 | .has_powergate = true, |
1884 | .broken_reset = false, | 1920 | .broken_reset = false, |
@@ -1894,6 +1930,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = { | |||
1894 | .supports_interlacing = true, | 1930 | .supports_interlacing = true, |
1895 | .supports_cursor = true, | 1931 | .supports_cursor = true, |
1896 | .supports_block_linear = true, | 1932 | .supports_block_linear = true, |
1933 | .supports_blending = true, | ||
1897 | .pitch_align = 64, | 1934 | .pitch_align = 64, |
1898 | .has_powergate = true, | 1935 | .has_powergate = true, |
1899 | .broken_reset = false, | 1936 | .broken_reset = false, |
@@ -1943,6 +1980,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = { | |||
1943 | .supports_interlacing = true, | 1980 | .supports_interlacing = true, |
1944 | .supports_cursor = true, | 1981 | .supports_cursor = true, |
1945 | .supports_block_linear = true, | 1982 | .supports_block_linear = true, |
1983 | .supports_blending = true, | ||
1946 | .pitch_align = 64, | 1984 | .pitch_align = 64, |
1947 | .has_powergate = false, | 1985 | .has_powergate = false, |
1948 | .broken_reset = false, | 1986 | .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 { | |||
55 | bool supports_interlacing; | 55 | bool supports_interlacing; |
56 | bool supports_cursor; | 56 | bool supports_cursor; |
57 | bool supports_block_linear; | 57 | bool supports_block_linear; |
58 | bool supports_blending; | ||
58 | unsigned int pitch_align; | 59 | unsigned int pitch_align; |
59 | bool has_powergate; | 60 | bool has_powergate; |
60 | bool broken_reset; | 61 | bool broken_reset; |
@@ -136,6 +137,7 @@ struct tegra_dc_window { | |||
136 | unsigned int bits_per_pixel; | 137 | unsigned int bits_per_pixel; |
137 | unsigned int stride[2]; | 138 | unsigned int stride[2]; |
138 | unsigned long base[3]; | 139 | unsigned long base[3]; |
140 | unsigned int zpos; | ||
139 | bool bottom_up; | 141 | bool bottom_up; |
140 | 142 | ||
141 | struct tegra_bo_tiling tiling; | 143 | 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 { | |||
33 | struct mutex lock; | 33 | struct mutex lock; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | static int tegra_atomic_check(struct drm_device *drm, | ||
37 | struct drm_atomic_state *state) | ||
38 | { | ||
39 | int err; | ||
40 | |||
41 | err = drm_atomic_helper_check_modeset(drm, state); | ||
42 | if (err < 0) | ||
43 | return err; | ||
44 | |||
45 | err = drm_atomic_normalize_zpos(drm, state); | ||
46 | if (err < 0) | ||
47 | return err; | ||
48 | |||
49 | err = drm_atomic_helper_check_planes(drm, state); | ||
50 | if (err < 0) | ||
51 | return err; | ||
52 | |||
53 | if (state->legacy_cursor_update) | ||
54 | state->async_update = !drm_atomic_helper_async_check(drm, state); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
36 | static struct drm_atomic_state * | 59 | static struct drm_atomic_state * |
37 | tegra_atomic_state_alloc(struct drm_device *drm) | 60 | tegra_atomic_state_alloc(struct drm_device *drm) |
38 | { | 61 | { |
@@ -67,7 +90,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = { | |||
67 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 90 | #ifdef CONFIG_DRM_FBDEV_EMULATION |
68 | .output_poll_changed = tegra_fb_output_poll_changed, | 91 | .output_poll_changed = tegra_fb_output_poll_changed, |
69 | #endif | 92 | #endif |
70 | .atomic_check = drm_atomic_helper_check, | 93 | .atomic_check = tegra_atomic_check, |
71 | .atomic_commit = drm_atomic_helper_commit, | 94 | .atomic_commit = drm_atomic_helper_commit, |
72 | .atomic_state_alloc = tegra_atomic_state_alloc, | 95 | .atomic_state_alloc = tegra_atomic_state_alloc, |
73 | .atomic_state_clear = tegra_atomic_state_clear, | 96 | .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, | |||
399 | { | 399 | { |
400 | struct tegra_plane_state *state = to_tegra_plane_state(plane->state); | 400 | struct tegra_plane_state *state = to_tegra_plane_state(plane->state); |
401 | struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); | 401 | struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); |
402 | unsigned int zpos = plane->state->normalized_zpos; | ||
402 | struct drm_framebuffer *fb = plane->state->fb; | 403 | struct drm_framebuffer *fb = plane->state->fb; |
403 | struct tegra_plane *p = to_tegra_plane(plane); | 404 | struct tegra_plane *p = to_tegra_plane(plane); |
404 | struct tegra_bo *bo; | 405 | struct tegra_bo *bo; |
@@ -431,7 +432,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, | |||
431 | BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; | 432 | BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; |
432 | tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT); | 433 | tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT); |
433 | 434 | ||
434 | value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(p->depth); | 435 | value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - zpos); |
435 | tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL); | 436 | tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL); |
436 | 437 | ||
437 | /* bypass scaling */ | 438 | /* bypass scaling */ |
@@ -536,7 +537,6 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, | |||
536 | 537 | ||
537 | plane->base.offset = 0x0a00 + 0x0300 * index; | 538 | plane->base.offset = 0x0a00 + 0x0300 * index; |
538 | plane->base.index = index; | 539 | plane->base.index = index; |
539 | plane->base.depth = 0; | ||
540 | 540 | ||
541 | plane->wgrp = &hub->wgrps[wgrp]; | 541 | plane->wgrp = &hub->wgrps[wgrp]; |
542 | plane->wgrp->parent = dc->dev; | 542 | plane->wgrp->parent = dc->dev; |
@@ -555,6 +555,7 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, | |||
555 | } | 555 | } |
556 | 556 | ||
557 | drm_plane_helper_add(p, &tegra_shared_plane_helper_funcs); | 557 | drm_plane_helper_add(p, &tegra_shared_plane_helper_funcs); |
558 | drm_plane_create_zpos_property(p, 0, 0, 255); | ||
558 | 559 | ||
559 | return p; | 560 | return p; |
560 | } | 561 | } |
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 { | |||
19 | struct tegra_dc *dc; | 19 | struct tegra_dc *dc; |
20 | unsigned int offset; | 20 | unsigned int offset; |
21 | unsigned int index; | 21 | unsigned int index; |
22 | unsigned int depth; | ||
23 | }; | 22 | }; |
24 | 23 | ||
25 | struct tegra_cursor { | 24 | struct tegra_cursor { |