xref: /linux/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c (revision c771600c6af14749609b49565ffb4cac2959710d)
13bace359SJammy Zhou /*
23bace359SJammy Zhou  * Copyright 2015 Advanced Micro Devices, Inc.
33bace359SJammy Zhou  *
43bace359SJammy Zhou  * Permission is hereby granted, free of charge, to any person obtaining a
53bace359SJammy Zhou  * copy of this software and associated documentation files (the "Software"),
63bace359SJammy Zhou  * to deal in the Software without restriction, including without limitation
73bace359SJammy Zhou  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83bace359SJammy Zhou  * and/or sell copies of the Software, and to permit persons to whom the
93bace359SJammy Zhou  * Software is furnished to do so, subject to the following conditions:
103bace359SJammy Zhou  *
113bace359SJammy Zhou  * The above copyright notice and this permission notice shall be included in
123bace359SJammy Zhou  * all copies or substantial portions of the Software.
133bace359SJammy Zhou  *
143bace359SJammy Zhou  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153bace359SJammy Zhou  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163bace359SJammy Zhou  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
173bace359SJammy Zhou  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
183bace359SJammy Zhou  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
193bace359SJammy Zhou  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
203bace359SJammy Zhou  * OTHER DEALINGS IN THE SOFTWARE.
213bace359SJammy Zhou  *
223bace359SJammy Zhou  */
237bd55429SHuang Rui #include "pp_debug.h"
243bace359SJammy Zhou #include <linux/types.h>
253bace359SJammy Zhou #include <linux/kernel.h>
263bace359SJammy Zhou #include <linux/slab.h>
27b7a1f382SAlex Deucher #include <linux/pci.h>
28b7a1f382SAlex Deucher 
293b4ca9e6SRex Zhu #include <drm/amdgpu_drm.h>
303bace359SJammy Zhou #include "processpptables.h"
313bace359SJammy Zhou #include <atom-types.h>
323bace359SJammy Zhou #include <atombios.h>
333bace359SJammy Zhou #include "pptable.h"
343bace359SJammy Zhou #include "power_state.h"
353bace359SJammy Zhou #include "hwmgr.h"
363bace359SJammy Zhou #include "hardwaremanager.h"
373bace359SJammy Zhou 
383bace359SJammy Zhou 
393bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
403bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
413bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
423bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
433bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
443bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
453bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
463bace359SJammy Zhou #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
473bace359SJammy Zhou 
483bace359SJammy Zhou #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
493bace359SJammy Zhou 
get_vce_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)503bace359SJammy Zhou static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,
513bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
523bace359SJammy Zhou {
533bace359SJammy Zhou 	uint16_t vce_table_offset = 0;
543bace359SJammy Zhou 
553bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
563bace359SJammy Zhou 	   sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
573bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
583bace359SJammy Zhou 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
593bace359SJammy Zhou 
603bace359SJammy Zhou 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
613bace359SJammy Zhou 			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
623bace359SJammy Zhou 						(const ATOM_PPLIB_EXTENDEDHEADER *)
633bace359SJammy Zhou 						(((unsigned long)powerplay_table3) +
643bace359SJammy Zhou 						le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
653bace359SJammy Zhou 			if (le16_to_cpu(extended_header->usSize) >=
663bace359SJammy Zhou 			   SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)
673bace359SJammy Zhou 				vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);
683bace359SJammy Zhou 		}
693bace359SJammy Zhou 	}
703bace359SJammy Zhou 
713bace359SJammy Zhou 	return vce_table_offset;
723bace359SJammy Zhou }
733bace359SJammy Zhou 
get_vce_clock_info_array_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)743bace359SJammy Zhou static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,
753bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
763bace359SJammy Zhou {
773bace359SJammy Zhou 	uint16_t table_offset = get_vce_table_offset(hwmgr,
783bace359SJammy Zhou 						powerplay_table);
793bace359SJammy Zhou 
803bace359SJammy Zhou 	if (table_offset > 0)
813bace359SJammy Zhou 		return table_offset + 1;
823bace359SJammy Zhou 
833bace359SJammy Zhou 	return 0;
843bace359SJammy Zhou }
853bace359SJammy Zhou 
get_vce_clock_info_array_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)863bace359SJammy Zhou static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,
873bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
883bace359SJammy Zhou {
893bace359SJammy Zhou 	uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
903bace359SJammy Zhou 							powerplay_table);
913bace359SJammy Zhou 	uint16_t table_size = 0;
923bace359SJammy Zhou 
933bace359SJammy Zhou 	if (table_offset > 0) {
943bace359SJammy Zhou 		const VCEClockInfoArray *p = (const VCEClockInfoArray *)
953bace359SJammy Zhou 			(((unsigned long) powerplay_table) + table_offset);
963bace359SJammy Zhou 		table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);
973bace359SJammy Zhou 	}
983bace359SJammy Zhou 
993bace359SJammy Zhou 	return table_size;
1003bace359SJammy Zhou }
1013bace359SJammy Zhou 
get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1023bace359SJammy Zhou static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,
1033bace359SJammy Zhou 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1043bace359SJammy Zhou {
1053bace359SJammy Zhou 	uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,
1063bace359SJammy Zhou 							powerplay_table);
1073bace359SJammy Zhou 
1083bace359SJammy Zhou 	if (table_offset > 0)
1093bace359SJammy Zhou 		return table_offset + get_vce_clock_info_array_size(hwmgr,
1103bace359SJammy Zhou 							powerplay_table);
1113bace359SJammy Zhou 
1123bace359SJammy Zhou 	return 0;
1133bace359SJammy Zhou }
1143bace359SJammy Zhou 
get_vce_clock_voltage_limit_table_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1153bace359SJammy Zhou static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,
1163bace359SJammy Zhou 							const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1173bace359SJammy Zhou {
1183bace359SJammy Zhou 	uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1193bace359SJammy Zhou 	uint16_t table_size = 0;
1203bace359SJammy Zhou 
1213bace359SJammy Zhou 	if (table_offset > 0) {
1223bace359SJammy Zhou 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =
1233bace359SJammy Zhou 			(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);
1243bace359SJammy Zhou 
1253bace359SJammy Zhou 		table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);
1263bace359SJammy Zhou 	}
1273bace359SJammy Zhou 	return table_size;
1283bace359SJammy Zhou }
1293bace359SJammy Zhou 
get_vce_state_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1303bace359SJammy Zhou static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1313bace359SJammy Zhou {
1323bace359SJammy Zhou 	uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1333bace359SJammy Zhou 
1343bace359SJammy Zhou 	if (table_offset > 0)
1353bace359SJammy Zhou 		return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);
1363bace359SJammy Zhou 
1373bace359SJammy Zhou 	return 0;
1383bace359SJammy Zhou }
1393bace359SJammy Zhou 
get_vce_state_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1403bace359SJammy Zhou static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(
1413bace359SJammy Zhou 						struct pp_hwmgr *hwmgr,
1423bace359SJammy Zhou 						const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1433bace359SJammy Zhou {
1443bace359SJammy Zhou 	uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);
1453bace359SJammy Zhou 
1463bace359SJammy Zhou 	if (table_offset > 0)
1473bace359SJammy Zhou 		return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);
1483bace359SJammy Zhou 
1493bace359SJammy Zhou 	return NULL;
1503bace359SJammy Zhou }
1513bace359SJammy Zhou 
get_uvd_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1523bace359SJammy Zhou static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,
1533bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1543bace359SJammy Zhou {
1553bace359SJammy Zhou 	uint16_t uvd_table_offset = 0;
1563bace359SJammy Zhou 
1573bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1583bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
1593bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
1603bace359SJammy Zhou 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1613bace359SJammy Zhou 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
1623bace359SJammy Zhou 			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
1633bace359SJammy Zhou 					(const ATOM_PPLIB_EXTENDEDHEADER *)
1643bace359SJammy Zhou 					(((unsigned long)powerplay_table3) +
1653bace359SJammy Zhou 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1663bace359SJammy Zhou 			if (le16_to_cpu(extended_header->usSize) >=
1673bace359SJammy Zhou 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)
1683bace359SJammy Zhou 				uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);
1693bace359SJammy Zhou 		}
1703bace359SJammy Zhou 	}
1713bace359SJammy Zhou 	return uvd_table_offset;
1723bace359SJammy Zhou }
1733bace359SJammy Zhou 
get_uvd_clock_info_array_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1743bace359SJammy Zhou static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,
1753bace359SJammy Zhou 			 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1763bace359SJammy Zhou {
1773bace359SJammy Zhou 	uint16_t table_offset = get_uvd_table_offset(hwmgr,
1783bace359SJammy Zhou 						    powerplay_table);
1793bace359SJammy Zhou 
1803bace359SJammy Zhou 	if (table_offset > 0)
1813bace359SJammy Zhou 		return table_offset + 1;
1823bace359SJammy Zhou 	return 0;
1833bace359SJammy Zhou }
1843bace359SJammy Zhou 
get_uvd_clock_info_array_size(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1853bace359SJammy Zhou static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,
1863bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1873bace359SJammy Zhou {
1883bace359SJammy Zhou 	uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
1893bace359SJammy Zhou 						    powerplay_table);
1903bace359SJammy Zhou 	uint16_t table_size = 0;
1913bace359SJammy Zhou 
1923bace359SJammy Zhou 	if (table_offset > 0) {
1933bace359SJammy Zhou 		const UVDClockInfoArray *p = (const UVDClockInfoArray *)
1943bace359SJammy Zhou 					(((unsigned long) powerplay_table)
1953bace359SJammy Zhou 					+ table_offset);
1963bace359SJammy Zhou 		table_size = sizeof(UCHAR) +
1973bace359SJammy Zhou 			     p->ucNumEntries * sizeof(UVDClockInfo);
1983bace359SJammy Zhou 	}
1993bace359SJammy Zhou 
2003bace359SJammy Zhou 	return table_size;
2013bace359SJammy Zhou }
2023bace359SJammy Zhou 
get_uvd_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)2033bace359SJammy Zhou static uint16_t get_uvd_clock_voltage_limit_table_offset(
2043bace359SJammy Zhou 			struct pp_hwmgr *hwmgr,
2053bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
2063bace359SJammy Zhou {
2073bace359SJammy Zhou 	uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,
2083bace359SJammy Zhou 						     powerplay_table);
2093bace359SJammy Zhou 
2103bace359SJammy Zhou 	if (table_offset > 0)
2113bace359SJammy Zhou 		return table_offset +
2123bace359SJammy Zhou 			get_uvd_clock_info_array_size(hwmgr, powerplay_table);
2133bace359SJammy Zhou 
2143bace359SJammy Zhou 	return 0;
2153bace359SJammy Zhou }
2163bace359SJammy Zhou 
get_samu_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)2173bace359SJammy Zhou static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,
2183bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
2193bace359SJammy Zhou {
2203bace359SJammy Zhou 	uint16_t samu_table_offset = 0;
2213bace359SJammy Zhou 
2223bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
2233bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
2243bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
2253bace359SJammy Zhou 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
2263bace359SJammy Zhou 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
2273bace359SJammy Zhou 			const ATOM_PPLIB_EXTENDEDHEADER  *extended_header =
2283bace359SJammy Zhou 				(const ATOM_PPLIB_EXTENDEDHEADER *)
2293bace359SJammy Zhou 				(((unsigned long)powerplay_table3) +
2303bace359SJammy Zhou 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
2313bace359SJammy Zhou 			if (le16_to_cpu(extended_header->usSize) >=
2323bace359SJammy Zhou 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)
2333bace359SJammy Zhou 				samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);
2343bace359SJammy Zhou 		}
2353bace359SJammy Zhou 	}
2363bace359SJammy Zhou 
2373bace359SJammy Zhou 	return samu_table_offset;
2383bace359SJammy Zhou }
2393bace359SJammy Zhou 
get_samu_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)2403bace359SJammy Zhou static uint16_t get_samu_clock_voltage_limit_table_offset(
2413bace359SJammy Zhou 			struct pp_hwmgr *hwmgr,
2423bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
2433bace359SJammy Zhou {
2443bace359SJammy Zhou 	uint16_t table_offset = get_samu_table_offset(hwmgr,
2453bace359SJammy Zhou 					    powerplay_table);
2463bace359SJammy Zhou 
2473bace359SJammy Zhou 	if (table_offset > 0)
2483bace359SJammy Zhou 		return table_offset + 1;
2493bace359SJammy Zhou 
2503bace359SJammy Zhou 	return 0;
2513bace359SJammy Zhou }
2523bace359SJammy Zhou 
get_acp_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)2533bace359SJammy Zhou static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,
2543bace359SJammy Zhou 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
2553bace359SJammy Zhou {
2563bace359SJammy Zhou 	uint16_t acp_table_offset = 0;
2573bace359SJammy Zhou 
2583bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
2593bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
2603bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
2613bace359SJammy Zhou 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
2623bace359SJammy Zhou 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
2633bace359SJammy Zhou 			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
2643bace359SJammy Zhou 				(const ATOM_PPLIB_EXTENDEDHEADER *)
2653bace359SJammy Zhou 				(((unsigned long)powerplay_table3) +
2663bace359SJammy Zhou 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
2673bace359SJammy Zhou 			if (le16_to_cpu(pExtendedHeader->usSize) >=
2683bace359SJammy Zhou 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)
2693bace359SJammy Zhou 				acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);
2703bace359SJammy Zhou 		}
2713bace359SJammy Zhou 	}
2723bace359SJammy Zhou 
2733bace359SJammy Zhou 	return acp_table_offset;
2743bace359SJammy Zhou }
2753bace359SJammy Zhou 
get_acp_clock_voltage_limit_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)2763bace359SJammy Zhou static uint16_t get_acp_clock_voltage_limit_table_offset(
2773bace359SJammy Zhou 				struct pp_hwmgr *hwmgr,
2783bace359SJammy Zhou 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
2793bace359SJammy Zhou {
2803bace359SJammy Zhou 	uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);
2813bace359SJammy Zhou 
2823bace359SJammy Zhou 	if (tableOffset > 0)
2833bace359SJammy Zhou 		return tableOffset + 1;
2843bace359SJammy Zhou 
2853bace359SJammy Zhou 	return 0;
2863bace359SJammy Zhou }
2873bace359SJammy Zhou 
get_cacp_tdp_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)2883bace359SJammy Zhou static uint16_t get_cacp_tdp_table_offset(
2893bace359SJammy Zhou 				struct pp_hwmgr *hwmgr,
2903bace359SJammy Zhou 				const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
2913bace359SJammy Zhou {
2923bace359SJammy Zhou 	uint16_t cacTdpTableOffset = 0;
2933bace359SJammy Zhou 
2943bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
2953bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
2963bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
2973bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
2983bace359SJammy Zhou 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
2993bace359SJammy Zhou 			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
3003bace359SJammy Zhou 					(const ATOM_PPLIB_EXTENDEDHEADER *)
3013bace359SJammy Zhou 					(((unsigned long)powerplay_table3) +
3023bace359SJammy Zhou 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
3033bace359SJammy Zhou 			if (le16_to_cpu(pExtendedHeader->usSize) >=
3043bace359SJammy Zhou 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)
3053bace359SJammy Zhou 				cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);
3063bace359SJammy Zhou 		}
3073bace359SJammy Zhou 	}
3083bace359SJammy Zhou 
3093bace359SJammy Zhou 	return cacTdpTableOffset;
3103bace359SJammy Zhou }
3113bace359SJammy Zhou 
get_cac_tdp_table(struct pp_hwmgr * hwmgr,struct phm_cac_tdp_table ** ptable,const ATOM_PowerTune_Table * table,uint16_t us_maximum_power_delivery_limit)3123bace359SJammy Zhou static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,
3133bace359SJammy Zhou 				struct phm_cac_tdp_table **ptable,
3143bace359SJammy Zhou 				const ATOM_PowerTune_Table *table,
3153bace359SJammy Zhou 				uint16_t us_maximum_power_delivery_limit)
3163bace359SJammy Zhou {
3173bace359SJammy Zhou 	unsigned long table_size;
3183bace359SJammy Zhou 	struct phm_cac_tdp_table *tdp_table;
3193bace359SJammy Zhou 
3203bace359SJammy Zhou 	table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);
3213bace359SJammy Zhou 
3223bace359SJammy Zhou 	tdp_table = kzalloc(table_size, GFP_KERNEL);
3233bace359SJammy Zhou 	if (NULL == tdp_table)
3243bace359SJammy Zhou 		return -ENOMEM;
3253bace359SJammy Zhou 
3263bace359SJammy Zhou 	tdp_table->usTDP = le16_to_cpu(table->usTDP);
3273bace359SJammy Zhou 	tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);
3283bace359SJammy Zhou 	tdp_table->usTDC = le16_to_cpu(table->usTDC);
3293bace359SJammy Zhou 	tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);
3303bace359SJammy Zhou 	tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);
3313bace359SJammy Zhou 	tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);
3323bace359SJammy Zhou 	tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);
3333bace359SJammy Zhou 	tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;
3343bace359SJammy Zhou 
3353bace359SJammy Zhou 	*ptable = tdp_table;
3363bace359SJammy Zhou 
3373bace359SJammy Zhou 	return 0;
3383bace359SJammy Zhou }
3393bace359SJammy Zhou 
get_sclk_vdd_gfx_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)3403bace359SJammy Zhou static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,
3413bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
3423bace359SJammy Zhou {
3433bace359SJammy Zhou 	uint16_t sclk_vdd_gfx_table_offset = 0;
3443bace359SJammy Zhou 
3453bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
3463bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
3473bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
3483bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
3493bace359SJammy Zhou 		if (powerplay_table3->usExtendendedHeaderOffset > 0) {
3503bace359SJammy Zhou 			const ATOM_PPLIB_EXTENDEDHEADER  *pExtendedHeader =
3513bace359SJammy Zhou 				(const ATOM_PPLIB_EXTENDEDHEADER *)
3523bace359SJammy Zhou 				(((unsigned long)powerplay_table3) +
3533bace359SJammy Zhou 				le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
3543bace359SJammy Zhou 			if (le16_to_cpu(pExtendedHeader->usSize) >=
3553bace359SJammy Zhou 			    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)
3563bace359SJammy Zhou 				sclk_vdd_gfx_table_offset =
3573bace359SJammy Zhou 					le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);
3583bace359SJammy Zhou 		}
3593bace359SJammy Zhou 	}
3603bace359SJammy Zhou 
3613bace359SJammy Zhou 	return sclk_vdd_gfx_table_offset;
3623bace359SJammy Zhou }
3633bace359SJammy Zhou 
get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)3643bace359SJammy Zhou static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
3653bace359SJammy Zhou 			struct pp_hwmgr *hwmgr,
3663bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
3673bace359SJammy Zhou {
3683bace359SJammy Zhou 	uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);
3693bace359SJammy Zhou 
3703bace359SJammy Zhou 	if (tableOffset > 0)
3713bace359SJammy Zhou 		return tableOffset;
3723bace359SJammy Zhou 
3733bace359SJammy Zhou 	return 0;
3743bace359SJammy Zhou }
3753bace359SJammy Zhou 
3763bace359SJammy Zhou 
get_clock_voltage_dependency_table(struct pp_hwmgr * hwmgr,struct phm_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_Clock_Voltage_Dependency_Table * table)3773bace359SJammy Zhou static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
3783bace359SJammy Zhou 		struct phm_clock_voltage_dependency_table **ptable,
3793bace359SJammy Zhou 		const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)
3803bace359SJammy Zhou {
3813bace359SJammy Zhou 
38223bdba95SGustavo A. R. Silva 	unsigned long i;
3833bace359SJammy Zhou 	struct phm_clock_voltage_dependency_table *dep_table;
3843bace359SJammy Zhou 
38523bdba95SGustavo A. R. Silva 	dep_table = kzalloc(struct_size(dep_table, entries, table->ucNumEntries),
38623bdba95SGustavo A. R. Silva 			    GFP_KERNEL);
3873bace359SJammy Zhou 	if (NULL == dep_table)
3883bace359SJammy Zhou 		return -ENOMEM;
3893bace359SJammy Zhou 
3903bace359SJammy Zhou 	dep_table->count = (unsigned long)table->ucNumEntries;
3913bace359SJammy Zhou 
3923bace359SJammy Zhou 	for (i = 0; i < dep_table->count; i++) {
3933bace359SJammy Zhou 		dep_table->entries[i].clk =
3943bace359SJammy Zhou 			((unsigned long)table->entries[i].ucClockHigh << 16) |
3953bace359SJammy Zhou 			le16_to_cpu(table->entries[i].usClockLow);
3963bace359SJammy Zhou 		dep_table->entries[i].v =
3973bace359SJammy Zhou 			(unsigned long)le16_to_cpu(table->entries[i].usVoltage);
3983bace359SJammy Zhou 	}
3993bace359SJammy Zhou 
4003bace359SJammy Zhou 	*ptable = dep_table;
4013bace359SJammy Zhou 
4023bace359SJammy Zhou 	return 0;
4033bace359SJammy Zhou }
4043bace359SJammy Zhou 
get_valid_clk(struct pp_hwmgr * hwmgr,struct phm_clock_array ** ptable,const struct phm_clock_voltage_dependency_table * table)4053bace359SJammy Zhou static int get_valid_clk(struct pp_hwmgr *hwmgr,
4063bace359SJammy Zhou 			struct phm_clock_array **ptable,
4073bace359SJammy Zhou 			const struct phm_clock_voltage_dependency_table *table)
4083bace359SJammy Zhou {
409e0af7d11SGustavo A. R. Silva 	unsigned long i;
4103bace359SJammy Zhou 	struct phm_clock_array *clock_table;
4113bace359SJammy Zhou 
412e0af7d11SGustavo A. R. Silva 	clock_table = kzalloc(struct_size(clock_table, values, table->count), GFP_KERNEL);
413e0af7d11SGustavo A. R. Silva 	if (!clock_table)
4143bace359SJammy Zhou 		return -ENOMEM;
4153bace359SJammy Zhou 
4163bace359SJammy Zhou 	clock_table->count = (unsigned long)table->count;
4173bace359SJammy Zhou 
4183bace359SJammy Zhou 	for (i = 0; i < clock_table->count; i++)
4193bace359SJammy Zhou 		clock_table->values[i] = (unsigned long)table->entries[i].clk;
4203bace359SJammy Zhou 
4213bace359SJammy Zhou 	*ptable = clock_table;
4223bace359SJammy Zhou 
4233bace359SJammy Zhou 	return 0;
4243bace359SJammy Zhou }
4253bace359SJammy Zhou 
get_clock_voltage_limit(struct pp_hwmgr * hwmgr,struct phm_clock_and_voltage_limits * limits,const ATOM_PPLIB_Clock_Voltage_Limit_Table * table)4263bace359SJammy Zhou static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
4273bace359SJammy Zhou 			struct phm_clock_and_voltage_limits *limits,
4283bace359SJammy Zhou 			const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
4293bace359SJammy Zhou {
4303bace359SJammy Zhou 	limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
4313bace359SJammy Zhou 			le16_to_cpu(table->entries[0].usSclkLow);
4323bace359SJammy Zhou 	limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
4333bace359SJammy Zhou 			le16_to_cpu(table->entries[0].usMclkLow);
4343bace359SJammy Zhou 	limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
4353bace359SJammy Zhou 	limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
4363bace359SJammy Zhou 
4373bace359SJammy Zhou 	return 0;
4383bace359SJammy Zhou }
4393bace359SJammy Zhou 
4403bace359SJammy Zhou 
set_hw_cap(struct pp_hwmgr * hwmgr,bool enable,enum phm_platform_caps cap)4413bace359SJammy Zhou static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
4423bace359SJammy Zhou 		       enum phm_platform_caps cap)
4433bace359SJammy Zhou {
4443bace359SJammy Zhou 	if (enable)
4453bace359SJammy Zhou 		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
4463bace359SJammy Zhou 	else
4473bace359SJammy Zhou 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
4483bace359SJammy Zhou }
4493bace359SJammy Zhou 
set_platform_caps(struct pp_hwmgr * hwmgr,unsigned long powerplay_caps)4503bace359SJammy Zhou static int set_platform_caps(struct pp_hwmgr *hwmgr,
4513bace359SJammy Zhou 			unsigned long powerplay_caps)
4523bace359SJammy Zhou {
4533bace359SJammy Zhou 	set_hw_cap(
4543bace359SJammy Zhou 		hwmgr,
4553bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
4563bace359SJammy Zhou 		PHM_PlatformCaps_PowerPlaySupport
4573bace359SJammy Zhou 	);
4583bace359SJammy Zhou 
4593bace359SJammy Zhou 	set_hw_cap(
4603bace359SJammy Zhou 		hwmgr,
4613bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
4623bace359SJammy Zhou 		PHM_PlatformCaps_BiosPowerSourceControl
4633bace359SJammy Zhou 	);
4643bace359SJammy Zhou 
4653bace359SJammy Zhou 	set_hw_cap(
4663bace359SJammy Zhou 		hwmgr,
4673bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
4683bace359SJammy Zhou 		PHM_PlatformCaps_EnableASPML0s
4693bace359SJammy Zhou 	);
4703bace359SJammy Zhou 
4713bace359SJammy Zhou 	set_hw_cap(
4723bace359SJammy Zhou 		hwmgr,
4733bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
4743bace359SJammy Zhou 		PHM_PlatformCaps_EnableASPML1
4753bace359SJammy Zhou 	);
4763bace359SJammy Zhou 
4773bace359SJammy Zhou 	set_hw_cap(
4783bace359SJammy Zhou 		hwmgr,
4793bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
4803bace359SJammy Zhou 		PHM_PlatformCaps_EnableBackbias
4813bace359SJammy Zhou 	);
4823bace359SJammy Zhou 
4833bace359SJammy Zhou 	set_hw_cap(
4843bace359SJammy Zhou 		hwmgr,
4853bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
4863bace359SJammy Zhou 		PHM_PlatformCaps_AutomaticDCTransition
4873bace359SJammy Zhou 	);
4883bace359SJammy Zhou 
4893bace359SJammy Zhou 	set_hw_cap(
4903bace359SJammy Zhou 		hwmgr,
4913bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
4923bace359SJammy Zhou 		PHM_PlatformCaps_GeminiPrimary
4933bace359SJammy Zhou 	);
4943bace359SJammy Zhou 
4953bace359SJammy Zhou 	set_hw_cap(
4963bace359SJammy Zhou 		hwmgr,
4973bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
4983bace359SJammy Zhou 		PHM_PlatformCaps_StepVddc
4993bace359SJammy Zhou 	);
5003bace359SJammy Zhou 
5013bace359SJammy Zhou 	set_hw_cap(
5023bace359SJammy Zhou 		hwmgr,
5033bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
5043bace359SJammy Zhou 		PHM_PlatformCaps_EnableVoltageControl
5053bace359SJammy Zhou 	);
5063bace359SJammy Zhou 
5073bace359SJammy Zhou 	set_hw_cap(
5083bace359SJammy Zhou 		hwmgr,
5093bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
5103bace359SJammy Zhou 		PHM_PlatformCaps_EnableSideportControl
5113bace359SJammy Zhou 	);
5123bace359SJammy Zhou 
5133bace359SJammy Zhou 	set_hw_cap(
5143bace359SJammy Zhou 		hwmgr,
5153bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
5163bace359SJammy Zhou 		PHM_PlatformCaps_TurnOffPll_ASPML1
5173bace359SJammy Zhou 	);
5183bace359SJammy Zhou 
5193bace359SJammy Zhou 	set_hw_cap(
5203bace359SJammy Zhou 		hwmgr,
5213bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
5223bace359SJammy Zhou 		PHM_PlatformCaps_EnableHTLinkControl
5233bace359SJammy Zhou 	);
5243bace359SJammy Zhou 
5253bace359SJammy Zhou 	set_hw_cap(
5263bace359SJammy Zhou 		hwmgr,
5273bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
5283bace359SJammy Zhou 		PHM_PlatformCaps_EnableMVDDControl
5293bace359SJammy Zhou 	);
5303bace359SJammy Zhou 
5313bace359SJammy Zhou 	set_hw_cap(
5323bace359SJammy Zhou 		hwmgr,
5333bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
5343bace359SJammy Zhou 		PHM_PlatformCaps_ControlVDDCI
5353bace359SJammy Zhou 	);
5363bace359SJammy Zhou 
5373bace359SJammy Zhou 	set_hw_cap(
5383bace359SJammy Zhou 		hwmgr,
5393bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
5403bace359SJammy Zhou 		PHM_PlatformCaps_RegulatorHot
5413bace359SJammy Zhou 	);
5423bace359SJammy Zhou 
5433bace359SJammy Zhou 	set_hw_cap(
5443bace359SJammy Zhou 		hwmgr,
5453bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
5463bace359SJammy Zhou 		PHM_PlatformCaps_BootStateOnAlert
5473bace359SJammy Zhou 	);
5483bace359SJammy Zhou 
5493bace359SJammy Zhou 	set_hw_cap(
5503bace359SJammy Zhou 		hwmgr,
5513bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
5523bace359SJammy Zhou 		PHM_PlatformCaps_DontWaitForVBlankOnAlert
5533bace359SJammy Zhou 	);
5543bace359SJammy Zhou 
5553bace359SJammy Zhou 	set_hw_cap(
5563bace359SJammy Zhou 		hwmgr,
5573bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
5583bace359SJammy Zhou 		PHM_PlatformCaps_BACO
5593bace359SJammy Zhou 	);
5603bace359SJammy Zhou 
5613bace359SJammy Zhou 	set_hw_cap(
5623bace359SJammy Zhou 		hwmgr,
5633bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
5643bace359SJammy Zhou 		PHM_PlatformCaps_NewCACVoltage
5653bace359SJammy Zhou 	);
5663bace359SJammy Zhou 
5673bace359SJammy Zhou 	set_hw_cap(
5683bace359SJammy Zhou 		hwmgr,
5693bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
5703bace359SJammy Zhou 		PHM_PlatformCaps_RevertGPIO5Polarity
5713bace359SJammy Zhou 	);
5723bace359SJammy Zhou 
5733bace359SJammy Zhou 	set_hw_cap(
5743bace359SJammy Zhou 		hwmgr,
5753bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
5763bace359SJammy Zhou 		PHM_PlatformCaps_Thermal2GPIO17
5773bace359SJammy Zhou 	);
5783bace359SJammy Zhou 
5793bace359SJammy Zhou 	set_hw_cap(
5803bace359SJammy Zhou 		hwmgr,
5813bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
5823bace359SJammy Zhou 		PHM_PlatformCaps_VRHotGPIOConfigurable
5833bace359SJammy Zhou 	);
5843bace359SJammy Zhou 
5853bace359SJammy Zhou 	set_hw_cap(
5863bace359SJammy Zhou 		hwmgr,
5873bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
5883bace359SJammy Zhou 		PHM_PlatformCaps_TempInversion
5893bace359SJammy Zhou 	);
5903bace359SJammy Zhou 
5913bace359SJammy Zhou 	set_hw_cap(
5923bace359SJammy Zhou 		hwmgr,
5933bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
5943bace359SJammy Zhou 		PHM_PlatformCaps_EVV
5953bace359SJammy Zhou 	);
5963bace359SJammy Zhou 
5973bace359SJammy Zhou 	set_hw_cap(
5983bace359SJammy Zhou 		hwmgr,
5993bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
6003bace359SJammy Zhou 		PHM_PlatformCaps_CombinePCCWithThermalSignal
6013bace359SJammy Zhou 	);
6023bace359SJammy Zhou 
6033bace359SJammy Zhou 	set_hw_cap(
6043bace359SJammy Zhou 		hwmgr,
6053bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
6063bace359SJammy Zhou 		PHM_PlatformCaps_LoadPostProductionFirmware
6073bace359SJammy Zhou 	);
6083bace359SJammy Zhou 
6093bace359SJammy Zhou 	set_hw_cap(
6103bace359SJammy Zhou 		hwmgr,
6113bace359SJammy Zhou 		0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
6123bace359SJammy Zhou 		PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
6133bace359SJammy Zhou 	);
6143bace359SJammy Zhou 
6153bace359SJammy Zhou 	return 0;
6163bace359SJammy Zhou }
6173bace359SJammy Zhou 
make_classification_flags(struct pp_hwmgr * hwmgr,USHORT classification,USHORT classification2)6183bace359SJammy Zhou static PP_StateClassificationFlags make_classification_flags(
6193bace359SJammy Zhou 						   struct pp_hwmgr *hwmgr,
6203bace359SJammy Zhou 						    USHORT classification,
6213bace359SJammy Zhou 						   USHORT classification2)
6223bace359SJammy Zhou {
6233bace359SJammy Zhou 	PP_StateClassificationFlags result = 0;
6243bace359SJammy Zhou 
6253bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
6263bace359SJammy Zhou 		result |= PP_StateClassificationFlag_Boot;
6273bace359SJammy Zhou 
6283bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
6293bace359SJammy Zhou 		result |= PP_StateClassificationFlag_Thermal;
6303bace359SJammy Zhou 
6313bace359SJammy Zhou 	if (classification &
6323bace359SJammy Zhou 			ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
6333bace359SJammy Zhou 		result |= PP_StateClassificationFlag_LimitedPowerSource;
6343bace359SJammy Zhou 
6353bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
6363bace359SJammy Zhou 		result |= PP_StateClassificationFlag_Rest;
6373bace359SJammy Zhou 
6383bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
6393bace359SJammy Zhou 		result |= PP_StateClassificationFlag_Forced;
6403bace359SJammy Zhou 
6413bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
6423bace359SJammy Zhou 		result |= PP_StateClassificationFlag_3DPerformance;
6433bace359SJammy Zhou 
6443bace359SJammy Zhou 
6453bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
6463bace359SJammy Zhou 		result |= PP_StateClassificationFlag_ACOverdriveTemplate;
6473bace359SJammy Zhou 
6483bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
6493bace359SJammy Zhou 		result |= PP_StateClassificationFlag_Uvd;
6503bace359SJammy Zhou 
6513bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
6523bace359SJammy Zhou 		result |= PP_StateClassificationFlag_UvdHD;
6533bace359SJammy Zhou 
6543bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
6553bace359SJammy Zhou 		result |= PP_StateClassificationFlag_UvdSD;
6563bace359SJammy Zhou 
6573bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
6583bace359SJammy Zhou 		result |= PP_StateClassificationFlag_HD2;
6593bace359SJammy Zhou 
6603bace359SJammy Zhou 	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
6613bace359SJammy Zhou 		result |= PP_StateClassificationFlag_ACPI;
6623bace359SJammy Zhou 
6633bace359SJammy Zhou 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
6643bace359SJammy Zhou 		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
6653bace359SJammy Zhou 
6663bace359SJammy Zhou 
6673bace359SJammy Zhou 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
6683bace359SJammy Zhou 		result |= PP_StateClassificationFlag_ULV;
6693bace359SJammy Zhou 
6703bace359SJammy Zhou 	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
6713bace359SJammy Zhou 		result |= PP_StateClassificationFlag_UvdMVC;
6723bace359SJammy Zhou 
6733bace359SJammy Zhou 	return result;
6743bace359SJammy Zhou }
6753bace359SJammy Zhou 
init_non_clock_fields(struct pp_hwmgr * hwmgr,struct pp_power_state * ps,uint8_t version,const ATOM_PPLIB_NONCLOCK_INFO * pnon_clock_info)6763bace359SJammy Zhou static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
6773bace359SJammy Zhou 						struct pp_power_state *ps,
6783bace359SJammy Zhou 							    uint8_t version,
6793bace359SJammy Zhou 			 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
6803bace359SJammy Zhou 	unsigned long rrr_index;
6813bace359SJammy Zhou 	unsigned long tmp;
6823bace359SJammy Zhou 
6833bace359SJammy Zhou 	ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
6843bace359SJammy Zhou 					ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
6853bace359SJammy Zhou 	ps->classification.flags = make_classification_flags(hwmgr,
6863bace359SJammy Zhou 				le16_to_cpu(pnon_clock_info->usClassification),
6873bace359SJammy Zhou 				le16_to_cpu(pnon_clock_info->usClassification2));
6883bace359SJammy Zhou 
6893bace359SJammy Zhou 	ps->classification.temporary_state = false;
6903bace359SJammy Zhou 	ps->classification.to_be_deleted = false;
6913bace359SJammy Zhou 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
6923bace359SJammy Zhou 		ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
6933bace359SJammy Zhou 
6943bace359SJammy Zhou 	ps->validation.singleDisplayOnly = (0 != tmp);
6953bace359SJammy Zhou 
6963bace359SJammy Zhou 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
6973bace359SJammy Zhou 		ATOM_PPLIB_DISALLOW_ON_DC;
6983bace359SJammy Zhou 
6993bace359SJammy Zhou 	ps->validation.disallowOnDC = (0 != tmp);
7003bace359SJammy Zhou 
7013bace359SJammy Zhou 	ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7023bace359SJammy Zhou 				ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
7033bace359SJammy Zhou 				ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
7043bace359SJammy Zhou 
7053bace359SJammy Zhou 	ps->display.disableFrameModulation = false;
7063bace359SJammy Zhou 
7073bace359SJammy Zhou 	rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7083bace359SJammy Zhou 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
7093bace359SJammy Zhou 			ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
7103bace359SJammy Zhou 
7113bace359SJammy Zhou 	if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
7123bace359SJammy Zhou 		static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
7133bace359SJammy Zhou 								{ 0, 50, 0 };
7143bace359SJammy Zhou 
7153bace359SJammy Zhou 		ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
7163bace359SJammy Zhou 		ps->display.explicitRefreshrate = look_up[rrr_index];
7173bace359SJammy Zhou 		ps->display.limitRefreshrate = true;
7183bace359SJammy Zhou 
7193bace359SJammy Zhou 		if (ps->display.explicitRefreshrate == 0)
7203bace359SJammy Zhou 			ps->display.limitRefreshrate = false;
7213bace359SJammy Zhou 	} else
7223bace359SJammy Zhou 		ps->display.limitRefreshrate = false;
7233bace359SJammy Zhou 
7243bace359SJammy Zhou 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7253bace359SJammy Zhou 		ATOM_PPLIB_ENABLE_VARIBRIGHT;
7263bace359SJammy Zhou 
7273bace359SJammy Zhou 	ps->display.enableVariBright = (0 != tmp);
7283bace359SJammy Zhou 
7293bace359SJammy Zhou 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7303bace359SJammy Zhou 		ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
7313bace359SJammy Zhou 
7323bace359SJammy Zhou 	ps->memory.dllOff = (0 != tmp);
7333bace359SJammy Zhou 
7347c9574f2SDan Carpenter 	ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7353bace359SJammy Zhou 			    ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
7363bace359SJammy Zhou 
7373bace359SJammy Zhou 	ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
7383bace359SJammy Zhou 				     pnon_clock_info->ucMinTemperature;
7393bace359SJammy Zhou 
7403bace359SJammy Zhou 	ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
7413bace359SJammy Zhou 				     pnon_clock_info->ucMaxTemperature;
7423bace359SJammy Zhou 
7433bace359SJammy Zhou 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7443bace359SJammy Zhou 		ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
7453bace359SJammy Zhou 
7463bace359SJammy Zhou 	ps->software.disableLoadBalancing = tmp;
7473bace359SJammy Zhou 
7483bace359SJammy Zhou 	tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
7493bace359SJammy Zhou 		ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
7503bace359SJammy Zhou 
7513bace359SJammy Zhou 	ps->software.enableSleepForTimestamps = (0 != tmp);
7523bace359SJammy Zhou 
7533bace359SJammy Zhou 	ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
7543bace359SJammy Zhou 
7553bace359SJammy Zhou 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
75654f16ebfSAlex Deucher 		ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
75754f16ebfSAlex Deucher 		ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
7583bace359SJammy Zhou 	} else {
7593bace359SJammy Zhou 		ps->uvd_clocks.VCLK = 0;
7603bace359SJammy Zhou 		ps->uvd_clocks.DCLK = 0;
7613bace359SJammy Zhou 	}
7623bace359SJammy Zhou 
7633bace359SJammy Zhou 	return 0;
7643bace359SJammy Zhou }
7653bace359SJammy Zhou 
size_of_entry_v2(ULONG num_dpm_levels)7663bace359SJammy Zhou static ULONG size_of_entry_v2(ULONG num_dpm_levels)
7673bace359SJammy Zhou {
7683bace359SJammy Zhou 	return (sizeof(UCHAR) + sizeof(UCHAR) +
7693bace359SJammy Zhou 			(num_dpm_levels * sizeof(UCHAR)));
7703bace359SJammy Zhou }
7713bace359SJammy Zhou 
get_state_entry_v2(const StateArray * pstate_arrays,ULONG entry_index)7723bace359SJammy Zhou static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
7733bace359SJammy Zhou 					const StateArray * pstate_arrays,
7743bace359SJammy Zhou 							 ULONG entry_index)
7753bace359SJammy Zhou {
7763bace359SJammy Zhou 	ULONG i;
7773bace359SJammy Zhou 	const ATOM_PPLIB_STATE_V2 *pstate;
7783bace359SJammy Zhou 
7793bace359SJammy Zhou 	pstate = pstate_arrays->states;
7803bace359SJammy Zhou 	if (entry_index <= pstate_arrays->ucNumEntries) {
7813bace359SJammy Zhou 		for (i = 0; i < entry_index; i++)
7823bace359SJammy Zhou 			pstate = (ATOM_PPLIB_STATE_V2 *)(
7833bace359SJammy Zhou 						  (unsigned long)pstate +
7843bace359SJammy Zhou 			     size_of_entry_v2(pstate->ucNumDPMLevels));
7853bace359SJammy Zhou 	}
7863bace359SJammy Zhou 	return pstate;
7873bace359SJammy Zhou }
7883bace359SJammy Zhou 
7896cdb91e2SDave Airlie static const unsigned char soft_dummy_pp_table[] = {
7903b4ca9e6SRex Zhu 	0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
7913b4ca9e6SRex Zhu 	0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
7923b4ca9e6SRex Zhu 	0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
7933b4ca9e6SRex Zhu 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7943b4ca9e6SRex Zhu 	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
7953b4ca9e6SRex Zhu 	0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
7963b4ca9e6SRex Zhu 	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
7973b4ca9e6SRex Zhu 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7983b4ca9e6SRex Zhu 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7993b4ca9e6SRex Zhu 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
8003b4ca9e6SRex Zhu 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
8013b4ca9e6SRex Zhu 	0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
8023b4ca9e6SRex Zhu 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
8033b4ca9e6SRex Zhu 	0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
8043b4ca9e6SRex Zhu 	0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
8053b4ca9e6SRex Zhu 	0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
8063b4ca9e6SRex Zhu 	0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
8073b4ca9e6SRex Zhu 	0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
8083b4ca9e6SRex Zhu 	0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
8093b4ca9e6SRex Zhu 	0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
8103b4ca9e6SRex Zhu 	0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
8113b4ca9e6SRex Zhu 	0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
8123b4ca9e6SRex Zhu 	0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
8133b4ca9e6SRex Zhu 	0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
8143b4ca9e6SRex Zhu 	0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
8153b4ca9e6SRex Zhu 	0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
8163b4ca9e6SRex Zhu 	0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
8173b4ca9e6SRex Zhu 	0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
8183b4ca9e6SRex Zhu 	0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
8193b4ca9e6SRex Zhu 	0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
8203b4ca9e6SRex Zhu 	0x00
8213b4ca9e6SRex Zhu };
8223bace359SJammy Zhou 
get_powerplay_table(struct pp_hwmgr * hwmgr)8233bace359SJammy Zhou static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
8243bace359SJammy Zhou 				     struct pp_hwmgr *hwmgr)
8253bace359SJammy Zhou {
826cf17039fSEric Huang 	const void *table_addr = hwmgr->soft_pp_table;
8273bace359SJammy Zhou 	uint8_t frev, crev;
8283bace359SJammy Zhou 	uint16_t size;
8293bace359SJammy Zhou 
830cf17039fSEric Huang 	if (!table_addr) {
831741deadeSAlex Deucher 		if (hwmgr->chip_id == CHIP_RAVEN) {
8323b4ca9e6SRex Zhu 			table_addr = &soft_dummy_pp_table[0];
8333b4ca9e6SRex Zhu 			hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
8343b4ca9e6SRex Zhu 			hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
8353b4ca9e6SRex Zhu 		} else {
836b3892e2bSRex Zhu 			table_addr = smu_atom_get_data_table(hwmgr->adev,
8373bace359SJammy Zhou 					GetIndexIntoMasterTable(DATA, PowerPlayInfo),
8383bace359SJammy Zhou 					&size, &frev, &crev);
8393bace359SJammy Zhou 			hwmgr->soft_pp_table = table_addr;
840cf17039fSEric Huang 			hwmgr->soft_pp_table_size = size;
841cf17039fSEric Huang 		}
8423b4ca9e6SRex Zhu 	}
8433bace359SJammy Zhou 
8443bace359SJammy Zhou 	return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
8453bace359SJammy Zhou }
8463bace359SJammy Zhou 
pp_tables_get_response_times(struct pp_hwmgr * hwmgr,uint32_t * vol_rep_time,uint32_t * bb_rep_time)847f476852aSHuang Rui int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
848f476852aSHuang Rui 				uint32_t *vol_rep_time, uint32_t *bb_rep_time)
849f476852aSHuang Rui {
850f476852aSHuang Rui 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
851f476852aSHuang Rui 
852f476852aSHuang Rui 	PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
853f476852aSHuang Rui 			    "Missing PowerPlay Table!", return -EINVAL);
854f476852aSHuang Rui 
855f476852aSHuang Rui 	*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
856f476852aSHuang Rui 	*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
857f476852aSHuang Rui 
858f476852aSHuang Rui 	return 0;
859f476852aSHuang Rui }
8603bace359SJammy Zhou 
pp_tables_get_num_of_entries(struct pp_hwmgr * hwmgr,unsigned long * num_of_entries)8613bace359SJammy Zhou int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
8623bace359SJammy Zhou 				     unsigned long *num_of_entries)
8633bace359SJammy Zhou {
8643bace359SJammy Zhou 	const StateArray *pstate_arrays;
8653bace359SJammy Zhou 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
8663bace359SJammy Zhou 
8673bace359SJammy Zhou 	if (powerplay_table == NULL)
8683bace359SJammy Zhou 		return -1;
8693bace359SJammy Zhou 
8703bace359SJammy Zhou 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
8713bace359SJammy Zhou 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
8723bace359SJammy Zhou 					le16_to_cpu(powerplay_table->usStateArrayOffset));
8733bace359SJammy Zhou 
8743bace359SJammy Zhou 		*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
8753bace359SJammy Zhou 	} else
8763bace359SJammy Zhou 		*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
8773bace359SJammy Zhou 
8783bace359SJammy Zhou 	return 0;
8793bace359SJammy Zhou }
8803bace359SJammy Zhou 
pp_tables_get_entry(struct pp_hwmgr * hwmgr,unsigned long entry_index,struct pp_power_state * ps,pp_tables_hw_clock_info_callback func)8813bace359SJammy Zhou int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
8823bace359SJammy Zhou 				unsigned long entry_index,
8833bace359SJammy Zhou 				struct pp_power_state *ps,
8843bace359SJammy Zhou 			 pp_tables_hw_clock_info_callback func)
8853bace359SJammy Zhou {
8863bace359SJammy Zhou 	int i;
8873bace359SJammy Zhou 	const StateArray *pstate_arrays;
8883bace359SJammy Zhou 	const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
8893bace359SJammy Zhou 	const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
8903bace359SJammy Zhou 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
8913bace359SJammy Zhou 	int result = 0;
8923bace359SJammy Zhou 	int res = 0;
8933bace359SJammy Zhou 
8943bace359SJammy Zhou 	const ClockInfoArray *pclock_arrays;
8953bace359SJammy Zhou 
8963bace359SJammy Zhou 	const NonClockInfoArray *pnon_clock_arrays;
8973bace359SJammy Zhou 
8983bace359SJammy Zhou 	const ATOM_PPLIB_STATE *pstate_entry;
8993bace359SJammy Zhou 
9003bace359SJammy Zhou 	if (powerplay_table == NULL)
9013bace359SJammy Zhou 		return -1;
9023bace359SJammy Zhou 
9033bace359SJammy Zhou 	ps->classification.bios_index = entry_index;
9043bace359SJammy Zhou 
9053bace359SJammy Zhou 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
9063bace359SJammy Zhou 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
9073bace359SJammy Zhou 					le16_to_cpu(powerplay_table->usStateArrayOffset));
9083bace359SJammy Zhou 
9093bace359SJammy Zhou 		if (entry_index > pstate_arrays->ucNumEntries)
9103bace359SJammy Zhou 			return -1;
9113bace359SJammy Zhou 
9123bace359SJammy Zhou 		pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
9133bace359SJammy Zhou 		pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
9143bace359SJammy Zhou 					le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
9153bace359SJammy Zhou 
9163bace359SJammy Zhou 		pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
9173bace359SJammy Zhou 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
9183bace359SJammy Zhou 
9193bace359SJammy Zhou 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
9203bace359SJammy Zhou 					(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
9213bace359SJammy Zhou 
9223bace359SJammy Zhou 		result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
9233bace359SJammy Zhou 
9243bace359SJammy Zhou 		for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
9253bace359SJammy Zhou 			const void *pclock_info = (const void *)(
9263bace359SJammy Zhou 							(unsigned long)(pclock_arrays->clockInfo) +
9273bace359SJammy Zhou 							(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
9283bace359SJammy Zhou 			res = func(hwmgr, &ps->hardware, i, pclock_info);
9293bace359SJammy Zhou 			if ((0 == result) && (0 != res))
9303bace359SJammy Zhou 				result = res;
9313bace359SJammy Zhou 		}
9323bace359SJammy Zhou 	} else {
9333bace359SJammy Zhou 		if (entry_index > powerplay_table->ucNumStates)
9343bace359SJammy Zhou 			return -1;
9353bace359SJammy Zhou 
93654f16ebfSAlex Deucher 		pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
93754f16ebfSAlex Deucher 						    le16_to_cpu(powerplay_table->usStateArrayOffset) +
9383bace359SJammy Zhou 						    entry_index * powerplay_table->ucStateEntrySize);
9393bace359SJammy Zhou 
9403bace359SJammy Zhou 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
9413bace359SJammy Zhou 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
9423bace359SJammy Zhou 						pstate_entry->ucNonClockStateIndex *
9433bace359SJammy Zhou 						powerplay_table->ucNonClockSize);
9443bace359SJammy Zhou 
9453bace359SJammy Zhou 		result = init_non_clock_fields(hwmgr, ps,
9463bace359SJammy Zhou 							powerplay_table->ucNonClockSize,
9473bace359SJammy Zhou 							pnon_clock_info);
9483bace359SJammy Zhou 
9493bace359SJammy Zhou 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
9503bace359SJammy Zhou 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
9513bace359SJammy Zhou 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
9523bace359SJammy Zhou 						pstate_entry->ucClockStateIndices[i] *
9533bace359SJammy Zhou 						powerplay_table->ucClockInfoSize);
9543bace359SJammy Zhou 
9553bace359SJammy Zhou 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
9563bace359SJammy Zhou 
9573bace359SJammy Zhou 			if ((0 == result) && (0 != res))
9583bace359SJammy Zhou 					result = res;
9593bace359SJammy Zhou 		}
9603bace359SJammy Zhou 	}
9613bace359SJammy Zhou 
9623b4ca9e6SRex Zhu 	if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
9633b4ca9e6SRex Zhu 		if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
9643bace359SJammy Zhou 			result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
9653b4ca9e6SRex Zhu 	}
9663bace359SJammy Zhou 
9673bace359SJammy Zhou 	return result;
9683bace359SJammy Zhou }
9693bace359SJammy Zhou 
init_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)9703bace359SJammy Zhou static int init_powerplay_tables(
9713bace359SJammy Zhou 			struct pp_hwmgr *hwmgr,
9723bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
9733bace359SJammy Zhou )
9743bace359SJammy Zhou {
9753bace359SJammy Zhou 	return 0;
9763bace359SJammy Zhou }
9773bace359SJammy Zhou 
9783bace359SJammy Zhou 
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)9793bace359SJammy Zhou static int init_thermal_controller(
9803bace359SJammy Zhou 			struct pp_hwmgr *hwmgr,
9813bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
9823bace359SJammy Zhou {
983b7a1f382SAlex Deucher 	struct amdgpu_device *adev = hwmgr->adev;
984b7a1f382SAlex Deucher 
985bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.ucType =
986bbc25dadSSandeep Raghuraman 			powerplay_table->sThermalController.ucType;
987bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.ucI2cLine =
988bbc25dadSSandeep Raghuraman 			powerplay_table->sThermalController.ucI2cLine;
989bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.ucI2cAddress =
990bbc25dadSSandeep Raghuraman 			powerplay_table->sThermalController.ucI2cAddress;
991bbc25dadSSandeep Raghuraman 
992bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.fanInfo.bNoFan =
993bbc25dadSSandeep Raghuraman 		(0 != (powerplay_table->sThermalController.ucFanParameters &
994bbc25dadSSandeep Raghuraman 			ATOM_PP_FANPARAMETERS_NOFAN));
995bbc25dadSSandeep Raghuraman 
996bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
997bbc25dadSSandeep Raghuraman 		powerplay_table->sThermalController.ucFanParameters &
998bbc25dadSSandeep Raghuraman 		ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
999bbc25dadSSandeep Raghuraman 
1000bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.fanInfo.ulMinRPM
1001bbc25dadSSandeep Raghuraman 		= powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1002bbc25dadSSandeep Raghuraman 	hwmgr->thermal_controller.fanInfo.ulMaxRPM
1003bbc25dadSSandeep Raghuraman 		= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1004bbc25dadSSandeep Raghuraman 
1005bbc25dadSSandeep Raghuraman 	set_hw_cap(hwmgr,
1006bbc25dadSSandeep Raghuraman 		   ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1007bbc25dadSSandeep Raghuraman 		   PHM_PlatformCaps_ThermalController);
1008bbc25dadSSandeep Raghuraman 
1009b7a1f382SAlex Deucher         if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
1010b7a1f382SAlex Deucher 		const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
1011b7a1f382SAlex Deucher 			(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1012b7a1f382SAlex Deucher 
1013b7a1f382SAlex Deucher 		if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {
1014bbc25dadSSandeep Raghuraman 			hwmgr->thermal_controller.use_hw_fan_control = 1;
1015b7a1f382SAlex Deucher 			return 0;
1016b7a1f382SAlex Deucher 		} else {
1017b7a1f382SAlex Deucher 			const ATOM_PPLIB_FANTABLE *fan_table =
1018b7a1f382SAlex Deucher 				(const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) +
1019b7a1f382SAlex Deucher 							      le16_to_cpu(powerplay_table3->usFanTableOffset));
1020b7a1f382SAlex Deucher 
1021b7a1f382SAlex Deucher 			if (1 <= fan_table->ucFanTableFormat) {
1022b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst =
1023b7a1f382SAlex Deucher 					fan_table->ucTHyst;
1024b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usTMin =
1025b7a1f382SAlex Deucher 					le16_to_cpu(fan_table->usTMin);
1026b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usTMed =
1027b7a1f382SAlex Deucher 					le16_to_cpu(fan_table->usTMed);
1028b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usTHigh =
1029b7a1f382SAlex Deucher 					le16_to_cpu(fan_table->usTHigh);
1030b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
1031b7a1f382SAlex Deucher 					le16_to_cpu(fan_table->usPWMMin);
1032b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed =
1033b7a1f382SAlex Deucher 					le16_to_cpu(fan_table->usPWMMed);
1034b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh =
1035b7a1f382SAlex Deucher 					le16_to_cpu(fan_table->usPWMHigh);
1036b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900;
1037b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000;
1038b7a1f382SAlex Deucher 
1039b7a1f382SAlex Deucher 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1040b7a1f382SAlex Deucher 					    PHM_PlatformCaps_MicrocodeFanControl);
1041b7a1f382SAlex Deucher 			}
1042b7a1f382SAlex Deucher 
1043b7a1f382SAlex Deucher 			if (2 <= fan_table->ucFanTableFormat) {
1044b7a1f382SAlex Deucher 				const ATOM_PPLIB_FANTABLE2 *fan_table2 =
1045b7a1f382SAlex Deucher 					(const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) +
1046b7a1f382SAlex Deucher 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1047b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
1048b7a1f382SAlex Deucher 					le16_to_cpu(fan_table2->usTMax);
1049b7a1f382SAlex Deucher 			}
1050b7a1f382SAlex Deucher 
1051b7a1f382SAlex Deucher 			if (3 <= fan_table->ucFanTableFormat) {
1052b7a1f382SAlex Deucher 				const ATOM_PPLIB_FANTABLE3 *fan_table3 =
1053b7a1f382SAlex Deucher 					(const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) +
1054b7a1f382SAlex Deucher 									le16_to_cpu(powerplay_table3->usFanTableOffset));
1055b7a1f382SAlex Deucher 
1056b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =
1057b7a1f382SAlex Deucher 					fan_table3->ucFanControlMode;
1058b7a1f382SAlex Deucher 
1059b7a1f382SAlex Deucher 				if ((3 == fan_table->ucFanTableFormat) &&
1060b7a1f382SAlex Deucher 				    (0x67B1 == adev->pdev->device))
1061b7a1f382SAlex Deucher 					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1062b7a1f382SAlex Deucher 						47;
1063b7a1f382SAlex Deucher 				else
1064b7a1f382SAlex Deucher 					hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1065b7a1f382SAlex Deucher 						le16_to_cpu(fan_table3->usFanPWMMax);
1066b7a1f382SAlex Deucher 
1067b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity =
1068b7a1f382SAlex Deucher 					4836;
1069b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
1070b7a1f382SAlex Deucher 					le16_to_cpu(fan_table3->usFanOutputSensitivity);
1071b7a1f382SAlex Deucher 			}
1072b7a1f382SAlex Deucher 
1073b7a1f382SAlex Deucher 			if (6 <= fan_table->ucFanTableFormat) {
1074b7a1f382SAlex Deucher 				const ATOM_PPLIB_FANTABLE4 *fan_table4 =
1075b7a1f382SAlex Deucher 					(const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) +
1076b7a1f382SAlex Deucher 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1077b7a1f382SAlex Deucher 
1078b7a1f382SAlex Deucher 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1079b7a1f382SAlex Deucher 					    PHM_PlatformCaps_FanSpeedInTableIsRPM);
1080b7a1f382SAlex Deucher 
1081b7a1f382SAlex Deucher 				hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM =
1082b7a1f382SAlex Deucher 					le16_to_cpu(fan_table4->usFanRPMMax);
1083b7a1f382SAlex Deucher 			}
1084b7a1f382SAlex Deucher 
1085b7a1f382SAlex Deucher 			if (7 <= fan_table->ucFanTableFormat) {
1086b7a1f382SAlex Deucher 				const ATOM_PPLIB_FANTABLE5 *fan_table5 =
1087b7a1f382SAlex Deucher 					(const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) +
1088b7a1f382SAlex Deucher 								       le16_to_cpu(powerplay_table3->usFanTableOffset));
1089b7a1f382SAlex Deucher 
1090b7a1f382SAlex Deucher 				if (0x67A2 == adev->pdev->device ||
1091b7a1f382SAlex Deucher 				    0x67A9 == adev->pdev->device ||
1092b7a1f382SAlex Deucher 				    0x67B9 == adev->pdev->device) {
1093b7a1f382SAlex Deucher 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1094b7a1f382SAlex Deucher 						    PHM_PlatformCaps_GeminiRegulatorFanControlSupport);
1095b7a1f382SAlex Deucher 					hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow =
1096b7a1f382SAlex Deucher 						le16_to_cpu(fan_table5->usFanCurrentLow);
1097b7a1f382SAlex Deucher 					hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh =
1098b7a1f382SAlex Deucher 						le16_to_cpu(fan_table5->usFanCurrentHigh);
1099b7a1f382SAlex Deucher 					hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow =
1100b7a1f382SAlex Deucher 						le16_to_cpu(fan_table5->usFanRPMLow);
1101b7a1f382SAlex Deucher 					hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh =
1102b7a1f382SAlex Deucher 						le16_to_cpu(fan_table5->usFanRPMHigh);
1103b7a1f382SAlex Deucher 				}
1104b7a1f382SAlex Deucher 			}
1105b7a1f382SAlex Deucher 		}
1106b7a1f382SAlex Deucher 	}
1107bbc25dadSSandeep Raghuraman 
11083bace359SJammy Zhou 	return 0;
11093bace359SJammy Zhou }
11103bace359SJammy Zhou 
init_overdrive_limits_V1_4(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V1_4 * fw_info)11113bace359SJammy Zhou static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
11123bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
11133bace359SJammy Zhou 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
11143bace359SJammy Zhou {
11153bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
11163bace359SJammy Zhou 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
11173bace359SJammy Zhou 
11183bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
11193bace359SJammy Zhou 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
11203bace359SJammy Zhou 
11213bace359SJammy Zhou 	hwmgr->platform_descriptor.maxOverdriveVDDC =
11223bace359SJammy Zhou 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
11233bace359SJammy Zhou 
11243bace359SJammy Zhou 	hwmgr->platform_descriptor.minOverdriveVDDC =
11253bace359SJammy Zhou 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
11263bace359SJammy Zhou 
11273bace359SJammy Zhou 	hwmgr->platform_descriptor.maxOverdriveVDDC =
11283bace359SJammy Zhou 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
11293bace359SJammy Zhou 
11303bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
11313bace359SJammy Zhou 	return 0;
11323bace359SJammy Zhou }
11333bace359SJammy Zhou 
init_overdrive_limits_V2_1(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V2_1 * fw_info)11343bace359SJammy Zhou static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
11353bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
11363bace359SJammy Zhou 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
11373bace359SJammy Zhou {
11383bace359SJammy Zhou 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
11393bace359SJammy Zhou 	const ATOM_PPLIB_EXTENDEDHEADER *header;
11403bace359SJammy Zhou 
11413bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) <
11423bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
11433bace359SJammy Zhou 		return 0;
11443bace359SJammy Zhou 
11453bace359SJammy Zhou 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
11463bace359SJammy Zhou 
11473bace359SJammy Zhou 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
11483bace359SJammy Zhou 		return 0;
11493bace359SJammy Zhou 
11503bace359SJammy Zhou 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
11513bace359SJammy Zhou 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
11523bace359SJammy Zhou 
11533bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
11543bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
11553bace359SJammy Zhou 
11563bace359SJammy Zhou 
11573bace359SJammy Zhou 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
11583bace359SJammy Zhou 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
11593bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
11603bace359SJammy Zhou 
11613bace359SJammy Zhou 	return 0;
11623bace359SJammy Zhou }
11633bace359SJammy Zhou 
init_overdrive_limits(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)11643bace359SJammy Zhou static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
11653bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
11663bace359SJammy Zhou {
116719fef71cSErnst Sjöstrand 	int result = 0;
11683bace359SJammy Zhou 	uint8_t frev, crev;
11693bace359SJammy Zhou 	uint16_t size;
11703bace359SJammy Zhou 
11713bace359SJammy Zhou 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
11723bace359SJammy Zhou 
11733bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
11743bace359SJammy Zhou 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
11753bace359SJammy Zhou 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
11763bace359SJammy Zhou 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1177a960d61cSRex Zhu 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1178a960d61cSRex Zhu 
1179741deadeSAlex Deucher 	if (hwmgr->chip_id == CHIP_RAVEN)
1180a960d61cSRex Zhu 		return 0;
11813bace359SJammy Zhou 
11823bace359SJammy Zhou 	/* We assume here that fw_info is unchanged if this call fails.*/
1183b3892e2bSRex Zhu 	fw_info = smu_atom_get_data_table(hwmgr->adev,
11843bace359SJammy Zhou 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
11853bace359SJammy Zhou 			 &size, &frev, &crev);
1186186fb12eSTim Huang 	PP_ASSERT_WITH_CODE(fw_info != NULL,
1187186fb12eSTim Huang 			    "Missing firmware info!", return -EINVAL);
11883bace359SJammy Zhou 
11893bace359SJammy Zhou 	if ((fw_info->ucTableFormatRevision == 1)
119054f16ebfSAlex Deucher 	    && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
11913bace359SJammy Zhou 		result = init_overdrive_limits_V1_4(hwmgr,
11923bace359SJammy Zhou 				powerplay_table,
11933bace359SJammy Zhou 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
11943bace359SJammy Zhou 
11953bace359SJammy Zhou 	else if ((fw_info->ucTableFormatRevision == 2)
119654f16ebfSAlex Deucher 		 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
11973bace359SJammy Zhou 		result = init_overdrive_limits_V2_1(hwmgr,
11983bace359SJammy Zhou 				powerplay_table,
11993bace359SJammy Zhou 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
12003bace359SJammy Zhou 
12013bace359SJammy Zhou 	return result;
12023bace359SJammy Zhou }
12033bace359SJammy Zhou 
get_uvd_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_uvd_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table * table,const UVDClockInfoArray * array)12043bace359SJammy Zhou static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
12053bace359SJammy Zhou 		struct phm_uvd_clock_voltage_dependency_table **ptable,
12063bace359SJammy Zhou 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
12073bace359SJammy Zhou 		const UVDClockInfoArray *array)
12083bace359SJammy Zhou {
1209737123d6SGustavo A. R. Silva 	unsigned long i;
12103bace359SJammy Zhou 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
12113bace359SJammy Zhou 
1212737123d6SGustavo A. R. Silva 	uvd_table = kzalloc(struct_size(uvd_table, entries, table->numEntries),
1213737123d6SGustavo A. R. Silva 			    GFP_KERNEL);
1214737123d6SGustavo A. R. Silva 	if (!uvd_table)
12153bace359SJammy Zhou 		return -ENOMEM;
12163bace359SJammy Zhou 
12173bace359SJammy Zhou 	uvd_table->count = table->numEntries;
12183bace359SJammy Zhou 
12193bace359SJammy Zhou 	for (i = 0; i < table->numEntries; i++) {
12203bace359SJammy Zhou 		const UVDClockInfo *entry =
12213bace359SJammy Zhou 			&array->entries[table->entries[i].ucUVDClockInfoIndex];
12223bace359SJammy Zhou 		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
12233bace359SJammy Zhou 		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
12243bace359SJammy Zhou 					 | le16_to_cpu(entry->usVClkLow);
12253bace359SJammy Zhou 		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
12263bace359SJammy Zhou 					 | le16_to_cpu(entry->usDClkLow);
12273bace359SJammy Zhou 	}
12283bace359SJammy Zhou 
12293bace359SJammy Zhou 	*ptable = uvd_table;
12303bace359SJammy Zhou 
12313bace359SJammy Zhou 	return 0;
12323bace359SJammy Zhou }
12333bace359SJammy Zhou 
get_vce_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_vce_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table * table,const VCEClockInfoArray * array)12343bace359SJammy Zhou static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
12353bace359SJammy Zhou 		struct phm_vce_clock_voltage_dependency_table **ptable,
12363bace359SJammy Zhou 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
12373bace359SJammy Zhou 		const VCEClockInfoArray    *array)
12383bace359SJammy Zhou {
1239637f7576SGustavo A. R. Silva 	unsigned long i;
12406f8e98b9SRuan Jinjie 	struct phm_vce_clock_voltage_dependency_table *vce_table;
12413bace359SJammy Zhou 
1242637f7576SGustavo A. R. Silva 	vce_table = kzalloc(struct_size(vce_table, entries, table->numEntries),
1243637f7576SGustavo A. R. Silva 			    GFP_KERNEL);
1244637f7576SGustavo A. R. Silva 	if (!vce_table)
12453bace359SJammy Zhou 		return -ENOMEM;
12463bace359SJammy Zhou 
12473bace359SJammy Zhou 	vce_table->count = table->numEntries;
12483bace359SJammy Zhou 	for (i = 0; i < table->numEntries; i++) {
12493bace359SJammy Zhou 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
12503bace359SJammy Zhou 
12513bace359SJammy Zhou 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
12523bace359SJammy Zhou 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
12533bace359SJammy Zhou 					| le16_to_cpu(entry->usEVClkLow);
12543bace359SJammy Zhou 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
12553bace359SJammy Zhou 					| le16_to_cpu(entry->usECClkLow);
12563bace359SJammy Zhou 	}
12573bace359SJammy Zhou 
12583bace359SJammy Zhou 	*ptable = vce_table;
12593bace359SJammy Zhou 
12603bace359SJammy Zhou 	return 0;
12613bace359SJammy Zhou }
12623bace359SJammy Zhou 
get_samu_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_samu_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_SAMClk_Voltage_Limit_Table * table)12633bace359SJammy Zhou static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
12643bace359SJammy Zhou 		 struct phm_samu_clock_voltage_dependency_table **ptable,
12653bace359SJammy Zhou 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
12663bace359SJammy Zhou {
126789c785bbSGustavo A. R. Silva 	unsigned long i;
12683bace359SJammy Zhou 	struct phm_samu_clock_voltage_dependency_table *samu_table;
12693bace359SJammy Zhou 
127089c785bbSGustavo A. R. Silva 	samu_table = kzalloc(struct_size(samu_table, entries, table->numEntries),
127189c785bbSGustavo A. R. Silva 			     GFP_KERNEL);
127289c785bbSGustavo A. R. Silva 	if (!samu_table)
12733bace359SJammy Zhou 		return -ENOMEM;
12743bace359SJammy Zhou 
12753bace359SJammy Zhou 	samu_table->count = table->numEntries;
12763bace359SJammy Zhou 
12773bace359SJammy Zhou 	for (i = 0; i < table->numEntries; i++) {
12783bace359SJammy Zhou 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
12793bace359SJammy Zhou 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
12803bace359SJammy Zhou 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
12813bace359SJammy Zhou 	}
12823bace359SJammy Zhou 
12833bace359SJammy Zhou 	*ptable = samu_table;
12843bace359SJammy Zhou 
12853bace359SJammy Zhou 	return 0;
12863bace359SJammy Zhou }
12873bace359SJammy Zhou 
get_acp_clock_voltage_limit_table(struct pp_hwmgr * hwmgr,struct phm_acp_clock_voltage_dependency_table ** ptable,const ATOM_PPLIB_ACPClk_Voltage_Limit_Table * table)12883bace359SJammy Zhou static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
12893bace359SJammy Zhou 		struct phm_acp_clock_voltage_dependency_table **ptable,
12903bace359SJammy Zhou 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
12913bace359SJammy Zhou {
12920e319cfeSGustavo A. R. Silva 	unsigned long i;
12933bace359SJammy Zhou 	struct phm_acp_clock_voltage_dependency_table *acp_table;
12943bace359SJammy Zhou 
12950e319cfeSGustavo A. R. Silva 	acp_table = kzalloc(struct_size(acp_table, entries, table->numEntries),
12960e319cfeSGustavo A. R. Silva 			    GFP_KERNEL);
12970e319cfeSGustavo A. R. Silva 	if (!acp_table)
12983bace359SJammy Zhou 		return -ENOMEM;
12993bace359SJammy Zhou 
13003bace359SJammy Zhou 	acp_table->count = (unsigned long)table->numEntries;
13013bace359SJammy Zhou 
13023bace359SJammy Zhou 	for (i = 0; i < table->numEntries; i++) {
13033bace359SJammy Zhou 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
13043bace359SJammy Zhou 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
13053bace359SJammy Zhou 					 | le16_to_cpu(table->entries[i].usACPClockLow);
13063bace359SJammy Zhou 	}
13073bace359SJammy Zhou 
13083bace359SJammy Zhou 	*ptable = acp_table;
13093bace359SJammy Zhou 
13103bace359SJammy Zhou 	return 0;
13113bace359SJammy Zhou }
13123bace359SJammy Zhou 
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)13133bace359SJammy Zhou static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
13143bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
13153bace359SJammy Zhou {
13163bace359SJammy Zhou 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
13173bace359SJammy Zhou 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
13183bace359SJammy Zhou 	int result = 0;
13193bace359SJammy Zhou 
13203bace359SJammy Zhou 	uint16_t vce_clock_info_array_offset;
13213bace359SJammy Zhou 	uint16_t uvd_clock_info_array_offset;
13223bace359SJammy Zhou 	uint16_t table_offset;
13233bace359SJammy Zhou 
13243bace359SJammy Zhou 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
13253bace359SJammy Zhou 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
13263bace359SJammy Zhou 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
13273bace359SJammy Zhou 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
13283bace359SJammy Zhou 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
13299c0bad90SAlex Deucher 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
13309c0bad90SAlex Deucher 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
13313bace359SJammy Zhou 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
13323bace359SJammy Zhou 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
13333bace359SJammy Zhou 	hwmgr->dyn_state.ppm_parameter_table = NULL;
13343bace359SJammy Zhou 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
13353bace359SJammy Zhou 
13363bace359SJammy Zhou 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
13373bace359SJammy Zhou 						hwmgr, powerplay_table);
13383bace359SJammy Zhou 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
13393bace359SJammy Zhou 						powerplay_table);
13403bace359SJammy Zhou 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
13413bace359SJammy Zhou 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
13423bace359SJammy Zhou 				(((unsigned long) powerplay_table) +
13433bace359SJammy Zhou 				vce_clock_info_array_offset);
13443bace359SJammy Zhou 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
13453bace359SJammy Zhou 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
13463bace359SJammy Zhou 				(((unsigned long) powerplay_table) + table_offset);
13473bace359SJammy Zhou 		result = get_vce_clock_voltage_limit_table(hwmgr,
13489c0bad90SAlex Deucher 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
13493bace359SJammy Zhou 				table, array);
13503bace359SJammy Zhou 	}
13513bace359SJammy Zhou 
13523bace359SJammy Zhou 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
13533bace359SJammy Zhou 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
13543bace359SJammy Zhou 
13553bace359SJammy Zhou 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
13563bace359SJammy Zhou 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
13573bace359SJammy Zhou 				(((unsigned long) powerplay_table) +
13583bace359SJammy Zhou 				uvd_clock_info_array_offset);
13593bace359SJammy Zhou 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
13603bace359SJammy Zhou 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
13613bace359SJammy Zhou 				(((unsigned long) powerplay_table) + table_offset);
13623bace359SJammy Zhou 		result = get_uvd_clock_voltage_limit_table(hwmgr,
13639c0bad90SAlex Deucher 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
13643bace359SJammy Zhou 	}
13653bace359SJammy Zhou 
13663bace359SJammy Zhou 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
13673bace359SJammy Zhou 							    powerplay_table);
13683bace359SJammy Zhou 
13693bace359SJammy Zhou 	if (table_offset > 0) {
13703bace359SJammy Zhou 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
13713bace359SJammy Zhou 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
13723bace359SJammy Zhou 				(((unsigned long) powerplay_table) + table_offset);
13733bace359SJammy Zhou 		result = get_samu_clock_voltage_limit_table(hwmgr,
13743bace359SJammy Zhou 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
13753bace359SJammy Zhou 	}
13763bace359SJammy Zhou 
13773bace359SJammy Zhou 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
13783bace359SJammy Zhou 							     powerplay_table);
13793bace359SJammy Zhou 
13803bace359SJammy Zhou 	if (table_offset > 0) {
13813bace359SJammy Zhou 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
13823bace359SJammy Zhou 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
13833bace359SJammy Zhou 				(((unsigned long) powerplay_table) + table_offset);
13843bace359SJammy Zhou 		result = get_acp_clock_voltage_limit_table(hwmgr,
13853bace359SJammy Zhou 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
13863bace359SJammy Zhou 	}
13873bace359SJammy Zhou 
13883bace359SJammy Zhou 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
13893bace359SJammy Zhou 	if (table_offset > 0) {
13903bace359SJammy Zhou 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
13913bace359SJammy Zhou 
13923bace359SJammy Zhou 		if (rev_id > 0) {
13933bace359SJammy Zhou 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
13943bace359SJammy Zhou 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
13953bace359SJammy Zhou 				(((unsigned long) powerplay_table) + table_offset);
13963bace359SJammy Zhou 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
13973bace359SJammy Zhou 				&tune_table->power_tune_table,
13983bace359SJammy Zhou 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
13993bace359SJammy Zhou 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
14003bace359SJammy Zhou 				le16_to_cpu(tune_table->usTjMax);
14013bace359SJammy Zhou 		} else {
14023bace359SJammy Zhou 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
14033bace359SJammy Zhou 				(const ATOM_PPLIB_POWERTUNE_Table *)
14043bace359SJammy Zhou 				(((unsigned long) powerplay_table) + table_offset);
14053bace359SJammy Zhou 			result = get_cac_tdp_table(hwmgr,
14063bace359SJammy Zhou 				&hwmgr->dyn_state.cac_dtp_table,
14073bace359SJammy Zhou 				&tune_table->power_tune_table, 255);
14083bace359SJammy Zhou 		}
14093bace359SJammy Zhou 	}
14103bace359SJammy Zhou 
14113bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
14123bace359SJammy Zhou 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
14133bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
14143bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
14153bace359SJammy Zhou 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
14163bace359SJammy Zhou 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
14173bace359SJammy Zhou 				(((unsigned long) powerplay_table4) +
141854f16ebfSAlex Deucher 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
14193bace359SJammy Zhou 			result = get_clock_voltage_dependency_table(hwmgr,
14203bace359SJammy Zhou 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
14213bace359SJammy Zhou 		}
14223bace359SJammy Zhou 
14233bace359SJammy Zhou 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
14243bace359SJammy Zhou 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
14253bace359SJammy Zhou 				(((unsigned long) powerplay_table4) +
142654f16ebfSAlex Deucher 				 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
14273bace359SJammy Zhou 			result = get_clock_voltage_dependency_table(hwmgr,
14283bace359SJammy Zhou 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
14293bace359SJammy Zhou 		}
14303bace359SJammy Zhou 
14313bace359SJammy Zhou 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
14323bace359SJammy Zhou 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
14333bace359SJammy Zhou 				(((unsigned long) powerplay_table4) +
143454f16ebfSAlex Deucher 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
14353bace359SJammy Zhou 			result = get_clock_voltage_dependency_table(hwmgr,
14363bace359SJammy Zhou 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
14373bace359SJammy Zhou 		}
14383bace359SJammy Zhou 
14393bace359SJammy Zhou 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
14403bace359SJammy Zhou 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
14413bace359SJammy Zhou 				(((unsigned long) powerplay_table4) +
144254f16ebfSAlex Deucher 				 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
14433bace359SJammy Zhou 			result = get_clock_voltage_limit(hwmgr,
14443bace359SJammy Zhou 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
14453bace359SJammy Zhou 		}
14463bace359SJammy Zhou 
14473bace359SJammy Zhou 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
14483bace359SJammy Zhou 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
14493bace359SJammy Zhou 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
14503bace359SJammy Zhou 					hwmgr->dyn_state.vddc_dependency_on_mclk);
14513bace359SJammy Zhou 
14523bace359SJammy Zhou 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
14533bace359SJammy Zhou 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
14543bace359SJammy Zhou 			result = get_valid_clk(hwmgr,
14553bace359SJammy Zhou 				&hwmgr->dyn_state.valid_sclk_values,
14563bace359SJammy Zhou 				hwmgr->dyn_state.vddc_dependency_on_sclk);
14573bace359SJammy Zhou 
14583bace359SJammy Zhou 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
14593bace359SJammy Zhou 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
14603bace359SJammy Zhou 				(((unsigned long) powerplay_table4) +
146154f16ebfSAlex Deucher 				 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
14623bace359SJammy Zhou 			result = get_clock_voltage_dependency_table(hwmgr,
14633bace359SJammy Zhou 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
14643bace359SJammy Zhou 		}
14653bace359SJammy Zhou 	}
14663bace359SJammy Zhou 
14673bace359SJammy Zhou 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
14683bace359SJammy Zhou 								powerplay_table);
14693bace359SJammy Zhou 
14703bace359SJammy Zhou 	if (table_offset > 0) {
14713bace359SJammy Zhou 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
14723bace359SJammy Zhou 			(((unsigned long) powerplay_table) + table_offset);
14733bace359SJammy Zhou 		result = get_clock_voltage_dependency_table(hwmgr,
14743bace359SJammy Zhou 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
14753bace359SJammy Zhou 	}
14763bace359SJammy Zhou 
14773bace359SJammy Zhou 	return result;
14783bace359SJammy Zhou }
14793bace359SJammy Zhou 
get_cac_leakage_table(struct pp_hwmgr * hwmgr,struct phm_cac_leakage_table ** ptable,const ATOM_PPLIB_CAC_Leakage_Table * table)14803bace359SJammy Zhou static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
14813bace359SJammy Zhou 				 struct phm_cac_leakage_table **ptable,
14823bace359SJammy Zhou 				const ATOM_PPLIB_CAC_Leakage_Table *table)
14833bace359SJammy Zhou {
14843bace359SJammy Zhou 	struct phm_cac_leakage_table  *cac_leakage_table;
1485aa8d10a1SGustavo A. R. Silva 	unsigned long i;
14863bace359SJammy Zhou 
1487aa8d10a1SGustavo A. R. Silva 	if (!hwmgr || !table || !ptable)
1488c15c8d70SRex Zhu 		return -EINVAL;
1489c15c8d70SRex Zhu 
1490aa8d10a1SGustavo A. R. Silva 	cac_leakage_table = kzalloc(struct_size(cac_leakage_table, entries, table->ucNumEntries),
1491aa8d10a1SGustavo A. R. Silva 				    GFP_KERNEL);
1492aa8d10a1SGustavo A. R. Silva 	if (!cac_leakage_table)
1493c15c8d70SRex Zhu 		return -ENOMEM;
1494c15c8d70SRex Zhu 
14953bace359SJammy Zhou 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
14963bace359SJammy Zhou 
14973bace359SJammy Zhou 	for (i = 0; i < cac_leakage_table->count; i++) {
14983bace359SJammy Zhou 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
14993bace359SJammy Zhou 				PHM_PlatformCaps_EVV)) {
15003bace359SJammy Zhou 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
15013bace359SJammy Zhou 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
15023bace359SJammy Zhou 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
15033bace359SJammy Zhou 		} else {
15043bace359SJammy Zhou 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
15053bace359SJammy Zhou 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
15063bace359SJammy Zhou 		}
15073bace359SJammy Zhou 	}
15083bace359SJammy Zhou 
15093bace359SJammy Zhou 	*ptable = cac_leakage_table;
15103bace359SJammy Zhou 
15113bace359SJammy Zhou 	return 0;
15123bace359SJammy Zhou }
15133bace359SJammy Zhou 
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_PPLIB_PPM_Table * atom_ppm_table)15143bace359SJammy Zhou static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
15153bace359SJammy Zhou 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
15163bace359SJammy Zhou {
1517c15c8d70SRex Zhu 	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
15183bace359SJammy Zhou 
15193bace359SJammy Zhou 	if (NULL == ptr)
15203bace359SJammy Zhou 		return -ENOMEM;
15213bace359SJammy Zhou 
15223bace359SJammy Zhou 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
15233bace359SJammy Zhou 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
15243bace359SJammy Zhou 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
15253bace359SJammy Zhou 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
15263bace359SJammy Zhou 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
15273bace359SJammy Zhou 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
15283bace359SJammy Zhou 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
15293bace359SJammy Zhou 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
15303bace359SJammy Zhou 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
15313bace359SJammy Zhou 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
15323bace359SJammy Zhou 	hwmgr->dyn_state.ppm_parameter_table = ptr;
15333bace359SJammy Zhou 
15343bace359SJammy Zhou 	return 0;
15353bace359SJammy Zhou }
15363bace359SJammy Zhou 
init_dpm2_parameters(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)15373bace359SJammy Zhou static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
15383bace359SJammy Zhou 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
15393bace359SJammy Zhou {
15403bace359SJammy Zhou 	int result = 0;
15413bace359SJammy Zhou 
15423bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
15433bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
15443bace359SJammy Zhou 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
15453bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
15463bace359SJammy Zhou 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
15473bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
15483bace359SJammy Zhou 				(&ptable5->basicTable4);
15493bace359SJammy Zhou 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
15503bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
15513bace359SJammy Zhou 				(&ptable4->basicTable3);
15523bace359SJammy Zhou 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
15533bace359SJammy Zhou 		uint16_t table_offset;
15543bace359SJammy Zhou 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
15553bace359SJammy Zhou 
15563bace359SJammy Zhou 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
15573bace359SJammy Zhou 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
15583bace359SJammy Zhou 
15593bace359SJammy Zhou 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
15603bace359SJammy Zhou 		hwmgr->platform_descriptor.TDPAdjustment = 0;
15613bace359SJammy Zhou 
15623bace359SJammy Zhou 		hwmgr->platform_descriptor.VidAdjustment = 0;
15633bace359SJammy Zhou 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
15643bace359SJammy Zhou 		hwmgr->platform_descriptor.VidMinLimit     = 0;
15653bace359SJammy Zhou 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
15663bace359SJammy Zhou 		hwmgr->platform_descriptor.VidStep         = 6250;
15673bace359SJammy Zhou 
15683bace359SJammy Zhou 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
15693bace359SJammy Zhou 
15703bace359SJammy Zhou 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
15713bace359SJammy Zhou 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
15723bace359SJammy Zhou 					PHM_PlatformCaps_PowerControl);
15733bace359SJammy Zhou 
15743bace359SJammy Zhou 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
15753bace359SJammy Zhou 
15763bace359SJammy Zhou 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
15773bace359SJammy Zhou 
15783bace359SJammy Zhou 		hwmgr->dyn_state.cac_leakage_table = NULL;
15793bace359SJammy Zhou 
15803bace359SJammy Zhou 		if (0 != ptable5->usCACLeakageTableOffset) {
15813bace359SJammy Zhou 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
15823bace359SJammy Zhou 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
15833bace359SJammy Zhou 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
15843bace359SJammy Zhou 			result = get_cac_leakage_table(hwmgr,
15853bace359SJammy Zhou 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
15863bace359SJammy Zhou 		}
15873bace359SJammy Zhou 
15883bace359SJammy Zhou 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
15893bace359SJammy Zhou 
15903bace359SJammy Zhou 		hwmgr->dyn_state.ppm_parameter_table = NULL;
15913bace359SJammy Zhou 
15923bace359SJammy Zhou 		if (0 != ptable3->usExtendendedHeaderOffset) {
15933bace359SJammy Zhou 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
15943bace359SJammy Zhou 					(((unsigned long)powerplay_table) +
15953bace359SJammy Zhou 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
15963bace359SJammy Zhou 			if ((extended_header->usPPMTableOffset > 0) &&
15973bace359SJammy Zhou 				le16_to_cpu(extended_header->usSize) >=
15983bace359SJammy Zhou 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
15993bace359SJammy Zhou 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
16003bace359SJammy Zhou 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
16013bace359SJammy Zhou 					(((unsigned long)powerplay_table) + table_offset);
16023bace359SJammy Zhou 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
16033bace359SJammy Zhou 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
16043bace359SJammy Zhou 						PHM_PlatformCaps_EnablePlatformPowerManagement);
16053bace359SJammy Zhou 			}
16063bace359SJammy Zhou 		}
16073bace359SJammy Zhou 	}
16083bace359SJammy Zhou 	return result;
16093bace359SJammy Zhou }
16103bace359SJammy Zhou 
init_phase_shedding_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)16113bace359SJammy Zhou static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
16123bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
16133bace359SJammy Zhou {
16143bace359SJammy Zhou 	if (le16_to_cpu(powerplay_table->usTableSize) >=
16153bace359SJammy Zhou 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
16163bace359SJammy Zhou 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
16173bace359SJammy Zhou 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
16183bace359SJammy Zhou 
16193bace359SJammy Zhou 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
16203bace359SJammy Zhou 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
16213bace359SJammy Zhou 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
16223bace359SJammy Zhou 				(((unsigned long)powerplay_table4) +
16233bace359SJammy Zhou 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
16243bace359SJammy Zhou 			struct phm_phase_shedding_limits_table *table;
16259526e431SGustavo A. R. Silva 			unsigned long i;
16263bace359SJammy Zhou 
16273bace359SJammy Zhou 
16289526e431SGustavo A. R. Silva 			table = kzalloc(struct_size(table, entries, ptable->ucNumEntries),
16299526e431SGustavo A. R. Silva 					GFP_KERNEL);
16309526e431SGustavo A. R. Silva 			if (!table)
1631c15c8d70SRex Zhu 				return -ENOMEM;
1632c15c8d70SRex Zhu 
16333bace359SJammy Zhou 			table->count = (unsigned long)ptable->ucNumEntries;
16343bace359SJammy Zhou 
16353bace359SJammy Zhou 			for (i = 0; i < table->count; i++) {
16363bace359SJammy Zhou 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
16373bace359SJammy Zhou 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
16383bace359SJammy Zhou 							| le16_to_cpu(ptable->entries[i].usSclkLow);
16393bace359SJammy Zhou 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
16403bace359SJammy Zhou 							| le16_to_cpu(ptable->entries[i].usMclkLow);
16413bace359SJammy Zhou 			}
16423bace359SJammy Zhou 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
16433bace359SJammy Zhou 		}
16443bace359SJammy Zhou 	}
16453bace359SJammy Zhou 
16463bace359SJammy Zhou 	return 0;
16473bace359SJammy Zhou }
16483bace359SJammy Zhou 
get_number_of_vce_state_table_entries(struct pp_hwmgr * hwmgr)1649f8a4c11bSBaoyou Xie static int get_number_of_vce_state_table_entries(
16503bace359SJammy Zhou 						  struct pp_hwmgr *hwmgr)
16513bace359SJammy Zhou {
16523bace359SJammy Zhou 	const ATOM_PPLIB_POWERPLAYTABLE *table =
16533bace359SJammy Zhou 					     get_powerplay_table(hwmgr);
16543bace359SJammy Zhou 	const ATOM_PPLIB_VCE_State_Table *vce_table =
16553bace359SJammy Zhou 				    get_vce_state_table(hwmgr, table);
16563bace359SJammy Zhou 
1657eafc9c27SArnd Bergmann 	if (vce_table)
16583bace359SJammy Zhou 		return vce_table->numEntries;
16593bace359SJammy Zhou 
16603bace359SJammy Zhou 	return 0;
16613bace359SJammy Zhou }
16623bace359SJammy Zhou 
get_vce_state_table_entry(struct pp_hwmgr * hwmgr,unsigned long i,struct amd_vce_state * vce_state,void ** clock_info,unsigned long * flag)1663f8a4c11bSBaoyou Xie static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
16643bace359SJammy Zhou 							unsigned long i,
16650d8de7caSRex Zhu 							struct amd_vce_state *vce_state,
16663bace359SJammy Zhou 							void **clock_info,
16673bace359SJammy Zhou 							unsigned long *flag)
16683bace359SJammy Zhou {
16693bace359SJammy Zhou 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
16703bace359SJammy Zhou 
16713bace359SJammy Zhou 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
16723bace359SJammy Zhou 
16733bace359SJammy Zhou 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
16743bace359SJammy Zhou 
16753bace359SJammy Zhou 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
16763bace359SJammy Zhou 
167754f16ebfSAlex Deucher 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
167854f16ebfSAlex Deucher 								le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
16793bace359SJammy Zhou 
16803bace359SJammy Zhou 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
16813bace359SJammy Zhou 
16823bace359SJammy Zhou 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
16833bace359SJammy Zhou 
16843bace359SJammy Zhou 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
16853bace359SJammy Zhou 
16863bace359SJammy Zhou 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
16873bace359SJammy Zhou 
168854f16ebfSAlex Deucher 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
168954f16ebfSAlex Deucher 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
16903bace359SJammy Zhou 
16913bace359SJammy Zhou 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
16923bace359SJammy Zhou 
16933bace359SJammy Zhou 	return 0;
16943bace359SJammy Zhou }
16953bace359SJammy Zhou 
16963bace359SJammy Zhou 
pp_tables_initialize(struct pp_hwmgr * hwmgr)16973bace359SJammy Zhou static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
16983bace359SJammy Zhou {
16993bace359SJammy Zhou 	int result;
17003bace359SJammy Zhou 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
17013bace359SJammy Zhou 
1702741deadeSAlex Deucher 	if (hwmgr->chip_id == CHIP_RAVEN)
17039e23f192SHawking Zhang 		return 0;
17049e23f192SHawking Zhang 
17059c0bad90SAlex Deucher 	hwmgr->need_pp_table_upload = true;
17069c0bad90SAlex Deucher 
17073bace359SJammy Zhou 	powerplay_table = get_powerplay_table(hwmgr);
17083bace359SJammy Zhou 
17093bace359SJammy Zhou 	result = init_powerplay_tables(hwmgr, powerplay_table);
17103bace359SJammy Zhou 
1711a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1712a71e06d9SAlex Deucher 			    "init_powerplay_tables failed", return result);
1713a71e06d9SAlex Deucher 
17143bace359SJammy Zhou 	result = set_platform_caps(hwmgr,
17153bace359SJammy Zhou 				le32_to_cpu(powerplay_table->ulPlatformCaps));
17163bace359SJammy Zhou 
1717a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1718a71e06d9SAlex Deucher 			    "set_platform_caps failed", return result);
1719a71e06d9SAlex Deucher 
17203bace359SJammy Zhou 	result = init_thermal_controller(hwmgr, powerplay_table);
17213bace359SJammy Zhou 
1722a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1723a71e06d9SAlex Deucher 			    "init_thermal_controller failed", return result);
1724a71e06d9SAlex Deucher 
17253bace359SJammy Zhou 	result = init_overdrive_limits(hwmgr, powerplay_table);
17263bace359SJammy Zhou 
1727a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1728a71e06d9SAlex Deucher 			    "init_overdrive_limits failed", return result);
1729a71e06d9SAlex Deucher 
17303bace359SJammy Zhou 	result = init_clock_voltage_dependency(hwmgr,
17313bace359SJammy Zhou 					       powerplay_table);
17323bace359SJammy Zhou 
1733a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1734a71e06d9SAlex Deucher 			    "init_clock_voltage_dependency failed", return result);
1735a71e06d9SAlex Deucher 
17363bace359SJammy Zhou 	result = init_dpm2_parameters(hwmgr, powerplay_table);
17373bace359SJammy Zhou 
1738a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1739a71e06d9SAlex Deucher 			    "init_dpm2_parameters failed", return result);
1740a71e06d9SAlex Deucher 
17413bace359SJammy Zhou 	result = init_phase_shedding_table(hwmgr, powerplay_table);
17423bace359SJammy Zhou 
1743a71e06d9SAlex Deucher 	PP_ASSERT_WITH_CODE((result == 0),
1744a71e06d9SAlex Deucher 			    "init_phase_shedding_table failed", return result);
1745a71e06d9SAlex Deucher 
17463bace359SJammy Zhou 	return result;
17473bace359SJammy Zhou }
17483bace359SJammy Zhou 
pp_tables_uninitialize(struct pp_hwmgr * hwmgr)17493bace359SJammy Zhou static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
17503bace359SJammy Zhou {
1751741deadeSAlex Deucher 	if (hwmgr->chip_id == CHIP_RAVEN)
17529e23f192SHawking Zhang 		return 0;
17539e23f192SHawking Zhang 
17543bace359SJammy Zhou 	kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
17553bace359SJammy Zhou 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
17563bace359SJammy Zhou 
17573bace359SJammy Zhou 	kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
17583bace359SJammy Zhou 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
17593bace359SJammy Zhou 
17603bace359SJammy Zhou 	kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
17613bace359SJammy Zhou 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
17623bace359SJammy Zhou 
17633bace359SJammy Zhou 	kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
17643bace359SJammy Zhou 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
17653bace359SJammy Zhou 
17663bace359SJammy Zhou 	kfree(hwmgr->dyn_state.valid_mclk_values);
17673bace359SJammy Zhou 	hwmgr->dyn_state.valid_mclk_values = NULL;
17683bace359SJammy Zhou 
17693bace359SJammy Zhou 	kfree(hwmgr->dyn_state.valid_sclk_values);
17703bace359SJammy Zhou 	hwmgr->dyn_state.valid_sclk_values = NULL;
17713bace359SJammy Zhou 
17723bace359SJammy Zhou 	kfree(hwmgr->dyn_state.cac_leakage_table);
17733bace359SJammy Zhou 	hwmgr->dyn_state.cac_leakage_table = NULL;
17743bace359SJammy Zhou 
17753bace359SJammy Zhou 	kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
17763bace359SJammy Zhou 	hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
17773bace359SJammy Zhou 
17789c0bad90SAlex Deucher 	kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
17799c0bad90SAlex Deucher 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
17803bace359SJammy Zhou 
17819c0bad90SAlex Deucher 	kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
17829c0bad90SAlex Deucher 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
17833bace359SJammy Zhou 
17843bace359SJammy Zhou 	kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
17853bace359SJammy Zhou 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
17863bace359SJammy Zhou 
17873bace359SJammy Zhou 	kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
17883bace359SJammy Zhou 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
17893bace359SJammy Zhou 
17903bace359SJammy Zhou 	kfree(hwmgr->dyn_state.cac_dtp_table);
17913bace359SJammy Zhou 	hwmgr->dyn_state.cac_dtp_table = NULL;
17923bace359SJammy Zhou 
17933bace359SJammy Zhou 	kfree(hwmgr->dyn_state.ppm_parameter_table);
17943bace359SJammy Zhou 	hwmgr->dyn_state.ppm_parameter_table = NULL;
17953bace359SJammy Zhou 
17963bace359SJammy Zhou 	kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
17973bace359SJammy Zhou 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
17983bace359SJammy Zhou 
17993bace359SJammy Zhou 	return 0;
18003bace359SJammy Zhou }
18013bace359SJammy Zhou 
18023bace359SJammy Zhou const struct pp_table_func pptable_funcs = {
18033bace359SJammy Zhou 	.pptable_init = pp_tables_initialize,
18043bace359SJammy Zhou 	.pptable_fini = pp_tables_uninitialize,
18053bace359SJammy Zhou 	.pptable_get_number_of_vce_state_table_entries =
18063bace359SJammy Zhou 				get_number_of_vce_state_table_entries,
18073bace359SJammy Zhou 	.pptable_get_vce_state_table_entry =
18083bace359SJammy Zhou 						get_vce_state_table_entry,
18093bace359SJammy Zhou };
18103bace359SJammy Zhou 
1811