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 = le32_to_cpu(pnon_clock_info->ulVCLK);
761 		ps->uvd_clocks.DCLK = le32_to_cpu(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 +
941 						    le16_to_cpu(powerplay_table->usStateArrayOffset) +
942 						    entry_index * powerplay_table->ucStateEntrySize);
943 
944 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
945 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
946 						pstate_entry->ucNonClockStateIndex *
947 						powerplay_table->ucNonClockSize);
948 
949 		result = init_non_clock_fields(hwmgr, ps,
950 							powerplay_table->ucNonClockSize,
951 							pnon_clock_info);
952 
953 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
954 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
955 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
956 						pstate_entry->ucClockStateIndices[i] *
957 						powerplay_table->ucClockInfoSize);
958 
959 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
960 
961 			if ((0 == result) && (0 != res))
962 					result = res;
963 		}
964 	}
965 
966 	if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
967 		if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
968 			result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
969 	}
970 
971 	return result;
972 }
973 
974 static int init_powerplay_tables(
975 			struct pp_hwmgr *hwmgr,
976 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
977 )
978 {
979 	return 0;
980 }
981 
982 
983 static int init_thermal_controller(
984 			struct pp_hwmgr *hwmgr,
985 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
986 {
987 	hwmgr->thermal_controller.ucType =
988 			powerplay_table->sThermalController.ucType;
989 	hwmgr->thermal_controller.ucI2cLine =
990 			powerplay_table->sThermalController.ucI2cLine;
991 	hwmgr->thermal_controller.ucI2cAddress =
992 			powerplay_table->sThermalController.ucI2cAddress;
993 
994 	hwmgr->thermal_controller.fanInfo.bNoFan =
995 		(0 != (powerplay_table->sThermalController.ucFanParameters &
996 			ATOM_PP_FANPARAMETERS_NOFAN));
997 
998 	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
999 		powerplay_table->sThermalController.ucFanParameters &
1000 		ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
1001 
1002 	hwmgr->thermal_controller.fanInfo.ulMinRPM
1003 		= powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1004 	hwmgr->thermal_controller.fanInfo.ulMaxRPM
1005 		= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1006 
1007 	set_hw_cap(hwmgr,
1008 		   ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1009 		   PHM_PlatformCaps_ThermalController);
1010 
1011 	hwmgr->thermal_controller.use_hw_fan_control = 1;
1012 
1013 	return 0;
1014 }
1015 
1016 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
1017 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1018 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
1019 {
1020 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
1021 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
1022 
1023 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1024 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1025 
1026 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1027 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1028 
1029 	hwmgr->platform_descriptor.minOverdriveVDDC =
1030 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1031 
1032 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1033 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1034 
1035 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1036 	return 0;
1037 }
1038 
1039 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1040 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1041 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1042 {
1043 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1044 	const ATOM_PPLIB_EXTENDEDHEADER *header;
1045 
1046 	if (le16_to_cpu(powerplay_table->usTableSize) <
1047 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1048 		return 0;
1049 
1050 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1051 
1052 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
1053 		return 0;
1054 
1055 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1056 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1057 
1058 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1059 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1060 
1061 
1062 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1063 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1064 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1065 
1066 	return 0;
1067 }
1068 
1069 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1070 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1071 {
1072 	int result = 0;
1073 	uint8_t frev, crev;
1074 	uint16_t size;
1075 
1076 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1077 
1078 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1079 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1080 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1081 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1082 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1083 
1084 	if (hwmgr->chip_id == CHIP_RAVEN)
1085 		return 0;
1086 
1087 	/* We assume here that fw_info is unchanged if this call fails.*/
1088 	fw_info = smu_atom_get_data_table(hwmgr->adev,
1089 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1090 			 &size, &frev, &crev);
1091 
1092 	if ((fw_info->ucTableFormatRevision == 1)
1093 	    && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1094 		result = init_overdrive_limits_V1_4(hwmgr,
1095 				powerplay_table,
1096 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1097 
1098 	else if ((fw_info->ucTableFormatRevision == 2)
1099 		 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1100 		result = init_overdrive_limits_V2_1(hwmgr,
1101 				powerplay_table,
1102 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1103 
1104 	return result;
1105 }
1106 
1107 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1108 		struct phm_uvd_clock_voltage_dependency_table **ptable,
1109 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1110 		const UVDClockInfoArray *array)
1111 {
1112 	unsigned long table_size, i;
1113 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1114 
1115 	table_size = sizeof(unsigned long) +
1116 		 sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1117 		 table->numEntries;
1118 
1119 	uvd_table = kzalloc(table_size, GFP_KERNEL);
1120 	if (NULL == uvd_table)
1121 		return -ENOMEM;
1122 
1123 	uvd_table->count = table->numEntries;
1124 
1125 	for (i = 0; i < table->numEntries; i++) {
1126 		const UVDClockInfo *entry =
1127 			&array->entries[table->entries[i].ucUVDClockInfoIndex];
1128 		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1129 		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1130 					 | le16_to_cpu(entry->usVClkLow);
1131 		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1132 					 | le16_to_cpu(entry->usDClkLow);
1133 	}
1134 
1135 	*ptable = uvd_table;
1136 
1137 	return 0;
1138 }
1139 
1140 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1141 		struct phm_vce_clock_voltage_dependency_table **ptable,
1142 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1143 		const VCEClockInfoArray    *array)
1144 {
1145 	unsigned long table_size, i;
1146 	struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1147 
1148 	table_size = sizeof(unsigned long) +
1149 			sizeof(struct phm_vce_clock_voltage_dependency_table)
1150 			* table->numEntries;
1151 
1152 	vce_table = kzalloc(table_size, GFP_KERNEL);
1153 	if (NULL == vce_table)
1154 		return -ENOMEM;
1155 
1156 	vce_table->count = table->numEntries;
1157 	for (i = 0; i < table->numEntries; i++) {
1158 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1159 
1160 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1161 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1162 					| le16_to_cpu(entry->usEVClkLow);
1163 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1164 					| le16_to_cpu(entry->usECClkLow);
1165 	}
1166 
1167 	*ptable = vce_table;
1168 
1169 	return 0;
1170 }
1171 
1172 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1173 		 struct phm_samu_clock_voltage_dependency_table **ptable,
1174 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1175 {
1176 	unsigned long table_size, i;
1177 	struct phm_samu_clock_voltage_dependency_table *samu_table;
1178 
1179 	table_size = sizeof(unsigned long) +
1180 		sizeof(struct phm_samu_clock_voltage_dependency_table) *
1181 		table->numEntries;
1182 
1183 	samu_table = kzalloc(table_size, GFP_KERNEL);
1184 	if (NULL == samu_table)
1185 		return -ENOMEM;
1186 
1187 	samu_table->count = table->numEntries;
1188 
1189 	for (i = 0; i < table->numEntries; i++) {
1190 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1191 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1192 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
1193 	}
1194 
1195 	*ptable = samu_table;
1196 
1197 	return 0;
1198 }
1199 
1200 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1201 		struct phm_acp_clock_voltage_dependency_table **ptable,
1202 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1203 {
1204 	unsigned table_size, i;
1205 	struct phm_acp_clock_voltage_dependency_table *acp_table;
1206 
1207 	table_size = sizeof(unsigned long) +
1208 		sizeof(struct phm_acp_clock_voltage_dependency_table) *
1209 		table->numEntries;
1210 
1211 	acp_table = kzalloc(table_size, GFP_KERNEL);
1212 	if (NULL == acp_table)
1213 		return -ENOMEM;
1214 
1215 	acp_table->count = (unsigned long)table->numEntries;
1216 
1217 	for (i = 0; i < table->numEntries; i++) {
1218 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1219 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1220 					 | le16_to_cpu(table->entries[i].usACPClockLow);
1221 	}
1222 
1223 	*ptable = acp_table;
1224 
1225 	return 0;
1226 }
1227 
1228 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1229 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1230 {
1231 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1232 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1233 	int result = 0;
1234 
1235 	uint16_t vce_clock_info_array_offset;
1236 	uint16_t uvd_clock_info_array_offset;
1237 	uint16_t table_offset;
1238 
1239 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1240 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1241 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1242 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1243 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1244 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1245 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1246 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1247 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1248 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1249 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1250 
1251 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1252 						hwmgr, powerplay_table);
1253 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1254 						powerplay_table);
1255 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1256 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1257 				(((unsigned long) powerplay_table) +
1258 				vce_clock_info_array_offset);
1259 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1260 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1261 				(((unsigned long) powerplay_table) + table_offset);
1262 		result = get_vce_clock_voltage_limit_table(hwmgr,
1263 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1264 				table, array);
1265 	}
1266 
1267 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1268 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1269 
1270 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1271 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1272 				(((unsigned long) powerplay_table) +
1273 				uvd_clock_info_array_offset);
1274 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1275 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1276 				(((unsigned long) powerplay_table) + table_offset);
1277 		result = get_uvd_clock_voltage_limit_table(hwmgr,
1278 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1279 	}
1280 
1281 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1282 							    powerplay_table);
1283 
1284 	if (table_offset > 0) {
1285 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1286 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1287 				(((unsigned long) powerplay_table) + table_offset);
1288 		result = get_samu_clock_voltage_limit_table(hwmgr,
1289 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1290 	}
1291 
1292 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1293 							     powerplay_table);
1294 
1295 	if (table_offset > 0) {
1296 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1297 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1298 				(((unsigned long) powerplay_table) + table_offset);
1299 		result = get_acp_clock_voltage_limit_table(hwmgr,
1300 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1301 	}
1302 
1303 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1304 	if (table_offset > 0) {
1305 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1306 
1307 		if (rev_id > 0) {
1308 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1309 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1310 				(((unsigned long) powerplay_table) + table_offset);
1311 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1312 				&tune_table->power_tune_table,
1313 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1314 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1315 				le16_to_cpu(tune_table->usTjMax);
1316 		} else {
1317 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1318 				(const ATOM_PPLIB_POWERTUNE_Table *)
1319 				(((unsigned long) powerplay_table) + table_offset);
1320 			result = get_cac_tdp_table(hwmgr,
1321 				&hwmgr->dyn_state.cac_dtp_table,
1322 				&tune_table->power_tune_table, 255);
1323 		}
1324 	}
1325 
1326 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1327 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1328 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1329 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1330 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1331 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1332 				(((unsigned long) powerplay_table4) +
1333 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1334 			result = get_clock_voltage_dependency_table(hwmgr,
1335 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1336 		}
1337 
1338 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1339 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1340 				(((unsigned long) powerplay_table4) +
1341 				 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1342 			result = get_clock_voltage_dependency_table(hwmgr,
1343 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1344 		}
1345 
1346 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1347 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1348 				(((unsigned long) powerplay_table4) +
1349 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1350 			result = get_clock_voltage_dependency_table(hwmgr,
1351 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1352 		}
1353 
1354 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1355 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1356 				(((unsigned long) powerplay_table4) +
1357 				 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1358 			result = get_clock_voltage_limit(hwmgr,
1359 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1360 		}
1361 
1362 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1363 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1364 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1365 					hwmgr->dyn_state.vddc_dependency_on_mclk);
1366 
1367 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1368 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1369 			result = get_valid_clk(hwmgr,
1370 				&hwmgr->dyn_state.valid_sclk_values,
1371 				hwmgr->dyn_state.vddc_dependency_on_sclk);
1372 
1373 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1374 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1375 				(((unsigned long) powerplay_table4) +
1376 				 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1377 			result = get_clock_voltage_dependency_table(hwmgr,
1378 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1379 		}
1380 	}
1381 
1382 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1383 								powerplay_table);
1384 
1385 	if (table_offset > 0) {
1386 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1387 			(((unsigned long) powerplay_table) + table_offset);
1388 		result = get_clock_voltage_dependency_table(hwmgr,
1389 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1390 	}
1391 
1392 	return result;
1393 }
1394 
1395 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1396 				 struct phm_cac_leakage_table **ptable,
1397 				const ATOM_PPLIB_CAC_Leakage_Table *table)
1398 {
1399 	struct phm_cac_leakage_table  *cac_leakage_table;
1400 	unsigned long            table_size, i;
1401 
1402 	if (hwmgr == NULL || table == NULL || ptable == NULL)
1403 		return -EINVAL;
1404 
1405 	table_size = sizeof(ULONG) +
1406 		(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1407 
1408 	cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1409 
1410 	if (cac_leakage_table == NULL)
1411 		return -ENOMEM;
1412 
1413 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
1414 
1415 	for (i = 0; i < cac_leakage_table->count; i++) {
1416 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1417 				PHM_PlatformCaps_EVV)) {
1418 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1419 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1420 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1421 		} else {
1422 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1423 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1424 		}
1425 	}
1426 
1427 	*ptable = cac_leakage_table;
1428 
1429 	return 0;
1430 }
1431 
1432 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1433 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
1434 {
1435 	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1436 
1437 	if (NULL == ptr)
1438 		return -ENOMEM;
1439 
1440 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1441 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1442 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1443 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1444 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1445 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1446 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1447 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1448 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1449 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1450 	hwmgr->dyn_state.ppm_parameter_table = ptr;
1451 
1452 	return 0;
1453 }
1454 
1455 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1456 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1457 {
1458 	int result = 0;
1459 
1460 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1461 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1462 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1463 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1464 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1465 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1466 				(&ptable5->basicTable4);
1467 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1468 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1469 				(&ptable4->basicTable3);
1470 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1471 		uint16_t table_offset;
1472 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
1473 
1474 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1475 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1476 
1477 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1478 		hwmgr->platform_descriptor.TDPAdjustment = 0;
1479 
1480 		hwmgr->platform_descriptor.VidAdjustment = 0;
1481 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1482 		hwmgr->platform_descriptor.VidMinLimit     = 0;
1483 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1484 		hwmgr->platform_descriptor.VidStep         = 6250;
1485 
1486 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1487 
1488 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
1489 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1490 					PHM_PlatformCaps_PowerControl);
1491 
1492 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1493 
1494 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1495 
1496 		hwmgr->dyn_state.cac_leakage_table = NULL;
1497 
1498 		if (0 != ptable5->usCACLeakageTableOffset) {
1499 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1500 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1501 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
1502 			result = get_cac_leakage_table(hwmgr,
1503 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1504 		}
1505 
1506 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1507 
1508 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1509 
1510 		if (0 != ptable3->usExtendendedHeaderOffset) {
1511 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1512 					(((unsigned long)powerplay_table) +
1513 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1514 			if ((extended_header->usPPMTableOffset > 0) &&
1515 				le16_to_cpu(extended_header->usSize) >=
1516 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1517 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1518 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1519 					(((unsigned long)powerplay_table) + table_offset);
1520 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1521 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1522 						PHM_PlatformCaps_EnablePlatformPowerManagement);
1523 			}
1524 		}
1525 	}
1526 	return result;
1527 }
1528 
1529 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1530 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1531 {
1532 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1533 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1534 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1535 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1536 
1537 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1538 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1539 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1540 				(((unsigned long)powerplay_table4) +
1541 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1542 			struct phm_phase_shedding_limits_table *table;
1543 			unsigned long size, i;
1544 
1545 
1546 			size = sizeof(unsigned long) +
1547 				(sizeof(struct phm_phase_shedding_limits_table) *
1548 				ptable->ucNumEntries);
1549 
1550 			table = kzalloc(size, GFP_KERNEL);
1551 
1552 			if (table == NULL)
1553 				return -ENOMEM;
1554 
1555 			table->count = (unsigned long)ptable->ucNumEntries;
1556 
1557 			for (i = 0; i < table->count; i++) {
1558 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1559 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1560 							| le16_to_cpu(ptable->entries[i].usSclkLow);
1561 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1562 							| le16_to_cpu(ptable->entries[i].usMclkLow);
1563 			}
1564 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1565 		}
1566 	}
1567 
1568 	return 0;
1569 }
1570 
1571 static int get_number_of_vce_state_table_entries(
1572 						  struct pp_hwmgr *hwmgr)
1573 {
1574 	const ATOM_PPLIB_POWERPLAYTABLE *table =
1575 					     get_powerplay_table(hwmgr);
1576 	const ATOM_PPLIB_VCE_State_Table *vce_table =
1577 				    get_vce_state_table(hwmgr, table);
1578 
1579 	if (vce_table)
1580 		return vce_table->numEntries;
1581 
1582 	return 0;
1583 }
1584 
1585 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1586 							unsigned long i,
1587 							struct amd_vce_state *vce_state,
1588 							void **clock_info,
1589 							unsigned long *flag)
1590 {
1591 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1592 
1593 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1594 
1595 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1596 
1597 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1598 
1599 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1600 								le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1601 
1602 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1603 
1604 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1605 
1606 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1607 
1608 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1609 
1610 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1611 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1612 
1613 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1614 
1615 	return 0;
1616 }
1617 
1618 
1619 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1620 {
1621 	int result;
1622 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1623 
1624 	if (hwmgr->chip_id == CHIP_RAVEN)
1625 		return 0;
1626 
1627 	hwmgr->need_pp_table_upload = true;
1628 
1629 	powerplay_table = get_powerplay_table(hwmgr);
1630 
1631 	result = init_powerplay_tables(hwmgr, powerplay_table);
1632 
1633 	PP_ASSERT_WITH_CODE((result == 0),
1634 			    "init_powerplay_tables failed", return result);
1635 
1636 	result = set_platform_caps(hwmgr,
1637 				le32_to_cpu(powerplay_table->ulPlatformCaps));
1638 
1639 	PP_ASSERT_WITH_CODE((result == 0),
1640 			    "set_platform_caps failed", return result);
1641 
1642 	result = init_thermal_controller(hwmgr, powerplay_table);
1643 
1644 	PP_ASSERT_WITH_CODE((result == 0),
1645 			    "init_thermal_controller failed", return result);
1646 
1647 	result = init_overdrive_limits(hwmgr, powerplay_table);
1648 
1649 	PP_ASSERT_WITH_CODE((result == 0),
1650 			    "init_overdrive_limits failed", return result);
1651 
1652 	result = init_clock_voltage_dependency(hwmgr,
1653 					       powerplay_table);
1654 
1655 	PP_ASSERT_WITH_CODE((result == 0),
1656 			    "init_clock_voltage_dependency failed", return result);
1657 
1658 	result = init_dpm2_parameters(hwmgr, powerplay_table);
1659 
1660 	PP_ASSERT_WITH_CODE((result == 0),
1661 			    "init_dpm2_parameters failed", return result);
1662 
1663 	result = init_phase_shedding_table(hwmgr, powerplay_table);
1664 
1665 	PP_ASSERT_WITH_CODE((result == 0),
1666 			    "init_phase_shedding_table failed", return result);
1667 
1668 	return result;
1669 }
1670 
1671 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1672 {
1673 	if (hwmgr->chip_id == CHIP_RAVEN)
1674 		return 0;
1675 
1676 	kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1677 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1678 
1679 	kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1680 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1681 
1682 	kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1683 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1684 
1685 	kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1686 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1687 
1688 	kfree(hwmgr->dyn_state.valid_mclk_values);
1689 	hwmgr->dyn_state.valid_mclk_values = NULL;
1690 
1691 	kfree(hwmgr->dyn_state.valid_sclk_values);
1692 	hwmgr->dyn_state.valid_sclk_values = NULL;
1693 
1694 	kfree(hwmgr->dyn_state.cac_leakage_table);
1695 	hwmgr->dyn_state.cac_leakage_table = NULL;
1696 
1697 	kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1698 	hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1699 
1700 	kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1701 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1702 
1703 	kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1704 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1705 
1706 	kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1707 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1708 
1709 	kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1710 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1711 
1712 	kfree(hwmgr->dyn_state.cac_dtp_table);
1713 	hwmgr->dyn_state.cac_dtp_table = NULL;
1714 
1715 	kfree(hwmgr->dyn_state.ppm_parameter_table);
1716 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1717 
1718 	kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1719 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1720 
1721 	return 0;
1722 }
1723 
1724 const struct pp_table_func pptable_funcs = {
1725 	.pptable_init = pp_tables_initialize,
1726 	.pptable_fini = pp_tables_uninitialize,
1727 	.pptable_get_number_of_vce_state_table_entries =
1728 				get_number_of_vce_state_table_entries,
1729 	.pptable_get_vce_state_table_entry =
1730 						get_vce_state_table_entry,
1731 };
1732 
1733