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 
1189 	if ((fw_info->ucTableFormatRevision == 1)
1190 	    && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1191 		result = init_overdrive_limits_V1_4(hwmgr,
1192 				powerplay_table,
1193 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1194 
1195 	else if ((fw_info->ucTableFormatRevision == 2)
1196 		 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1197 		result = init_overdrive_limits_V2_1(hwmgr,
1198 				powerplay_table,
1199 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1200 
1201 	return result;
1202 }
1203 
1204 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1205 		struct phm_uvd_clock_voltage_dependency_table **ptable,
1206 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1207 		const UVDClockInfoArray *array)
1208 {
1209 	unsigned long i;
1210 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1211 
1212 	uvd_table = kzalloc(struct_size(uvd_table, entries, table->numEntries),
1213 			    GFP_KERNEL);
1214 	if (!uvd_table)
1215 		return -ENOMEM;
1216 
1217 	uvd_table->count = table->numEntries;
1218 
1219 	for (i = 0; i < table->numEntries; i++) {
1220 		const UVDClockInfo *entry =
1221 			&array->entries[table->entries[i].ucUVDClockInfoIndex];
1222 		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1223 		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1224 					 | le16_to_cpu(entry->usVClkLow);
1225 		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1226 					 | le16_to_cpu(entry->usDClkLow);
1227 	}
1228 
1229 	*ptable = uvd_table;
1230 
1231 	return 0;
1232 }
1233 
1234 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1235 		struct phm_vce_clock_voltage_dependency_table **ptable,
1236 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1237 		const VCEClockInfoArray    *array)
1238 {
1239 	unsigned long i;
1240 	struct phm_vce_clock_voltage_dependency_table *vce_table;
1241 
1242 	vce_table = kzalloc(struct_size(vce_table, entries, table->numEntries),
1243 			    GFP_KERNEL);
1244 	if (!vce_table)
1245 		return -ENOMEM;
1246 
1247 	vce_table->count = table->numEntries;
1248 	for (i = 0; i < table->numEntries; i++) {
1249 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1250 
1251 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1252 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1253 					| le16_to_cpu(entry->usEVClkLow);
1254 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1255 					| le16_to_cpu(entry->usECClkLow);
1256 	}
1257 
1258 	*ptable = vce_table;
1259 
1260 	return 0;
1261 }
1262 
1263 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1264 		 struct phm_samu_clock_voltage_dependency_table **ptable,
1265 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1266 {
1267 	unsigned long i;
1268 	struct phm_samu_clock_voltage_dependency_table *samu_table;
1269 
1270 	samu_table = kzalloc(struct_size(samu_table, entries, table->numEntries),
1271 			     GFP_KERNEL);
1272 	if (!samu_table)
1273 		return -ENOMEM;
1274 
1275 	samu_table->count = table->numEntries;
1276 
1277 	for (i = 0; i < table->numEntries; i++) {
1278 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1279 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1280 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
1281 	}
1282 
1283 	*ptable = samu_table;
1284 
1285 	return 0;
1286 }
1287 
1288 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1289 		struct phm_acp_clock_voltage_dependency_table **ptable,
1290 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1291 {
1292 	unsigned long i;
1293 	struct phm_acp_clock_voltage_dependency_table *acp_table;
1294 
1295 	acp_table = kzalloc(struct_size(acp_table, entries, table->numEntries),
1296 			    GFP_KERNEL);
1297 	if (!acp_table)
1298 		return -ENOMEM;
1299 
1300 	acp_table->count = (unsigned long)table->numEntries;
1301 
1302 	for (i = 0; i < table->numEntries; i++) {
1303 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1304 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1305 					 | le16_to_cpu(table->entries[i].usACPClockLow);
1306 	}
1307 
1308 	*ptable = acp_table;
1309 
1310 	return 0;
1311 }
1312 
1313 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1314 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1315 {
1316 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1317 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1318 	int result = 0;
1319 
1320 	uint16_t vce_clock_info_array_offset;
1321 	uint16_t uvd_clock_info_array_offset;
1322 	uint16_t table_offset;
1323 
1324 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1325 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1326 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1327 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1328 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1329 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1330 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1331 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1332 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1333 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1334 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1335 
1336 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1337 						hwmgr, powerplay_table);
1338 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1339 						powerplay_table);
1340 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1341 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1342 				(((unsigned long) powerplay_table) +
1343 				vce_clock_info_array_offset);
1344 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1345 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1346 				(((unsigned long) powerplay_table) + table_offset);
1347 		result = get_vce_clock_voltage_limit_table(hwmgr,
1348 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1349 				table, array);
1350 	}
1351 
1352 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1353 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1354 
1355 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1356 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1357 				(((unsigned long) powerplay_table) +
1358 				uvd_clock_info_array_offset);
1359 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1360 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1361 				(((unsigned long) powerplay_table) + table_offset);
1362 		result = get_uvd_clock_voltage_limit_table(hwmgr,
1363 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1364 	}
1365 
1366 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1367 							    powerplay_table);
1368 
1369 	if (table_offset > 0) {
1370 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1371 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1372 				(((unsigned long) powerplay_table) + table_offset);
1373 		result = get_samu_clock_voltage_limit_table(hwmgr,
1374 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1375 	}
1376 
1377 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1378 							     powerplay_table);
1379 
1380 	if (table_offset > 0) {
1381 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1382 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1383 				(((unsigned long) powerplay_table) + table_offset);
1384 		result = get_acp_clock_voltage_limit_table(hwmgr,
1385 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1386 	}
1387 
1388 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1389 	if (table_offset > 0) {
1390 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1391 
1392 		if (rev_id > 0) {
1393 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1394 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1395 				(((unsigned long) powerplay_table) + table_offset);
1396 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1397 				&tune_table->power_tune_table,
1398 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1399 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1400 				le16_to_cpu(tune_table->usTjMax);
1401 		} else {
1402 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1403 				(const ATOM_PPLIB_POWERTUNE_Table *)
1404 				(((unsigned long) powerplay_table) + table_offset);
1405 			result = get_cac_tdp_table(hwmgr,
1406 				&hwmgr->dyn_state.cac_dtp_table,
1407 				&tune_table->power_tune_table, 255);
1408 		}
1409 	}
1410 
1411 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1412 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1413 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1414 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1415 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1416 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1417 				(((unsigned long) powerplay_table4) +
1418 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1419 			result = get_clock_voltage_dependency_table(hwmgr,
1420 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1421 		}
1422 
1423 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1424 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1425 				(((unsigned long) powerplay_table4) +
1426 				 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1427 			result = get_clock_voltage_dependency_table(hwmgr,
1428 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1429 		}
1430 
1431 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1432 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1433 				(((unsigned long) powerplay_table4) +
1434 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1435 			result = get_clock_voltage_dependency_table(hwmgr,
1436 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1437 		}
1438 
1439 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1440 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1441 				(((unsigned long) powerplay_table4) +
1442 				 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1443 			result = get_clock_voltage_limit(hwmgr,
1444 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1445 		}
1446 
1447 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1448 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1449 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1450 					hwmgr->dyn_state.vddc_dependency_on_mclk);
1451 
1452 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1453 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1454 			result = get_valid_clk(hwmgr,
1455 				&hwmgr->dyn_state.valid_sclk_values,
1456 				hwmgr->dyn_state.vddc_dependency_on_sclk);
1457 
1458 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1459 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1460 				(((unsigned long) powerplay_table4) +
1461 				 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1462 			result = get_clock_voltage_dependency_table(hwmgr,
1463 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1464 		}
1465 	}
1466 
1467 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1468 								powerplay_table);
1469 
1470 	if (table_offset > 0) {
1471 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1472 			(((unsigned long) powerplay_table) + table_offset);
1473 		result = get_clock_voltage_dependency_table(hwmgr,
1474 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1475 	}
1476 
1477 	return result;
1478 }
1479 
1480 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1481 				 struct phm_cac_leakage_table **ptable,
1482 				const ATOM_PPLIB_CAC_Leakage_Table *table)
1483 {
1484 	struct phm_cac_leakage_table  *cac_leakage_table;
1485 	unsigned long i;
1486 
1487 	if (!hwmgr || !table || !ptable)
1488 		return -EINVAL;
1489 
1490 	cac_leakage_table = kzalloc(struct_size(cac_leakage_table, entries, table->ucNumEntries),
1491 				    GFP_KERNEL);
1492 	if (!cac_leakage_table)
1493 		return -ENOMEM;
1494 
1495 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
1496 
1497 	for (i = 0; i < cac_leakage_table->count; i++) {
1498 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1499 				PHM_PlatformCaps_EVV)) {
1500 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1501 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1502 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1503 		} else {
1504 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1505 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1506 		}
1507 	}
1508 
1509 	*ptable = cac_leakage_table;
1510 
1511 	return 0;
1512 }
1513 
1514 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1515 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
1516 {
1517 	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1518 
1519 	if (NULL == ptr)
1520 		return -ENOMEM;
1521 
1522 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1523 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1524 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1525 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1526 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1527 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1528 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1529 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1530 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1531 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1532 	hwmgr->dyn_state.ppm_parameter_table = ptr;
1533 
1534 	return 0;
1535 }
1536 
1537 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1538 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1539 {
1540 	int result = 0;
1541 
1542 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1543 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1544 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1545 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1546 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1547 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1548 				(&ptable5->basicTable4);
1549 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1550 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1551 				(&ptable4->basicTable3);
1552 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1553 		uint16_t table_offset;
1554 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
1555 
1556 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1557 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1558 
1559 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1560 		hwmgr->platform_descriptor.TDPAdjustment = 0;
1561 
1562 		hwmgr->platform_descriptor.VidAdjustment = 0;
1563 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1564 		hwmgr->platform_descriptor.VidMinLimit     = 0;
1565 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1566 		hwmgr->platform_descriptor.VidStep         = 6250;
1567 
1568 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1569 
1570 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
1571 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1572 					PHM_PlatformCaps_PowerControl);
1573 
1574 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1575 
1576 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1577 
1578 		hwmgr->dyn_state.cac_leakage_table = NULL;
1579 
1580 		if (0 != ptable5->usCACLeakageTableOffset) {
1581 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1582 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1583 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
1584 			result = get_cac_leakage_table(hwmgr,
1585 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1586 		}
1587 
1588 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1589 
1590 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1591 
1592 		if (0 != ptable3->usExtendendedHeaderOffset) {
1593 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1594 					(((unsigned long)powerplay_table) +
1595 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1596 			if ((extended_header->usPPMTableOffset > 0) &&
1597 				le16_to_cpu(extended_header->usSize) >=
1598 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1599 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1600 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1601 					(((unsigned long)powerplay_table) + table_offset);
1602 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1603 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1604 						PHM_PlatformCaps_EnablePlatformPowerManagement);
1605 			}
1606 		}
1607 	}
1608 	return result;
1609 }
1610 
1611 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1612 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1613 {
1614 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1615 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1616 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1617 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1618 
1619 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1620 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1621 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1622 				(((unsigned long)powerplay_table4) +
1623 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1624 			struct phm_phase_shedding_limits_table *table;
1625 			unsigned long i;
1626 
1627 
1628 			table = kzalloc(struct_size(table, entries, ptable->ucNumEntries),
1629 					GFP_KERNEL);
1630 			if (!table)
1631 				return -ENOMEM;
1632 
1633 			table->count = (unsigned long)ptable->ucNumEntries;
1634 
1635 			for (i = 0; i < table->count; i++) {
1636 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1637 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1638 							| le16_to_cpu(ptable->entries[i].usSclkLow);
1639 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1640 							| le16_to_cpu(ptable->entries[i].usMclkLow);
1641 			}
1642 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1643 		}
1644 	}
1645 
1646 	return 0;
1647 }
1648 
1649 static int get_number_of_vce_state_table_entries(
1650 						  struct pp_hwmgr *hwmgr)
1651 {
1652 	const ATOM_PPLIB_POWERPLAYTABLE *table =
1653 					     get_powerplay_table(hwmgr);
1654 	const ATOM_PPLIB_VCE_State_Table *vce_table =
1655 				    get_vce_state_table(hwmgr, table);
1656 
1657 	if (vce_table)
1658 		return vce_table->numEntries;
1659 
1660 	return 0;
1661 }
1662 
1663 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1664 							unsigned long i,
1665 							struct amd_vce_state *vce_state,
1666 							void **clock_info,
1667 							unsigned long *flag)
1668 {
1669 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1670 
1671 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1672 
1673 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1674 
1675 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1676 
1677 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1678 								le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1679 
1680 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1681 
1682 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1683 
1684 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1685 
1686 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1687 
1688 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1689 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1690 
1691 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1692 
1693 	return 0;
1694 }
1695 
1696 
1697 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1698 {
1699 	int result;
1700 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1701 
1702 	if (hwmgr->chip_id == CHIP_RAVEN)
1703 		return 0;
1704 
1705 	hwmgr->need_pp_table_upload = true;
1706 
1707 	powerplay_table = get_powerplay_table(hwmgr);
1708 
1709 	result = init_powerplay_tables(hwmgr, powerplay_table);
1710 
1711 	PP_ASSERT_WITH_CODE((result == 0),
1712 			    "init_powerplay_tables failed", return result);
1713 
1714 	result = set_platform_caps(hwmgr,
1715 				le32_to_cpu(powerplay_table->ulPlatformCaps));
1716 
1717 	PP_ASSERT_WITH_CODE((result == 0),
1718 			    "set_platform_caps failed", return result);
1719 
1720 	result = init_thermal_controller(hwmgr, powerplay_table);
1721 
1722 	PP_ASSERT_WITH_CODE((result == 0),
1723 			    "init_thermal_controller failed", return result);
1724 
1725 	result = init_overdrive_limits(hwmgr, powerplay_table);
1726 
1727 	PP_ASSERT_WITH_CODE((result == 0),
1728 			    "init_overdrive_limits failed", return result);
1729 
1730 	result = init_clock_voltage_dependency(hwmgr,
1731 					       powerplay_table);
1732 
1733 	PP_ASSERT_WITH_CODE((result == 0),
1734 			    "init_clock_voltage_dependency failed", return result);
1735 
1736 	result = init_dpm2_parameters(hwmgr, powerplay_table);
1737 
1738 	PP_ASSERT_WITH_CODE((result == 0),
1739 			    "init_dpm2_parameters failed", return result);
1740 
1741 	result = init_phase_shedding_table(hwmgr, powerplay_table);
1742 
1743 	PP_ASSERT_WITH_CODE((result == 0),
1744 			    "init_phase_shedding_table failed", return result);
1745 
1746 	return result;
1747 }
1748 
1749 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1750 {
1751 	if (hwmgr->chip_id == CHIP_RAVEN)
1752 		return 0;
1753 
1754 	kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1755 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1756 
1757 	kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1758 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1759 
1760 	kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1761 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1762 
1763 	kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1764 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1765 
1766 	kfree(hwmgr->dyn_state.valid_mclk_values);
1767 	hwmgr->dyn_state.valid_mclk_values = NULL;
1768 
1769 	kfree(hwmgr->dyn_state.valid_sclk_values);
1770 	hwmgr->dyn_state.valid_sclk_values = NULL;
1771 
1772 	kfree(hwmgr->dyn_state.cac_leakage_table);
1773 	hwmgr->dyn_state.cac_leakage_table = NULL;
1774 
1775 	kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1776 	hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1777 
1778 	kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1779 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1780 
1781 	kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1782 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1783 
1784 	kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1785 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1786 
1787 	kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1788 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1789 
1790 	kfree(hwmgr->dyn_state.cac_dtp_table);
1791 	hwmgr->dyn_state.cac_dtp_table = NULL;
1792 
1793 	kfree(hwmgr->dyn_state.ppm_parameter_table);
1794 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1795 
1796 	kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1797 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1798 
1799 	return 0;
1800 }
1801 
1802 const struct pp_table_func pptable_funcs = {
1803 	.pptable_init = pp_tables_initialize,
1804 	.pptable_fini = pp_tables_uninitialize,
1805 	.pptable_get_number_of_vce_state_table_entries =
1806 				get_number_of_vce_state_table_entries,
1807 	.pptable_get_vce_state_table_entry =
1808 						get_vce_state_table_entry,
1809 };
1810 
1811