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