xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/powerplay/hwmgr/amdgpu_processpptables.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: amdgpu_processpptables.c,v 1.2 2021/12/18 23:45:26 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2015 Advanced Micro Devices, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */
25 #include <sys/cdefs.h>
26 __KERNEL_RCSID(0, "$NetBSD: amdgpu_processpptables.c,v 1.2 2021/12/18 23:45:26 riastradh Exp $");
27 
28 #include "pp_debug.h"
29 #include <linux/types.h>
30 #include <linux/kernel.h>
31 #include <linux/slab.h>
32 #include <drm/amdgpu_drm.h>
33 #include "processpptables.h"
34 #include <atom-types.h>
35 #include <atombios.h>
36 #include "pptable.h"
37 #include "power_state.h"
38 #include "hwmgr.h"
39 #include "hardwaremanager.h"
40 
41 
42 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
43 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
44 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
45 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
46 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
47 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
48 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
49 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
50 
51 #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
52 
get_vce_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)53 static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
54 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
55 {
56 	uint16_t vce_table_offset = 0;
57 
58 	if (le16_to_cpu(powerplay_table->usTableSize) >=
59 	   sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
60 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
61 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
62 
63 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
64 			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
65 						(const ATOM_PPLIB_EXTENDEDHEADER *)
66 						(((unsigned long)powerplay_table3) +
67 						le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
68 			if (le16_to_cpu(extended_header->usSize) >=
69 			   SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
70 				vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
71 		}
72 	}
73 
74 	return vce_table_offset;
75 }
76 
get_vce_clock_info_array_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)77 static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,
78 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
79 {
80 	uint16_t table_offset = get_vce_table_offset(hwmgr,
81 						powerplay_table);
82 
83 	if (table_offset > 0)
84 		return table_offset + 1;
85 
86 	return 0;
87 }
88 
get_vce_clock_info_array_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)89 static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
90 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
91 {
92 	uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
93 							powerplay_table);
94 	uint16_t table_size = 0;
95 
96 	if (table_offset > 0) {
97 		const VCEClockInfoArray *p = (const VCEClockInfoArray *)
98 			(((unsigned long) powerplay_table) + table_offset);
99 		table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
100 	}
101 
102 	return table_size;
103 }
104 
get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)105 static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
106 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
107 {
108 	uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
109 							powerplay_table);
110 
111 	if (table_offset > 0)
112 		return table_offset + get_vce_clock_info_array_size(hwmgr,
113 							powerplay_table);
114 
115 	return 0;
116 }
117 
get_vce_clock_voltage_limit_table_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)118 static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
119 							const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
120 {
121 	uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
122 	uint16_t table_size = 0;
123 
124 	if (table_offset > 0) {
125 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
126 			(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
127 
128 		table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
129 	}
130 	return table_size;
131 }
132 
get_vce_state_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)133 static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
134 {
135 	uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
136 
137 	if (table_offset > 0)
138 		return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
139 
140 	return 0;
141 }
142 
get_vce_state_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)143 static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
144 						struct pp_hwmgr *hwmgr,
145 						const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
146 {
147 	uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
148 
149 	if (table_offset > 0)
150 		return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
151 
152 	return NULL;
153 }
154 
get_uvd_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)155 static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
156 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
157 {
158 	uint16_t uvd_table_offset = 0;
159 
160 	if (le16_to_cpu(powerplay_table->usTableSize) >=
161 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
162 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
163 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
164 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
165 			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
166 					(const ATOM_PPLIB_EXTENDEDHEADER *)
167 					(((unsigned long)powerplay_table3) +
168 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
169 			if (le16_to_cpu(extended_header->usSize) >=
170 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
171 				uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
172 		}
173 	}
174 	return uvd_table_offset;
175 }
176 
get_uvd_clock_info_array_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)177 static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,
178 			 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
179 {
180 	uint16_t table_offset = get_uvd_table_offset(hwmgr,
181 						    powerplay_table);
182 
183 	if (table_offset > 0)
184 		return table_offset + 1;
185 	return 0;
186 }
187 
get_uvd_clock_info_array_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)188 static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
189 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
190 {
191 	uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
192 						    powerplay_table);
193 	uint16_t table_size = 0;
194 
195 	if (table_offset > 0) {
196 		const UVDClockInfoArray *p = (const UVDClockInfoArray *)
197 					(((unsigned long) powerplay_table)
198 					+ table_offset);
199 		table_size = sizeof(UCHAR) +
200 			     p->ucNumEntries * sizeof(UVDClockInfo);
201 	}
202 
203 	return table_size;
204 }
205 
get_uvd_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)206 static uint16_t get_uvd_clock_voltage_limit_table_offset(
207 			struct pp_hwmgr *hwmgr,
208 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
209 {
210 	uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
211 						     powerplay_table);
212 
213 	if (table_offset > 0)
214 		return table_offset +
215 			get_uvd_clock_info_array_size(hwmgr, powerplay_table);
216 
217 	return 0;
218 }
219 
get_samu_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)220 static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
221 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
222 {
223 	uint16_t samu_table_offset = 0;
224 
225 	if (le16_to_cpu(powerplay_table->usTableSize) >=
226 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
227 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
228 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
229 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
230 			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
231 				(const ATOM_PPLIB_EXTENDEDHEADER *)
232 				(((unsigned long)powerplay_table3) +
233 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
234 			if (le16_to_cpu(extended_header->usSize) >=
235 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
236 				samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
237 		}
238 	}
239 
240 	return samu_table_offset;
241 }
242 
get_samu_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)243 static uint16_t get_samu_clock_voltage_limit_table_offset(
244 			struct pp_hwmgr *hwmgr,
245 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
246 {
247 	uint16_t table_offset = get_samu_table_offset(hwmgr,
248 					    powerplay_table);
249 
250 	if (table_offset > 0)
251 		return table_offset + 1;
252 
253 	return 0;
254 }
255 
get_acp_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)256 static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
257 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
258 {
259 	uint16_t acp_table_offset = 0;
260 
261 	if (le16_to_cpu(powerplay_table->usTableSize) >=
262 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
263 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
264 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
265 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
266 			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
267 				(const ATOM_PPLIB_EXTENDEDHEADER *)
268 				(((unsigned long)powerplay_table3) +
269 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
270 			if (le16_to_cpu(pExtendedHeader->usSize) >=
271 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
272 				acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
273 		}
274 	}
275 
276 	return acp_table_offset;
277 }
278 
get_acp_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)279 static uint16_t get_acp_clock_voltage_limit_table_offset(
280 				struct pp_hwmgr *hwmgr,
281 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
282 {
283 	uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);
284 
285 	if (tableOffset > 0)
286 		return tableOffset + 1;
287 
288 	return 0;
289 }
290 
get_cacp_tdp_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)291 static uint16_t get_cacp_tdp_table_offset(
292 				struct pp_hwmgr *hwmgr,
293 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
294 {
295 	uint16_t cacTdpTableOffset = 0;
296 
297 	if (le16_to_cpu(powerplay_table->usTableSize) >=
298 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
299 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
300 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
301 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
302 			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
303 					(const ATOM_PPLIB_EXTENDEDHEADER *)
304 					(((unsigned long)powerplay_table3) +
305 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
306 			if (le16_to_cpu(pExtendedHeader->usSize) >=
307 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
308 				cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
309 		}
310 	}
311 
312 	return cacTdpTableOffset;
313 }
314 
get_cac_tdp_table(struct pp_hwmgr * hwmgr,struct phm_cac_tdp_table ** ptable,const ATOM_PowerTune_Table * table,uint16_t us_maximum_power_delivery_limit)315 static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,
316 				struct phm_cac_tdp_table **ptable,
317 				const ATOM_PowerTune_Table *table,
318 				uint16_t us_maximum_power_delivery_limit)
319 {
320 	unsigned long table_size;
321 	struct phm_cac_tdp_table *tdp_table;
322 
323 	table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);
324 
325 	tdp_table = kzalloc(table_size, GFP_KERNEL);
326 	if (NULL == tdp_table)
327 		return -ENOMEM;
328 
329 	tdp_table->usTDP = le16_to_cpu(table->usTDP);
330 	tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);
331 	tdp_table->usTDC = le16_to_cpu(table->usTDC);
332 	tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);
333 	tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);
334 	tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);
335 	tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);
336 	tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;
337 
338 	*ptable = tdp_table;
339 
340 	return 0;
341 }
342 
get_sclk_vdd_gfx_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)343 static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
344 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
345 {
346 	uint16_t sclk_vdd_gfx_table_offset = 0;
347 
348 	if (le16_to_cpu(powerplay_table->usTableSize) >=
349 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
350 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
351 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
352 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
353 			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
354 				(const ATOM_PPLIB_EXTENDEDHEADER *)
355 				(((unsigned long)powerplay_table3) +
356 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
357 			if (le16_to_cpu(pExtendedHeader->usSize) >=
358 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
359 				sclk_vdd_gfx_table_offset =
360 					le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
361 		}
362 	}
363 
364 	return sclk_vdd_gfx_table_offset;
365 }
366 
get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)367 static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
368 			struct pp_hwmgr *hwmgr,
369 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
370 {
371 	uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);
372 
373 	if (tableOffset > 0)
374 		return tableOffset;
375 
376 	return 0;
377 }
378 
379 
get_clock_voltage_dependency_table(struct pp_hwmgr * hwmgr,struct phm_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_Clock_Voltage_Dependency_Table * table)380 static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
381 		struct phm_clock_voltage_dependency_table **ptable,
382 		const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)
383 {
384 
385 	unsigned long table_size, i;
386 	struct phm_clock_voltage_dependency_table *dep_table;
387 
388 	table_size = sizeof(unsigned long) +
389 		sizeof(struct phm_clock_voltage_dependency_table)
390 		* table->ucNumEntries;
391 
392 	dep_table = kzalloc(table_size, GFP_KERNEL);
393 	if (NULL == dep_table)
394 		return -ENOMEM;
395 
396 	dep_table->count = (unsigned long)table->ucNumEntries;
397 
398 	for (i = 0; i < dep_table->count; i++) {
399 		dep_table->entries[i].clk =
400 			((unsigned long)table->entries[i].ucClockHigh << 16) |
401 			le16_to_cpu(table->entries[i].usClockLow);
402 		dep_table->entries[i].v =
403 			(unsigned long)le16_to_cpu(table->entries[i].usVoltage);
404 	}
405 
406 	*ptable = dep_table;
407 
408 	return 0;
409 }
410 
get_valid_clk(struct pp_hwmgr * hwmgr,struct phm_clock_array ** ptable,const struct phm_clock_voltage_dependency_table * table)411 static int get_valid_clk(struct pp_hwmgr *hwmgr,
412 			struct phm_clock_array **ptable,
413 			const struct phm_clock_voltage_dependency_table *table)
414 {
415 	unsigned long table_size, i;
416 	struct phm_clock_array *clock_table;
417 
418 	table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count;
419 	clock_table = kzalloc(table_size, GFP_KERNEL);
420 	if (NULL == clock_table)
421 		return -ENOMEM;
422 
423 	clock_table->count = (unsigned long)table->count;
424 
425 	for (i = 0; i < clock_table->count; i++)
426 		clock_table->values[i] = (unsigned long)table->entries[i].clk;
427 
428 	*ptable = clock_table;
429 
430 	return 0;
431 }
432 
get_clock_voltage_limit(struct pp_hwmgr * hwmgr,struct phm_clock_and_voltage_limits * limits,const ATOM_PPLIB_Clock_Voltage_Limit_Table * table)433 static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
434 			struct phm_clock_and_voltage_limits *limits,
435 			const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
436 {
437 	limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
438 			le16_to_cpu(table->entries[0].usSclkLow);
439 	limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
440 			le16_to_cpu(table->entries[0].usMclkLow);
441 	limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
442 	limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
443 
444 	return 0;
445 }
446 
447 
set_hw_cap(struct pp_hwmgr * hwmgr,bool enable,enum phm_platform_caps cap)448 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
449 		       enum phm_platform_caps cap)
450 {
451 	if (enable)
452 		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
453 	else
454 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
455 }
456 
set_platform_caps(struct pp_hwmgr * hwmgr,unsigned long powerplay_caps)457 static int set_platform_caps(struct pp_hwmgr *hwmgr,
458 			unsigned long powerplay_caps)
459 {
460 	set_hw_cap(
461 		hwmgr,
462 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
463 		PHM_PlatformCaps_PowerPlaySupport
464 	);
465 
466 	set_hw_cap(
467 		hwmgr,
468 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
469 		PHM_PlatformCaps_BiosPowerSourceControl
470 	);
471 
472 	set_hw_cap(
473 		hwmgr,
474 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
475 		PHM_PlatformCaps_EnableASPML0s
476 	);
477 
478 	set_hw_cap(
479 		hwmgr,
480 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
481 		PHM_PlatformCaps_EnableASPML1
482 	);
483 
484 	set_hw_cap(
485 		hwmgr,
486 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
487 		PHM_PlatformCaps_EnableBackbias
488 	);
489 
490 	set_hw_cap(
491 		hwmgr,
492 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
493 		PHM_PlatformCaps_AutomaticDCTransition
494 	);
495 
496 	set_hw_cap(
497 		hwmgr,
498 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
499 		PHM_PlatformCaps_GeminiPrimary
500 	);
501 
502 	set_hw_cap(
503 		hwmgr,
504 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
505 		PHM_PlatformCaps_StepVddc
506 	);
507 
508 	set_hw_cap(
509 		hwmgr,
510 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
511 		PHM_PlatformCaps_EnableVoltageControl
512 	);
513 
514 	set_hw_cap(
515 		hwmgr,
516 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
517 		PHM_PlatformCaps_EnableSideportControl
518 	);
519 
520 	set_hw_cap(
521 		hwmgr,
522 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
523 		PHM_PlatformCaps_TurnOffPll_ASPML1
524 	);
525 
526 	set_hw_cap(
527 		hwmgr,
528 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
529 		PHM_PlatformCaps_EnableHTLinkControl
530 	);
531 
532 	set_hw_cap(
533 		hwmgr,
534 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
535 		PHM_PlatformCaps_EnableMVDDControl
536 	);
537 
538 	set_hw_cap(
539 		hwmgr,
540 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
541 		PHM_PlatformCaps_ControlVDDCI
542 	);
543 
544 	set_hw_cap(
545 		hwmgr,
546 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
547 		PHM_PlatformCaps_RegulatorHot
548 	);
549 
550 	set_hw_cap(
551 		hwmgr,
552 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
553 		PHM_PlatformCaps_BootStateOnAlert
554 	);
555 
556 	set_hw_cap(
557 		hwmgr,
558 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
559 		PHM_PlatformCaps_DontWaitForVBlankOnAlert
560 	);
561 
562 	set_hw_cap(
563 		hwmgr,
564 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
565 		PHM_PlatformCaps_BACO
566 	);
567 
568 	set_hw_cap(
569 		hwmgr,
570 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
571 		PHM_PlatformCaps_NewCACVoltage
572 	);
573 
574 	set_hw_cap(
575 		hwmgr,
576 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
577 		PHM_PlatformCaps_RevertGPIO5Polarity
578 	);
579 
580 	set_hw_cap(
581 		hwmgr,
582 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
583 		PHM_PlatformCaps_Thermal2GPIO17
584 	);
585 
586 	set_hw_cap(
587 		hwmgr,
588 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
589 		PHM_PlatformCaps_VRHotGPIOConfigurable
590 	);
591 
592 	set_hw_cap(
593 		hwmgr,
594 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
595 		PHM_PlatformCaps_TempInversion
596 	);
597 
598 	set_hw_cap(
599 		hwmgr,
600 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
601 		PHM_PlatformCaps_EVV
602 	);
603 
604 	set_hw_cap(
605 		hwmgr,
606 		0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
607 		PHM_PlatformCaps_CombinePCCWithThermalSignal
608 	);
609 
610 	set_hw_cap(
611 		hwmgr,
612 		0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
613 		PHM_PlatformCaps_LoadPostProductionFirmware
614 	);
615 
616 	set_hw_cap(
617 		hwmgr,
618 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
619 		PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
620 	);
621 
622 	return 0;
623 }
624 
make_classification_flags(struct pp_hwmgr * hwmgr,USHORT classification,USHORT classification2)625 static PP_StateClassificationFlags make_classification_flags(
626 						   struct pp_hwmgr *hwmgr,
627 						    USHORT classification,
628 						   USHORT classification2)
629 {
630 	PP_StateClassificationFlags result = 0;
631 
632 	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
633 		result |= PP_StateClassificationFlag_Boot;
634 
635 	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
636 		result |= PP_StateClassificationFlag_Thermal;
637 
638 	if (classification &
639 			ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
640 		result |= PP_StateClassificationFlag_LimitedPowerSource;
641 
642 	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
643 		result |= PP_StateClassificationFlag_Rest;
644 
645 	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
646 		result |= PP_StateClassificationFlag_Forced;
647 
648 	if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
649 		result |= PP_StateClassificationFlag_3DPerformance;
650 
651 
652 	if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
653 		result |= PP_StateClassificationFlag_ACOverdriveTemplate;
654 
655 	if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
656 		result |= PP_StateClassificationFlag_Uvd;
657 
658 	if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
659 		result |= PP_StateClassificationFlag_UvdHD;
660 
661 	if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
662 		result |= PP_StateClassificationFlag_UvdSD;
663 
664 	if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
665 		result |= PP_StateClassificationFlag_HD2;
666 
667 	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
668 		result |= PP_StateClassificationFlag_ACPI;
669 
670 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
671 		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
672 
673 
674 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
675 		result |= PP_StateClassificationFlag_ULV;
676 
677 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
678 		result |= PP_StateClassificationFlag_UvdMVC;
679 
680 	return result;
681 }
682 
init_non_clock_fields(struct pp_hwmgr * hwmgr,struct pp_power_state * ps,uint8_t version,const ATOM_PPLIB_NONCLOCK_INFO * pnon_clock_info)683 static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
684 						struct pp_power_state *ps,
685 							    uint8_t version,
686 			 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
687 	unsigned long rrr_index;
688 	unsigned long tmp;
689 
690 	ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
691 					ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
692 	ps->classification.flags = make_classification_flags(hwmgr,
693 				le16_to_cpu(pnon_clock_info->usClassification),
694 				le16_to_cpu(pnon_clock_info->usClassification2));
695 
696 	ps->classification.temporary_state = false;
697 	ps->classification.to_be_deleted = false;
698 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
699 		ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
700 
701 	ps->validation.singleDisplayOnly = (0 != tmp);
702 
703 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
704 		ATOM_PPLIB_DISALLOW_ON_DC;
705 
706 	ps->validation.disallowOnDC = (0 != tmp);
707 
708 	ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
709 				ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
710 				ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
711 
712 	ps->pcie.lanes = 0;
713 
714 	ps->display.disableFrameModulation = false;
715 
716 	rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
717 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
718 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
719 
720 	if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
721 		static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
722 								{ 0, 50, 0 };
723 
724 		ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
725 		ps->display.explicitRefreshrate = look_up[rrr_index];
726 		ps->display.limitRefreshrate = true;
727 
728 		if (ps->display.explicitRefreshrate == 0)
729 			ps->display.limitRefreshrate = false;
730 	} else
731 		ps->display.limitRefreshrate = false;
732 
733 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
734 		ATOM_PPLIB_ENABLE_VARIBRIGHT;
735 
736 	ps->display.enableVariBright = (0 != tmp);
737 
738 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
739 		ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
740 
741 	ps->memory.dllOff = (0 != tmp);
742 
743 	ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
744 			    ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
745 
746 	ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
747 				     pnon_clock_info->ucMinTemperature;
748 
749 	ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
750 				     pnon_clock_info->ucMaxTemperature;
751 
752 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
753 		ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
754 
755 	ps->software.disableLoadBalancing = tmp;
756 
757 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
758 		ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
759 
760 	ps->software.enableSleepForTimestamps = (0 != tmp);
761 
762 	ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
763 
764 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
765 		ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
766 		ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
767 	} else {
768 		ps->uvd_clocks.VCLK = 0;
769 		ps->uvd_clocks.DCLK = 0;
770 	}
771 
772 	return 0;
773 }
774 
size_of_entry_v2(ULONG num_dpm_levels)775 static ULONG size_of_entry_v2(ULONG num_dpm_levels)
776 {
777 	return (sizeof(UCHAR) + sizeof(UCHAR) +
778 			(num_dpm_levels * sizeof(UCHAR)));
779 }
780 
get_state_entry_v2(const StateArray * pstate_arrays,ULONG entry_index)781 static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
782 					const StateArray * pstate_arrays,
783 							 ULONG entry_index)
784 {
785 	ULONG i;
786 	const ATOM_PPLIB_STATE_V2 *pstate;
787 
788 	pstate = pstate_arrays->states;
789 	if (entry_index <= pstate_arrays->ucNumEntries) {
790 		for (i = 0; i < entry_index; i++)
791 			pstate = (ATOM_PPLIB_STATE_V2 *)(
792 						  (unsigned long)pstate +
793 			     size_of_entry_v2(pstate->ucNumDPMLevels));
794 	}
795 	return pstate;
796 }
797 
798 static const unsigned char soft_dummy_pp_table[] = {
799 	0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
800 	0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
801 	0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
802 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
804 	0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
805 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
806 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
809 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
810 	0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
811 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
812 	0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
813 	0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
814 	0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
815 	0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
816 	0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
817 	0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
818 	0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
819 	0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
820 	0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
821 	0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
822 	0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
823 	0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
824 	0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
825 	0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
826 	0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
827 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
828 	0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
829 	0x00
830 };
831 
get_powerplay_table(struct pp_hwmgr * hwmgr)832 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
833 				     struct pp_hwmgr *hwmgr)
834 {
835 	const void *table_addr = hwmgr->soft_pp_table;
836 	uint8_t frev, crev;
837 	uint16_t size;
838 
839 	if (!table_addr) {
840 		if (hwmgr->chip_id == CHIP_RAVEN) {
841 			table_addr = &soft_dummy_pp_table[0];
842 			hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
843 			hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
844 		} else {
845 			table_addr = smu_atom_get_data_table(hwmgr->adev,
846 					GetIndexIntoMasterTable(DATA, PowerPlayInfo),
847 					&size, &frev, &crev);
848 			hwmgr->soft_pp_table = table_addr;
849 			hwmgr->soft_pp_table_size = size;
850 		}
851 	}
852 
853 	return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
854 }
855 
pp_tables_get_response_times(struct pp_hwmgr * hwmgr,uint32_t * vol_rep_time,uint32_t * bb_rep_time)856 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
857 				uint32_t *vol_rep_time, uint32_t *bb_rep_time)
858 {
859 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
860 
861 	PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
862 			    "Missing PowerPlay Table!", return -EINVAL);
863 
864 	*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
865 	*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
866 
867 	return 0;
868 }
869 
pp_tables_get_num_of_entries(struct pp_hwmgr * hwmgr,unsigned long * num_of_entries)870 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
871 				     unsigned long *num_of_entries)
872 {
873 	const StateArray *pstate_arrays;
874 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
875 
876 	if (powerplay_table == NULL)
877 		return -1;
878 
879 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
880 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
881 					le16_to_cpu(powerplay_table->usStateArrayOffset));
882 
883 		*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
884 	} else
885 		*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
886 
887 	return 0;
888 }
889 
pp_tables_get_entry(struct pp_hwmgr * hwmgr,unsigned long entry_index,struct pp_power_state * ps,pp_tables_hw_clock_info_callback func)890 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
891 				unsigned long entry_index,
892 				struct pp_power_state *ps,
893 			 pp_tables_hw_clock_info_callback func)
894 {
895 	int i;
896 	const StateArray *pstate_arrays;
897 	const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
898 	const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
899 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
900 	int result = 0;
901 	int res = 0;
902 
903 	const ClockInfoArray *pclock_arrays;
904 
905 	const NonClockInfoArray *pnon_clock_arrays;
906 
907 	const ATOM_PPLIB_STATE *pstate_entry;
908 
909 	if (powerplay_table == NULL)
910 		return -1;
911 
912 	ps->classification.bios_index = entry_index;
913 
914 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
915 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
916 					le16_to_cpu(powerplay_table->usStateArrayOffset));
917 
918 		if (entry_index > pstate_arrays->ucNumEntries)
919 			return -1;
920 
921 		pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
922 		pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
923 					le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
924 
925 		pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
926 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
927 
928 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
929 					(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
930 
931 		result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
932 
933 		for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
934 			const void *pclock_info = (const void *)(
935 							(unsigned long)(pclock_arrays->clockInfo) +
936 							(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
937 			res = func(hwmgr, &ps->hardware, i, pclock_info);
938 			if ((0 == result) && (0 != res))
939 				result = res;
940 		}
941 	} else {
942 		if (entry_index > powerplay_table->ucNumStates)
943 			return -1;
944 
945 		pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
946 						    le16_to_cpu(powerplay_table->usStateArrayOffset) +
947 						    entry_index * powerplay_table->ucStateEntrySize);
948 
949 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
950 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
951 						pstate_entry->ucNonClockStateIndex *
952 						powerplay_table->ucNonClockSize);
953 
954 		result = init_non_clock_fields(hwmgr, ps,
955 							powerplay_table->ucNonClockSize,
956 							pnon_clock_info);
957 
958 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
959 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
960 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
961 						pstate_entry->ucClockStateIndices[i] *
962 						powerplay_table->ucClockInfoSize);
963 
964 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
965 
966 			if ((0 == result) && (0 != res))
967 					result = res;
968 		}
969 	}
970 
971 	if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
972 		if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
973 			result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
974 	}
975 
976 	return result;
977 }
978 
init_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)979 static int init_powerplay_tables(
980 			struct pp_hwmgr *hwmgr,
981 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
982 )
983 {
984 	return 0;
985 }
986 
987 
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)988 static int init_thermal_controller(
989 			struct pp_hwmgr *hwmgr,
990 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
991 {
992 	return 0;
993 }
994 
init_overdrive_limits_V1_4(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V1_4 * fw_info)995 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
996 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
997 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
998 {
999 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
1000 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
1001 
1002 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1003 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1004 
1005 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1006 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1007 
1008 	hwmgr->platform_descriptor.minOverdriveVDDC =
1009 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1010 
1011 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1012 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1013 
1014 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1015 	return 0;
1016 }
1017 
init_overdrive_limits_V2_1(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V2_1 * fw_info)1018 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1019 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1020 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1021 {
1022 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1023 	const ATOM_PPLIB_EXTENDEDHEADER *header;
1024 
1025 	if (le16_to_cpu(powerplay_table->usTableSize) <
1026 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1027 		return 0;
1028 
1029 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1030 
1031 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
1032 		return 0;
1033 
1034 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1035 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1036 
1037 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1038 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1039 
1040 
1041 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1042 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1043 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1044 
1045 	return 0;
1046 }
1047 
init_overdrive_limits(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1048 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1049 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1050 {
1051 	int result = 0;
1052 	uint8_t frev, crev;
1053 	uint16_t size;
1054 
1055 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1056 
1057 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1058 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1059 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1060 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1061 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1062 
1063 	if (hwmgr->chip_id == CHIP_RAVEN)
1064 		return 0;
1065 
1066 	/* We assume here that fw_info is unchanged if this call fails.*/
1067 	fw_info = smu_atom_get_data_table(hwmgr->adev,
1068 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1069 			 &size, &frev, &crev);
1070 
1071 	if ((fw_info->ucTableFormatRevision == 1)
1072 	    && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1073 		result = init_overdrive_limits_V1_4(hwmgr,
1074 				powerplay_table,
1075 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1076 
1077 	else if ((fw_info->ucTableFormatRevision == 2)
1078 		 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1079 		result = init_overdrive_limits_V2_1(hwmgr,
1080 				powerplay_table,
1081 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1082 
1083 	return result;
1084 }
1085 
get_uvd_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_uvd_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table * table,const UVDClockInfoArray * array)1086 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1087 		struct phm_uvd_clock_voltage_dependency_table **ptable,
1088 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1089 		const UVDClockInfoArray *array)
1090 {
1091 	unsigned long table_size, i;
1092 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1093 
1094 	table_size = sizeof(unsigned long) +
1095 		 sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1096 		 table->numEntries;
1097 
1098 	uvd_table = kzalloc(table_size, GFP_KERNEL);
1099 	if (NULL == uvd_table)
1100 		return -ENOMEM;
1101 
1102 	uvd_table->count = table->numEntries;
1103 
1104 	for (i = 0; i < table->numEntries; i++) {
1105 		const UVDClockInfo *entry =
1106 			&array->entries[table->entries[i].ucUVDClockInfoIndex];
1107 		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1108 		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1109 					 | le16_to_cpu(entry->usVClkLow);
1110 		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1111 					 | le16_to_cpu(entry->usDClkLow);
1112 	}
1113 
1114 	*ptable = uvd_table;
1115 
1116 	return 0;
1117 }
1118 
get_vce_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_vce_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table * table,const VCEClockInfoArray * array)1119 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1120 		struct phm_vce_clock_voltage_dependency_table **ptable,
1121 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1122 		const VCEClockInfoArray    *array)
1123 {
1124 	unsigned long table_size, i;
1125 	struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1126 
1127 	table_size = sizeof(unsigned long) +
1128 			sizeof(struct phm_vce_clock_voltage_dependency_table)
1129 			* table->numEntries;
1130 
1131 	vce_table = kzalloc(table_size, GFP_KERNEL);
1132 	if (NULL == vce_table)
1133 		return -ENOMEM;
1134 
1135 	vce_table->count = table->numEntries;
1136 	for (i = 0; i < table->numEntries; i++) {
1137 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1138 
1139 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1140 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1141 					| le16_to_cpu(entry->usEVClkLow);
1142 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1143 					| le16_to_cpu(entry->usECClkLow);
1144 	}
1145 
1146 	*ptable = vce_table;
1147 
1148 	return 0;
1149 }
1150 
get_samu_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_samu_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_SAMClk_Voltage_Limit_Table * table)1151 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1152 		 struct phm_samu_clock_voltage_dependency_table **ptable,
1153 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1154 {
1155 	unsigned long table_size, i;
1156 	struct phm_samu_clock_voltage_dependency_table *samu_table;
1157 
1158 	table_size = sizeof(unsigned long) +
1159 		sizeof(struct phm_samu_clock_voltage_dependency_table) *
1160 		table->numEntries;
1161 
1162 	samu_table = kzalloc(table_size, GFP_KERNEL);
1163 	if (NULL == samu_table)
1164 		return -ENOMEM;
1165 
1166 	samu_table->count = table->numEntries;
1167 
1168 	for (i = 0; i < table->numEntries; i++) {
1169 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1170 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1171 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
1172 	}
1173 
1174 	*ptable = samu_table;
1175 
1176 	return 0;
1177 }
1178 
get_acp_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_acp_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_ACPClk_Voltage_Limit_Table * table)1179 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1180 		struct phm_acp_clock_voltage_dependency_table **ptable,
1181 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1182 {
1183 	unsigned table_size, i;
1184 	struct phm_acp_clock_voltage_dependency_table *acp_table;
1185 
1186 	table_size = sizeof(unsigned long) +
1187 		sizeof(struct phm_acp_clock_voltage_dependency_table) *
1188 		table->numEntries;
1189 
1190 	acp_table = kzalloc(table_size, GFP_KERNEL);
1191 	if (NULL == acp_table)
1192 		return -ENOMEM;
1193 
1194 	acp_table->count = (unsigned long)table->numEntries;
1195 
1196 	for (i = 0; i < table->numEntries; i++) {
1197 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1198 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1199 					 | le16_to_cpu(table->entries[i].usACPClockLow);
1200 	}
1201 
1202 	*ptable = acp_table;
1203 
1204 	return 0;
1205 }
1206 
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1207 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1208 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1209 {
1210 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1211 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1212 	int result = 0;
1213 
1214 	uint16_t vce_clock_info_array_offset;
1215 	uint16_t uvd_clock_info_array_offset;
1216 	uint16_t table_offset;
1217 
1218 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1219 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1220 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1221 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1222 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1223 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1224 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1225 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1226 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1227 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1228 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1229 
1230 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1231 						hwmgr, powerplay_table);
1232 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1233 						powerplay_table);
1234 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1235 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1236 				(((unsigned long) powerplay_table) +
1237 				vce_clock_info_array_offset);
1238 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1239 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1240 				(((unsigned long) powerplay_table) + table_offset);
1241 		result = get_vce_clock_voltage_limit_table(hwmgr,
1242 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1243 				table, array);
1244 	}
1245 
1246 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1247 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1248 
1249 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1250 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1251 				(((unsigned long) powerplay_table) +
1252 				uvd_clock_info_array_offset);
1253 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1254 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1255 				(((unsigned long) powerplay_table) + table_offset);
1256 		result = get_uvd_clock_voltage_limit_table(hwmgr,
1257 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1258 	}
1259 
1260 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1261 							    powerplay_table);
1262 
1263 	if (table_offset > 0) {
1264 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1265 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1266 				(((unsigned long) powerplay_table) + table_offset);
1267 		result = get_samu_clock_voltage_limit_table(hwmgr,
1268 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1269 	}
1270 
1271 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1272 							     powerplay_table);
1273 
1274 	if (table_offset > 0) {
1275 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1276 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1277 				(((unsigned long) powerplay_table) + table_offset);
1278 		result = get_acp_clock_voltage_limit_table(hwmgr,
1279 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1280 	}
1281 
1282 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1283 	if (table_offset > 0) {
1284 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1285 
1286 		if (rev_id > 0) {
1287 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1288 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1289 				(((unsigned long) powerplay_table) + table_offset);
1290 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1291 				&tune_table->power_tune_table,
1292 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1293 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1294 				le16_to_cpu(tune_table->usTjMax);
1295 		} else {
1296 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1297 				(const ATOM_PPLIB_POWERTUNE_Table *)
1298 				(((unsigned long) powerplay_table) + table_offset);
1299 			result = get_cac_tdp_table(hwmgr,
1300 				&hwmgr->dyn_state.cac_dtp_table,
1301 				&tune_table->power_tune_table, 255);
1302 		}
1303 	}
1304 
1305 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1306 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1307 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1308 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1309 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1310 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1311 				(((unsigned long) powerplay_table4) +
1312 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1313 			result = get_clock_voltage_dependency_table(hwmgr,
1314 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1315 		}
1316 
1317 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1318 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1319 				(((unsigned long) powerplay_table4) +
1320 				 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1321 			result = get_clock_voltage_dependency_table(hwmgr,
1322 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1323 		}
1324 
1325 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1326 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1327 				(((unsigned long) powerplay_table4) +
1328 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1329 			result = get_clock_voltage_dependency_table(hwmgr,
1330 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1331 		}
1332 
1333 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1334 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1335 				(((unsigned long) powerplay_table4) +
1336 				 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1337 			result = get_clock_voltage_limit(hwmgr,
1338 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1339 		}
1340 
1341 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1342 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1343 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1344 					hwmgr->dyn_state.vddc_dependency_on_mclk);
1345 
1346 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1347 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1348 			result = get_valid_clk(hwmgr,
1349 				&hwmgr->dyn_state.valid_sclk_values,
1350 				hwmgr->dyn_state.vddc_dependency_on_sclk);
1351 
1352 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1353 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1354 				(((unsigned long) powerplay_table4) +
1355 				 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1356 			result = get_clock_voltage_dependency_table(hwmgr,
1357 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1358 		}
1359 	}
1360 
1361 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1362 								powerplay_table);
1363 
1364 	if (table_offset > 0) {
1365 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1366 			(((unsigned long) powerplay_table) + table_offset);
1367 		result = get_clock_voltage_dependency_table(hwmgr,
1368 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1369 	}
1370 
1371 	return result;
1372 }
1373 
get_cac_leakage_table(struct pp_hwmgr * hwmgr,struct phm_cac_leakage_table ** ptable,const ATOM_PPLIB_CAC_Leakage_Table * table)1374 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1375 				 struct phm_cac_leakage_table **ptable,
1376 				const ATOM_PPLIB_CAC_Leakage_Table *table)
1377 {
1378 	struct phm_cac_leakage_table  *cac_leakage_table;
1379 	unsigned long            table_size, i;
1380 
1381 	if (hwmgr == NULL || table == NULL || ptable == NULL)
1382 		return -EINVAL;
1383 
1384 	table_size = sizeof(ULONG) +
1385 		(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1386 
1387 	cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1388 
1389 	if (cac_leakage_table == NULL)
1390 		return -ENOMEM;
1391 
1392 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
1393 
1394 	for (i = 0; i < cac_leakage_table->count; i++) {
1395 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1396 				PHM_PlatformCaps_EVV)) {
1397 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1398 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1399 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1400 		} else {
1401 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1402 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1403 		}
1404 	}
1405 
1406 	*ptable = cac_leakage_table;
1407 
1408 	return 0;
1409 }
1410 
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_PPLIB_PPM_Table * atom_ppm_table)1411 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1412 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
1413 {
1414 	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1415 
1416 	if (NULL == ptr)
1417 		return -ENOMEM;
1418 
1419 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1420 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1421 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1422 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1423 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1424 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1425 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1426 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1427 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1428 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1429 	hwmgr->dyn_state.ppm_parameter_table = ptr;
1430 
1431 	return 0;
1432 }
1433 
init_dpm2_parameters(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1434 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1435 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1436 {
1437 	int result = 0;
1438 
1439 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1440 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1441 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1442 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1443 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1444 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1445 				(&ptable5->basicTable4);
1446 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1447 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1448 				(&ptable4->basicTable3);
1449 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1450 		uint16_t table_offset;
1451 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
1452 
1453 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1454 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1455 
1456 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1457 		hwmgr->platform_descriptor.TDPAdjustment = 0;
1458 
1459 		hwmgr->platform_descriptor.VidAdjustment = 0;
1460 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1461 		hwmgr->platform_descriptor.VidMinLimit     = 0;
1462 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1463 		hwmgr->platform_descriptor.VidStep         = 6250;
1464 
1465 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1466 
1467 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
1468 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1469 					PHM_PlatformCaps_PowerControl);
1470 
1471 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1472 
1473 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1474 
1475 		hwmgr->dyn_state.cac_leakage_table = NULL;
1476 
1477 		if (0 != ptable5->usCACLeakageTableOffset) {
1478 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1479 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1480 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
1481 			result = get_cac_leakage_table(hwmgr,
1482 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1483 		}
1484 
1485 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1486 
1487 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1488 
1489 		if (0 != ptable3->usExtendendedHeaderOffset) {
1490 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1491 					(((unsigned long)powerplay_table) +
1492 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1493 			if ((extended_header->usPPMTableOffset > 0) &&
1494 				le16_to_cpu(extended_header->usSize) >=
1495 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1496 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1497 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1498 					(((unsigned long)powerplay_table) + table_offset);
1499 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1500 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1501 						PHM_PlatformCaps_EnablePlatformPowerManagement);
1502 			}
1503 		}
1504 	}
1505 	return result;
1506 }
1507 
init_phase_shedding_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1508 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1509 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1510 {
1511 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1512 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1513 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1514 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1515 
1516 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1517 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1518 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1519 				(((unsigned long)powerplay_table4) +
1520 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1521 			struct phm_phase_shedding_limits_table *table;
1522 			unsigned long size, i;
1523 
1524 
1525 			size = sizeof(unsigned long) +
1526 				(sizeof(struct phm_phase_shedding_limits_table) *
1527 				ptable->ucNumEntries);
1528 
1529 			table = kzalloc(size, GFP_KERNEL);
1530 
1531 			if (table == NULL)
1532 				return -ENOMEM;
1533 
1534 			table->count = (unsigned long)ptable->ucNumEntries;
1535 
1536 			for (i = 0; i < table->count; i++) {
1537 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1538 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1539 							| le16_to_cpu(ptable->entries[i].usSclkLow);
1540 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1541 							| le16_to_cpu(ptable->entries[i].usMclkLow);
1542 			}
1543 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1544 		}
1545 	}
1546 
1547 	return 0;
1548 }
1549 
get_number_of_vce_state_table_entries(struct pp_hwmgr * hwmgr)1550 static int get_number_of_vce_state_table_entries(
1551 						  struct pp_hwmgr *hwmgr)
1552 {
1553 	const ATOM_PPLIB_POWERPLAYTABLE *table =
1554 					     get_powerplay_table(hwmgr);
1555 	const ATOM_PPLIB_VCE_State_Table *vce_table =
1556 				    get_vce_state_table(hwmgr, table);
1557 
1558 	if (vce_table)
1559 		return vce_table->numEntries;
1560 
1561 	return 0;
1562 }
1563 
get_vce_state_table_entry(struct pp_hwmgr * hwmgr,unsigned long i,struct amd_vce_state * vce_state,void ** clock_info,unsigned long * flag)1564 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1565 							unsigned long i,
1566 							struct amd_vce_state *vce_state,
1567 							void **clock_info,
1568 							unsigned long *flag)
1569 {
1570 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1571 
1572 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1573 
1574 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1575 
1576 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1577 
1578 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1579 								le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1580 
1581 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1582 
1583 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1584 
1585 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1586 
1587 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1588 
1589 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1590 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1591 
1592 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1593 
1594 	return 0;
1595 }
1596 
1597 
pp_tables_initialize(struct pp_hwmgr * hwmgr)1598 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1599 {
1600 	int result;
1601 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1602 
1603 	if (hwmgr->chip_id == CHIP_RAVEN)
1604 		return 0;
1605 
1606 	hwmgr->need_pp_table_upload = true;
1607 
1608 	powerplay_table = get_powerplay_table(hwmgr);
1609 
1610 	result = init_powerplay_tables(hwmgr, powerplay_table);
1611 
1612 	PP_ASSERT_WITH_CODE((result == 0),
1613 			    "init_powerplay_tables failed", return result);
1614 
1615 	result = set_platform_caps(hwmgr,
1616 				le32_to_cpu(powerplay_table->ulPlatformCaps));
1617 
1618 	PP_ASSERT_WITH_CODE((result == 0),
1619 			    "set_platform_caps failed", return result);
1620 
1621 	result = init_thermal_controller(hwmgr, powerplay_table);
1622 
1623 	PP_ASSERT_WITH_CODE((result == 0),
1624 			    "init_thermal_controller failed", return result);
1625 
1626 	result = init_overdrive_limits(hwmgr, powerplay_table);
1627 
1628 	PP_ASSERT_WITH_CODE((result == 0),
1629 			    "init_overdrive_limits failed", return result);
1630 
1631 	result = init_clock_voltage_dependency(hwmgr,
1632 					       powerplay_table);
1633 
1634 	PP_ASSERT_WITH_CODE((result == 0),
1635 			    "init_clock_voltage_dependency failed", return result);
1636 
1637 	result = init_dpm2_parameters(hwmgr, powerplay_table);
1638 
1639 	PP_ASSERT_WITH_CODE((result == 0),
1640 			    "init_dpm2_parameters failed", return result);
1641 
1642 	result = init_phase_shedding_table(hwmgr, powerplay_table);
1643 
1644 	PP_ASSERT_WITH_CODE((result == 0),
1645 			    "init_phase_shedding_table failed", return result);
1646 
1647 	return result;
1648 }
1649 
pp_tables_uninitialize(struct pp_hwmgr * hwmgr)1650 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1651 {
1652 	if (hwmgr->chip_id == CHIP_RAVEN)
1653 		return 0;
1654 
1655 	kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1656 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1657 
1658 	kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1659 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1660 
1661 	kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1662 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1663 
1664 	kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1665 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1666 
1667 	kfree(hwmgr->dyn_state.valid_mclk_values);
1668 	hwmgr->dyn_state.valid_mclk_values = NULL;
1669 
1670 	kfree(hwmgr->dyn_state.valid_sclk_values);
1671 	hwmgr->dyn_state.valid_sclk_values = NULL;
1672 
1673 	kfree(hwmgr->dyn_state.cac_leakage_table);
1674 	hwmgr->dyn_state.cac_leakage_table = NULL;
1675 
1676 	kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1677 	hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1678 
1679 	kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1680 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1681 
1682 	kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1683 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1684 
1685 	kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1686 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1687 
1688 	kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1689 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1690 
1691 	kfree(hwmgr->dyn_state.cac_dtp_table);
1692 	hwmgr->dyn_state.cac_dtp_table = NULL;
1693 
1694 	kfree(hwmgr->dyn_state.ppm_parameter_table);
1695 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1696 
1697 	kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1698 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1699 
1700 	return 0;
1701 }
1702 
1703 const struct pp_table_func pptable_funcs = {
1704 	.pptable_init = pp_tables_initialize,
1705 	.pptable_fini = pp_tables_uninitialize,
1706 	.pptable_get_number_of_vce_state_table_entries =
1707 				get_number_of_vce_state_table_entries,
1708 	.pptable_get_vce_state_table_entry =
1709 						get_vce_state_table_entry,
1710 };
1711 
1712