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