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