aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-12-14 07:46:20 -0500
committerThierry Reding <treding@nvidia.com>2017-12-21 08:52:35 -0500
commitab7d3f5826c55ad23101327eab435660caa83436 (patch)
tree8d8c77f5c2f8c727bebcd0ba2085a91369b2dee4
parent363541e8eeed16fdf696252008ddee823730f82c (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.c94
-rw-r--r--drivers/gpu/drm/tegra/dc.h2
-rw-r--r--drivers/gpu/drm/tegra/drm.c25
-rw-r--r--drivers/gpu/drm/tegra/hub.c5
-rw-r--r--drivers/gpu/drm/tegra/plane.h1
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
155static 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
185static 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
155static void tegra_dc_setup_window(struct tegra_plane *plane, 204static 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
322static const u32 tegra20_primary_formats[] = { 349static 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
36static 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
36static struct drm_atomic_state * 59static struct drm_atomic_state *
37tegra_atomic_state_alloc(struct drm_device *drm) 60tegra_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
25struct tegra_cursor { 24struct tegra_cursor {