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