xref: /linux/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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->display.disableFrameModulation = false;
706 
707 	rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
708 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
709 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
710 
711 	if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
712 		static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
713 								{ 0, 50, 0 };
714 
715 		ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
716 		ps->display.explicitRefreshrate = look_up[rrr_index];
717 		ps->display.limitRefreshrate = true;
718 
719 		if (ps->display.explicitRefreshrate == 0)
720 			ps->display.limitRefreshrate = false;
721 	} else
722 		ps->display.limitRefreshrate = false;
723 
724 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
725 		ATOM_PPLIB_ENABLE_VARIBRIGHT;
726 
727 	ps->display.enableVariBright = (0 != tmp);
728 
729 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
730 		ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
731 
732 	ps->memory.dllOff = (0 != tmp);
733 
734 	ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
735 			    ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
736 
737 	ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
738 				     pnon_clock_info->ucMinTemperature;
739 
740 	ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
741 				     pnon_clock_info->ucMaxTemperature;
742 
743 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
744 		ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
745 
746 	ps->software.disableLoadBalancing = tmp;
747 
748 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
749 		ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
750 
751 	ps->software.enableSleepForTimestamps = (0 != tmp);
752 
753 	ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
754 
755 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
756 		ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
757 		ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
758 	} else {
759 		ps->uvd_clocks.VCLK = 0;
760 		ps->uvd_clocks.DCLK = 0;
761 	}
762 
763 	return 0;
764 }
765 
766 static ULONG size_of_entry_v2(ULONG num_dpm_levels)
767 {
768 	return (sizeof(UCHAR) + sizeof(UCHAR) +
769 			(num_dpm_levels * sizeof(UCHAR)));
770 }
771 
772 static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
773 					const StateArray * pstate_arrays,
774 							 ULONG entry_index)
775 {
776 	ULONG i;
777 	const ATOM_PPLIB_STATE_V2 *pstate;
778 
779 	pstate = pstate_arrays->states;
780 	if (entry_index <= pstate_arrays->ucNumEntries) {
781 		for (i = 0; i < entry_index; i++)
782 			pstate = (ATOM_PPLIB_STATE_V2 *)(
783 						  (unsigned long)pstate +
784 			     size_of_entry_v2(pstate->ucNumDPMLevels));
785 	}
786 	return pstate;
787 }
788 
789 static const unsigned char soft_dummy_pp_table[] = {
790 	0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
791 	0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
792 	0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
793 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
795 	0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
796 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
797 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
800 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
801 	0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
802 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
803 	0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
804 	0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
805 	0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
806 	0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
807 	0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
808 	0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
809 	0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
810 	0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
811 	0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
812 	0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
813 	0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
814 	0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
815 	0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
816 	0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
817 	0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
818 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
819 	0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
820 	0x00
821 };
822 
823 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
824 				     struct pp_hwmgr *hwmgr)
825 {
826 	const void *table_addr = hwmgr->soft_pp_table;
827 	uint8_t frev, crev;
828 	uint16_t size;
829 
830 	if (!table_addr) {
831 		if (hwmgr->chip_id == CHIP_RAVEN) {
832 			table_addr = &soft_dummy_pp_table[0];
833 			hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
834 			hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
835 		} else {
836 			table_addr = smu_atom_get_data_table(hwmgr->adev,
837 					GetIndexIntoMasterTable(DATA, PowerPlayInfo),
838 					&size, &frev, &crev);
839 			hwmgr->soft_pp_table = table_addr;
840 			hwmgr->soft_pp_table_size = size;
841 		}
842 	}
843 
844 	return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
845 }
846 
847 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
848 				uint32_t *vol_rep_time, uint32_t *bb_rep_time)
849 {
850 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
851 
852 	PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
853 			    "Missing PowerPlay Table!", return -EINVAL);
854 
855 	*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
856 	*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
857 
858 	return 0;
859 }
860 
861 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
862 				     unsigned long *num_of_entries)
863 {
864 	const StateArray *pstate_arrays;
865 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
866 
867 	if (powerplay_table == NULL)
868 		return -1;
869 
870 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
871 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
872 					le16_to_cpu(powerplay_table->usStateArrayOffset));
873 
874 		*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
875 	} else
876 		*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
877 
878 	return 0;
879 }
880 
881 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
882 				unsigned long entry_index,
883 				struct pp_power_state *ps,
884 			 pp_tables_hw_clock_info_callback func)
885 {
886 	int i;
887 	const StateArray *pstate_arrays;
888 	const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
889 	const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
890 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
891 	int result = 0;
892 	int res = 0;
893 
894 	const ClockInfoArray *pclock_arrays;
895 
896 	const NonClockInfoArray *pnon_clock_arrays;
897 
898 	const ATOM_PPLIB_STATE *pstate_entry;
899 
900 	if (powerplay_table == NULL)
901 		return -1;
902 
903 	ps->classification.bios_index = entry_index;
904 
905 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
906 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
907 					le16_to_cpu(powerplay_table->usStateArrayOffset));
908 
909 		if (entry_index > pstate_arrays->ucNumEntries)
910 			return -1;
911 
912 		pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
913 		pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
914 					le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
915 
916 		pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
917 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
918 
919 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
920 					(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
921 
922 		result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
923 
924 		for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
925 			const void *pclock_info = (const void *)(
926 							(unsigned long)(pclock_arrays->clockInfo) +
927 							(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
928 			res = func(hwmgr, &ps->hardware, i, pclock_info);
929 			if ((0 == result) && (0 != res))
930 				result = res;
931 		}
932 	} else {
933 		if (entry_index > powerplay_table->ucNumStates)
934 			return -1;
935 
936 		pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
937 						    le16_to_cpu(powerplay_table->usStateArrayOffset) +
938 						    entry_index * powerplay_table->ucStateEntrySize);
939 
940 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
941 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
942 						pstate_entry->ucNonClockStateIndex *
943 						powerplay_table->ucNonClockSize);
944 
945 		result = init_non_clock_fields(hwmgr, ps,
946 							powerplay_table->ucNonClockSize,
947 							pnon_clock_info);
948 
949 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
950 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
951 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
952 						pstate_entry->ucClockStateIndices[i] *
953 						powerplay_table->ucClockInfoSize);
954 
955 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
956 
957 			if ((0 == result) && (0 != res))
958 					result = res;
959 		}
960 	}
961 
962 	if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
963 		if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
964 			result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
965 	}
966 
967 	return result;
968 }
969 
970 static int init_powerplay_tables(
971 			struct pp_hwmgr *hwmgr,
972 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
973 )
974 {
975 	return 0;
976 }
977 
978 
979 static int init_thermal_controller(
980 			struct pp_hwmgr *hwmgr,
981 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
982 {
983 	struct amdgpu_device *adev = hwmgr->adev;
984 
985 	hwmgr->thermal_controller.ucType =
986 			powerplay_table->sThermalController.ucType;
987 	hwmgr->thermal_controller.ucI2cLine =
988 			powerplay_table->sThermalController.ucI2cLine;
989 	hwmgr->thermal_controller.ucI2cAddress =
990 			powerplay_table->sThermalController.ucI2cAddress;
991 
992 	hwmgr->thermal_controller.fanInfo.bNoFan =
993 		(0 != (powerplay_table->sThermalController.ucFanParameters &
994 			ATOM_PP_FANPARAMETERS_NOFAN));
995 
996 	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
997 		powerplay_table->sThermalController.ucFanParameters &
998 		ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
999 
1000 	hwmgr->thermal_controller.fanInfo.ulMinRPM
1001 		= powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1002 	hwmgr->thermal_controller.fanInfo.ulMaxRPM
1003 		= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1004 
1005 	set_hw_cap(hwmgr,
1006 		   ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1007 		   PHM_PlatformCaps_ThermalController);
1008 
1009         if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
1010 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
1011 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1012 
1013 		if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {
1014 			hwmgr->thermal_controller.use_hw_fan_control = 1;
1015 			return 0;
1016 		} else {
1017 			const ATOM_PPLIB_FANTABLE *fan_table =
1018 				(const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) +
1019 							      le16_to_cpu(powerplay_table3->usFanTableOffset));
1020 
1021 			if (1 <= fan_table->ucFanTableFormat) {
1022 				hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst =
1023 					fan_table->ucTHyst;
1024 				hwmgr->thermal_controller.advanceFanControlParameters.usTMin =
1025 					le16_to_cpu(fan_table->usTMin);
1026 				hwmgr->thermal_controller.advanceFanControlParameters.usTMed =
1027 					le16_to_cpu(fan_table->usTMed);
1028 				hwmgr->thermal_controller.advanceFanControlParameters.usTHigh =
1029 					le16_to_cpu(fan_table->usTHigh);
1030 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
1031 					le16_to_cpu(fan_table->usPWMMin);
1032 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed =
1033 					le16_to_cpu(fan_table->usPWMMed);
1034 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh =
1035 					le16_to_cpu(fan_table->usPWMHigh);
1036 				hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900;
1037 				hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000;
1038 
1039 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1040 					    PHM_PlatformCaps_MicrocodeFanControl);
1041 			}
1042 
1043 			if (2 <= fan_table->ucFanTableFormat) {
1044 				const ATOM_PPLIB_FANTABLE2 *fan_table2 =
1045 					(const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) +
1046 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1047 				hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
1048 					le16_to_cpu(fan_table2->usTMax);
1049 			}
1050 
1051 			if (3 <= fan_table->ucFanTableFormat) {
1052 				const ATOM_PPLIB_FANTABLE3 *fan_table3 =
1053 					(const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) +
1054 									le16_to_cpu(powerplay_table3->usFanTableOffset));
1055 
1056 				hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =
1057 					fan_table3->ucFanControlMode;
1058 
1059 				if ((3 == fan_table->ucFanTableFormat) &&
1060 				    (0x67B1 == adev->pdev->device))
1061 					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1062 						47;
1063 				else
1064 					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1065 						le16_to_cpu(fan_table3->usFanPWMMax);
1066 
1067 				hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity =
1068 					4836;
1069 				hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
1070 					le16_to_cpu(fan_table3->usFanOutputSensitivity);
1071 			}
1072 
1073 			if (6 <= fan_table->ucFanTableFormat) {
1074 				const ATOM_PPLIB_FANTABLE4 *fan_table4 =
1075 					(const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) +
1076 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1077 
1078 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1079 					    PHM_PlatformCaps_FanSpeedInTableIsRPM);
1080 
1081 				hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM =
1082 					le16_to_cpu(fan_table4->usFanRPMMax);
1083 			}
1084 
1085 			if (7 <= fan_table->ucFanTableFormat) {
1086 				const ATOM_PPLIB_FANTABLE5 *fan_table5 =
1087 					(const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) +
1088 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1089 
1090 				if (0x67A2 == adev->pdev->device ||
1091 				    0x67A9 == adev->pdev->device ||
1092 				    0x67B9 == adev->pdev->device) {
1093 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1094 						    PHM_PlatformCaps_GeminiRegulatorFanControlSupport);
1095 					hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow =
1096 						le16_to_cpu(fan_table5->usFanCurrentLow);
1097 					hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh =
1098 						le16_to_cpu(fan_table5->usFanCurrentHigh);
1099 					hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow =
1100 						le16_to_cpu(fan_table5->usFanRPMLow);
1101 					hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh =
1102 						le16_to_cpu(fan_table5->usFanRPMHigh);
1103 				}
1104 			}
1105 		}
1106 	}
1107 
1108 	return 0;
1109 }
1110 
1111 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
1112 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1113 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
1114 {
1115 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
1116 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
1117 
1118 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1119 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1120 
1121 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1122 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1123 
1124 	hwmgr->platform_descriptor.minOverdriveVDDC =
1125 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1126 
1127 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1128 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1129 
1130 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1131 	return 0;
1132 }
1133 
1134 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1135 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1136 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1137 {
1138 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1139 	const ATOM_PPLIB_EXTENDEDHEADER *header;
1140 
1141 	if (le16_to_cpu(powerplay_table->usTableSize) <
1142 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1143 		return 0;
1144 
1145 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1146 
1147 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
1148 		return 0;
1149 
1150 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1151 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1152 
1153 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1154 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1155 
1156 
1157 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1158 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1159 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1160 
1161 	return 0;
1162 }
1163 
1164 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1165 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1166 {
1167 	int result = 0;
1168 	uint8_t frev, crev;
1169 	uint16_t size;
1170 
1171 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1172 
1173 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1174 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1175 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1176 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1177 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1178 
1179 	if (hwmgr->chip_id == CHIP_RAVEN)
1180 		return 0;
1181 
1182 	/* We assume here that fw_info is unchanged if this call fails.*/
1183 	fw_info = smu_atom_get_data_table(hwmgr->adev,
1184 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1185 			 &size, &frev, &crev);
1186 	PP_ASSERT_WITH_CODE(fw_info != NULL,
1187 			    "Missing firmware info!", return -EINVAL);
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