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