1 /* 2 * Copyright 2018 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24 #include <linux/delay.h> 25 #include <linux/module.h> 26 #include <linux/slab.h> 27 28 #include "hwmgr.h" 29 #include "amd_powerplay.h" 30 #include "vega20_smumgr.h" 31 #include "hardwaremanager.h" 32 #include "ppatomfwctrl.h" 33 #include "atomfirmware.h" 34 #include "cgs_common.h" 35 #include "vega20_powertune.h" 36 #include "vega20_inc.h" 37 #include "pppcielanes.h" 38 #include "vega20_hwmgr.h" 39 #include "vega20_processpptables.h" 40 #include "vega20_pptable.h" 41 #include "vega20_thermal.h" 42 #include "vega20_ppsmc.h" 43 #include "pp_debug.h" 44 #include "amd_pcie_helpers.h" 45 #include "ppinterrupt.h" 46 #include "pp_overdriver.h" 47 #include "pp_thermal.h" 48 #include "soc15_common.h" 49 #include "vega20_baco.h" 50 #include "smuio/smuio_9_0_offset.h" 51 #include "smuio/smuio_9_0_sh_mask.h" 52 #include "nbio/nbio_7_4_sh_mask.h" 53 54 #define smnPCIE_LC_SPEED_CNTL 0x11140290 55 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 56 57 #define LINK_WIDTH_MAX 6 58 #define LINK_SPEED_MAX 3 59 static const int link_width[] = {0, 1, 2, 4, 8, 12, 16}; 60 static const int link_speed[] = {25, 50, 80, 160}; 61 62 static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr) 63 { 64 struct vega20_hwmgr *data = 65 (struct vega20_hwmgr *)(hwmgr->backend); 66 67 data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT; 68 data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT; 69 data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT; 70 data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT; 71 data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT; 72 73 data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT; 74 data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 75 data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 76 data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 77 data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 78 data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 79 data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 80 data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 81 data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 82 data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 83 data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 84 data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 85 data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; 86 87 /* 88 * Disable the following features for now: 89 * GFXCLK DS 90 * SOCLK DS 91 * LCLK DS 92 * DCEFCLK DS 93 * FCLK DS 94 * MP1CLK DS 95 * MP0CLK DS 96 */ 97 data->registry_data.disallowed_features = 0xE0041C00; 98 /* ECC feature should be disabled on old SMUs */ 99 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version); 100 if (hwmgr->smu_version < 0x282100) 101 data->registry_data.disallowed_features |= FEATURE_ECC_MASK; 102 103 if (!(hwmgr->feature_mask & PP_PCIE_DPM_MASK)) 104 data->registry_data.disallowed_features |= FEATURE_DPM_LINK_MASK; 105 106 if (!(hwmgr->feature_mask & PP_SCLK_DPM_MASK)) 107 data->registry_data.disallowed_features |= FEATURE_DPM_GFXCLK_MASK; 108 109 if (!(hwmgr->feature_mask & PP_SOCCLK_DPM_MASK)) 110 data->registry_data.disallowed_features |= FEATURE_DPM_SOCCLK_MASK; 111 112 if (!(hwmgr->feature_mask & PP_MCLK_DPM_MASK)) 113 data->registry_data.disallowed_features |= FEATURE_DPM_UCLK_MASK; 114 115 if (!(hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK)) 116 data->registry_data.disallowed_features |= FEATURE_DPM_DCEFCLK_MASK; 117 118 if (!(hwmgr->feature_mask & PP_ULV_MASK)) 119 data->registry_data.disallowed_features |= FEATURE_ULV_MASK; 120 121 if (!(hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK)) 122 data->registry_data.disallowed_features |= FEATURE_DS_GFXCLK_MASK; 123 124 data->registry_data.od_state_in_dc_support = 0; 125 data->registry_data.thermal_support = 1; 126 data->registry_data.skip_baco_hardware = 0; 127 128 data->registry_data.log_avfs_param = 0; 129 data->registry_data.sclk_throttle_low_notification = 1; 130 data->registry_data.force_dpm_high = 0; 131 data->registry_data.stable_pstate_sclk_dpm_percentage = 75; 132 133 data->registry_data.didt_support = 0; 134 if (data->registry_data.didt_support) { 135 data->registry_data.didt_mode = 6; 136 data->registry_data.sq_ramping_support = 1; 137 data->registry_data.db_ramping_support = 0; 138 data->registry_data.td_ramping_support = 0; 139 data->registry_data.tcp_ramping_support = 0; 140 data->registry_data.dbr_ramping_support = 0; 141 data->registry_data.edc_didt_support = 1; 142 data->registry_data.gc_didt_support = 0; 143 data->registry_data.psm_didt_support = 0; 144 } 145 146 data->registry_data.pcie_lane_override = 0xff; 147 data->registry_data.pcie_speed_override = 0xff; 148 data->registry_data.pcie_clock_override = 0xffffffff; 149 data->registry_data.regulator_hot_gpio_support = 1; 150 data->registry_data.ac_dc_switch_gpio_support = 0; 151 data->registry_data.quick_transition_support = 0; 152 data->registry_data.zrpm_start_temp = 0xffff; 153 data->registry_data.zrpm_stop_temp = 0xffff; 154 data->registry_data.od8_feature_enable = 1; 155 data->registry_data.disable_water_mark = 0; 156 data->registry_data.disable_pp_tuning = 0; 157 data->registry_data.disable_xlpp_tuning = 0; 158 data->registry_data.disable_workload_policy = 0; 159 data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F; 160 data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919; 161 data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A; 162 data->registry_data.force_workload_policy_mask = 0; 163 data->registry_data.disable_3d_fs_detection = 0; 164 data->registry_data.fps_support = 1; 165 data->registry_data.disable_auto_wattman = 1; 166 data->registry_data.auto_wattman_debug = 0; 167 data->registry_data.auto_wattman_sample_period = 100; 168 data->registry_data.fclk_gfxclk_ratio = 0; 169 data->registry_data.auto_wattman_threshold = 50; 170 data->registry_data.gfxoff_controlled_by_driver = 1; 171 data->gfxoff_allowed = false; 172 data->counter_gfxoff = 0; 173 data->registry_data.pcie_dpm_key_disabled = !(hwmgr->feature_mask & PP_PCIE_DPM_MASK); 174 } 175 176 static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr) 177 { 178 struct vega20_hwmgr *data = 179 (struct vega20_hwmgr *)(hwmgr->backend); 180 struct amdgpu_device *adev = hwmgr->adev; 181 182 if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE) 183 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 184 PHM_PlatformCaps_ControlVDDCI); 185 186 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 187 PHM_PlatformCaps_TablelessHardwareInterface); 188 189 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 190 PHM_PlatformCaps_BACO); 191 192 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 193 PHM_PlatformCaps_EnableSMU7ThermalManagement); 194 195 if (adev->pg_flags & AMD_PG_SUPPORT_UVD) 196 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 197 PHM_PlatformCaps_UVDPowerGating); 198 199 if (adev->pg_flags & AMD_PG_SUPPORT_VCE) 200 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 201 PHM_PlatformCaps_VCEPowerGating); 202 203 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 204 PHM_PlatformCaps_UnTabledHardwareInterface); 205 206 if (data->registry_data.od8_feature_enable) 207 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 208 PHM_PlatformCaps_OD8inACSupport); 209 210 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 211 PHM_PlatformCaps_ActivityReporting); 212 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 213 PHM_PlatformCaps_FanSpeedInTableIsRPM); 214 215 if (data->registry_data.od_state_in_dc_support) { 216 if (data->registry_data.od8_feature_enable) 217 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 218 PHM_PlatformCaps_OD8inDCSupport); 219 } 220 221 if (data->registry_data.thermal_support && 222 data->registry_data.fuzzy_fan_control_support && 223 hwmgr->thermal_controller.advanceFanControlParameters.usTMax) 224 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 225 PHM_PlatformCaps_ODFuzzyFanControlSupport); 226 227 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 228 PHM_PlatformCaps_DynamicPowerManagement); 229 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 230 PHM_PlatformCaps_SMC); 231 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 232 PHM_PlatformCaps_ThermalPolicyDelay); 233 234 if (data->registry_data.force_dpm_high) 235 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 236 PHM_PlatformCaps_ExclusiveModeAlwaysHigh); 237 238 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 239 PHM_PlatformCaps_DynamicUVDState); 240 241 if (data->registry_data.sclk_throttle_low_notification) 242 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 243 PHM_PlatformCaps_SclkThrottleLowNotification); 244 245 /* power tune caps */ 246 /* assume disabled */ 247 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 248 PHM_PlatformCaps_PowerContainment); 249 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 250 PHM_PlatformCaps_DiDtSupport); 251 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 252 PHM_PlatformCaps_SQRamping); 253 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 254 PHM_PlatformCaps_DBRamping); 255 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 256 PHM_PlatformCaps_TDRamping); 257 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 258 PHM_PlatformCaps_TCPRamping); 259 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 260 PHM_PlatformCaps_DBRRamping); 261 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 262 PHM_PlatformCaps_DiDtEDCEnable); 263 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 264 PHM_PlatformCaps_GCEDC); 265 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 266 PHM_PlatformCaps_PSM); 267 268 if (data->registry_data.didt_support) { 269 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 270 PHM_PlatformCaps_DiDtSupport); 271 if (data->registry_data.sq_ramping_support) 272 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 273 PHM_PlatformCaps_SQRamping); 274 if (data->registry_data.db_ramping_support) 275 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 276 PHM_PlatformCaps_DBRamping); 277 if (data->registry_data.td_ramping_support) 278 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 279 PHM_PlatformCaps_TDRamping); 280 if (data->registry_data.tcp_ramping_support) 281 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 282 PHM_PlatformCaps_TCPRamping); 283 if (data->registry_data.dbr_ramping_support) 284 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 285 PHM_PlatformCaps_DBRRamping); 286 if (data->registry_data.edc_didt_support) 287 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 288 PHM_PlatformCaps_DiDtEDCEnable); 289 if (data->registry_data.gc_didt_support) 290 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 291 PHM_PlatformCaps_GCEDC); 292 if (data->registry_data.psm_didt_support) 293 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 294 PHM_PlatformCaps_PSM); 295 } 296 297 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 298 PHM_PlatformCaps_RegulatorHot); 299 300 if (data->registry_data.ac_dc_switch_gpio_support) { 301 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 302 PHM_PlatformCaps_AutomaticDCTransition); 303 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 304 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); 305 } 306 307 if (data->registry_data.quick_transition_support) { 308 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 309 PHM_PlatformCaps_AutomaticDCTransition); 310 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 311 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); 312 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 313 PHM_PlatformCaps_Falcon_QuickTransition); 314 } 315 316 if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) { 317 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 318 PHM_PlatformCaps_LowestUclkReservedForUlv); 319 if (data->lowest_uclk_reserved_for_ulv == 1) 320 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 321 PHM_PlatformCaps_LowestUclkReservedForUlv); 322 } 323 324 if (data->registry_data.custom_fan_support) 325 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 326 PHM_PlatformCaps_CustomFanControlSupport); 327 328 return 0; 329 } 330 331 static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr) 332 { 333 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 334 struct amdgpu_device *adev = hwmgr->adev; 335 uint32_t top32, bottom32; 336 int i; 337 338 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = 339 FEATURE_DPM_PREFETCHER_BIT; 340 data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = 341 FEATURE_DPM_GFXCLK_BIT; 342 data->smu_features[GNLD_DPM_UCLK].smu_feature_id = 343 FEATURE_DPM_UCLK_BIT; 344 data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = 345 FEATURE_DPM_SOCCLK_BIT; 346 data->smu_features[GNLD_DPM_UVD].smu_feature_id = 347 FEATURE_DPM_UVD_BIT; 348 data->smu_features[GNLD_DPM_VCE].smu_feature_id = 349 FEATURE_DPM_VCE_BIT; 350 data->smu_features[GNLD_ULV].smu_feature_id = 351 FEATURE_ULV_BIT; 352 data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = 353 FEATURE_DPM_MP0CLK_BIT; 354 data->smu_features[GNLD_DPM_LINK].smu_feature_id = 355 FEATURE_DPM_LINK_BIT; 356 data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = 357 FEATURE_DPM_DCEFCLK_BIT; 358 data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = 359 FEATURE_DS_GFXCLK_BIT; 360 data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = 361 FEATURE_DS_SOCCLK_BIT; 362 data->smu_features[GNLD_DS_LCLK].smu_feature_id = 363 FEATURE_DS_LCLK_BIT; 364 data->smu_features[GNLD_PPT].smu_feature_id = 365 FEATURE_PPT_BIT; 366 data->smu_features[GNLD_TDC].smu_feature_id = 367 FEATURE_TDC_BIT; 368 data->smu_features[GNLD_THERMAL].smu_feature_id = 369 FEATURE_THERMAL_BIT; 370 data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = 371 FEATURE_GFX_PER_CU_CG_BIT; 372 data->smu_features[GNLD_RM].smu_feature_id = 373 FEATURE_RM_BIT; 374 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = 375 FEATURE_DS_DCEFCLK_BIT; 376 data->smu_features[GNLD_ACDC].smu_feature_id = 377 FEATURE_ACDC_BIT; 378 data->smu_features[GNLD_VR0HOT].smu_feature_id = 379 FEATURE_VR0HOT_BIT; 380 data->smu_features[GNLD_VR1HOT].smu_feature_id = 381 FEATURE_VR1HOT_BIT; 382 data->smu_features[GNLD_FW_CTF].smu_feature_id = 383 FEATURE_FW_CTF_BIT; 384 data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = 385 FEATURE_LED_DISPLAY_BIT; 386 data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = 387 FEATURE_FAN_CONTROL_BIT; 388 data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; 389 data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT; 390 data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT; 391 data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT; 392 data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT; 393 data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT; 394 data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT; 395 data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT; 396 data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT; 397 398 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 399 data->smu_features[i].smu_feature_bitmap = 400 (uint64_t)(1ULL << data->smu_features[i].smu_feature_id); 401 data->smu_features[i].allowed = 402 ((data->registry_data.disallowed_features >> i) & 1) ? 403 false : true; 404 } 405 406 /* Get the SN to turn into a Unique ID */ 407 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); 408 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); 409 410 adev->unique_id = ((uint64_t)bottom32 << 32) | top32; 411 } 412 413 static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) 414 { 415 return 0; 416 } 417 418 static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) 419 { 420 kfree(hwmgr->backend); 421 hwmgr->backend = NULL; 422 423 return 0; 424 } 425 426 static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr) 427 { 428 struct vega20_hwmgr *data; 429 struct amdgpu_device *adev = hwmgr->adev; 430 431 data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL); 432 if (data == NULL) 433 return -ENOMEM; 434 435 hwmgr->backend = data; 436 437 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; 438 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; 439 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; 440 441 vega20_set_default_registry_data(hwmgr); 442 443 data->disable_dpm_mask = 0xff; 444 445 /* need to set voltage control types before EVV patching */ 446 data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE; 447 data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE; 448 data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE; 449 450 data->water_marks_bitmap = 0; 451 data->avfs_exist = false; 452 453 vega20_set_features_platform_caps(hwmgr); 454 455 vega20_init_dpm_defaults(hwmgr); 456 457 /* Parse pptable data read from VBIOS */ 458 vega20_set_private_data_based_on_pptable(hwmgr); 459 460 data->is_tlu_enabled = false; 461 462 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = 463 VEGA20_MAX_HARDWARE_POWERLEVELS; 464 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; 465 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; 466 467 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ 468 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ 469 hwmgr->platform_descriptor.clockStep.engineClock = 500; 470 hwmgr->platform_descriptor.clockStep.memoryClock = 500; 471 472 data->total_active_cus = adev->gfx.cu_info.number; 473 data->is_custom_profile_set = false; 474 475 return 0; 476 } 477 478 static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr) 479 { 480 struct vega20_hwmgr *data = 481 (struct vega20_hwmgr *)(hwmgr->backend); 482 483 data->low_sclk_interrupt_threshold = 0; 484 485 return 0; 486 } 487 488 static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) 489 { 490 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); 491 int ret = 0; 492 bool use_baco = (amdgpu_in_reset(adev) && 493 (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || 494 (adev->in_runpm && amdgpu_asic_supports_baco(adev)); 495 496 ret = vega20_init_sclk_threshold(hwmgr); 497 PP_ASSERT_WITH_CODE(!ret, 498 "Failed to init sclk threshold!", 499 return ret); 500 501 if (use_baco) { 502 ret = vega20_baco_apply_vdci_flush_workaround(hwmgr); 503 if (ret) 504 pr_err("Failed to apply vega20 baco workaround!\n"); 505 } 506 507 return ret; 508 } 509 510 /* 511 * @fn vega20_init_dpm_state 512 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. 513 * 514 * @param dpm_state - the address of the DPM Table to initiailize. 515 * @return None. 516 */ 517 static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state) 518 { 519 dpm_state->soft_min_level = 0x0; 520 dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT; 521 dpm_state->hard_min_level = 0x0; 522 dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT; 523 } 524 525 static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr, 526 PPCLK_e clk_id, uint32_t *num_of_levels) 527 { 528 int ret = 0; 529 530 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 531 PPSMC_MSG_GetDpmFreqByIndex, 532 (clk_id << 16 | 0xFF), 533 num_of_levels); 534 PP_ASSERT_WITH_CODE(!ret, 535 "[GetNumOfDpmLevel] failed to get dpm levels!", 536 return ret); 537 538 return ret; 539 } 540 541 static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr, 542 PPCLK_e clk_id, uint32_t index, uint32_t *clk) 543 { 544 int ret = 0; 545 546 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 547 PPSMC_MSG_GetDpmFreqByIndex, 548 (clk_id << 16 | index), 549 clk); 550 PP_ASSERT_WITH_CODE(!ret, 551 "[GetDpmFreqByIndex] failed to get dpm freq by index!", 552 return ret); 553 554 return ret; 555 } 556 557 static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr, 558 struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id) 559 { 560 int ret = 0; 561 uint32_t i, num_of_levels, clk; 562 563 ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels); 564 PP_ASSERT_WITH_CODE(!ret, 565 "[SetupSingleDpmTable] failed to get clk levels!", 566 return ret); 567 568 dpm_table->count = num_of_levels; 569 570 for (i = 0; i < num_of_levels; i++) { 571 ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk); 572 PP_ASSERT_WITH_CODE(!ret, 573 "[SetupSingleDpmTable] failed to get clk of specific level!", 574 return ret); 575 dpm_table->dpm_levels[i].value = clk; 576 dpm_table->dpm_levels[i].enabled = true; 577 } 578 579 return ret; 580 } 581 582 static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr) 583 { 584 struct vega20_hwmgr *data = 585 (struct vega20_hwmgr *)(hwmgr->backend); 586 struct vega20_single_dpm_table *dpm_table; 587 int ret = 0; 588 589 dpm_table = &(data->dpm_table.gfx_table); 590 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { 591 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK); 592 PP_ASSERT_WITH_CODE(!ret, 593 "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!", 594 return ret); 595 } else { 596 dpm_table->count = 1; 597 dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100; 598 } 599 600 return ret; 601 } 602 603 static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr) 604 { 605 struct vega20_hwmgr *data = 606 (struct vega20_hwmgr *)(hwmgr->backend); 607 struct vega20_single_dpm_table *dpm_table; 608 int ret = 0; 609 610 dpm_table = &(data->dpm_table.mem_table); 611 if (data->smu_features[GNLD_DPM_UCLK].enabled) { 612 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK); 613 PP_ASSERT_WITH_CODE(!ret, 614 "[SetupDefaultDpmTable] failed to get memclk dpm levels!", 615 return ret); 616 } else { 617 dpm_table->count = 1; 618 dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100; 619 } 620 621 return ret; 622 } 623 624 /* 625 * This function is to initialize all DPM state tables 626 * for SMU based on the dependency table. 627 * Dynamic state patching function will then trim these 628 * state tables to the allowed range based 629 * on the power policy or external client requests, 630 * such as UVD request, etc. 631 */ 632 static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) 633 { 634 struct vega20_hwmgr *data = 635 (struct vega20_hwmgr *)(hwmgr->backend); 636 struct vega20_single_dpm_table *dpm_table; 637 int ret = 0; 638 639 memset(&data->dpm_table, 0, sizeof(data->dpm_table)); 640 641 /* socclk */ 642 dpm_table = &(data->dpm_table.soc_table); 643 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { 644 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK); 645 PP_ASSERT_WITH_CODE(!ret, 646 "[SetupDefaultDpmTable] failed to get socclk dpm levels!", 647 return ret); 648 } else { 649 dpm_table->count = 1; 650 dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100; 651 } 652 vega20_init_dpm_state(&(dpm_table->dpm_state)); 653 654 /* gfxclk */ 655 dpm_table = &(data->dpm_table.gfx_table); 656 ret = vega20_setup_gfxclk_dpm_table(hwmgr); 657 if (ret) 658 return ret; 659 vega20_init_dpm_state(&(dpm_table->dpm_state)); 660 661 /* memclk */ 662 dpm_table = &(data->dpm_table.mem_table); 663 ret = vega20_setup_memclk_dpm_table(hwmgr); 664 if (ret) 665 return ret; 666 vega20_init_dpm_state(&(dpm_table->dpm_state)); 667 668 /* eclk */ 669 dpm_table = &(data->dpm_table.eclk_table); 670 if (data->smu_features[GNLD_DPM_VCE].enabled) { 671 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK); 672 PP_ASSERT_WITH_CODE(!ret, 673 "[SetupDefaultDpmTable] failed to get eclk dpm levels!", 674 return ret); 675 } else { 676 dpm_table->count = 1; 677 dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100; 678 } 679 vega20_init_dpm_state(&(dpm_table->dpm_state)); 680 681 /* vclk */ 682 dpm_table = &(data->dpm_table.vclk_table); 683 if (data->smu_features[GNLD_DPM_UVD].enabled) { 684 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK); 685 PP_ASSERT_WITH_CODE(!ret, 686 "[SetupDefaultDpmTable] failed to get vclk dpm levels!", 687 return ret); 688 } else { 689 dpm_table->count = 1; 690 dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100; 691 } 692 vega20_init_dpm_state(&(dpm_table->dpm_state)); 693 694 /* dclk */ 695 dpm_table = &(data->dpm_table.dclk_table); 696 if (data->smu_features[GNLD_DPM_UVD].enabled) { 697 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK); 698 PP_ASSERT_WITH_CODE(!ret, 699 "[SetupDefaultDpmTable] failed to get dclk dpm levels!", 700 return ret); 701 } else { 702 dpm_table->count = 1; 703 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100; 704 } 705 vega20_init_dpm_state(&(dpm_table->dpm_state)); 706 707 /* dcefclk */ 708 dpm_table = &(data->dpm_table.dcef_table); 709 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 710 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK); 711 PP_ASSERT_WITH_CODE(!ret, 712 "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!", 713 return ret); 714 } else { 715 dpm_table->count = 1; 716 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100; 717 } 718 vega20_init_dpm_state(&(dpm_table->dpm_state)); 719 720 /* pixclk */ 721 dpm_table = &(data->dpm_table.pixel_table); 722 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 723 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK); 724 PP_ASSERT_WITH_CODE(!ret, 725 "[SetupDefaultDpmTable] failed to get pixclk dpm levels!", 726 return ret); 727 } else 728 dpm_table->count = 0; 729 vega20_init_dpm_state(&(dpm_table->dpm_state)); 730 731 /* dispclk */ 732 dpm_table = &(data->dpm_table.display_table); 733 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 734 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK); 735 PP_ASSERT_WITH_CODE(!ret, 736 "[SetupDefaultDpmTable] failed to get dispclk dpm levels!", 737 return ret); 738 } else 739 dpm_table->count = 0; 740 vega20_init_dpm_state(&(dpm_table->dpm_state)); 741 742 /* phyclk */ 743 dpm_table = &(data->dpm_table.phy_table); 744 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 745 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK); 746 PP_ASSERT_WITH_CODE(!ret, 747 "[SetupDefaultDpmTable] failed to get phyclk dpm levels!", 748 return ret); 749 } else 750 dpm_table->count = 0; 751 vega20_init_dpm_state(&(dpm_table->dpm_state)); 752 753 /* fclk */ 754 dpm_table = &(data->dpm_table.fclk_table); 755 if (data->smu_features[GNLD_DPM_FCLK].enabled) { 756 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK); 757 PP_ASSERT_WITH_CODE(!ret, 758 "[SetupDefaultDpmTable] failed to get fclk dpm levels!", 759 return ret); 760 } else { 761 dpm_table->count = 1; 762 dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100; 763 } 764 vega20_init_dpm_state(&(dpm_table->dpm_state)); 765 766 /* save a copy of the default DPM table */ 767 memcpy(&(data->golden_dpm_table), &(data->dpm_table), 768 sizeof(struct vega20_dpm_table)); 769 770 return 0; 771 } 772 773 /** 774 * vega20_init_smc_table - Initializes the SMC table and uploads it 775 * 776 * @hwmgr: the address of the powerplay hardware manager. 777 * return: always 0 778 */ 779 static int vega20_init_smc_table(struct pp_hwmgr *hwmgr) 780 { 781 int result; 782 struct vega20_hwmgr *data = 783 (struct vega20_hwmgr *)(hwmgr->backend); 784 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 785 struct pp_atomfwctrl_bios_boot_up_values boot_up_values; 786 struct phm_ppt_v3_information *pptable_information = 787 (struct phm_ppt_v3_information *)hwmgr->pptable; 788 789 result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); 790 PP_ASSERT_WITH_CODE(!result, 791 "[InitSMCTable] Failed to get vbios bootup values!", 792 return result); 793 794 data->vbios_boot_state.vddc = boot_up_values.usVddc; 795 data->vbios_boot_state.vddci = boot_up_values.usVddci; 796 data->vbios_boot_state.mvddc = boot_up_values.usMvddc; 797 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; 798 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; 799 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; 800 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; 801 data->vbios_boot_state.eclock = boot_up_values.ulEClk; 802 data->vbios_boot_state.vclock = boot_up_values.ulVClk; 803 data->vbios_boot_state.dclock = boot_up_values.ulDClk; 804 data->vbios_boot_state.fclock = boot_up_values.ulFClk; 805 data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID; 806 807 smum_send_msg_to_smc_with_parameter(hwmgr, 808 PPSMC_MSG_SetMinDeepSleepDcefclk, 809 (uint32_t)(data->vbios_boot_state.dcef_clock / 100), 810 NULL); 811 812 memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t)); 813 814 result = smum_smc_table_manager(hwmgr, 815 (uint8_t *)pp_table, TABLE_PPTABLE, false); 816 PP_ASSERT_WITH_CODE(!result, 817 "[InitSMCTable] Failed to upload PPtable!", 818 return result); 819 820 return 0; 821 } 822 823 /* 824 * Override PCIe link speed and link width for DPM Level 1. PPTable entries 825 * reflect the ASIC capabilities and not the system capabilities. For e.g. 826 * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch 827 * to DPM1, it fails as system doesn't support Gen4. 828 */ 829 static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr) 830 { 831 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); 832 struct vega20_hwmgr *data = 833 (struct vega20_hwmgr *)(hwmgr->backend); 834 uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg; 835 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 836 int i; 837 int ret; 838 839 if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) 840 pcie_gen = 3; 841 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) 842 pcie_gen = 2; 843 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) 844 pcie_gen = 1; 845 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) 846 pcie_gen = 0; 847 848 if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) 849 pcie_width = 6; 850 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) 851 pcie_width = 5; 852 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) 853 pcie_width = 4; 854 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) 855 pcie_width = 3; 856 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) 857 pcie_width = 2; 858 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) 859 pcie_width = 1; 860 861 /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 862 * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 863 * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 864 */ 865 for (i = 0; i < NUM_LINK_LEVELS; i++) { 866 pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen : 867 pp_table->PcieGenSpeed[i]; 868 pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width : 869 pp_table->PcieLaneCount[i]; 870 871 if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg != 872 pp_table->PcieLaneCount[i]) { 873 smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg; 874 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 875 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg, 876 NULL); 877 PP_ASSERT_WITH_CODE(!ret, 878 "[OverridePcieParameters] Attempt to override pcie params failed!", 879 return ret); 880 } 881 882 /* update the pptable */ 883 pp_table->PcieGenSpeed[i] = pcie_gen_arg; 884 pp_table->PcieLaneCount[i] = pcie_width_arg; 885 } 886 887 /* override to the highest if it's disabled from ppfeaturmask */ 888 if (data->registry_data.pcie_dpm_key_disabled) { 889 for (i = 0; i < NUM_LINK_LEVELS; i++) { 890 smu_pcie_arg = (i << 16) | (pcie_gen << 8) | pcie_width; 891 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 892 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg, 893 NULL); 894 PP_ASSERT_WITH_CODE(!ret, 895 "[OverridePcieParameters] Attempt to override pcie params failed!", 896 return ret); 897 898 pp_table->PcieGenSpeed[i] = pcie_gen; 899 pp_table->PcieLaneCount[i] = pcie_width; 900 } 901 ret = vega20_enable_smc_features(hwmgr, 902 false, 903 data->smu_features[GNLD_DPM_LINK].smu_feature_bitmap); 904 PP_ASSERT_WITH_CODE(!ret, 905 "Attempt to Disable DPM LINK Failed!", 906 return ret); 907 data->smu_features[GNLD_DPM_LINK].enabled = false; 908 data->smu_features[GNLD_DPM_LINK].supported = false; 909 } 910 911 return 0; 912 } 913 914 static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr) 915 { 916 struct vega20_hwmgr *data = 917 (struct vega20_hwmgr *)(hwmgr->backend); 918 uint32_t allowed_features_low = 0, allowed_features_high = 0; 919 int i; 920 int ret = 0; 921 922 for (i = 0; i < GNLD_FEATURES_MAX; i++) 923 if (data->smu_features[i].allowed) 924 data->smu_features[i].smu_feature_id > 31 ? 925 (allowed_features_high |= 926 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) 927 & 0xFFFFFFFF)) : 928 (allowed_features_low |= 929 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) 930 & 0xFFFFFFFF)); 931 932 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 933 PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, NULL); 934 PP_ASSERT_WITH_CODE(!ret, 935 "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!", 936 return ret); 937 938 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 939 PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, NULL); 940 PP_ASSERT_WITH_CODE(!ret, 941 "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!", 942 return ret); 943 944 return 0; 945 } 946 947 static int vega20_run_btc(struct pp_hwmgr *hwmgr) 948 { 949 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc, NULL); 950 } 951 952 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr) 953 { 954 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc, NULL); 955 } 956 957 static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr) 958 { 959 struct vega20_hwmgr *data = 960 (struct vega20_hwmgr *)(hwmgr->backend); 961 uint64_t features_enabled; 962 int i; 963 bool enabled; 964 int ret = 0; 965 966 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, 967 PPSMC_MSG_EnableAllSmuFeatures, 968 NULL)) == 0, 969 "[EnableAllSMUFeatures] Failed to enable all smu features!", 970 return ret); 971 972 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 973 PP_ASSERT_WITH_CODE(!ret, 974 "[EnableAllSmuFeatures] Failed to get enabled smc features!", 975 return ret); 976 977 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 978 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? 979 true : false; 980 data->smu_features[i].enabled = enabled; 981 data->smu_features[i].supported = enabled; 982 983 #if 0 984 if (data->smu_features[i].allowed && !enabled) 985 pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i); 986 else if (!data->smu_features[i].allowed && enabled) 987 pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i); 988 #endif 989 } 990 991 return 0; 992 } 993 994 static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr) 995 { 996 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 997 998 if (data->smu_features[GNLD_DPM_UCLK].enabled) 999 return smum_send_msg_to_smc_with_parameter(hwmgr, 1000 PPSMC_MSG_SetUclkFastSwitch, 1001 1, 1002 NULL); 1003 1004 return 0; 1005 } 1006 1007 static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr) 1008 { 1009 struct vega20_hwmgr *data = 1010 (struct vega20_hwmgr *)(hwmgr->backend); 1011 1012 return smum_send_msg_to_smc_with_parameter(hwmgr, 1013 PPSMC_MSG_SetFclkGfxClkRatio, 1014 data->registry_data.fclk_gfxclk_ratio, 1015 NULL); 1016 } 1017 1018 static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) 1019 { 1020 struct vega20_hwmgr *data = 1021 (struct vega20_hwmgr *)(hwmgr->backend); 1022 int i, ret = 0; 1023 1024 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, 1025 PPSMC_MSG_DisableAllSmuFeatures, 1026 NULL)) == 0, 1027 "[DisableAllSMUFeatures] Failed to disable all smu features!", 1028 return ret); 1029 1030 for (i = 0; i < GNLD_FEATURES_MAX; i++) 1031 data->smu_features[i].enabled = 0; 1032 1033 return 0; 1034 } 1035 1036 static int vega20_od8_set_feature_capabilities( 1037 struct pp_hwmgr *hwmgr) 1038 { 1039 struct phm_ppt_v3_information *pptable_information = 1040 (struct phm_ppt_v3_information *)hwmgr->pptable; 1041 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 1042 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1043 struct vega20_od8_settings *od_settings = &(data->od8_settings); 1044 1045 od_settings->overdrive8_capabilities = 0; 1046 1047 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { 1048 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] && 1049 pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 && 1050 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 && 1051 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >= 1052 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) 1053 od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS; 1054 1055 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] && 1056 (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >= 1057 pp_table->MinVoltageGfx / VOLTAGE_SCALE) && 1058 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <= 1059 pp_table->MaxVoltageGfx / VOLTAGE_SCALE) && 1060 (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >= 1061 pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1])) 1062 od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE; 1063 } 1064 1065 if (data->smu_features[GNLD_DPM_UCLK].enabled) { 1066 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] = 1067 data->dpm_table.mem_table.dpm_levels[data->dpm_table.mem_table.count - 2].value; 1068 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] && 1069 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 && 1070 pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 && 1071 (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >= 1072 pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX])) 1073 od_settings->overdrive8_capabilities |= OD8_UCLK_MAX; 1074 } 1075 1076 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] && 1077 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 && 1078 pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 && 1079 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 && 1080 pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100) 1081 od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT; 1082 1083 if (data->smu_features[GNLD_FAN_CONTROL].enabled) { 1084 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] && 1085 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && 1086 pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && 1087 (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >= 1088 pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) 1089 od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK; 1090 1091 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] && 1092 (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >= 1093 (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) && 1094 pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 && 1095 (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >= 1096 pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) 1097 od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN; 1098 } 1099 1100 if (data->smu_features[GNLD_THERMAL].enabled) { 1101 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] && 1102 pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 && 1103 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 && 1104 (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >= 1105 pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) 1106 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN; 1107 1108 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] && 1109 pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && 1110 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && 1111 (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >= 1112 pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) 1113 od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM; 1114 } 1115 1116 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE]) 1117 od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE; 1118 1119 if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] && 1120 pp_table->FanZeroRpmEnable) 1121 od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL; 1122 1123 if (!od_settings->overdrive8_capabilities) 1124 hwmgr->od_enabled = false; 1125 1126 return 0; 1127 } 1128 1129 static int vega20_od8_set_feature_id( 1130 struct pp_hwmgr *hwmgr) 1131 { 1132 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 1133 struct vega20_od8_settings *od_settings = &(data->od8_settings); 1134 1135 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { 1136 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = 1137 OD8_GFXCLK_LIMITS; 1138 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = 1139 OD8_GFXCLK_LIMITS; 1140 } else { 1141 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = 1142 0; 1143 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = 1144 0; 1145 } 1146 1147 if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { 1148 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = 1149 OD8_GFXCLK_CURVE; 1150 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = 1151 OD8_GFXCLK_CURVE; 1152 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = 1153 OD8_GFXCLK_CURVE; 1154 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = 1155 OD8_GFXCLK_CURVE; 1156 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = 1157 OD8_GFXCLK_CURVE; 1158 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = 1159 OD8_GFXCLK_CURVE; 1160 } else { 1161 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = 1162 0; 1163 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = 1164 0; 1165 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = 1166 0; 1167 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = 1168 0; 1169 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = 1170 0; 1171 od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = 1172 0; 1173 } 1174 1175 if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX) 1176 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX; 1177 else 1178 od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0; 1179 1180 if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT) 1181 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT; 1182 else 1183 od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0; 1184 1185 if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) 1186 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = 1187 OD8_ACOUSTIC_LIMIT_SCLK; 1188 else 1189 od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = 1190 0; 1191 1192 if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) 1193 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = 1194 OD8_FAN_SPEED_MIN; 1195 else 1196 od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = 1197 0; 1198 1199 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) 1200 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = 1201 OD8_TEMPERATURE_FAN; 1202 else 1203 od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = 1204 0; 1205 1206 if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) 1207 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = 1208 OD8_TEMPERATURE_SYSTEM; 1209 else 1210 od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = 1211 0; 1212 1213 return 0; 1214 } 1215 1216 static int vega20_od8_get_gfx_clock_base_voltage( 1217 struct pp_hwmgr *hwmgr, 1218 uint32_t *voltage, 1219 uint32_t freq) 1220 { 1221 int ret = 0; 1222 1223 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 1224 PPSMC_MSG_GetAVFSVoltageByDpm, 1225 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq), 1226 voltage); 1227 PP_ASSERT_WITH_CODE(!ret, 1228 "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!", 1229 return ret); 1230 1231 *voltage = *voltage / VOLTAGE_SCALE; 1232 1233 return 0; 1234 } 1235 1236 static int vega20_od8_initialize_default_settings( 1237 struct pp_hwmgr *hwmgr) 1238 { 1239 struct phm_ppt_v3_information *pptable_information = 1240 (struct phm_ppt_v3_information *)hwmgr->pptable; 1241 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 1242 struct vega20_od8_settings *od8_settings = &(data->od8_settings); 1243 OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table); 1244 int i, ret = 0; 1245 1246 /* Set Feature Capabilities */ 1247 vega20_od8_set_feature_capabilities(hwmgr); 1248 1249 /* Map FeatureID to individual settings */ 1250 vega20_od8_set_feature_id(hwmgr); 1251 1252 /* Set default values */ 1253 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true); 1254 PP_ASSERT_WITH_CODE(!ret, 1255 "Failed to export over drive table!", 1256 return ret); 1257 1258 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { 1259 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = 1260 od_table->GfxclkFmin; 1261 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = 1262 od_table->GfxclkFmax; 1263 } else { 1264 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = 1265 0; 1266 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = 1267 0; 1268 } 1269 1270 if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { 1271 od_table->GfxclkFreq1 = od_table->GfxclkFmin; 1272 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = 1273 od_table->GfxclkFreq1; 1274 1275 od_table->GfxclkFreq3 = od_table->GfxclkFmax; 1276 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = 1277 od_table->GfxclkFreq3; 1278 1279 od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2; 1280 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = 1281 od_table->GfxclkFreq2; 1282 1283 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, 1284 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value), 1285 od_table->GfxclkFreq1), 1286 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", 1287 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0); 1288 od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value 1289 * VOLTAGE_SCALE; 1290 1291 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, 1292 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value), 1293 od_table->GfxclkFreq2), 1294 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", 1295 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0); 1296 od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value 1297 * VOLTAGE_SCALE; 1298 1299 PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, 1300 &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value), 1301 od_table->GfxclkFreq3), 1302 "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", 1303 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0); 1304 od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value 1305 * VOLTAGE_SCALE; 1306 } else { 1307 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = 1308 0; 1309 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 1310 0; 1311 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = 1312 0; 1313 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 1314 0; 1315 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = 1316 0; 1317 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 1318 0; 1319 } 1320 1321 if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX) 1322 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = 1323 od_table->UclkFmax; 1324 else 1325 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = 1326 0; 1327 1328 if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT) 1329 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = 1330 od_table->OverDrivePct; 1331 else 1332 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = 1333 0; 1334 1335 if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) 1336 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = 1337 od_table->FanMaximumRpm; 1338 else 1339 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = 1340 0; 1341 1342 if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) 1343 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = 1344 od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100; 1345 else 1346 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = 1347 0; 1348 1349 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) 1350 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = 1351 od_table->FanTargetTemperature; 1352 else 1353 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = 1354 0; 1355 1356 if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) 1357 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = 1358 od_table->MaxOpTemp; 1359 else 1360 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = 1361 0; 1362 1363 for (i = 0; i < OD8_SETTING_COUNT; i++) { 1364 if (od8_settings->od8_settings_array[i].feature_id) { 1365 od8_settings->od8_settings_array[i].min_value = 1366 pptable_information->od_settings_min[i]; 1367 od8_settings->od8_settings_array[i].max_value = 1368 pptable_information->od_settings_max[i]; 1369 od8_settings->od8_settings_array[i].current_value = 1370 od8_settings->od8_settings_array[i].default_value; 1371 } else { 1372 od8_settings->od8_settings_array[i].min_value = 1373 0; 1374 od8_settings->od8_settings_array[i].max_value = 1375 0; 1376 od8_settings->od8_settings_array[i].current_value = 1377 0; 1378 } 1379 } 1380 1381 ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false); 1382 PP_ASSERT_WITH_CODE(!ret, 1383 "Failed to import over drive table!", 1384 return ret); 1385 1386 return 0; 1387 } 1388 1389 static int vega20_od8_set_settings( 1390 struct pp_hwmgr *hwmgr, 1391 uint32_t index, 1392 uint32_t value) 1393 { 1394 OverDriveTable_t od_table; 1395 int ret = 0; 1396 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 1397 struct vega20_od8_single_setting *od8_settings = 1398 data->od8_settings.od8_settings_array; 1399 1400 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true); 1401 PP_ASSERT_WITH_CODE(!ret, 1402 "Failed to export over drive table!", 1403 return ret); 1404 1405 switch (index) { 1406 case OD8_SETTING_GFXCLK_FMIN: 1407 od_table.GfxclkFmin = (uint16_t)value; 1408 break; 1409 case OD8_SETTING_GFXCLK_FMAX: 1410 if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value || 1411 value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) 1412 return -EINVAL; 1413 1414 od_table.GfxclkFmax = (uint16_t)value; 1415 break; 1416 case OD8_SETTING_GFXCLK_FREQ1: 1417 od_table.GfxclkFreq1 = (uint16_t)value; 1418 break; 1419 case OD8_SETTING_GFXCLK_VOLTAGE1: 1420 od_table.GfxclkVolt1 = (uint16_t)value; 1421 break; 1422 case OD8_SETTING_GFXCLK_FREQ2: 1423 od_table.GfxclkFreq2 = (uint16_t)value; 1424 break; 1425 case OD8_SETTING_GFXCLK_VOLTAGE2: 1426 od_table.GfxclkVolt2 = (uint16_t)value; 1427 break; 1428 case OD8_SETTING_GFXCLK_FREQ3: 1429 od_table.GfxclkFreq3 = (uint16_t)value; 1430 break; 1431 case OD8_SETTING_GFXCLK_VOLTAGE3: 1432 od_table.GfxclkVolt3 = (uint16_t)value; 1433 break; 1434 case OD8_SETTING_UCLK_FMAX: 1435 if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || 1436 value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) 1437 return -EINVAL; 1438 od_table.UclkFmax = (uint16_t)value; 1439 break; 1440 case OD8_SETTING_POWER_PERCENTAGE: 1441 od_table.OverDrivePct = (int16_t)value; 1442 break; 1443 case OD8_SETTING_FAN_ACOUSTIC_LIMIT: 1444 od_table.FanMaximumRpm = (uint16_t)value; 1445 break; 1446 case OD8_SETTING_FAN_MIN_SPEED: 1447 od_table.FanMinimumPwm = (uint16_t)value; 1448 break; 1449 case OD8_SETTING_FAN_TARGET_TEMP: 1450 od_table.FanTargetTemperature = (uint16_t)value; 1451 break; 1452 case OD8_SETTING_OPERATING_TEMP_MAX: 1453 od_table.MaxOpTemp = (uint16_t)value; 1454 break; 1455 } 1456 1457 ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false); 1458 PP_ASSERT_WITH_CODE(!ret, 1459 "Failed to import over drive table!", 1460 return ret); 1461 1462 return 0; 1463 } 1464 1465 static int vega20_get_sclk_od( 1466 struct pp_hwmgr *hwmgr) 1467 { 1468 struct vega20_hwmgr *data = hwmgr->backend; 1469 struct vega20_single_dpm_table *sclk_table = 1470 &(data->dpm_table.gfx_table); 1471 struct vega20_single_dpm_table *golden_sclk_table = 1472 &(data->golden_dpm_table.gfx_table); 1473 int value = sclk_table->dpm_levels[sclk_table->count - 1].value; 1474 int golden_value = golden_sclk_table->dpm_levels 1475 [golden_sclk_table->count - 1].value; 1476 1477 /* od percentage */ 1478 value -= golden_value; 1479 value = DIV_ROUND_UP(value * 100, golden_value); 1480 1481 return value; 1482 } 1483 1484 static int vega20_set_sclk_od( 1485 struct pp_hwmgr *hwmgr, uint32_t value) 1486 { 1487 struct vega20_hwmgr *data = hwmgr->backend; 1488 struct vega20_single_dpm_table *golden_sclk_table = 1489 &(data->golden_dpm_table.gfx_table); 1490 uint32_t od_sclk; 1491 int ret = 0; 1492 1493 od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value; 1494 od_sclk /= 100; 1495 od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; 1496 1497 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk); 1498 PP_ASSERT_WITH_CODE(!ret, 1499 "[SetSclkOD] failed to set od gfxclk!", 1500 return ret); 1501 1502 /* retrieve updated gfxclk table */ 1503 ret = vega20_setup_gfxclk_dpm_table(hwmgr); 1504 PP_ASSERT_WITH_CODE(!ret, 1505 "[SetSclkOD] failed to refresh gfxclk table!", 1506 return ret); 1507 1508 return 0; 1509 } 1510 1511 static int vega20_get_mclk_od( 1512 struct pp_hwmgr *hwmgr) 1513 { 1514 struct vega20_hwmgr *data = hwmgr->backend; 1515 struct vega20_single_dpm_table *mclk_table = 1516 &(data->dpm_table.mem_table); 1517 struct vega20_single_dpm_table *golden_mclk_table = 1518 &(data->golden_dpm_table.mem_table); 1519 int value = mclk_table->dpm_levels[mclk_table->count - 1].value; 1520 int golden_value = golden_mclk_table->dpm_levels 1521 [golden_mclk_table->count - 1].value; 1522 1523 /* od percentage */ 1524 value -= golden_value; 1525 value = DIV_ROUND_UP(value * 100, golden_value); 1526 1527 return value; 1528 } 1529 1530 static int vega20_set_mclk_od( 1531 struct pp_hwmgr *hwmgr, uint32_t value) 1532 { 1533 struct vega20_hwmgr *data = hwmgr->backend; 1534 struct vega20_single_dpm_table *golden_mclk_table = 1535 &(data->golden_dpm_table.mem_table); 1536 uint32_t od_mclk; 1537 int ret = 0; 1538 1539 od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value; 1540 od_mclk /= 100; 1541 od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; 1542 1543 ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk); 1544 PP_ASSERT_WITH_CODE(!ret, 1545 "[SetMclkOD] failed to set od memclk!", 1546 return ret); 1547 1548 /* retrieve updated memclk table */ 1549 ret = vega20_setup_memclk_dpm_table(hwmgr); 1550 PP_ASSERT_WITH_CODE(!ret, 1551 "[SetMclkOD] failed to refresh memclk table!", 1552 return ret); 1553 1554 return 0; 1555 } 1556 1557 static void vega20_populate_umdpstate_clocks(struct pp_hwmgr *hwmgr) 1558 { 1559 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 1560 struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table); 1561 struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table); 1562 1563 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && 1564 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { 1565 hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 1566 hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 1567 } else { 1568 hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value; 1569 hwmgr->pstate_mclk = mem_table->dpm_levels[0].value; 1570 } 1571 1572 hwmgr->pstate_sclk_peak = gfx_table->dpm_levels[gfx_table->count - 1].value; 1573 hwmgr->pstate_mclk_peak = mem_table->dpm_levels[mem_table->count - 1].value; 1574 } 1575 1576 static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr, 1577 PP_Clock *clock, PPCLK_e clock_select) 1578 { 1579 int ret = 0; 1580 1581 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 1582 PPSMC_MSG_GetDcModeMaxDpmFreq, 1583 (clock_select << 16), 1584 clock)) == 0, 1585 "[GetMaxSustainableClock] Failed to get max DC clock from SMC!", 1586 return ret); 1587 1588 /* if DC limit is zero, return AC limit */ 1589 if (*clock == 0) { 1590 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 1591 PPSMC_MSG_GetMaxDpmFreq, 1592 (clock_select << 16), 1593 clock)) == 0, 1594 "[GetMaxSustainableClock] failed to get max AC clock from SMC!", 1595 return ret); 1596 } 1597 1598 return 0; 1599 } 1600 1601 static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr) 1602 { 1603 struct vega20_hwmgr *data = 1604 (struct vega20_hwmgr *)(hwmgr->backend); 1605 struct vega20_max_sustainable_clocks *max_sustainable_clocks = 1606 &(data->max_sustainable_clocks); 1607 int ret = 0; 1608 1609 max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100; 1610 max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100; 1611 max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100; 1612 max_sustainable_clocks->display_clock = 0xFFFFFFFF; 1613 max_sustainable_clocks->phy_clock = 0xFFFFFFFF; 1614 max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; 1615 1616 if (data->smu_features[GNLD_DPM_UCLK].enabled) 1617 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1618 &(max_sustainable_clocks->uclock), 1619 PPCLK_UCLK)) == 0, 1620 "[InitMaxSustainableClocks] failed to get max UCLK from SMC!", 1621 return ret); 1622 1623 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) 1624 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1625 &(max_sustainable_clocks->soc_clock), 1626 PPCLK_SOCCLK)) == 0, 1627 "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!", 1628 return ret); 1629 1630 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 1631 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1632 &(max_sustainable_clocks->dcef_clock), 1633 PPCLK_DCEFCLK)) == 0, 1634 "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!", 1635 return ret); 1636 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1637 &(max_sustainable_clocks->display_clock), 1638 PPCLK_DISPCLK)) == 0, 1639 "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!", 1640 return ret); 1641 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1642 &(max_sustainable_clocks->phy_clock), 1643 PPCLK_PHYCLK)) == 0, 1644 "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!", 1645 return ret); 1646 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1647 &(max_sustainable_clocks->pixel_clock), 1648 PPCLK_PIXCLK)) == 0, 1649 "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!", 1650 return ret); 1651 } 1652 1653 if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) 1654 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; 1655 1656 return 0; 1657 } 1658 1659 static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) 1660 { 1661 int result; 1662 1663 result = smum_send_msg_to_smc(hwmgr, 1664 PPSMC_MSG_SetMGpuFanBoostLimitRpm, 1665 NULL); 1666 PP_ASSERT_WITH_CODE(!result, 1667 "[EnableMgpuFan] Failed to enable mgpu fan boost!", 1668 return result); 1669 1670 return 0; 1671 } 1672 1673 static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) 1674 { 1675 struct vega20_hwmgr *data = 1676 (struct vega20_hwmgr *)(hwmgr->backend); 1677 1678 data->uvd_power_gated = true; 1679 data->vce_power_gated = true; 1680 } 1681 1682 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) 1683 { 1684 int result = 0; 1685 1686 smum_send_msg_to_smc_with_parameter(hwmgr, 1687 PPSMC_MSG_NumOfDisplays, 0, NULL); 1688 1689 result = vega20_set_allowed_featuresmask(hwmgr); 1690 PP_ASSERT_WITH_CODE(!result, 1691 "[EnableDPMTasks] Failed to set allowed featuresmask!\n", 1692 return result); 1693 1694 result = vega20_init_smc_table(hwmgr); 1695 PP_ASSERT_WITH_CODE(!result, 1696 "[EnableDPMTasks] Failed to initialize SMC table!", 1697 return result); 1698 1699 result = vega20_run_btc(hwmgr); 1700 PP_ASSERT_WITH_CODE(!result, 1701 "[EnableDPMTasks] Failed to run btc!", 1702 return result); 1703 1704 result = vega20_run_btc_afll(hwmgr); 1705 PP_ASSERT_WITH_CODE(!result, 1706 "[EnableDPMTasks] Failed to run btc afll!", 1707 return result); 1708 1709 result = vega20_enable_all_smu_features(hwmgr); 1710 PP_ASSERT_WITH_CODE(!result, 1711 "[EnableDPMTasks] Failed to enable all smu features!", 1712 return result); 1713 1714 result = vega20_override_pcie_parameters(hwmgr); 1715 PP_ASSERT_WITH_CODE(!result, 1716 "[EnableDPMTasks] Failed to override pcie parameters!", 1717 return result); 1718 1719 result = vega20_notify_smc_display_change(hwmgr); 1720 PP_ASSERT_WITH_CODE(!result, 1721 "[EnableDPMTasks] Failed to notify smc display change!", 1722 return result); 1723 1724 result = vega20_send_clock_ratio(hwmgr); 1725 PP_ASSERT_WITH_CODE(!result, 1726 "[EnableDPMTasks] Failed to send clock ratio!", 1727 return result); 1728 1729 /* Initialize UVD/VCE powergating state */ 1730 vega20_init_powergate_state(hwmgr); 1731 1732 result = vega20_setup_default_dpm_tables(hwmgr); 1733 PP_ASSERT_WITH_CODE(!result, 1734 "[EnableDPMTasks] Failed to setup default DPM tables!", 1735 return result); 1736 1737 result = vega20_init_max_sustainable_clocks(hwmgr); 1738 PP_ASSERT_WITH_CODE(!result, 1739 "[EnableDPMTasks] Failed to get maximum sustainable clocks!", 1740 return result); 1741 1742 result = vega20_power_control_set_level(hwmgr); 1743 PP_ASSERT_WITH_CODE(!result, 1744 "[EnableDPMTasks] Failed to power control set level!", 1745 return result); 1746 1747 result = vega20_od8_initialize_default_settings(hwmgr); 1748 PP_ASSERT_WITH_CODE(!result, 1749 "[EnableDPMTasks] Failed to initialize odn settings!", 1750 return result); 1751 1752 vega20_populate_umdpstate_clocks(hwmgr); 1753 1754 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit, 1755 POWER_SOURCE_AC << 16, &hwmgr->default_power_limit); 1756 PP_ASSERT_WITH_CODE(!result, 1757 "[GetPptLimit] get default PPT limit failed!", 1758 return result); 1759 hwmgr->power_limit = 1760 hwmgr->default_power_limit; 1761 1762 return 0; 1763 } 1764 1765 static uint32_t vega20_find_lowest_dpm_level( 1766 struct vega20_single_dpm_table *table) 1767 { 1768 uint32_t i; 1769 1770 for (i = 0; i < table->count; i++) { 1771 if (table->dpm_levels[i].enabled) 1772 break; 1773 } 1774 if (i >= table->count) { 1775 i = 0; 1776 table->dpm_levels[i].enabled = true; 1777 } 1778 1779 return i; 1780 } 1781 1782 static uint32_t vega20_find_highest_dpm_level( 1783 struct vega20_single_dpm_table *table) 1784 { 1785 int i = 0; 1786 1787 PP_ASSERT_WITH_CODE(table != NULL, 1788 "[FindHighestDPMLevel] DPM Table does not exist!", 1789 return 0); 1790 PP_ASSERT_WITH_CODE(table->count > 0, 1791 "[FindHighestDPMLevel] DPM Table has no entry!", 1792 return 0); 1793 PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER, 1794 "[FindHighestDPMLevel] DPM Table has too many entries!", 1795 return MAX_REGULAR_DPM_NUMBER - 1); 1796 1797 for (i = table->count - 1; i >= 0; i--) { 1798 if (table->dpm_levels[i].enabled) 1799 break; 1800 } 1801 if (i < 0) { 1802 i = 0; 1803 table->dpm_levels[i].enabled = true; 1804 } 1805 1806 return i; 1807 } 1808 1809 static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) 1810 { 1811 struct vega20_hwmgr *data = 1812 (struct vega20_hwmgr *)(hwmgr->backend); 1813 uint32_t min_freq; 1814 int ret = 0; 1815 1816 if (data->smu_features[GNLD_DPM_GFXCLK].enabled && 1817 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { 1818 min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level; 1819 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1820 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1821 (PPCLK_GFXCLK << 16) | (min_freq & 0xffff), 1822 NULL)), 1823 "Failed to set soft min gfxclk !", 1824 return ret); 1825 } 1826 1827 if (data->smu_features[GNLD_DPM_UCLK].enabled && 1828 (feature_mask & FEATURE_DPM_UCLK_MASK)) { 1829 min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level; 1830 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1831 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1832 (PPCLK_UCLK << 16) | (min_freq & 0xffff), 1833 NULL)), 1834 "Failed to set soft min memclk !", 1835 return ret); 1836 } 1837 1838 if (data->smu_features[GNLD_DPM_UVD].enabled && 1839 (feature_mask & FEATURE_DPM_UVD_MASK)) { 1840 min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level; 1841 1842 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1843 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1844 (PPCLK_VCLK << 16) | (min_freq & 0xffff), 1845 NULL)), 1846 "Failed to set soft min vclk!", 1847 return ret); 1848 1849 min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level; 1850 1851 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1852 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1853 (PPCLK_DCLK << 16) | (min_freq & 0xffff), 1854 NULL)), 1855 "Failed to set soft min dclk!", 1856 return ret); 1857 } 1858 1859 if (data->smu_features[GNLD_DPM_VCE].enabled && 1860 (feature_mask & FEATURE_DPM_VCE_MASK)) { 1861 min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level; 1862 1863 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1864 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1865 (PPCLK_ECLK << 16) | (min_freq & 0xffff), 1866 NULL)), 1867 "Failed to set soft min eclk!", 1868 return ret); 1869 } 1870 1871 if (data->smu_features[GNLD_DPM_SOCCLK].enabled && 1872 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { 1873 min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level; 1874 1875 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1876 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1877 (PPCLK_SOCCLK << 16) | (min_freq & 0xffff), 1878 NULL)), 1879 "Failed to set soft min socclk!", 1880 return ret); 1881 } 1882 1883 if (data->smu_features[GNLD_DPM_FCLK].enabled && 1884 (feature_mask & FEATURE_DPM_FCLK_MASK)) { 1885 min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level; 1886 1887 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1888 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1889 (PPCLK_FCLK << 16) | (min_freq & 0xffff), 1890 NULL)), 1891 "Failed to set soft min fclk!", 1892 return ret); 1893 } 1894 1895 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled && 1896 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { 1897 min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level; 1898 1899 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1900 hwmgr, PPSMC_MSG_SetHardMinByFreq, 1901 (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff), 1902 NULL)), 1903 "Failed to set hard min dcefclk!", 1904 return ret); 1905 } 1906 1907 return ret; 1908 } 1909 1910 static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) 1911 { 1912 struct vega20_hwmgr *data = 1913 (struct vega20_hwmgr *)(hwmgr->backend); 1914 uint32_t max_freq; 1915 int ret = 0; 1916 1917 if (data->smu_features[GNLD_DPM_GFXCLK].enabled && 1918 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { 1919 max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level; 1920 1921 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1922 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1923 (PPCLK_GFXCLK << 16) | (max_freq & 0xffff), 1924 NULL)), 1925 "Failed to set soft max gfxclk!", 1926 return ret); 1927 } 1928 1929 if (data->smu_features[GNLD_DPM_UCLK].enabled && 1930 (feature_mask & FEATURE_DPM_UCLK_MASK)) { 1931 max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level; 1932 1933 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1934 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1935 (PPCLK_UCLK << 16) | (max_freq & 0xffff), 1936 NULL)), 1937 "Failed to set soft max memclk!", 1938 return ret); 1939 } 1940 1941 if (data->smu_features[GNLD_DPM_UVD].enabled && 1942 (feature_mask & FEATURE_DPM_UVD_MASK)) { 1943 max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level; 1944 1945 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1946 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1947 (PPCLK_VCLK << 16) | (max_freq & 0xffff), 1948 NULL)), 1949 "Failed to set soft max vclk!", 1950 return ret); 1951 1952 max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level; 1953 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1954 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1955 (PPCLK_DCLK << 16) | (max_freq & 0xffff), 1956 NULL)), 1957 "Failed to set soft max dclk!", 1958 return ret); 1959 } 1960 1961 if (data->smu_features[GNLD_DPM_VCE].enabled && 1962 (feature_mask & FEATURE_DPM_VCE_MASK)) { 1963 max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level; 1964 1965 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1966 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1967 (PPCLK_ECLK << 16) | (max_freq & 0xffff), 1968 NULL)), 1969 "Failed to set soft max eclk!", 1970 return ret); 1971 } 1972 1973 if (data->smu_features[GNLD_DPM_SOCCLK].enabled && 1974 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { 1975 max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level; 1976 1977 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1978 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1979 (PPCLK_SOCCLK << 16) | (max_freq & 0xffff), 1980 NULL)), 1981 "Failed to set soft max socclk!", 1982 return ret); 1983 } 1984 1985 if (data->smu_features[GNLD_DPM_FCLK].enabled && 1986 (feature_mask & FEATURE_DPM_FCLK_MASK)) { 1987 max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level; 1988 1989 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1990 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1991 (PPCLK_FCLK << 16) | (max_freq & 0xffff), 1992 NULL)), 1993 "Failed to set soft max fclk!", 1994 return ret); 1995 } 1996 1997 return ret; 1998 } 1999 2000 static int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) 2001 { 2002 struct vega20_hwmgr *data = 2003 (struct vega20_hwmgr *)(hwmgr->backend); 2004 int ret = 0; 2005 2006 if (data->smu_features[GNLD_DPM_VCE].supported) { 2007 if (data->smu_features[GNLD_DPM_VCE].enabled == enable) { 2008 if (enable) 2009 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n"); 2010 else 2011 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n"); 2012 } 2013 2014 ret = vega20_enable_smc_features(hwmgr, 2015 enable, 2016 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap); 2017 PP_ASSERT_WITH_CODE(!ret, 2018 "Attempt to Enable/Disable DPM VCE Failed!", 2019 return ret); 2020 data->smu_features[GNLD_DPM_VCE].enabled = enable; 2021 } 2022 2023 return 0; 2024 } 2025 2026 static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr, 2027 uint32_t *clock, 2028 PPCLK_e clock_select, 2029 bool max) 2030 { 2031 int ret; 2032 *clock = 0; 2033 2034 if (max) { 2035 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2036 PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16), 2037 clock)) == 0, 2038 "[GetClockRanges] Failed to get max clock from SMC!", 2039 return ret); 2040 } else { 2041 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2042 PPSMC_MSG_GetMinDpmFreq, 2043 (clock_select << 16), 2044 clock)) == 0, 2045 "[GetClockRanges] Failed to get min clock from SMC!", 2046 return ret); 2047 } 2048 2049 return 0; 2050 } 2051 2052 static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 2053 { 2054 struct vega20_hwmgr *data = 2055 (struct vega20_hwmgr *)(hwmgr->backend); 2056 uint32_t gfx_clk; 2057 int ret = 0; 2058 2059 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled, 2060 "[GetSclks]: gfxclk dpm not enabled!\n", 2061 return -EPERM); 2062 2063 if (low) { 2064 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false); 2065 PP_ASSERT_WITH_CODE(!ret, 2066 "[GetSclks]: fail to get min PPCLK_GFXCLK\n", 2067 return ret); 2068 } else { 2069 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true); 2070 PP_ASSERT_WITH_CODE(!ret, 2071 "[GetSclks]: fail to get max PPCLK_GFXCLK\n", 2072 return ret); 2073 } 2074 2075 return (gfx_clk * 100); 2076 } 2077 2078 static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 2079 { 2080 struct vega20_hwmgr *data = 2081 (struct vega20_hwmgr *)(hwmgr->backend); 2082 uint32_t mem_clk; 2083 int ret = 0; 2084 2085 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled, 2086 "[MemMclks]: memclk dpm not enabled!\n", 2087 return -EPERM); 2088 2089 if (low) { 2090 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false); 2091 PP_ASSERT_WITH_CODE(!ret, 2092 "[GetMclks]: fail to get min PPCLK_UCLK\n", 2093 return ret); 2094 } else { 2095 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true); 2096 PP_ASSERT_WITH_CODE(!ret, 2097 "[GetMclks]: fail to get max PPCLK_UCLK\n", 2098 return ret); 2099 } 2100 2101 return (mem_clk * 100); 2102 } 2103 2104 static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, 2105 SmuMetrics_t *metrics_table, 2106 bool bypass_cache) 2107 { 2108 struct vega20_hwmgr *data = 2109 (struct vega20_hwmgr *)(hwmgr->backend); 2110 int ret = 0; 2111 2112 if (bypass_cache || 2113 !data->metrics_time || 2114 time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { 2115 ret = smum_smc_table_manager(hwmgr, 2116 (uint8_t *)(&data->metrics_table), 2117 TABLE_SMU_METRICS, 2118 true); 2119 if (ret) { 2120 pr_info("Failed to export SMU metrics table!\n"); 2121 return ret; 2122 } 2123 data->metrics_time = jiffies; 2124 } 2125 2126 if (metrics_table) 2127 memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); 2128 2129 return ret; 2130 } 2131 2132 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, int idx, 2133 uint32_t *query) 2134 { 2135 int ret = 0; 2136 SmuMetrics_t metrics_table; 2137 2138 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2139 if (ret) 2140 return ret; 2141 2142 /* For the 40.46 release, they changed the value name */ 2143 switch (idx) { 2144 case AMDGPU_PP_SENSOR_GPU_AVG_POWER: 2145 if (hwmgr->smu_version == 0x282e00) 2146 *query = metrics_table.AverageSocketPower << 8; 2147 else 2148 ret = -EOPNOTSUPP; 2149 break; 2150 case AMDGPU_PP_SENSOR_GPU_INPUT_POWER: 2151 *query = metrics_table.CurrSocketPower << 8; 2152 break; 2153 } 2154 2155 return ret; 2156 } 2157 2158 static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr, 2159 PPCLK_e clk_id, uint32_t *clk_freq) 2160 { 2161 int ret = 0; 2162 2163 *clk_freq = 0; 2164 2165 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2166 PPSMC_MSG_GetDpmClockFreq, (clk_id << 16), 2167 clk_freq)) == 0, 2168 "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!", 2169 return ret); 2170 2171 *clk_freq = *clk_freq * 100; 2172 2173 return 0; 2174 } 2175 2176 static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr, 2177 int idx, 2178 uint32_t *activity_percent) 2179 { 2180 int ret = 0; 2181 SmuMetrics_t metrics_table; 2182 2183 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2184 if (ret) 2185 return ret; 2186 2187 switch (idx) { 2188 case AMDGPU_PP_SENSOR_GPU_LOAD: 2189 *activity_percent = metrics_table.AverageGfxActivity; 2190 break; 2191 case AMDGPU_PP_SENSOR_MEM_LOAD: 2192 *activity_percent = metrics_table.AverageUclkActivity; 2193 break; 2194 default: 2195 pr_err("Invalid index for retrieving clock activity\n"); 2196 return -EINVAL; 2197 } 2198 2199 return ret; 2200 } 2201 2202 static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, 2203 void *value, int *size) 2204 { 2205 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2206 struct amdgpu_device *adev = hwmgr->adev; 2207 SmuMetrics_t metrics_table; 2208 uint32_t val_vid; 2209 int ret = 0; 2210 2211 switch (idx) { 2212 case AMDGPU_PP_SENSOR_GFX_SCLK: 2213 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2214 if (ret) 2215 return ret; 2216 2217 *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100; 2218 *size = 4; 2219 break; 2220 case AMDGPU_PP_SENSOR_GFX_MCLK: 2221 ret = vega20_get_current_clk_freq(hwmgr, 2222 PPCLK_UCLK, 2223 (uint32_t *)value); 2224 if (!ret) 2225 *size = 4; 2226 break; 2227 case AMDGPU_PP_SENSOR_GPU_LOAD: 2228 case AMDGPU_PP_SENSOR_MEM_LOAD: 2229 ret = vega20_get_current_activity_percent(hwmgr, idx, (uint32_t *)value); 2230 if (!ret) 2231 *size = 4; 2232 break; 2233 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 2234 *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr); 2235 *size = 4; 2236 break; 2237 case AMDGPU_PP_SENSOR_EDGE_TEMP: 2238 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2239 if (ret) 2240 return ret; 2241 2242 *((uint32_t *)value) = metrics_table.TemperatureEdge * 2243 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 2244 *size = 4; 2245 break; 2246 case AMDGPU_PP_SENSOR_MEM_TEMP: 2247 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2248 if (ret) 2249 return ret; 2250 2251 *((uint32_t *)value) = metrics_table.TemperatureHBM * 2252 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 2253 *size = 4; 2254 break; 2255 case AMDGPU_PP_SENSOR_UVD_POWER: 2256 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; 2257 *size = 4; 2258 break; 2259 case AMDGPU_PP_SENSOR_VCE_POWER: 2260 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; 2261 *size = 4; 2262 break; 2263 case AMDGPU_PP_SENSOR_GPU_AVG_POWER: 2264 case AMDGPU_PP_SENSOR_GPU_INPUT_POWER: 2265 *size = 16; 2266 ret = vega20_get_gpu_power(hwmgr, idx, (uint32_t *)value); 2267 break; 2268 case AMDGPU_PP_SENSOR_VDDGFX: 2269 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) & 2270 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >> 2271 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT; 2272 *((uint32_t *)value) = 2273 (uint32_t)convert_to_vddc((uint8_t)val_vid); 2274 break; 2275 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: 2276 ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value); 2277 if (!ret) 2278 *size = 8; 2279 break; 2280 default: 2281 ret = -EOPNOTSUPP; 2282 break; 2283 } 2284 return ret; 2285 } 2286 2287 static int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, 2288 struct pp_display_clock_request *clock_req) 2289 { 2290 int result = 0; 2291 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2292 enum amd_pp_clock_type clk_type = clock_req->clock_type; 2293 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; 2294 PPCLK_e clk_select = 0; 2295 uint32_t clk_request = 0; 2296 2297 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 2298 switch (clk_type) { 2299 case amd_pp_dcef_clock: 2300 clk_select = PPCLK_DCEFCLK; 2301 break; 2302 case amd_pp_disp_clock: 2303 clk_select = PPCLK_DISPCLK; 2304 break; 2305 case amd_pp_pixel_clock: 2306 clk_select = PPCLK_PIXCLK; 2307 break; 2308 case amd_pp_phy_clock: 2309 clk_select = PPCLK_PHYCLK; 2310 break; 2311 default: 2312 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); 2313 result = -EINVAL; 2314 break; 2315 } 2316 2317 if (!result) { 2318 clk_request = (clk_select << 16) | clk_freq; 2319 result = smum_send_msg_to_smc_with_parameter(hwmgr, 2320 PPSMC_MSG_SetHardMinByFreq, 2321 clk_request, 2322 NULL); 2323 } 2324 } 2325 2326 return result; 2327 } 2328 2329 static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 2330 PHM_PerformanceLevelDesignation designation, uint32_t index, 2331 PHM_PerformanceLevel *level) 2332 { 2333 return 0; 2334 } 2335 2336 static int vega20_notify_smc_display_config_after_ps_adjustment( 2337 struct pp_hwmgr *hwmgr) 2338 { 2339 struct vega20_hwmgr *data = 2340 (struct vega20_hwmgr *)(hwmgr->backend); 2341 struct vega20_single_dpm_table *dpm_table = 2342 &data->dpm_table.mem_table; 2343 struct PP_Clocks min_clocks = {0}; 2344 struct pp_display_clock_request clock_req; 2345 int ret = 0; 2346 2347 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; 2348 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; 2349 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 2350 2351 if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { 2352 clock_req.clock_type = amd_pp_dcef_clock; 2353 clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10; 2354 if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { 2355 if (data->smu_features[GNLD_DS_DCEFCLK].supported) 2356 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( 2357 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, 2358 min_clocks.dcefClockInSR / 100, 2359 NULL)) == 0, 2360 "Attempt to set divider for DCEFCLK Failed!", 2361 return ret); 2362 } else { 2363 pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); 2364 } 2365 } 2366 2367 if (data->smu_features[GNLD_DPM_UCLK].enabled) { 2368 dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100; 2369 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2370 PPSMC_MSG_SetHardMinByFreq, 2371 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level, 2372 NULL)), 2373 "[SetHardMinFreq] Set hard min uclk failed!", 2374 return ret); 2375 } 2376 2377 return 0; 2378 } 2379 2380 static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr) 2381 { 2382 struct vega20_hwmgr *data = 2383 (struct vega20_hwmgr *)(hwmgr->backend); 2384 uint32_t soft_level; 2385 int ret = 0; 2386 2387 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 2388 2389 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2390 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2391 data->dpm_table.gfx_table.dpm_levels[soft_level].value; 2392 2393 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); 2394 2395 data->dpm_table.mem_table.dpm_state.soft_min_level = 2396 data->dpm_table.mem_table.dpm_state.soft_max_level = 2397 data->dpm_table.mem_table.dpm_levels[soft_level].value; 2398 2399 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); 2400 2401 data->dpm_table.soc_table.dpm_state.soft_min_level = 2402 data->dpm_table.soc_table.dpm_state.soft_max_level = 2403 data->dpm_table.soc_table.dpm_levels[soft_level].value; 2404 2405 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2406 FEATURE_DPM_UCLK_MASK | 2407 FEATURE_DPM_SOCCLK_MASK); 2408 PP_ASSERT_WITH_CODE(!ret, 2409 "Failed to upload boot level to highest!", 2410 return ret); 2411 2412 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2413 FEATURE_DPM_UCLK_MASK | 2414 FEATURE_DPM_SOCCLK_MASK); 2415 PP_ASSERT_WITH_CODE(!ret, 2416 "Failed to upload dpm max level to highest!", 2417 return ret); 2418 2419 return 0; 2420 } 2421 2422 static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr) 2423 { 2424 struct vega20_hwmgr *data = 2425 (struct vega20_hwmgr *)(hwmgr->backend); 2426 uint32_t soft_level; 2427 int ret = 0; 2428 2429 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 2430 2431 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2432 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2433 data->dpm_table.gfx_table.dpm_levels[soft_level].value; 2434 2435 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 2436 2437 data->dpm_table.mem_table.dpm_state.soft_min_level = 2438 data->dpm_table.mem_table.dpm_state.soft_max_level = 2439 data->dpm_table.mem_table.dpm_levels[soft_level].value; 2440 2441 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); 2442 2443 data->dpm_table.soc_table.dpm_state.soft_min_level = 2444 data->dpm_table.soc_table.dpm_state.soft_max_level = 2445 data->dpm_table.soc_table.dpm_levels[soft_level].value; 2446 2447 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2448 FEATURE_DPM_UCLK_MASK | 2449 FEATURE_DPM_SOCCLK_MASK); 2450 PP_ASSERT_WITH_CODE(!ret, 2451 "Failed to upload boot level to highest!", 2452 return ret); 2453 2454 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2455 FEATURE_DPM_UCLK_MASK | 2456 FEATURE_DPM_SOCCLK_MASK); 2457 PP_ASSERT_WITH_CODE(!ret, 2458 "Failed to upload dpm max level to highest!", 2459 return ret); 2460 2461 return 0; 2462 2463 } 2464 2465 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr) 2466 { 2467 struct vega20_hwmgr *data = 2468 (struct vega20_hwmgr *)(hwmgr->backend); 2469 uint32_t soft_min_level, soft_max_level; 2470 int ret = 0; 2471 2472 /* gfxclk soft min/max settings */ 2473 soft_min_level = 2474 vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 2475 soft_max_level = 2476 vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 2477 2478 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2479 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; 2480 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2481 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; 2482 2483 /* uclk soft min/max settings */ 2484 soft_min_level = 2485 vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 2486 soft_max_level = 2487 vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); 2488 2489 data->dpm_table.mem_table.dpm_state.soft_min_level = 2490 data->dpm_table.mem_table.dpm_levels[soft_min_level].value; 2491 data->dpm_table.mem_table.dpm_state.soft_max_level = 2492 data->dpm_table.mem_table.dpm_levels[soft_max_level].value; 2493 2494 /* socclk soft min/max settings */ 2495 soft_min_level = 2496 vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); 2497 soft_max_level = 2498 vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); 2499 2500 data->dpm_table.soc_table.dpm_state.soft_min_level = 2501 data->dpm_table.soc_table.dpm_levels[soft_min_level].value; 2502 data->dpm_table.soc_table.dpm_state.soft_max_level = 2503 data->dpm_table.soc_table.dpm_levels[soft_max_level].value; 2504 2505 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2506 FEATURE_DPM_UCLK_MASK | 2507 FEATURE_DPM_SOCCLK_MASK); 2508 PP_ASSERT_WITH_CODE(!ret, 2509 "Failed to upload DPM Bootup Levels!", 2510 return ret); 2511 2512 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2513 FEATURE_DPM_UCLK_MASK | 2514 FEATURE_DPM_SOCCLK_MASK); 2515 PP_ASSERT_WITH_CODE(!ret, 2516 "Failed to upload DPM Max Levels!", 2517 return ret); 2518 2519 return 0; 2520 } 2521 2522 static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, 2523 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) 2524 { 2525 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2526 struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table); 2527 struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table); 2528 struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table); 2529 2530 *sclk_mask = 0; 2531 *mclk_mask = 0; 2532 *soc_mask = 0; 2533 2534 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && 2535 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL && 2536 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { 2537 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; 2538 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; 2539 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; 2540 } 2541 2542 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 2543 *sclk_mask = 0; 2544 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 2545 *mclk_mask = 0; 2546 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2547 *sclk_mask = gfx_dpm_table->count - 1; 2548 *mclk_mask = mem_dpm_table->count - 1; 2549 *soc_mask = soc_dpm_table->count - 1; 2550 } 2551 2552 return 0; 2553 } 2554 2555 static int vega20_force_clock_level(struct pp_hwmgr *hwmgr, 2556 enum pp_clock_type type, uint32_t mask) 2557 { 2558 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2559 uint32_t soft_min_level, soft_max_level, hard_min_level; 2560 int ret = 0; 2561 2562 switch (type) { 2563 case PP_SCLK: 2564 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2565 soft_max_level = mask ? (fls(mask) - 1) : 0; 2566 2567 if (soft_max_level >= data->dpm_table.gfx_table.count) { 2568 pr_err("Clock level specified %d is over max allowed %d\n", 2569 soft_max_level, 2570 data->dpm_table.gfx_table.count - 1); 2571 return -EINVAL; 2572 } 2573 2574 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2575 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; 2576 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2577 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; 2578 2579 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); 2580 PP_ASSERT_WITH_CODE(!ret, 2581 "Failed to upload boot level to lowest!", 2582 return ret); 2583 2584 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); 2585 PP_ASSERT_WITH_CODE(!ret, 2586 "Failed to upload dpm max level to highest!", 2587 return ret); 2588 break; 2589 2590 case PP_MCLK: 2591 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2592 soft_max_level = mask ? (fls(mask) - 1) : 0; 2593 2594 if (soft_max_level >= data->dpm_table.mem_table.count) { 2595 pr_err("Clock level specified %d is over max allowed %d\n", 2596 soft_max_level, 2597 data->dpm_table.mem_table.count - 1); 2598 return -EINVAL; 2599 } 2600 2601 data->dpm_table.mem_table.dpm_state.soft_min_level = 2602 data->dpm_table.mem_table.dpm_levels[soft_min_level].value; 2603 data->dpm_table.mem_table.dpm_state.soft_max_level = 2604 data->dpm_table.mem_table.dpm_levels[soft_max_level].value; 2605 2606 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK); 2607 PP_ASSERT_WITH_CODE(!ret, 2608 "Failed to upload boot level to lowest!", 2609 return ret); 2610 2611 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK); 2612 PP_ASSERT_WITH_CODE(!ret, 2613 "Failed to upload dpm max level to highest!", 2614 return ret); 2615 2616 break; 2617 2618 case PP_SOCCLK: 2619 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2620 soft_max_level = mask ? (fls(mask) - 1) : 0; 2621 2622 if (soft_max_level >= data->dpm_table.soc_table.count) { 2623 pr_err("Clock level specified %d is over max allowed %d\n", 2624 soft_max_level, 2625 data->dpm_table.soc_table.count - 1); 2626 return -EINVAL; 2627 } 2628 2629 data->dpm_table.soc_table.dpm_state.soft_min_level = 2630 data->dpm_table.soc_table.dpm_levels[soft_min_level].value; 2631 data->dpm_table.soc_table.dpm_state.soft_max_level = 2632 data->dpm_table.soc_table.dpm_levels[soft_max_level].value; 2633 2634 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); 2635 PP_ASSERT_WITH_CODE(!ret, 2636 "Failed to upload boot level to lowest!", 2637 return ret); 2638 2639 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); 2640 PP_ASSERT_WITH_CODE(!ret, 2641 "Failed to upload dpm max level to highest!", 2642 return ret); 2643 2644 break; 2645 2646 case PP_FCLK: 2647 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2648 soft_max_level = mask ? (fls(mask) - 1) : 0; 2649 2650 if (soft_max_level >= data->dpm_table.fclk_table.count) { 2651 pr_err("Clock level specified %d is over max allowed %d\n", 2652 soft_max_level, 2653 data->dpm_table.fclk_table.count - 1); 2654 return -EINVAL; 2655 } 2656 2657 data->dpm_table.fclk_table.dpm_state.soft_min_level = 2658 data->dpm_table.fclk_table.dpm_levels[soft_min_level].value; 2659 data->dpm_table.fclk_table.dpm_state.soft_max_level = 2660 data->dpm_table.fclk_table.dpm_levels[soft_max_level].value; 2661 2662 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK); 2663 PP_ASSERT_WITH_CODE(!ret, 2664 "Failed to upload boot level to lowest!", 2665 return ret); 2666 2667 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK); 2668 PP_ASSERT_WITH_CODE(!ret, 2669 "Failed to upload dpm max level to highest!", 2670 return ret); 2671 2672 break; 2673 2674 case PP_DCEFCLK: 2675 hard_min_level = mask ? (ffs(mask) - 1) : 0; 2676 2677 if (hard_min_level >= data->dpm_table.dcef_table.count) { 2678 pr_err("Clock level specified %d is over max allowed %d\n", 2679 hard_min_level, 2680 data->dpm_table.dcef_table.count - 1); 2681 return -EINVAL; 2682 } 2683 2684 data->dpm_table.dcef_table.dpm_state.hard_min_level = 2685 data->dpm_table.dcef_table.dpm_levels[hard_min_level].value; 2686 2687 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK); 2688 PP_ASSERT_WITH_CODE(!ret, 2689 "Failed to upload boot level to lowest!", 2690 return ret); 2691 2692 //TODO: Setting DCEFCLK max dpm level is not supported 2693 2694 break; 2695 2696 case PP_PCIE: 2697 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2698 soft_max_level = mask ? (fls(mask) - 1) : 0; 2699 if (soft_min_level >= NUM_LINK_LEVELS || 2700 soft_max_level >= NUM_LINK_LEVELS) 2701 return -EINVAL; 2702 2703 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2704 PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level, 2705 NULL); 2706 PP_ASSERT_WITH_CODE(!ret, 2707 "Failed to set min link dpm level!", 2708 return ret); 2709 2710 break; 2711 2712 default: 2713 break; 2714 } 2715 2716 return 0; 2717 } 2718 2719 static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, 2720 enum amd_dpm_forced_level level) 2721 { 2722 int ret = 0; 2723 uint32_t sclk_mask, mclk_mask, soc_mask; 2724 2725 switch (level) { 2726 case AMD_DPM_FORCED_LEVEL_HIGH: 2727 ret = vega20_force_dpm_highest(hwmgr); 2728 break; 2729 2730 case AMD_DPM_FORCED_LEVEL_LOW: 2731 ret = vega20_force_dpm_lowest(hwmgr); 2732 break; 2733 2734 case AMD_DPM_FORCED_LEVEL_AUTO: 2735 ret = vega20_unforce_dpm_levels(hwmgr); 2736 break; 2737 2738 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 2739 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 2740 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 2741 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 2742 ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); 2743 if (ret) 2744 return ret; 2745 vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask); 2746 vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask); 2747 vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask); 2748 break; 2749 2750 case AMD_DPM_FORCED_LEVEL_MANUAL: 2751 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 2752 default: 2753 break; 2754 } 2755 2756 return ret; 2757 } 2758 2759 static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr) 2760 { 2761 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2762 2763 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) 2764 return AMD_FAN_CTRL_MANUAL; 2765 else 2766 return AMD_FAN_CTRL_AUTO; 2767 } 2768 2769 static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) 2770 { 2771 switch (mode) { 2772 case AMD_FAN_CTRL_NONE: 2773 vega20_fan_ctrl_set_fan_speed_pwm(hwmgr, 255); 2774 break; 2775 case AMD_FAN_CTRL_MANUAL: 2776 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 2777 vega20_fan_ctrl_stop_smc_fan_control(hwmgr); 2778 break; 2779 case AMD_FAN_CTRL_AUTO: 2780 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 2781 vega20_fan_ctrl_start_smc_fan_control(hwmgr); 2782 break; 2783 default: 2784 break; 2785 } 2786 } 2787 2788 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr, 2789 struct amd_pp_simple_clock_info *info) 2790 { 2791 #if 0 2792 struct phm_ppt_v2_information *table_info = 2793 (struct phm_ppt_v2_information *)hwmgr->pptable; 2794 struct phm_clock_and_voltage_limits *max_limits = 2795 &table_info->max_clock_voltage_on_ac; 2796 2797 info->engine_max_clock = max_limits->sclk; 2798 info->memory_max_clock = max_limits->mclk; 2799 #endif 2800 return 0; 2801 } 2802 2803 2804 static int vega20_get_sclks(struct pp_hwmgr *hwmgr, 2805 struct pp_clock_levels_with_latency *clocks) 2806 { 2807 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2808 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); 2809 int i, count; 2810 2811 if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) 2812 return -1; 2813 2814 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2815 clocks->num_levels = count; 2816 2817 for (i = 0; i < count; i++) { 2818 clocks->data[i].clocks_in_khz = 2819 dpm_table->dpm_levels[i].value * 1000; 2820 clocks->data[i].latency_in_us = 0; 2821 } 2822 2823 return 0; 2824 } 2825 2826 static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr, 2827 uint32_t clock) 2828 { 2829 return 25; 2830 } 2831 2832 static int vega20_get_memclocks(struct pp_hwmgr *hwmgr, 2833 struct pp_clock_levels_with_latency *clocks) 2834 { 2835 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2836 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table); 2837 int i, count; 2838 2839 if (!data->smu_features[GNLD_DPM_UCLK].enabled) 2840 return -1; 2841 2842 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2843 clocks->num_levels = data->mclk_latency_table.count = count; 2844 2845 for (i = 0; i < count; i++) { 2846 clocks->data[i].clocks_in_khz = 2847 data->mclk_latency_table.entries[i].frequency = 2848 dpm_table->dpm_levels[i].value * 1000; 2849 clocks->data[i].latency_in_us = 2850 data->mclk_latency_table.entries[i].latency = 2851 vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); 2852 } 2853 2854 return 0; 2855 } 2856 2857 static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr, 2858 struct pp_clock_levels_with_latency *clocks) 2859 { 2860 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2861 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table); 2862 int i, count; 2863 2864 if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled) 2865 return -1; 2866 2867 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2868 clocks->num_levels = count; 2869 2870 for (i = 0; i < count; i++) { 2871 clocks->data[i].clocks_in_khz = 2872 dpm_table->dpm_levels[i].value * 1000; 2873 clocks->data[i].latency_in_us = 0; 2874 } 2875 2876 return 0; 2877 } 2878 2879 static int vega20_get_socclocks(struct pp_hwmgr *hwmgr, 2880 struct pp_clock_levels_with_latency *clocks) 2881 { 2882 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2883 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table); 2884 int i, count; 2885 2886 if (!data->smu_features[GNLD_DPM_SOCCLK].enabled) 2887 return -1; 2888 2889 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2890 clocks->num_levels = count; 2891 2892 for (i = 0; i < count; i++) { 2893 clocks->data[i].clocks_in_khz = 2894 dpm_table->dpm_levels[i].value * 1000; 2895 clocks->data[i].latency_in_us = 0; 2896 } 2897 2898 return 0; 2899 2900 } 2901 2902 static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, 2903 enum amd_pp_clock_type type, 2904 struct pp_clock_levels_with_latency *clocks) 2905 { 2906 int ret; 2907 2908 switch (type) { 2909 case amd_pp_sys_clock: 2910 ret = vega20_get_sclks(hwmgr, clocks); 2911 break; 2912 case amd_pp_mem_clock: 2913 ret = vega20_get_memclocks(hwmgr, clocks); 2914 break; 2915 case amd_pp_dcef_clock: 2916 ret = vega20_get_dcefclocks(hwmgr, clocks); 2917 break; 2918 case amd_pp_soc_clock: 2919 ret = vega20_get_socclocks(hwmgr, clocks); 2920 break; 2921 default: 2922 return -EINVAL; 2923 } 2924 2925 return ret; 2926 } 2927 2928 static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, 2929 enum amd_pp_clock_type type, 2930 struct pp_clock_levels_with_voltage *clocks) 2931 { 2932 clocks->num_levels = 0; 2933 2934 return 0; 2935 } 2936 2937 static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, 2938 void *clock_ranges) 2939 { 2940 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2941 Watermarks_t *table = &(data->smc_state_table.water_marks_table); 2942 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; 2943 2944 if (!data->registry_data.disable_water_mark && 2945 data->smu_features[GNLD_DPM_DCEFCLK].supported && 2946 data->smu_features[GNLD_DPM_SOCCLK].supported) { 2947 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); 2948 data->water_marks_bitmap |= WaterMarksExist; 2949 data->water_marks_bitmap &= ~WaterMarksLoaded; 2950 } 2951 2952 return 0; 2953 } 2954 2955 static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, 2956 enum PP_OD_DPM_TABLE_COMMAND type, 2957 long *input, uint32_t size) 2958 { 2959 struct vega20_hwmgr *data = 2960 (struct vega20_hwmgr *)(hwmgr->backend); 2961 struct vega20_od8_single_setting *od8_settings = 2962 data->od8_settings.od8_settings_array; 2963 OverDriveTable_t *od_table = 2964 &(data->smc_state_table.overdrive_table); 2965 int32_t input_clk, input_vol, i; 2966 uint32_t input_index; 2967 int od8_id; 2968 int ret; 2969 2970 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", 2971 return -EINVAL); 2972 2973 switch (type) { 2974 case PP_OD_EDIT_SCLK_VDDC_TABLE: 2975 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && 2976 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) { 2977 pr_info("Sclk min/max frequency overdrive not supported\n"); 2978 return -EOPNOTSUPP; 2979 } 2980 2981 for (i = 0; i < size; i += 2) { 2982 if (i + 2 > size) { 2983 pr_info("invalid number of input parameters %d\n", 2984 size); 2985 return -EINVAL; 2986 } 2987 2988 input_index = input[i]; 2989 input_clk = input[i + 1]; 2990 2991 if (input_index != 0 && input_index != 1) { 2992 pr_info("Invalid index %d\n", input_index); 2993 pr_info("Support min/max sclk frequency setting only which index by 0/1\n"); 2994 return -EINVAL; 2995 } 2996 2997 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value || 2998 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) { 2999 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 3000 input_clk, 3001 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, 3002 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); 3003 return -EINVAL; 3004 } 3005 3006 if ((input_index == 0 && od_table->GfxclkFmin != input_clk) || 3007 (input_index == 1 && od_table->GfxclkFmax != input_clk)) 3008 data->gfxclk_overdrive = true; 3009 3010 if (input_index == 0) 3011 od_table->GfxclkFmin = input_clk; 3012 else 3013 od_table->GfxclkFmax = input_clk; 3014 } 3015 3016 break; 3017 3018 case PP_OD_EDIT_MCLK_VDDC_TABLE: 3019 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { 3020 pr_info("Mclk max frequency overdrive not supported\n"); 3021 return -EOPNOTSUPP; 3022 } 3023 3024 for (i = 0; i < size; i += 2) { 3025 if (i + 2 > size) { 3026 pr_info("invalid number of input parameters %d\n", 3027 size); 3028 return -EINVAL; 3029 } 3030 3031 input_index = input[i]; 3032 input_clk = input[i + 1]; 3033 3034 if (input_index != 1) { 3035 pr_info("Invalid index %d\n", input_index); 3036 pr_info("Support max Mclk frequency setting only which index by 1\n"); 3037 return -EINVAL; 3038 } 3039 3040 if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || 3041 input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { 3042 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 3043 input_clk, 3044 od8_settings[OD8_SETTING_UCLK_FMAX].min_value, 3045 od8_settings[OD8_SETTING_UCLK_FMAX].max_value); 3046 return -EINVAL; 3047 } 3048 3049 if (input_index == 1 && od_table->UclkFmax != input_clk) 3050 data->memclk_overdrive = true; 3051 3052 od_table->UclkFmax = input_clk; 3053 } 3054 3055 break; 3056 3057 case PP_OD_EDIT_VDDC_CURVE: 3058 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && 3059 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && 3060 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && 3061 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 3062 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 3063 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { 3064 pr_info("Voltage curve calibrate not supported\n"); 3065 return -EOPNOTSUPP; 3066 } 3067 3068 for (i = 0; i < size; i += 3) { 3069 if (i + 3 > size) { 3070 pr_info("invalid number of input parameters %d\n", 3071 size); 3072 return -EINVAL; 3073 } 3074 3075 input_index = input[i]; 3076 input_clk = input[i + 1]; 3077 input_vol = input[i + 2]; 3078 3079 if (input_index > 2) { 3080 pr_info("Setting for point %d is not supported\n", 3081 input_index + 1); 3082 pr_info("Three supported points index by 0, 1, 2\n"); 3083 return -EINVAL; 3084 } 3085 3086 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index; 3087 if (input_clk < od8_settings[od8_id].min_value || 3088 input_clk > od8_settings[od8_id].max_value) { 3089 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 3090 input_clk, 3091 od8_settings[od8_id].min_value, 3092 od8_settings[od8_id].max_value); 3093 return -EINVAL; 3094 } 3095 3096 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index; 3097 if (input_vol < od8_settings[od8_id].min_value || 3098 input_vol > od8_settings[od8_id].max_value) { 3099 pr_info("clock voltage %d is not within allowed range [%d - %d]\n", 3100 input_vol, 3101 od8_settings[od8_id].min_value, 3102 od8_settings[od8_id].max_value); 3103 return -EINVAL; 3104 } 3105 3106 switch (input_index) { 3107 case 0: 3108 od_table->GfxclkFreq1 = input_clk; 3109 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE; 3110 break; 3111 case 1: 3112 od_table->GfxclkFreq2 = input_clk; 3113 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE; 3114 break; 3115 case 2: 3116 od_table->GfxclkFreq3 = input_clk; 3117 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE; 3118 break; 3119 } 3120 } 3121 break; 3122 3123 case PP_OD_RESTORE_DEFAULT_TABLE: 3124 data->gfxclk_overdrive = false; 3125 data->memclk_overdrive = false; 3126 3127 ret = smum_smc_table_manager(hwmgr, 3128 (uint8_t *)od_table, 3129 TABLE_OVERDRIVE, true); 3130 PP_ASSERT_WITH_CODE(!ret, 3131 "Failed to export overdrive table!", 3132 return ret); 3133 break; 3134 3135 case PP_OD_COMMIT_DPM_TABLE: 3136 ret = smum_smc_table_manager(hwmgr, 3137 (uint8_t *)od_table, 3138 TABLE_OVERDRIVE, false); 3139 PP_ASSERT_WITH_CODE(!ret, 3140 "Failed to import overdrive table!", 3141 return ret); 3142 3143 /* retrieve updated gfxclk table */ 3144 if (data->gfxclk_overdrive) { 3145 data->gfxclk_overdrive = false; 3146 3147 ret = vega20_setup_gfxclk_dpm_table(hwmgr); 3148 if (ret) 3149 return ret; 3150 } 3151 3152 /* retrieve updated memclk table */ 3153 if (data->memclk_overdrive) { 3154 data->memclk_overdrive = false; 3155 3156 ret = vega20_setup_memclk_dpm_table(hwmgr); 3157 if (ret) 3158 return ret; 3159 } 3160 break; 3161 3162 default: 3163 return -EINVAL; 3164 } 3165 3166 return 0; 3167 } 3168 3169 static int vega20_set_mp1_state(struct pp_hwmgr *hwmgr, 3170 enum pp_mp1_state mp1_state) 3171 { 3172 uint16_t msg; 3173 int ret; 3174 3175 switch (mp1_state) { 3176 case PP_MP1_STATE_SHUTDOWN: 3177 msg = PPSMC_MSG_PrepareMp1ForShutdown; 3178 break; 3179 case PP_MP1_STATE_UNLOAD: 3180 msg = PPSMC_MSG_PrepareMp1ForUnload; 3181 break; 3182 case PP_MP1_STATE_RESET: 3183 msg = PPSMC_MSG_PrepareMp1ForReset; 3184 break; 3185 case PP_MP1_STATE_NONE: 3186 default: 3187 return 0; 3188 } 3189 3190 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, 3191 "[PrepareMp1] Failed!", 3192 return ret); 3193 3194 return 0; 3195 } 3196 3197 static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) 3198 { 3199 static const char *ppfeature_name[] = { 3200 "DPM_PREFETCHER", 3201 "GFXCLK_DPM", 3202 "UCLK_DPM", 3203 "SOCCLK_DPM", 3204 "UVD_DPM", 3205 "VCE_DPM", 3206 "ULV", 3207 "MP0CLK_DPM", 3208 "LINK_DPM", 3209 "DCEFCLK_DPM", 3210 "GFXCLK_DS", 3211 "SOCCLK_DS", 3212 "LCLK_DS", 3213 "PPT", 3214 "TDC", 3215 "THERMAL", 3216 "GFX_PER_CU_CG", 3217 "RM", 3218 "DCEFCLK_DS", 3219 "ACDC", 3220 "VR0HOT", 3221 "VR1HOT", 3222 "FW_CTF", 3223 "LED_DISPLAY", 3224 "FAN_CONTROL", 3225 "GFX_EDC", 3226 "GFXOFF", 3227 "CG", 3228 "FCLK_DPM", 3229 "FCLK_DS", 3230 "MP1CLK_DS", 3231 "MP0CLK_DS", 3232 "XGMI", 3233 "ECC"}; 3234 static const char *output_title[] = { 3235 "FEATURES", 3236 "BITMASK", 3237 "ENABLEMENT"}; 3238 uint64_t features_enabled; 3239 int i; 3240 int ret = 0; 3241 int size = 0; 3242 3243 phm_get_sysfs_buf(&buf, &size); 3244 3245 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 3246 PP_ASSERT_WITH_CODE(!ret, 3247 "[EnableAllSmuFeatures] Failed to get enabled smc features!", 3248 return ret); 3249 3250 size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled); 3251 size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n", 3252 output_title[0], 3253 output_title[1], 3254 output_title[2]); 3255 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 3256 size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n", 3257 ppfeature_name[i], 3258 1ULL << i, 3259 (features_enabled & (1ULL << i)) ? "Y" : "N"); 3260 } 3261 3262 return size; 3263 } 3264 3265 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) 3266 { 3267 struct vega20_hwmgr *data = 3268 (struct vega20_hwmgr *)(hwmgr->backend); 3269 uint64_t features_enabled, features_to_enable, features_to_disable; 3270 int i, ret = 0; 3271 bool enabled; 3272 3273 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) 3274 return -EINVAL; 3275 3276 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 3277 if (ret) 3278 return ret; 3279 3280 features_to_disable = 3281 features_enabled & ~new_ppfeature_masks; 3282 features_to_enable = 3283 ~features_enabled & new_ppfeature_masks; 3284 3285 pr_debug("features_to_disable 0x%llx\n", features_to_disable); 3286 pr_debug("features_to_enable 0x%llx\n", features_to_enable); 3287 3288 if (features_to_disable) { 3289 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable); 3290 if (ret) 3291 return ret; 3292 } 3293 3294 if (features_to_enable) { 3295 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable); 3296 if (ret) 3297 return ret; 3298 } 3299 3300 /* Update the cached feature enablement state */ 3301 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 3302 if (ret) 3303 return ret; 3304 3305 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 3306 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? 3307 true : false; 3308 data->smu_features[i].enabled = enabled; 3309 } 3310 3311 return 0; 3312 } 3313 3314 static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) 3315 { 3316 struct amdgpu_device *adev = hwmgr->adev; 3317 3318 return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & 3319 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) 3320 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; 3321 } 3322 3323 static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) 3324 { 3325 uint32_t width_level; 3326 3327 width_level = vega20_get_current_pcie_link_width_level(hwmgr); 3328 if (width_level > LINK_WIDTH_MAX) 3329 width_level = 0; 3330 3331 return link_width[width_level]; 3332 } 3333 3334 static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) 3335 { 3336 struct amdgpu_device *adev = hwmgr->adev; 3337 3338 return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & 3339 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) 3340 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; 3341 } 3342 3343 static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) 3344 { 3345 uint32_t speed_level; 3346 3347 speed_level = vega20_get_current_pcie_link_speed_level(hwmgr); 3348 if (speed_level > LINK_SPEED_MAX) 3349 speed_level = 0; 3350 3351 return link_speed[speed_level]; 3352 } 3353 3354 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, 3355 enum pp_clock_type type, char *buf) 3356 { 3357 struct vega20_hwmgr *data = 3358 (struct vega20_hwmgr *)(hwmgr->backend); 3359 struct vega20_od8_single_setting *od8_settings = 3360 data->od8_settings.od8_settings_array; 3361 OverDriveTable_t *od_table = 3362 &(data->smc_state_table.overdrive_table); 3363 PPTable_t *pptable = &(data->smc_state_table.pp_table); 3364 struct pp_clock_levels_with_latency clocks; 3365 struct vega20_single_dpm_table *fclk_dpm_table = 3366 &(data->dpm_table.fclk_table); 3367 int i, now, size = 0; 3368 int ret = 0; 3369 uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width; 3370 3371 switch (type) { 3372 case PP_SCLK: 3373 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now); 3374 PP_ASSERT_WITH_CODE(!ret, 3375 "Attempt to get current gfx clk Failed!", 3376 return ret); 3377 3378 if (vega20_get_sclks(hwmgr, &clocks)) { 3379 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3380 now / 100); 3381 break; 3382 } 3383 3384 for (i = 0; i < clocks.num_levels; i++) 3385 size += sprintf(buf + size, "%d: %uMhz %s\n", 3386 i, clocks.data[i].clocks_in_khz / 1000, 3387 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3388 break; 3389 3390 case PP_MCLK: 3391 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now); 3392 PP_ASSERT_WITH_CODE(!ret, 3393 "Attempt to get current mclk freq Failed!", 3394 return ret); 3395 3396 if (vega20_get_memclocks(hwmgr, &clocks)) { 3397 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3398 now / 100); 3399 break; 3400 } 3401 3402 for (i = 0; i < clocks.num_levels; i++) 3403 size += sprintf(buf + size, "%d: %uMhz %s\n", 3404 i, clocks.data[i].clocks_in_khz / 1000, 3405 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3406 break; 3407 3408 case PP_SOCCLK: 3409 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now); 3410 PP_ASSERT_WITH_CODE(!ret, 3411 "Attempt to get current socclk freq Failed!", 3412 return ret); 3413 3414 if (vega20_get_socclocks(hwmgr, &clocks)) { 3415 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3416 now / 100); 3417 break; 3418 } 3419 3420 for (i = 0; i < clocks.num_levels; i++) 3421 size += sprintf(buf + size, "%d: %uMhz %s\n", 3422 i, clocks.data[i].clocks_in_khz / 1000, 3423 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3424 break; 3425 3426 case PP_FCLK: 3427 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now); 3428 PP_ASSERT_WITH_CODE(!ret, 3429 "Attempt to get current fclk freq Failed!", 3430 return ret); 3431 3432 for (i = 0; i < fclk_dpm_table->count; i++) 3433 size += sprintf(buf + size, "%d: %uMhz %s\n", 3434 i, fclk_dpm_table->dpm_levels[i].value, 3435 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : ""); 3436 break; 3437 3438 case PP_DCEFCLK: 3439 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now); 3440 PP_ASSERT_WITH_CODE(!ret, 3441 "Attempt to get current dcefclk freq Failed!", 3442 return ret); 3443 3444 if (vega20_get_dcefclocks(hwmgr, &clocks)) { 3445 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3446 now / 100); 3447 break; 3448 } 3449 3450 for (i = 0; i < clocks.num_levels; i++) 3451 size += sprintf(buf + size, "%d: %uMhz %s\n", 3452 i, clocks.data[i].clocks_in_khz / 1000, 3453 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3454 break; 3455 3456 case PP_PCIE: 3457 current_gen_speed = 3458 vega20_get_current_pcie_link_speed_level(hwmgr); 3459 current_lane_width = 3460 vega20_get_current_pcie_link_width_level(hwmgr); 3461 for (i = 0; i < NUM_LINK_LEVELS; i++) { 3462 gen_speed = pptable->PcieGenSpeed[i]; 3463 lane_width = pptable->PcieLaneCount[i]; 3464 3465 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, 3466 (gen_speed == 0) ? "2.5GT/s," : 3467 (gen_speed == 1) ? "5.0GT/s," : 3468 (gen_speed == 2) ? "8.0GT/s," : 3469 (gen_speed == 3) ? "16.0GT/s," : "", 3470 (lane_width == 1) ? "x1" : 3471 (lane_width == 2) ? "x2" : 3472 (lane_width == 3) ? "x4" : 3473 (lane_width == 4) ? "x8" : 3474 (lane_width == 5) ? "x12" : 3475 (lane_width == 6) ? "x16" : "", 3476 pptable->LclkFreq[i], 3477 (current_gen_speed == gen_speed) && 3478 (current_lane_width == lane_width) ? 3479 "*" : ""); 3480 } 3481 break; 3482 3483 case OD_SCLK: 3484 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && 3485 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { 3486 size += sprintf(buf + size, "%s:\n", "OD_SCLK"); 3487 size += sprintf(buf + size, "0: %10uMhz\n", 3488 od_table->GfxclkFmin); 3489 size += sprintf(buf + size, "1: %10uMhz\n", 3490 od_table->GfxclkFmax); 3491 } 3492 break; 3493 3494 case OD_MCLK: 3495 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { 3496 size += sprintf(buf + size, "%s:\n", "OD_MCLK"); 3497 size += sprintf(buf + size, "1: %10uMhz\n", 3498 od_table->UclkFmax); 3499 } 3500 3501 break; 3502 3503 case OD_VDDC_CURVE: 3504 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && 3505 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && 3506 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && 3507 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 3508 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 3509 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { 3510 size += sprintf(buf + size, "%s:\n", "OD_VDDC_CURVE"); 3511 size += sprintf(buf + size, "0: %10uMhz %10dmV\n", 3512 od_table->GfxclkFreq1, 3513 od_table->GfxclkVolt1 / VOLTAGE_SCALE); 3514 size += sprintf(buf + size, "1: %10uMhz %10dmV\n", 3515 od_table->GfxclkFreq2, 3516 od_table->GfxclkVolt2 / VOLTAGE_SCALE); 3517 size += sprintf(buf + size, "2: %10uMhz %10dmV\n", 3518 od_table->GfxclkFreq3, 3519 od_table->GfxclkVolt3 / VOLTAGE_SCALE); 3520 } 3521 3522 break; 3523 3524 case OD_RANGE: 3525 size += sprintf(buf + size, "%s:\n", "OD_RANGE"); 3526 3527 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && 3528 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { 3529 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 3530 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, 3531 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); 3532 } 3533 3534 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { 3535 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", 3536 od8_settings[OD8_SETTING_UCLK_FMAX].min_value, 3537 od8_settings[OD8_SETTING_UCLK_FMAX].max_value); 3538 } 3539 3540 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && 3541 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && 3542 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && 3543 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 3544 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 3545 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { 3546 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", 3547 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, 3548 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value); 3549 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", 3550 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, 3551 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); 3552 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", 3553 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, 3554 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value); 3555 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", 3556 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, 3557 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); 3558 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", 3559 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, 3560 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value); 3561 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", 3562 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, 3563 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); 3564 } 3565 3566 break; 3567 default: 3568 break; 3569 } 3570 return size; 3571 } 3572 3573 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr, 3574 struct vega20_single_dpm_table *dpm_table) 3575 { 3576 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3577 int ret = 0; 3578 3579 if (data->smu_features[GNLD_DPM_UCLK].enabled) { 3580 PP_ASSERT_WITH_CODE(dpm_table->count > 0, 3581 "[SetUclkToHightestDpmLevel] Dpm table has no entry!", 3582 return -EINVAL); 3583 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS, 3584 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!", 3585 return -EINVAL); 3586 3587 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3588 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, 3589 PPSMC_MSG_SetHardMinByFreq, 3590 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level, 3591 NULL)), 3592 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!", 3593 return ret); 3594 } 3595 3596 return ret; 3597 } 3598 3599 static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr) 3600 { 3601 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3602 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table); 3603 int ret = 0; 3604 3605 if (data->smu_features[GNLD_DPM_FCLK].enabled) { 3606 PP_ASSERT_WITH_CODE(dpm_table->count > 0, 3607 "[SetFclkToHightestDpmLevel] Dpm table has no entry!", 3608 return -EINVAL); 3609 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS, 3610 "[SetFclkToHightestDpmLevel] Dpm table has too many entries!", 3611 return -EINVAL); 3612 3613 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3614 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, 3615 PPSMC_MSG_SetSoftMinByFreq, 3616 (PPCLK_FCLK << 16) | dpm_table->dpm_state.soft_min_level, 3617 NULL)), 3618 "[SetFclkToHightestDpmLevel] Set soft min fclk failed!", 3619 return ret); 3620 } 3621 3622 return ret; 3623 } 3624 3625 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 3626 { 3627 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3628 int ret = 0; 3629 3630 smum_send_msg_to_smc_with_parameter(hwmgr, 3631 PPSMC_MSG_NumOfDisplays, 0, NULL); 3632 3633 ret = vega20_set_uclk_to_highest_dpm_level(hwmgr, 3634 &data->dpm_table.mem_table); 3635 if (ret) 3636 return ret; 3637 3638 return vega20_set_fclk_to_highest_dpm_level(hwmgr); 3639 } 3640 3641 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 3642 { 3643 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3644 int result = 0; 3645 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); 3646 3647 if ((data->water_marks_bitmap & WaterMarksExist) && 3648 !(data->water_marks_bitmap & WaterMarksLoaded)) { 3649 result = smum_smc_table_manager(hwmgr, 3650 (uint8_t *)wm_table, TABLE_WATERMARKS, false); 3651 PP_ASSERT_WITH_CODE(!result, 3652 "Failed to update WMTABLE!", 3653 return result); 3654 data->water_marks_bitmap |= WaterMarksLoaded; 3655 } 3656 3657 if ((data->water_marks_bitmap & WaterMarksExist) && 3658 data->smu_features[GNLD_DPM_DCEFCLK].supported && 3659 data->smu_features[GNLD_DPM_SOCCLK].supported) { 3660 result = smum_send_msg_to_smc_with_parameter(hwmgr, 3661 PPSMC_MSG_NumOfDisplays, 3662 hwmgr->display_config->num_display, 3663 NULL); 3664 } 3665 3666 return result; 3667 } 3668 3669 static int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) 3670 { 3671 struct vega20_hwmgr *data = 3672 (struct vega20_hwmgr *)(hwmgr->backend); 3673 int ret = 0; 3674 3675 if (data->smu_features[GNLD_DPM_UVD].supported) { 3676 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) { 3677 if (enable) 3678 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n"); 3679 else 3680 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n"); 3681 } 3682 3683 ret = vega20_enable_smc_features(hwmgr, 3684 enable, 3685 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap); 3686 PP_ASSERT_WITH_CODE(!ret, 3687 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!", 3688 return ret); 3689 data->smu_features[GNLD_DPM_UVD].enabled = enable; 3690 } 3691 3692 return 0; 3693 } 3694 3695 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) 3696 { 3697 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3698 3699 if (data->vce_power_gated == bgate) 3700 return ; 3701 3702 data->vce_power_gated = bgate; 3703 if (bgate) { 3704 vega20_enable_disable_vce_dpm(hwmgr, !bgate); 3705 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 3706 AMD_IP_BLOCK_TYPE_VCE, 3707 AMD_PG_STATE_GATE); 3708 } else { 3709 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 3710 AMD_IP_BLOCK_TYPE_VCE, 3711 AMD_PG_STATE_UNGATE); 3712 vega20_enable_disable_vce_dpm(hwmgr, !bgate); 3713 } 3714 3715 } 3716 3717 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) 3718 { 3719 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3720 3721 if (data->uvd_power_gated == bgate) 3722 return ; 3723 3724 data->uvd_power_gated = bgate; 3725 vega20_enable_disable_uvd_dpm(hwmgr, !bgate); 3726 } 3727 3728 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr) 3729 { 3730 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3731 struct vega20_single_dpm_table *dpm_table; 3732 bool vblank_too_short = false; 3733 bool disable_mclk_switching; 3734 bool disable_fclk_switching; 3735 uint32_t i, latency; 3736 3737 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && 3738 !hwmgr->display_config->multi_monitor_in_sync) || 3739 vblank_too_short; 3740 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; 3741 3742 /* gfxclk */ 3743 dpm_table = &(data->dpm_table.gfx_table); 3744 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3745 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3746 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3747 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3748 3749 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3750 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { 3751 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 3752 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 3753 } 3754 3755 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 3756 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3757 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; 3758 } 3759 3760 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3761 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3762 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3763 } 3764 } 3765 3766 /* memclk */ 3767 dpm_table = &(data->dpm_table.mem_table); 3768 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3769 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3770 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3771 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3772 3773 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3774 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { 3775 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 3776 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 3777 } 3778 3779 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 3780 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3781 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; 3782 } 3783 3784 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3785 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3786 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3787 } 3788 } 3789 3790 /* honour DAL's UCLK Hardmin */ 3791 if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100)) 3792 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100; 3793 3794 /* Hardmin is dependent on displayconfig */ 3795 if (disable_mclk_switching) { 3796 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3797 for (i = 0; i < data->mclk_latency_table.count - 1; i++) { 3798 if (data->mclk_latency_table.entries[i].latency <= latency) { 3799 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) { 3800 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; 3801 break; 3802 } 3803 } 3804 } 3805 } 3806 3807 if (hwmgr->display_config->nb_pstate_switch_disable) 3808 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3809 3810 if ((disable_mclk_switching && 3811 (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) || 3812 hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value) 3813 disable_fclk_switching = true; 3814 else 3815 disable_fclk_switching = false; 3816 3817 /* fclk */ 3818 dpm_table = &(data->dpm_table.fclk_table); 3819 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3820 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3821 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3822 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3823 if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching) 3824 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3825 3826 /* vclk */ 3827 dpm_table = &(data->dpm_table.vclk_table); 3828 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3829 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3830 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3831 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3832 3833 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3834 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { 3835 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3836 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3837 } 3838 3839 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3840 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3841 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3842 } 3843 } 3844 3845 /* dclk */ 3846 dpm_table = &(data->dpm_table.dclk_table); 3847 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3848 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3849 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3850 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3851 3852 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3853 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { 3854 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3855 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3856 } 3857 3858 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3859 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3860 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3861 } 3862 } 3863 3864 /* socclk */ 3865 dpm_table = &(data->dpm_table.soc_table); 3866 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3867 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3868 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3869 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3870 3871 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3872 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { 3873 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; 3874 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; 3875 } 3876 3877 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3878 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3879 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3880 } 3881 } 3882 3883 /* eclk */ 3884 dpm_table = &(data->dpm_table.eclk_table); 3885 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3886 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3887 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3888 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3889 3890 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3891 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { 3892 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; 3893 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; 3894 } 3895 3896 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3897 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3898 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3899 } 3900 } 3901 3902 return 0; 3903 } 3904 3905 static bool 3906 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) 3907 { 3908 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3909 bool is_update_required = false; 3910 3911 if (data->display_timing.num_existing_displays != 3912 hwmgr->display_config->num_display) 3913 is_update_required = true; 3914 3915 if (data->registry_data.gfx_clk_deep_sleep_support && 3916 (data->display_timing.min_clock_in_sr != 3917 hwmgr->display_config->min_core_set_clock_in_sr)) 3918 is_update_required = true; 3919 3920 return is_update_required; 3921 } 3922 3923 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 3924 { 3925 int ret = 0; 3926 3927 ret = vega20_disable_all_smu_features(hwmgr); 3928 PP_ASSERT_WITH_CODE(!ret, 3929 "[DisableDpmTasks] Failed to disable all smu features!", 3930 return ret); 3931 3932 return 0; 3933 } 3934 3935 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr) 3936 { 3937 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3938 int result; 3939 3940 result = vega20_disable_dpm_tasks(hwmgr); 3941 PP_ASSERT_WITH_CODE((0 == result), 3942 "[PowerOffAsic] Failed to disable DPM!", 3943 ); 3944 data->water_marks_bitmap &= ~(WaterMarksLoaded); 3945 3946 return result; 3947 } 3948 3949 static int conv_power_profile_to_pplib_workload(int power_profile) 3950 { 3951 int pplib_workload = 0; 3952 3953 switch (power_profile) { 3954 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: 3955 pplib_workload = WORKLOAD_DEFAULT_BIT; 3956 break; 3957 case PP_SMC_POWER_PROFILE_FULLSCREEN3D: 3958 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; 3959 break; 3960 case PP_SMC_POWER_PROFILE_POWERSAVING: 3961 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; 3962 break; 3963 case PP_SMC_POWER_PROFILE_VIDEO: 3964 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; 3965 break; 3966 case PP_SMC_POWER_PROFILE_VR: 3967 pplib_workload = WORKLOAD_PPLIB_VR_BIT; 3968 break; 3969 case PP_SMC_POWER_PROFILE_COMPUTE: 3970 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; 3971 break; 3972 case PP_SMC_POWER_PROFILE_CUSTOM: 3973 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT; 3974 break; 3975 } 3976 3977 return pplib_workload; 3978 } 3979 3980 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) 3981 { 3982 DpmActivityMonitorCoeffInt_t activity_monitor; 3983 uint32_t i, size = 0; 3984 uint16_t workload_type = 0; 3985 static const char *title[] = { 3986 "PROFILE_INDEX(NAME)", 3987 "CLOCK_TYPE(NAME)", 3988 "FPS", 3989 "UseRlcBusy", 3990 "MinActiveFreqType", 3991 "MinActiveFreq", 3992 "BoosterFreqType", 3993 "BoosterFreq", 3994 "PD_Data_limit_c", 3995 "PD_Data_error_coeff", 3996 "PD_Data_error_rate_coeff"}; 3997 int result = 0; 3998 3999 if (!buf) 4000 return -EINVAL; 4001 4002 phm_get_sysfs_buf(&buf, &size); 4003 4004 size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n", 4005 title[0], title[1], title[2], title[3], title[4], title[5], 4006 title[6], title[7], title[8], title[9], title[10]); 4007 4008 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { 4009 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 4010 workload_type = conv_power_profile_to_pplib_workload(i); 4011 result = vega20_get_activity_monitor_coeff(hwmgr, 4012 (uint8_t *)(&activity_monitor), workload_type); 4013 PP_ASSERT_WITH_CODE(!result, 4014 "[GetPowerProfile] Failed to get activity monitor!", 4015 return result); 4016 4017 size += sysfs_emit_at(buf, size, "%2d %14s%s:\n", 4018 i, amdgpu_pp_profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " "); 4019 4020 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4021 " ", 4022 0, 4023 "GFXCLK", 4024 activity_monitor.Gfx_FPS, 4025 activity_monitor.Gfx_UseRlcBusy, 4026 activity_monitor.Gfx_MinActiveFreqType, 4027 activity_monitor.Gfx_MinActiveFreq, 4028 activity_monitor.Gfx_BoosterFreqType, 4029 activity_monitor.Gfx_BoosterFreq, 4030 activity_monitor.Gfx_PD_Data_limit_c, 4031 activity_monitor.Gfx_PD_Data_error_coeff, 4032 activity_monitor.Gfx_PD_Data_error_rate_coeff); 4033 4034 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4035 " ", 4036 1, 4037 "SOCCLK", 4038 activity_monitor.Soc_FPS, 4039 activity_monitor.Soc_UseRlcBusy, 4040 activity_monitor.Soc_MinActiveFreqType, 4041 activity_monitor.Soc_MinActiveFreq, 4042 activity_monitor.Soc_BoosterFreqType, 4043 activity_monitor.Soc_BoosterFreq, 4044 activity_monitor.Soc_PD_Data_limit_c, 4045 activity_monitor.Soc_PD_Data_error_coeff, 4046 activity_monitor.Soc_PD_Data_error_rate_coeff); 4047 4048 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4049 " ", 4050 2, 4051 "UCLK", 4052 activity_monitor.Mem_FPS, 4053 activity_monitor.Mem_UseRlcBusy, 4054 activity_monitor.Mem_MinActiveFreqType, 4055 activity_monitor.Mem_MinActiveFreq, 4056 activity_monitor.Mem_BoosterFreqType, 4057 activity_monitor.Mem_BoosterFreq, 4058 activity_monitor.Mem_PD_Data_limit_c, 4059 activity_monitor.Mem_PD_Data_error_coeff, 4060 activity_monitor.Mem_PD_Data_error_rate_coeff); 4061 4062 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4063 " ", 4064 3, 4065 "FCLK", 4066 activity_monitor.Fclk_FPS, 4067 activity_monitor.Fclk_UseRlcBusy, 4068 activity_monitor.Fclk_MinActiveFreqType, 4069 activity_monitor.Fclk_MinActiveFreq, 4070 activity_monitor.Fclk_BoosterFreqType, 4071 activity_monitor.Fclk_BoosterFreq, 4072 activity_monitor.Fclk_PD_Data_limit_c, 4073 activity_monitor.Fclk_PD_Data_error_coeff, 4074 activity_monitor.Fclk_PD_Data_error_rate_coeff); 4075 } 4076 4077 return size; 4078 } 4079 4080 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) 4081 { 4082 DpmActivityMonitorCoeffInt_t activity_monitor; 4083 int workload_type, result = 0; 4084 uint32_t power_profile_mode = input[size]; 4085 4086 if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { 4087 pr_err("Invalid power profile mode %d\n", power_profile_mode); 4088 return -EINVAL; 4089 } 4090 4091 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { 4092 struct vega20_hwmgr *data = 4093 (struct vega20_hwmgr *)(hwmgr->backend); 4094 if (size == 0 && !data->is_custom_profile_set) 4095 return -EINVAL; 4096 if (size < 10 && size != 0) 4097 return -EINVAL; 4098 4099 result = vega20_get_activity_monitor_coeff(hwmgr, 4100 (uint8_t *)(&activity_monitor), 4101 WORKLOAD_PPLIB_CUSTOM_BIT); 4102 PP_ASSERT_WITH_CODE(!result, 4103 "[SetPowerProfile] Failed to get activity monitor!", 4104 return result); 4105 4106 /* If size==0, then we want to apply the already-configured 4107 * CUSTOM profile again. Just apply it, since we checked its 4108 * validity above 4109 */ 4110 if (size == 0) 4111 goto out; 4112 4113 switch (input[0]) { 4114 case 0: /* Gfxclk */ 4115 activity_monitor.Gfx_FPS = input[1]; 4116 activity_monitor.Gfx_UseRlcBusy = input[2]; 4117 activity_monitor.Gfx_MinActiveFreqType = input[3]; 4118 activity_monitor.Gfx_MinActiveFreq = input[4]; 4119 activity_monitor.Gfx_BoosterFreqType = input[5]; 4120 activity_monitor.Gfx_BoosterFreq = input[6]; 4121 activity_monitor.Gfx_PD_Data_limit_c = input[7]; 4122 activity_monitor.Gfx_PD_Data_error_coeff = input[8]; 4123 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; 4124 break; 4125 case 1: /* Socclk */ 4126 activity_monitor.Soc_FPS = input[1]; 4127 activity_monitor.Soc_UseRlcBusy = input[2]; 4128 activity_monitor.Soc_MinActiveFreqType = input[3]; 4129 activity_monitor.Soc_MinActiveFreq = input[4]; 4130 activity_monitor.Soc_BoosterFreqType = input[5]; 4131 activity_monitor.Soc_BoosterFreq = input[6]; 4132 activity_monitor.Soc_PD_Data_limit_c = input[7]; 4133 activity_monitor.Soc_PD_Data_error_coeff = input[8]; 4134 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; 4135 break; 4136 case 2: /* Uclk */ 4137 activity_monitor.Mem_FPS = input[1]; 4138 activity_monitor.Mem_UseRlcBusy = input[2]; 4139 activity_monitor.Mem_MinActiveFreqType = input[3]; 4140 activity_monitor.Mem_MinActiveFreq = input[4]; 4141 activity_monitor.Mem_BoosterFreqType = input[5]; 4142 activity_monitor.Mem_BoosterFreq = input[6]; 4143 activity_monitor.Mem_PD_Data_limit_c = input[7]; 4144 activity_monitor.Mem_PD_Data_error_coeff = input[8]; 4145 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; 4146 break; 4147 case 3: /* Fclk */ 4148 activity_monitor.Fclk_FPS = input[1]; 4149 activity_monitor.Fclk_UseRlcBusy = input[2]; 4150 activity_monitor.Fclk_MinActiveFreqType = input[3]; 4151 activity_monitor.Fclk_MinActiveFreq = input[4]; 4152 activity_monitor.Fclk_BoosterFreqType = input[5]; 4153 activity_monitor.Fclk_BoosterFreq = input[6]; 4154 activity_monitor.Fclk_PD_Data_limit_c = input[7]; 4155 activity_monitor.Fclk_PD_Data_error_coeff = input[8]; 4156 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; 4157 break; 4158 } 4159 4160 result = vega20_set_activity_monitor_coeff(hwmgr, 4161 (uint8_t *)(&activity_monitor), 4162 WORKLOAD_PPLIB_CUSTOM_BIT); 4163 data->is_custom_profile_set = true; 4164 PP_ASSERT_WITH_CODE(!result, 4165 "[SetPowerProfile] Failed to set activity monitor!", 4166 return result); 4167 } 4168 4169 out: 4170 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 4171 workload_type = 4172 conv_power_profile_to_pplib_workload(power_profile_mode); 4173 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, 4174 1 << workload_type, 4175 NULL); 4176 4177 hwmgr->power_profile_mode = power_profile_mode; 4178 4179 return 0; 4180 } 4181 4182 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, 4183 uint32_t virtual_addr_low, 4184 uint32_t virtual_addr_hi, 4185 uint32_t mc_addr_low, 4186 uint32_t mc_addr_hi, 4187 uint32_t size) 4188 { 4189 smum_send_msg_to_smc_with_parameter(hwmgr, 4190 PPSMC_MSG_SetSystemVirtualDramAddrHigh, 4191 virtual_addr_hi, 4192 NULL); 4193 smum_send_msg_to_smc_with_parameter(hwmgr, 4194 PPSMC_MSG_SetSystemVirtualDramAddrLow, 4195 virtual_addr_low, 4196 NULL); 4197 smum_send_msg_to_smc_with_parameter(hwmgr, 4198 PPSMC_MSG_DramLogSetDramAddrHigh, 4199 mc_addr_hi, 4200 NULL); 4201 4202 smum_send_msg_to_smc_with_parameter(hwmgr, 4203 PPSMC_MSG_DramLogSetDramAddrLow, 4204 mc_addr_low, 4205 NULL); 4206 4207 smum_send_msg_to_smc_with_parameter(hwmgr, 4208 PPSMC_MSG_DramLogSetDramSize, 4209 size, 4210 NULL); 4211 return 0; 4212 } 4213 4214 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, 4215 struct PP_TemperatureRange *thermal_data) 4216 { 4217 struct phm_ppt_v3_information *pptable_information = 4218 (struct phm_ppt_v3_information *)hwmgr->pptable; 4219 struct vega20_hwmgr *data = 4220 (struct vega20_hwmgr *)(hwmgr->backend); 4221 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 4222 4223 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); 4224 4225 thermal_data->max = pp_table->TedgeLimit * 4226 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4227 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * 4228 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4229 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * 4230 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4231 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * 4232 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4233 thermal_data->mem_crit_max = pp_table->ThbmLimit * 4234 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4235 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* 4236 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4237 thermal_data->sw_ctf_threshold = pptable_information->us_software_shutdown_temp * 4238 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4239 4240 return 0; 4241 } 4242 4243 static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire) 4244 { 4245 int res; 4246 4247 /* I2C bus access can happen very early, when SMU not loaded yet */ 4248 if (!vega20_is_smc_ram_running(hwmgr)) 4249 return 0; 4250 4251 res = smum_send_msg_to_smc_with_parameter(hwmgr, 4252 (acquire ? 4253 PPSMC_MSG_RequestI2CBus : 4254 PPSMC_MSG_ReleaseI2CBus), 4255 0, 4256 NULL); 4257 4258 PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res); 4259 return res; 4260 } 4261 4262 static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr, 4263 enum pp_df_cstate state) 4264 { 4265 int ret; 4266 4267 /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */ 4268 if (hwmgr->smu_version < 0x283200) { 4269 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n"); 4270 return -EINVAL; 4271 } 4272 4273 ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state, 4274 NULL); 4275 if (ret) 4276 pr_err("SetDfCstate failed!\n"); 4277 4278 return ret; 4279 } 4280 4281 static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr, 4282 uint32_t pstate) 4283 { 4284 int ret; 4285 4286 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 4287 PPSMC_MSG_SetXgmiMode, 4288 pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, 4289 NULL); 4290 if (ret) 4291 pr_err("SetXgmiPstate failed!\n"); 4292 4293 return ret; 4294 } 4295 4296 static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) 4297 { 4298 memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); 4299 4300 gpu_metrics->common_header.structure_size = 4301 sizeof(struct gpu_metrics_v1_0); 4302 gpu_metrics->common_header.format_revision = 1; 4303 gpu_metrics->common_header.content_revision = 0; 4304 4305 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 4306 } 4307 4308 static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, 4309 void **table) 4310 { 4311 struct vega20_hwmgr *data = 4312 (struct vega20_hwmgr *)(hwmgr->backend); 4313 struct gpu_metrics_v1_0 *gpu_metrics = 4314 &data->gpu_metrics_table; 4315 SmuMetrics_t metrics; 4316 uint32_t fan_speed_rpm; 4317 int ret; 4318 4319 ret = vega20_get_metrics_table(hwmgr, &metrics, true); 4320 if (ret) 4321 return ret; 4322 4323 vega20_init_gpu_metrics_v1_0(gpu_metrics); 4324 4325 gpu_metrics->temperature_edge = metrics.TemperatureEdge; 4326 gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; 4327 gpu_metrics->temperature_mem = metrics.TemperatureHBM; 4328 gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; 4329 gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; 4330 gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; 4331 4332 gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; 4333 gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; 4334 4335 gpu_metrics->average_socket_power = metrics.AverageSocketPower; 4336 4337 gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; 4338 gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; 4339 gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; 4340 4341 gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; 4342 gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; 4343 gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; 4344 gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; 4345 gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; 4346 4347 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 4348 4349 vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); 4350 gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; 4351 4352 gpu_metrics->pcie_link_width = 4353 vega20_get_current_pcie_link_width(hwmgr); 4354 gpu_metrics->pcie_link_speed = 4355 vega20_get_current_pcie_link_speed(hwmgr); 4356 4357 *table = (void *)gpu_metrics; 4358 4359 return sizeof(struct gpu_metrics_v1_0); 4360 } 4361 4362 static const struct pp_hwmgr_func vega20_hwmgr_funcs = { 4363 /* init/fini related */ 4364 .backend_init = vega20_hwmgr_backend_init, 4365 .backend_fini = vega20_hwmgr_backend_fini, 4366 .asic_setup = vega20_setup_asic_task, 4367 .power_off_asic = vega20_power_off_asic, 4368 .dynamic_state_management_enable = vega20_enable_dpm_tasks, 4369 .dynamic_state_management_disable = vega20_disable_dpm_tasks, 4370 /* power state related */ 4371 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, 4372 .pre_display_config_changed = vega20_pre_display_configuration_changed_task, 4373 .display_config_changed = vega20_display_configuration_changed_task, 4374 .check_smc_update_required_for_display_configuration = 4375 vega20_check_smc_update_required_for_display_configuration, 4376 .notify_smc_display_config_after_ps_adjustment = 4377 vega20_notify_smc_display_config_after_ps_adjustment, 4378 /* export to DAL */ 4379 .get_sclk = vega20_dpm_get_sclk, 4380 .get_mclk = vega20_dpm_get_mclk, 4381 .get_dal_power_level = vega20_get_dal_power_level, 4382 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency, 4383 .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage, 4384 .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges, 4385 .display_clock_voltage_request = vega20_display_clock_voltage_request, 4386 .get_performance_level = vega20_get_performance_level, 4387 /* UMD pstate, profile related */ 4388 .force_dpm_level = vega20_dpm_force_dpm_level, 4389 .get_power_profile_mode = vega20_get_power_profile_mode, 4390 .set_power_profile_mode = vega20_set_power_profile_mode, 4391 /* od related */ 4392 .set_power_limit = vega20_set_power_limit, 4393 .get_sclk_od = vega20_get_sclk_od, 4394 .set_sclk_od = vega20_set_sclk_od, 4395 .get_mclk_od = vega20_get_mclk_od, 4396 .set_mclk_od = vega20_set_mclk_od, 4397 .odn_edit_dpm_table = vega20_odn_edit_dpm_table, 4398 /* for sysfs to retrive/set gfxclk/memclk */ 4399 .force_clock_level = vega20_force_clock_level, 4400 .print_clock_levels = vega20_print_clock_levels, 4401 .read_sensor = vega20_read_sensor, 4402 .get_ppfeature_status = vega20_get_ppfeature_status, 4403 .set_ppfeature_status = vega20_set_ppfeature_status, 4404 /* powergate related */ 4405 .powergate_uvd = vega20_power_gate_uvd, 4406 .powergate_vce = vega20_power_gate_vce, 4407 /* thermal related */ 4408 .start_thermal_controller = vega20_start_thermal_controller, 4409 .stop_thermal_controller = vega20_thermal_stop_thermal_controller, 4410 .get_thermal_temperature_range = vega20_get_thermal_temperature_range, 4411 .register_irq_handlers = smu9_register_irq_handlers, 4412 .disable_smc_firmware_ctf = vega20_thermal_disable_alert, 4413 /* fan control related */ 4414 .get_fan_speed_pwm = vega20_fan_ctrl_get_fan_speed_pwm, 4415 .set_fan_speed_pwm = vega20_fan_ctrl_set_fan_speed_pwm, 4416 .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info, 4417 .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm, 4418 .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm, 4419 .get_fan_control_mode = vega20_get_fan_control_mode, 4420 .set_fan_control_mode = vega20_set_fan_control_mode, 4421 /* smu memory related */ 4422 .notify_cac_buffer_info = vega20_notify_cac_buffer_info, 4423 .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost, 4424 /* BACO related */ 4425 .get_asic_baco_capability = vega20_baco_get_capability, 4426 .get_asic_baco_state = vega20_baco_get_state, 4427 .set_asic_baco_state = vega20_baco_set_state, 4428 .set_mp1_state = vega20_set_mp1_state, 4429 .smu_i2c_bus_access = vega20_smu_i2c_bus_access, 4430 .set_df_cstate = vega20_set_df_cstate, 4431 .set_xgmi_pstate = vega20_set_xgmi_pstate, 4432 .get_gpu_metrics = vega20_get_gpu_metrics, 4433 }; 4434 4435 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr) 4436 { 4437 hwmgr->hwmgr_func = &vega20_hwmgr_funcs; 4438 hwmgr->pptable_func = &vega20_pptable_funcs; 4439 4440 return 0; 4441 } 4442