aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/0014-drm-amd-display-Add-support-for-toggling-DFS-bypass.patch
blob: 2ded7d55f5832bd1ba35511b304dbfd0b4deb8aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
From 3a227ba5123fa86598753ccb7fd2ddf00aa0c486 Mon Sep 17 00:00:00 2001
From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Date: Thu, 26 Jul 2018 09:32:48 -0400
Subject: [PATCH 0014/2940] drm/amd/display: Add support for toggling DFS
 bypass

[Why]

If the hardware supports DFS bypass it will always be enabled after
creation of the DCCG. DFS bypass should only be enabled when
the current stream consists of a single embedded panel and the
minimum display clock is below the DFS bypass threshold.

[How]

Add a function to the DCCG table that updates the DFS bypass state
when setting the bandwidth. If the DFS bypass state is changed, the
clock needs to be reprogrammed to reflect this before the DPREFCLK
is updated for audio endpoints. The existing display clock value
is used as the target display clock value when reprogramming since the
resulting change will be equal or larger to the current value.

These changes only specifically target dce110 but do offer a framework
for support on other applicable targets.

Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: David Francis <David.Francis@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/display/dc/dce/dce_clocks.c   | 63 +++++++++++++++++--
 .../gpu/drm/amd/display/dc/dce/dce_clocks.h   |  2 +
 .../display/dc/dce110/dce110_hw_sequencer.c   | 12 +++-
 .../drm/amd/display/dc/inc/hw/display_clock.h |  5 ++
 4 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
index a8087fced9b8..3b3264938941 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
@@ -255,13 +255,12 @@ static int dce_set_clock(
 	pxl_clk_params.target_pixel_clock = requested_clk_khz;
 	pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
 
-	if (clk_dce->dfs_bypass_enabled)
+	if (clk_dce->dfs_bypass_active)
 		pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true;
 
 	bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
 
-	if (clk_dce->dfs_bypass_enabled) {
-
+	if (clk_dce->dfs_bypass_active) {
 		/* Cache the fixed display clock*/
 		clk_dce->dfs_bypass_disp_clk =
 			pxl_clk_params.dfs_bypass_display_clock;
@@ -680,6 +679,61 @@ static void dce_update_clocks(struct dccg *dccg,
 	}
 }
 
+static bool dce_update_dfs_bypass(
+       struct dccg *dccg,
+       struct dc *dc,
+       struct dc_state *context,
+       int requested_clock_khz)
+{
+       struct dce_dccg *clk_dce = TO_DCE_CLOCKS(dccg);
+       struct resource_context *res_ctx = &context->res_ctx;
+       enum signal_type signal_type = SIGNAL_TYPE_NONE;
+       bool was_active = clk_dce->dfs_bypass_active;
+       int i;
+
+       /* Disable DFS bypass by default. */
+       clk_dce->dfs_bypass_active = false;
+
+       /* Check that DFS bypass is available. */
+       if (!clk_dce->dfs_bypass_enabled)
+               goto update;
+
+       /* Check if the requested display clock is below the threshold. */
+       if (requested_clock_khz >= 400000)
+               goto update;
+
+       /* DFS-bypass should only be enabled on single stream setups */
+       if (context->stream_count != 1)
+               goto update;
+
+       /* Check that the stream's signal type is an embedded panel */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (res_ctx->pipe_ctx[i].stream) {
+                       struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+
+                       signal_type = pipe_ctx->stream->sink->link->connector_signal;
+                       break;
+               }
+       }
+
+       if (signal_type == SIGNAL_TYPE_EDP ||
+               signal_type == SIGNAL_TYPE_LVDS)
+               clk_dce->dfs_bypass_active = true;
+
+update:
+       /* Update the clock state. We don't need to respect safe_to_lower
+        * because DFS bypass should always be greater than the current
+        * display clock frequency.
+        */
+       if (was_active != clk_dce->dfs_bypass_active) {
+               dccg->clks.dispclk_khz =
+                       dccg->funcs->set_dispclk(dccg, dccg->clks.dispclk_khz);
+               return true;
+       }
+
+       return false;
+}
+
 #ifdef CONFIG_X86
 static const struct display_clock_funcs dcn1_funcs = {
 	.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
@@ -703,7 +757,8 @@ static const struct display_clock_funcs dce112_funcs = {
 static const struct display_clock_funcs dce110_funcs = {
 	.get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
 	.set_dispclk = dce_psr_set_clock,
-	.update_clocks = dce_update_clocks
+	.update_clocks = dce_update_clocks,
+	.update_dfs_bypass = dce_update_dfs_bypass
 };
 
 static const struct display_clock_funcs dce_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
index e5e44adc6c27..8be68eb000c5 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
@@ -78,6 +78,8 @@ struct dce_dccg {
 
 	/* Cache the status of DFS-bypass feature*/
 	bool dfs_bypass_enabled;
+	/* True if the DFS-bypass feature is enabled and active. */
+	bool dfs_bypass_active;
 	/* Cache the display clock returned by VBIOS if DFS-bypass is enabled.
 	 * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */
 	int dfs_bypass_disp_clk;
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 94cb4c77018a..f1c5467bc615 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -2566,6 +2566,7 @@ static void dce110_set_bandwidth(
 		bool decrease_allowed)
 {
 	struct dc_clocks req_clks;
+	struct dccg *dccg = dc->res_pool->dccg;
 
 	req_clks.dispclk_khz = context->bw.dce.dispclk_khz;
 	req_clks.phyclk_khz = get_max_pixel_clock_for_all_paths(dc, context);
@@ -2575,8 +2576,15 @@ static void dce110_set_bandwidth(
 	else
 		dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
 
-	dc->res_pool->dccg->funcs->update_clocks(
-			dc->res_pool->dccg,
+	if (dccg->funcs->update_dfs_bypass)
+		dccg->funcs->update_dfs_bypass(
+			dccg,
+			dc,
+			context,
+			req_clks.dispclk_khz);
+
+	dccg->funcs->update_clocks(
+			dccg,
 			&req_clks,
 			decrease_allowed);
 	pplib_apply_display_requirements(dc, context);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h
index 3c7ccb68ecdb..689faa16c0ae 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h
@@ -53,6 +53,11 @@ struct display_clock_funcs {
 		int requested_clock_khz);
 
 	int (*get_dp_ref_clk_frequency)(struct dccg *dccg);
+
+	bool (*update_dfs_bypass)(struct dccg *dccg,
+		struct dc *dc,
+		struct dc_state *context,
+		int requested_clock_khz);
 };
 
 #endif /* __DISPLAY_CLOCK_H__ */
-- 
2.17.1