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