diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2018-05-04 10:39:58 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2018-05-17 08:08:44 -0400 |
commit | acc6a3a9afdd4e0537342012656cdb5c4a3127c5 (patch) | |
tree | 51c4a4280fdecd57d3ed457bd0eb4073bfadad56 | |
parent | 0c407de5ed1a329468122cbf4f3e727e0c1e3f36 (diff) |
drm/tegra: dc: Enable plane scaling filters
Currently resized plane produces a "pixelated" image which doesn't look
nice, especially in a case of a video overlay. Enable scaling filters that
significantly improve image quality of a scaled overlay.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 81 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 7 |
2 files changed, 88 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 3e7ec3937346..a4dd866fc8be 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -224,6 +224,39 @@ static void tegra_plane_setup_blending(struct tegra_plane *plane, | |||
224 | tegra_plane_writel(plane, value, DC_WIN_BLEND_LAYER_CONTROL); | 224 | tegra_plane_writel(plane, value, DC_WIN_BLEND_LAYER_CONTROL); |
225 | } | 225 | } |
226 | 226 | ||
227 | static bool | ||
228 | tegra_plane_use_horizontal_filtering(struct tegra_plane *plane, | ||
229 | const struct tegra_dc_window *window) | ||
230 | { | ||
231 | struct tegra_dc *dc = plane->dc; | ||
232 | |||
233 | if (window->src.w == window->dst.w) | ||
234 | return false; | ||
235 | |||
236 | if (plane->index == 0 && dc->soc->has_win_a_without_filters) | ||
237 | return false; | ||
238 | |||
239 | return true; | ||
240 | } | ||
241 | |||
242 | static bool | ||
243 | tegra_plane_use_vertical_filtering(struct tegra_plane *plane, | ||
244 | const struct tegra_dc_window *window) | ||
245 | { | ||
246 | struct tegra_dc *dc = plane->dc; | ||
247 | |||
248 | if (window->src.h == window->dst.h) | ||
249 | return false; | ||
250 | |||
251 | if (plane->index == 0 && dc->soc->has_win_a_without_filters) | ||
252 | return false; | ||
253 | |||
254 | if (plane->index == 2 && dc->soc->has_win_c_without_vert_filter) | ||
255 | return false; | ||
256 | |||
257 | return true; | ||
258 | } | ||
259 | |||
227 | static void tegra_dc_setup_window(struct tegra_plane *plane, | 260 | static void tegra_dc_setup_window(struct tegra_plane *plane, |
228 | const struct tegra_dc_window *window) | 261 | const struct tegra_dc_window *window) |
229 | { | 262 | { |
@@ -361,6 +394,44 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, | |||
361 | if (window->bottom_up) | 394 | if (window->bottom_up) |
362 | value |= V_DIRECTION; | 395 | value |= V_DIRECTION; |
363 | 396 | ||
397 | if (tegra_plane_use_horizontal_filtering(plane, window)) { | ||
398 | /* | ||
399 | * Enable horizontal 6-tap filter and set filtering | ||
400 | * coefficients to the default values defined in TRM. | ||
401 | */ | ||
402 | tegra_plane_writel(plane, 0x00008000, DC_WIN_H_FILTER_P(0)); | ||
403 | tegra_plane_writel(plane, 0x3e087ce1, DC_WIN_H_FILTER_P(1)); | ||
404 | tegra_plane_writel(plane, 0x3b117ac1, DC_WIN_H_FILTER_P(2)); | ||
405 | tegra_plane_writel(plane, 0x591b73aa, DC_WIN_H_FILTER_P(3)); | ||
406 | tegra_plane_writel(plane, 0x57256d9a, DC_WIN_H_FILTER_P(4)); | ||
407 | tegra_plane_writel(plane, 0x552f668b, DC_WIN_H_FILTER_P(5)); | ||
408 | tegra_plane_writel(plane, 0x73385e8b, DC_WIN_H_FILTER_P(6)); | ||
409 | tegra_plane_writel(plane, 0x72435583, DC_WIN_H_FILTER_P(7)); | ||
410 | tegra_plane_writel(plane, 0x714c4c8b, DC_WIN_H_FILTER_P(8)); | ||
411 | tegra_plane_writel(plane, 0x70554393, DC_WIN_H_FILTER_P(9)); | ||
412 | tegra_plane_writel(plane, 0x715e389b, DC_WIN_H_FILTER_P(10)); | ||
413 | tegra_plane_writel(plane, 0x71662faa, DC_WIN_H_FILTER_P(11)); | ||
414 | tegra_plane_writel(plane, 0x536d25ba, DC_WIN_H_FILTER_P(12)); | ||
415 | tegra_plane_writel(plane, 0x55731bca, DC_WIN_H_FILTER_P(13)); | ||
416 | tegra_plane_writel(plane, 0x387a11d9, DC_WIN_H_FILTER_P(14)); | ||
417 | tegra_plane_writel(plane, 0x3c7c08f1, DC_WIN_H_FILTER_P(15)); | ||
418 | |||
419 | value |= H_FILTER; | ||
420 | } | ||
421 | |||
422 | if (tegra_plane_use_vertical_filtering(plane, window)) { | ||
423 | unsigned int i, k; | ||
424 | |||
425 | /* | ||
426 | * Enable vertical 2-tap filter and set filtering | ||
427 | * coefficients to the default values defined in TRM. | ||
428 | */ | ||
429 | for (i = 0, k = 128; i < 16; i++, k -= 8) | ||
430 | tegra_plane_writel(plane, k, DC_WIN_V_FILTER_P(i)); | ||
431 | |||
432 | value |= V_FILTER; | ||
433 | } | ||
434 | |||
364 | tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); | 435 | tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); |
365 | 436 | ||
366 | if (dc->soc->supports_blending) | 437 | if (dc->soc->supports_blending) |
@@ -1951,6 +2022,8 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { | |||
1951 | .num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats), | 2022 | .num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats), |
1952 | .overlay_formats = tegra20_overlay_formats, | 2023 | .overlay_formats = tegra20_overlay_formats, |
1953 | .modifiers = tegra20_modifiers, | 2024 | .modifiers = tegra20_modifiers, |
2025 | .has_win_a_without_filters = true, | ||
2026 | .has_win_c_without_vert_filter = true, | ||
1954 | }; | 2027 | }; |
1955 | 2028 | ||
1956 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { | 2029 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { |
@@ -1968,6 +2041,8 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = { | |||
1968 | .num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats), | 2041 | .num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats), |
1969 | .overlay_formats = tegra20_overlay_formats, | 2042 | .overlay_formats = tegra20_overlay_formats, |
1970 | .modifiers = tegra20_modifiers, | 2043 | .modifiers = tegra20_modifiers, |
2044 | .has_win_a_without_filters = false, | ||
2045 | .has_win_c_without_vert_filter = false, | ||
1971 | }; | 2046 | }; |
1972 | 2047 | ||
1973 | static const struct tegra_dc_soc_info tegra114_dc_soc_info = { | 2048 | static const struct tegra_dc_soc_info tegra114_dc_soc_info = { |
@@ -1985,6 +2060,8 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = { | |||
1985 | .num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats), | 2060 | .num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats), |
1986 | .overlay_formats = tegra114_overlay_formats, | 2061 | .overlay_formats = tegra114_overlay_formats, |
1987 | .modifiers = tegra20_modifiers, | 2062 | .modifiers = tegra20_modifiers, |
2063 | .has_win_a_without_filters = false, | ||
2064 | .has_win_c_without_vert_filter = false, | ||
1988 | }; | 2065 | }; |
1989 | 2066 | ||
1990 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | 2067 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { |
@@ -2002,6 +2079,8 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | |||
2002 | .num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats), | 2079 | .num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats), |
2003 | .overlay_formats = tegra124_overlay_formats, | 2080 | .overlay_formats = tegra124_overlay_formats, |
2004 | .modifiers = tegra124_modifiers, | 2081 | .modifiers = tegra124_modifiers, |
2082 | .has_win_a_without_filters = false, | ||
2083 | .has_win_c_without_vert_filter = false, | ||
2005 | }; | 2084 | }; |
2006 | 2085 | ||
2007 | static const struct tegra_dc_soc_info tegra210_dc_soc_info = { | 2086 | static const struct tegra_dc_soc_info tegra210_dc_soc_info = { |
@@ -2019,6 +2098,8 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = { | |||
2019 | .num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats), | 2098 | .num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats), |
2020 | .overlay_formats = tegra114_overlay_formats, | 2099 | .overlay_formats = tegra114_overlay_formats, |
2021 | .modifiers = tegra124_modifiers, | 2100 | .modifiers = tegra124_modifiers, |
2101 | .has_win_a_without_filters = false, | ||
2102 | .has_win_c_without_vert_filter = false, | ||
2022 | }; | 2103 | }; |
2023 | 2104 | ||
2024 | static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = { | 2105 | static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = { |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 7be786febb17..556321fde9d2 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
@@ -67,6 +67,8 @@ struct tegra_dc_soc_info { | |||
67 | const u32 *overlay_formats; | 67 | const u32 *overlay_formats; |
68 | unsigned int num_overlay_formats; | 68 | unsigned int num_overlay_formats; |
69 | const u64 *modifiers; | 69 | const u64 *modifiers; |
70 | bool has_win_a_without_filters; | ||
71 | bool has_win_c_without_vert_filter; | ||
70 | }; | 72 | }; |
71 | 73 | ||
72 | struct tegra_dc { | 74 | struct tegra_dc { |
@@ -553,6 +555,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); | |||
553 | #define THREAD_NUM(x) (((x) & 0x1f) << 1) | 555 | #define THREAD_NUM(x) (((x) & 0x1f) << 1) |
554 | #define THREAD_GROUP_ENABLE (1 << 0) | 556 | #define THREAD_GROUP_ENABLE (1 << 0) |
555 | 557 | ||
558 | #define DC_WIN_H_FILTER_P(p) (0x601 + (p)) | ||
559 | #define DC_WIN_V_FILTER_P(p) (0x619 + (p)) | ||
560 | |||
556 | #define DC_WIN_CSC_YOF 0x611 | 561 | #define DC_WIN_CSC_YOF 0x611 |
557 | #define DC_WIN_CSC_KYRGB 0x612 | 562 | #define DC_WIN_CSC_KYRGB 0x612 |
558 | #define DC_WIN_CSC_KUR 0x613 | 563 | #define DC_WIN_CSC_KUR 0x613 |
@@ -566,6 +571,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); | |||
566 | #define H_DIRECTION (1 << 0) | 571 | #define H_DIRECTION (1 << 0) |
567 | #define V_DIRECTION (1 << 2) | 572 | #define V_DIRECTION (1 << 2) |
568 | #define COLOR_EXPAND (1 << 6) | 573 | #define COLOR_EXPAND (1 << 6) |
574 | #define H_FILTER (1 << 8) | ||
575 | #define V_FILTER (1 << 10) | ||
569 | #define CSC_ENABLE (1 << 18) | 576 | #define CSC_ENABLE (1 << 18) |
570 | #define WIN_ENABLE (1 << 30) | 577 | #define WIN_ENABLE (1 << 30) |
571 | 578 | ||