xref: /linux/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c (revision d24cf9ce3f0607649a175f47c6f3d8f45dbf08ad)
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_flex(*dep_table, entries, table->ucNumEntries);
386 	if (NULL == dep_table)
387 		return -ENOMEM;
388 
389 	dep_table->count = (unsigned long)table->ucNumEntries;
390 
391 	for (i = 0; i < dep_table->count; i++) {
392 		dep_table->entries[i].clk =
393 			((unsigned long)table->entries[i].ucClockHigh << 16) |
394 			le16_to_cpu(table->entries[i].usClockLow);
395 		dep_table->entries[i].v =
396 			(unsigned long)le16_to_cpu(table->entries[i].usVoltage);
397 	}
398 
399 	*ptable = dep_table;
400 
401 	return 0;
402 }
403 
404 static int get_valid_clk(struct pp_hwmgr *hwmgr,
405 			struct phm_clock_array **ptable,
406 			const struct phm_clock_voltage_dependency_table *table)
407 {
408 	unsigned long i;
409 	struct phm_clock_array *clock_table;
410 
411 	clock_table = kzalloc_flex(*clock_table, values, table->count);
412 	if (!clock_table)
413 		return -ENOMEM;
414 
415 	clock_table->count = (unsigned long)table->count;
416 
417 	for (i = 0; i < clock_table->count; i++)
418 		clock_table->values[i] = (unsigned long)table->entries[i].clk;
419 
420 	*ptable = clock_table;
421 
422 	return 0;
423 }
424 
425 static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
426 			struct phm_clock_and_voltage_limits *limits,
427 			const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
428 {
429 	limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
430 			le16_to_cpu(table->entries[0].usSclkLow);
431 	limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
432 			le16_to_cpu(table->entries[0].usMclkLow);
433 	limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
434 	limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
435 
436 	return 0;
437 }
438 
439 
440 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
441 		       enum phm_platform_caps cap)
442 {
443 	if (enable)
444 		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
445 	else
446 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
447 }
448 
449 static int set_platform_caps(struct pp_hwmgr *hwmgr,
450 			unsigned long powerplay_caps)
451 {
452 	set_hw_cap(
453 		hwmgr,
454 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
455 		PHM_PlatformCaps_PowerPlaySupport
456 	);
457 
458 	set_hw_cap(
459 		hwmgr,
460 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
461 		PHM_PlatformCaps_BiosPowerSourceControl
462 	);
463 
464 	set_hw_cap(
465 		hwmgr,
466 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
467 		PHM_PlatformCaps_EnableASPML0s
468 	);
469 
470 	set_hw_cap(
471 		hwmgr,
472 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
473 		PHM_PlatformCaps_EnableASPML1
474 	);
475 
476 	set_hw_cap(
477 		hwmgr,
478 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
479 		PHM_PlatformCaps_EnableBackbias
480 	);
481 
482 	set_hw_cap(
483 		hwmgr,
484 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
485 		PHM_PlatformCaps_AutomaticDCTransition
486 	);
487 
488 	set_hw_cap(
489 		hwmgr,
490 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
491 		PHM_PlatformCaps_GeminiPrimary
492 	);
493 
494 	set_hw_cap(
495 		hwmgr,
496 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
497 		PHM_PlatformCaps_StepVddc
498 	);
499 
500 	set_hw_cap(
501 		hwmgr,
502 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
503 		PHM_PlatformCaps_EnableVoltageControl
504 	);
505 
506 	set_hw_cap(
507 		hwmgr,
508 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
509 		PHM_PlatformCaps_EnableSideportControl
510 	);
511 
512 	set_hw_cap(
513 		hwmgr,
514 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
515 		PHM_PlatformCaps_TurnOffPll_ASPML1
516 	);
517 
518 	set_hw_cap(
519 		hwmgr,
520 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
521 		PHM_PlatformCaps_EnableHTLinkControl
522 	);
523 
524 	set_hw_cap(
525 		hwmgr,
526 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
527 		PHM_PlatformCaps_EnableMVDDControl
528 	);
529 
530 	set_hw_cap(
531 		hwmgr,
532 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
533 		PHM_PlatformCaps_ControlVDDCI
534 	);
535 
536 	set_hw_cap(
537 		hwmgr,
538 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
539 		PHM_PlatformCaps_RegulatorHot
540 	);
541 
542 	set_hw_cap(
543 		hwmgr,
544 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
545 		PHM_PlatformCaps_BootStateOnAlert
546 	);
547 
548 	set_hw_cap(
549 		hwmgr,
550 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
551 		PHM_PlatformCaps_DontWaitForVBlankOnAlert
552 	);
553 
554 	set_hw_cap(
555 		hwmgr,
556 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
557 		PHM_PlatformCaps_BACO
558 	);
559 
560 	set_hw_cap(
561 		hwmgr,
562 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
563 		PHM_PlatformCaps_NewCACVoltage
564 	);
565 
566 	set_hw_cap(
567 		hwmgr,
568 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
569 		PHM_PlatformCaps_RevertGPIO5Polarity
570 	);
571 
572 	set_hw_cap(
573 		hwmgr,
574 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
575 		PHM_PlatformCaps_Thermal2GPIO17
576 	);
577 
578 	set_hw_cap(
579 		hwmgr,
580 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
581 		PHM_PlatformCaps_VRHotGPIOConfigurable
582 	);
583 
584 	set_hw_cap(
585 		hwmgr,
586 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
587 		PHM_PlatformCaps_TempInversion
588 	);
589 
590 	set_hw_cap(
591 		hwmgr,
592 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
593 		PHM_PlatformCaps_EVV
594 	);
595 
596 	set_hw_cap(
597 		hwmgr,
598 		0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
599 		PHM_PlatformCaps_CombinePCCWithThermalSignal
600 	);
601 
602 	set_hw_cap(
603 		hwmgr,
604 		0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
605 		PHM_PlatformCaps_LoadPostProductionFirmware
606 	);
607 
608 	set_hw_cap(
609 		hwmgr,
610 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
611 		PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
612 	);
613 
614 	return 0;
615 }
616 
617 static PP_StateClassificationFlags make_classification_flags(
618 						   struct pp_hwmgr *hwmgr,
619 						    USHORT classification,
620 						   USHORT classification2)
621 {
622 	PP_StateClassificationFlags result = 0;
623 
624 	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
625 		result |= PP_StateClassificationFlag_Boot;
626 
627 	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
628 		result |= PP_StateClassificationFlag_Thermal;
629 
630 	if (classification &
631 			ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
632 		result |= PP_StateClassificationFlag_LimitedPowerSource;
633 
634 	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
635 		result |= PP_StateClassificationFlag_Rest;
636 
637 	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
638 		result |= PP_StateClassificationFlag_Forced;
639 
640 	if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
641 		result |= PP_StateClassificationFlag_3DPerformance;
642 
643 
644 	if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
645 		result |= PP_StateClassificationFlag_ACOverdriveTemplate;
646 
647 	if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
648 		result |= PP_StateClassificationFlag_Uvd;
649 
650 	if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
651 		result |= PP_StateClassificationFlag_UvdHD;
652 
653 	if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
654 		result |= PP_StateClassificationFlag_UvdSD;
655 
656 	if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
657 		result |= PP_StateClassificationFlag_HD2;
658 
659 	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
660 		result |= PP_StateClassificationFlag_ACPI;
661 
662 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
663 		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
664 
665 
666 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
667 		result |= PP_StateClassificationFlag_ULV;
668 
669 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
670 		result |= PP_StateClassificationFlag_UvdMVC;
671 
672 	return result;
673 }
674 
675 static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
676 						struct pp_power_state *ps,
677 							    uint8_t version,
678 			 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
679 	unsigned long rrr_index;
680 	unsigned long tmp;
681 
682 	ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
683 					ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
684 	ps->classification.flags = make_classification_flags(hwmgr,
685 				le16_to_cpu(pnon_clock_info->usClassification),
686 				le16_to_cpu(pnon_clock_info->usClassification2));
687 
688 	ps->classification.temporary_state = false;
689 	ps->classification.to_be_deleted = false;
690 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
691 		ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
692 
693 	ps->validation.singleDisplayOnly = (0 != tmp);
694 
695 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
696 		ATOM_PPLIB_DISALLOW_ON_DC;
697 
698 	ps->validation.disallowOnDC = (0 != tmp);
699 
700 	ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
701 				ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
702 				ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
703 
704 	ps->display.disableFrameModulation = false;
705 
706 	rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
707 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
708 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
709 
710 	if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
711 		static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
712 								{ 0, 50, 0 };
713 
714 		ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
715 		ps->display.explicitRefreshrate = look_up[rrr_index];
716 		ps->display.limitRefreshrate = true;
717 
718 		if (ps->display.explicitRefreshrate == 0)
719 			ps->display.limitRefreshrate = false;
720 	} else
721 		ps->display.limitRefreshrate = false;
722 
723 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
724 		ATOM_PPLIB_ENABLE_VARIBRIGHT;
725 
726 	ps->display.enableVariBright = (0 != tmp);
727 
728 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
729 		ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
730 
731 	ps->memory.dllOff = (0 != tmp);
732 
733 	ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
734 			    ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
735 
736 	ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
737 				     pnon_clock_info->ucMinTemperature;
738 
739 	ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
740 				     pnon_clock_info->ucMaxTemperature;
741 
742 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
743 		ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
744 
745 	ps->software.disableLoadBalancing = tmp;
746 
747 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
748 		ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
749 
750 	ps->software.enableSleepForTimestamps = (0 != tmp);
751 
752 	ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
753 
754 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
755 		ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
756 		ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
757 	} else {
758 		ps->uvd_clocks.VCLK = 0;
759 		ps->uvd_clocks.DCLK = 0;
760 	}
761 
762 	return 0;
763 }
764 
765 static ULONG size_of_entry_v2(ULONG num_dpm_levels)
766 {
767 	return (sizeof(UCHAR) + sizeof(UCHAR) +
768 			(num_dpm_levels * sizeof(UCHAR)));
769 }
770 
771 static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
772 					const StateArray * pstate_arrays,
773 							 ULONG entry_index)
774 {
775 	ULONG i;
776 	const ATOM_PPLIB_STATE_V2 *pstate;
777 
778 	pstate = pstate_arrays->states;
779 	if (entry_index <= pstate_arrays->ucNumEntries) {
780 		for (i = 0; i < entry_index; i++)
781 			pstate = (ATOM_PPLIB_STATE_V2 *)(
782 						  (unsigned long)pstate +
783 			     size_of_entry_v2(pstate->ucNumDPMLevels));
784 	}
785 	return pstate;
786 }
787 
788 static const unsigned char soft_dummy_pp_table[] = {
789 	0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
790 	0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
791 	0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
792 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
794 	0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
795 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
796 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
799 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
800 	0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
801 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
802 	0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
803 	0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
804 	0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
805 	0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
806 	0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
807 	0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
808 	0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
809 	0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
810 	0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
811 	0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
812 	0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
813 	0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
814 	0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
815 	0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
816 	0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
817 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
818 	0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
819 	0x00
820 };
821 
822 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
823 				     struct pp_hwmgr *hwmgr)
824 {
825 	const void *table_addr = hwmgr->soft_pp_table;
826 	uint8_t frev, crev;
827 	uint16_t size;
828 
829 	if (!table_addr) {
830 		if (hwmgr->chip_id == CHIP_RAVEN) {
831 			table_addr = &soft_dummy_pp_table[0];
832 			hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
833 			hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
834 		} else {
835 			table_addr = smu_atom_get_data_table(hwmgr->adev,
836 					GetIndexIntoMasterTable(DATA, PowerPlayInfo),
837 					&size, &frev, &crev);
838 			hwmgr->soft_pp_table = table_addr;
839 			hwmgr->soft_pp_table_size = size;
840 		}
841 	}
842 
843 	return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
844 }
845 
846 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
847 				uint32_t *vol_rep_time, uint32_t *bb_rep_time)
848 {
849 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
850 
851 	PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
852 			    "Missing PowerPlay Table!", return -EINVAL);
853 
854 	*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
855 	*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
856 
857 	return 0;
858 }
859 
860 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
861 				     unsigned long *num_of_entries)
862 {
863 	const StateArray *pstate_arrays;
864 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
865 
866 	if (powerplay_table == NULL)
867 		return -1;
868 
869 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
870 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
871 					le16_to_cpu(powerplay_table->usStateArrayOffset));
872 
873 		*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
874 	} else
875 		*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
876 
877 	return 0;
878 }
879 
880 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
881 				unsigned long entry_index,
882 				struct pp_power_state *ps,
883 			 pp_tables_hw_clock_info_callback func)
884 {
885 	int i;
886 	const StateArray *pstate_arrays;
887 	const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
888 	const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
889 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
890 	int result = 0;
891 	int res = 0;
892 
893 	const ClockInfoArray *pclock_arrays;
894 
895 	const NonClockInfoArray *pnon_clock_arrays;
896 
897 	const ATOM_PPLIB_STATE *pstate_entry;
898 
899 	if (powerplay_table == NULL)
900 		return -1;
901 
902 	ps->classification.bios_index = entry_index;
903 
904 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
905 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
906 					le16_to_cpu(powerplay_table->usStateArrayOffset));
907 
908 		if (entry_index > pstate_arrays->ucNumEntries)
909 			return -1;
910 
911 		pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
912 		pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
913 					le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
914 
915 		pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
916 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
917 
918 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
919 					(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
920 
921 		result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
922 
923 		for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
924 			const void *pclock_info = (const void *)(
925 							(unsigned long)(pclock_arrays->clockInfo) +
926 							(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
927 			res = func(hwmgr, &ps->hardware, i, pclock_info);
928 			if ((0 == result) && (0 != res))
929 				result = res;
930 		}
931 	} else {
932 		if (entry_index > powerplay_table->ucNumStates)
933 			return -1;
934 
935 		pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
936 						    le16_to_cpu(powerplay_table->usStateArrayOffset) +
937 						    entry_index * powerplay_table->ucStateEntrySize);
938 
939 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
940 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
941 						pstate_entry->ucNonClockStateIndex *
942 						powerplay_table->ucNonClockSize);
943 
944 		result = init_non_clock_fields(hwmgr, ps,
945 							powerplay_table->ucNonClockSize,
946 							pnon_clock_info);
947 
948 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
949 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
950 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
951 						pstate_entry->ucClockStateIndices[i] *
952 						powerplay_table->ucClockInfoSize);
953 
954 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
955 
956 			if ((0 == result) && (0 != res))
957 					result = res;
958 		}
959 	}
960 
961 	if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
962 		if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
963 			result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
964 	}
965 
966 	return result;
967 }
968 
969 static int init_powerplay_tables(
970 			struct pp_hwmgr *hwmgr,
971 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
972 )
973 {
974 	return 0;
975 }
976 
977 
978 static int init_thermal_controller(
979 			struct pp_hwmgr *hwmgr,
980 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
981 {
982 	struct amdgpu_device *adev = hwmgr->adev;
983 
984 	hwmgr->thermal_controller.ucType =
985 			powerplay_table->sThermalController.ucType;
986 	hwmgr->thermal_controller.ucI2cLine =
987 			powerplay_table->sThermalController.ucI2cLine;
988 	hwmgr->thermal_controller.ucI2cAddress =
989 			powerplay_table->sThermalController.ucI2cAddress;
990 
991 	hwmgr->thermal_controller.fanInfo.bNoFan =
992 		(0 != (powerplay_table->sThermalController.ucFanParameters &
993 			ATOM_PP_FANPARAMETERS_NOFAN));
994 
995 	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
996 		powerplay_table->sThermalController.ucFanParameters &
997 		ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
998 
999 	hwmgr->thermal_controller.fanInfo.ulMinRPM
1000 		= powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1001 	hwmgr->thermal_controller.fanInfo.ulMaxRPM
1002 		= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1003 
1004 	set_hw_cap(hwmgr,
1005 		   ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1006 		   PHM_PlatformCaps_ThermalController);
1007 
1008         if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
1009 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
1010 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1011 
1012 		if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {
1013 			hwmgr->thermal_controller.use_hw_fan_control = 1;
1014 			return 0;
1015 		} else {
1016 			const ATOM_PPLIB_FANTABLE *fan_table =
1017 				(const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) +
1018 							      le16_to_cpu(powerplay_table3->usFanTableOffset));
1019 
1020 			if (1 <= fan_table->ucFanTableFormat) {
1021 				hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst =
1022 					fan_table->ucTHyst;
1023 				hwmgr->thermal_controller.advanceFanControlParameters.usTMin =
1024 					le16_to_cpu(fan_table->usTMin);
1025 				hwmgr->thermal_controller.advanceFanControlParameters.usTMed =
1026 					le16_to_cpu(fan_table->usTMed);
1027 				hwmgr->thermal_controller.advanceFanControlParameters.usTHigh =
1028 					le16_to_cpu(fan_table->usTHigh);
1029 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
1030 					le16_to_cpu(fan_table->usPWMMin);
1031 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed =
1032 					le16_to_cpu(fan_table->usPWMMed);
1033 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh =
1034 					le16_to_cpu(fan_table->usPWMHigh);
1035 				hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900;
1036 				hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000;
1037 
1038 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1039 					    PHM_PlatformCaps_MicrocodeFanControl);
1040 			}
1041 
1042 			if (2 <= fan_table->ucFanTableFormat) {
1043 				const ATOM_PPLIB_FANTABLE2 *fan_table2 =
1044 					(const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) +
1045 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1046 				hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
1047 					le16_to_cpu(fan_table2->usTMax);
1048 			}
1049 
1050 			if (3 <= fan_table->ucFanTableFormat) {
1051 				const ATOM_PPLIB_FANTABLE3 *fan_table3 =
1052 					(const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) +
1053 									le16_to_cpu(powerplay_table3->usFanTableOffset));
1054 
1055 				hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =
1056 					fan_table3->ucFanControlMode;
1057 
1058 				if ((3 == fan_table->ucFanTableFormat) &&
1059 				    (0x67B1 == adev->pdev->device))
1060 					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1061 						47;
1062 				else
1063 					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1064 						le16_to_cpu(fan_table3->usFanPWMMax);
1065 
1066 				hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity =
1067 					4836;
1068 				hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
1069 					le16_to_cpu(fan_table3->usFanOutputSensitivity);
1070 			}
1071 
1072 			if (6 <= fan_table->ucFanTableFormat) {
1073 				const ATOM_PPLIB_FANTABLE4 *fan_table4 =
1074 					(const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) +
1075 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1076 
1077 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1078 					    PHM_PlatformCaps_FanSpeedInTableIsRPM);
1079 
1080 				hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM =
1081 					le16_to_cpu(fan_table4->usFanRPMMax);
1082 			}
1083 
1084 			if (7 <= fan_table->ucFanTableFormat) {
1085 				const ATOM_PPLIB_FANTABLE5 *fan_table5 =
1086 					(const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) +
1087 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1088 
1089 				if (0x67A2 == adev->pdev->device ||
1090 				    0x67A9 == adev->pdev->device ||
1091 				    0x67B9 == adev->pdev->device) {
1092 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1093 						    PHM_PlatformCaps_GeminiRegulatorFanControlSupport);
1094 					hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow =
1095 						le16_to_cpu(fan_table5->usFanCurrentLow);
1096 					hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh =
1097 						le16_to_cpu(fan_table5->usFanCurrentHigh);
1098 					hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow =
1099 						le16_to_cpu(fan_table5->usFanRPMLow);
1100 					hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh =
1101 						le16_to_cpu(fan_table5->usFanRPMHigh);
1102 				}
1103 			}
1104 		}
1105 	}
1106 
1107 	return 0;
1108 }
1109 
1110 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
1111 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1112 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
1113 {
1114 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
1115 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
1116 
1117 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1118 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1119 
1120 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1121 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1122 
1123 	hwmgr->platform_descriptor.minOverdriveVDDC =
1124 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1125 
1126 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1127 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1128 
1129 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1130 	return 0;
1131 }
1132 
1133 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1134 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1135 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1136 {
1137 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1138 	const ATOM_PPLIB_EXTENDEDHEADER *header;
1139 
1140 	if (le16_to_cpu(powerplay_table->usTableSize) <
1141 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1142 		return 0;
1143 
1144 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1145 
1146 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
1147 		return 0;
1148 
1149 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1150 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1151 
1152 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1153 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1154 
1155 
1156 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1157 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1158 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1159 
1160 	return 0;
1161 }
1162 
1163 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1164 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1165 {
1166 	int result = 0;
1167 	uint8_t frev, crev;
1168 	uint16_t size;
1169 
1170 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1171 
1172 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1173 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1174 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1175 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1176 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1177 
1178 	if (hwmgr->chip_id == CHIP_RAVEN)
1179 		return 0;
1180 
1181 	/* We assume here that fw_info is unchanged if this call fails.*/
1182 	fw_info = smu_atom_get_data_table(hwmgr->adev,
1183 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1184 			 &size, &frev, &crev);
1185 	PP_ASSERT_WITH_CODE(fw_info != NULL,
1186 			    "Missing firmware info!", return -EINVAL);
1187 
1188 	if ((fw_info->ucTableFormatRevision == 1)
1189 	    && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1190 		result = init_overdrive_limits_V1_4(hwmgr,
1191 				powerplay_table,
1192 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1193 
1194 	else if ((fw_info->ucTableFormatRevision == 2)
1195 		 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1196 		result = init_overdrive_limits_V2_1(hwmgr,
1197 				powerplay_table,
1198 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1199 
1200 	return result;
1201 }
1202 
1203 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1204 		struct phm_uvd_clock_voltage_dependency_table **ptable,
1205 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1206 		const UVDClockInfoArray *array)
1207 {
1208 	unsigned long i;
1209 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1210 
1211 	uvd_table = kzalloc_flex(*uvd_table, entries, table->numEntries);
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_flex(*vce_table, entries, table->numEntries);
1241 	if (!vce_table)
1242 		return -ENOMEM;
1243 
1244 	vce_table->count = table->numEntries;
1245 	for (i = 0; i < table->numEntries; i++) {
1246 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1247 
1248 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1249 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1250 					| le16_to_cpu(entry->usEVClkLow);
1251 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1252 					| le16_to_cpu(entry->usECClkLow);
1253 	}
1254 
1255 	*ptable = vce_table;
1256 
1257 	return 0;
1258 }
1259 
1260 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1261 		 struct phm_samu_clock_voltage_dependency_table **ptable,
1262 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1263 {
1264 	unsigned long i;
1265 	struct phm_samu_clock_voltage_dependency_table *samu_table;
1266 
1267 	samu_table = kzalloc_flex(*samu_table, entries, table->numEntries);
1268 	if (!samu_table)
1269 		return -ENOMEM;
1270 
1271 	samu_table->count = table->numEntries;
1272 
1273 	for (i = 0; i < table->numEntries; i++) {
1274 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1275 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1276 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
1277 	}
1278 
1279 	*ptable = samu_table;
1280 
1281 	return 0;
1282 }
1283 
1284 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1285 		struct phm_acp_clock_voltage_dependency_table **ptable,
1286 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1287 {
1288 	unsigned long i;
1289 	struct phm_acp_clock_voltage_dependency_table *acp_table;
1290 
1291 	acp_table = kzalloc_flex(*acp_table, entries, table->numEntries);
1292 	if (!acp_table)
1293 		return -ENOMEM;
1294 
1295 	acp_table->count = (unsigned long)table->numEntries;
1296 
1297 	for (i = 0; i < table->numEntries; i++) {
1298 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1299 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1300 					 | le16_to_cpu(table->entries[i].usACPClockLow);
1301 	}
1302 
1303 	*ptable = acp_table;
1304 
1305 	return 0;
1306 }
1307 
1308 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1309 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1310 {
1311 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1312 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1313 	int result = 0;
1314 
1315 	uint16_t vce_clock_info_array_offset;
1316 	uint16_t uvd_clock_info_array_offset;
1317 	uint16_t table_offset;
1318 
1319 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1320 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1321 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1322 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1323 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1324 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1325 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1326 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1327 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1328 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1329 
1330 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1331 						hwmgr, powerplay_table);
1332 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1333 						powerplay_table);
1334 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1335 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1336 				(((unsigned long) powerplay_table) +
1337 				vce_clock_info_array_offset);
1338 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1339 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1340 				(((unsigned long) powerplay_table) + table_offset);
1341 		result = get_vce_clock_voltage_limit_table(hwmgr,
1342 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1343 				table, array);
1344 	}
1345 
1346 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1347 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1348 
1349 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1350 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1351 				(((unsigned long) powerplay_table) +
1352 				uvd_clock_info_array_offset);
1353 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1354 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1355 				(((unsigned long) powerplay_table) + table_offset);
1356 		result = get_uvd_clock_voltage_limit_table(hwmgr,
1357 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1358 	}
1359 
1360 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1361 							    powerplay_table);
1362 
1363 	if (table_offset > 0) {
1364 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1365 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1366 				(((unsigned long) powerplay_table) + table_offset);
1367 		result = get_samu_clock_voltage_limit_table(hwmgr,
1368 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1369 	}
1370 
1371 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1372 							     powerplay_table);
1373 
1374 	if (table_offset > 0) {
1375 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1376 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1377 				(((unsigned long) powerplay_table) + table_offset);
1378 		result = get_acp_clock_voltage_limit_table(hwmgr,
1379 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1380 	}
1381 
1382 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1383 	if (table_offset > 0) {
1384 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1385 
1386 		if (rev_id > 0) {
1387 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1388 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1389 				(((unsigned long) powerplay_table) + table_offset);
1390 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1391 				&tune_table->power_tune_table,
1392 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1393 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1394 				le16_to_cpu(tune_table->usTjMax);
1395 		} else {
1396 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1397 				(const ATOM_PPLIB_POWERTUNE_Table *)
1398 				(((unsigned long) powerplay_table) + table_offset);
1399 			result = get_cac_tdp_table(hwmgr,
1400 				&hwmgr->dyn_state.cac_dtp_table,
1401 				&tune_table->power_tune_table, 255);
1402 		}
1403 	}
1404 
1405 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1406 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1407 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1408 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1409 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1410 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1411 				(((unsigned long) powerplay_table4) +
1412 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1413 			result = get_clock_voltage_dependency_table(hwmgr,
1414 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1415 		}
1416 
1417 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1418 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1419 				(((unsigned long) powerplay_table4) +
1420 				 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1421 			result = get_clock_voltage_dependency_table(hwmgr,
1422 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1423 		}
1424 
1425 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1426 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1427 				(((unsigned long) powerplay_table4) +
1428 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1429 			result = get_clock_voltage_dependency_table(hwmgr,
1430 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1431 		}
1432 
1433 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1434 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1435 				(((unsigned long) powerplay_table4) +
1436 				 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1437 			result = get_clock_voltage_limit(hwmgr,
1438 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1439 		}
1440 
1441 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1442 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1443 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1444 					hwmgr->dyn_state.vddc_dependency_on_mclk);
1445 
1446 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1447 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1448 			result = get_valid_clk(hwmgr,
1449 				&hwmgr->dyn_state.valid_sclk_values,
1450 				hwmgr->dyn_state.vddc_dependency_on_sclk);
1451 
1452 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1453 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1454 				(((unsigned long) powerplay_table4) +
1455 				 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1456 			result = get_clock_voltage_dependency_table(hwmgr,
1457 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1458 		}
1459 	}
1460 
1461 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1462 								powerplay_table);
1463 
1464 	if (table_offset > 0) {
1465 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1466 			(((unsigned long) powerplay_table) + table_offset);
1467 		result = get_clock_voltage_dependency_table(hwmgr,
1468 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1469 	}
1470 
1471 	return result;
1472 }
1473 
1474 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1475 				 struct phm_cac_leakage_table **ptable,
1476 				const ATOM_PPLIB_CAC_Leakage_Table *table)
1477 {
1478 	struct phm_cac_leakage_table  *cac_leakage_table;
1479 	unsigned long i;
1480 
1481 	if (!hwmgr || !table || !ptable)
1482 		return -EINVAL;
1483 
1484 	cac_leakage_table = kzalloc_flex(*cac_leakage_table, entries,
1485 					 table->ucNumEntries);
1486 	if (!cac_leakage_table)
1487 		return -ENOMEM;
1488 
1489 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
1490 
1491 	for (i = 0; i < cac_leakage_table->count; i++) {
1492 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1493 				PHM_PlatformCaps_EVV)) {
1494 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1495 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1496 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1497 		} else {
1498 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1499 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1500 		}
1501 	}
1502 
1503 	*ptable = cac_leakage_table;
1504 
1505 	return 0;
1506 }
1507 
1508 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1509 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
1510 {
1511 	struct phm_ppm_table *ptr = kzalloc_obj(struct phm_ppm_table);
1512 
1513 	if (NULL == ptr)
1514 		return -ENOMEM;
1515 
1516 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1517 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1518 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1519 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1520 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1521 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1522 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1523 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1524 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1525 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1526 	hwmgr->dyn_state.ppm_parameter_table = ptr;
1527 
1528 	return 0;
1529 }
1530 
1531 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1532 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1533 {
1534 	int result = 0;
1535 
1536 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1537 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1538 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1539 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1540 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1541 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1542 				(&ptable5->basicTable4);
1543 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1544 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1545 				(&ptable4->basicTable3);
1546 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1547 		uint16_t table_offset;
1548 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
1549 
1550 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1551 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1552 
1553 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1554 		hwmgr->platform_descriptor.TDPAdjustment = 0;
1555 
1556 		hwmgr->platform_descriptor.VidAdjustment = 0;
1557 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1558 		hwmgr->platform_descriptor.VidMinLimit     = 0;
1559 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1560 		hwmgr->platform_descriptor.VidStep         = 6250;
1561 
1562 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1563 
1564 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
1565 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1566 					PHM_PlatformCaps_PowerControl);
1567 
1568 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1569 
1570 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1571 
1572 		hwmgr->dyn_state.cac_leakage_table = NULL;
1573 
1574 		if (0 != ptable5->usCACLeakageTableOffset) {
1575 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1576 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1577 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
1578 			result = get_cac_leakage_table(hwmgr,
1579 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1580 		}
1581 
1582 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1583 
1584 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1585 
1586 		if (0 != ptable3->usExtendendedHeaderOffset) {
1587 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1588 					(((unsigned long)powerplay_table) +
1589 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1590 			if ((extended_header->usPPMTableOffset > 0) &&
1591 				le16_to_cpu(extended_header->usSize) >=
1592 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1593 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1594 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1595 					(((unsigned long)powerplay_table) + table_offset);
1596 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1597 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1598 						PHM_PlatformCaps_EnablePlatformPowerManagement);
1599 			}
1600 		}
1601 	}
1602 	return result;
1603 }
1604 
1605 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1606 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1607 {
1608 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1609 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1610 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1611 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1612 
1613 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1614 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1615 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1616 				(((unsigned long)powerplay_table4) +
1617 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1618 			struct phm_phase_shedding_limits_table *table;
1619 			unsigned long i;
1620 
1621 
1622 			table = kzalloc_flex(*table, entries,
1623 					     ptable->ucNumEntries);
1624 			if (!table)
1625 				return -ENOMEM;
1626 
1627 			table->count = (unsigned long)ptable->ucNumEntries;
1628 
1629 			for (i = 0; i < table->count; i++) {
1630 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1631 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1632 							| le16_to_cpu(ptable->entries[i].usSclkLow);
1633 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1634 							| le16_to_cpu(ptable->entries[i].usMclkLow);
1635 			}
1636 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1637 		}
1638 	}
1639 
1640 	return 0;
1641 }
1642 
1643 static int get_number_of_vce_state_table_entries(
1644 						  struct pp_hwmgr *hwmgr)
1645 {
1646 	const ATOM_PPLIB_POWERPLAYTABLE *table =
1647 					     get_powerplay_table(hwmgr);
1648 	const ATOM_PPLIB_VCE_State_Table *vce_table =
1649 				    get_vce_state_table(hwmgr, table);
1650 
1651 	if (vce_table)
1652 		return vce_table->numEntries;
1653 
1654 	return 0;
1655 }
1656 
1657 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1658 							unsigned long i,
1659 							struct amd_vce_state *vce_state,
1660 							void **clock_info,
1661 							unsigned long *flag)
1662 {
1663 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1664 
1665 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1666 
1667 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1668 
1669 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1670 
1671 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1672 								le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1673 
1674 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1675 
1676 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1677 
1678 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1679 
1680 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1681 
1682 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1683 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1684 
1685 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1686 
1687 	return 0;
1688 }
1689 
1690 
1691 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1692 {
1693 	int result;
1694 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1695 
1696 	if (hwmgr->chip_id == CHIP_RAVEN)
1697 		return 0;
1698 
1699 	hwmgr->need_pp_table_upload = true;
1700 
1701 	powerplay_table = get_powerplay_table(hwmgr);
1702 
1703 	result = init_powerplay_tables(hwmgr, powerplay_table);
1704 
1705 	PP_ASSERT_WITH_CODE((result == 0),
1706 			    "init_powerplay_tables failed", return result);
1707 
1708 	result = set_platform_caps(hwmgr,
1709 				le32_to_cpu(powerplay_table->ulPlatformCaps));
1710 
1711 	PP_ASSERT_WITH_CODE((result == 0),
1712 			    "set_platform_caps failed", return result);
1713 
1714 	result = init_thermal_controller(hwmgr, powerplay_table);
1715 
1716 	PP_ASSERT_WITH_CODE((result == 0),
1717 			    "init_thermal_controller failed", return result);
1718 
1719 	result = init_overdrive_limits(hwmgr, powerplay_table);
1720 
1721 	PP_ASSERT_WITH_CODE((result == 0),
1722 			    "init_overdrive_limits failed", return result);
1723 
1724 	result = init_clock_voltage_dependency(hwmgr,
1725 					       powerplay_table);
1726 
1727 	PP_ASSERT_WITH_CODE((result == 0),
1728 			    "init_clock_voltage_dependency failed", return result);
1729 
1730 	result = init_dpm2_parameters(hwmgr, powerplay_table);
1731 
1732 	PP_ASSERT_WITH_CODE((result == 0),
1733 			    "init_dpm2_parameters failed", return result);
1734 
1735 	result = init_phase_shedding_table(hwmgr, powerplay_table);
1736 
1737 	PP_ASSERT_WITH_CODE((result == 0),
1738 			    "init_phase_shedding_table failed", return result);
1739 
1740 	return result;
1741 }
1742 
1743 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1744 {
1745 	if (hwmgr->chip_id == CHIP_RAVEN)
1746 		return 0;
1747 
1748 	kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1749 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1750 
1751 	kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1752 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1753 
1754 	kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1755 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1756 
1757 	kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1758 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1759 
1760 	kfree(hwmgr->dyn_state.valid_mclk_values);
1761 	hwmgr->dyn_state.valid_mclk_values = NULL;
1762 
1763 	kfree(hwmgr->dyn_state.valid_sclk_values);
1764 	hwmgr->dyn_state.valid_sclk_values = NULL;
1765 
1766 	kfree(hwmgr->dyn_state.cac_leakage_table);
1767 	hwmgr->dyn_state.cac_leakage_table = NULL;
1768 
1769 	kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1770 	hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1771 
1772 	kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1773 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1774 
1775 	kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1776 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1777 
1778 	kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1779 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1780 
1781 	kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1782 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1783 
1784 	kfree(hwmgr->dyn_state.cac_dtp_table);
1785 	hwmgr->dyn_state.cac_dtp_table = NULL;
1786 
1787 	kfree(hwmgr->dyn_state.ppm_parameter_table);
1788 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1789 
1790 	kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1791 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1792 
1793 	return 0;
1794 }
1795 
1796 const struct pp_table_func pptable_funcs = {
1797 	.pptable_init = pp_tables_initialize,
1798 	.pptable_fini = pp_tables_uninitialize,
1799 	.pptable_get_number_of_vce_state_table_entries =
1800 				get_number_of_vce_state_table_entries,
1801 	.pptable_get_vce_state_table_entry =
1802 						get_vce_state_table_entry,
1803 };
1804 
1805