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