2 * Copyright 2015 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <drm/amdgpu_drm.h>
28 #include "processpptables.h"
29 #include <atom-types.h>
32 #include "power_state.h"
34 #include "hardwaremanager.h"
37 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
38 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
39 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
40 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
41 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
42 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
43 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
44 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
46 #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6
48 static uint16_t get_vce_table_offset(struct pp_hwmgr
*hwmgr
,
49 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
51 uint16_t vce_table_offset
= 0;
53 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
54 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
)) {
55 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
=
56 (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
58 if (powerplay_table3
->usExtendendedHeaderOffset
> 0) {
59 const ATOM_PPLIB_EXTENDEDHEADER
*extended_header
=
60 (const ATOM_PPLIB_EXTENDEDHEADER
*)
61 (((unsigned long)powerplay_table3
) +
62 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
63 if (le16_to_cpu(extended_header
->usSize
) >=
64 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2
)
65 vce_table_offset
= le16_to_cpu(extended_header
->usVCETableOffset
);
69 return vce_table_offset
;
72 static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr
*hwmgr
,
73 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
75 uint16_t table_offset
= get_vce_table_offset(hwmgr
,
79 return table_offset
+ 1;
84 static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr
*hwmgr
,
85 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
87 uint16_t table_offset
= get_vce_clock_info_array_offset(hwmgr
,
89 uint16_t table_size
= 0;
91 if (table_offset
> 0) {
92 const VCEClockInfoArray
*p
= (const VCEClockInfoArray
*)
93 (((unsigned long) powerplay_table
) + table_offset
);
94 table_size
= sizeof(uint8_t) + p
->ucNumEntries
* sizeof(VCEClockInfo
);
100 static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr
*hwmgr
,
101 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
103 uint16_t table_offset
= get_vce_clock_info_array_offset(hwmgr
,
106 if (table_offset
> 0)
107 return table_offset
+ get_vce_clock_info_array_size(hwmgr
,
113 static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr
*hwmgr
,
114 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
116 uint16_t table_offset
= get_vce_clock_voltage_limit_table_offset(hwmgr
, powerplay_table
);
117 uint16_t table_size
= 0;
119 if (table_offset
> 0) {
120 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table
*ptable
=
121 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table
*)(((unsigned long) powerplay_table
) + table_offset
);
123 table_size
= sizeof(uint8_t) + ptable
->numEntries
* sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record
);
128 static uint16_t get_vce_state_table_offset(struct pp_hwmgr
*hwmgr
, const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
130 uint16_t table_offset
= get_vce_clock_voltage_limit_table_offset(hwmgr
, powerplay_table
);
132 if (table_offset
> 0)
133 return table_offset
+ get_vce_clock_voltage_limit_table_size(hwmgr
, powerplay_table
);
138 static const ATOM_PPLIB_VCE_State_Table
*get_vce_state_table(
139 struct pp_hwmgr
*hwmgr
,
140 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
142 uint16_t table_offset
= get_vce_state_table_offset(hwmgr
, powerplay_table
);
144 if (table_offset
> 0)
145 return (const ATOM_PPLIB_VCE_State_Table
*)(((unsigned long) powerplay_table
) + table_offset
);
150 static uint16_t get_uvd_table_offset(struct pp_hwmgr
*hwmgr
,
151 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
153 uint16_t uvd_table_offset
= 0;
155 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
156 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
)) {
157 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
=
158 (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
159 if (powerplay_table3
->usExtendendedHeaderOffset
> 0) {
160 const ATOM_PPLIB_EXTENDEDHEADER
*extended_header
=
161 (const ATOM_PPLIB_EXTENDEDHEADER
*)
162 (((unsigned long)powerplay_table3
) +
163 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
164 if (le16_to_cpu(extended_header
->usSize
) >=
165 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3
)
166 uvd_table_offset
= le16_to_cpu(extended_header
->usUVDTableOffset
);
169 return uvd_table_offset
;
172 static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr
*hwmgr
,
173 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
175 uint16_t table_offset
= get_uvd_table_offset(hwmgr
,
178 if (table_offset
> 0)
179 return table_offset
+ 1;
183 static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr
*hwmgr
,
184 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
186 uint16_t table_offset
= get_uvd_clock_info_array_offset(hwmgr
,
188 uint16_t table_size
= 0;
190 if (table_offset
> 0) {
191 const UVDClockInfoArray
*p
= (const UVDClockInfoArray
*)
192 (((unsigned long) powerplay_table
)
194 table_size
= sizeof(UCHAR
) +
195 p
->ucNumEntries
* sizeof(UVDClockInfo
);
201 static uint16_t get_uvd_clock_voltage_limit_table_offset(
202 struct pp_hwmgr
*hwmgr
,
203 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
205 uint16_t table_offset
= get_uvd_clock_info_array_offset(hwmgr
,
208 if (table_offset
> 0)
209 return table_offset
+
210 get_uvd_clock_info_array_size(hwmgr
, powerplay_table
);
215 static uint16_t get_samu_table_offset(struct pp_hwmgr
*hwmgr
,
216 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
218 uint16_t samu_table_offset
= 0;
220 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
221 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
)) {
222 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
=
223 (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
224 if (powerplay_table3
->usExtendendedHeaderOffset
> 0) {
225 const ATOM_PPLIB_EXTENDEDHEADER
*extended_header
=
226 (const ATOM_PPLIB_EXTENDEDHEADER
*)
227 (((unsigned long)powerplay_table3
) +
228 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
229 if (le16_to_cpu(extended_header
->usSize
) >=
230 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4
)
231 samu_table_offset
= le16_to_cpu(extended_header
->usSAMUTableOffset
);
235 return samu_table_offset
;
238 static uint16_t get_samu_clock_voltage_limit_table_offset(
239 struct pp_hwmgr
*hwmgr
,
240 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
242 uint16_t table_offset
= get_samu_table_offset(hwmgr
,
245 if (table_offset
> 0)
246 return table_offset
+ 1;
251 static uint16_t get_acp_table_offset(struct pp_hwmgr
*hwmgr
,
252 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
254 uint16_t acp_table_offset
= 0;
256 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
257 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
)) {
258 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
=
259 (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
260 if (powerplay_table3
->usExtendendedHeaderOffset
> 0) {
261 const ATOM_PPLIB_EXTENDEDHEADER
*pExtendedHeader
=
262 (const ATOM_PPLIB_EXTENDEDHEADER
*)
263 (((unsigned long)powerplay_table3
) +
264 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
265 if (le16_to_cpu(pExtendedHeader
->usSize
) >=
266 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6
)
267 acp_table_offset
= le16_to_cpu(pExtendedHeader
->usACPTableOffset
);
271 return acp_table_offset
;
274 static uint16_t get_acp_clock_voltage_limit_table_offset(
275 struct pp_hwmgr
*hwmgr
,
276 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
278 uint16_t tableOffset
= get_acp_table_offset(hwmgr
, powerplay_table
);
281 return tableOffset
+ 1;
286 static uint16_t get_cacp_tdp_table_offset(
287 struct pp_hwmgr
*hwmgr
,
288 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
290 uint16_t cacTdpTableOffset
= 0;
292 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
293 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
)) {
294 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
=
295 (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
296 if (powerplay_table3
->usExtendendedHeaderOffset
> 0) {
297 const ATOM_PPLIB_EXTENDEDHEADER
*pExtendedHeader
=
298 (const ATOM_PPLIB_EXTENDEDHEADER
*)
299 (((unsigned long)powerplay_table3
) +
300 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
301 if (le16_to_cpu(pExtendedHeader
->usSize
) >=
302 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7
)
303 cacTdpTableOffset
= le16_to_cpu(pExtendedHeader
->usPowerTuneTableOffset
);
307 return cacTdpTableOffset
;
310 static int get_cac_tdp_table(struct pp_hwmgr
*hwmgr
,
311 struct phm_cac_tdp_table
**ptable
,
312 const ATOM_PowerTune_Table
*table
,
313 uint16_t us_maximum_power_delivery_limit
)
315 unsigned long table_size
;
316 struct phm_cac_tdp_table
*tdp_table
;
318 table_size
= sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table
);
320 tdp_table
= kzalloc(table_size
, GFP_KERNEL
);
321 if (NULL
== tdp_table
)
324 tdp_table
->usTDP
= le16_to_cpu(table
->usTDP
);
325 tdp_table
->usConfigurableTDP
= le16_to_cpu(table
->usConfigurableTDP
);
326 tdp_table
->usTDC
= le16_to_cpu(table
->usTDC
);
327 tdp_table
->usBatteryPowerLimit
= le16_to_cpu(table
->usBatteryPowerLimit
);
328 tdp_table
->usSmallPowerLimit
= le16_to_cpu(table
->usSmallPowerLimit
);
329 tdp_table
->usLowCACLeakage
= le16_to_cpu(table
->usLowCACLeakage
);
330 tdp_table
->usHighCACLeakage
= le16_to_cpu(table
->usHighCACLeakage
);
331 tdp_table
->usMaximumPowerDeliveryLimit
= us_maximum_power_delivery_limit
;
338 static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr
*hwmgr
,
339 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
341 uint16_t sclk_vdd_gfx_table_offset
= 0;
343 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
344 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
)) {
345 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
=
346 (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
347 if (powerplay_table3
->usExtendendedHeaderOffset
> 0) {
348 const ATOM_PPLIB_EXTENDEDHEADER
*pExtendedHeader
=
349 (const ATOM_PPLIB_EXTENDEDHEADER
*)
350 (((unsigned long)powerplay_table3
) +
351 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
352 if (le16_to_cpu(pExtendedHeader
->usSize
) >=
353 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8
)
354 sclk_vdd_gfx_table_offset
=
355 le16_to_cpu(pExtendedHeader
->usSclkVddgfxTableOffset
);
359 return sclk_vdd_gfx_table_offset
;
362 static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(
363 struct pp_hwmgr
*hwmgr
,
364 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
366 uint16_t tableOffset
= get_sclk_vdd_gfx_table_offset(hwmgr
, powerplay_table
);
375 static int get_clock_voltage_dependency_table(struct pp_hwmgr
*hwmgr
,
376 struct phm_clock_voltage_dependency_table
**ptable
,
377 const ATOM_PPLIB_Clock_Voltage_Dependency_Table
*table
)
380 unsigned long table_size
, i
;
381 struct phm_clock_voltage_dependency_table
*dep_table
;
383 table_size
= sizeof(unsigned long) +
384 sizeof(struct phm_clock_voltage_dependency_table
)
385 * table
->ucNumEntries
;
387 dep_table
= kzalloc(table_size
, GFP_KERNEL
);
388 if (NULL
== dep_table
)
391 dep_table
->count
= (unsigned long)table
->ucNumEntries
;
393 for (i
= 0; i
< dep_table
->count
; i
++) {
394 dep_table
->entries
[i
].clk
=
395 ((unsigned long)table
->entries
[i
].ucClockHigh
<< 16) |
396 le16_to_cpu(table
->entries
[i
].usClockLow
);
397 dep_table
->entries
[i
].v
=
398 (unsigned long)le16_to_cpu(table
->entries
[i
].usVoltage
);
406 static int get_valid_clk(struct pp_hwmgr
*hwmgr
,
407 struct phm_clock_array
**ptable
,
408 const struct phm_clock_voltage_dependency_table
*table
)
410 unsigned long table_size
, i
;
411 struct phm_clock_array
*clock_table
;
413 table_size
= sizeof(unsigned long) + sizeof(unsigned long) * table
->count
;
414 clock_table
= kzalloc(table_size
, GFP_KERNEL
);
415 if (NULL
== clock_table
)
418 clock_table
->count
= (unsigned long)table
->count
;
420 for (i
= 0; i
< clock_table
->count
; i
++)
421 clock_table
->values
[i
] = (unsigned long)table
->entries
[i
].clk
;
423 *ptable
= clock_table
;
428 static int get_clock_voltage_limit(struct pp_hwmgr
*hwmgr
,
429 struct phm_clock_and_voltage_limits
*limits
,
430 const ATOM_PPLIB_Clock_Voltage_Limit_Table
*table
)
432 limits
->sclk
= ((unsigned long)table
->entries
[0].ucSclkHigh
<< 16) |
433 le16_to_cpu(table
->entries
[0].usSclkLow
);
434 limits
->mclk
= ((unsigned long)table
->entries
[0].ucMclkHigh
<< 16) |
435 le16_to_cpu(table
->entries
[0].usMclkLow
);
436 limits
->vddc
= (unsigned long)le16_to_cpu(table
->entries
[0].usVddc
);
437 limits
->vddci
= (unsigned long)le16_to_cpu(table
->entries
[0].usVddci
);
443 static void set_hw_cap(struct pp_hwmgr
*hwmgr
, bool enable
,
444 enum phm_platform_caps cap
)
447 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
, cap
);
449 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
, cap
);
452 static int set_platform_caps(struct pp_hwmgr
*hwmgr
,
453 unsigned long powerplay_caps
)
457 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_POWERPLAY
),
458 PHM_PlatformCaps_PowerPlaySupport
463 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE
),
464 PHM_PlatformCaps_BiosPowerSourceControl
469 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_ASPM_L0s
),
470 PHM_PlatformCaps_EnableASPML0s
475 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_ASPM_L1
),
476 PHM_PlatformCaps_EnableASPML1
481 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_BACKBIAS
),
482 PHM_PlatformCaps_EnableBackbias
487 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_HARDWAREDC
),
488 PHM_PlatformCaps_AutomaticDCTransition
493 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY
),
494 PHM_PlatformCaps_GeminiPrimary
499 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_STEPVDDC
),
500 PHM_PlatformCaps_StepVddc
505 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL
),
506 PHM_PlatformCaps_EnableVoltageControl
511 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL
),
512 PHM_PlatformCaps_EnableSideportControl
517 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1
),
518 PHM_PlatformCaps_TurnOffPll_ASPML1
523 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_HTLINKCONTROL
),
524 PHM_PlatformCaps_EnableHTLinkControl
529 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_MVDDCONTROL
),
530 PHM_PlatformCaps_EnableMVDDControl
535 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL
),
536 PHM_PlatformCaps_ControlVDDCI
541 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_REGULATOR_HOT
),
542 PHM_PlatformCaps_RegulatorHot
547 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT
),
548 PHM_PlatformCaps_BootStateOnAlert
553 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT
),
554 PHM_PlatformCaps_DontWaitForVBlankOnAlert
559 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_BACO
),
560 PHM_PlatformCaps_BACO
565 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE
),
566 PHM_PlatformCaps_NewCACVoltage
571 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY
),
572 PHM_PlatformCaps_RevertGPIO5Polarity
577 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17
),
578 PHM_PlatformCaps_Thermal2GPIO17
583 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE
),
584 PHM_PlatformCaps_VRHotGPIOConfigurable
589 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_TEMP_INVERSION
),
590 PHM_PlatformCaps_TempInversion
595 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_EVV
),
601 0 != (powerplay_caps
& ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL
),
602 PHM_PlatformCaps_CombinePCCWithThermalSignal
607 0 != (powerplay_caps
& ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE
),
608 PHM_PlatformCaps_LoadPostProductionFirmware
613 0 != (powerplay_caps
& ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC
),
614 PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc
620 static PP_StateClassificationFlags
make_classification_flags(
621 struct pp_hwmgr
*hwmgr
,
622 USHORT classification
,
623 USHORT classification2
)
625 PP_StateClassificationFlags result
= 0;
627 if (classification
& ATOM_PPLIB_CLASSIFICATION_BOOT
)
628 result
|= PP_StateClassificationFlag_Boot
;
630 if (classification
& ATOM_PPLIB_CLASSIFICATION_THERMAL
)
631 result
|= PP_StateClassificationFlag_Thermal
;
634 ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE
)
635 result
|= PP_StateClassificationFlag_LimitedPowerSource
;
637 if (classification
& ATOM_PPLIB_CLASSIFICATION_REST
)
638 result
|= PP_StateClassificationFlag_Rest
;
640 if (classification
& ATOM_PPLIB_CLASSIFICATION_FORCED
)
641 result
|= PP_StateClassificationFlag_Forced
;
643 if (classification
& ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE
)
644 result
|= PP_StateClassificationFlag_3DPerformance
;
647 if (classification
& ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE
)
648 result
|= PP_StateClassificationFlag_ACOverdriveTemplate
;
650 if (classification
& ATOM_PPLIB_CLASSIFICATION_UVDSTATE
)
651 result
|= PP_StateClassificationFlag_Uvd
;
653 if (classification
& ATOM_PPLIB_CLASSIFICATION_HDSTATE
)
654 result
|= PP_StateClassificationFlag_UvdHD
;
656 if (classification
& ATOM_PPLIB_CLASSIFICATION_SDSTATE
)
657 result
|= PP_StateClassificationFlag_UvdSD
;
659 if (classification
& ATOM_PPLIB_CLASSIFICATION_HD2STATE
)
660 result
|= PP_StateClassificationFlag_HD2
;
662 if (classification
& ATOM_PPLIB_CLASSIFICATION_ACPI
)
663 result
|= PP_StateClassificationFlag_ACPI
;
665 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2
)
666 result
|= PP_StateClassificationFlag_LimitedPowerSource_2
;
669 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_ULV
)
670 result
|= PP_StateClassificationFlag_ULV
;
672 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_MVC
)
673 result
|= PP_StateClassificationFlag_UvdMVC
;
678 static int init_non_clock_fields(struct pp_hwmgr
*hwmgr
,
679 struct pp_power_state
*ps
,
681 const ATOM_PPLIB_NONCLOCK_INFO
*pnon_clock_info
) {
682 unsigned long rrr_index
;
685 ps
->classification
.ui_label
= (le16_to_cpu(pnon_clock_info
->usClassification
) &
686 ATOM_PPLIB_CLASSIFICATION_UI_MASK
) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT
;
687 ps
->classification
.flags
= make_classification_flags(hwmgr
,
688 le16_to_cpu(pnon_clock_info
->usClassification
),
689 le16_to_cpu(pnon_clock_info
->usClassification2
));
691 ps
->classification
.temporary_state
= false;
692 ps
->classification
.to_be_deleted
= false;
693 tmp
= le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
694 ATOM_PPLIB_SINGLE_DISPLAY_ONLY
;
696 ps
->validation
.singleDisplayOnly
= (0 != tmp
);
698 tmp
= le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
699 ATOM_PPLIB_DISALLOW_ON_DC
;
701 ps
->validation
.disallowOnDC
= (0 != tmp
);
703 ps
->pcie
.lanes
= ((le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
704 ATOM_PPLIB_PCIE_LINK_WIDTH_MASK
) >>
705 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT
) + 1;
709 ps
->display
.disableFrameModulation
= false;
711 rrr_index
= (le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
712 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK
) >>
713 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT
;
715 if (rrr_index
!= ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED
) {
716 static const uint8_t look_up
[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK
>> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT
) + 1] = \
719 ps
->display
.refreshrateSource
= PP_RefreshrateSource_Explicit
;
720 ps
->display
.explicitRefreshrate
= look_up
[rrr_index
];
721 ps
->display
.limitRefreshrate
= true;
723 if (ps
->display
.explicitRefreshrate
== 0)
724 ps
->display
.limitRefreshrate
= false;
726 ps
->display
.limitRefreshrate
= false;
728 tmp
= le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
729 ATOM_PPLIB_ENABLE_VARIBRIGHT
;
731 ps
->display
.enableVariBright
= (0 != tmp
);
733 tmp
= le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
734 ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF
;
736 ps
->memory
.dllOff
= (0 != tmp
);
738 ps
->memory
.m3arb
= (le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
739 ATOM_PPLIB_M3ARB_MASK
) >> ATOM_PPLIB_M3ARB_SHIFT
;
741 ps
->temperatures
.min
= PP_TEMPERATURE_UNITS_PER_CENTIGRADES
*
742 pnon_clock_info
->ucMinTemperature
;
744 ps
->temperatures
.max
= PP_TEMPERATURE_UNITS_PER_CENTIGRADES
*
745 pnon_clock_info
->ucMaxTemperature
;
747 tmp
= le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
748 ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING
;
750 ps
->software
.disableLoadBalancing
= tmp
;
752 tmp
= le32_to_cpu(pnon_clock_info
->ulCapsAndSettings
) &
753 ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS
;
755 ps
->software
.enableSleepForTimestamps
= (0 != tmp
);
757 ps
->validation
.supportedPowerLevels
= pnon_clock_info
->ucRequiredPower
;
759 if (ATOM_PPLIB_NONCLOCKINFO_VER1
< version
) {
760 ps
->uvd_clocks
.VCLK
= le32_to_cpu(pnon_clock_info
->ulVCLK
);
761 ps
->uvd_clocks
.DCLK
= le32_to_cpu(pnon_clock_info
->ulDCLK
);
763 ps
->uvd_clocks
.VCLK
= 0;
764 ps
->uvd_clocks
.DCLK
= 0;
770 static ULONG
size_of_entry_v2(ULONG num_dpm_levels
)
772 return (sizeof(UCHAR
) + sizeof(UCHAR
) +
773 (num_dpm_levels
* sizeof(UCHAR
)));
776 static const ATOM_PPLIB_STATE_V2
*get_state_entry_v2(
777 const StateArray
* pstate_arrays
,
781 const ATOM_PPLIB_STATE_V2
*pstate
;
783 pstate
= pstate_arrays
->states
;
784 if (entry_index
<= pstate_arrays
->ucNumEntries
) {
785 for (i
= 0; i
< entry_index
; i
++)
786 pstate
= (ATOM_PPLIB_STATE_V2
*)(
787 (unsigned long)pstate
+
788 size_of_entry_v2(pstate
->ucNumDPMLevels
));
793 static const unsigned char soft_dummy_pp_table
[] = {
794 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
796 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
799 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
800 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,
805 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
806 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,
807 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
808 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,
809 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,
810 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,
811 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,
812 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,
813 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,
814 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,
815 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,
816 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,
817 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,
818 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,
819 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,
820 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,
821 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,
822 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,
823 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,
827 static const ATOM_PPLIB_POWERPLAYTABLE
*get_powerplay_table(
828 struct pp_hwmgr
*hwmgr
)
830 const void *table_addr
= hwmgr
->soft_pp_table
;
835 if (hwmgr
->chip_id
== CHIP_RAVEN
) {
836 table_addr
= &soft_dummy_pp_table
[0];
837 hwmgr
->soft_pp_table
= &soft_dummy_pp_table
[0];
838 hwmgr
->soft_pp_table_size
= sizeof(soft_dummy_pp_table
);
840 table_addr
= smu_atom_get_data_table(hwmgr
->adev
,
841 GetIndexIntoMasterTable(DATA
, PowerPlayInfo
),
842 &size
, &frev
, &crev
);
843 hwmgr
->soft_pp_table
= table_addr
;
844 hwmgr
->soft_pp_table_size
= size
;
848 return (const ATOM_PPLIB_POWERPLAYTABLE
*)table_addr
;
851 int pp_tables_get_response_times(struct pp_hwmgr
*hwmgr
,
852 uint32_t *vol_rep_time
, uint32_t *bb_rep_time
)
854 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_tab
= get_powerplay_table(hwmgr
);
856 PP_ASSERT_WITH_CODE(NULL
!= powerplay_tab
,
857 "Missing PowerPlay Table!", return -EINVAL
);
859 *vol_rep_time
= (uint32_t)le16_to_cpu(powerplay_tab
->usVoltageTime
);
860 *bb_rep_time
= (uint32_t)le16_to_cpu(powerplay_tab
->usBackbiasTime
);
865 int pp_tables_get_num_of_entries(struct pp_hwmgr
*hwmgr
,
866 unsigned long *num_of_entries
)
868 const StateArray
*pstate_arrays
;
869 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
= get_powerplay_table(hwmgr
);
871 if (powerplay_table
== NULL
)
874 if (powerplay_table
->sHeader
.ucTableFormatRevision
>= 6) {
875 pstate_arrays
= (StateArray
*)(((unsigned long)powerplay_table
) +
876 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
878 *num_of_entries
= (unsigned long)(pstate_arrays
->ucNumEntries
);
880 *num_of_entries
= (unsigned long)(powerplay_table
->ucNumStates
);
885 int pp_tables_get_entry(struct pp_hwmgr
*hwmgr
,
886 unsigned long entry_index
,
887 struct pp_power_state
*ps
,
888 pp_tables_hw_clock_info_callback func
)
891 const StateArray
*pstate_arrays
;
892 const ATOM_PPLIB_STATE_V2
*pstate_entry_v2
;
893 const ATOM_PPLIB_NONCLOCK_INFO
*pnon_clock_info
;
894 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
= get_powerplay_table(hwmgr
);
898 const ClockInfoArray
*pclock_arrays
;
900 const NonClockInfoArray
*pnon_clock_arrays
;
902 const ATOM_PPLIB_STATE
*pstate_entry
;
904 if (powerplay_table
== NULL
)
907 ps
->classification
.bios_index
= entry_index
;
909 if (powerplay_table
->sHeader
.ucTableFormatRevision
>= 6) {
910 pstate_arrays
= (StateArray
*)(((unsigned long)powerplay_table
) +
911 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
913 if (entry_index
> pstate_arrays
->ucNumEntries
)
916 pstate_entry_v2
= get_state_entry_v2(pstate_arrays
, entry_index
);
917 pclock_arrays
= (ClockInfoArray
*)(((unsigned long)powerplay_table
) +
918 le16_to_cpu(powerplay_table
->usClockInfoArrayOffset
));
920 pnon_clock_arrays
= (NonClockInfoArray
*)(((unsigned long)powerplay_table
) +
921 le16_to_cpu(powerplay_table
->usNonClockInfoArrayOffset
));
923 pnon_clock_info
= (ATOM_PPLIB_NONCLOCK_INFO
*)((unsigned long)(pnon_clock_arrays
->nonClockInfo
) +
924 (pstate_entry_v2
->nonClockInfoIndex
* pnon_clock_arrays
->ucEntrySize
));
926 result
= init_non_clock_fields(hwmgr
, ps
, pnon_clock_arrays
->ucEntrySize
, pnon_clock_info
);
928 for (i
= 0; i
< pstate_entry_v2
->ucNumDPMLevels
; i
++) {
929 const void *pclock_info
= (const void *)(
930 (unsigned long)(pclock_arrays
->clockInfo
) +
931 (pstate_entry_v2
->clockInfoIndex
[i
] * pclock_arrays
->ucEntrySize
));
932 res
= func(hwmgr
, &ps
->hardware
, i
, pclock_info
);
933 if ((0 == result
) && (0 != res
))
937 if (entry_index
> powerplay_table
->ucNumStates
)
940 pstate_entry
= (ATOM_PPLIB_STATE
*)((unsigned long)powerplay_table
+
941 le16_to_cpu(powerplay_table
->usStateArrayOffset
) +
942 entry_index
* powerplay_table
->ucStateEntrySize
);
944 pnon_clock_info
= (ATOM_PPLIB_NONCLOCK_INFO
*)((unsigned long)powerplay_table
+
945 le16_to_cpu(powerplay_table
->usNonClockInfoArrayOffset
) +
946 pstate_entry
->ucNonClockStateIndex
*
947 powerplay_table
->ucNonClockSize
);
949 result
= init_non_clock_fields(hwmgr
, ps
,
950 powerplay_table
->ucNonClockSize
,
953 for (i
= 0; i
< powerplay_table
->ucStateEntrySize
-1; i
++) {
954 const void *pclock_info
= (const void *)((unsigned long)powerplay_table
+
955 le16_to_cpu(powerplay_table
->usClockInfoArrayOffset
) +
956 pstate_entry
->ucClockStateIndices
[i
] *
957 powerplay_table
->ucClockInfoSize
);
959 int res
= func(hwmgr
, &ps
->hardware
, i
, pclock_info
);
961 if ((0 == result
) && (0 != res
))
966 if ((0 == result
) && (0 != (ps
->classification
.flags
& PP_StateClassificationFlag_Boot
))) {
967 if (hwmgr
->chip_family
< AMDGPU_FAMILY_RV
)
968 result
= hwmgr
->hwmgr_func
->patch_boot_state(hwmgr
, &(ps
->hardware
));
974 static int init_powerplay_tables(
975 struct pp_hwmgr
*hwmgr
,
976 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
983 static int init_thermal_controller(
984 struct pp_hwmgr
*hwmgr
,
985 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
990 static int init_overdrive_limits_V1_4(struct pp_hwmgr
*hwmgr
,
991 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
,
992 const ATOM_FIRMWARE_INFO_V1_4
*fw_info
)
994 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
995 le32_to_cpu(fw_info
->ulASICMaxEngineClock
);
997 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
=
998 le32_to_cpu(fw_info
->ulASICMaxMemoryClock
);
1000 hwmgr
->platform_descriptor
.maxOverdriveVDDC
=
1001 le32_to_cpu(fw_info
->ul3DAccelerationEngineClock
) & 0x7FF;
1003 hwmgr
->platform_descriptor
.minOverdriveVDDC
=
1004 le16_to_cpu(fw_info
->usBootUpVDDCVoltage
);
1006 hwmgr
->platform_descriptor
.maxOverdriveVDDC
=
1007 le16_to_cpu(fw_info
->usBootUpVDDCVoltage
);
1009 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
1013 static int init_overdrive_limits_V2_1(struct pp_hwmgr
*hwmgr
,
1014 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
,
1015 const ATOM_FIRMWARE_INFO_V2_1
*fw_info
)
1017 const ATOM_PPLIB_POWERPLAYTABLE3
*powerplay_table3
;
1018 const ATOM_PPLIB_EXTENDEDHEADER
*header
;
1020 if (le16_to_cpu(powerplay_table
->usTableSize
) <
1021 sizeof(ATOM_PPLIB_POWERPLAYTABLE3
))
1024 powerplay_table3
= (const ATOM_PPLIB_POWERPLAYTABLE3
*)powerplay_table
;
1026 if (0 == powerplay_table3
->usExtendendedHeaderOffset
)
1029 header
= (ATOM_PPLIB_EXTENDEDHEADER
*)(((unsigned long) powerplay_table
) +
1030 le16_to_cpu(powerplay_table3
->usExtendendedHeaderOffset
));
1032 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
= le32_to_cpu(header
->ulMaxEngineClock
);
1033 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
= le32_to_cpu(header
->ulMaxMemoryClock
);
1036 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
1037 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
1038 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
1043 static int init_overdrive_limits(struct pp_hwmgr
*hwmgr
,
1044 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
1050 const ATOM_COMMON_TABLE_HEADER
*fw_info
= NULL
;
1052 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
= 0;
1053 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
= 0;
1054 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
1055 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
1056 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
1058 if (hwmgr
->chip_id
== CHIP_RAVEN
)
1061 /* We assume here that fw_info is unchanged if this call fails.*/
1062 fw_info
= smu_atom_get_data_table(hwmgr
->adev
,
1063 GetIndexIntoMasterTable(DATA
, FirmwareInfo
),
1064 &size
, &frev
, &crev
);
1066 if ((fw_info
->ucTableFormatRevision
== 1)
1067 && (le16_to_cpu(fw_info
->usStructureSize
) >= sizeof(ATOM_FIRMWARE_INFO_V1_4
)))
1068 result
= init_overdrive_limits_V1_4(hwmgr
,
1070 (const ATOM_FIRMWARE_INFO_V1_4
*)fw_info
);
1072 else if ((fw_info
->ucTableFormatRevision
== 2)
1073 && (le16_to_cpu(fw_info
->usStructureSize
) >= sizeof(ATOM_FIRMWARE_INFO_V2_1
)))
1074 result
= init_overdrive_limits_V2_1(hwmgr
,
1076 (const ATOM_FIRMWARE_INFO_V2_1
*)fw_info
);
1081 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr
*hwmgr
,
1082 struct phm_uvd_clock_voltage_dependency_table
**ptable
,
1083 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table
*table
,
1084 const UVDClockInfoArray
*array
)
1086 unsigned long table_size
, i
;
1087 struct phm_uvd_clock_voltage_dependency_table
*uvd_table
;
1089 table_size
= sizeof(unsigned long) +
1090 sizeof(struct phm_uvd_clock_voltage_dependency_table
) *
1093 uvd_table
= kzalloc(table_size
, GFP_KERNEL
);
1094 if (NULL
== uvd_table
)
1097 uvd_table
->count
= table
->numEntries
;
1099 for (i
= 0; i
< table
->numEntries
; i
++) {
1100 const UVDClockInfo
*entry
=
1101 &array
->entries
[table
->entries
[i
].ucUVDClockInfoIndex
];
1102 uvd_table
->entries
[i
].v
= (unsigned long)le16_to_cpu(table
->entries
[i
].usVoltage
);
1103 uvd_table
->entries
[i
].vclk
= ((unsigned long)entry
->ucVClkHigh
<< 16)
1104 | le16_to_cpu(entry
->usVClkLow
);
1105 uvd_table
->entries
[i
].dclk
= ((unsigned long)entry
->ucDClkHigh
<< 16)
1106 | le16_to_cpu(entry
->usDClkLow
);
1109 *ptable
= uvd_table
;
1114 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr
*hwmgr
,
1115 struct phm_vce_clock_voltage_dependency_table
**ptable
,
1116 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table
*table
,
1117 const VCEClockInfoArray
*array
)
1119 unsigned long table_size
, i
;
1120 struct phm_vce_clock_voltage_dependency_table
*vce_table
= NULL
;
1122 table_size
= sizeof(unsigned long) +
1123 sizeof(struct phm_vce_clock_voltage_dependency_table
)
1124 * table
->numEntries
;
1126 vce_table
= kzalloc(table_size
, GFP_KERNEL
);
1127 if (NULL
== vce_table
)
1130 vce_table
->count
= table
->numEntries
;
1131 for (i
= 0; i
< table
->numEntries
; i
++) {
1132 const VCEClockInfo
*entry
= &array
->entries
[table
->entries
[i
].ucVCEClockInfoIndex
];
1134 vce_table
->entries
[i
].v
= (unsigned long)le16_to_cpu(table
->entries
[i
].usVoltage
);
1135 vce_table
->entries
[i
].evclk
= ((unsigned long)entry
->ucEVClkHigh
<< 16)
1136 | le16_to_cpu(entry
->usEVClkLow
);
1137 vce_table
->entries
[i
].ecclk
= ((unsigned long)entry
->ucECClkHigh
<< 16)
1138 | le16_to_cpu(entry
->usECClkLow
);
1141 *ptable
= vce_table
;
1146 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr
*hwmgr
,
1147 struct phm_samu_clock_voltage_dependency_table
**ptable
,
1148 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table
*table
)
1150 unsigned long table_size
, i
;
1151 struct phm_samu_clock_voltage_dependency_table
*samu_table
;
1153 table_size
= sizeof(unsigned long) +
1154 sizeof(struct phm_samu_clock_voltage_dependency_table
) *
1157 samu_table
= kzalloc(table_size
, GFP_KERNEL
);
1158 if (NULL
== samu_table
)
1161 samu_table
->count
= table
->numEntries
;
1163 for (i
= 0; i
< table
->numEntries
; i
++) {
1164 samu_table
->entries
[i
].v
= (unsigned long)le16_to_cpu(table
->entries
[i
].usVoltage
);
1165 samu_table
->entries
[i
].samclk
= ((unsigned long)table
->entries
[i
].ucSAMClockHigh
<< 16)
1166 | le16_to_cpu(table
->entries
[i
].usSAMClockLow
);
1169 *ptable
= samu_table
;
1174 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr
*hwmgr
,
1175 struct phm_acp_clock_voltage_dependency_table
**ptable
,
1176 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table
*table
)
1178 unsigned table_size
, i
;
1179 struct phm_acp_clock_voltage_dependency_table
*acp_table
;
1181 table_size
= sizeof(unsigned long) +
1182 sizeof(struct phm_acp_clock_voltage_dependency_table
) *
1185 acp_table
= kzalloc(table_size
, GFP_KERNEL
);
1186 if (NULL
== acp_table
)
1189 acp_table
->count
= (unsigned long)table
->numEntries
;
1191 for (i
= 0; i
< table
->numEntries
; i
++) {
1192 acp_table
->entries
[i
].v
= (unsigned long)le16_to_cpu(table
->entries
[i
].usVoltage
);
1193 acp_table
->entries
[i
].acpclk
= ((unsigned long)table
->entries
[i
].ucACPClockHigh
<< 16)
1194 | le16_to_cpu(table
->entries
[i
].usACPClockLow
);
1197 *ptable
= acp_table
;
1202 static int init_clock_voltage_dependency(struct pp_hwmgr
*hwmgr
,
1203 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
1205 ATOM_PPLIB_Clock_Voltage_Dependency_Table
*table
;
1206 ATOM_PPLIB_Clock_Voltage_Limit_Table
*limit_table
;
1209 uint16_t vce_clock_info_array_offset
;
1210 uint16_t uvd_clock_info_array_offset
;
1211 uint16_t table_offset
;
1213 hwmgr
->dyn_state
.vddc_dependency_on_sclk
= NULL
;
1214 hwmgr
->dyn_state
.vddci_dependency_on_mclk
= NULL
;
1215 hwmgr
->dyn_state
.vddc_dependency_on_mclk
= NULL
;
1216 hwmgr
->dyn_state
.vddc_dep_on_dal_pwrl
= NULL
;
1217 hwmgr
->dyn_state
.mvdd_dependency_on_mclk
= NULL
;
1218 hwmgr
->dyn_state
.vce_clock_voltage_dependency_table
= NULL
;
1219 hwmgr
->dyn_state
.uvd_clock_voltage_dependency_table
= NULL
;
1220 hwmgr
->dyn_state
.samu_clock_voltage_dependency_table
= NULL
;
1221 hwmgr
->dyn_state
.acp_clock_voltage_dependency_table
= NULL
;
1222 hwmgr
->dyn_state
.ppm_parameter_table
= NULL
;
1223 hwmgr
->dyn_state
.vdd_gfx_dependency_on_sclk
= NULL
;
1225 vce_clock_info_array_offset
= get_vce_clock_info_array_offset(
1226 hwmgr
, powerplay_table
);
1227 table_offset
= get_vce_clock_voltage_limit_table_offset(hwmgr
,
1229 if (vce_clock_info_array_offset
> 0 && table_offset
> 0) {
1230 const VCEClockInfoArray
*array
= (const VCEClockInfoArray
*)
1231 (((unsigned long) powerplay_table
) +
1232 vce_clock_info_array_offset
);
1233 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table
*table
=
1234 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table
*)
1235 (((unsigned long) powerplay_table
) + table_offset
);
1236 result
= get_vce_clock_voltage_limit_table(hwmgr
,
1237 &hwmgr
->dyn_state
.vce_clock_voltage_dependency_table
,
1241 uvd_clock_info_array_offset
= get_uvd_clock_info_array_offset(hwmgr
, powerplay_table
);
1242 table_offset
= get_uvd_clock_voltage_limit_table_offset(hwmgr
, powerplay_table
);
1244 if (uvd_clock_info_array_offset
> 0 && table_offset
> 0) {
1245 const UVDClockInfoArray
*array
= (const UVDClockInfoArray
*)
1246 (((unsigned long) powerplay_table
) +
1247 uvd_clock_info_array_offset
);
1248 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table
*ptable
=
1249 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table
*)
1250 (((unsigned long) powerplay_table
) + table_offset
);
1251 result
= get_uvd_clock_voltage_limit_table(hwmgr
,
1252 &hwmgr
->dyn_state
.uvd_clock_voltage_dependency_table
, ptable
, array
);
1255 table_offset
= get_samu_clock_voltage_limit_table_offset(hwmgr
,
1258 if (table_offset
> 0) {
1259 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table
*ptable
=
1260 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table
*)
1261 (((unsigned long) powerplay_table
) + table_offset
);
1262 result
= get_samu_clock_voltage_limit_table(hwmgr
,
1263 &hwmgr
->dyn_state
.samu_clock_voltage_dependency_table
, ptable
);
1266 table_offset
= get_acp_clock_voltage_limit_table_offset(hwmgr
,
1269 if (table_offset
> 0) {
1270 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table
*ptable
=
1271 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table
*)
1272 (((unsigned long) powerplay_table
) + table_offset
);
1273 result
= get_acp_clock_voltage_limit_table(hwmgr
,
1274 &hwmgr
->dyn_state
.acp_clock_voltage_dependency_table
, ptable
);
1277 table_offset
= get_cacp_tdp_table_offset(hwmgr
, powerplay_table
);
1278 if (table_offset
> 0) {
1279 UCHAR rev_id
= *(UCHAR
*)(((unsigned long)powerplay_table
) + table_offset
);
1282 const ATOM_PPLIB_POWERTUNE_Table_V1
*tune_table
=
1283 (const ATOM_PPLIB_POWERTUNE_Table_V1
*)
1284 (((unsigned long) powerplay_table
) + table_offset
);
1285 result
= get_cac_tdp_table(hwmgr
, &hwmgr
->dyn_state
.cac_dtp_table
,
1286 &tune_table
->power_tune_table
,
1287 le16_to_cpu(tune_table
->usMaximumPowerDeliveryLimit
));
1288 hwmgr
->dyn_state
.cac_dtp_table
->usDefaultTargetOperatingTemp
=
1289 le16_to_cpu(tune_table
->usTjMax
);
1291 const ATOM_PPLIB_POWERTUNE_Table
*tune_table
=
1292 (const ATOM_PPLIB_POWERTUNE_Table
*)
1293 (((unsigned long) powerplay_table
) + table_offset
);
1294 result
= get_cac_tdp_table(hwmgr
,
1295 &hwmgr
->dyn_state
.cac_dtp_table
,
1296 &tune_table
->power_tune_table
, 255);
1300 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
1301 sizeof(ATOM_PPLIB_POWERPLAYTABLE4
)) {
1302 const ATOM_PPLIB_POWERPLAYTABLE4
*powerplay_table4
=
1303 (const ATOM_PPLIB_POWERPLAYTABLE4
*)powerplay_table
;
1304 if (0 != powerplay_table4
->usVddcDependencyOnSCLKOffset
) {
1305 table
= (ATOM_PPLIB_Clock_Voltage_Dependency_Table
*)
1306 (((unsigned long) powerplay_table4
) +
1307 le16_to_cpu(powerplay_table4
->usVddcDependencyOnSCLKOffset
));
1308 result
= get_clock_voltage_dependency_table(hwmgr
,
1309 &hwmgr
->dyn_state
.vddc_dependency_on_sclk
, table
);
1312 if (result
== 0 && (0 != powerplay_table4
->usVddciDependencyOnMCLKOffset
)) {
1313 table
= (ATOM_PPLIB_Clock_Voltage_Dependency_Table
*)
1314 (((unsigned long) powerplay_table4
) +
1315 le16_to_cpu(powerplay_table4
->usVddciDependencyOnMCLKOffset
));
1316 result
= get_clock_voltage_dependency_table(hwmgr
,
1317 &hwmgr
->dyn_state
.vddci_dependency_on_mclk
, table
);
1320 if (result
== 0 && (0 != powerplay_table4
->usVddcDependencyOnMCLKOffset
)) {
1321 table
= (ATOM_PPLIB_Clock_Voltage_Dependency_Table
*)
1322 (((unsigned long) powerplay_table4
) +
1323 le16_to_cpu(powerplay_table4
->usVddcDependencyOnMCLKOffset
));
1324 result
= get_clock_voltage_dependency_table(hwmgr
,
1325 &hwmgr
->dyn_state
.vddc_dependency_on_mclk
, table
);
1328 if (result
== 0 && (0 != powerplay_table4
->usMaxClockVoltageOnDCOffset
)) {
1329 limit_table
= (ATOM_PPLIB_Clock_Voltage_Limit_Table
*)
1330 (((unsigned long) powerplay_table4
) +
1331 le16_to_cpu(powerplay_table4
->usMaxClockVoltageOnDCOffset
));
1332 result
= get_clock_voltage_limit(hwmgr
,
1333 &hwmgr
->dyn_state
.max_clock_voltage_on_dc
, limit_table
);
1336 if (result
== 0 && (NULL
!= hwmgr
->dyn_state
.vddc_dependency_on_mclk
) &&
1337 (0 != hwmgr
->dyn_state
.vddc_dependency_on_mclk
->count
))
1338 result
= get_valid_clk(hwmgr
, &hwmgr
->dyn_state
.valid_mclk_values
,
1339 hwmgr
->dyn_state
.vddc_dependency_on_mclk
);
1341 if(result
== 0 && (NULL
!= hwmgr
->dyn_state
.vddc_dependency_on_sclk
) &&
1342 (0 != hwmgr
->dyn_state
.vddc_dependency_on_sclk
->count
))
1343 result
= get_valid_clk(hwmgr
,
1344 &hwmgr
->dyn_state
.valid_sclk_values
,
1345 hwmgr
->dyn_state
.vddc_dependency_on_sclk
);
1347 if (result
== 0 && (0 != powerplay_table4
->usMvddDependencyOnMCLKOffset
)) {
1348 table
= (ATOM_PPLIB_Clock_Voltage_Dependency_Table
*)
1349 (((unsigned long) powerplay_table4
) +
1350 le16_to_cpu(powerplay_table4
->usMvddDependencyOnMCLKOffset
));
1351 result
= get_clock_voltage_dependency_table(hwmgr
,
1352 &hwmgr
->dyn_state
.mvdd_dependency_on_mclk
, table
);
1356 table_offset
= get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr
,
1359 if (table_offset
> 0) {
1360 table
= (ATOM_PPLIB_Clock_Voltage_Dependency_Table
*)
1361 (((unsigned long) powerplay_table
) + table_offset
);
1362 result
= get_clock_voltage_dependency_table(hwmgr
,
1363 &hwmgr
->dyn_state
.vdd_gfx_dependency_on_sclk
, table
);
1369 static int get_cac_leakage_table(struct pp_hwmgr
*hwmgr
,
1370 struct phm_cac_leakage_table
**ptable
,
1371 const ATOM_PPLIB_CAC_Leakage_Table
*table
)
1373 struct phm_cac_leakage_table
*cac_leakage_table
;
1374 unsigned long table_size
, i
;
1376 if (hwmgr
== NULL
|| table
== NULL
|| ptable
== NULL
)
1379 table_size
= sizeof(ULONG
) +
1380 (sizeof(struct phm_cac_leakage_table
) * table
->ucNumEntries
);
1382 cac_leakage_table
= kzalloc(table_size
, GFP_KERNEL
);
1384 if (cac_leakage_table
== NULL
)
1387 cac_leakage_table
->count
= (ULONG
)table
->ucNumEntries
;
1389 for (i
= 0; i
< cac_leakage_table
->count
; i
++) {
1390 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
1391 PHM_PlatformCaps_EVV
)) {
1392 cac_leakage_table
->entries
[i
].Vddc1
= le16_to_cpu(table
->entries
[i
].usVddc1
);
1393 cac_leakage_table
->entries
[i
].Vddc2
= le16_to_cpu(table
->entries
[i
].usVddc2
);
1394 cac_leakage_table
->entries
[i
].Vddc3
= le16_to_cpu(table
->entries
[i
].usVddc3
);
1396 cac_leakage_table
->entries
[i
].Vddc
= le16_to_cpu(table
->entries
[i
].usVddc
);
1397 cac_leakage_table
->entries
[i
].Leakage
= le32_to_cpu(table
->entries
[i
].ulLeakageValue
);
1401 *ptable
= cac_leakage_table
;
1406 static int get_platform_power_management_table(struct pp_hwmgr
*hwmgr
,
1407 ATOM_PPLIB_PPM_Table
*atom_ppm_table
)
1409 struct phm_ppm_table
*ptr
= kzalloc(sizeof(struct phm_ppm_table
), GFP_KERNEL
);
1414 ptr
->ppm_design
= atom_ppm_table
->ucPpmDesign
;
1415 ptr
->cpu_core_number
= le16_to_cpu(atom_ppm_table
->usCpuCoreNumber
);
1416 ptr
->platform_tdp
= le32_to_cpu(atom_ppm_table
->ulPlatformTDP
);
1417 ptr
->small_ac_platform_tdp
= le32_to_cpu(atom_ppm_table
->ulSmallACPlatformTDP
);
1418 ptr
->platform_tdc
= le32_to_cpu(atom_ppm_table
->ulPlatformTDC
);
1419 ptr
->small_ac_platform_tdc
= le32_to_cpu(atom_ppm_table
->ulSmallACPlatformTDC
);
1420 ptr
->apu_tdp
= le32_to_cpu(atom_ppm_table
->ulApuTDP
);
1421 ptr
->dgpu_tdp
= le32_to_cpu(atom_ppm_table
->ulDGpuTDP
);
1422 ptr
->dgpu_ulv_power
= le32_to_cpu(atom_ppm_table
->ulDGpuUlvPower
);
1423 ptr
->tj_max
= le32_to_cpu(atom_ppm_table
->ulTjmax
);
1424 hwmgr
->dyn_state
.ppm_parameter_table
= ptr
;
1429 static int init_dpm2_parameters(struct pp_hwmgr
*hwmgr
,
1430 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
1434 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
1435 sizeof(ATOM_PPLIB_POWERPLAYTABLE5
)) {
1436 const ATOM_PPLIB_POWERPLAYTABLE5
*ptable5
=
1437 (const ATOM_PPLIB_POWERPLAYTABLE5
*)powerplay_table
;
1438 const ATOM_PPLIB_POWERPLAYTABLE4
*ptable4
=
1439 (const ATOM_PPLIB_POWERPLAYTABLE4
*)
1440 (&ptable5
->basicTable4
);
1441 const ATOM_PPLIB_POWERPLAYTABLE3
*ptable3
=
1442 (const ATOM_PPLIB_POWERPLAYTABLE3
*)
1443 (&ptable4
->basicTable3
);
1444 const ATOM_PPLIB_EXTENDEDHEADER
*extended_header
;
1445 uint16_t table_offset
;
1446 ATOM_PPLIB_PPM_Table
*atom_ppm_table
;
1448 hwmgr
->platform_descriptor
.TDPLimit
= le32_to_cpu(ptable5
->ulTDPLimit
);
1449 hwmgr
->platform_descriptor
.nearTDPLimit
= le32_to_cpu(ptable5
->ulNearTDPLimit
);
1451 hwmgr
->platform_descriptor
.TDPODLimit
= le16_to_cpu(ptable5
->usTDPODLimit
);
1452 hwmgr
->platform_descriptor
.TDPAdjustment
= 0;
1454 hwmgr
->platform_descriptor
.VidAdjustment
= 0;
1455 hwmgr
->platform_descriptor
.VidAdjustmentPolarity
= 0;
1456 hwmgr
->platform_descriptor
.VidMinLimit
= 0;
1457 hwmgr
->platform_descriptor
.VidMaxLimit
= 1500000;
1458 hwmgr
->platform_descriptor
.VidStep
= 6250;
1460 hwmgr
->platform_descriptor
.nearTDPLimitAdjusted
= le32_to_cpu(ptable5
->ulNearTDPLimit
);
1462 if (hwmgr
->platform_descriptor
.TDPODLimit
!= 0)
1463 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
1464 PHM_PlatformCaps_PowerControl
);
1466 hwmgr
->platform_descriptor
.SQRampingThreshold
= le32_to_cpu(ptable5
->ulSQRampingThreshold
);
1468 hwmgr
->platform_descriptor
.CACLeakage
= le32_to_cpu(ptable5
->ulCACLeakage
);
1470 hwmgr
->dyn_state
.cac_leakage_table
= NULL
;
1472 if (0 != ptable5
->usCACLeakageTableOffset
) {
1473 const ATOM_PPLIB_CAC_Leakage_Table
*pCAC_leakage_table
=
1474 (ATOM_PPLIB_CAC_Leakage_Table
*)(((unsigned long)ptable5
) +
1475 le16_to_cpu(ptable5
->usCACLeakageTableOffset
));
1476 result
= get_cac_leakage_table(hwmgr
,
1477 &hwmgr
->dyn_state
.cac_leakage_table
, pCAC_leakage_table
);
1480 hwmgr
->platform_descriptor
.LoadLineSlope
= le16_to_cpu(ptable5
->usLoadLineSlope
);
1482 hwmgr
->dyn_state
.ppm_parameter_table
= NULL
;
1484 if (0 != ptable3
->usExtendendedHeaderOffset
) {
1485 extended_header
= (const ATOM_PPLIB_EXTENDEDHEADER
*)
1486 (((unsigned long)powerplay_table
) +
1487 le16_to_cpu(ptable3
->usExtendendedHeaderOffset
));
1488 if ((extended_header
->usPPMTableOffset
> 0) &&
1489 le16_to_cpu(extended_header
->usSize
) >=
1490 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5
) {
1491 table_offset
= le16_to_cpu(extended_header
->usPPMTableOffset
);
1492 atom_ppm_table
= (ATOM_PPLIB_PPM_Table
*)
1493 (((unsigned long)powerplay_table
) + table_offset
);
1494 if (0 == get_platform_power_management_table(hwmgr
, atom_ppm_table
))
1495 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
1496 PHM_PlatformCaps_EnablePlatformPowerManagement
);
1503 static int init_phase_shedding_table(struct pp_hwmgr
*hwmgr
,
1504 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
)
1506 if (le16_to_cpu(powerplay_table
->usTableSize
) >=
1507 sizeof(ATOM_PPLIB_POWERPLAYTABLE4
)) {
1508 const ATOM_PPLIB_POWERPLAYTABLE4
*powerplay_table4
=
1509 (const ATOM_PPLIB_POWERPLAYTABLE4
*)powerplay_table
;
1511 if (0 != powerplay_table4
->usVddcPhaseShedLimitsTableOffset
) {
1512 const ATOM_PPLIB_PhaseSheddingLimits_Table
*ptable
=
1513 (ATOM_PPLIB_PhaseSheddingLimits_Table
*)
1514 (((unsigned long)powerplay_table4
) +
1515 le16_to_cpu(powerplay_table4
->usVddcPhaseShedLimitsTableOffset
));
1516 struct phm_phase_shedding_limits_table
*table
;
1517 unsigned long size
, i
;
1520 size
= sizeof(unsigned long) +
1521 (sizeof(struct phm_phase_shedding_limits_table
) *
1522 ptable
->ucNumEntries
);
1524 table
= kzalloc(size
, GFP_KERNEL
);
1529 table
->count
= (unsigned long)ptable
->ucNumEntries
;
1531 for (i
= 0; i
< table
->count
; i
++) {
1532 table
->entries
[i
].Voltage
= (unsigned long)le16_to_cpu(ptable
->entries
[i
].usVoltage
);
1533 table
->entries
[i
].Sclk
= ((unsigned long)ptable
->entries
[i
].ucSclkHigh
<< 16)
1534 | le16_to_cpu(ptable
->entries
[i
].usSclkLow
);
1535 table
->entries
[i
].Mclk
= ((unsigned long)ptable
->entries
[i
].ucMclkHigh
<< 16)
1536 | le16_to_cpu(ptable
->entries
[i
].usMclkLow
);
1538 hwmgr
->dyn_state
.vddc_phase_shed_limits_table
= table
;
1545 static int get_number_of_vce_state_table_entries(
1546 struct pp_hwmgr
*hwmgr
)
1548 const ATOM_PPLIB_POWERPLAYTABLE
*table
=
1549 get_powerplay_table(hwmgr
);
1550 const ATOM_PPLIB_VCE_State_Table
*vce_table
=
1551 get_vce_state_table(hwmgr
, table
);
1554 return vce_table
->numEntries
;
1559 static int get_vce_state_table_entry(struct pp_hwmgr
*hwmgr
,
1561 struct amd_vce_state
*vce_state
,
1563 unsigned long *flag
)
1565 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
= get_powerplay_table(hwmgr
);
1567 const ATOM_PPLIB_VCE_State_Table
*vce_state_table
= get_vce_state_table(hwmgr
, powerplay_table
);
1569 unsigned short vce_clock_info_array_offset
= get_vce_clock_info_array_offset(hwmgr
, powerplay_table
);
1571 const VCEClockInfoArray
*vce_clock_info_array
= (const VCEClockInfoArray
*)(((unsigned long) powerplay_table
) + vce_clock_info_array_offset
);
1573 const ClockInfoArray
*clock_arrays
= (ClockInfoArray
*)(((unsigned long)powerplay_table
) +
1574 le16_to_cpu(powerplay_table
->usClockInfoArrayOffset
));
1576 const ATOM_PPLIB_VCE_State_Record
*record
= &vce_state_table
->entries
[i
];
1578 const VCEClockInfo
*vce_clock_info
= &vce_clock_info_array
->entries
[record
->ucVCEClockInfoIndex
];
1580 unsigned long clockInfoIndex
= record
->ucClockInfoIndex
& 0x3F;
1582 *flag
= (record
->ucClockInfoIndex
>> NUM_BITS_CLOCK_INFO_ARRAY_INDEX
);
1584 vce_state
->evclk
= ((uint32_t)vce_clock_info
->ucEVClkHigh
<< 16) | le16_to_cpu(vce_clock_info
->usEVClkLow
);
1585 vce_state
->ecclk
= ((uint32_t)vce_clock_info
->ucECClkHigh
<< 16) | le16_to_cpu(vce_clock_info
->usECClkLow
);
1587 *clock_info
= (void *)((unsigned long)(clock_arrays
->clockInfo
) + (clockInfoIndex
* clock_arrays
->ucEntrySize
));
1593 static int pp_tables_initialize(struct pp_hwmgr
*hwmgr
)
1596 const ATOM_PPLIB_POWERPLAYTABLE
*powerplay_table
;
1598 if (hwmgr
->chip_id
== CHIP_RAVEN
)
1601 hwmgr
->need_pp_table_upload
= true;
1603 powerplay_table
= get_powerplay_table(hwmgr
);
1605 result
= init_powerplay_tables(hwmgr
, powerplay_table
);
1607 PP_ASSERT_WITH_CODE((result
== 0),
1608 "init_powerplay_tables failed", return result
);
1610 result
= set_platform_caps(hwmgr
,
1611 le32_to_cpu(powerplay_table
->ulPlatformCaps
));
1613 PP_ASSERT_WITH_CODE((result
== 0),
1614 "set_platform_caps failed", return result
);
1616 result
= init_thermal_controller(hwmgr
, powerplay_table
);
1618 PP_ASSERT_WITH_CODE((result
== 0),
1619 "init_thermal_controller failed", return result
);
1621 result
= init_overdrive_limits(hwmgr
, powerplay_table
);
1623 PP_ASSERT_WITH_CODE((result
== 0),
1624 "init_overdrive_limits failed", return result
);
1626 result
= init_clock_voltage_dependency(hwmgr
,
1629 PP_ASSERT_WITH_CODE((result
== 0),
1630 "init_clock_voltage_dependency failed", return result
);
1632 result
= init_dpm2_parameters(hwmgr
, powerplay_table
);
1634 PP_ASSERT_WITH_CODE((result
== 0),
1635 "init_dpm2_parameters failed", return result
);
1637 result
= init_phase_shedding_table(hwmgr
, powerplay_table
);
1639 PP_ASSERT_WITH_CODE((result
== 0),
1640 "init_phase_shedding_table failed", return result
);
1645 static int pp_tables_uninitialize(struct pp_hwmgr
*hwmgr
)
1647 if (hwmgr
->chip_id
== CHIP_RAVEN
)
1650 kfree(hwmgr
->dyn_state
.vddc_dependency_on_sclk
);
1651 hwmgr
->dyn_state
.vddc_dependency_on_sclk
= NULL
;
1653 kfree(hwmgr
->dyn_state
.vddci_dependency_on_mclk
);
1654 hwmgr
->dyn_state
.vddci_dependency_on_mclk
= NULL
;
1656 kfree(hwmgr
->dyn_state
.vddc_dependency_on_mclk
);
1657 hwmgr
->dyn_state
.vddc_dependency_on_mclk
= NULL
;
1659 kfree(hwmgr
->dyn_state
.mvdd_dependency_on_mclk
);
1660 hwmgr
->dyn_state
.mvdd_dependency_on_mclk
= NULL
;
1662 kfree(hwmgr
->dyn_state
.valid_mclk_values
);
1663 hwmgr
->dyn_state
.valid_mclk_values
= NULL
;
1665 kfree(hwmgr
->dyn_state
.valid_sclk_values
);
1666 hwmgr
->dyn_state
.valid_sclk_values
= NULL
;
1668 kfree(hwmgr
->dyn_state
.cac_leakage_table
);
1669 hwmgr
->dyn_state
.cac_leakage_table
= NULL
;
1671 kfree(hwmgr
->dyn_state
.vddc_phase_shed_limits_table
);
1672 hwmgr
->dyn_state
.vddc_phase_shed_limits_table
= NULL
;
1674 kfree(hwmgr
->dyn_state
.vce_clock_voltage_dependency_table
);
1675 hwmgr
->dyn_state
.vce_clock_voltage_dependency_table
= NULL
;
1677 kfree(hwmgr
->dyn_state
.uvd_clock_voltage_dependency_table
);
1678 hwmgr
->dyn_state
.uvd_clock_voltage_dependency_table
= NULL
;
1680 kfree(hwmgr
->dyn_state
.samu_clock_voltage_dependency_table
);
1681 hwmgr
->dyn_state
.samu_clock_voltage_dependency_table
= NULL
;
1683 kfree(hwmgr
->dyn_state
.acp_clock_voltage_dependency_table
);
1684 hwmgr
->dyn_state
.acp_clock_voltage_dependency_table
= NULL
;
1686 kfree(hwmgr
->dyn_state
.cac_dtp_table
);
1687 hwmgr
->dyn_state
.cac_dtp_table
= NULL
;
1689 kfree(hwmgr
->dyn_state
.ppm_parameter_table
);
1690 hwmgr
->dyn_state
.ppm_parameter_table
= NULL
;
1692 kfree(hwmgr
->dyn_state
.vdd_gfx_dependency_on_sclk
);
1693 hwmgr
->dyn_state
.vdd_gfx_dependency_on_sclk
= NULL
;
1698 const struct pp_table_func pptable_funcs
= {
1699 .pptable_init
= pp_tables_initialize
,
1700 .pptable_fini
= pp_tables_uninitialize
,
1701 .pptable_get_number_of_vce_state_table_entries
=
1702 get_number_of_vce_state_table_entries
,
1703 .pptable_get_vce_state_table_entry
=
1704 get_vce_state_table_entry
,