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 = le32_to_cpu(pnon_clock_info->ulVCLK);
761 		ps->uvd_clocks.DCLK = le32_to_cpu(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 +
941 						    le16_to_cpu(powerplay_table->usStateArrayOffset) +
942 						    entry_index * powerplay_table->ucStateEntrySize);
943 
944 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
945 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
946 						pstate_entry->ucNonClockStateIndex *
947 						powerplay_table->ucNonClockSize);
948 
949 		result = init_non_clock_fields(hwmgr, ps,
950 							powerplay_table->ucNonClockSize,
951 							pnon_clock_info);
952 
953 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
954 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
955 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
956 						pstate_entry->ucClockStateIndices[i] *
957 						powerplay_table->ucClockInfoSize);
958 
959 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
960 
961 			if ((0 == result) && (0 != res))
962 					result = res;
963 		}
964 	}
965 
966 	if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
967 		if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
968 			result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
969 	}
970 
971 	return result;
972 }
973 
init_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)974 static int init_powerplay_tables(
975 			struct pp_hwmgr *hwmgr,
976 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
977 )
978 {
979 	return 0;
980 }
981 
982 
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)983 static int init_thermal_controller(
984 			struct pp_hwmgr *hwmgr,
985 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
986 {
987 	return 0;
988 }
989 
init_overdrive_limits_V1_4(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V1_4 * fw_info)990 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
991 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
992 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
993 {
994 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
995 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
996 
997 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
998 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
999 
1000 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1001 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1002 
1003 	hwmgr->platform_descriptor.minOverdriveVDDC =
1004 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1005 
1006 	hwmgr->platform_descriptor.maxOverdriveVDDC =
1007 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1008 
1009 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1010 	return 0;
1011 }
1012 
init_overdrive_limits_V2_1(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V2_1 * fw_info)1013 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1014 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1015 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1016 {
1017 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1018 	const ATOM_PPLIB_EXTENDEDHEADER *header;
1019 
1020 	if (le16_to_cpu(powerplay_table->usTableSize) <
1021 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1022 		return 0;
1023 
1024 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1025 
1026 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
1027 		return 0;
1028 
1029 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1030 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1031 
1032 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1033 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1034 
1035 
1036 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1037 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1038 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1039 
1040 	return 0;
1041 }
1042 
init_overdrive_limits(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1043 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1044 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1045 {
1046 	int result = 0;
1047 	uint8_t frev, crev;
1048 	uint16_t size;
1049 
1050 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1051 
1052 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1053 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1054 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1055 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1056 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1057 
1058 	if (hwmgr->chip_id == CHIP_RAVEN)
1059 		return 0;
1060 
1061 	/* We assume here that fw_info is unchanged if this call fails.*/
1062 	fw_info = smu_atom_get_data_table(hwmgr->adev,
1063 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1064 			 &size, &frev, &crev);
1065 
1066 	if ((fw_info->ucTableFormatRevision == 1)
1067 	    && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1068 		result = init_overdrive_limits_V1_4(hwmgr,
1069 				powerplay_table,
1070 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1071 
1072 	else if ((fw_info->ucTableFormatRevision == 2)
1073 		 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1074 		result = init_overdrive_limits_V2_1(hwmgr,
1075 				powerplay_table,
1076 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1077 
1078 	return result;
1079 }
1080 
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)1081 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1082 		struct phm_uvd_clock_voltage_dependency_table **ptable,
1083 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1084 		const UVDClockInfoArray *array)
1085 {
1086 	unsigned long table_size, i;
1087 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1088 
1089 	table_size = sizeof(unsigned long) +
1090 		 sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1091 		 table->numEntries;
1092 
1093 	uvd_table = kzalloc(table_size, GFP_KERNEL);
1094 	if (NULL == uvd_table)
1095 		return -ENOMEM;
1096 
1097 	uvd_table->count = table->numEntries;
1098 
1099 	for (i = 0; i < table->numEntries; i++) {
1100 		const UVDClockInfo *entry =
1101 			&array->entries[table->entries[i].ucUVDClockInfoIndex];
1102 		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1103 		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1104 					 | le16_to_cpu(entry->usVClkLow);
1105 		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1106 					 | le16_to_cpu(entry->usDClkLow);
1107 	}
1108 
1109 	*ptable = uvd_table;
1110 
1111 	return 0;
1112 }
1113 
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)1114 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1115 		struct phm_vce_clock_voltage_dependency_table **ptable,
1116 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1117 		const VCEClockInfoArray    *array)
1118 {
1119 	unsigned long table_size, i;
1120 	struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1121 
1122 	table_size = sizeof(unsigned long) +
1123 			sizeof(struct phm_vce_clock_voltage_dependency_table)
1124 			* table->numEntries;
1125 
1126 	vce_table = kzalloc(table_size, GFP_KERNEL);
1127 	if (NULL == vce_table)
1128 		return -ENOMEM;
1129 
1130 	vce_table->count = table->numEntries;
1131 	for (i = 0; i < table->numEntries; i++) {
1132 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1133 
1134 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1135 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1136 					| le16_to_cpu(entry->usEVClkLow);
1137 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1138 					| le16_to_cpu(entry->usECClkLow);
1139 	}
1140 
1141 	*ptable = vce_table;
1142 
1143 	return 0;
1144 }
1145 
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)1146 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1147 		 struct phm_samu_clock_voltage_dependency_table **ptable,
1148 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1149 {
1150 	unsigned long table_size, i;
1151 	struct phm_samu_clock_voltage_dependency_table *samu_table;
1152 
1153 	table_size = sizeof(unsigned long) +
1154 		sizeof(struct phm_samu_clock_voltage_dependency_table) *
1155 		table->numEntries;
1156 
1157 	samu_table = kzalloc(table_size, GFP_KERNEL);
1158 	if (NULL == samu_table)
1159 		return -ENOMEM;
1160 
1161 	samu_table->count = table->numEntries;
1162 
1163 	for (i = 0; i < table->numEntries; i++) {
1164 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1165 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1166 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
1167 	}
1168 
1169 	*ptable = samu_table;
1170 
1171 	return 0;
1172 }
1173 
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)1174 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1175 		struct phm_acp_clock_voltage_dependency_table **ptable,
1176 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1177 {
1178 	unsigned table_size, i;
1179 	struct phm_acp_clock_voltage_dependency_table *acp_table;
1180 
1181 	table_size = sizeof(unsigned long) +
1182 		sizeof(struct phm_acp_clock_voltage_dependency_table) *
1183 		table->numEntries;
1184 
1185 	acp_table = kzalloc(table_size, GFP_KERNEL);
1186 	if (NULL == acp_table)
1187 		return -ENOMEM;
1188 
1189 	acp_table->count = (unsigned long)table->numEntries;
1190 
1191 	for (i = 0; i < table->numEntries; i++) {
1192 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1193 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1194 					 | le16_to_cpu(table->entries[i].usACPClockLow);
1195 	}
1196 
1197 	*ptable = acp_table;
1198 
1199 	return 0;
1200 }
1201 
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1202 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1203 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1204 {
1205 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1206 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1207 	int result = 0;
1208 
1209 	uint16_t vce_clock_info_array_offset;
1210 	uint16_t uvd_clock_info_array_offset;
1211 	uint16_t table_offset;
1212 
1213 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1214 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1215 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1216 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1217 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1218 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1219 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1220 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1221 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1222 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1223 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1224 
1225 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1226 						hwmgr, powerplay_table);
1227 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1228 						powerplay_table);
1229 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1230 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1231 				(((unsigned long) powerplay_table) +
1232 				vce_clock_info_array_offset);
1233 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1234 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1235 				(((unsigned long) powerplay_table) + table_offset);
1236 		result = get_vce_clock_voltage_limit_table(hwmgr,
1237 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1238 				table, array);
1239 	}
1240 
1241 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1242 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1243 
1244 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1245 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1246 				(((unsigned long) powerplay_table) +
1247 				uvd_clock_info_array_offset);
1248 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1249 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1250 				(((unsigned long) powerplay_table) + table_offset);
1251 		result = get_uvd_clock_voltage_limit_table(hwmgr,
1252 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1253 	}
1254 
1255 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1256 							    powerplay_table);
1257 
1258 	if (table_offset > 0) {
1259 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1260 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1261 				(((unsigned long) powerplay_table) + table_offset);
1262 		result = get_samu_clock_voltage_limit_table(hwmgr,
1263 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1264 	}
1265 
1266 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1267 							     powerplay_table);
1268 
1269 	if (table_offset > 0) {
1270 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1271 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1272 				(((unsigned long) powerplay_table) + table_offset);
1273 		result = get_acp_clock_voltage_limit_table(hwmgr,
1274 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1275 	}
1276 
1277 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1278 	if (table_offset > 0) {
1279 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1280 
1281 		if (rev_id > 0) {
1282 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1283 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1284 				(((unsigned long) powerplay_table) + table_offset);
1285 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1286 				&tune_table->power_tune_table,
1287 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1288 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1289 				le16_to_cpu(tune_table->usTjMax);
1290 		} else {
1291 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1292 				(const ATOM_PPLIB_POWERTUNE_Table *)
1293 				(((unsigned long) powerplay_table) + table_offset);
1294 			result = get_cac_tdp_table(hwmgr,
1295 				&hwmgr->dyn_state.cac_dtp_table,
1296 				&tune_table->power_tune_table, 255);
1297 		}
1298 	}
1299 
1300 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1301 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1302 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1303 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1304 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1305 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1306 				(((unsigned long) powerplay_table4) +
1307 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1308 			result = get_clock_voltage_dependency_table(hwmgr,
1309 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1310 		}
1311 
1312 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1313 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1314 				(((unsigned long) powerplay_table4) +
1315 				 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1316 			result = get_clock_voltage_dependency_table(hwmgr,
1317 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1318 		}
1319 
1320 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1321 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1322 				(((unsigned long) powerplay_table4) +
1323 				 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1324 			result = get_clock_voltage_dependency_table(hwmgr,
1325 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1326 		}
1327 
1328 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1329 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1330 				(((unsigned long) powerplay_table4) +
1331 				 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1332 			result = get_clock_voltage_limit(hwmgr,
1333 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1334 		}
1335 
1336 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1337 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1338 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1339 					hwmgr->dyn_state.vddc_dependency_on_mclk);
1340 
1341 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1342 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1343 			result = get_valid_clk(hwmgr,
1344 				&hwmgr->dyn_state.valid_sclk_values,
1345 				hwmgr->dyn_state.vddc_dependency_on_sclk);
1346 
1347 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1348 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1349 				(((unsigned long) powerplay_table4) +
1350 				 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1351 			result = get_clock_voltage_dependency_table(hwmgr,
1352 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1353 		}
1354 	}
1355 
1356 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1357 								powerplay_table);
1358 
1359 	if (table_offset > 0) {
1360 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1361 			(((unsigned long) powerplay_table) + table_offset);
1362 		result = get_clock_voltage_dependency_table(hwmgr,
1363 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1364 	}
1365 
1366 	return result;
1367 }
1368 
get_cac_leakage_table(struct pp_hwmgr * hwmgr,struct phm_cac_leakage_table ** ptable,const ATOM_PPLIB_CAC_Leakage_Table * table)1369 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1370 				 struct phm_cac_leakage_table **ptable,
1371 				const ATOM_PPLIB_CAC_Leakage_Table *table)
1372 {
1373 	struct phm_cac_leakage_table  *cac_leakage_table;
1374 	unsigned long            table_size, i;
1375 
1376 	if (hwmgr == NULL || table == NULL || ptable == NULL)
1377 		return -EINVAL;
1378 
1379 	table_size = sizeof(ULONG) +
1380 		(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1381 
1382 	cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1383 
1384 	if (cac_leakage_table == NULL)
1385 		return -ENOMEM;
1386 
1387 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
1388 
1389 	for (i = 0; i < cac_leakage_table->count; i++) {
1390 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1391 				PHM_PlatformCaps_EVV)) {
1392 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1393 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1394 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1395 		} else {
1396 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1397 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1398 		}
1399 	}
1400 
1401 	*ptable = cac_leakage_table;
1402 
1403 	return 0;
1404 }
1405 
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_PPLIB_PPM_Table * atom_ppm_table)1406 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1407 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
1408 {
1409 	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1410 
1411 	if (NULL == ptr)
1412 		return -ENOMEM;
1413 
1414 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1415 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1416 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1417 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1418 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1419 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1420 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1421 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1422 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1423 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1424 	hwmgr->dyn_state.ppm_parameter_table = ptr;
1425 
1426 	return 0;
1427 }
1428 
init_dpm2_parameters(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1429 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1430 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1431 {
1432 	int result = 0;
1433 
1434 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1435 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1436 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1437 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1438 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1439 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1440 				(&ptable5->basicTable4);
1441 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1442 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1443 				(&ptable4->basicTable3);
1444 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1445 		uint16_t table_offset;
1446 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
1447 
1448 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1449 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1450 
1451 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1452 		hwmgr->platform_descriptor.TDPAdjustment = 0;
1453 
1454 		hwmgr->platform_descriptor.VidAdjustment = 0;
1455 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1456 		hwmgr->platform_descriptor.VidMinLimit     = 0;
1457 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1458 		hwmgr->platform_descriptor.VidStep         = 6250;
1459 
1460 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1461 
1462 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
1463 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1464 					PHM_PlatformCaps_PowerControl);
1465 
1466 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1467 
1468 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1469 
1470 		hwmgr->dyn_state.cac_leakage_table = NULL;
1471 
1472 		if (0 != ptable5->usCACLeakageTableOffset) {
1473 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1474 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1475 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
1476 			result = get_cac_leakage_table(hwmgr,
1477 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1478 		}
1479 
1480 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1481 
1482 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1483 
1484 		if (0 != ptable3->usExtendendedHeaderOffset) {
1485 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1486 					(((unsigned long)powerplay_table) +
1487 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1488 			if ((extended_header->usPPMTableOffset > 0) &&
1489 				le16_to_cpu(extended_header->usSize) >=
1490 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1491 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1492 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1493 					(((unsigned long)powerplay_table) + table_offset);
1494 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1495 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1496 						PHM_PlatformCaps_EnablePlatformPowerManagement);
1497 			}
1498 		}
1499 	}
1500 	return result;
1501 }
1502 
init_phase_shedding_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1503 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1504 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1505 {
1506 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1507 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1508 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1509 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1510 
1511 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1512 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1513 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1514 				(((unsigned long)powerplay_table4) +
1515 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1516 			struct phm_phase_shedding_limits_table *table;
1517 			unsigned long size, i;
1518 
1519 
1520 			size = sizeof(unsigned long) +
1521 				(sizeof(struct phm_phase_shedding_limits_table) *
1522 				ptable->ucNumEntries);
1523 
1524 			table = kzalloc(size, GFP_KERNEL);
1525 
1526 			if (table == NULL)
1527 				return -ENOMEM;
1528 
1529 			table->count = (unsigned long)ptable->ucNumEntries;
1530 
1531 			for (i = 0; i < table->count; i++) {
1532 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1533 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1534 							| le16_to_cpu(ptable->entries[i].usSclkLow);
1535 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1536 							| le16_to_cpu(ptable->entries[i].usMclkLow);
1537 			}
1538 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1539 		}
1540 	}
1541 
1542 	return 0;
1543 }
1544 
get_number_of_vce_state_table_entries(struct pp_hwmgr * hwmgr)1545 static int get_number_of_vce_state_table_entries(
1546 						  struct pp_hwmgr *hwmgr)
1547 {
1548 	const ATOM_PPLIB_POWERPLAYTABLE *table =
1549 					     get_powerplay_table(hwmgr);
1550 	const ATOM_PPLIB_VCE_State_Table *vce_table =
1551 				    get_vce_state_table(hwmgr, table);
1552 
1553 	if (vce_table)
1554 		return vce_table->numEntries;
1555 
1556 	return 0;
1557 }
1558 
get_vce_state_table_entry(struct pp_hwmgr * hwmgr,unsigned long i,struct amd_vce_state * vce_state,void ** clock_info,unsigned long * flag)1559 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1560 							unsigned long i,
1561 							struct amd_vce_state *vce_state,
1562 							void **clock_info,
1563 							unsigned long *flag)
1564 {
1565 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1566 
1567 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1568 
1569 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1570 
1571 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1572 
1573 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1574 								le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1575 
1576 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1577 
1578 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1579 
1580 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1581 
1582 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1583 
1584 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1585 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1586 
1587 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1588 
1589 	return 0;
1590 }
1591 
1592 
pp_tables_initialize(struct pp_hwmgr * hwmgr)1593 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1594 {
1595 	int result;
1596 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1597 
1598 	if (hwmgr->chip_id == CHIP_RAVEN)
1599 		return 0;
1600 
1601 	hwmgr->need_pp_table_upload = true;
1602 
1603 	powerplay_table = get_powerplay_table(hwmgr);
1604 
1605 	result = init_powerplay_tables(hwmgr, powerplay_table);
1606 
1607 	PP_ASSERT_WITH_CODE((result == 0),
1608 			    "init_powerplay_tables failed", return result);
1609 
1610 	result = set_platform_caps(hwmgr,
1611 				le32_to_cpu(powerplay_table->ulPlatformCaps));
1612 
1613 	PP_ASSERT_WITH_CODE((result == 0),
1614 			    "set_platform_caps failed", return result);
1615 
1616 	result = init_thermal_controller(hwmgr, powerplay_table);
1617 
1618 	PP_ASSERT_WITH_CODE((result == 0),
1619 			    "init_thermal_controller failed", return result);
1620 
1621 	result = init_overdrive_limits(hwmgr, powerplay_table);
1622 
1623 	PP_ASSERT_WITH_CODE((result == 0),
1624 			    "init_overdrive_limits failed", return result);
1625 
1626 	result = init_clock_voltage_dependency(hwmgr,
1627 					       powerplay_table);
1628 
1629 	PP_ASSERT_WITH_CODE((result == 0),
1630 			    "init_clock_voltage_dependency failed", return result);
1631 
1632 	result = init_dpm2_parameters(hwmgr, powerplay_table);
1633 
1634 	PP_ASSERT_WITH_CODE((result == 0),
1635 			    "init_dpm2_parameters failed", return result);
1636 
1637 	result = init_phase_shedding_table(hwmgr, powerplay_table);
1638 
1639 	PP_ASSERT_WITH_CODE((result == 0),
1640 			    "init_phase_shedding_table failed", return result);
1641 
1642 	return result;
1643 }
1644 
pp_tables_uninitialize(struct pp_hwmgr * hwmgr)1645 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1646 {
1647 	if (hwmgr->chip_id == CHIP_RAVEN)
1648 		return 0;
1649 
1650 	kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1651 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1652 
1653 	kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1654 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1655 
1656 	kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1657 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1658 
1659 	kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1660 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1661 
1662 	kfree(hwmgr->dyn_state.valid_mclk_values);
1663 	hwmgr->dyn_state.valid_mclk_values = NULL;
1664 
1665 	kfree(hwmgr->dyn_state.valid_sclk_values);
1666 	hwmgr->dyn_state.valid_sclk_values = NULL;
1667 
1668 	kfree(hwmgr->dyn_state.cac_leakage_table);
1669 	hwmgr->dyn_state.cac_leakage_table = NULL;
1670 
1671 	kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1672 	hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1673 
1674 	kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1675 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1676 
1677 	kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1678 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1679 
1680 	kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1681 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1682 
1683 	kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1684 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1685 
1686 	kfree(hwmgr->dyn_state.cac_dtp_table);
1687 	hwmgr->dyn_state.cac_dtp_table = NULL;
1688 
1689 	kfree(hwmgr->dyn_state.ppm_parameter_table);
1690 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1691 
1692 	kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1693 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1694 
1695 	return 0;
1696 }
1697 
1698 const struct pp_table_func pptable_funcs = {
1699 	.pptable_init = pp_tables_initialize,
1700 	.pptable_fini = pp_tables_uninitialize,
1701 	.pptable_get_number_of_vce_state_table_entries =
1702 				get_number_of_vce_state_table_entries,
1703 	.pptable_get_vce_state_table_entry =
1704 						get_vce_state_table_entry,
1705 };
1706 
1707