aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch
blob: a2e8e7d3d488118ea9714104a0d8d551c9d2f27e (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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
From 16c580abc2cbfc2a6dedecd88773bce4c0611a12 Mon Sep 17 00:00:00 2001
From: "Signed-off-by: David Rokhvarg" <David.Rokhvarg@amd.com>
Date: Thu, 3 Mar 2016 17:32:18 -0500
Subject: [PATCH 0613/1110] drm/amd/dal: Integrate
 amd_powerplay_get_clock_by_type() into DM.

This replaces hardcoded values by PPLib values.

Signed-off-by: David Rokhvarg <David.Rokhvarg@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Acked-by: Harry Wentland<harry.wentland@amd.com>
---
 .../drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c    | 155 +++++++++++++++++----
 drivers/gpu/drm/amd/dal/dc/dc_services.h           |   8 +-
 2 files changed, 133 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c
index 94c8a38..12b9475 100644
--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c
@@ -258,34 +258,24 @@ bool dc_service_get_system_clocks_range(
 	return true;
 }
 
-
-bool dc_service_pp_get_clock_levels_by_type(
-		const struct dc_context *ctx,
+static void get_default_clock_levels(
 		enum dc_pp_clock_type clk_type,
 		struct dc_pp_clock_levels *clks)
 {
-/*
- #ifdef CONFIG_DRM_AMD_POWERPLAY
-	if(amd_powerplay_get_clocks_by_type(adev->powerplay.pp_handle,
-		(int)clk_type, (void *)clks) == fail
-		PPlib return clocks in tens of kHz
-		divide by 10 & push to the clks which kHz
-#endif
-*/
-	uint32_t disp_clks_in_khz[8] = {
-	300000, 411430, 480000, 533340, 626090, 626090, 626090, 626090 };
-	uint32_t sclks_in_khz[8] = {
-	200000, 266670, 342860, 411430, 450000, 514290, 576000, 626090 };
-	uint32_t mclks_in_khz[8] = { 333000, 800000 };
+	uint32_t disp_clks_in_khz[6] = {
+			300000, 400000, 496560, 626090, 685720, 757900 };
+	uint32_t sclks_in_khz[6] = {
+			300000, 360000, 423530, 514290, 626090, 720000 };
+	uint32_t mclks_in_khz[2] = { 333000, 800000 };
 
 	switch (clk_type) {
 	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
-		clks->num_levels = 8;
+		clks->num_levels = 6;
 		dc_service_memmove(clks->clocks_in_khz, disp_clks_in_khz,
 				sizeof(disp_clks_in_khz));
 		break;
 	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
-		clks->num_levels = 8;
+		clks->num_levels = 6;
 		dc_service_memmove(clks->clocks_in_khz, sclks_in_khz,
 				sizeof(sclks_in_khz));
 		break;
@@ -295,26 +285,135 @@ bool dc_service_pp_get_clock_levels_by_type(
 				sizeof(mclks_in_khz));
 		break;
 	default:
-		return false;
+		clks->num_levels = 0;
+		break;
 	}
+}
 
 #ifdef CONFIG_DRM_AMD_POWERPLAY
-	if (clk_type ==  DC_PP_CLOCK_TYPE_ENGINE_CLK ||
-		clk_type ==  DC_PP_CLOCK_TYPE_DISPLAY_CLK) {
+static enum amd_pp_clock_type dc_to_pp_clock_type(
+		enum dc_pp_clock_type dc_pp_clk_type)
+{
+	enum amd_pp_clock_type amd_pp_clk_type = 0;
+
+	switch (dc_pp_clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		amd_pp_clk_type = amd_pp_disp_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		amd_pp_clk_type = amd_pp_sys_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		amd_pp_clk_type = amd_pp_mem_clock;
+		break;
+	default:
+		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
+				dc_pp_clk_type);
+		break;
+	}
 
-		struct amdgpu_device *adev = ctx->driver_context;
-		struct amd_pp_dal_clock_info info = {0};
+	return amd_pp_clk_type;
+}
+
+static void pp_to_dc_clock_levels(
+		const struct amd_pp_clocks *pp_clks,
+		struct dc_pp_clock_levels *dc_clks,
+		enum dc_pp_clock_type dc_clk_type)
+{
+	uint32_t i;
 
-		if (0 == amd_powerplay_get_display_power_level(
-				adev->powerplay.pp_handle, &info) &&
-				info.level < clks->num_levels) {
-		/*if the max possible power level less then use smaller*/
-			clks->num_levels = info.level;
+	if (pp_clks->count > DC_PP_MAX_CLOCK_LEVELS) {
+		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
+				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
+				pp_clks->count,
+				DC_PP_MAX_CLOCK_LEVELS);
+
+		dc_clks->num_levels = DC_PP_MAX_CLOCK_LEVELS;
+	} else
+		dc_clks->num_levels = pp_clks->count;
+
+	DRM_INFO("DM_PPLIB: values for %s clock\n",
+			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
+
+	for (i = 0; i < dc_clks->num_levels; i++) {
+		DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
+		/* translate 10kHz to kHz */
+		dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
+	}
+}
+#endif
+
+bool dc_service_pp_get_clock_levels_by_type(
+		const struct dc_context *ctx,
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *dc_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+	void *pp_handle = adev->powerplay.pp_handle;
+	struct amd_pp_clocks pp_clks = { 0 };
+	struct amd_pp_simple_clock_info validation_clks = { 0 };
+	uint32_t i;
+
+	if (amd_powerplay_get_clock_by_type(pp_handle,
+			dc_to_pp_clock_type(clk_type), &pp_clks)) {
+		/* Error in pplib. Provide default values. */
+		get_default_clock_levels(clk_type, dc_clks);
+		return true;
+	}
+
+	pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
+
+	if (amd_powerplay_get_display_mode_validation_clocks(pp_handle,
+			&validation_clks)) {
+		/* Error in pplib. Provide default values. */
+		DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
+		validation_clks.engine_max_clock = 72000;
+		validation_clks.memory_max_clock = 80000;
+		validation_clks.level = 0;
+	}
+
+	DRM_INFO("DM_PPLIB: Validation clocks:\n");
+	DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
+			validation_clks.engine_max_clock);
+	DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
+			validation_clks.memory_max_clock);
+	DRM_INFO("DM_PPLIB:    level           : %d\n",
+			validation_clks.level);
+
+	/* Translate 10 kHz to kHz. */
+	validation_clks.engine_max_clock *= 10;
+	validation_clks.memory_max_clock *= 10;
+
+	/* Determine the highest non-boosted level from the Validation Clocks */
+	if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
+				/* This clock is higher the validation clock.
+				 * Than means the previous one is the highest
+				 * non-boosted one. */
+				DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	} else if (clk_type == DC_PP_CLOCK_TYPE_MEMORY_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
+				DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
 		}
 	}
