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