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