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 i;
383 struct phm_clock_voltage_dependency_table *dep_table;
384
385 dep_table = kzalloc_flex(*dep_table, entries, table->ucNumEntries);
386 if (NULL == dep_table)
387 return -ENOMEM;
388
389 dep_table->count = (unsigned long)table->ucNumEntries;
390
391 for (i = 0; i < dep_table->count; i++) {
392 dep_table->entries[i].clk =
393 ((unsigned long)table->entries[i].ucClockHigh << 16) |
394 le16_to_cpu(table->entries[i].usClockLow);
395 dep_table->entries[i].v =
396 (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
397 }
398
399 *ptable = dep_table;
400
401 return 0;
402 }
403
get_valid_clk(struct pp_hwmgr * hwmgr,struct phm_clock_array ** ptable,const struct phm_clock_voltage_dependency_table * table)404 static int get_valid_clk(struct pp_hwmgr *hwmgr,
405 struct phm_clock_array **ptable,
406 const struct phm_clock_voltage_dependency_table *table)
407 {
408 unsigned long i;
409 struct phm_clock_array *clock_table;
410
411 clock_table = kzalloc_flex(*clock_table, values, table->count);
412 if (!clock_table)
413 return -ENOMEM;
414
415 clock_table->count = (unsigned long)table->count;
416
417 for (i = 0; i < clock_table->count; i++)
418 clock_table->values[i] = (unsigned long)table->entries[i].clk;
419
420 *ptable = clock_table;
421
422 return 0;
423 }
424
get_clock_voltage_limit(struct pp_hwmgr * hwmgr,struct phm_clock_and_voltage_limits * limits,const ATOM_PPLIB_Clock_Voltage_Limit_Table * table)425 static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,
426 struct phm_clock_and_voltage_limits *limits,
427 const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)
428 {
429 limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |
430 le16_to_cpu(table->entries[0].usSclkLow);
431 limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |
432 le16_to_cpu(table->entries[0].usMclkLow);
433 limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);
434 limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);
435
436 return 0;
437 }
438
439
set_hw_cap(struct pp_hwmgr * hwmgr,bool enable,enum phm_platform_caps cap)440 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
441 enum phm_platform_caps cap)
442 {
443 if (enable)
444 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
445 else
446 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
447 }
448
set_platform_caps(struct pp_hwmgr * hwmgr,unsigned long powerplay_caps)449 static int set_platform_caps(struct pp_hwmgr *hwmgr,
450 unsigned long powerplay_caps)
451 {
452 set_hw_cap(
453 hwmgr,
454 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),
455 PHM_PlatformCaps_PowerPlaySupport
456 );
457
458 set_hw_cap(
459 hwmgr,
460 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
461 PHM_PlatformCaps_BiosPowerSourceControl
462 );
463
464 set_hw_cap(
465 hwmgr,
466 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),
467 PHM_PlatformCaps_EnableASPML0s
468 );
469
470 set_hw_cap(
471 hwmgr,
472 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),
473 PHM_PlatformCaps_EnableASPML1
474 );
475
476 set_hw_cap(
477 hwmgr,
478 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),
479 PHM_PlatformCaps_EnableBackbias
480 );
481
482 set_hw_cap(
483 hwmgr,
484 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),
485 PHM_PlatformCaps_AutomaticDCTransition
486 );
487
488 set_hw_cap(
489 hwmgr,
490 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),
491 PHM_PlatformCaps_GeminiPrimary
492 );
493
494 set_hw_cap(
495 hwmgr,
496 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),
497 PHM_PlatformCaps_StepVddc
498 );
499
500 set_hw_cap(
501 hwmgr,
502 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),
503 PHM_PlatformCaps_EnableVoltageControl
504 );
505
506 set_hw_cap(
507 hwmgr,
508 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),
509 PHM_PlatformCaps_EnableSideportControl
510 );
511
512 set_hw_cap(
513 hwmgr,
514 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),
515 PHM_PlatformCaps_TurnOffPll_ASPML1
516 );
517
518 set_hw_cap(
519 hwmgr,
520 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),
521 PHM_PlatformCaps_EnableHTLinkControl
522 );
523
524 set_hw_cap(
525 hwmgr,
526 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),
527 PHM_PlatformCaps_EnableMVDDControl
528 );
529
530 set_hw_cap(
531 hwmgr,
532 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),
533 PHM_PlatformCaps_ControlVDDCI
534 );
535
536 set_hw_cap(
537 hwmgr,
538 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),
539 PHM_PlatformCaps_RegulatorHot
540 );
541
542 set_hw_cap(
543 hwmgr,
544 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),
545 PHM_PlatformCaps_BootStateOnAlert
546 );
547
548 set_hw_cap(
549 hwmgr,
550 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),
551 PHM_PlatformCaps_DontWaitForVBlankOnAlert
552 );
553
554 set_hw_cap(
555 hwmgr,
556 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),
557 PHM_PlatformCaps_BACO
558 );
559
560 set_hw_cap(
561 hwmgr,
562 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),
563 PHM_PlatformCaps_NewCACVoltage
564 );
565
566 set_hw_cap(
567 hwmgr,
568 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),
569 PHM_PlatformCaps_RevertGPIO5Polarity
570 );
571
572 set_hw_cap(
573 hwmgr,
574 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),
575 PHM_PlatformCaps_Thermal2GPIO17
576 );
577
578 set_hw_cap(
579 hwmgr,
580 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),
581 PHM_PlatformCaps_VRHotGPIOConfigurable
582 );
583
584 set_hw_cap(
585 hwmgr,
586 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),
587 PHM_PlatformCaps_TempInversion
588 );
589
590 set_hw_cap(
591 hwmgr,
592 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),
593 PHM_PlatformCaps_EVV
594 );
595
596 set_hw_cap(
597 hwmgr,
598 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
599 PHM_PlatformCaps_CombinePCCWithThermalSignal
600 );
601
602 set_hw_cap(
603 hwmgr,
604 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
605 PHM_PlatformCaps_LoadPostProductionFirmware
606 );
607
608 set_hw_cap(
609 hwmgr,
610 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),
611 PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
612 );
613
614 return 0;
615 }
616
make_classification_flags(struct pp_hwmgr * hwmgr,USHORT classification,USHORT classification2)617 static PP_StateClassificationFlags make_classification_flags(
618 struct pp_hwmgr *hwmgr,
619 USHORT classification,
620 USHORT classification2)
621 {
622 PP_StateClassificationFlags result = 0;
623
624 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
625 result |= PP_StateClassificationFlag_Boot;
626
627 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
628 result |= PP_StateClassificationFlag_Thermal;
629
630 if (classification &
631 ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
632 result |= PP_StateClassificationFlag_LimitedPowerSource;
633
634 if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
635 result |= PP_StateClassificationFlag_Rest;
636
637 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
638 result |= PP_StateClassificationFlag_Forced;
639
640 if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
641 result |= PP_StateClassificationFlag_3DPerformance;
642
643
644 if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
645 result |= PP_StateClassificationFlag_ACOverdriveTemplate;
646
647 if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
648 result |= PP_StateClassificationFlag_Uvd;
649
650 if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
651 result |= PP_StateClassificationFlag_UvdHD;
652
653 if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
654 result |= PP_StateClassificationFlag_UvdSD;
655
656 if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
657 result |= PP_StateClassificationFlag_HD2;
658
659 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
660 result |= PP_StateClassificationFlag_ACPI;
661
662 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
663 result |= PP_StateClassificationFlag_LimitedPowerSource_2;
664
665
666 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
667 result |= PP_StateClassificationFlag_ULV;
668
669 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
670 result |= PP_StateClassificationFlag_UvdMVC;
671
672 return result;
673 }
674
init_non_clock_fields(struct pp_hwmgr * hwmgr,struct pp_power_state * ps,uint8_t version,const ATOM_PPLIB_NONCLOCK_INFO * pnon_clock_info)675 static int init_non_clock_fields(struct pp_hwmgr *hwmgr,
676 struct pp_power_state *ps,
677 uint8_t version,
678 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {
679 unsigned long rrr_index;
680 unsigned long tmp;
681
682 ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &
683 ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
684 ps->classification.flags = make_classification_flags(hwmgr,
685 le16_to_cpu(pnon_clock_info->usClassification),
686 le16_to_cpu(pnon_clock_info->usClassification2));
687
688 ps->classification.temporary_state = false;
689 ps->classification.to_be_deleted = false;
690 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
691 ATOM_PPLIB_SINGLE_DISPLAY_ONLY;
692
693 ps->validation.singleDisplayOnly = (0 != tmp);
694
695 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
696 ATOM_PPLIB_DISALLOW_ON_DC;
697
698 ps->validation.disallowOnDC = (0 != tmp);
699
700 ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
701 ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
702 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
703
704 ps->display.disableFrameModulation = false;
705
706 rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
707 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>
708 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;
709
710 if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {
711 static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \
712 { 0, 50, 0 };
713
714 ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;
715 ps->display.explicitRefreshrate = look_up[rrr_index];
716 ps->display.limitRefreshrate = true;
717
718 if (ps->display.explicitRefreshrate == 0)
719 ps->display.limitRefreshrate = false;
720 } else
721 ps->display.limitRefreshrate = false;
722
723 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
724 ATOM_PPLIB_ENABLE_VARIBRIGHT;
725
726 ps->display.enableVariBright = (0 != tmp);
727
728 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
729 ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;
730
731 ps->memory.dllOff = (0 != tmp);
732
733 ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
734 ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;
735
736 ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
737 pnon_clock_info->ucMinTemperature;
738
739 ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *
740 pnon_clock_info->ucMaxTemperature;
741
742 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
743 ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;
744
745 ps->software.disableLoadBalancing = tmp;
746
747 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &
748 ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;
749
750 ps->software.enableSleepForTimestamps = (0 != tmp);
751
752 ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;
753
754 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {
755 ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);
756 ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);
757 } else {
758 ps->uvd_clocks.VCLK = 0;
759 ps->uvd_clocks.DCLK = 0;
760 }
761
762 return 0;
763 }
764
size_of_entry_v2(ULONG num_dpm_levels)765 static ULONG size_of_entry_v2(ULONG num_dpm_levels)
766 {
767 return (sizeof(UCHAR) + sizeof(UCHAR) +
768 (num_dpm_levels * sizeof(UCHAR)));
769 }
770
get_state_entry_v2(const StateArray * pstate_arrays,ULONG entry_index)771 static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(
772 const StateArray * pstate_arrays,
773 ULONG entry_index)
774 {
775 ULONG i;
776 const ATOM_PPLIB_STATE_V2 *pstate;
777
778 pstate = pstate_arrays->states;
779 if (entry_index <= pstate_arrays->ucNumEntries) {
780 for (i = 0; i < entry_index; i++)
781 pstate = (ATOM_PPLIB_STATE_V2 *)(
782 (unsigned long)pstate +
783 size_of_entry_v2(pstate->ucNumDPMLevels));
784 }
785 return pstate;
786 }
787
788 static const unsigned char soft_dummy_pp_table[] = {
789 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
790 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
791 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
794 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
795 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
800 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
801 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
802 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
803 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
804 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
805 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
806 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
807 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
808 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
809 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
810 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
811 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
812 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
813 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
814 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
815 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
816 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
817 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
818 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
819 0x00
820 };
821
get_powerplay_table(struct pp_hwmgr * hwmgr)822 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(
823 struct pp_hwmgr *hwmgr)
824 {
825 const void *table_addr = hwmgr->soft_pp_table;
826 uint8_t frev, crev;
827 uint16_t size;
828
829 if (!table_addr) {
830 if (hwmgr->chip_id == CHIP_RAVEN) {
831 table_addr = &soft_dummy_pp_table[0];
832 hwmgr->soft_pp_table = &soft_dummy_pp_table[0];
833 hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);
834 } else {
835 table_addr = smu_atom_get_data_table(hwmgr->adev,
836 GetIndexIntoMasterTable(DATA, PowerPlayInfo),
837 &size, &frev, &crev);
838 hwmgr->soft_pp_table = table_addr;
839 hwmgr->soft_pp_table_size = size;
840 }
841 }
842
843 return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;
844 }
845
pp_tables_get_response_times(struct pp_hwmgr * hwmgr,uint32_t * vol_rep_time,uint32_t * bb_rep_time)846 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
847 uint32_t *vol_rep_time, uint32_t *bb_rep_time)
848 {
849 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);
850
851 PP_ASSERT_WITH_CODE(NULL != powerplay_tab,
852 "Missing PowerPlay Table!", return -EINVAL);
853
854 *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);
855 *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);
856
857 return 0;
858 }
859
pp_tables_get_num_of_entries(struct pp_hwmgr * hwmgr,unsigned long * num_of_entries)860 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
861 unsigned long *num_of_entries)
862 {
863 const StateArray *pstate_arrays;
864 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
865
866 if (powerplay_table == NULL)
867 return -1;
868
869 if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
870 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
871 le16_to_cpu(powerplay_table->usStateArrayOffset));
872
873 *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);
874 } else
875 *num_of_entries = (unsigned long)(powerplay_table->ucNumStates);
876
877 return 0;
878 }
879
pp_tables_get_entry(struct pp_hwmgr * hwmgr,unsigned long entry_index,struct pp_power_state * ps,pp_tables_hw_clock_info_callback func)880 int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
881 unsigned long entry_index,
882 struct pp_power_state *ps,
883 pp_tables_hw_clock_info_callback func)
884 {
885 int i;
886 const StateArray *pstate_arrays;
887 const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;
888 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;
889 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
890 int result = 0;
891 int res = 0;
892
893 const ClockInfoArray *pclock_arrays;
894
895 const NonClockInfoArray *pnon_clock_arrays;
896
897 const ATOM_PPLIB_STATE *pstate_entry;
898
899 if (powerplay_table == NULL)
900 return -1;
901
902 ps->classification.bios_index = entry_index;
903
904 if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {
905 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +
906 le16_to_cpu(powerplay_table->usStateArrayOffset));
907
908 if (entry_index > pstate_arrays->ucNumEntries)
909 return -1;
910
911 pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);
912 pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
913 le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
914
915 pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +
916 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));
917
918 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +
919 (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));
920
921 result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);
922
923 for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {
924 const void *pclock_info = (const void *)(
925 (unsigned long)(pclock_arrays->clockInfo) +
926 (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));
927 res = func(hwmgr, &ps->hardware, i, pclock_info);
928 if ((0 == result) && (0 != res))
929 result = res;
930 }
931 } else {
932 if (entry_index > powerplay_table->ucNumStates)
933 return -1;
934
935 pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +
936 le16_to_cpu(powerplay_table->usStateArrayOffset) +
937 entry_index * powerplay_table->ucStateEntrySize);
938
939 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +
940 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +
941 pstate_entry->ucNonClockStateIndex *
942 powerplay_table->ucNonClockSize);
943
944 result = init_non_clock_fields(hwmgr, ps,
945 powerplay_table->ucNonClockSize,
946 pnon_clock_info);
947
948 for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {
949 const void *pclock_info = (const void *)((unsigned long)powerplay_table +
950 le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +
951 pstate_entry->ucClockStateIndices[i] *
952 powerplay_table->ucClockInfoSize);
953
954 int res = func(hwmgr, &ps->hardware, i, pclock_info);
955
956 if ((0 == result) && (0 != res))
957 result = res;
958 }
959 }
960
961 if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {
962 if (hwmgr->chip_family < AMDGPU_FAMILY_RV)
963 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));
964 }
965
966 return result;
967 }
968
init_powerplay_tables(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)969 static int init_powerplay_tables(
970 struct pp_hwmgr *hwmgr,
971 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table
972 )
973 {
974 return 0;
975 }
976
977
init_thermal_controller(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)978 static int init_thermal_controller(
979 struct pp_hwmgr *hwmgr,
980 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
981 {
982 struct amdgpu_device *adev = hwmgr->adev;
983
984 hwmgr->thermal_controller.ucType =
985 powerplay_table->sThermalController.ucType;
986 hwmgr->thermal_controller.ucI2cLine =
987 powerplay_table->sThermalController.ucI2cLine;
988 hwmgr->thermal_controller.ucI2cAddress =
989 powerplay_table->sThermalController.ucI2cAddress;
990
991 hwmgr->thermal_controller.fanInfo.bNoFan =
992 (0 != (powerplay_table->sThermalController.ucFanParameters &
993 ATOM_PP_FANPARAMETERS_NOFAN));
994
995 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
996 powerplay_table->sThermalController.ucFanParameters &
997 ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
998
999 hwmgr->thermal_controller.fanInfo.ulMinRPM
1000 = powerplay_table->sThermalController.ucFanMinRPM * 100UL;
1001 hwmgr->thermal_controller.fanInfo.ulMaxRPM
1002 = powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
1003
1004 set_hw_cap(hwmgr,
1005 ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
1006 PHM_PlatformCaps_ThermalController);
1007
1008 if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {
1009 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =
1010 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1011
1012 if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {
1013 hwmgr->thermal_controller.use_hw_fan_control = 1;
1014 return 0;
1015 } else {
1016 const ATOM_PPLIB_FANTABLE *fan_table =
1017 (const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) +
1018 le16_to_cpu(powerplay_table3->usFanTableOffset));
1019
1020 if (1 <= fan_table->ucFanTableFormat) {
1021 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst =
1022 fan_table->ucTHyst;
1023 hwmgr->thermal_controller.advanceFanControlParameters.usTMin =
1024 le16_to_cpu(fan_table->usTMin);
1025 hwmgr->thermal_controller.advanceFanControlParameters.usTMed =
1026 le16_to_cpu(fan_table->usTMed);
1027 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh =
1028 le16_to_cpu(fan_table->usTHigh);
1029 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
1030 le16_to_cpu(fan_table->usPWMMin);
1031 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed =
1032 le16_to_cpu(fan_table->usPWMMed);
1033 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh =
1034 le16_to_cpu(fan_table->usPWMHigh);
1035 hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900;
1036 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000;
1037
1038 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1039 PHM_PlatformCaps_MicrocodeFanControl);
1040 }
1041
1042 if (2 <= fan_table->ucFanTableFormat) {
1043 const ATOM_PPLIB_FANTABLE2 *fan_table2 =
1044 (const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) +
1045 le16_to_cpu(powerplay_table3->usFanTableOffset));
1046 hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
1047 le16_to_cpu(fan_table2->usTMax);
1048 }
1049
1050 if (3 <= fan_table->ucFanTableFormat) {
1051 const ATOM_PPLIB_FANTABLE3 *fan_table3 =
1052 (const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) +
1053 le16_to_cpu(powerplay_table3->usFanTableOffset));
1054
1055 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =
1056 fan_table3->ucFanControlMode;
1057
1058 if ((3 == fan_table->ucFanTableFormat) &&
1059 (0x67B1 == adev->pdev->device))
1060 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1061 47;
1062 else
1063 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =
1064 le16_to_cpu(fan_table3->usFanPWMMax);
1065
1066 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity =
1067 4836;
1068 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
1069 le16_to_cpu(fan_table3->usFanOutputSensitivity);
1070 }
1071
1072 if (6 <= fan_table->ucFanTableFormat) {
1073 const ATOM_PPLIB_FANTABLE4 *fan_table4 =
1074 (const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) +
1075 le16_to_cpu(powerplay_table3->usFanTableOffset));
1076
1077 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1078 PHM_PlatformCaps_FanSpeedInTableIsRPM);
1079
1080 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM =
1081 le16_to_cpu(fan_table4->usFanRPMMax);
1082 }
1083
1084 if (7 <= fan_table->ucFanTableFormat) {
1085 const ATOM_PPLIB_FANTABLE5 *fan_table5 =
1086 (const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) +
1087 le16_to_cpu(powerplay_table3->usFanTableOffset));
1088
1089 if (0x67A2 == adev->pdev->device ||
1090 0x67A9 == adev->pdev->device ||
1091 0x67B9 == adev->pdev->device) {
1092 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1093 PHM_PlatformCaps_GeminiRegulatorFanControlSupport);
1094 hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow =
1095 le16_to_cpu(fan_table5->usFanCurrentLow);
1096 hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh =
1097 le16_to_cpu(fan_table5->usFanCurrentHigh);
1098 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow =
1099 le16_to_cpu(fan_table5->usFanRPMLow);
1100 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh =
1101 le16_to_cpu(fan_table5->usFanRPMHigh);
1102 }
1103 }
1104 }
1105 }
1106
1107 return 0;
1108 }
1109
init_overdrive_limits_V1_4(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V1_4 * fw_info)1110 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,
1111 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1112 const ATOM_FIRMWARE_INFO_V1_4 *fw_info)
1113 {
1114 hwmgr->platform_descriptor.overdriveLimit.engineClock =
1115 le32_to_cpu(fw_info->ulASICMaxEngineClock);
1116
1117 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
1118 le32_to_cpu(fw_info->ulASICMaxMemoryClock);
1119
1120 hwmgr->platform_descriptor.maxOverdriveVDDC =
1121 le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;
1122
1123 hwmgr->platform_descriptor.minOverdriveVDDC =
1124 le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1125
1126 hwmgr->platform_descriptor.maxOverdriveVDDC =
1127 le16_to_cpu(fw_info->usBootUpVDDCVoltage);
1128
1129 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1130 return 0;
1131 }
1132
init_overdrive_limits_V2_1(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table,const ATOM_FIRMWARE_INFO_V2_1 * fw_info)1133 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,
1134 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,
1135 const ATOM_FIRMWARE_INFO_V2_1 *fw_info)
1136 {
1137 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;
1138 const ATOM_PPLIB_EXTENDEDHEADER *header;
1139
1140 if (le16_to_cpu(powerplay_table->usTableSize) <
1141 sizeof(ATOM_PPLIB_POWERPLAYTABLE3))
1142 return 0;
1143
1144 powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;
1145
1146 if (0 == powerplay_table3->usExtendendedHeaderOffset)
1147 return 0;
1148
1149 header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +
1150 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));
1151
1152 hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);
1153 hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);
1154
1155
1156 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1157 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1158 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1159
1160 return 0;
1161 }
1162
init_overdrive_limits(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1163 static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
1164 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1165 {
1166 int result = 0;
1167 uint8_t frev, crev;
1168 uint16_t size;
1169
1170 const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;
1171
1172 hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;
1173 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;
1174 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
1175 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
1176 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
1177
1178 if (hwmgr->chip_id == CHIP_RAVEN)
1179 return 0;
1180
1181 /* We assume here that fw_info is unchanged if this call fails.*/
1182 fw_info = smu_atom_get_data_table(hwmgr->adev,
1183 GetIndexIntoMasterTable(DATA, FirmwareInfo),
1184 &size, &frev, &crev);
1185 PP_ASSERT_WITH_CODE(fw_info != NULL,
1186 "Missing firmware info!", return -EINVAL);
1187
1188 if ((fw_info->ucTableFormatRevision == 1)
1189 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))
1190 result = init_overdrive_limits_V1_4(hwmgr,
1191 powerplay_table,
1192 (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);
1193
1194 else if ((fw_info->ucTableFormatRevision == 2)
1195 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))
1196 result = init_overdrive_limits_V2_1(hwmgr,
1197 powerplay_table,
1198 (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
1199
1200 return result;
1201 }
1202
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)1203 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1204 struct phm_uvd_clock_voltage_dependency_table **ptable,
1205 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,
1206 const UVDClockInfoArray *array)
1207 {
1208 unsigned long i;
1209 struct phm_uvd_clock_voltage_dependency_table *uvd_table;
1210
1211 uvd_table = kzalloc_flex(*uvd_table, entries, table->numEntries);
1212 if (!uvd_table)
1213 return -ENOMEM;
1214
1215 uvd_table->count = table->numEntries;
1216
1217 for (i = 0; i < table->numEntries; i++) {
1218 const UVDClockInfo *entry =
1219 &array->entries[table->entries[i].ucUVDClockInfoIndex];
1220 uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1221 uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)
1222 | le16_to_cpu(entry->usVClkLow);
1223 uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)
1224 | le16_to_cpu(entry->usDClkLow);
1225 }
1226
1227 *ptable = uvd_table;
1228
1229 return 0;
1230 }
1231
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)1232 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1233 struct phm_vce_clock_voltage_dependency_table **ptable,
1234 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,
1235 const VCEClockInfoArray *array)
1236 {
1237 unsigned long i;
1238 struct phm_vce_clock_voltage_dependency_table *vce_table;
1239
1240 vce_table = kzalloc_flex(*vce_table, entries, table->numEntries);
1241 if (!vce_table)
1242 return -ENOMEM;
1243
1244 vce_table->count = table->numEntries;
1245 for (i = 0; i < table->numEntries; i++) {
1246 const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];
1247
1248 vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1249 vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)
1250 | le16_to_cpu(entry->usEVClkLow);
1251 vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)
1252 | le16_to_cpu(entry->usECClkLow);
1253 }
1254
1255 *ptable = vce_table;
1256
1257 return 0;
1258 }
1259
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)1260 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1261 struct phm_samu_clock_voltage_dependency_table **ptable,
1262 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)
1263 {
1264 unsigned long i;
1265 struct phm_samu_clock_voltage_dependency_table *samu_table;
1266
1267 samu_table = kzalloc_flex(*samu_table, entries, table->numEntries);
1268 if (!samu_table)
1269 return -ENOMEM;
1270
1271 samu_table->count = table->numEntries;
1272
1273 for (i = 0; i < table->numEntries; i++) {
1274 samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1275 samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)
1276 | le16_to_cpu(table->entries[i].usSAMClockLow);
1277 }
1278
1279 *ptable = samu_table;
1280
1281 return 0;
1282 }
1283
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)1284 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,
1285 struct phm_acp_clock_voltage_dependency_table **ptable,
1286 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)
1287 {
1288 unsigned long i;
1289 struct phm_acp_clock_voltage_dependency_table *acp_table;
1290
1291 acp_table = kzalloc_flex(*acp_table, entries, table->numEntries);
1292 if (!acp_table)
1293 return -ENOMEM;
1294
1295 acp_table->count = (unsigned long)table->numEntries;
1296
1297 for (i = 0; i < table->numEntries; i++) {
1298 acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);
1299 acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)
1300 | le16_to_cpu(table->entries[i].usACPClockLow);
1301 }
1302
1303 *ptable = acp_table;
1304
1305 return 0;
1306 }
1307
init_clock_voltage_dependency(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1308 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,
1309 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1310 {
1311 ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;
1312 ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;
1313 int result = 0;
1314
1315 uint16_t vce_clock_info_array_offset;
1316 uint16_t uvd_clock_info_array_offset;
1317 uint16_t table_offset;
1318
1319 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1320 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1321 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1322 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1323 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1324 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1325 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1326 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1327 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1328 hwmgr->dyn_state.ppm_parameter_table = NULL;
1329 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1330
1331 vce_clock_info_array_offset = get_vce_clock_info_array_offset(
1332 hwmgr, powerplay_table);
1333 table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,
1334 powerplay_table);
1335 if (vce_clock_info_array_offset > 0 && table_offset > 0) {
1336 const VCEClockInfoArray *array = (const VCEClockInfoArray *)
1337 (((unsigned long) powerplay_table) +
1338 vce_clock_info_array_offset);
1339 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =
1340 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
1341 (((unsigned long) powerplay_table) + table_offset);
1342 result = get_vce_clock_voltage_limit_table(hwmgr,
1343 &hwmgr->dyn_state.vce_clock_voltage_dependency_table,
1344 table, array);
1345 }
1346
1347 uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);
1348 table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);
1349
1350 if (uvd_clock_info_array_offset > 0 && table_offset > 0) {
1351 const UVDClockInfoArray *array = (const UVDClockInfoArray *)
1352 (((unsigned long) powerplay_table) +
1353 uvd_clock_info_array_offset);
1354 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =
1355 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
1356 (((unsigned long) powerplay_table) + table_offset);
1357 result = get_uvd_clock_voltage_limit_table(hwmgr,
1358 &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);
1359 }
1360
1361 table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,
1362 powerplay_table);
1363
1364 if (table_offset > 0) {
1365 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =
1366 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
1367 (((unsigned long) powerplay_table) + table_offset);
1368 result = get_samu_clock_voltage_limit_table(hwmgr,
1369 &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);
1370 }
1371
1372 table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,
1373 powerplay_table);
1374
1375 if (table_offset > 0) {
1376 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =
1377 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
1378 (((unsigned long) powerplay_table) + table_offset);
1379 result = get_acp_clock_voltage_limit_table(hwmgr,
1380 &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);
1381 }
1382
1383 table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);
1384 if (table_offset > 0) {
1385 UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);
1386
1387 if (rev_id > 0) {
1388 const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =
1389 (const ATOM_PPLIB_POWERTUNE_Table_V1 *)
1390 (((unsigned long) powerplay_table) + table_offset);
1391 result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,
1392 &tune_table->power_tune_table,
1393 le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));
1394 hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
1395 le16_to_cpu(tune_table->usTjMax);
1396 } else {
1397 const ATOM_PPLIB_POWERTUNE_Table *tune_table =
1398 (const ATOM_PPLIB_POWERTUNE_Table *)
1399 (((unsigned long) powerplay_table) + table_offset);
1400 result = get_cac_tdp_table(hwmgr,
1401 &hwmgr->dyn_state.cac_dtp_table,
1402 &tune_table->power_tune_table, 255);
1403 }
1404 }
1405
1406 if (le16_to_cpu(powerplay_table->usTableSize) >=
1407 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1408 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1409 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1410 if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {
1411 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1412 (((unsigned long) powerplay_table4) +
1413 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));
1414 result = get_clock_voltage_dependency_table(hwmgr,
1415 &hwmgr->dyn_state.vddc_dependency_on_sclk, table);
1416 }
1417
1418 if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {
1419 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1420 (((unsigned long) powerplay_table4) +
1421 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));
1422 result = get_clock_voltage_dependency_table(hwmgr,
1423 &hwmgr->dyn_state.vddci_dependency_on_mclk, table);
1424 }
1425
1426 if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {
1427 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1428 (((unsigned long) powerplay_table4) +
1429 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));
1430 result = get_clock_voltage_dependency_table(hwmgr,
1431 &hwmgr->dyn_state.vddc_dependency_on_mclk, table);
1432 }
1433
1434 if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {
1435 limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
1436 (((unsigned long) powerplay_table4) +
1437 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));
1438 result = get_clock_voltage_limit(hwmgr,
1439 &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);
1440 }
1441
1442 if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&
1443 (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))
1444 result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,
1445 hwmgr->dyn_state.vddc_dependency_on_mclk);
1446
1447 if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&
1448 (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))
1449 result = get_valid_clk(hwmgr,
1450 &hwmgr->dyn_state.valid_sclk_values,
1451 hwmgr->dyn_state.vddc_dependency_on_sclk);
1452
1453 if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {
1454 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1455 (((unsigned long) powerplay_table4) +
1456 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));
1457 result = get_clock_voltage_dependency_table(hwmgr,
1458 &hwmgr->dyn_state.mvdd_dependency_on_mclk, table);
1459 }
1460 }
1461
1462 table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,
1463 powerplay_table);
1464
1465 if (table_offset > 0) {
1466 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
1467 (((unsigned long) powerplay_table) + table_offset);
1468 result = get_clock_voltage_dependency_table(hwmgr,
1469 &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);
1470 }
1471
1472 return result;
1473 }
1474
get_cac_leakage_table(struct pp_hwmgr * hwmgr,struct phm_cac_leakage_table ** ptable,const ATOM_PPLIB_CAC_Leakage_Table * table)1475 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,
1476 struct phm_cac_leakage_table **ptable,
1477 const ATOM_PPLIB_CAC_Leakage_Table *table)
1478 {
1479 struct phm_cac_leakage_table *cac_leakage_table;
1480 unsigned long i;
1481
1482 if (!hwmgr || !table || !ptable)
1483 return -EINVAL;
1484
1485 cac_leakage_table = kzalloc_flex(*cac_leakage_table, entries,
1486 table->ucNumEntries);
1487 if (!cac_leakage_table)
1488 return -ENOMEM;
1489
1490 cac_leakage_table->count = (ULONG)table->ucNumEntries;
1491
1492 for (i = 0; i < cac_leakage_table->count; i++) {
1493 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1494 PHM_PlatformCaps_EVV)) {
1495 cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);
1496 cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);
1497 cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);
1498 } else {
1499 cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc);
1500 cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);
1501 }
1502 }
1503
1504 *ptable = cac_leakage_table;
1505
1506 return 0;
1507 }
1508
get_platform_power_management_table(struct pp_hwmgr * hwmgr,ATOM_PPLIB_PPM_Table * atom_ppm_table)1509 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,
1510 ATOM_PPLIB_PPM_Table *atom_ppm_table)
1511 {
1512 struct phm_ppm_table *ptr = kzalloc_obj(struct phm_ppm_table);
1513
1514 if (NULL == ptr)
1515 return -ENOMEM;
1516
1517 ptr->ppm_design = atom_ppm_table->ucPpmDesign;
1518 ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
1519 ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
1520 ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
1521 ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
1522 ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
1523 ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP);
1524 ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
1525 ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
1526 ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax);
1527 hwmgr->dyn_state.ppm_parameter_table = ptr;
1528
1529 return 0;
1530 }
1531
init_dpm2_parameters(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1532 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,
1533 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1534 {
1535 int result = 0;
1536
1537 if (le16_to_cpu(powerplay_table->usTableSize) >=
1538 sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {
1539 const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =
1540 (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;
1541 const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =
1542 (const ATOM_PPLIB_POWERPLAYTABLE4 *)
1543 (&ptable5->basicTable4);
1544 const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =
1545 (const ATOM_PPLIB_POWERPLAYTABLE3 *)
1546 (&ptable4->basicTable3);
1547 const ATOM_PPLIB_EXTENDEDHEADER *extended_header;
1548 uint16_t table_offset;
1549 ATOM_PPLIB_PPM_Table *atom_ppm_table;
1550
1551 hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit);
1552 hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);
1553
1554 hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit);
1555 hwmgr->platform_descriptor.TDPAdjustment = 0;
1556
1557 hwmgr->platform_descriptor.VidAdjustment = 0;
1558 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
1559 hwmgr->platform_descriptor.VidMinLimit = 0;
1560 hwmgr->platform_descriptor.VidMaxLimit = 1500000;
1561 hwmgr->platform_descriptor.VidStep = 6250;
1562
1563 hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);
1564
1565 if (hwmgr->platform_descriptor.TDPODLimit != 0)
1566 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1567 PHM_PlatformCaps_PowerControl);
1568
1569 hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);
1570
1571 hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);
1572
1573 hwmgr->dyn_state.cac_leakage_table = NULL;
1574
1575 if (0 != ptable5->usCACLeakageTableOffset) {
1576 const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =
1577 (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +
1578 le16_to_cpu(ptable5->usCACLeakageTableOffset));
1579 result = get_cac_leakage_table(hwmgr,
1580 &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);
1581 }
1582
1583 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);
1584
1585 hwmgr->dyn_state.ppm_parameter_table = NULL;
1586
1587 if (0 != ptable3->usExtendendedHeaderOffset) {
1588 extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)
1589 (((unsigned long)powerplay_table) +
1590 le16_to_cpu(ptable3->usExtendendedHeaderOffset));
1591 if ((extended_header->usPPMTableOffset > 0) &&
1592 le16_to_cpu(extended_header->usSize) >=
1593 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {
1594 table_offset = le16_to_cpu(extended_header->usPPMTableOffset);
1595 atom_ppm_table = (ATOM_PPLIB_PPM_Table *)
1596 (((unsigned long)powerplay_table) + table_offset);
1597 if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))
1598 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
1599 PHM_PlatformCaps_EnablePlatformPowerManagement);
1600 }
1601 }
1602 }
1603 return result;
1604 }
1605
init_phase_shedding_table(struct pp_hwmgr * hwmgr,const ATOM_PPLIB_POWERPLAYTABLE * powerplay_table)1606 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,
1607 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
1608 {
1609 if (le16_to_cpu(powerplay_table->usTableSize) >=
1610 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {
1611 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =
1612 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;
1613
1614 if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {
1615 const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =
1616 (ATOM_PPLIB_PhaseSheddingLimits_Table *)
1617 (((unsigned long)powerplay_table4) +
1618 le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));
1619 struct phm_phase_shedding_limits_table *table;
1620 unsigned long i;
1621
1622
1623 table = kzalloc_flex(*table, entries,
1624 ptable->ucNumEntries);
1625 if (!table)
1626 return -ENOMEM;
1627
1628 table->count = (unsigned long)ptable->ucNumEntries;
1629
1630 for (i = 0; i < table->count; i++) {
1631 table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);
1632 table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)
1633 | le16_to_cpu(ptable->entries[i].usSclkLow);
1634 table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)
1635 | le16_to_cpu(ptable->entries[i].usMclkLow);
1636 }
1637 hwmgr->dyn_state.vddc_phase_shed_limits_table = table;
1638 }
1639 }
1640
1641 return 0;
1642 }
1643
get_number_of_vce_state_table_entries(struct pp_hwmgr * hwmgr)1644 static int get_number_of_vce_state_table_entries(
1645 struct pp_hwmgr *hwmgr)
1646 {
1647 const ATOM_PPLIB_POWERPLAYTABLE *table =
1648 get_powerplay_table(hwmgr);
1649 const ATOM_PPLIB_VCE_State_Table *vce_table =
1650 get_vce_state_table(hwmgr, table);
1651
1652 if (vce_table)
1653 return vce_table->numEntries;
1654
1655 return 0;
1656 }
1657
get_vce_state_table_entry(struct pp_hwmgr * hwmgr,unsigned long i,struct amd_vce_state * vce_state,void ** clock_info,unsigned long * flag)1658 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
1659 unsigned long i,
1660 struct amd_vce_state *vce_state,
1661 void **clock_info,
1662 unsigned long *flag)
1663 {
1664 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);
1665
1666 const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);
1667
1668 unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);
1669
1670 const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);
1671
1672 const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +
1673 le16_to_cpu(powerplay_table->usClockInfoArrayOffset));
1674
1675 const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];
1676
1677 const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];
1678
1679 unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;
1680
1681 *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);
1682
1683 vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);
1684 vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);
1685
1686 *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));
1687
1688 return 0;
1689 }
1690
1691
pp_tables_initialize(struct pp_hwmgr * hwmgr)1692 static int pp_tables_initialize(struct pp_hwmgr *hwmgr)
1693 {
1694 int result;
1695 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;
1696
1697 if (hwmgr->chip_id == CHIP_RAVEN)
1698 return 0;
1699
1700 hwmgr->need_pp_table_upload = true;
1701
1702 powerplay_table = get_powerplay_table(hwmgr);
1703
1704 result = init_powerplay_tables(hwmgr, powerplay_table);
1705
1706 PP_ASSERT_WITH_CODE((result == 0),
1707 "init_powerplay_tables failed", return result);
1708
1709 result = set_platform_caps(hwmgr,
1710 le32_to_cpu(powerplay_table->ulPlatformCaps));
1711
1712 PP_ASSERT_WITH_CODE((result == 0),
1713 "set_platform_caps failed", return result);
1714
1715 result = init_thermal_controller(hwmgr, powerplay_table);
1716
1717 PP_ASSERT_WITH_CODE((result == 0),
1718 "init_thermal_controller failed", return result);
1719
1720 result = init_overdrive_limits(hwmgr, powerplay_table);
1721
1722 PP_ASSERT_WITH_CODE((result == 0),
1723 "init_overdrive_limits failed", return result);
1724
1725 result = init_clock_voltage_dependency(hwmgr,
1726 powerplay_table);
1727
1728 PP_ASSERT_WITH_CODE((result == 0),
1729 "init_clock_voltage_dependency failed", return result);
1730
1731 result = init_dpm2_parameters(hwmgr, powerplay_table);
1732
1733 PP_ASSERT_WITH_CODE((result == 0),
1734 "init_dpm2_parameters failed", return result);
1735
1736 result = init_phase_shedding_table(hwmgr, powerplay_table);
1737
1738 PP_ASSERT_WITH_CODE((result == 0),
1739 "init_phase_shedding_table failed", return result);
1740
1741 return result;
1742 }
1743
pp_tables_uninitialize(struct pp_hwmgr * hwmgr)1744 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
1745 {
1746 if (hwmgr->chip_id == CHIP_RAVEN)
1747 return 0;
1748
1749 kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);
1750 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;
1751
1752 kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);
1753 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;
1754
1755 kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);
1756 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;
1757
1758 kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);
1759 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;
1760
1761 kfree(hwmgr->dyn_state.valid_mclk_values);
1762 hwmgr->dyn_state.valid_mclk_values = NULL;
1763
1764 kfree(hwmgr->dyn_state.valid_sclk_values);
1765 hwmgr->dyn_state.valid_sclk_values = NULL;
1766
1767 kfree(hwmgr->dyn_state.cac_leakage_table);
1768 hwmgr->dyn_state.cac_leakage_table = NULL;
1769
1770 kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);
1771 hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;
1772
1773 kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);
1774 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;
1775
1776 kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);
1777 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;
1778
1779 kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);
1780 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;
1781
1782 kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);
1783 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;
1784
1785 kfree(hwmgr->dyn_state.cac_dtp_table);
1786 hwmgr->dyn_state.cac_dtp_table = NULL;
1787
1788 kfree(hwmgr->dyn_state.ppm_parameter_table);
1789 hwmgr->dyn_state.ppm_parameter_table = NULL;
1790
1791 kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);
1792 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;
1793
1794 return 0;
1795 }
1796
1797 const struct pp_table_func pptable_funcs = {
1798 .pptable_init = pp_tables_initialize,
1799 .pptable_fini = pp_tables_uninitialize,
1800 .pptable_get_number_of_vce_state_table_entries =
1801 get_number_of_vce_state_table_entries,
1802 .pptable_get_vce_state_table_entry =
1803 get_vce_state_table_entry,
1804 };
1805
1806