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