• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 #include "pp_debug.h"
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 
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 
get_powerplay_table(struct pp_hwmgr * hwmgr)794 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
795 				     struct pp_hwmgr *hwmgr)
796 {
797 	const void *table_addr = hwmgr->soft_pp_table;
798 	uint8_t frev, crev;
799 	uint16_t size;
800 
801 	if (!table_addr) {
802 		table_addr = cgs_atom_get_data_table(hwmgr->device,
803 				GetIndexIntoMasterTable(DATA, PowerPlayInfo),
804 				&size, &frev, &crev);
805 
806 		hwmgr->soft_pp_table = table_addr;
807 		hwmgr->soft_pp_table_size = size;
808 	}
809 
810 	return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
811 }
812 
pp_tables_get_response_times(struct pp_hwmgr * hwmgr,uint32_t * vol_rep_time,uint32_t * bb_rep_time)813 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
814 				uint32_t *vol_rep_time, uint32_t *bb_rep_time)
815 {
816 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
817 
818 	PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
819 			    "Missing PowerPlay Table!", return -EINVAL);
820 
821 	*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
822 	*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
823 
824 	return 0;
825 }
826 
pp_tables_get_num_of_entries(struct pp_hwmgr * hwmgr,unsigned long * num_of_entries)827 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
828 				     unsigned long *num_of_entries)
829 {
830 	const StateArray *pstate_arrays;
831 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
832 
833 	if (powerplay_table == NULL)
834 		return -1;
835 
836 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
837 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
838 					le16_to_cpu(powerplay_table->usStateArrayOffset));
839 
840 		*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
841 	} else
842 		*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
843 
844 	return 0;
845 }
846 
pp_tables_get_entry(struct pp_hwmgr * hwmgr,unsigned long entry_index,struct pp_power_state * ps,pp_tables_hw_clock_info_callback func)847 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
848 				unsigned long entry_index,
849 				struct pp_power_state *ps,
850 			 pp_tables_hw_clock_info_callback func)
851 {
852 	int i;
853 	const StateArray *pstate_arrays;
854 	const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
855 	const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
856 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
857 	int result = 0;
858 	int res = 0;
859 
860 	const ClockInfoArray *pclock_arrays;
861 
862 	const NonClockInfoArray *pnon_clock_arrays;
863 
864 	const ATOM_PPLIB_STATE *pstate_entry;
865 
866 	if (powerplay_table == NULL)
867 		return -1;
868 
869 	ps->classification.bios_index = entry_index;
870 
871 	if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
872 		pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
873 					le16_to_cpu(powerplay_table->usStateArrayOffset));
874 
875 		if (entry_index > pstate_arrays->ucNumEntries)
876 			return -1;
877 
878 		pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
879 		pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
880 					le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
881 
882 		pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
883 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
884 
885 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
886 					(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
887 
888 		result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
889 
890 		for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
891 			const void *pclock_info = (const void *)(
892 							(unsigned long)(pclock_arrays->clockInfo) +
893 							(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
894 			res = func(hwmgr, &ps->hardware, i, pclock_info);
895 			if ((0 == result) && (0 != res))
896 				result = res;
897 		}
898 	} else {
899 		if (entry_index > powerplay_table->ucNumStates)
900 			return -1;
901 
902 		pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + powerplay_table->usStateArrayOffset +
903 				entry_index * powerplay_table->ucStateEntrySize);
904 
905 		pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
906 						le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
907 						pstate_entry->ucNonClockStateIndex *
908 						powerplay_table->ucNonClockSize);
909 
910 		result = init_non_clock_fields(hwmgr, ps,
911 							powerplay_table->ucNonClockSize,
912 							pnon_clock_info);
913 
914 		for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
915 			const void *pclock_info = (const void *)((unsigned long)powerplay_table +
916 						le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
917 						pstate_entry->ucClockStateIndices[i] *
918 						powerplay_table->ucClockInfoSize);
919 
920 			int res = func(hwmgr, &ps->hardware, i, pclock_info);
921 
922 			if ((0 == result) && (0 != res))
923 					result = res;
924 		}
925 	}
926 
927 	if ((0 == result) &&
928 		(0 != (ps->classification.flags & PP_StateClassificationFlag_Boot)))
929 		result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
930 
931 	return result;
932 }
933 
934 
935 
init_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)936 static int init_powerplay_tables(
937 			struct pp_hwmgr *hwmgr,
938 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
939 )
940 {
941 	return 0;
942 }
943 
944 
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)945 static int init_thermal_controller(
946 			struct pp_hwmgr *hwmgr,
947 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
948 {
949 	return 0;
950 }
951 
init_overdrive_limits_V1_4(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V1_4 * fw_info)952 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
953 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
954 			const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
955 {
956 	hwmgr->platform_descriptor.overdriveLimit.engineClock =
957 				le32_to_cpu(fw_info->ulASICMaxEngineClock);
958 
959 	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
960 				le32_to_cpu(fw_info->ulASICMaxMemoryClock);
961 
962 	hwmgr->platform_descriptor.maxOverdriveVDDC =
963 		le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
964 
965 	hwmgr->platform_descriptor.minOverdriveVDDC =
966 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
967 
968 	hwmgr->platform_descriptor.maxOverdriveVDDC =
969 			   le16_to_cpu(fw_info->usBootUpVDDCVoltage);
970 
971 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
972 	return 0;
973 }
974 
init_overdrive_limits_V2_1(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V2_1 * fw_info)975 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
976 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
977 			const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
978 {
979 	const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
980 	const ATOM_PPLIB_EXTENDEDHEADER *header;
981 
982 	if (le16_to_cpu(powerplay_table->usTableSize) <
983 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
984 		return 0;
985 
986 	powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
987 
988 	if (0 == powerplay_table3->usExtendendedHeaderOffset)
989 		return 0;
990 
991 	header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
992 			le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
993 
994 	hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
995 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
996 
997 
998 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
999 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1000 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1001 
1002 	return 0;
1003 }
1004 
init_overdrive_limits(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1005 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1006 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1007 {
1008 	int result;
1009 	uint8_t frev, crev;
1010 	uint16_t size;
1011 
1012 	const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1013 
1014 	hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1015 	hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1016 	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1017 	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1018 	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1019 
1020 	if (hwmgr->chip_id == CHIP_RAVEN)
1021 		return 0;
1022 
1023 	/* We assume here that fw_info is unchanged if this call fails.*/
1024 	fw_info = cgs_atom_get_data_table(hwmgr->device,
1025 			 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1026 			 &size, &frev, &crev);
1027 
1028 	if ((fw_info->ucTableFormatRevision == 1)
1029 		&& (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1030 		result = init_overdrive_limits_V1_4(hwmgr,
1031 				powerplay_table,
1032 				(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1033 
1034 	else if ((fw_info->ucTableFormatRevision == 2)
1035 		&& (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1036 		result = init_overdrive_limits_V2_1(hwmgr,
1037 				powerplay_table,
1038 				(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1039 
1040 	if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0
1041 		&& hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0
1042 		&& !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1043 			PHM_PlatformCaps_OverdriveDisabledByPowerBudget))
1044 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1045 				PHM_PlatformCaps_ACOverdriveSupport);
1046 
1047 	return result;
1048 }
1049 
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)1050 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1051 		struct phm_uvd_clock_voltage_dependency_table **ptable,
1052 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1053 		const UVDClockInfoArray *array)
1054 {
1055 	unsigned long table_size, i;
1056 	struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1057 
1058 	table_size = sizeof(unsigned long) +
1059 		 sizeof(struct phm_uvd_clock_voltage_dependency_table) *
1060 		 table->numEntries;
1061 
1062 	uvd_table = kzalloc(table_size, GFP_KERNEL);
1063 	if (NULL == uvd_table)
1064 		return -ENOMEM;
1065 
1066 	uvd_table->count = table->numEntries;
1067 
1068 	for (i = 0; i < table->numEntries; i++) {
1069 		const UVDClockInfo *entry =
1070 			&array->entries[table->entries[i].ucUVDClockInfoIndex];
1071 		uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1072 		uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1073 					 | le16_to_cpu(entry->usVClkLow);
1074 		uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1075 					 | le16_to_cpu(entry->usDClkLow);
1076 	}
1077 
1078 	*ptable = uvd_table;
1079 
1080 	return 0;
1081 }
1082 
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)1083 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1084 		struct phm_vce_clock_voltage_dependency_table **ptable,
1085 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1086 		const VCEClockInfoArray    *array)
1087 {
1088 	unsigned long table_size, i;
1089 	struct phm_vce_clock_voltage_dependency_table *vce_table = NULL;
1090 
1091 	table_size = sizeof(unsigned long) +
1092 			sizeof(struct phm_vce_clock_voltage_dependency_table)
1093 			* table->numEntries;
1094 
1095 	vce_table = kzalloc(table_size, GFP_KERNEL);
1096 	if (NULL == vce_table)
1097 		return -ENOMEM;
1098 
1099 	vce_table->count = table->numEntries;
1100 	for (i = 0; i < table->numEntries; i++) {
1101 		const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1102 
1103 		vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1104 		vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1105 					| le16_to_cpu(entry->usEVClkLow);
1106 		vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1107 					| le16_to_cpu(entry->usECClkLow);
1108 	}
1109 
1110 	*ptable = vce_table;
1111 
1112 	return 0;
1113 }
1114 
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)1115 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1116 		 struct phm_samu_clock_voltage_dependency_table **ptable,
1117 		 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1118 {
1119 	unsigned long table_size, i;
1120 	struct phm_samu_clock_voltage_dependency_table *samu_table;
1121 
1122 	table_size = sizeof(unsigned long) +
1123 		sizeof(struct phm_samu_clock_voltage_dependency_table) *
1124 		table->numEntries;
1125 
1126 	samu_table = kzalloc(table_size, GFP_KERNEL);
1127 	if (NULL == samu_table)
1128 		return -ENOMEM;
1129 
1130 	samu_table->count = table->numEntries;
1131 
1132 	for (i = 0; i < table->numEntries; i++) {
1133 		samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1134 		samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1135 					 | le16_to_cpu(table->entries[i].usSAMClockLow);
1136 	}
1137 
1138 	*ptable = samu_table;
1139 
1140 	return 0;
1141 }
1142 
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)1143 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1144 		struct phm_acp_clock_voltage_dependency_table **ptable,
1145 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1146 {
1147 	unsigned table_size, i;
1148 	struct phm_acp_clock_voltage_dependency_table *acp_table;
1149 
1150 	table_size = sizeof(unsigned long) +
1151 		sizeof(struct phm_acp_clock_voltage_dependency_table) *
1152 		table->numEntries;
1153 
1154 	acp_table = kzalloc(table_size, GFP_KERNEL);
1155 	if (NULL == acp_table)
1156 		return -ENOMEM;
1157 
1158 	acp_table->count = (unsigned long)table->numEntries;
1159 
1160 	for (i = 0; i < table->numEntries; i++) {
1161 		acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1162 		acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1163 					 | le16_to_cpu(table->entries[i].usACPClockLow);
1164 	}
1165 
1166 	*ptable = acp_table;
1167 
1168 	return 0;
1169 }
1170 
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1171 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1172 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1173 {
1174 	ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1175 	ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1176 	int result = 0;
1177 
1178 	uint16_t vce_clock_info_array_offset;
1179 	uint16_t uvd_clock_info_array_offset;
1180 	uint16_t table_offset;
1181 
1182 	hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1183 	hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1184 	hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1185 	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1186 	hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1187 	hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1188 	hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1189 	hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1190 	hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1191 	hwmgr->dyn_state.ppm_parameter_table = NULL;
1192 	hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1193 
1194 	vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1195 						hwmgr, powerplay_table);
1196 	table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1197 						powerplay_table);
1198 	if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1199 		const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1200 				(((unsigned long) powerplay_table) +
1201 				vce_clock_info_array_offset);
1202 		const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1203 				(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1204 				(((unsigned long) powerplay_table) + table_offset);
1205 		result = get_vce_clock_voltage_limit_table(hwmgr,
1206 				&hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1207 				table, array);
1208 	}
1209 
1210 	uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1211 	table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1212 
1213 	if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1214 		const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1215 				(((unsigned long) powerplay_table) +
1216 				uvd_clock_info_array_offset);
1217 		const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1218 				(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1219 				(((unsigned long) powerplay_table) + table_offset);
1220 		result = get_uvd_clock_voltage_limit_table(hwmgr,
1221 				&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1222 	}
1223 
1224 	table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1225 							    powerplay_table);
1226 
1227 	if (table_offset > 0) {
1228 		const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1229 				(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1230 				(((unsigned long) powerplay_table) + table_offset);
1231 		result = get_samu_clock_voltage_limit_table(hwmgr,
1232 				&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1233 	}
1234 
1235 	table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1236 							     powerplay_table);
1237 
1238 	if (table_offset > 0) {
1239 		const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1240 				(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1241 				(((unsigned long) powerplay_table) + table_offset);
1242 		result = get_acp_clock_voltage_limit_table(hwmgr,
1243 				&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1244 	}
1245 
1246 	table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1247 	if (table_offset > 0) {
1248 		UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1249 
1250 		if (rev_id > 0) {
1251 			const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1252 				(const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1253 				(((unsigned long) powerplay_table) + table_offset);
1254 			result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1255 				&tune_table->power_tune_table,
1256 				le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1257 			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1258 				le16_to_cpu(tune_table->usTjMax);
1259 		} else {
1260 			const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1261 				(const ATOM_PPLIB_POWERTUNE_Table *)
1262 				(((unsigned long) powerplay_table) + table_offset);
1263 			result = get_cac_tdp_table(hwmgr,
1264 				&hwmgr->dyn_state.cac_dtp_table,
1265 				&tune_table->power_tune_table, 255);
1266 		}
1267 	}
1268 
1269 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1270 		sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1271 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1272 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1273 		if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1274 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1275 				(((unsigned long) powerplay_table4) +
1276 				powerplay_table4->usVddcDependencyOnSCLKOffset);
1277 			result = get_clock_voltage_dependency_table(hwmgr,
1278 				&hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1279 		}
1280 
1281 		if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1282 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1283 				(((unsigned long) powerplay_table4) +
1284 				powerplay_table4->usVddciDependencyOnMCLKOffset);
1285 			result = get_clock_voltage_dependency_table(hwmgr,
1286 				&hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1287 		}
1288 
1289 		if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1290 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1291 				(((unsigned long) powerplay_table4) +
1292 				powerplay_table4->usVddcDependencyOnMCLKOffset);
1293 			result = get_clock_voltage_dependency_table(hwmgr,
1294 				&hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1295 		}
1296 
1297 		if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1298 			limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1299 				(((unsigned long) powerplay_table4) +
1300 				powerplay_table4->usMaxClockVoltageOnDCOffset);
1301 			result = get_clock_voltage_limit(hwmgr,
1302 				&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1303 		}
1304 
1305 		if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1306 			(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1307 			result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1308 					hwmgr->dyn_state.vddc_dependency_on_mclk);
1309 
1310 		if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1311 			(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1312 			result = get_valid_clk(hwmgr,
1313 				&hwmgr->dyn_state.valid_sclk_values,
1314 				hwmgr->dyn_state.vddc_dependency_on_sclk);
1315 
1316 		if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1317 			table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1318 				(((unsigned long) powerplay_table4) +
1319 				powerplay_table4->usMvddDependencyOnMCLKOffset);
1320 			result = get_clock_voltage_dependency_table(hwmgr,
1321 				&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1322 		}
1323 	}
1324 
1325 	table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1326 								powerplay_table);
1327 
1328 	if (table_offset > 0) {
1329 		table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1330 			(((unsigned long) powerplay_table) + table_offset);
1331 		result = get_clock_voltage_dependency_table(hwmgr,
1332 			&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1333 	}
1334 
1335 	return result;
1336 }
1337 
get_cac_leakage_table(struct pp_hwmgr * hwmgr,struct phm_cac_leakage_table ** ptable,const ATOM_PPLIB_CAC_Leakage_Table * table)1338 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1339 				 struct phm_cac_leakage_table **ptable,
1340 				const ATOM_PPLIB_CAC_Leakage_Table *table)
1341 {
1342 	struct phm_cac_leakage_table  *cac_leakage_table;
1343 	unsigned long            table_size, i;
1344 
1345 	if (hwmgr == NULL || table == NULL || ptable == NULL)
1346 		return -EINVAL;
1347 
1348 	table_size = sizeof(ULONG) +
1349 		(sizeof(struct phm_cac_leakage_table) * table->ucNumEntries);
1350 
1351 	cac_leakage_table = kzalloc(table_size, GFP_KERNEL);
1352 
1353 	if (cac_leakage_table == NULL)
1354 		return -ENOMEM;
1355 
1356 	cac_leakage_table->count = (ULONG)table->ucNumEntries;
1357 
1358 	for (i = 0; i < cac_leakage_table->count; i++) {
1359 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1360 				PHM_PlatformCaps_EVV)) {
1361 			cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1362 			cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1363 			cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1364 		} else {
1365 			cac_leakage_table->entries[i].Vddc    = le16_to_cpu(table->entries[i].usVddc);
1366 			cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1367 		}
1368 	}
1369 
1370 	*ptable = cac_leakage_table;
1371 
1372 	return 0;
1373 }
1374 
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_PPLIB_PPM_Table * atom_ppm_table)1375 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1376 			ATOM_PPLIB_PPM_Table *atom_ppm_table)
1377 {
1378 	struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);
1379 
1380 	if (NULL == ptr)
1381 		return -ENOMEM;
1382 
1383 	ptr->ppm_design            = atom_ppm_table->ucPpmDesign;
1384 	ptr->cpu_core_number        = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1385 	ptr->platform_tdp          = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1386 	ptr->small_ac_platform_tdp   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1387 	ptr->platform_tdc          = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1388 	ptr->small_ac_platform_tdc   = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1389 	ptr->apu_tdp               = le32_to_cpu(atom_ppm_table->ulApuTDP);
1390 	ptr->dgpu_tdp              = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1391 	ptr->dgpu_ulv_power         = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1392 	ptr->tj_max                = le32_to_cpu(atom_ppm_table->ulTjmax);
1393 	hwmgr->dyn_state.ppm_parameter_table = ptr;
1394 
1395 	return 0;
1396 }
1397 
init_dpm2_parameters(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1398 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1399 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1400 {
1401 	int result = 0;
1402 
1403 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1404 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1405 		const  ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1406 				(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1407 		const  ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1408 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)
1409 				(&ptable5->basicTable4);
1410 		const  ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1411 				(const ATOM_PPLIB_POWERPLAYTABLE3 *)
1412 				(&ptable4->basicTable3);
1413 		const  ATOM_PPLIB_EXTENDEDHEADER  *extended_header;
1414 		uint16_t table_offset;
1415 		ATOM_PPLIB_PPM_Table *atom_ppm_table;
1416 
1417 		hwmgr->platform_descriptor.TDPLimit     = le32_to_cpu(ptable5->ulTDPLimit);
1418 		hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1419 
1420 		hwmgr->platform_descriptor.TDPODLimit   = le16_to_cpu(ptable5->usTDPODLimit);
1421 		hwmgr->platform_descriptor.TDPAdjustment = 0;
1422 
1423 		hwmgr->platform_descriptor.VidAdjustment = 0;
1424 		hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1425 		hwmgr->platform_descriptor.VidMinLimit     = 0;
1426 		hwmgr->platform_descriptor.VidMaxLimit     = 1500000;
1427 		hwmgr->platform_descriptor.VidStep         = 6250;
1428 
1429 		hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1430 
1431 		if (hwmgr->platform_descriptor.TDPODLimit != 0)
1432 			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1433 					PHM_PlatformCaps_PowerControl);
1434 
1435 		hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1436 
1437 		hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1438 
1439 		hwmgr->dyn_state.cac_leakage_table = NULL;
1440 
1441 		if (0 != ptable5->usCACLeakageTableOffset) {
1442 			const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1443 				(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1444 				le16_to_cpu(ptable5->usCACLeakageTableOffset));
1445 			result = get_cac_leakage_table(hwmgr,
1446 				&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1447 		}
1448 
1449 		hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1450 
1451 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1452 
1453 		if (0 != ptable3->usExtendendedHeaderOffset) {
1454 			extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1455 					(((unsigned long)powerplay_table) +
1456 					le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1457 			if ((extended_header->usPPMTableOffset > 0) &&
1458 				le16_to_cpu(extended_header->usSize) >=
1459 				    SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1460 				table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1461 				atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1462 					(((unsigned long)powerplay_table) + table_offset);
1463 				if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1464 					phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1465 						PHM_PlatformCaps_EnablePlatformPowerManagement);
1466 			}
1467 		}
1468 	}
1469 	return result;
1470 }
1471 
init_phase_shedding_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1472 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1473 		const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1474 {
1475 	if (le16_to_cpu(powerplay_table->usTableSize) >=
1476 	    sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1477 		const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1478 				(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1479 
1480 		if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1481 			const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1482 				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
1483 				(((unsigned long)powerplay_table4) +
1484 				le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1485 			struct phm_phase_shedding_limits_table *table;
1486 			unsigned long size, i;
1487 
1488 
1489 			size = sizeof(unsigned long) +
1490 				(sizeof(struct phm_phase_shedding_limits_table) *
1491 				ptable->ucNumEntries);
1492 
1493 			table = kzalloc(size, GFP_KERNEL);
1494 
1495 			if (table == NULL)
1496 				return -ENOMEM;
1497 
1498 			table->count = (unsigned long)ptable->ucNumEntries;
1499 
1500 			for (i = 0; i < table->count; i++) {
1501 				table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1502 				table->entries[i].Sclk    = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1503 							| le16_to_cpu(ptable->entries[i].usSclkLow);
1504 				table->entries[i].Mclk    = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1505 							| le16_to_cpu(ptable->entries[i].usMclkLow);
1506 			}
1507 			hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1508 		}
1509 	}
1510 
1511 	return 0;
1512 }
1513 
get_number_of_vce_state_table_entries(struct pp_hwmgr * hwmgr)1514 static int get_number_of_vce_state_table_entries(
1515 						  struct pp_hwmgr *hwmgr)
1516 {
1517 	const ATOM_PPLIB_POWERPLAYTABLE *table =
1518 					     get_powerplay_table(hwmgr);
1519 	const ATOM_PPLIB_VCE_State_Table *vce_table =
1520 				    get_vce_state_table(hwmgr, table);
1521 
1522 	if (vce_table)
1523 		return vce_table->numEntries;
1524 
1525 	return 0;
1526 }
1527 
get_vce_state_table_entry(struct pp_hwmgr * hwmgr,unsigned long i,struct amd_vce_state * vce_state,void ** clock_info,unsigned long * flag)1528 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1529 							unsigned long i,
1530 							struct amd_vce_state *vce_state,
1531 							void **clock_info,
1532 							unsigned long *flag)
1533 {
1534 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1535 
1536 	const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1537 
1538 	unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1539 
1540 	const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1541 
1542 	const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset);
1543 
1544 	const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1545 
1546 	const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1547 
1548 	unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1549 
1550 	*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1551 
1552 	vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow;
1553 	vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow;
1554 
1555 	*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1556 
1557 	return 0;
1558 }
1559 
1560 
pp_tables_initialize(struct pp_hwmgr * hwmgr)1561 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1562 {
1563 	int result;
1564 	const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1565 
1566 	if (hwmgr->chip_id == CHIP_RAVEN)
1567 		return 0;
1568 
1569 	hwmgr->need_pp_table_upload = true;
1570 
1571 	powerplay_table = get_powerplay_table(hwmgr);
1572 
1573 	result = init_powerplay_tables(hwmgr, powerplay_table);
1574 
1575 	PP_ASSERT_WITH_CODE((result == 0),
1576 			    "init_powerplay_tables failed", return result);
1577 
1578 	result = set_platform_caps(hwmgr,
1579 				le32_to_cpu(powerplay_table->ulPlatformCaps));
1580 
1581 	PP_ASSERT_WITH_CODE((result == 0),
1582 			    "set_platform_caps failed", return result);
1583 
1584 	result = init_thermal_controller(hwmgr, powerplay_table);
1585 
1586 	PP_ASSERT_WITH_CODE((result == 0),
1587 			    "init_thermal_controller failed", return result);
1588 
1589 	result = init_overdrive_limits(hwmgr, powerplay_table);
1590 
1591 	PP_ASSERT_WITH_CODE((result == 0),
1592 			    "init_overdrive_limits failed", return result);
1593 
1594 	result = init_clock_voltage_dependency(hwmgr,
1595 					       powerplay_table);
1596 
1597 	PP_ASSERT_WITH_CODE((result == 0),
1598 			    "init_clock_voltage_dependency failed", return result);
1599 
1600 	result = init_dpm2_parameters(hwmgr, powerplay_table);
1601 
1602 	PP_ASSERT_WITH_CODE((result == 0),
1603 			    "init_dpm2_parameters failed", return result);
1604 
1605 	result = init_phase_shedding_table(hwmgr, powerplay_table);
1606 
1607 	PP_ASSERT_WITH_CODE((result == 0),
1608 			    "init_phase_shedding_table failed", return result);
1609 
1610 	return result;
1611 }
1612 
pp_tables_uninitialize(struct pp_hwmgr * hwmgr)1613 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1614 {
1615 	if (hwmgr->chip_id == CHIP_RAVEN)
1616 		return 0;
1617 
1618 	if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) {
1619 		kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1620 		hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1621 	}
1622 
1623 	if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) {
1624 		kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1625 		hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1626 	}
1627 
1628 	if (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) {
1629 		kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1630 		hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1631 	}
1632 
1633 	if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) {
1634 		kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1635 		hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1636 	}
1637 
1638 	if (NULL != hwmgr->dyn_state.valid_mclk_values) {
1639 		kfree(hwmgr->dyn_state.valid_mclk_values);
1640 		hwmgr->dyn_state.valid_mclk_values = NULL;
1641 	}
1642 
1643 	if (NULL != hwmgr->dyn_state.valid_sclk_values) {
1644 		kfree(hwmgr->dyn_state.valid_sclk_values);
1645 		hwmgr->dyn_state.valid_sclk_values = NULL;
1646 	}
1647 
1648 	if (NULL != hwmgr->dyn_state.cac_leakage_table) {
1649 		kfree(hwmgr->dyn_state.cac_leakage_table);
1650 		hwmgr->dyn_state.cac_leakage_table = NULL;
1651 	}
1652 
1653 	if (NULL != hwmgr->dyn_state.vddc_phase_shed_limits_table) {
1654 		kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1655 		hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1656 	}
1657 
1658 	if (NULL != hwmgr->dyn_state.vce_clock_voltage_dependency_table) {
1659 		kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1660 		hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1661 	}
1662 
1663 	if (NULL != hwmgr->dyn_state.uvd_clock_voltage_dependency_table) {
1664 		kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1665 		hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1666 	}
1667 
1668 	if (NULL != hwmgr->dyn_state.samu_clock_voltage_dependency_table) {
1669 		kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1670 		hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1671 	}
1672 
1673 	if (NULL != hwmgr->dyn_state.acp_clock_voltage_dependency_table) {
1674 		kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1675 		hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1676 	}
1677 
1678 	if (NULL != hwmgr->dyn_state.cac_dtp_table) {
1679 		kfree(hwmgr->dyn_state.cac_dtp_table);
1680 		hwmgr->dyn_state.cac_dtp_table = NULL;
1681 	}
1682 
1683 	if (NULL != hwmgr->dyn_state.ppm_parameter_table) {
1684 		kfree(hwmgr->dyn_state.ppm_parameter_table);
1685 		hwmgr->dyn_state.ppm_parameter_table = NULL;
1686 	}
1687 
1688 	if (NULL != hwmgr->dyn_state.vdd_gfx_dependency_on_sclk) {
1689 		kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1690 		hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1691 	}
1692 
1693 	if (NULL != hwmgr->dyn_state.vq_budgeting_table) {
1694 		kfree(hwmgr->dyn_state.vq_budgeting_table);
1695 		hwmgr->dyn_state.vq_budgeting_table = NULL;
1696 	}
1697 
1698 	return 0;
1699 }
1700 
1701 const struct pp_table_func pptable_funcs = {
1702 	.pptable_init = pp_tables_initialize,
1703 	.pptable_fini = pp_tables_uninitialize,
1704 	.pptable_get_number_of_vce_state_table_entries =
1705 				get_number_of_vce_state_table_entries,
1706 	.pptable_get_vce_state_table_entry =
1707 						get_vce_state_table_entry,
1708 };
1709 
1710