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