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