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