+#else
+	get_default_clock_levels(clk_type, dc_clks);
 #endif
 	return true;
 }
+
 /**** end of power component interfaces ****/
 
 
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_services.h b/drivers/gpu/drm/amd/dal/dc/dc_services.h
index edb558d..907b415 100644
--- a/drivers/gpu/drm/amd/dal/dc/dc_services.h
+++ b/drivers/gpu/drm/amd/dal/dc/dc_services.h
@@ -105,7 +105,6 @@ struct dc_pp_display_configuration {
 	bool cpu_pstate_disable;
 	uint32_t cpu_pstate_separation_time;
 
-	/* 10khz steps */
 	uint32_t min_memory_clock_khz;
 	uint32_t min_engine_clock_khz;
 	uint32_t min_engine_clock_deep_sleep_khz;
@@ -167,10 +166,15 @@ bool dc_service_get_system_clocks_range(
 
 enum dc_pp_clock_type {
 	DC_PP_CLOCK_TYPE_DISPLAY_CLK = 1,
-	DC_PP_CLOCK_TYPE_ENGINE_CLK,
+	DC_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */
 	DC_PP_CLOCK_TYPE_MEMORY_CLK
 };
 
+#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
+	(clk_type) == DC_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
+
 #define DC_PP_MAX_CLOCK_LEVELS 8
 
 struct dc_pp_clock_levels {
-- 
2.7.4