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