2 * Copyright 2018 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/delay.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
30 #include "amd_powerplay.h"
31 #include "vega20_smumgr.h"
32 #include "hardwaremanager.h"
33 #include "ppatomfwctrl.h"
34 #include "atomfirmware.h"
35 #include "cgs_common.h"
36 #include "vega20_powertune.h"
37 #include "vega20_inc.h"
38 #include "pppcielanes.h"
39 #include "vega20_hwmgr.h"
40 #include "vega20_processpptables.h"
41 #include "vega20_pptable.h"
42 #include "vega20_thermal.h"
43 #include "vega20_ppsmc.h"
45 #include "amd_pcie_helpers.h"
46 #include "ppinterrupt.h"
47 #include "pp_overdriver.h"
48 #include "pp_thermal.h"
49 #include "soc15_common.h"
50 #include "vega20_baco.h"
51 #include "smuio/smuio_9_0_offset.h"
52 #include "smuio/smuio_9_0_sh_mask.h"
53 #include "nbio/nbio_7_4_sh_mask.h"
55 #define smnPCIE_LC_SPEED_CNTL 0x11140290
56 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
58 static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
60 struct vega20_hwmgr *data =
61 (struct vega20_hwmgr *)(hwmgr->backend);
63 data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT;
64 data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT;
65 data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT;
66 data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT;
67 data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT;
69 data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT;
70 data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
71 data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
72 data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
73 data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
74 data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
75 data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
76 data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
77 data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
78 data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
79 data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
80 data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
81 data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
84 * Disable the following features for now:
93 data->registry_data.disallowed_features = 0xE0041C00;
94 /* ECC feature should be disabled on old SMUs */
95 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
96 hwmgr->smu_version = smum_get_argument(hwmgr);
97 if (hwmgr->smu_version < 0x282100)
98 data->registry_data.disallowed_features |= FEATURE_ECC_MASK;
100 data->registry_data.od_state_in_dc_support = 0;
101 data->registry_data.thermal_support = 1;
102 data->registry_data.skip_baco_hardware = 0;
104 data->registry_data.log_avfs_param = 0;
105 data->registry_data.sclk_throttle_low_notification = 1;
106 data->registry_data.force_dpm_high = 0;
107 data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
109 data->registry_data.didt_support = 0;
110 if (data->registry_data.didt_support) {
111 data->registry_data.didt_mode = 6;
112 data->registry_data.sq_ramping_support = 1;
113 data->registry_data.db_ramping_support = 0;
114 data->registry_data.td_ramping_support = 0;
115 data->registry_data.tcp_ramping_support = 0;
116 data->registry_data.dbr_ramping_support = 0;
117 data->registry_data.edc_didt_support = 1;
118 data->registry_data.gc_didt_support = 0;
119 data->registry_data.psm_didt_support = 0;
122 data->registry_data.pcie_lane_override = 0xff;
123 data->registry_data.pcie_speed_override = 0xff;
124 data->registry_data.pcie_clock_override = 0xffffffff;
125 data->registry_data.regulator_hot_gpio_support = 1;
126 data->registry_data.ac_dc_switch_gpio_support = 0;
127 data->registry_data.quick_transition_support = 0;
128 data->registry_data.zrpm_start_temp = 0xffff;
129 data->registry_data.zrpm_stop_temp = 0xffff;
130 data->registry_data.od8_feature_enable = 1;
131 data->registry_data.disable_water_mark = 0;
132 data->registry_data.disable_pp_tuning = 0;
133 data->registry_data.disable_xlpp_tuning = 0;
134 data->registry_data.disable_workload_policy = 0;
135 data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
136 data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
137 data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
138 data->registry_data.force_workload_policy_mask = 0;
139 data->registry_data.disable_3d_fs_detection = 0;
140 data->registry_data.fps_support = 1;
141 data->registry_data.disable_auto_wattman = 1;
142 data->registry_data.auto_wattman_debug = 0;
143 data->registry_data.auto_wattman_sample_period = 100;
144 data->registry_data.fclk_gfxclk_ratio = 0;
145 data->registry_data.auto_wattman_threshold = 50;
146 data->registry_data.gfxoff_controlled_by_driver = 1;
147 data->gfxoff_allowed = false;
148 data->counter_gfxoff = 0;
151 static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
153 struct vega20_hwmgr *data =
154 (struct vega20_hwmgr *)(hwmgr->backend);
155 struct amdgpu_device *adev = hwmgr->adev;
157 if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE)
158 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
159 PHM_PlatformCaps_ControlVDDCI);
161 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
162 PHM_PlatformCaps_TablelessHardwareInterface);
164 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
165 PHM_PlatformCaps_EnableSMU7ThermalManagement);
167 if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
168 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
169 PHM_PlatformCaps_UVDPowerGating);
171 if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
172 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
173 PHM_PlatformCaps_VCEPowerGating);
175 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
176 PHM_PlatformCaps_UnTabledHardwareInterface);
178 if (data->registry_data.od8_feature_enable)
179 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
180 PHM_PlatformCaps_OD8inACSupport);
182 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
183 PHM_PlatformCaps_ActivityReporting);
184 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
185 PHM_PlatformCaps_FanSpeedInTableIsRPM);
187 if (data->registry_data.od_state_in_dc_support) {
188 if (data->registry_data.od8_feature_enable)
189 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
190 PHM_PlatformCaps_OD8inDCSupport);
193 if (data->registry_data.thermal_support &&
194 data->registry_data.fuzzy_fan_control_support &&
195 hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
196 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
197 PHM_PlatformCaps_ODFuzzyFanControlSupport);
199 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
200 PHM_PlatformCaps_DynamicPowerManagement);
201 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
202 PHM_PlatformCaps_SMC);
203 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
204 PHM_PlatformCaps_ThermalPolicyDelay);
206 if (data->registry_data.force_dpm_high)
207 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
208 PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
210 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
211 PHM_PlatformCaps_DynamicUVDState);
213 if (data->registry_data.sclk_throttle_low_notification)
214 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
215 PHM_PlatformCaps_SclkThrottleLowNotification);
217 /* power tune caps */
218 /* assume disabled */
219 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
220 PHM_PlatformCaps_PowerContainment);
221 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
222 PHM_PlatformCaps_DiDtSupport);
223 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
224 PHM_PlatformCaps_SQRamping);
225 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
226 PHM_PlatformCaps_DBRamping);
227 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
228 PHM_PlatformCaps_TDRamping);
229 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
230 PHM_PlatformCaps_TCPRamping);
231 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
232 PHM_PlatformCaps_DBRRamping);
233 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
234 PHM_PlatformCaps_DiDtEDCEnable);
235 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
236 PHM_PlatformCaps_GCEDC);
237 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
238 PHM_PlatformCaps_PSM);
240 if (data->registry_data.didt_support) {
241 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
242 PHM_PlatformCaps_DiDtSupport);
243 if (data->registry_data.sq_ramping_support)
244 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
245 PHM_PlatformCaps_SQRamping);
246 if (data->registry_data.db_ramping_support)
247 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
248 PHM_PlatformCaps_DBRamping);
249 if (data->registry_data.td_ramping_support)
250 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
251 PHM_PlatformCaps_TDRamping);
252 if (data->registry_data.tcp_ramping_support)
253 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
254 PHM_PlatformCaps_TCPRamping);
255 if (data->registry_data.dbr_ramping_support)
256 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
257 PHM_PlatformCaps_DBRRamping);
258 if (data->registry_data.edc_didt_support)
259 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
260 PHM_PlatformCaps_DiDtEDCEnable);
261 if (data->registry_data.gc_didt_support)
262 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
263 PHM_PlatformCaps_GCEDC);
264 if (data->registry_data.psm_didt_support)
265 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
266 PHM_PlatformCaps_PSM);
269 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
270 PHM_PlatformCaps_RegulatorHot);
272 if (data->registry_data.ac_dc_switch_gpio_support) {
273 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
274 PHM_PlatformCaps_AutomaticDCTransition);
275 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
276 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
279 if (data->registry_data.quick_transition_support) {
280 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
281 PHM_PlatformCaps_AutomaticDCTransition);
282 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
283 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
284 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
285 PHM_PlatformCaps_Falcon_QuickTransition);
288 if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) {
289 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
290 PHM_PlatformCaps_LowestUclkReservedForUlv);
291 if (data->lowest_uclk_reserved_for_ulv == 1)
292 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
293 PHM_PlatformCaps_LowestUclkReservedForUlv);
296 if (data->registry_data.custom_fan_support)
297 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
298 PHM_PlatformCaps_CustomFanControlSupport);
303 static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr)
305 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
308 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
309 FEATURE_DPM_PREFETCHER_BIT;
310 data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
311 FEATURE_DPM_GFXCLK_BIT;
312 data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
313 FEATURE_DPM_UCLK_BIT;
314 data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
315 FEATURE_DPM_SOCCLK_BIT;
316 data->smu_features[GNLD_DPM_UVD].smu_feature_id =
318 data->smu_features[GNLD_DPM_VCE].smu_feature_id =
320 data->smu_features[GNLD_ULV].smu_feature_id =
322 data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
323 FEATURE_DPM_MP0CLK_BIT;
324 data->smu_features[GNLD_DPM_LINK].smu_feature_id =
325 FEATURE_DPM_LINK_BIT;
326 data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
327 FEATURE_DPM_DCEFCLK_BIT;
328 data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
329 FEATURE_DS_GFXCLK_BIT;
330 data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
331 FEATURE_DS_SOCCLK_BIT;
332 data->smu_features[GNLD_DS_LCLK].smu_feature_id =
334 data->smu_features[GNLD_PPT].smu_feature_id =
336 data->smu_features[GNLD_TDC].smu_feature_id =
338 data->smu_features[GNLD_THERMAL].smu_feature_id =
340 data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
341 FEATURE_GFX_PER_CU_CG_BIT;
342 data->smu_features[GNLD_RM].smu_feature_id =
344 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
345 FEATURE_DS_DCEFCLK_BIT;
346 data->smu_features[GNLD_ACDC].smu_feature_id =
348 data->smu_features[GNLD_VR0HOT].smu_feature_id =
350 data->smu_features[GNLD_VR1HOT].smu_feature_id =
352 data->smu_features[GNLD_FW_CTF].smu_feature_id =
354 data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
355 FEATURE_LED_DISPLAY_BIT;
356 data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
357 FEATURE_FAN_CONTROL_BIT;
358 data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
359 data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
360 data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
361 data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT;
362 data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT;
363 data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT;
364 data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT;
365 data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT;
366 data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT;
368 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
369 data->smu_features[i].smu_feature_bitmap =
370 (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
371 data->smu_features[i].allowed =
372 ((data->registry_data.disallowed_features >> i) & 1) ?
377 static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
382 static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
384 kfree(hwmgr->backend);
385 hwmgr->backend = NULL;
390 static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
392 struct vega20_hwmgr *data;
393 struct amdgpu_device *adev = hwmgr->adev;
395 data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL);
399 hwmgr->backend = data;
401 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
402 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
403 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
405 vega20_set_default_registry_data(hwmgr);
407 data->disable_dpm_mask = 0xff;
409 /* need to set voltage control types before EVV patching */
410 data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE;
411 data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE;
412 data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE;
414 data->water_marks_bitmap = 0;
415 data->avfs_exist = false;
417 vega20_set_features_platform_caps(hwmgr);
419 vega20_init_dpm_defaults(hwmgr);
421 /* Parse pptable data read from VBIOS */
422 vega20_set_private_data_based_on_pptable(hwmgr);
424 data->is_tlu_enabled = false;
426 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
427 VEGA20_MAX_HARDWARE_POWERLEVELS;
428 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
429 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
431 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
432 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
433 hwmgr->platform_descriptor.clockStep.engineClock = 500;
434 hwmgr->platform_descriptor.clockStep.memoryClock = 500;
436 data->total_active_cus = adev->gfx.cu_info.number;
437 data->is_custom_profile_set = false;
442 static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr)
444 struct vega20_hwmgr *data =
445 (struct vega20_hwmgr *)(hwmgr->backend);
447 data->low_sclk_interrupt_threshold = 0;
452 static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
454 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
457 ret = vega20_init_sclk_threshold(hwmgr);
458 PP_ASSERT_WITH_CODE(!ret,
459 "Failed to init sclk threshold!",
462 if (adev->in_baco_reset) {
463 adev->in_baco_reset = 0;
465 ret = vega20_baco_apply_vdci_flush_workaround(hwmgr);
467 pr_err("Failed to apply vega20 baco workaround!\n");
474 * @fn vega20_init_dpm_state
475 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff.
477 * @param dpm_state - the address of the DPM Table to initiailize.
480 static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state)
482 dpm_state->soft_min_level = 0x0;
483 dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT;
484 dpm_state->hard_min_level = 0x0;
485 dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT;
488 static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
489 PPCLK_e clk_id, uint32_t *num_of_levels)
493 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
494 PPSMC_MSG_GetDpmFreqByIndex,
495 (clk_id << 16 | 0xFF));
496 PP_ASSERT_WITH_CODE(!ret,
497 "[GetNumOfDpmLevel] failed to get dpm levels!",
500 *num_of_levels = smum_get_argument(hwmgr);
501 PP_ASSERT_WITH_CODE(*num_of_levels > 0,
502 "[GetNumOfDpmLevel] number of clk levels is invalid!",
508 static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
509 PPCLK_e clk_id, uint32_t index, uint32_t *clk)
513 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
514 PPSMC_MSG_GetDpmFreqByIndex,
515 (clk_id << 16 | index));
516 PP_ASSERT_WITH_CODE(!ret,
517 "[GetDpmFreqByIndex] failed to get dpm freq by index!",
520 *clk = smum_get_argument(hwmgr);
521 PP_ASSERT_WITH_CODE(*clk,
522 "[GetDpmFreqByIndex] clk value is invalid!",
528 static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
529 struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id)
532 uint32_t i, num_of_levels, clk;
534 ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels);
535 PP_ASSERT_WITH_CODE(!ret,
536 "[SetupSingleDpmTable] failed to get clk levels!",
539 dpm_table->count = num_of_levels;
541 for (i = 0; i < num_of_levels; i++) {
542 ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk);
543 PP_ASSERT_WITH_CODE(!ret,
544 "[SetupSingleDpmTable] failed to get clk of specific level!",
546 dpm_table->dpm_levels[i].value = clk;
547 dpm_table->dpm_levels[i].enabled = true;
553 static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr)
555 struct vega20_hwmgr *data =
556 (struct vega20_hwmgr *)(hwmgr->backend);
557 struct vega20_single_dpm_table *dpm_table;
560 dpm_table = &(data->dpm_table.gfx_table);
561 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
562 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
563 PP_ASSERT_WITH_CODE(!ret,
564 "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
567 dpm_table->count = 1;
568 dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
574 static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr)
576 struct vega20_hwmgr *data =
577 (struct vega20_hwmgr *)(hwmgr->backend);
578 struct vega20_single_dpm_table *dpm_table;
581 dpm_table = &(data->dpm_table.mem_table);
582 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
583 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
584 PP_ASSERT_WITH_CODE(!ret,
585 "[SetupDefaultDpmTable] failed to get memclk dpm levels!",
588 dpm_table->count = 1;
589 dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
596 * This function is to initialize all DPM state tables
597 * for SMU based on the dependency table.
598 * Dynamic state patching function will then trim these
599 * state tables to the allowed range based
600 * on the power policy or external client requests,
601 * such as UVD request, etc.
603 static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
605 struct vega20_hwmgr *data =
606 (struct vega20_hwmgr *)(hwmgr->backend);
607 struct vega20_single_dpm_table *dpm_table;
610 memset(&data->dpm_table, 0, sizeof(data->dpm_table));
613 dpm_table = &(data->dpm_table.soc_table);
614 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
615 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK);
616 PP_ASSERT_WITH_CODE(!ret,
617 "[SetupDefaultDpmTable] failed to get socclk dpm levels!",
620 dpm_table->count = 1;
621 dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100;
623 vega20_init_dpm_state(&(dpm_table->dpm_state));
626 dpm_table = &(data->dpm_table.gfx_table);
627 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
630 vega20_init_dpm_state(&(dpm_table->dpm_state));
633 dpm_table = &(data->dpm_table.mem_table);
634 ret = vega20_setup_memclk_dpm_table(hwmgr);
637 vega20_init_dpm_state(&(dpm_table->dpm_state));
640 dpm_table = &(data->dpm_table.eclk_table);
641 if (data->smu_features[GNLD_DPM_VCE].enabled) {
642 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK);
643 PP_ASSERT_WITH_CODE(!ret,
644 "[SetupDefaultDpmTable] failed to get eclk dpm levels!",
647 dpm_table->count = 1;
648 dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100;
650 vega20_init_dpm_state(&(dpm_table->dpm_state));
653 dpm_table = &(data->dpm_table.vclk_table);
654 if (data->smu_features[GNLD_DPM_UVD].enabled) {
655 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK);
656 PP_ASSERT_WITH_CODE(!ret,
657 "[SetupDefaultDpmTable] failed to get vclk dpm levels!",
660 dpm_table->count = 1;
661 dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100;
663 vega20_init_dpm_state(&(dpm_table->dpm_state));
666 dpm_table = &(data->dpm_table.dclk_table);
667 if (data->smu_features[GNLD_DPM_UVD].enabled) {
668 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK);
669 PP_ASSERT_WITH_CODE(!ret,
670 "[SetupDefaultDpmTable] failed to get dclk dpm levels!",
673 dpm_table->count = 1;
674 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100;
676 vega20_init_dpm_state(&(dpm_table->dpm_state));
679 dpm_table = &(data->dpm_table.dcef_table);
680 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
681 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK);
682 PP_ASSERT_WITH_CODE(!ret,
683 "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!",
686 dpm_table->count = 1;
687 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100;
689 vega20_init_dpm_state(&(dpm_table->dpm_state));
692 dpm_table = &(data->dpm_table.pixel_table);
693 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
694 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK);
695 PP_ASSERT_WITH_CODE(!ret,
696 "[SetupDefaultDpmTable] failed to get pixclk dpm levels!",
699 dpm_table->count = 0;
700 vega20_init_dpm_state(&(dpm_table->dpm_state));
703 dpm_table = &(data->dpm_table.display_table);
704 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
705 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK);
706 PP_ASSERT_WITH_CODE(!ret,
707 "[SetupDefaultDpmTable] failed to get dispclk dpm levels!",
710 dpm_table->count = 0;
711 vega20_init_dpm_state(&(dpm_table->dpm_state));
714 dpm_table = &(data->dpm_table.phy_table);
715 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
716 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK);
717 PP_ASSERT_WITH_CODE(!ret,
718 "[SetupDefaultDpmTable] failed to get phyclk dpm levels!",
721 dpm_table->count = 0;
722 vega20_init_dpm_state(&(dpm_table->dpm_state));
725 dpm_table = &(data->dpm_table.fclk_table);
726 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
727 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK);
728 PP_ASSERT_WITH_CODE(!ret,
729 "[SetupDefaultDpmTable] failed to get fclk dpm levels!",
732 dpm_table->count = 1;
733 dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100;
735 vega20_init_dpm_state(&(dpm_table->dpm_state));
737 /* save a copy of the default DPM table */
738 memcpy(&(data->golden_dpm_table), &(data->dpm_table),
739 sizeof(struct vega20_dpm_table));
745 * Initializes the SMC table and uploads it
747 * @param hwmgr the address of the powerplay hardware manager.
748 * @param pInput the pointer to input data (PowerState)
751 static int vega20_init_smc_table(struct pp_hwmgr *hwmgr)
754 struct vega20_hwmgr *data =
755 (struct vega20_hwmgr *)(hwmgr->backend);
756 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
757 struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
758 struct phm_ppt_v3_information *pptable_information =
759 (struct phm_ppt_v3_information *)hwmgr->pptable;
761 result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
762 PP_ASSERT_WITH_CODE(!result,
763 "[InitSMCTable] Failed to get vbios bootup values!",
766 data->vbios_boot_state.vddc = boot_up_values.usVddc;
767 data->vbios_boot_state.vddci = boot_up_values.usVddci;
768 data->vbios_boot_state.mvddc = boot_up_values.usMvddc;
769 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
770 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
771 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
772 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
773 data->vbios_boot_state.eclock = boot_up_values.ulEClk;
774 data->vbios_boot_state.vclock = boot_up_values.ulVClk;
775 data->vbios_boot_state.dclock = boot_up_values.ulDClk;
776 data->vbios_boot_state.fclock = boot_up_values.ulFClk;
777 data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
779 smum_send_msg_to_smc_with_parameter(hwmgr,
780 PPSMC_MSG_SetMinDeepSleepDcefclk,
781 (uint32_t)(data->vbios_boot_state.dcef_clock / 100));
783 memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
785 result = smum_smc_table_manager(hwmgr,
786 (uint8_t *)pp_table, TABLE_PPTABLE, false);
787 PP_ASSERT_WITH_CODE(!result,
788 "[InitSMCTable] Failed to upload PPtable!",
795 * Override PCIe link speed and link width for DPM Level 1. PPTable entries
796 * reflect the ASIC capabilities and not the system capabilities. For e.g.
797 * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch
798 * to DPM1, it fails as system doesn't support Gen4.
800 static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
802 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
803 struct vega20_hwmgr *data =
804 (struct vega20_hwmgr *)(hwmgr->backend);
805 uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg;
808 if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
810 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
812 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
814 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
817 if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
819 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
821 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
823 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
825 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
827 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
830 /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1
831 * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
832 * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
834 smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width;
835 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
836 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg);
837 PP_ASSERT_WITH_CODE(!ret,
838 "[OverridePcieParameters] Attempt to override pcie params failed!",
841 data->pcie_parameters_override = 1;
842 data->pcie_gen_level1 = pcie_gen;
843 data->pcie_width_level1 = pcie_width;
848 static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
850 struct vega20_hwmgr *data =
851 (struct vega20_hwmgr *)(hwmgr->backend);
852 uint32_t allowed_features_low = 0, allowed_features_high = 0;
856 for (i = 0; i < GNLD_FEATURES_MAX; i++)
857 if (data->smu_features[i].allowed)
858 data->smu_features[i].smu_feature_id > 31 ?
859 (allowed_features_high |=
860 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT)
862 (allowed_features_low |=
863 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT)
866 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
867 PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high);
868 PP_ASSERT_WITH_CODE(!ret,
869 "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!",
872 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
873 PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low);
874 PP_ASSERT_WITH_CODE(!ret,
875 "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
881 static int vega20_run_btc(struct pp_hwmgr *hwmgr)
883 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc);
886 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr)
888 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc);
891 static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr)
893 struct vega20_hwmgr *data =
894 (struct vega20_hwmgr *)(hwmgr->backend);
895 uint64_t features_enabled;
900 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
901 PPSMC_MSG_EnableAllSmuFeatures)) == 0,
902 "[EnableAllSMUFeatures] Failed to enable all smu features!",
905 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
906 PP_ASSERT_WITH_CODE(!ret,
907 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
910 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
911 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
913 data->smu_features[i].enabled = enabled;
914 data->smu_features[i].supported = enabled;
917 if (data->smu_features[i].allowed && !enabled)
918 pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i);
919 else if (!data->smu_features[i].allowed && enabled)
920 pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i);
927 static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr)
929 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
931 if (data->smu_features[GNLD_DPM_UCLK].enabled)
932 return smum_send_msg_to_smc_with_parameter(hwmgr,
933 PPSMC_MSG_SetUclkFastSwitch,
939 static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr)
941 struct vega20_hwmgr *data =
942 (struct vega20_hwmgr *)(hwmgr->backend);
944 return smum_send_msg_to_smc_with_parameter(hwmgr,
945 PPSMC_MSG_SetFclkGfxClkRatio,
946 data->registry_data.fclk_gfxclk_ratio);
949 static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr)
951 struct vega20_hwmgr *data =
952 (struct vega20_hwmgr *)(hwmgr->backend);
953 uint64_t features_enabled;
958 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
959 PPSMC_MSG_DisableAllSmuFeatures)) == 0,
960 "[DisableAllSMUFeatures] Failed to disable all smu features!",
963 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
964 PP_ASSERT_WITH_CODE(!ret,
965 "[DisableAllSMUFeatures] Failed to get enabled smc features!",
968 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
969 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
971 data->smu_features[i].enabled = enabled;
972 data->smu_features[i].supported = enabled;
978 static int vega20_od8_set_feature_capabilities(
979 struct pp_hwmgr *hwmgr)
981 struct phm_ppt_v3_information *pptable_information =
982 (struct phm_ppt_v3_information *)hwmgr->pptable;
983 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
984 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
985 struct vega20_od8_settings *od_settings = &(data->od8_settings);
987 od_settings->overdrive8_capabilities = 0;
989 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
990 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] &&
991 pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 &&
992 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 &&
993 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >=
994 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN]))
995 od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS;
997 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] &&
998 (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >=
999 pp_table->MinVoltageGfx / VOLTAGE_SCALE) &&
1000 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <=
1001 pp_table->MaxVoltageGfx / VOLTAGE_SCALE) &&
1002 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >=
1003 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1]))
1004 od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE;
1007 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
1008 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] =
1009 data->dpm_table.mem_table.dpm_levels[data->dpm_table.mem_table.count - 2].value;
1010 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] &&
1011 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 &&
1012 pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 &&
1013 (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >=
1014 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX]))
1015 od_settings->overdrive8_capabilities |= OD8_UCLK_MAX;
1018 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] &&
1019 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1020 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 &&
1021 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 &&
1022 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100)
1023 od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT;
1025 if (data->smu_features[GNLD_FAN_CONTROL].enabled) {
1026 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] &&
1027 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1028 pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 &&
1029 (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >=
1030 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT]))
1031 od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK;
1033 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] &&
1034 (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >=
1035 (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) &&
1036 pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 &&
1037 (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >=
1038 pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED]))
1039 od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN;
1042 if (data->smu_features[GNLD_THERMAL].enabled) {
1043 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] &&
1044 pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1045 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 &&
1046 (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >=
1047 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP]))
1048 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN;
1050 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] &&
1051 pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1052 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 &&
1053 (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >=
1054 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX]))
1055 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM;
1058 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE])
1059 od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE;
1061 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] &&
1062 pp_table->FanZeroRpmEnable)
1063 od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
1065 if (!od_settings->overdrive8_capabilities)
1066 hwmgr->od_enabled = false;
1071 static int vega20_od8_set_feature_id(
1072 struct pp_hwmgr *hwmgr)
1074 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1075 struct vega20_od8_settings *od_settings = &(data->od8_settings);
1077 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1078 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1080 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1083 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id =
1085 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id =
1089 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1090 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1092 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1094 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1096 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1098 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1100 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1103 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id =
1105 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id =
1107 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id =
1109 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id =
1111 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id =
1113 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id =
1117 if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1118 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX;
1120 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0;
1122 if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1123 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT;
1125 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0;
1127 if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1128 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1129 OD8_ACOUSTIC_LIMIT_SCLK;
1131 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id =
1134 if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1135 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1138 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id =
1141 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1142 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1143 OD8_TEMPERATURE_FAN;
1145 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id =
1148 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1149 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1150 OD8_TEMPERATURE_SYSTEM;
1152 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id =
1158 static int vega20_od8_get_gfx_clock_base_voltage(
1159 struct pp_hwmgr *hwmgr,
1165 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1166 PPSMC_MSG_GetAVFSVoltageByDpm,
1167 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq));
1168 PP_ASSERT_WITH_CODE(!ret,
1169 "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!",
1172 *voltage = smum_get_argument(hwmgr);
1173 *voltage = *voltage / VOLTAGE_SCALE;
1178 static int vega20_od8_initialize_default_settings(
1179 struct pp_hwmgr *hwmgr)
1181 struct phm_ppt_v3_information *pptable_information =
1182 (struct phm_ppt_v3_information *)hwmgr->pptable;
1183 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1184 struct vega20_od8_settings *od8_settings = &(data->od8_settings);
1185 OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table);
1188 /* Set Feature Capabilities */
1189 vega20_od8_set_feature_capabilities(hwmgr);
1191 /* Map FeatureID to individual settings */
1192 vega20_od8_set_feature_id(hwmgr);
1194 /* Set default values */
1195 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true);
1196 PP_ASSERT_WITH_CODE(!ret,
1197 "Failed to export over drive table!",
1200 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) {
1201 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1202 od_table->GfxclkFmin;
1203 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1204 od_table->GfxclkFmax;
1206 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value =
1208 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value =
1212 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) {
1213 od_table->GfxclkFreq1 = od_table->GfxclkFmin;
1214 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1215 od_table->GfxclkFreq1;
1217 od_table->GfxclkFreq3 = od_table->GfxclkFmax;
1218 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1219 od_table->GfxclkFreq3;
1221 od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2;
1222 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1223 od_table->GfxclkFreq2;
1225 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1226 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value),
1227 od_table->GfxclkFreq1),
1228 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1229 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0);
1230 od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value
1233 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1234 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value),
1235 od_table->GfxclkFreq2),
1236 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1237 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0);
1238 od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value
1241 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr,
1242 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value),
1243 od_table->GfxclkFreq3),
1244 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!",
1245 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0);
1246 od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value
1249 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value =
1251 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value =
1253 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value =
1255 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value =
1257 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value =
1259 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value =
1263 if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX)
1264 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1267 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value =
1270 if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT)
1271 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1272 od_table->OverDrivePct;
1274 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value =
1277 if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK)
1278 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1279 od_table->FanMaximumRpm;
1281 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value =
1284 if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN)
1285 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1286 od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100;
1288 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value =
1291 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN)
1292 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1293 od_table->FanTargetTemperature;
1295 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value =
1298 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM)
1299 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1300 od_table->MaxOpTemp;
1302 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value =
1305 for (i = 0; i < OD8_SETTING_COUNT; i++) {
1306 if (od8_settings->od8_settings_array[i].feature_id) {
1307 od8_settings->od8_settings_array[i].min_value =
1308 pptable_information->od_settings_min[i];
1309 od8_settings->od8_settings_array[i].max_value =
1310 pptable_information->od_settings_max[i];
1311 od8_settings->od8_settings_array[i].current_value =
1312 od8_settings->od8_settings_array[i].default_value;
1314 od8_settings->od8_settings_array[i].min_value =
1316 od8_settings->od8_settings_array[i].max_value =
1318 od8_settings->od8_settings_array[i].current_value =
1323 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false);
1324 PP_ASSERT_WITH_CODE(!ret,
1325 "Failed to import over drive table!",
1331 static int vega20_od8_set_settings(
1332 struct pp_hwmgr *hwmgr,
1336 OverDriveTable_t od_table;
1338 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1339 struct vega20_od8_single_setting *od8_settings =
1340 data->od8_settings.od8_settings_array;
1342 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true);
1343 PP_ASSERT_WITH_CODE(!ret,
1344 "Failed to export over drive table!",
1348 case OD8_SETTING_GFXCLK_FMIN:
1349 od_table.GfxclkFmin = (uint16_t)value;
1351 case OD8_SETTING_GFXCLK_FMAX:
1352 if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value ||
1353 value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value)
1356 od_table.GfxclkFmax = (uint16_t)value;
1358 case OD8_SETTING_GFXCLK_FREQ1:
1359 od_table.GfxclkFreq1 = (uint16_t)value;
1361 case OD8_SETTING_GFXCLK_VOLTAGE1:
1362 od_table.GfxclkVolt1 = (uint16_t)value;
1364 case OD8_SETTING_GFXCLK_FREQ2:
1365 od_table.GfxclkFreq2 = (uint16_t)value;
1367 case OD8_SETTING_GFXCLK_VOLTAGE2:
1368 od_table.GfxclkVolt2 = (uint16_t)value;
1370 case OD8_SETTING_GFXCLK_FREQ3:
1371 od_table.GfxclkFreq3 = (uint16_t)value;
1373 case OD8_SETTING_GFXCLK_VOLTAGE3:
1374 od_table.GfxclkVolt3 = (uint16_t)value;
1376 case OD8_SETTING_UCLK_FMAX:
1377 if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
1378 value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value)
1380 od_table.UclkFmax = (uint16_t)value;
1382 case OD8_SETTING_POWER_PERCENTAGE:
1383 od_table.OverDrivePct = (int16_t)value;
1385 case OD8_SETTING_FAN_ACOUSTIC_LIMIT:
1386 od_table.FanMaximumRpm = (uint16_t)value;
1388 case OD8_SETTING_FAN_MIN_SPEED:
1389 od_table.FanMinimumPwm = (uint16_t)value;
1391 case OD8_SETTING_FAN_TARGET_TEMP:
1392 od_table.FanTargetTemperature = (uint16_t)value;
1394 case OD8_SETTING_OPERATING_TEMP_MAX:
1395 od_table.MaxOpTemp = (uint16_t)value;
1399 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false);
1400 PP_ASSERT_WITH_CODE(!ret,
1401 "Failed to import over drive table!",
1407 static int vega20_get_sclk_od(
1408 struct pp_hwmgr *hwmgr)
1410 struct vega20_hwmgr *data = hwmgr->backend;
1411 struct vega20_single_dpm_table *sclk_table =
1412 &(data->dpm_table.gfx_table);
1413 struct vega20_single_dpm_table *golden_sclk_table =
1414 &(data->golden_dpm_table.gfx_table);
1415 int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
1416 int golden_value = golden_sclk_table->dpm_levels
1417 [golden_sclk_table->count - 1].value;
1420 value -= golden_value;
1421 value = DIV_ROUND_UP(value * 100, golden_value);
1426 static int vega20_set_sclk_od(
1427 struct pp_hwmgr *hwmgr, uint32_t value)
1429 struct vega20_hwmgr *data = hwmgr->backend;
1430 struct vega20_single_dpm_table *golden_sclk_table =
1431 &(data->golden_dpm_table.gfx_table);
1435 od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value;
1437 od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
1439 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk);
1440 PP_ASSERT_WITH_CODE(!ret,
1441 "[SetSclkOD] failed to set od gfxclk!",
1444 /* retrieve updated gfxclk table */
1445 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
1446 PP_ASSERT_WITH_CODE(!ret,
1447 "[SetSclkOD] failed to refresh gfxclk table!",
1453 static int vega20_get_mclk_od(
1454 struct pp_hwmgr *hwmgr)
1456 struct vega20_hwmgr *data = hwmgr->backend;
1457 struct vega20_single_dpm_table *mclk_table =
1458 &(data->dpm_table.mem_table);
1459 struct vega20_single_dpm_table *golden_mclk_table =
1460 &(data->golden_dpm_table.mem_table);
1461 int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
1462 int golden_value = golden_mclk_table->dpm_levels
1463 [golden_mclk_table->count - 1].value;
1466 value -= golden_value;
1467 value = DIV_ROUND_UP(value * 100, golden_value);
1472 static int vega20_set_mclk_od(
1473 struct pp_hwmgr *hwmgr, uint32_t value)
1475 struct vega20_hwmgr *data = hwmgr->backend;
1476 struct vega20_single_dpm_table *golden_mclk_table =
1477 &(data->golden_dpm_table.mem_table);
1481 od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value;
1483 od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
1485 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk);
1486 PP_ASSERT_WITH_CODE(!ret,
1487 "[SetMclkOD] failed to set od memclk!",
1490 /* retrieve updated memclk table */
1491 ret = vega20_setup_memclk_dpm_table(hwmgr);
1492 PP_ASSERT_WITH_CODE(!ret,
1493 "[SetMclkOD] failed to refresh memclk table!",
1499 static int vega20_populate_umdpstate_clocks(
1500 struct pp_hwmgr *hwmgr)
1502 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
1503 struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table);
1504 struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table);
1506 hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value;
1507 hwmgr->pstate_mclk = mem_table->dpm_levels[0].value;
1509 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
1510 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) {
1511 hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
1512 hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
1515 hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100;
1516 hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100;
1521 static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr,
1522 PP_Clock *clock, PPCLK_e clock_select)
1526 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1527 PPSMC_MSG_GetDcModeMaxDpmFreq,
1528 (clock_select << 16))) == 0,
1529 "[GetMaxSustainableClock] Failed to get max DC clock from SMC!",
1531 *clock = smum_get_argument(hwmgr);
1533 /* if DC limit is zero, return AC limit */
1535 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1536 PPSMC_MSG_GetMaxDpmFreq,
1537 (clock_select << 16))) == 0,
1538 "[GetMaxSustainableClock] failed to get max AC clock from SMC!",
1540 *clock = smum_get_argument(hwmgr);
1546 static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr)
1548 struct vega20_hwmgr *data =
1549 (struct vega20_hwmgr *)(hwmgr->backend);
1550 struct vega20_max_sustainable_clocks *max_sustainable_clocks =
1551 &(data->max_sustainable_clocks);
1554 max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100;
1555 max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100;
1556 max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100;
1557 max_sustainable_clocks->display_clock = 0xFFFFFFFF;
1558 max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
1559 max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;
1561 if (data->smu_features[GNLD_DPM_UCLK].enabled)
1562 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1563 &(max_sustainable_clocks->uclock),
1565 "[InitMaxSustainableClocks] failed to get max UCLK from SMC!",
1568 if (data->smu_features[GNLD_DPM_SOCCLK].enabled)
1569 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1570 &(max_sustainable_clocks->soc_clock),
1571 PPCLK_SOCCLK)) == 0,
1572 "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!",
1575 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
1576 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1577 &(max_sustainable_clocks->dcef_clock),
1578 PPCLK_DCEFCLK)) == 0,
1579 "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!",
1581 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1582 &(max_sustainable_clocks->display_clock),
1583 PPCLK_DISPCLK)) == 0,
1584 "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!",
1586 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1587 &(max_sustainable_clocks->phy_clock),
1588 PPCLK_PHYCLK)) == 0,
1589 "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!",
1591 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr,
1592 &(max_sustainable_clocks->pixel_clock),
1593 PPCLK_PIXCLK)) == 0,
1594 "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!",
1598 if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
1599 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock;
1604 static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
1608 result = smum_send_msg_to_smc(hwmgr,
1609 PPSMC_MSG_SetMGpuFanBoostLimitRpm);
1610 PP_ASSERT_WITH_CODE(!result,
1611 "[EnableMgpuFan] Failed to enable mgpu fan boost!",
1617 static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr)
1619 struct vega20_hwmgr *data =
1620 (struct vega20_hwmgr *)(hwmgr->backend);
1622 data->uvd_power_gated = true;
1623 data->vce_power_gated = true;
1625 if (data->smu_features[GNLD_DPM_UVD].enabled)
1626 data->uvd_power_gated = false;
1628 if (data->smu_features[GNLD_DPM_VCE].enabled)
1629 data->vce_power_gated = false;
1632 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1636 smum_send_msg_to_smc_with_parameter(hwmgr,
1637 PPSMC_MSG_NumOfDisplays, 0);
1639 result = vega20_set_allowed_featuresmask(hwmgr);
1640 PP_ASSERT_WITH_CODE(!result,
1641 "[EnableDPMTasks] Failed to set allowed featuresmask!\n",
1644 result = vega20_init_smc_table(hwmgr);
1645 PP_ASSERT_WITH_CODE(!result,
1646 "[EnableDPMTasks] Failed to initialize SMC table!",
1649 result = vega20_run_btc(hwmgr);
1650 PP_ASSERT_WITH_CODE(!result,
1651 "[EnableDPMTasks] Failed to run btc!",
1654 result = vega20_run_btc_afll(hwmgr);
1655 PP_ASSERT_WITH_CODE(!result,
1656 "[EnableDPMTasks] Failed to run btc afll!",
1659 result = vega20_enable_all_smu_features(hwmgr);
1660 PP_ASSERT_WITH_CODE(!result,
1661 "[EnableDPMTasks] Failed to enable all smu features!",
1664 result = vega20_override_pcie_parameters(hwmgr);
1665 PP_ASSERT_WITH_CODE(!result,
1666 "[EnableDPMTasks] Failed to override pcie parameters!",
1669 result = vega20_notify_smc_display_change(hwmgr);
1670 PP_ASSERT_WITH_CODE(!result,
1671 "[EnableDPMTasks] Failed to notify smc display change!",
1674 result = vega20_send_clock_ratio(hwmgr);
1675 PP_ASSERT_WITH_CODE(!result,
1676 "[EnableDPMTasks] Failed to send clock ratio!",
1679 /* Initialize UVD/VCE powergating state */
1680 vega20_init_powergate_state(hwmgr);
1682 result = vega20_setup_default_dpm_tables(hwmgr);
1683 PP_ASSERT_WITH_CODE(!result,
1684 "[EnableDPMTasks] Failed to setup default DPM tables!",
1687 result = vega20_init_max_sustainable_clocks(hwmgr);
1688 PP_ASSERT_WITH_CODE(!result,
1689 "[EnableDPMTasks] Failed to get maximum sustainable clocks!",
1692 result = vega20_power_control_set_level(hwmgr);
1693 PP_ASSERT_WITH_CODE(!result,
1694 "[EnableDPMTasks] Failed to power control set level!",
1697 result = vega20_od8_initialize_default_settings(hwmgr);
1698 PP_ASSERT_WITH_CODE(!result,
1699 "[EnableDPMTasks] Failed to initialize odn settings!",
1702 result = vega20_populate_umdpstate_clocks(hwmgr);
1703 PP_ASSERT_WITH_CODE(!result,
1704 "[EnableDPMTasks] Failed to populate umdpstate clocks!",
1707 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit,
1708 POWER_SOURCE_AC << 16);
1709 PP_ASSERT_WITH_CODE(!result,
1710 "[GetPptLimit] get default PPT limit failed!",
1712 hwmgr->power_limit =
1713 hwmgr->default_power_limit = smum_get_argument(hwmgr);
1718 static uint32_t vega20_find_lowest_dpm_level(
1719 struct vega20_single_dpm_table *table)
1723 for (i = 0; i < table->count; i++) {
1724 if (table->dpm_levels[i].enabled)
1727 if (i >= table->count) {
1729 table->dpm_levels[i].enabled = true;
1735 static uint32_t vega20_find_highest_dpm_level(
1736 struct vega20_single_dpm_table *table)
1740 PP_ASSERT_WITH_CODE(table != NULL,
1741 "[FindHighestDPMLevel] DPM Table does not exist!",
1743 PP_ASSERT_WITH_CODE(table->count > 0,
1744 "[FindHighestDPMLevel] DPM Table has no entry!",
1746 PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER,
1747 "[FindHighestDPMLevel] DPM Table has too many entries!",
1748 return MAX_REGULAR_DPM_NUMBER - 1);
1750 for (i = table->count - 1; i >= 0; i--) {
1751 if (table->dpm_levels[i].enabled)
1756 table->dpm_levels[i].enabled = true;
1762 static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
1764 struct vega20_hwmgr *data =
1765 (struct vega20_hwmgr *)(hwmgr->backend);
1769 if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
1770 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1771 min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level;
1772 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1773 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1774 (PPCLK_GFXCLK << 16) | (min_freq & 0xffff))),
1775 "Failed to set soft min gfxclk !",
1779 if (data->smu_features[GNLD_DPM_UCLK].enabled &&
1780 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1781 min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level;
1782 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1783 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1784 (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
1785 "Failed to set soft min memclk !",
1789 if (data->smu_features[GNLD_DPM_UVD].enabled &&
1790 (feature_mask & FEATURE_DPM_UVD_MASK)) {
1791 min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level;
1793 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1794 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1795 (PPCLK_VCLK << 16) | (min_freq & 0xffff))),
1796 "Failed to set soft min vclk!",
1799 min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level;
1801 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1802 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1803 (PPCLK_DCLK << 16) | (min_freq & 0xffff))),
1804 "Failed to set soft min dclk!",
1808 if (data->smu_features[GNLD_DPM_VCE].enabled &&
1809 (feature_mask & FEATURE_DPM_VCE_MASK)) {
1810 min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level;
1812 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1813 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1814 (PPCLK_ECLK << 16) | (min_freq & 0xffff))),
1815 "Failed to set soft min eclk!",
1819 if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
1820 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1821 min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level;
1823 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1824 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1825 (PPCLK_SOCCLK << 16) | (min_freq & 0xffff))),
1826 "Failed to set soft min socclk!",
1830 if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1831 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1832 min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level;
1834 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1835 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1836 (PPCLK_FCLK << 16) | (min_freq & 0xffff))),
1837 "Failed to set soft min fclk!",
1841 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
1842 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
1843 min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
1845 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1846 hwmgr, PPSMC_MSG_SetHardMinByFreq,
1847 (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
1848 "Failed to set hard min dcefclk!",
1855 static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
1857 struct vega20_hwmgr *data =
1858 (struct vega20_hwmgr *)(hwmgr->backend);
1862 if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
1863 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
1864 max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level;
1866 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1867 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1868 (PPCLK_GFXCLK << 16) | (max_freq & 0xffff))),
1869 "Failed to set soft max gfxclk!",
1873 if (data->smu_features[GNLD_DPM_UCLK].enabled &&
1874 (feature_mask & FEATURE_DPM_UCLK_MASK)) {
1875 max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level;
1877 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1878 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1879 (PPCLK_UCLK << 16) | (max_freq & 0xffff))),
1880 "Failed to set soft max memclk!",
1884 if (data->smu_features[GNLD_DPM_UVD].enabled &&
1885 (feature_mask & FEATURE_DPM_UVD_MASK)) {
1886 max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level;
1888 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1889 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1890 (PPCLK_VCLK << 16) | (max_freq & 0xffff))),
1891 "Failed to set soft max vclk!",
1894 max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level;
1895 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1896 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1897 (PPCLK_DCLK << 16) | (max_freq & 0xffff))),
1898 "Failed to set soft max dclk!",
1902 if (data->smu_features[GNLD_DPM_VCE].enabled &&
1903 (feature_mask & FEATURE_DPM_VCE_MASK)) {
1904 max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level;
1906 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1907 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1908 (PPCLK_ECLK << 16) | (max_freq & 0xffff))),
1909 "Failed to set soft max eclk!",
1913 if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
1914 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
1915 max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level;
1917 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1918 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1919 (PPCLK_SOCCLK << 16) | (max_freq & 0xffff))),
1920 "Failed to set soft max socclk!",
1924 if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1925 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1926 max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level;
1928 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1929 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1930 (PPCLK_FCLK << 16) | (max_freq & 0xffff))),
1931 "Failed to set soft max fclk!",
1938 int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
1940 struct vega20_hwmgr *data =
1941 (struct vega20_hwmgr *)(hwmgr->backend);
1944 if (data->smu_features[GNLD_DPM_VCE].supported) {
1945 if (data->smu_features[GNLD_DPM_VCE].enabled == enable) {
1947 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n");
1949 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n");
1952 ret = vega20_enable_smc_features(hwmgr,
1954 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap);
1955 PP_ASSERT_WITH_CODE(!ret,
1956 "Attempt to Enable/Disable DPM VCE Failed!",
1958 data->smu_features[GNLD_DPM_VCE].enabled = enable;
1964 static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr,
1966 PPCLK_e clock_select,
1973 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1974 PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16))) == 0,
1975 "[GetClockRanges] Failed to get max clock from SMC!",
1977 *clock = smum_get_argument(hwmgr);
1979 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1980 PPSMC_MSG_GetMinDpmFreq,
1981 (clock_select << 16))) == 0,
1982 "[GetClockRanges] Failed to get min clock from SMC!",
1984 *clock = smum_get_argument(hwmgr);
1990 static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
1992 struct vega20_hwmgr *data =
1993 (struct vega20_hwmgr *)(hwmgr->backend);
1997 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled,
1998 "[GetSclks]: gfxclk dpm not enabled!\n",
2002 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false);
2003 PP_ASSERT_WITH_CODE(!ret,
2004 "[GetSclks]: fail to get min PPCLK_GFXCLK\n",
2007 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true);
2008 PP_ASSERT_WITH_CODE(!ret,
2009 "[GetSclks]: fail to get max PPCLK_GFXCLK\n",
2013 return (gfx_clk * 100);
2016 static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
2018 struct vega20_hwmgr *data =
2019 (struct vega20_hwmgr *)(hwmgr->backend);
2023 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled,
2024 "[MemMclks]: memclk dpm not enabled!\n",
2028 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false);
2029 PP_ASSERT_WITH_CODE(!ret,
2030 "[GetMclks]: fail to get min PPCLK_UCLK\n",
2033 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true);
2034 PP_ASSERT_WITH_CODE(!ret,
2035 "[GetMclks]: fail to get max PPCLK_UCLK\n",
2039 return (mem_clk * 100);
2042 static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table)
2044 struct vega20_hwmgr *data =
2045 (struct vega20_hwmgr *)(hwmgr->backend);
2048 if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) {
2049 ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table,
2050 TABLE_SMU_METRICS, true);
2052 pr_info("Failed to export SMU metrics table!\n");
2055 memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t));
2056 data->metrics_time = jiffies;
2058 memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t));
2063 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr,
2067 SmuMetrics_t metrics_table;
2069 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2073 *query = metrics_table.CurrSocketPower << 8;
2078 static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr,
2079 PPCLK_e clk_id, uint32_t *clk_freq)
2085 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2086 PPSMC_MSG_GetDpmClockFreq, (clk_id << 16))) == 0,
2087 "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!",
2089 *clk_freq = smum_get_argument(hwmgr);
2091 *clk_freq = *clk_freq * 100;
2096 static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr,
2097 uint32_t *activity_percent)
2100 SmuMetrics_t metrics_table;
2102 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2106 *activity_percent = metrics_table.AverageGfxActivity;
2111 static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
2112 void *value, int *size)
2114 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2115 struct amdgpu_device *adev = hwmgr->adev;
2116 SmuMetrics_t metrics_table;
2121 case AMDGPU_PP_SENSOR_GFX_SCLK:
2122 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2126 *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100;
2129 case AMDGPU_PP_SENSOR_GFX_MCLK:
2130 ret = vega20_get_current_clk_freq(hwmgr,
2136 case AMDGPU_PP_SENSOR_GPU_LOAD:
2137 ret = vega20_get_current_activity_percent(hwmgr, (uint32_t *)value);
2141 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
2142 *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr);
2145 case AMDGPU_PP_SENSOR_EDGE_TEMP:
2146 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2150 *((uint32_t *)value) = metrics_table.TemperatureEdge *
2151 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2154 case AMDGPU_PP_SENSOR_MEM_TEMP:
2155 ret = vega20_get_metrics_table(hwmgr, &metrics_table);
2159 *((uint32_t *)value) = metrics_table.TemperatureHBM *
2160 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
2163 case AMDGPU_PP_SENSOR_UVD_POWER:
2164 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1;
2167 case AMDGPU_PP_SENSOR_VCE_POWER:
2168 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1;
2171 case AMDGPU_PP_SENSOR_GPU_POWER:
2173 ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value);
2175 case AMDGPU_PP_SENSOR_VDDGFX:
2176 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) &
2177 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >>
2178 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT;
2179 *((uint32_t *)value) =
2180 (uint32_t)convert_to_vddc((uint8_t)val_vid);
2182 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
2183 ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value);
2194 int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
2195 struct pp_display_clock_request *clock_req)
2198 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2199 enum amd_pp_clock_type clk_type = clock_req->clock_type;
2200 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
2201 PPCLK_e clk_select = 0;
2202 uint32_t clk_request = 0;
2204 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
2206 case amd_pp_dcef_clock:
2207 clk_select = PPCLK_DCEFCLK;
2209 case amd_pp_disp_clock:
2210 clk_select = PPCLK_DISPCLK;
2212 case amd_pp_pixel_clock:
2213 clk_select = PPCLK_PIXCLK;
2215 case amd_pp_phy_clock:
2216 clk_select = PPCLK_PHYCLK;
2219 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
2225 clk_request = (clk_select << 16) | clk_freq;
2226 result = smum_send_msg_to_smc_with_parameter(hwmgr,
2227 PPSMC_MSG_SetHardMinByFreq,
2235 static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
2236 PHM_PerformanceLevelDesignation designation, uint32_t index,
2237 PHM_PerformanceLevel *level)
2242 static int vega20_notify_smc_display_config_after_ps_adjustment(
2243 struct pp_hwmgr *hwmgr)
2245 struct vega20_hwmgr *data =
2246 (struct vega20_hwmgr *)(hwmgr->backend);
2247 struct vega20_single_dpm_table *dpm_table =
2248 &data->dpm_table.mem_table;
2249 struct PP_Clocks min_clocks = {0};
2250 struct pp_display_clock_request clock_req;
2253 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
2254 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;
2255 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock;
2257 if (data->smu_features[GNLD_DPM_DCEFCLK].supported) {
2258 clock_req.clock_type = amd_pp_dcef_clock;
2259 clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10;
2260 if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) {
2261 if (data->smu_features[GNLD_DS_DCEFCLK].supported)
2262 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(
2263 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
2264 min_clocks.dcefClockInSR / 100)) == 0,
2265 "Attempt to set divider for DCEFCLK Failed!",
2268 pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
2272 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
2273 dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100;
2274 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2275 PPSMC_MSG_SetHardMinByFreq,
2276 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)),
2277 "[SetHardMinFreq] Set hard min uclk failed!",
2284 static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
2286 struct vega20_hwmgr *data =
2287 (struct vega20_hwmgr *)(hwmgr->backend);
2288 uint32_t soft_level;
2291 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table));
2293 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2294 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2295 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2297 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table));
2299 data->dpm_table.mem_table.dpm_state.soft_min_level =
2300 data->dpm_table.mem_table.dpm_state.soft_max_level =
2301 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2303 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table));
2305 data->dpm_table.soc_table.dpm_state.soft_min_level =
2306 data->dpm_table.soc_table.dpm_state.soft_max_level =
2307 data->dpm_table.soc_table.dpm_levels[soft_level].value;
2309 ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
2310 PP_ASSERT_WITH_CODE(!ret,
2311 "Failed to upload boot level to highest!",
2314 ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
2315 PP_ASSERT_WITH_CODE(!ret,
2316 "Failed to upload dpm max level to highest!",
2322 static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
2324 struct vega20_hwmgr *data =
2325 (struct vega20_hwmgr *)(hwmgr->backend);
2326 uint32_t soft_level;
2329 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table));
2331 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2332 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2333 data->dpm_table.gfx_table.dpm_levels[soft_level].value;
2335 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table));
2337 data->dpm_table.mem_table.dpm_state.soft_min_level =
2338 data->dpm_table.mem_table.dpm_state.soft_max_level =
2339 data->dpm_table.mem_table.dpm_levels[soft_level].value;
2341 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table));
2343 data->dpm_table.soc_table.dpm_state.soft_min_level =
2344 data->dpm_table.soc_table.dpm_state.soft_max_level =
2345 data->dpm_table.soc_table.dpm_levels[soft_level].value;
2347 ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
2348 PP_ASSERT_WITH_CODE(!ret,
2349 "Failed to upload boot level to highest!",
2352 ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
2353 PP_ASSERT_WITH_CODE(!ret,
2354 "Failed to upload dpm max level to highest!",
2361 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
2365 ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
2366 PP_ASSERT_WITH_CODE(!ret,
2367 "Failed to upload DPM Bootup Levels!",
2370 ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
2371 PP_ASSERT_WITH_CODE(!ret,
2372 "Failed to upload DPM Max Levels!",
2378 static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level,
2379 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask)
2381 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2382 struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table);
2383 struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table);
2384 struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table);
2390 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL &&
2391 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL &&
2392 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) {
2393 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL;
2394 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL;
2395 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL;
2398 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
2400 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
2402 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
2403 *sclk_mask = gfx_dpm_table->count - 1;
2404 *mclk_mask = mem_dpm_table->count - 1;
2405 *soc_mask = soc_dpm_table->count - 1;
2411 static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
2412 enum pp_clock_type type, uint32_t mask)
2414 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2415 uint32_t soft_min_level, soft_max_level, hard_min_level;
2420 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2421 soft_max_level = mask ? (fls(mask) - 1) : 0;
2423 if (soft_max_level >= data->dpm_table.gfx_table.count) {
2424 pr_err("Clock level specified %d is over max allowed %d\n",
2426 data->dpm_table.gfx_table.count - 1);
2430 data->dpm_table.gfx_table.dpm_state.soft_min_level =
2431 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
2432 data->dpm_table.gfx_table.dpm_state.soft_max_level =
2433 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
2435 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
2436 PP_ASSERT_WITH_CODE(!ret,
2437 "Failed to upload boot level to lowest!",
2440 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
2441 PP_ASSERT_WITH_CODE(!ret,
2442 "Failed to upload dpm max level to highest!",
2447 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2448 soft_max_level = mask ? (fls(mask) - 1) : 0;
2450 if (soft_max_level >= data->dpm_table.mem_table.count) {
2451 pr_err("Clock level specified %d is over max allowed %d\n",
2453 data->dpm_table.mem_table.count - 1);
2457 data->dpm_table.mem_table.dpm_state.soft_min_level =
2458 data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
2459 data->dpm_table.mem_table.dpm_state.soft_max_level =
2460 data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
2462 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK);
2463 PP_ASSERT_WITH_CODE(!ret,
2464 "Failed to upload boot level to lowest!",
2467 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK);
2468 PP_ASSERT_WITH_CODE(!ret,
2469 "Failed to upload dpm max level to highest!",
2475 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2476 soft_max_level = mask ? (fls(mask) - 1) : 0;
2478 if (soft_max_level >= data->dpm_table.soc_table.count) {
2479 pr_err("Clock level specified %d is over max allowed %d\n",
2481 data->dpm_table.soc_table.count - 1);
2485 data->dpm_table.soc_table.dpm_state.soft_min_level =
2486 data->dpm_table.soc_table.dpm_levels[soft_min_level].value;
2487 data->dpm_table.soc_table.dpm_state.soft_max_level =
2488 data->dpm_table.soc_table.dpm_levels[soft_max_level].value;
2490 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
2491 PP_ASSERT_WITH_CODE(!ret,
2492 "Failed to upload boot level to lowest!",
2495 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK);
2496 PP_ASSERT_WITH_CODE(!ret,
2497 "Failed to upload dpm max level to highest!",
2503 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2504 soft_max_level = mask ? (fls(mask) - 1) : 0;
2506 if (soft_max_level >= data->dpm_table.fclk_table.count) {
2507 pr_err("Clock level specified %d is over max allowed %d\n",
2509 data->dpm_table.fclk_table.count - 1);
2513 data->dpm_table.fclk_table.dpm_state.soft_min_level =
2514 data->dpm_table.fclk_table.dpm_levels[soft_min_level].value;
2515 data->dpm_table.fclk_table.dpm_state.soft_max_level =
2516 data->dpm_table.fclk_table.dpm_levels[soft_max_level].value;
2518 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2519 PP_ASSERT_WITH_CODE(!ret,
2520 "Failed to upload boot level to lowest!",
2523 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2524 PP_ASSERT_WITH_CODE(!ret,
2525 "Failed to upload dpm max level to highest!",
2531 hard_min_level = mask ? (ffs(mask) - 1) : 0;
2533 if (hard_min_level >= data->dpm_table.dcef_table.count) {
2534 pr_err("Clock level specified %d is over max allowed %d\n",
2536 data->dpm_table.dcef_table.count - 1);
2540 data->dpm_table.dcef_table.dpm_state.hard_min_level =
2541 data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
2543 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
2544 PP_ASSERT_WITH_CODE(!ret,
2545 "Failed to upload boot level to lowest!",
2548 //TODO: Setting DCEFCLK max dpm level is not supported
2553 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2554 soft_max_level = mask ? (fls(mask) - 1) : 0;
2555 if (soft_min_level >= NUM_LINK_LEVELS ||
2556 soft_max_level >= NUM_LINK_LEVELS)
2559 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
2560 PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level);
2561 PP_ASSERT_WITH_CODE(!ret,
2562 "Failed to set min link dpm level!",
2574 static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
2575 enum amd_dpm_forced_level level)
2578 uint32_t sclk_mask, mclk_mask, soc_mask;
2581 case AMD_DPM_FORCED_LEVEL_HIGH:
2582 ret = vega20_force_dpm_highest(hwmgr);
2585 case AMD_DPM_FORCED_LEVEL_LOW:
2586 ret = vega20_force_dpm_lowest(hwmgr);
2589 case AMD_DPM_FORCED_LEVEL_AUTO:
2590 ret = vega20_unforce_dpm_levels(hwmgr);
2593 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
2594 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
2595 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
2596 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
2597 ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
2600 vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask);
2601 vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask);
2602 vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask);
2605 case AMD_DPM_FORCED_LEVEL_MANUAL:
2606 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
2614 static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr)
2616 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2618 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
2619 return AMD_FAN_CTRL_MANUAL;
2621 return AMD_FAN_CTRL_AUTO;
2624 static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
2627 case AMD_FAN_CTRL_NONE:
2628 vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
2630 case AMD_FAN_CTRL_MANUAL:
2631 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2632 vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
2634 case AMD_FAN_CTRL_AUTO:
2635 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
2636 vega20_fan_ctrl_start_smc_fan_control(hwmgr);
2643 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr,
2644 struct amd_pp_simple_clock_info *info)
2647 struct phm_ppt_v2_information *table_info =
2648 (struct phm_ppt_v2_information *)hwmgr->pptable;
2649 struct phm_clock_and_voltage_limits *max_limits =
2650 &table_info->max_clock_voltage_on_ac;
2652 info->engine_max_clock = max_limits->sclk;
2653 info->memory_max_clock = max_limits->mclk;
2659 static int vega20_get_sclks(struct pp_hwmgr *hwmgr,
2660 struct pp_clock_levels_with_latency *clocks)
2662 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2663 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
2666 if (!data->smu_features[GNLD_DPM_GFXCLK].enabled)
2669 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2670 clocks->num_levels = count;
2672 for (i = 0; i < count; i++) {
2673 clocks->data[i].clocks_in_khz =
2674 dpm_table->dpm_levels[i].value * 1000;
2675 clocks->data[i].latency_in_us = 0;
2681 static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr,
2687 static int vega20_get_memclocks(struct pp_hwmgr *hwmgr,
2688 struct pp_clock_levels_with_latency *clocks)
2690 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2691 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table);
2694 if (!data->smu_features[GNLD_DPM_UCLK].enabled)
2697 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2698 clocks->num_levels = data->mclk_latency_table.count = count;
2700 for (i = 0; i < count; i++) {
2701 clocks->data[i].clocks_in_khz =
2702 data->mclk_latency_table.entries[i].frequency =
2703 dpm_table->dpm_levels[i].value * 1000;
2704 clocks->data[i].latency_in_us =
2705 data->mclk_latency_table.entries[i].latency =
2706 vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value);
2712 static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr,
2713 struct pp_clock_levels_with_latency *clocks)
2715 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2716 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table);
2719 if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled)
2722 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2723 clocks->num_levels = count;
2725 for (i = 0; i < count; i++) {
2726 clocks->data[i].clocks_in_khz =
2727 dpm_table->dpm_levels[i].value * 1000;
2728 clocks->data[i].latency_in_us = 0;
2734 static int vega20_get_socclocks(struct pp_hwmgr *hwmgr,
2735 struct pp_clock_levels_with_latency *clocks)
2737 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2738 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table);
2741 if (!data->smu_features[GNLD_DPM_SOCCLK].enabled)
2744 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count;
2745 clocks->num_levels = count;
2747 for (i = 0; i < count; i++) {
2748 clocks->data[i].clocks_in_khz =
2749 dpm_table->dpm_levels[i].value * 1000;
2750 clocks->data[i].latency_in_us = 0;
2757 static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
2758 enum amd_pp_clock_type type,
2759 struct pp_clock_levels_with_latency *clocks)
2764 case amd_pp_sys_clock:
2765 ret = vega20_get_sclks(hwmgr, clocks);
2767 case amd_pp_mem_clock:
2768 ret = vega20_get_memclocks(hwmgr, clocks);
2770 case amd_pp_dcef_clock:
2771 ret = vega20_get_dcefclocks(hwmgr, clocks);
2773 case amd_pp_soc_clock:
2774 ret = vega20_get_socclocks(hwmgr, clocks);
2783 static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
2784 enum amd_pp_clock_type type,
2785 struct pp_clock_levels_with_voltage *clocks)
2787 clocks->num_levels = 0;
2792 static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
2795 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
2796 Watermarks_t *table = &(data->smc_state_table.water_marks_table);
2797 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
2799 if (!data->registry_data.disable_water_mark &&
2800 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
2801 data->smu_features[GNLD_DPM_SOCCLK].supported) {
2802 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
2803 data->water_marks_bitmap |= WaterMarksExist;
2804 data->water_marks_bitmap &= ~WaterMarksLoaded;
2810 static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
2811 enum PP_OD_DPM_TABLE_COMMAND type,
2812 long *input, uint32_t size)
2814 struct vega20_hwmgr *data =
2815 (struct vega20_hwmgr *)(hwmgr->backend);
2816 struct vega20_od8_single_setting *od8_settings =
2817 data->od8_settings.od8_settings_array;
2818 OverDriveTable_t *od_table =
2819 &(data->smc_state_table.overdrive_table);
2820 int32_t input_index, input_clk, input_vol, i;
2824 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
2828 case PP_OD_EDIT_SCLK_VDDC_TABLE:
2829 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
2830 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) {
2831 pr_info("Sclk min/max frequency overdrive not supported\n");
2835 for (i = 0; i < size; i += 2) {
2837 pr_info("invalid number of input parameters %d\n",
2842 input_index = input[i];
2843 input_clk = input[i + 1];
2845 if (input_index != 0 && input_index != 1) {
2846 pr_info("Invalid index %d\n", input_index);
2847 pr_info("Support min/max sclk frequency setting only which index by 0/1\n");
2851 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value ||
2852 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) {
2853 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2855 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
2856 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
2860 if ((input_index == 0 && od_table->GfxclkFmin != input_clk) ||
2861 (input_index == 1 && od_table->GfxclkFmax != input_clk))
2862 data->gfxclk_overdrive = true;
2864 if (input_index == 0)
2865 od_table->GfxclkFmin = input_clk;
2867 od_table->GfxclkFmax = input_clk;
2872 case PP_OD_EDIT_MCLK_VDDC_TABLE:
2873 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
2874 pr_info("Mclk max frequency overdrive not supported\n");
2878 for (i = 0; i < size; i += 2) {
2880 pr_info("invalid number of input parameters %d\n",
2885 input_index = input[i];
2886 input_clk = input[i + 1];
2888 if (input_index != 1) {
2889 pr_info("Invalid index %d\n", input_index);
2890 pr_info("Support max Mclk frequency setting only which index by 1\n");
2894 if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
2895 input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) {
2896 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2898 od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
2899 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
2903 if (input_index == 1 && od_table->UclkFmax != input_clk)
2904 data->memclk_overdrive = true;
2906 od_table->UclkFmax = input_clk;
2911 case PP_OD_EDIT_VDDC_CURVE:
2912 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
2913 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
2914 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
2915 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
2916 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
2917 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) {
2918 pr_info("Voltage curve calibrate not supported\n");
2922 for (i = 0; i < size; i += 3) {
2924 pr_info("invalid number of input parameters %d\n",
2929 input_index = input[i];
2930 input_clk = input[i + 1];
2931 input_vol = input[i + 2];
2933 if (input_index > 2) {
2934 pr_info("Setting for point %d is not supported\n",
2936 pr_info("Three supported points index by 0, 1, 2\n");
2940 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index;
2941 if (input_clk < od8_settings[od8_id].min_value ||
2942 input_clk > od8_settings[od8_id].max_value) {
2943 pr_info("clock freq %d is not within allowed range [%d - %d]\n",
2945 od8_settings[od8_id].min_value,
2946 od8_settings[od8_id].max_value);
2950 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index;
2951 if (input_vol < od8_settings[od8_id].min_value ||
2952 input_vol > od8_settings[od8_id].max_value) {
2953 pr_info("clock voltage %d is not within allowed range [%d - %d]\n",
2955 od8_settings[od8_id].min_value,
2956 od8_settings[od8_id].max_value);
2960 switch (input_index) {
2962 od_table->GfxclkFreq1 = input_clk;
2963 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE;
2966 od_table->GfxclkFreq2 = input_clk;
2967 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE;
2970 od_table->GfxclkFreq3 = input_clk;
2971 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE;
2977 case PP_OD_RESTORE_DEFAULT_TABLE:
2978 data->gfxclk_overdrive = false;
2979 data->memclk_overdrive = false;
2981 ret = smum_smc_table_manager(hwmgr,
2982 (uint8_t *)od_table,
2983 TABLE_OVERDRIVE, true);
2984 PP_ASSERT_WITH_CODE(!ret,
2985 "Failed to export overdrive table!",
2989 case PP_OD_COMMIT_DPM_TABLE:
2990 ret = smum_smc_table_manager(hwmgr,
2991 (uint8_t *)od_table,
2992 TABLE_OVERDRIVE, false);
2993 PP_ASSERT_WITH_CODE(!ret,
2994 "Failed to import overdrive table!",
2997 /* retrieve updated gfxclk table */
2998 if (data->gfxclk_overdrive) {
2999 data->gfxclk_overdrive = false;
3001 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
3006 /* retrieve updated memclk table */
3007 if (data->memclk_overdrive) {
3008 data->memclk_overdrive = false;
3010 ret = vega20_setup_memclk_dpm_table(hwmgr);
3023 static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf)
3025 static const char *ppfeature_name[] = {
3060 static const char *output_title[] = {
3064 uint64_t features_enabled;
3069 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3070 PP_ASSERT_WITH_CODE(!ret,
3071 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
3074 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled);
3075 size += sprintf(buf + size, "%-19s %-22s %s\n",
3079 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
3080 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n",
3083 (features_enabled & (1ULL << i)) ? "Y" : "N");
3089 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
3091 uint64_t features_enabled;
3092 uint64_t features_to_enable;
3093 uint64_t features_to_disable;
3096 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
3099 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3103 features_to_disable =
3104 features_enabled & ~new_ppfeature_masks;
3105 features_to_enable =
3106 ~features_enabled & new_ppfeature_masks;
3108 pr_debug("features_to_disable 0x%llx\n", features_to_disable);
3109 pr_debug("features_to_enable 0x%llx\n", features_to_enable);
3111 if (features_to_disable) {
3112 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
3117 if (features_to_enable) {
3118 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
3126 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
3127 enum pp_clock_type type, char *buf)
3129 struct vega20_hwmgr *data =
3130 (struct vega20_hwmgr *)(hwmgr->backend);
3131 struct vega20_od8_single_setting *od8_settings =
3132 data->od8_settings.od8_settings_array;
3133 OverDriveTable_t *od_table =
3134 &(data->smc_state_table.overdrive_table);
3135 struct phm_ppt_v3_information *pptable_information =
3136 (struct phm_ppt_v3_information *)hwmgr->pptable;
3137 PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
3138 struct amdgpu_device *adev = hwmgr->adev;
3139 struct pp_clock_levels_with_latency clocks;
3140 struct vega20_single_dpm_table *fclk_dpm_table =
3141 &(data->dpm_table.fclk_table);
3142 int i, now, size = 0;
3144 uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width;
3148 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now);
3149 PP_ASSERT_WITH_CODE(!ret,
3150 "Attempt to get current gfx clk Failed!",
3153 if (vega20_get_sclks(hwmgr, &clocks)) {
3154 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3159 for (i = 0; i < clocks.num_levels; i++)
3160 size += sprintf(buf + size, "%d: %uMhz %s\n",
3161 i, clocks.data[i].clocks_in_khz / 1000,
3162 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3166 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now);
3167 PP_ASSERT_WITH_CODE(!ret,
3168 "Attempt to get current mclk freq Failed!",
3171 if (vega20_get_memclocks(hwmgr, &clocks)) {
3172 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3177 for (i = 0; i < clocks.num_levels; i++)
3178 size += sprintf(buf + size, "%d: %uMhz %s\n",
3179 i, clocks.data[i].clocks_in_khz / 1000,
3180 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3184 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now);
3185 PP_ASSERT_WITH_CODE(!ret,
3186 "Attempt to get current socclk freq Failed!",
3189 if (vega20_get_socclocks(hwmgr, &clocks)) {
3190 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3195 for (i = 0; i < clocks.num_levels; i++)
3196 size += sprintf(buf + size, "%d: %uMhz %s\n",
3197 i, clocks.data[i].clocks_in_khz / 1000,
3198 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3202 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
3203 PP_ASSERT_WITH_CODE(!ret,
3204 "Attempt to get current fclk freq Failed!",
3207 for (i = 0; i < fclk_dpm_table->count; i++)
3208 size += sprintf(buf + size, "%d: %uMhz %s\n",
3209 i, fclk_dpm_table->dpm_levels[i].value,
3210 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
3214 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
3215 PP_ASSERT_WITH_CODE(!ret,
3216 "Attempt to get current dcefclk freq Failed!",
3219 if (vega20_get_dcefclocks(hwmgr, &clocks)) {
3220 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3225 for (i = 0; i < clocks.num_levels; i++)
3226 size += sprintf(buf + size, "%d: %uMhz %s\n",
3227 i, clocks.data[i].clocks_in_khz / 1000,
3228 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3232 current_gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
3233 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
3234 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
3235 current_lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
3236 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
3237 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
3238 for (i = 0; i < NUM_LINK_LEVELS; i++) {
3239 if (i == 1 && data->pcie_parameters_override) {
3240 gen_speed = data->pcie_gen_level1;
3241 lane_width = data->pcie_width_level1;
3243 gen_speed = pptable->PcieGenSpeed[i];
3244 lane_width = pptable->PcieLaneCount[i];
3246 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
3247 (gen_speed == 0) ? "2.5GT/s," :
3248 (gen_speed == 1) ? "5.0GT/s," :
3249 (gen_speed == 2) ? "8.0GT/s," :
3250 (gen_speed == 3) ? "16.0GT/s," : "",
3251 (lane_width == 1) ? "x1" :
3252 (lane_width == 2) ? "x2" :
3253 (lane_width == 3) ? "x4" :
3254 (lane_width == 4) ? "x8" :
3255 (lane_width == 5) ? "x12" :
3256 (lane_width == 6) ? "x16" : "",
3257 pptable->LclkFreq[i],
3258 (current_gen_speed == gen_speed) &&
3259 (current_lane_width == lane_width) ?
3265 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3266 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3267 size = sprintf(buf, "%s:\n", "OD_SCLK");
3268 size += sprintf(buf + size, "0: %10uMhz\n",
3269 od_table->GfxclkFmin);
3270 size += sprintf(buf + size, "1: %10uMhz\n",
3271 od_table->GfxclkFmax);
3276 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3277 size = sprintf(buf, "%s:\n", "OD_MCLK");
3278 size += sprintf(buf + size, "1: %10uMhz\n",
3279 od_table->UclkFmax);
3285 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3286 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3287 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3288 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3289 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3290 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3291 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE");
3292 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
3293 od_table->GfxclkFreq1,
3294 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
3295 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
3296 od_table->GfxclkFreq2,
3297 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
3298 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
3299 od_table->GfxclkFreq3,
3300 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
3306 size = sprintf(buf, "%s:\n", "OD_RANGE");
3308 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3309 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3310 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
3311 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
3312 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
3315 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3316 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
3317 od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
3318 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
3321 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3322 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3323 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3324 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3325 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3326 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3327 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
3328 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
3329 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
3330 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
3331 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
3332 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
3333 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
3334 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
3335 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
3336 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
3337 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
3338 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
3339 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
3340 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
3341 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
3342 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
3343 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
3344 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
3354 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr,
3355 struct vega20_single_dpm_table *dpm_table)
3357 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3360 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
3361 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3362 "[SetUclkToHightestDpmLevel] Dpm table has no entry!",
3364 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS,
3365 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!",
3368 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3369 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3370 PPSMC_MSG_SetHardMinByFreq,
3371 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)),
3372 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!",
3379 static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr)
3381 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3382 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table);
3385 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
3386 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3387 "[SetFclkToHightestDpmLevel] Dpm table has no entry!",
3389 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS,
3390 "[SetFclkToHightestDpmLevel] Dpm table has too many entries!",
3393 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3394 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3395 PPSMC_MSG_SetSoftMinByFreq,
3396 (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level)),
3397 "[SetFclkToHightestDpmLevel] Set soft min fclk failed!",
3404 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3406 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3409 smum_send_msg_to_smc_with_parameter(hwmgr,
3410 PPSMC_MSG_NumOfDisplays, 0);
3412 ret = vega20_set_uclk_to_highest_dpm_level(hwmgr,
3413 &data->dpm_table.mem_table);
3417 return vega20_set_fclk_to_highest_dpm_level(hwmgr);
3420 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3422 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3424 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
3426 if ((data->water_marks_bitmap & WaterMarksExist) &&
3427 !(data->water_marks_bitmap & WaterMarksLoaded)) {
3428 result = smum_smc_table_manager(hwmgr,
3429 (uint8_t *)wm_table, TABLE_WATERMARKS, false);
3430 PP_ASSERT_WITH_CODE(!result,
3431 "Failed to update WMTABLE!",
3433 data->water_marks_bitmap |= WaterMarksLoaded;
3436 if ((data->water_marks_bitmap & WaterMarksExist) &&
3437 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
3438 data->smu_features[GNLD_DPM_SOCCLK].supported) {
3439 result = smum_send_msg_to_smc_with_parameter(hwmgr,
3440 PPSMC_MSG_NumOfDisplays,
3441 hwmgr->display_config->num_display);
3447 int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
3449 struct vega20_hwmgr *data =
3450 (struct vega20_hwmgr *)(hwmgr->backend);
3453 if (data->smu_features[GNLD_DPM_UVD].supported) {
3454 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) {
3456 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n");
3458 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n");
3461 ret = vega20_enable_smc_features(hwmgr,
3463 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap);
3464 PP_ASSERT_WITH_CODE(!ret,
3465 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!",
3467 data->smu_features[GNLD_DPM_UVD].enabled = enable;
3473 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
3475 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3477 if (data->vce_power_gated == bgate)
3480 data->vce_power_gated = bgate;
3482 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3483 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3484 AMD_IP_BLOCK_TYPE_VCE,
3487 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3488 AMD_IP_BLOCK_TYPE_VCE,
3489 AMD_PG_STATE_UNGATE);
3490 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3495 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
3497 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3499 if (data->uvd_power_gated == bgate)
3502 data->uvd_power_gated = bgate;
3503 vega20_enable_disable_uvd_dpm(hwmgr, !bgate);
3506 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr)
3508 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3509 struct vega20_single_dpm_table *dpm_table;
3510 bool vblank_too_short = false;
3511 bool disable_mclk_switching;
3512 bool disable_fclk_switching;
3513 uint32_t i, latency;
3515 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
3516 !hwmgr->display_config->multi_monitor_in_sync) ||
3518 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3521 dpm_table = &(data->dpm_table.gfx_table);
3522 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3523 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3524 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3525 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3527 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3528 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
3529 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3530 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3533 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3534 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3535 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3538 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3539 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3540 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3545 dpm_table = &(data->dpm_table.mem_table);
3546 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3547 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3548 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3549 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3551 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3552 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
3553 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3554 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3557 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
3558 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3559 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3562 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3563 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3564 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3568 /* honour DAL's UCLK Hardmin */
3569 if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100))
3570 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100;
3572 /* Hardmin is dependent on displayconfig */
3573 if (disable_mclk_switching) {
3574 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3575 for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
3576 if (data->mclk_latency_table.entries[i].latency <= latency) {
3577 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
3578 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
3585 if (hwmgr->display_config->nb_pstate_switch_disable)
3586 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3588 if ((disable_mclk_switching &&
3589 (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) ||
3590 hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value)
3591 disable_fclk_switching = true;
3593 disable_fclk_switching = false;
3596 dpm_table = &(data->dpm_table.fclk_table);
3597 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3598 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3599 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3600 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3601 if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching)
3602 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3605 dpm_table = &(data->dpm_table.vclk_table);
3606 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3607 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3608 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3609 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3611 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3612 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3613 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3614 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3617 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3618 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3619 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3624 dpm_table = &(data->dpm_table.dclk_table);
3625 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3626 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3627 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3628 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3630 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3631 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3632 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3633 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3636 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3637 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3638 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3643 dpm_table = &(data->dpm_table.soc_table);
3644 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3645 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3646 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3647 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3649 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3650 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
3651 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3652 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3655 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3656 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3657 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3662 dpm_table = &(data->dpm_table.eclk_table);
3663 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3664 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3665 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3666 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3668 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3669 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
3670 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3671 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3674 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3675 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3676 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3684 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
3686 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3687 bool is_update_required = false;
3689 if (data->display_timing.num_existing_displays !=
3690 hwmgr->display_config->num_display)
3691 is_update_required = true;
3693 if (data->registry_data.gfx_clk_deep_sleep_support &&
3694 (data->display_timing.min_clock_in_sr !=
3695 hwmgr->display_config->min_core_set_clock_in_sr))
3696 is_update_required = true;
3698 return is_update_required;
3701 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
3705 ret = vega20_disable_all_smu_features(hwmgr);
3706 PP_ASSERT_WITH_CODE(!ret,
3707 "[DisableDpmTasks] Failed to disable all smu features!",
3713 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr)
3715 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3718 result = vega20_disable_dpm_tasks(hwmgr);
3719 PP_ASSERT_WITH_CODE((0 == result),
3720 "[PowerOffAsic] Failed to disable DPM!",
3722 data->water_marks_bitmap &= ~(WaterMarksLoaded);
3727 static int conv_power_profile_to_pplib_workload(int power_profile)
3729 int pplib_workload = 0;
3731 switch (power_profile) {
3732 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
3733 pplib_workload = WORKLOAD_DEFAULT_BIT;
3735 case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
3736 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
3738 case PP_SMC_POWER_PROFILE_POWERSAVING:
3739 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
3741 case PP_SMC_POWER_PROFILE_VIDEO:
3742 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
3744 case PP_SMC_POWER_PROFILE_VR:
3745 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
3747 case PP_SMC_POWER_PROFILE_COMPUTE:
3748 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
3750 case PP_SMC_POWER_PROFILE_CUSTOM:
3751 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
3755 return pplib_workload;
3758 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
3760 DpmActivityMonitorCoeffInt_t activity_monitor;
3761 uint32_t i, size = 0;
3762 uint16_t workload_type = 0;
3763 static const char *profile_name[] = {
3771 static const char *title[] = {
3772 "PROFILE_INDEX(NAME)",
3776 "MinActiveFreqType",
3781 "PD_Data_error_coeff",
3782 "PD_Data_error_rate_coeff"};
3788 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
3789 title[0], title[1], title[2], title[3], title[4], title[5],
3790 title[6], title[7], title[8], title[9], title[10]);
3792 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
3793 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
3794 workload_type = conv_power_profile_to_pplib_workload(i);
3795 result = vega20_get_activity_monitor_coeff(hwmgr,
3796 (uint8_t *)(&activity_monitor), workload_type);
3797 PP_ASSERT_WITH_CODE(!result,
3798 "[GetPowerProfile] Failed to get activity monitor!",
3801 size += sprintf(buf + size, "%2d %14s%s:\n",
3802 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
3804 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3808 activity_monitor.Gfx_FPS,
3809 activity_monitor.Gfx_UseRlcBusy,
3810 activity_monitor.Gfx_MinActiveFreqType,
3811 activity_monitor.Gfx_MinActiveFreq,
3812 activity_monitor.Gfx_BoosterFreqType,
3813 activity_monitor.Gfx_BoosterFreq,
3814 activity_monitor.Gfx_PD_Data_limit_c,
3815 activity_monitor.Gfx_PD_Data_error_coeff,
3816 activity_monitor.Gfx_PD_Data_error_rate_coeff);
3818 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3822 activity_monitor.Soc_FPS,
3823 activity_monitor.Soc_UseRlcBusy,
3824 activity_monitor.Soc_MinActiveFreqType,
3825 activity_monitor.Soc_MinActiveFreq,
3826 activity_monitor.Soc_BoosterFreqType,
3827 activity_monitor.Soc_BoosterFreq,
3828 activity_monitor.Soc_PD_Data_limit_c,
3829 activity_monitor.Soc_PD_Data_error_coeff,
3830 activity_monitor.Soc_PD_Data_error_rate_coeff);
3832 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3836 activity_monitor.Mem_FPS,
3837 activity_monitor.Mem_UseRlcBusy,
3838 activity_monitor.Mem_MinActiveFreqType,
3839 activity_monitor.Mem_MinActiveFreq,
3840 activity_monitor.Mem_BoosterFreqType,
3841 activity_monitor.Mem_BoosterFreq,
3842 activity_monitor.Mem_PD_Data_limit_c,
3843 activity_monitor.Mem_PD_Data_error_coeff,
3844 activity_monitor.Mem_PD_Data_error_rate_coeff);
3846 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
3850 activity_monitor.Fclk_FPS,
3851 activity_monitor.Fclk_UseRlcBusy,
3852 activity_monitor.Fclk_MinActiveFreqType,
3853 activity_monitor.Fclk_MinActiveFreq,
3854 activity_monitor.Fclk_BoosterFreqType,
3855 activity_monitor.Fclk_BoosterFreq,
3856 activity_monitor.Fclk_PD_Data_limit_c,
3857 activity_monitor.Fclk_PD_Data_error_coeff,
3858 activity_monitor.Fclk_PD_Data_error_rate_coeff);
3864 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
3866 DpmActivityMonitorCoeffInt_t activity_monitor;
3867 int workload_type, result = 0;
3868 uint32_t power_profile_mode = input[size];
3870 if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
3871 pr_err("Invalid power profile mode %d\n", power_profile_mode);
3875 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
3876 struct vega20_hwmgr *data =
3877 (struct vega20_hwmgr *)(hwmgr->backend);
3878 if (size == 0 && !data->is_custom_profile_set)
3880 if (size < 10 && size != 0)
3883 result = vega20_get_activity_monitor_coeff(hwmgr,
3884 (uint8_t *)(&activity_monitor),
3885 WORKLOAD_PPLIB_CUSTOM_BIT);
3886 PP_ASSERT_WITH_CODE(!result,
3887 "[SetPowerProfile] Failed to get activity monitor!",
3890 /* If size==0, then we want to apply the already-configured
3891 * CUSTOM profile again. Just apply it, since we checked its
3898 case 0: /* Gfxclk */
3899 activity_monitor.Gfx_FPS = input[1];
3900 activity_monitor.Gfx_UseRlcBusy = input[2];
3901 activity_monitor.Gfx_MinActiveFreqType = input[3];
3902 activity_monitor.Gfx_MinActiveFreq = input[4];
3903 activity_monitor.Gfx_BoosterFreqType = input[5];
3904 activity_monitor.Gfx_BoosterFreq = input[6];
3905 activity_monitor.Gfx_PD_Data_limit_c = input[7];
3906 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
3907 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
3909 case 1: /* Socclk */
3910 activity_monitor.Soc_FPS = input[1];
3911 activity_monitor.Soc_UseRlcBusy = input[2];
3912 activity_monitor.Soc_MinActiveFreqType = input[3];
3913 activity_monitor.Soc_MinActiveFreq = input[4];
3914 activity_monitor.Soc_BoosterFreqType = input[5];
3915 activity_monitor.Soc_BoosterFreq = input[6];
3916 activity_monitor.Soc_PD_Data_limit_c = input[7];
3917 activity_monitor.Soc_PD_Data_error_coeff = input[8];
3918 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
3921 activity_monitor.Mem_FPS = input[1];
3922 activity_monitor.Mem_UseRlcBusy = input[2];
3923 activity_monitor.Mem_MinActiveFreqType = input[3];
3924 activity_monitor.Mem_MinActiveFreq = input[4];
3925 activity_monitor.Mem_BoosterFreqType = input[5];
3926 activity_monitor.Mem_BoosterFreq = input[6];
3927 activity_monitor.Mem_PD_Data_limit_c = input[7];
3928 activity_monitor.Mem_PD_Data_error_coeff = input[8];
3929 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
3932 activity_monitor.Fclk_FPS = input[1];
3933 activity_monitor.Fclk_UseRlcBusy = input[2];
3934 activity_monitor.Fclk_MinActiveFreqType = input[3];
3935 activity_monitor.Fclk_MinActiveFreq = input[4];
3936 activity_monitor.Fclk_BoosterFreqType = input[5];
3937 activity_monitor.Fclk_BoosterFreq = input[6];
3938 activity_monitor.Fclk_PD_Data_limit_c = input[7];
3939 activity_monitor.Fclk_PD_Data_error_coeff = input[8];
3940 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
3944 result = vega20_set_activity_monitor_coeff(hwmgr,
3945 (uint8_t *)(&activity_monitor),
3946 WORKLOAD_PPLIB_CUSTOM_BIT);
3947 data->is_custom_profile_set = true;
3948 PP_ASSERT_WITH_CODE(!result,
3949 "[SetPowerProfile] Failed to set activity monitor!",
3954 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
3956 conv_power_profile_to_pplib_workload(power_profile_mode);
3957 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
3958 1 << workload_type);
3960 hwmgr->power_profile_mode = power_profile_mode;
3965 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
3966 uint32_t virtual_addr_low,
3967 uint32_t virtual_addr_hi,
3968 uint32_t mc_addr_low,
3969 uint32_t mc_addr_hi,
3972 smum_send_msg_to_smc_with_parameter(hwmgr,
3973 PPSMC_MSG_SetSystemVirtualDramAddrHigh,
3975 smum_send_msg_to_smc_with_parameter(hwmgr,
3976 PPSMC_MSG_SetSystemVirtualDramAddrLow,
3978 smum_send_msg_to_smc_with_parameter(hwmgr,
3979 PPSMC_MSG_DramLogSetDramAddrHigh,
3982 smum_send_msg_to_smc_with_parameter(hwmgr,
3983 PPSMC_MSG_DramLogSetDramAddrLow,
3986 smum_send_msg_to_smc_with_parameter(hwmgr,
3987 PPSMC_MSG_DramLogSetDramSize,
3992 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
3993 struct PP_TemperatureRange *thermal_data)
3995 struct vega20_hwmgr *data =
3996 (struct vega20_hwmgr *)(hwmgr->backend);
3997 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
3999 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
4001 thermal_data->max = pp_table->TedgeLimit *
4002 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4003 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
4004 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4005 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
4006 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4007 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
4008 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4009 thermal_data->mem_crit_max = pp_table->ThbmLimit *
4010 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4011 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
4012 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4017 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
4018 /* init/fini related */
4019 .backend_init = vega20_hwmgr_backend_init,
4020 .backend_fini = vega20_hwmgr_backend_fini,
4021 .asic_setup = vega20_setup_asic_task,
4022 .power_off_asic = vega20_power_off_asic,
4023 .dynamic_state_management_enable = vega20_enable_dpm_tasks,
4024 .dynamic_state_management_disable = vega20_disable_dpm_tasks,
4025 /* power state related */
4026 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
4027 .pre_display_config_changed = vega20_pre_display_configuration_changed_task,
4028 .display_config_changed = vega20_display_configuration_changed_task,
4029 .check_smc_update_required_for_display_configuration =
4030 vega20_check_smc_update_required_for_display_configuration,
4031 .notify_smc_display_config_after_ps_adjustment =
4032 vega20_notify_smc_display_config_after_ps_adjustment,
4034 .get_sclk = vega20_dpm_get_sclk,
4035 .get_mclk = vega20_dpm_get_mclk,
4036 .get_dal_power_level = vega20_get_dal_power_level,
4037 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
4038 .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage,
4039 .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges,
4040 .display_clock_voltage_request = vega20_display_clock_voltage_request,
4041 .get_performance_level = vega20_get_performance_level,
4042 /* UMD pstate, profile related */
4043 .force_dpm_level = vega20_dpm_force_dpm_level,
4044 .get_power_profile_mode = vega20_get_power_profile_mode,
4045 .set_power_profile_mode = vega20_set_power_profile_mode,
4047 .set_power_limit = vega20_set_power_limit,
4048 .get_sclk_od = vega20_get_sclk_od,
4049 .set_sclk_od = vega20_set_sclk_od,
4050 .get_mclk_od = vega20_get_mclk_od,
4051 .set_mclk_od = vega20_set_mclk_od,
4052 .odn_edit_dpm_table = vega20_odn_edit_dpm_table,
4053 /* for sysfs to retrive/set gfxclk/memclk */
4054 .force_clock_level = vega20_force_clock_level,
4055 .print_clock_levels = vega20_print_clock_levels,
4056 .read_sensor = vega20_read_sensor,
4057 .get_ppfeature_status = vega20_get_ppfeature_status,
4058 .set_ppfeature_status = vega20_set_ppfeature_status,
4059 /* powergate related */
4060 .powergate_uvd = vega20_power_gate_uvd,
4061 .powergate_vce = vega20_power_gate_vce,
4062 /* thermal related */
4063 .start_thermal_controller = vega20_start_thermal_controller,
4064 .stop_thermal_controller = vega20_thermal_stop_thermal_controller,
4065 .get_thermal_temperature_range = vega20_get_thermal_temperature_range,
4066 .register_irq_handlers = smu9_register_irq_handlers,
4067 .disable_smc_firmware_ctf = vega20_thermal_disable_alert,
4068 /* fan control related */
4069 .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent,
4070 .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent,
4071 .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info,
4072 .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm,
4073 .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm,
4074 .get_fan_control_mode = vega20_get_fan_control_mode,
4075 .set_fan_control_mode = vega20_set_fan_control_mode,
4076 /* smu memory related */
4077 .notify_cac_buffer_info = vega20_notify_cac_buffer_info,
4078 .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost,
4080 .get_asic_baco_capability = vega20_baco_get_capability,
4081 .get_asic_baco_state = vega20_baco_get_state,
4082 .set_asic_baco_state = vega20_baco_set_state,
4085 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
4087 hwmgr->hwmgr_func = &vega20_hwmgr_funcs;
4088 hwmgr->pptable_func = &vega20_pptable_funcs;