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 * 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 int vega20_populate_umdpstate_clocks( 1559 struct pp_hwmgr *hwmgr) 1560 { 1561 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 1562 struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table); 1563 struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table); 1564 1565 hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value; 1566 hwmgr->pstate_mclk = mem_table->dpm_levels[0].value; 1567 1568 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && 1569 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { 1570 hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 1571 hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 1572 } 1573 1574 hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100; 1575 hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100; 1576 1577 return 0; 1578 } 1579 1580 static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr, 1581 PP_Clock *clock, PPCLK_e clock_select) 1582 { 1583 int ret = 0; 1584 1585 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 1586 PPSMC_MSG_GetDcModeMaxDpmFreq, 1587 (clock_select << 16), 1588 clock)) == 0, 1589 "[GetMaxSustainableClock] Failed to get max DC clock from SMC!", 1590 return ret); 1591 1592 /* if DC limit is zero, return AC limit */ 1593 if (*clock == 0) { 1594 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 1595 PPSMC_MSG_GetMaxDpmFreq, 1596 (clock_select << 16), 1597 clock)) == 0, 1598 "[GetMaxSustainableClock] failed to get max AC clock from SMC!", 1599 return ret); 1600 } 1601 1602 return 0; 1603 } 1604 1605 static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr) 1606 { 1607 struct vega20_hwmgr *data = 1608 (struct vega20_hwmgr *)(hwmgr->backend); 1609 struct vega20_max_sustainable_clocks *max_sustainable_clocks = 1610 &(data->max_sustainable_clocks); 1611 int ret = 0; 1612 1613 max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100; 1614 max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100; 1615 max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100; 1616 max_sustainable_clocks->display_clock = 0xFFFFFFFF; 1617 max_sustainable_clocks->phy_clock = 0xFFFFFFFF; 1618 max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; 1619 1620 if (data->smu_features[GNLD_DPM_UCLK].enabled) 1621 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1622 &(max_sustainable_clocks->uclock), 1623 PPCLK_UCLK)) == 0, 1624 "[InitMaxSustainableClocks] failed to get max UCLK from SMC!", 1625 return ret); 1626 1627 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) 1628 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1629 &(max_sustainable_clocks->soc_clock), 1630 PPCLK_SOCCLK)) == 0, 1631 "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!", 1632 return ret); 1633 1634 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 1635 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1636 &(max_sustainable_clocks->dcef_clock), 1637 PPCLK_DCEFCLK)) == 0, 1638 "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!", 1639 return ret); 1640 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1641 &(max_sustainable_clocks->display_clock), 1642 PPCLK_DISPCLK)) == 0, 1643 "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!", 1644 return ret); 1645 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1646 &(max_sustainable_clocks->phy_clock), 1647 PPCLK_PHYCLK)) == 0, 1648 "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!", 1649 return ret); 1650 PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, 1651 &(max_sustainable_clocks->pixel_clock), 1652 PPCLK_PIXCLK)) == 0, 1653 "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!", 1654 return ret); 1655 } 1656 1657 if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) 1658 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; 1659 1660 return 0; 1661 } 1662 1663 static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) 1664 { 1665 int result; 1666 1667 result = smum_send_msg_to_smc(hwmgr, 1668 PPSMC_MSG_SetMGpuFanBoostLimitRpm, 1669 NULL); 1670 PP_ASSERT_WITH_CODE(!result, 1671 "[EnableMgpuFan] Failed to enable mgpu fan boost!", 1672 return result); 1673 1674 return 0; 1675 } 1676 1677 static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) 1678 { 1679 struct vega20_hwmgr *data = 1680 (struct vega20_hwmgr *)(hwmgr->backend); 1681 1682 data->uvd_power_gated = true; 1683 data->vce_power_gated = true; 1684 } 1685 1686 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) 1687 { 1688 int result = 0; 1689 1690 smum_send_msg_to_smc_with_parameter(hwmgr, 1691 PPSMC_MSG_NumOfDisplays, 0, NULL); 1692 1693 result = vega20_set_allowed_featuresmask(hwmgr); 1694 PP_ASSERT_WITH_CODE(!result, 1695 "[EnableDPMTasks] Failed to set allowed featuresmask!\n", 1696 return result); 1697 1698 result = vega20_init_smc_table(hwmgr); 1699 PP_ASSERT_WITH_CODE(!result, 1700 "[EnableDPMTasks] Failed to initialize SMC table!", 1701 return result); 1702 1703 result = vega20_run_btc(hwmgr); 1704 PP_ASSERT_WITH_CODE(!result, 1705 "[EnableDPMTasks] Failed to run btc!", 1706 return result); 1707 1708 result = vega20_run_btc_afll(hwmgr); 1709 PP_ASSERT_WITH_CODE(!result, 1710 "[EnableDPMTasks] Failed to run btc afll!", 1711 return result); 1712 1713 result = vega20_enable_all_smu_features(hwmgr); 1714 PP_ASSERT_WITH_CODE(!result, 1715 "[EnableDPMTasks] Failed to enable all smu features!", 1716 return result); 1717 1718 result = vega20_override_pcie_parameters(hwmgr); 1719 PP_ASSERT_WITH_CODE(!result, 1720 "[EnableDPMTasks] Failed to override pcie parameters!", 1721 return result); 1722 1723 result = vega20_notify_smc_display_change(hwmgr); 1724 PP_ASSERT_WITH_CODE(!result, 1725 "[EnableDPMTasks] Failed to notify smc display change!", 1726 return result); 1727 1728 result = vega20_send_clock_ratio(hwmgr); 1729 PP_ASSERT_WITH_CODE(!result, 1730 "[EnableDPMTasks] Failed to send clock ratio!", 1731 return result); 1732 1733 /* Initialize UVD/VCE powergating state */ 1734 vega20_init_powergate_state(hwmgr); 1735 1736 result = vega20_setup_default_dpm_tables(hwmgr); 1737 PP_ASSERT_WITH_CODE(!result, 1738 "[EnableDPMTasks] Failed to setup default DPM tables!", 1739 return result); 1740 1741 result = vega20_init_max_sustainable_clocks(hwmgr); 1742 PP_ASSERT_WITH_CODE(!result, 1743 "[EnableDPMTasks] Failed to get maximum sustainable clocks!", 1744 return result); 1745 1746 result = vega20_power_control_set_level(hwmgr); 1747 PP_ASSERT_WITH_CODE(!result, 1748 "[EnableDPMTasks] Failed to power control set level!", 1749 return result); 1750 1751 result = vega20_od8_initialize_default_settings(hwmgr); 1752 PP_ASSERT_WITH_CODE(!result, 1753 "[EnableDPMTasks] Failed to initialize odn settings!", 1754 return result); 1755 1756 result = vega20_populate_umdpstate_clocks(hwmgr); 1757 PP_ASSERT_WITH_CODE(!result, 1758 "[EnableDPMTasks] Failed to populate umdpstate clocks!", 1759 return result); 1760 1761 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit, 1762 POWER_SOURCE_AC << 16, &hwmgr->default_power_limit); 1763 PP_ASSERT_WITH_CODE(!result, 1764 "[GetPptLimit] get default PPT limit failed!", 1765 return result); 1766 hwmgr->power_limit = 1767 hwmgr->default_power_limit; 1768 1769 return 0; 1770 } 1771 1772 static uint32_t vega20_find_lowest_dpm_level( 1773 struct vega20_single_dpm_table *table) 1774 { 1775 uint32_t i; 1776 1777 for (i = 0; i < table->count; i++) { 1778 if (table->dpm_levels[i].enabled) 1779 break; 1780 } 1781 if (i >= table->count) { 1782 i = 0; 1783 table->dpm_levels[i].enabled = true; 1784 } 1785 1786 return i; 1787 } 1788 1789 static uint32_t vega20_find_highest_dpm_level( 1790 struct vega20_single_dpm_table *table) 1791 { 1792 int i = 0; 1793 1794 PP_ASSERT_WITH_CODE(table != NULL, 1795 "[FindHighestDPMLevel] DPM Table does not exist!", 1796 return 0); 1797 PP_ASSERT_WITH_CODE(table->count > 0, 1798 "[FindHighestDPMLevel] DPM Table has no entry!", 1799 return 0); 1800 PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER, 1801 "[FindHighestDPMLevel] DPM Table has too many entries!", 1802 return MAX_REGULAR_DPM_NUMBER - 1); 1803 1804 for (i = table->count - 1; i >= 0; i--) { 1805 if (table->dpm_levels[i].enabled) 1806 break; 1807 } 1808 if (i < 0) { 1809 i = 0; 1810 table->dpm_levels[i].enabled = true; 1811 } 1812 1813 return i; 1814 } 1815 1816 static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) 1817 { 1818 struct vega20_hwmgr *data = 1819 (struct vega20_hwmgr *)(hwmgr->backend); 1820 uint32_t min_freq; 1821 int ret = 0; 1822 1823 if (data->smu_features[GNLD_DPM_GFXCLK].enabled && 1824 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { 1825 min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level; 1826 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1827 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1828 (PPCLK_GFXCLK << 16) | (min_freq & 0xffff), 1829 NULL)), 1830 "Failed to set soft min gfxclk !", 1831 return ret); 1832 } 1833 1834 if (data->smu_features[GNLD_DPM_UCLK].enabled && 1835 (feature_mask & FEATURE_DPM_UCLK_MASK)) { 1836 min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level; 1837 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1838 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1839 (PPCLK_UCLK << 16) | (min_freq & 0xffff), 1840 NULL)), 1841 "Failed to set soft min memclk !", 1842 return ret); 1843 } 1844 1845 if (data->smu_features[GNLD_DPM_UVD].enabled && 1846 (feature_mask & FEATURE_DPM_UVD_MASK)) { 1847 min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level; 1848 1849 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1850 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1851 (PPCLK_VCLK << 16) | (min_freq & 0xffff), 1852 NULL)), 1853 "Failed to set soft min vclk!", 1854 return ret); 1855 1856 min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level; 1857 1858 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1859 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1860 (PPCLK_DCLK << 16) | (min_freq & 0xffff), 1861 NULL)), 1862 "Failed to set soft min dclk!", 1863 return ret); 1864 } 1865 1866 if (data->smu_features[GNLD_DPM_VCE].enabled && 1867 (feature_mask & FEATURE_DPM_VCE_MASK)) { 1868 min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level; 1869 1870 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1871 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1872 (PPCLK_ECLK << 16) | (min_freq & 0xffff), 1873 NULL)), 1874 "Failed to set soft min eclk!", 1875 return ret); 1876 } 1877 1878 if (data->smu_features[GNLD_DPM_SOCCLK].enabled && 1879 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { 1880 min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level; 1881 1882 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1883 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1884 (PPCLK_SOCCLK << 16) | (min_freq & 0xffff), 1885 NULL)), 1886 "Failed to set soft min socclk!", 1887 return ret); 1888 } 1889 1890 if (data->smu_features[GNLD_DPM_FCLK].enabled && 1891 (feature_mask & FEATURE_DPM_FCLK_MASK)) { 1892 min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level; 1893 1894 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1895 hwmgr, PPSMC_MSG_SetSoftMinByFreq, 1896 (PPCLK_FCLK << 16) | (min_freq & 0xffff), 1897 NULL)), 1898 "Failed to set soft min fclk!", 1899 return ret); 1900 } 1901 1902 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled && 1903 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { 1904 min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level; 1905 1906 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1907 hwmgr, PPSMC_MSG_SetHardMinByFreq, 1908 (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff), 1909 NULL)), 1910 "Failed to set hard min dcefclk!", 1911 return ret); 1912 } 1913 1914 return ret; 1915 } 1916 1917 static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) 1918 { 1919 struct vega20_hwmgr *data = 1920 (struct vega20_hwmgr *)(hwmgr->backend); 1921 uint32_t max_freq; 1922 int ret = 0; 1923 1924 if (data->smu_features[GNLD_DPM_GFXCLK].enabled && 1925 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { 1926 max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level; 1927 1928 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1929 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1930 (PPCLK_GFXCLK << 16) | (max_freq & 0xffff), 1931 NULL)), 1932 "Failed to set soft max gfxclk!", 1933 return ret); 1934 } 1935 1936 if (data->smu_features[GNLD_DPM_UCLK].enabled && 1937 (feature_mask & FEATURE_DPM_UCLK_MASK)) { 1938 max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level; 1939 1940 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1941 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1942 (PPCLK_UCLK << 16) | (max_freq & 0xffff), 1943 NULL)), 1944 "Failed to set soft max memclk!", 1945 return ret); 1946 } 1947 1948 if (data->smu_features[GNLD_DPM_UVD].enabled && 1949 (feature_mask & FEATURE_DPM_UVD_MASK)) { 1950 max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level; 1951 1952 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1953 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1954 (PPCLK_VCLK << 16) | (max_freq & 0xffff), 1955 NULL)), 1956 "Failed to set soft max vclk!", 1957 return ret); 1958 1959 max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level; 1960 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1961 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1962 (PPCLK_DCLK << 16) | (max_freq & 0xffff), 1963 NULL)), 1964 "Failed to set soft max dclk!", 1965 return ret); 1966 } 1967 1968 if (data->smu_features[GNLD_DPM_VCE].enabled && 1969 (feature_mask & FEATURE_DPM_VCE_MASK)) { 1970 max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level; 1971 1972 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1973 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1974 (PPCLK_ECLK << 16) | (max_freq & 0xffff), 1975 NULL)), 1976 "Failed to set soft max eclk!", 1977 return ret); 1978 } 1979 1980 if (data->smu_features[GNLD_DPM_SOCCLK].enabled && 1981 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { 1982 max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level; 1983 1984 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1985 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1986 (PPCLK_SOCCLK << 16) | (max_freq & 0xffff), 1987 NULL)), 1988 "Failed to set soft max socclk!", 1989 return ret); 1990 } 1991 1992 if (data->smu_features[GNLD_DPM_FCLK].enabled && 1993 (feature_mask & FEATURE_DPM_FCLK_MASK)) { 1994 max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level; 1995 1996 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( 1997 hwmgr, PPSMC_MSG_SetSoftMaxByFreq, 1998 (PPCLK_FCLK << 16) | (max_freq & 0xffff), 1999 NULL)), 2000 "Failed to set soft max fclk!", 2001 return ret); 2002 } 2003 2004 return ret; 2005 } 2006 2007 static int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) 2008 { 2009 struct vega20_hwmgr *data = 2010 (struct vega20_hwmgr *)(hwmgr->backend); 2011 int ret = 0; 2012 2013 if (data->smu_features[GNLD_DPM_VCE].supported) { 2014 if (data->smu_features[GNLD_DPM_VCE].enabled == enable) { 2015 if (enable) 2016 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n"); 2017 else 2018 PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n"); 2019 } 2020 2021 ret = vega20_enable_smc_features(hwmgr, 2022 enable, 2023 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap); 2024 PP_ASSERT_WITH_CODE(!ret, 2025 "Attempt to Enable/Disable DPM VCE Failed!", 2026 return ret); 2027 data->smu_features[GNLD_DPM_VCE].enabled = enable; 2028 } 2029 2030 return 0; 2031 } 2032 2033 static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr, 2034 uint32_t *clock, 2035 PPCLK_e clock_select, 2036 bool max) 2037 { 2038 int ret; 2039 *clock = 0; 2040 2041 if (max) { 2042 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2043 PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16), 2044 clock)) == 0, 2045 "[GetClockRanges] Failed to get max clock from SMC!", 2046 return ret); 2047 } else { 2048 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2049 PPSMC_MSG_GetMinDpmFreq, 2050 (clock_select << 16), 2051 clock)) == 0, 2052 "[GetClockRanges] Failed to get min clock from SMC!", 2053 return ret); 2054 } 2055 2056 return 0; 2057 } 2058 2059 static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 2060 { 2061 struct vega20_hwmgr *data = 2062 (struct vega20_hwmgr *)(hwmgr->backend); 2063 uint32_t gfx_clk; 2064 int ret = 0; 2065 2066 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled, 2067 "[GetSclks]: gfxclk dpm not enabled!\n", 2068 return -EPERM); 2069 2070 if (low) { 2071 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false); 2072 PP_ASSERT_WITH_CODE(!ret, 2073 "[GetSclks]: fail to get min PPCLK_GFXCLK\n", 2074 return ret); 2075 } else { 2076 ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true); 2077 PP_ASSERT_WITH_CODE(!ret, 2078 "[GetSclks]: fail to get max PPCLK_GFXCLK\n", 2079 return ret); 2080 } 2081 2082 return (gfx_clk * 100); 2083 } 2084 2085 static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 2086 { 2087 struct vega20_hwmgr *data = 2088 (struct vega20_hwmgr *)(hwmgr->backend); 2089 uint32_t mem_clk; 2090 int ret = 0; 2091 2092 PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled, 2093 "[MemMclks]: memclk dpm not enabled!\n", 2094 return -EPERM); 2095 2096 if (low) { 2097 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false); 2098 PP_ASSERT_WITH_CODE(!ret, 2099 "[GetMclks]: fail to get min PPCLK_UCLK\n", 2100 return ret); 2101 } else { 2102 ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true); 2103 PP_ASSERT_WITH_CODE(!ret, 2104 "[GetMclks]: fail to get max PPCLK_UCLK\n", 2105 return ret); 2106 } 2107 2108 return (mem_clk * 100); 2109 } 2110 2111 static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, 2112 SmuMetrics_t *metrics_table, 2113 bool bypass_cache) 2114 { 2115 struct vega20_hwmgr *data = 2116 (struct vega20_hwmgr *)(hwmgr->backend); 2117 int ret = 0; 2118 2119 if (bypass_cache || 2120 !data->metrics_time || 2121 time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { 2122 ret = smum_smc_table_manager(hwmgr, 2123 (uint8_t *)(&data->metrics_table), 2124 TABLE_SMU_METRICS, 2125 true); 2126 if (ret) { 2127 pr_info("Failed to export SMU metrics table!\n"); 2128 return ret; 2129 } 2130 data->metrics_time = jiffies; 2131 } 2132 2133 if (metrics_table) 2134 memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); 2135 2136 return ret; 2137 } 2138 2139 static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, 2140 uint32_t *query) 2141 { 2142 int ret = 0; 2143 SmuMetrics_t metrics_table; 2144 2145 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2146 if (ret) 2147 return ret; 2148 2149 /* For the 40.46 release, they changed the value name */ 2150 if (hwmgr->smu_version == 0x282e00) 2151 *query = metrics_table.AverageSocketPower << 8; 2152 else 2153 *query = metrics_table.CurrSocketPower << 8; 2154 2155 return ret; 2156 } 2157 2158 static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr, 2159 PPCLK_e clk_id, uint32_t *clk_freq) 2160 { 2161 int ret = 0; 2162 2163 *clk_freq = 0; 2164 2165 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2166 PPSMC_MSG_GetDpmClockFreq, (clk_id << 16), 2167 clk_freq)) == 0, 2168 "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!", 2169 return ret); 2170 2171 *clk_freq = *clk_freq * 100; 2172 2173 return 0; 2174 } 2175 2176 static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr, 2177 int idx, 2178 uint32_t *activity_percent) 2179 { 2180 int ret = 0; 2181 SmuMetrics_t metrics_table; 2182 2183 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2184 if (ret) 2185 return ret; 2186 2187 switch (idx) { 2188 case AMDGPU_PP_SENSOR_GPU_LOAD: 2189 *activity_percent = metrics_table.AverageGfxActivity; 2190 break; 2191 case AMDGPU_PP_SENSOR_MEM_LOAD: 2192 *activity_percent = metrics_table.AverageUclkActivity; 2193 break; 2194 default: 2195 pr_err("Invalid index for retrieving clock activity\n"); 2196 return -EINVAL; 2197 } 2198 2199 return ret; 2200 } 2201 2202 static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, 2203 void *value, int *size) 2204 { 2205 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2206 struct amdgpu_device *adev = hwmgr->adev; 2207 SmuMetrics_t metrics_table; 2208 uint32_t val_vid; 2209 int ret = 0; 2210 2211 switch (idx) { 2212 case AMDGPU_PP_SENSOR_GFX_SCLK: 2213 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2214 if (ret) 2215 return ret; 2216 2217 *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100; 2218 *size = 4; 2219 break; 2220 case AMDGPU_PP_SENSOR_GFX_MCLK: 2221 ret = vega20_get_current_clk_freq(hwmgr, 2222 PPCLK_UCLK, 2223 (uint32_t *)value); 2224 if (!ret) 2225 *size = 4; 2226 break; 2227 case AMDGPU_PP_SENSOR_GPU_LOAD: 2228 case AMDGPU_PP_SENSOR_MEM_LOAD: 2229 ret = vega20_get_current_activity_percent(hwmgr, idx, (uint32_t *)value); 2230 if (!ret) 2231 *size = 4; 2232 break; 2233 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 2234 *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr); 2235 *size = 4; 2236 break; 2237 case AMDGPU_PP_SENSOR_EDGE_TEMP: 2238 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2239 if (ret) 2240 return ret; 2241 2242 *((uint32_t *)value) = metrics_table.TemperatureEdge * 2243 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 2244 *size = 4; 2245 break; 2246 case AMDGPU_PP_SENSOR_MEM_TEMP: 2247 ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); 2248 if (ret) 2249 return ret; 2250 2251 *((uint32_t *)value) = metrics_table.TemperatureHBM * 2252 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 2253 *size = 4; 2254 break; 2255 case AMDGPU_PP_SENSOR_UVD_POWER: 2256 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; 2257 *size = 4; 2258 break; 2259 case AMDGPU_PP_SENSOR_VCE_POWER: 2260 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; 2261 *size = 4; 2262 break; 2263 case AMDGPU_PP_SENSOR_GPU_POWER: 2264 *size = 16; 2265 ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value); 2266 break; 2267 case AMDGPU_PP_SENSOR_VDDGFX: 2268 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) & 2269 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >> 2270 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT; 2271 *((uint32_t *)value) = 2272 (uint32_t)convert_to_vddc((uint8_t)val_vid); 2273 break; 2274 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: 2275 ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value); 2276 if (!ret) 2277 *size = 8; 2278 break; 2279 default: 2280 ret = -EOPNOTSUPP; 2281 break; 2282 } 2283 return ret; 2284 } 2285 2286 static int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, 2287 struct pp_display_clock_request *clock_req) 2288 { 2289 int result = 0; 2290 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2291 enum amd_pp_clock_type clk_type = clock_req->clock_type; 2292 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; 2293 PPCLK_e clk_select = 0; 2294 uint32_t clk_request = 0; 2295 2296 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { 2297 switch (clk_type) { 2298 case amd_pp_dcef_clock: 2299 clk_select = PPCLK_DCEFCLK; 2300 break; 2301 case amd_pp_disp_clock: 2302 clk_select = PPCLK_DISPCLK; 2303 break; 2304 case amd_pp_pixel_clock: 2305 clk_select = PPCLK_PIXCLK; 2306 break; 2307 case amd_pp_phy_clock: 2308 clk_select = PPCLK_PHYCLK; 2309 break; 2310 default: 2311 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); 2312 result = -EINVAL; 2313 break; 2314 } 2315 2316 if (!result) { 2317 clk_request = (clk_select << 16) | clk_freq; 2318 result = smum_send_msg_to_smc_with_parameter(hwmgr, 2319 PPSMC_MSG_SetHardMinByFreq, 2320 clk_request, 2321 NULL); 2322 } 2323 } 2324 2325 return result; 2326 } 2327 2328 static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 2329 PHM_PerformanceLevelDesignation designation, uint32_t index, 2330 PHM_PerformanceLevel *level) 2331 { 2332 return 0; 2333 } 2334 2335 static int vega20_notify_smc_display_config_after_ps_adjustment( 2336 struct pp_hwmgr *hwmgr) 2337 { 2338 struct vega20_hwmgr *data = 2339 (struct vega20_hwmgr *)(hwmgr->backend); 2340 struct vega20_single_dpm_table *dpm_table = 2341 &data->dpm_table.mem_table; 2342 struct PP_Clocks min_clocks = {0}; 2343 struct pp_display_clock_request clock_req; 2344 int ret = 0; 2345 2346 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; 2347 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; 2348 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 2349 2350 if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { 2351 clock_req.clock_type = amd_pp_dcef_clock; 2352 clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10; 2353 if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { 2354 if (data->smu_features[GNLD_DS_DCEFCLK].supported) 2355 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( 2356 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, 2357 min_clocks.dcefClockInSR / 100, 2358 NULL)) == 0, 2359 "Attempt to set divider for DCEFCLK Failed!", 2360 return ret); 2361 } else { 2362 pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); 2363 } 2364 } 2365 2366 if (data->smu_features[GNLD_DPM_UCLK].enabled) { 2367 dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100; 2368 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2369 PPSMC_MSG_SetHardMinByFreq, 2370 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, 2371 NULL)), 2372 "[SetHardMinFreq] Set hard min uclk failed!", 2373 return ret); 2374 } 2375 2376 return 0; 2377 } 2378 2379 static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr) 2380 { 2381 struct vega20_hwmgr *data = 2382 (struct vega20_hwmgr *)(hwmgr->backend); 2383 uint32_t soft_level; 2384 int ret = 0; 2385 2386 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 2387 2388 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2389 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2390 data->dpm_table.gfx_table.dpm_levels[soft_level].value; 2391 2392 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); 2393 2394 data->dpm_table.mem_table.dpm_state.soft_min_level = 2395 data->dpm_table.mem_table.dpm_state.soft_max_level = 2396 data->dpm_table.mem_table.dpm_levels[soft_level].value; 2397 2398 soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); 2399 2400 data->dpm_table.soc_table.dpm_state.soft_min_level = 2401 data->dpm_table.soc_table.dpm_state.soft_max_level = 2402 data->dpm_table.soc_table.dpm_levels[soft_level].value; 2403 2404 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2405 FEATURE_DPM_UCLK_MASK | 2406 FEATURE_DPM_SOCCLK_MASK); 2407 PP_ASSERT_WITH_CODE(!ret, 2408 "Failed to upload boot level to highest!", 2409 return ret); 2410 2411 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2412 FEATURE_DPM_UCLK_MASK | 2413 FEATURE_DPM_SOCCLK_MASK); 2414 PP_ASSERT_WITH_CODE(!ret, 2415 "Failed to upload dpm max level to highest!", 2416 return ret); 2417 2418 return 0; 2419 } 2420 2421 static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr) 2422 { 2423 struct vega20_hwmgr *data = 2424 (struct vega20_hwmgr *)(hwmgr->backend); 2425 uint32_t soft_level; 2426 int ret = 0; 2427 2428 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 2429 2430 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2431 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2432 data->dpm_table.gfx_table.dpm_levels[soft_level].value; 2433 2434 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 2435 2436 data->dpm_table.mem_table.dpm_state.soft_min_level = 2437 data->dpm_table.mem_table.dpm_state.soft_max_level = 2438 data->dpm_table.mem_table.dpm_levels[soft_level].value; 2439 2440 soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); 2441 2442 data->dpm_table.soc_table.dpm_state.soft_min_level = 2443 data->dpm_table.soc_table.dpm_state.soft_max_level = 2444 data->dpm_table.soc_table.dpm_levels[soft_level].value; 2445 2446 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2447 FEATURE_DPM_UCLK_MASK | 2448 FEATURE_DPM_SOCCLK_MASK); 2449 PP_ASSERT_WITH_CODE(!ret, 2450 "Failed to upload boot level to highest!", 2451 return ret); 2452 2453 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2454 FEATURE_DPM_UCLK_MASK | 2455 FEATURE_DPM_SOCCLK_MASK); 2456 PP_ASSERT_WITH_CODE(!ret, 2457 "Failed to upload dpm max level to highest!", 2458 return ret); 2459 2460 return 0; 2461 2462 } 2463 2464 static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr) 2465 { 2466 struct vega20_hwmgr *data = 2467 (struct vega20_hwmgr *)(hwmgr->backend); 2468 uint32_t soft_min_level, soft_max_level; 2469 int ret = 0; 2470 2471 /* gfxclk soft min/max settings */ 2472 soft_min_level = 2473 vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 2474 soft_max_level = 2475 vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 2476 2477 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2478 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; 2479 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2480 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; 2481 2482 /* uclk soft min/max settings */ 2483 soft_min_level = 2484 vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 2485 soft_max_level = 2486 vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); 2487 2488 data->dpm_table.mem_table.dpm_state.soft_min_level = 2489 data->dpm_table.mem_table.dpm_levels[soft_min_level].value; 2490 data->dpm_table.mem_table.dpm_state.soft_max_level = 2491 data->dpm_table.mem_table.dpm_levels[soft_max_level].value; 2492 2493 /* socclk soft min/max settings */ 2494 soft_min_level = 2495 vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); 2496 soft_max_level = 2497 vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); 2498 2499 data->dpm_table.soc_table.dpm_state.soft_min_level = 2500 data->dpm_table.soc_table.dpm_levels[soft_min_level].value; 2501 data->dpm_table.soc_table.dpm_state.soft_max_level = 2502 data->dpm_table.soc_table.dpm_levels[soft_max_level].value; 2503 2504 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2505 FEATURE_DPM_UCLK_MASK | 2506 FEATURE_DPM_SOCCLK_MASK); 2507 PP_ASSERT_WITH_CODE(!ret, 2508 "Failed to upload DPM Bootup Levels!", 2509 return ret); 2510 2511 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | 2512 FEATURE_DPM_UCLK_MASK | 2513 FEATURE_DPM_SOCCLK_MASK); 2514 PP_ASSERT_WITH_CODE(!ret, 2515 "Failed to upload DPM Max Levels!", 2516 return ret); 2517 2518 return 0; 2519 } 2520 2521 static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, 2522 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) 2523 { 2524 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2525 struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table); 2526 struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table); 2527 struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table); 2528 2529 *sclk_mask = 0; 2530 *mclk_mask = 0; 2531 *soc_mask = 0; 2532 2533 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && 2534 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL && 2535 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { 2536 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; 2537 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; 2538 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; 2539 } 2540 2541 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 2542 *sclk_mask = 0; 2543 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 2544 *mclk_mask = 0; 2545 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2546 *sclk_mask = gfx_dpm_table->count - 1; 2547 *mclk_mask = mem_dpm_table->count - 1; 2548 *soc_mask = soc_dpm_table->count - 1; 2549 } 2550 2551 return 0; 2552 } 2553 2554 static int vega20_force_clock_level(struct pp_hwmgr *hwmgr, 2555 enum pp_clock_type type, uint32_t mask) 2556 { 2557 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2558 uint32_t soft_min_level, soft_max_level, hard_min_level; 2559 int ret = 0; 2560 2561 switch (type) { 2562 case PP_SCLK: 2563 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2564 soft_max_level = mask ? (fls(mask) - 1) : 0; 2565 2566 if (soft_max_level >= data->dpm_table.gfx_table.count) { 2567 pr_err("Clock level specified %d is over max allowed %d\n", 2568 soft_max_level, 2569 data->dpm_table.gfx_table.count - 1); 2570 return -EINVAL; 2571 } 2572 2573 data->dpm_table.gfx_table.dpm_state.soft_min_level = 2574 data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; 2575 data->dpm_table.gfx_table.dpm_state.soft_max_level = 2576 data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; 2577 2578 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); 2579 PP_ASSERT_WITH_CODE(!ret, 2580 "Failed to upload boot level to lowest!", 2581 return ret); 2582 2583 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); 2584 PP_ASSERT_WITH_CODE(!ret, 2585 "Failed to upload dpm max level to highest!", 2586 return ret); 2587 break; 2588 2589 case PP_MCLK: 2590 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2591 soft_max_level = mask ? (fls(mask) - 1) : 0; 2592 2593 if (soft_max_level >= data->dpm_table.mem_table.count) { 2594 pr_err("Clock level specified %d is over max allowed %d\n", 2595 soft_max_level, 2596 data->dpm_table.mem_table.count - 1); 2597 return -EINVAL; 2598 } 2599 2600 data->dpm_table.mem_table.dpm_state.soft_min_level = 2601 data->dpm_table.mem_table.dpm_levels[soft_min_level].value; 2602 data->dpm_table.mem_table.dpm_state.soft_max_level = 2603 data->dpm_table.mem_table.dpm_levels[soft_max_level].value; 2604 2605 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK); 2606 PP_ASSERT_WITH_CODE(!ret, 2607 "Failed to upload boot level to lowest!", 2608 return ret); 2609 2610 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK); 2611 PP_ASSERT_WITH_CODE(!ret, 2612 "Failed to upload dpm max level to highest!", 2613 return ret); 2614 2615 break; 2616 2617 case PP_SOCCLK: 2618 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2619 soft_max_level = mask ? (fls(mask) - 1) : 0; 2620 2621 if (soft_max_level >= data->dpm_table.soc_table.count) { 2622 pr_err("Clock level specified %d is over max allowed %d\n", 2623 soft_max_level, 2624 data->dpm_table.soc_table.count - 1); 2625 return -EINVAL; 2626 } 2627 2628 data->dpm_table.soc_table.dpm_state.soft_min_level = 2629 data->dpm_table.soc_table.dpm_levels[soft_min_level].value; 2630 data->dpm_table.soc_table.dpm_state.soft_max_level = 2631 data->dpm_table.soc_table.dpm_levels[soft_max_level].value; 2632 2633 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); 2634 PP_ASSERT_WITH_CODE(!ret, 2635 "Failed to upload boot level to lowest!", 2636 return ret); 2637 2638 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); 2639 PP_ASSERT_WITH_CODE(!ret, 2640 "Failed to upload dpm max level to highest!", 2641 return ret); 2642 2643 break; 2644 2645 case PP_FCLK: 2646 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2647 soft_max_level = mask ? (fls(mask) - 1) : 0; 2648 2649 if (soft_max_level >= data->dpm_table.fclk_table.count) { 2650 pr_err("Clock level specified %d is over max allowed %d\n", 2651 soft_max_level, 2652 data->dpm_table.fclk_table.count - 1); 2653 return -EINVAL; 2654 } 2655 2656 data->dpm_table.fclk_table.dpm_state.soft_min_level = 2657 data->dpm_table.fclk_table.dpm_levels[soft_min_level].value; 2658 data->dpm_table.fclk_table.dpm_state.soft_max_level = 2659 data->dpm_table.fclk_table.dpm_levels[soft_max_level].value; 2660 2661 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK); 2662 PP_ASSERT_WITH_CODE(!ret, 2663 "Failed to upload boot level to lowest!", 2664 return ret); 2665 2666 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK); 2667 PP_ASSERT_WITH_CODE(!ret, 2668 "Failed to upload dpm max level to highest!", 2669 return ret); 2670 2671 break; 2672 2673 case PP_DCEFCLK: 2674 hard_min_level = mask ? (ffs(mask) - 1) : 0; 2675 2676 if (hard_min_level >= data->dpm_table.dcef_table.count) { 2677 pr_err("Clock level specified %d is over max allowed %d\n", 2678 hard_min_level, 2679 data->dpm_table.dcef_table.count - 1); 2680 return -EINVAL; 2681 } 2682 2683 data->dpm_table.dcef_table.dpm_state.hard_min_level = 2684 data->dpm_table.dcef_table.dpm_levels[hard_min_level].value; 2685 2686 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK); 2687 PP_ASSERT_WITH_CODE(!ret, 2688 "Failed to upload boot level to lowest!", 2689 return ret); 2690 2691 //TODO: Setting DCEFCLK max dpm level is not supported 2692 2693 break; 2694 2695 case PP_PCIE: 2696 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2697 soft_max_level = mask ? (fls(mask) - 1) : 0; 2698 if (soft_min_level >= NUM_LINK_LEVELS || 2699 soft_max_level >= NUM_LINK_LEVELS) 2700 return -EINVAL; 2701 2702 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 2703 PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level, 2704 NULL); 2705 PP_ASSERT_WITH_CODE(!ret, 2706 "Failed to set min link dpm level!", 2707 return ret); 2708 2709 break; 2710 2711 default: 2712 break; 2713 } 2714 2715 return 0; 2716 } 2717 2718 static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, 2719 enum amd_dpm_forced_level level) 2720 { 2721 int ret = 0; 2722 uint32_t sclk_mask, mclk_mask, soc_mask; 2723 2724 switch (level) { 2725 case AMD_DPM_FORCED_LEVEL_HIGH: 2726 ret = vega20_force_dpm_highest(hwmgr); 2727 break; 2728 2729 case AMD_DPM_FORCED_LEVEL_LOW: 2730 ret = vega20_force_dpm_lowest(hwmgr); 2731 break; 2732 2733 case AMD_DPM_FORCED_LEVEL_AUTO: 2734 ret = vega20_unforce_dpm_levels(hwmgr); 2735 break; 2736 2737 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 2738 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 2739 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 2740 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 2741 ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); 2742 if (ret) 2743 return ret; 2744 vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask); 2745 vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask); 2746 vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask); 2747 break; 2748 2749 case AMD_DPM_FORCED_LEVEL_MANUAL: 2750 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 2751 default: 2752 break; 2753 } 2754 2755 return ret; 2756 } 2757 2758 static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr) 2759 { 2760 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2761 2762 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) 2763 return AMD_FAN_CTRL_MANUAL; 2764 else 2765 return AMD_FAN_CTRL_AUTO; 2766 } 2767 2768 static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) 2769 { 2770 switch (mode) { 2771 case AMD_FAN_CTRL_NONE: 2772 vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100); 2773 break; 2774 case AMD_FAN_CTRL_MANUAL: 2775 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 2776 vega20_fan_ctrl_stop_smc_fan_control(hwmgr); 2777 break; 2778 case AMD_FAN_CTRL_AUTO: 2779 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 2780 vega20_fan_ctrl_start_smc_fan_control(hwmgr); 2781 break; 2782 default: 2783 break; 2784 } 2785 } 2786 2787 static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr, 2788 struct amd_pp_simple_clock_info *info) 2789 { 2790 #if 0 2791 struct phm_ppt_v2_information *table_info = 2792 (struct phm_ppt_v2_information *)hwmgr->pptable; 2793 struct phm_clock_and_voltage_limits *max_limits = 2794 &table_info->max_clock_voltage_on_ac; 2795 2796 info->engine_max_clock = max_limits->sclk; 2797 info->memory_max_clock = max_limits->mclk; 2798 #endif 2799 return 0; 2800 } 2801 2802 2803 static int vega20_get_sclks(struct pp_hwmgr *hwmgr, 2804 struct pp_clock_levels_with_latency *clocks) 2805 { 2806 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2807 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); 2808 int i, count; 2809 2810 if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) 2811 return -1; 2812 2813 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2814 clocks->num_levels = count; 2815 2816 for (i = 0; i < count; i++) { 2817 clocks->data[i].clocks_in_khz = 2818 dpm_table->dpm_levels[i].value * 1000; 2819 clocks->data[i].latency_in_us = 0; 2820 } 2821 2822 return 0; 2823 } 2824 2825 static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr, 2826 uint32_t clock) 2827 { 2828 return 25; 2829 } 2830 2831 static int vega20_get_memclocks(struct pp_hwmgr *hwmgr, 2832 struct pp_clock_levels_with_latency *clocks) 2833 { 2834 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2835 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table); 2836 int i, count; 2837 2838 if (!data->smu_features[GNLD_DPM_UCLK].enabled) 2839 return -1; 2840 2841 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2842 clocks->num_levels = data->mclk_latency_table.count = count; 2843 2844 for (i = 0; i < count; i++) { 2845 clocks->data[i].clocks_in_khz = 2846 data->mclk_latency_table.entries[i].frequency = 2847 dpm_table->dpm_levels[i].value * 1000; 2848 clocks->data[i].latency_in_us = 2849 data->mclk_latency_table.entries[i].latency = 2850 vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); 2851 } 2852 2853 return 0; 2854 } 2855 2856 static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr, 2857 struct pp_clock_levels_with_latency *clocks) 2858 { 2859 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2860 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table); 2861 int i, count; 2862 2863 if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled) 2864 return -1; 2865 2866 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2867 clocks->num_levels = count; 2868 2869 for (i = 0; i < count; i++) { 2870 clocks->data[i].clocks_in_khz = 2871 dpm_table->dpm_levels[i].value * 1000; 2872 clocks->data[i].latency_in_us = 0; 2873 } 2874 2875 return 0; 2876 } 2877 2878 static int vega20_get_socclocks(struct pp_hwmgr *hwmgr, 2879 struct pp_clock_levels_with_latency *clocks) 2880 { 2881 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2882 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table); 2883 int i, count; 2884 2885 if (!data->smu_features[GNLD_DPM_SOCCLK].enabled) 2886 return -1; 2887 2888 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 2889 clocks->num_levels = count; 2890 2891 for (i = 0; i < count; i++) { 2892 clocks->data[i].clocks_in_khz = 2893 dpm_table->dpm_levels[i].value * 1000; 2894 clocks->data[i].latency_in_us = 0; 2895 } 2896 2897 return 0; 2898 2899 } 2900 2901 static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, 2902 enum amd_pp_clock_type type, 2903 struct pp_clock_levels_with_latency *clocks) 2904 { 2905 int ret; 2906 2907 switch (type) { 2908 case amd_pp_sys_clock: 2909 ret = vega20_get_sclks(hwmgr, clocks); 2910 break; 2911 case amd_pp_mem_clock: 2912 ret = vega20_get_memclocks(hwmgr, clocks); 2913 break; 2914 case amd_pp_dcef_clock: 2915 ret = vega20_get_dcefclocks(hwmgr, clocks); 2916 break; 2917 case amd_pp_soc_clock: 2918 ret = vega20_get_socclocks(hwmgr, clocks); 2919 break; 2920 default: 2921 return -EINVAL; 2922 } 2923 2924 return ret; 2925 } 2926 2927 static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, 2928 enum amd_pp_clock_type type, 2929 struct pp_clock_levels_with_voltage *clocks) 2930 { 2931 clocks->num_levels = 0; 2932 2933 return 0; 2934 } 2935 2936 static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, 2937 void *clock_ranges) 2938 { 2939 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 2940 Watermarks_t *table = &(data->smc_state_table.water_marks_table); 2941 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; 2942 2943 if (!data->registry_data.disable_water_mark && 2944 data->smu_features[GNLD_DPM_DCEFCLK].supported && 2945 data->smu_features[GNLD_DPM_SOCCLK].supported) { 2946 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); 2947 data->water_marks_bitmap |= WaterMarksExist; 2948 data->water_marks_bitmap &= ~WaterMarksLoaded; 2949 } 2950 2951 return 0; 2952 } 2953 2954 static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, 2955 enum PP_OD_DPM_TABLE_COMMAND type, 2956 long *input, uint32_t size) 2957 { 2958 struct vega20_hwmgr *data = 2959 (struct vega20_hwmgr *)(hwmgr->backend); 2960 struct vega20_od8_single_setting *od8_settings = 2961 data->od8_settings.od8_settings_array; 2962 OverDriveTable_t *od_table = 2963 &(data->smc_state_table.overdrive_table); 2964 int32_t input_index, input_clk, input_vol, i; 2965 int od8_id; 2966 int ret; 2967 2968 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", 2969 return -EINVAL); 2970 2971 switch (type) { 2972 case PP_OD_EDIT_SCLK_VDDC_TABLE: 2973 if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && 2974 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) { 2975 pr_info("Sclk min/max frequency overdrive not supported\n"); 2976 return -EOPNOTSUPP; 2977 } 2978 2979 for (i = 0; i < size; i += 2) { 2980 if (i + 2 > size) { 2981 pr_info("invalid number of input parameters %d\n", 2982 size); 2983 return -EINVAL; 2984 } 2985 2986 input_index = input[i]; 2987 input_clk = input[i + 1]; 2988 2989 if (input_index != 0 && input_index != 1) { 2990 pr_info("Invalid index %d\n", input_index); 2991 pr_info("Support min/max sclk frequency setting only which index by 0/1\n"); 2992 return -EINVAL; 2993 } 2994 2995 if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value || 2996 input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) { 2997 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 2998 input_clk, 2999 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, 3000 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); 3001 return -EINVAL; 3002 } 3003 3004 if ((input_index == 0 && od_table->GfxclkFmin != input_clk) || 3005 (input_index == 1 && od_table->GfxclkFmax != input_clk)) 3006 data->gfxclk_overdrive = true; 3007 3008 if (input_index == 0) 3009 od_table->GfxclkFmin = input_clk; 3010 else 3011 od_table->GfxclkFmax = input_clk; 3012 } 3013 3014 break; 3015 3016 case PP_OD_EDIT_MCLK_VDDC_TABLE: 3017 if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { 3018 pr_info("Mclk max frequency overdrive not supported\n"); 3019 return -EOPNOTSUPP; 3020 } 3021 3022 for (i = 0; i < size; i += 2) { 3023 if (i + 2 > size) { 3024 pr_info("invalid number of input parameters %d\n", 3025 size); 3026 return -EINVAL; 3027 } 3028 3029 input_index = input[i]; 3030 input_clk = input[i + 1]; 3031 3032 if (input_index != 1) { 3033 pr_info("Invalid index %d\n", input_index); 3034 pr_info("Support max Mclk frequency setting only which index by 1\n"); 3035 return -EINVAL; 3036 } 3037 3038 if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || 3039 input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { 3040 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 3041 input_clk, 3042 od8_settings[OD8_SETTING_UCLK_FMAX].min_value, 3043 od8_settings[OD8_SETTING_UCLK_FMAX].max_value); 3044 return -EINVAL; 3045 } 3046 3047 if (input_index == 1 && od_table->UclkFmax != input_clk) 3048 data->memclk_overdrive = true; 3049 3050 od_table->UclkFmax = input_clk; 3051 } 3052 3053 break; 3054 3055 case PP_OD_EDIT_VDDC_CURVE: 3056 if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && 3057 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && 3058 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && 3059 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 3060 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 3061 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { 3062 pr_info("Voltage curve calibrate not supported\n"); 3063 return -EOPNOTSUPP; 3064 } 3065 3066 for (i = 0; i < size; i += 3) { 3067 if (i + 3 > size) { 3068 pr_info("invalid number of input parameters %d\n", 3069 size); 3070 return -EINVAL; 3071 } 3072 3073 input_index = input[i]; 3074 input_clk = input[i + 1]; 3075 input_vol = input[i + 2]; 3076 3077 if (input_index > 2) { 3078 pr_info("Setting for point %d is not supported\n", 3079 input_index + 1); 3080 pr_info("Three supported points index by 0, 1, 2\n"); 3081 return -EINVAL; 3082 } 3083 3084 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index; 3085 if (input_clk < od8_settings[od8_id].min_value || 3086 input_clk > od8_settings[od8_id].max_value) { 3087 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 3088 input_clk, 3089 od8_settings[od8_id].min_value, 3090 od8_settings[od8_id].max_value); 3091 return -EINVAL; 3092 } 3093 3094 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index; 3095 if (input_vol < od8_settings[od8_id].min_value || 3096 input_vol > od8_settings[od8_id].max_value) { 3097 pr_info("clock voltage %d is not within allowed range [%d - %d]\n", 3098 input_vol, 3099 od8_settings[od8_id].min_value, 3100 od8_settings[od8_id].max_value); 3101 return -EINVAL; 3102 } 3103 3104 switch (input_index) { 3105 case 0: 3106 od_table->GfxclkFreq1 = input_clk; 3107 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE; 3108 break; 3109 case 1: 3110 od_table->GfxclkFreq2 = input_clk; 3111 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE; 3112 break; 3113 case 2: 3114 od_table->GfxclkFreq3 = input_clk; 3115 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE; 3116 break; 3117 } 3118 } 3119 break; 3120 3121 case PP_OD_RESTORE_DEFAULT_TABLE: 3122 data->gfxclk_overdrive = false; 3123 data->memclk_overdrive = false; 3124 3125 ret = smum_smc_table_manager(hwmgr, 3126 (uint8_t *)od_table, 3127 TABLE_OVERDRIVE, true); 3128 PP_ASSERT_WITH_CODE(!ret, 3129 "Failed to export overdrive table!", 3130 return ret); 3131 break; 3132 3133 case PP_OD_COMMIT_DPM_TABLE: 3134 ret = smum_smc_table_manager(hwmgr, 3135 (uint8_t *)od_table, 3136 TABLE_OVERDRIVE, false); 3137 PP_ASSERT_WITH_CODE(!ret, 3138 "Failed to import overdrive table!", 3139 return ret); 3140 3141 /* retrieve updated gfxclk table */ 3142 if (data->gfxclk_overdrive) { 3143 data->gfxclk_overdrive = false; 3144 3145 ret = vega20_setup_gfxclk_dpm_table(hwmgr); 3146 if (ret) 3147 return ret; 3148 } 3149 3150 /* retrieve updated memclk table */ 3151 if (data->memclk_overdrive) { 3152 data->memclk_overdrive = false; 3153 3154 ret = vega20_setup_memclk_dpm_table(hwmgr); 3155 if (ret) 3156 return ret; 3157 } 3158 break; 3159 3160 default: 3161 return -EINVAL; 3162 } 3163 3164 return 0; 3165 } 3166 3167 static int vega20_set_mp1_state(struct pp_hwmgr *hwmgr, 3168 enum pp_mp1_state mp1_state) 3169 { 3170 uint16_t msg; 3171 int ret; 3172 3173 switch (mp1_state) { 3174 case PP_MP1_STATE_SHUTDOWN: 3175 msg = PPSMC_MSG_PrepareMp1ForShutdown; 3176 break; 3177 case PP_MP1_STATE_UNLOAD: 3178 msg = PPSMC_MSG_PrepareMp1ForUnload; 3179 break; 3180 case PP_MP1_STATE_RESET: 3181 msg = PPSMC_MSG_PrepareMp1ForReset; 3182 break; 3183 case PP_MP1_STATE_NONE: 3184 default: 3185 return 0; 3186 } 3187 3188 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, 3189 "[PrepareMp1] Failed!", 3190 return ret); 3191 3192 return 0; 3193 } 3194 3195 static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) 3196 { 3197 static const char *ppfeature_name[] = { 3198 "DPM_PREFETCHER", 3199 "GFXCLK_DPM", 3200 "UCLK_DPM", 3201 "SOCCLK_DPM", 3202 "UVD_DPM", 3203 "VCE_DPM", 3204 "ULV", 3205 "MP0CLK_DPM", 3206 "LINK_DPM", 3207 "DCEFCLK_DPM", 3208 "GFXCLK_DS", 3209 "SOCCLK_DS", 3210 "LCLK_DS", 3211 "PPT", 3212 "TDC", 3213 "THERMAL", 3214 "GFX_PER_CU_CG", 3215 "RM", 3216 "DCEFCLK_DS", 3217 "ACDC", 3218 "VR0HOT", 3219 "VR1HOT", 3220 "FW_CTF", 3221 "LED_DISPLAY", 3222 "FAN_CONTROL", 3223 "GFX_EDC", 3224 "GFXOFF", 3225 "CG", 3226 "FCLK_DPM", 3227 "FCLK_DS", 3228 "MP1CLK_DS", 3229 "MP0CLK_DS", 3230 "XGMI", 3231 "ECC"}; 3232 static const char *output_title[] = { 3233 "FEATURES", 3234 "BITMASK", 3235 "ENABLEMENT"}; 3236 uint64_t features_enabled; 3237 int i; 3238 int ret = 0; 3239 int size = 0; 3240 3241 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 3242 PP_ASSERT_WITH_CODE(!ret, 3243 "[EnableAllSmuFeatures] Failed to get enabled smc features!", 3244 return ret); 3245 3246 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); 3247 size += sprintf(buf + size, "%-19s %-22s %s\n", 3248 output_title[0], 3249 output_title[1], 3250 output_title[2]); 3251 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 3252 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", 3253 ppfeature_name[i], 3254 1ULL << i, 3255 (features_enabled & (1ULL << i)) ? "Y" : "N"); 3256 } 3257 3258 return size; 3259 } 3260 3261 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) 3262 { 3263 struct vega20_hwmgr *data = 3264 (struct vega20_hwmgr *)(hwmgr->backend); 3265 uint64_t features_enabled, features_to_enable, features_to_disable; 3266 int i, ret = 0; 3267 bool enabled; 3268 3269 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) 3270 return -EINVAL; 3271 3272 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 3273 if (ret) 3274 return ret; 3275 3276 features_to_disable = 3277 features_enabled & ~new_ppfeature_masks; 3278 features_to_enable = 3279 ~features_enabled & new_ppfeature_masks; 3280 3281 pr_debug("features_to_disable 0x%llx\n", features_to_disable); 3282 pr_debug("features_to_enable 0x%llx\n", features_to_enable); 3283 3284 if (features_to_disable) { 3285 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable); 3286 if (ret) 3287 return ret; 3288 } 3289 3290 if (features_to_enable) { 3291 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable); 3292 if (ret) 3293 return ret; 3294 } 3295 3296 /* Update the cached feature enablement state */ 3297 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); 3298 if (ret) 3299 return ret; 3300 3301 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 3302 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? 3303 true : false; 3304 data->smu_features[i].enabled = enabled; 3305 } 3306 3307 return 0; 3308 } 3309 3310 static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) 3311 { 3312 struct amdgpu_device *adev = hwmgr->adev; 3313 3314 return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & 3315 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) 3316 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; 3317 } 3318 3319 static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) 3320 { 3321 uint32_t width_level; 3322 3323 width_level = vega20_get_current_pcie_link_width_level(hwmgr); 3324 if (width_level > LINK_WIDTH_MAX) 3325 width_level = 0; 3326 3327 return link_width[width_level]; 3328 } 3329 3330 static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) 3331 { 3332 struct amdgpu_device *adev = hwmgr->adev; 3333 3334 return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & 3335 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) 3336 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; 3337 } 3338 3339 static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) 3340 { 3341 uint32_t speed_level; 3342 3343 speed_level = vega20_get_current_pcie_link_speed_level(hwmgr); 3344 if (speed_level > LINK_SPEED_MAX) 3345 speed_level = 0; 3346 3347 return link_speed[speed_level]; 3348 } 3349 3350 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, 3351 enum pp_clock_type type, char *buf) 3352 { 3353 struct vega20_hwmgr *data = 3354 (struct vega20_hwmgr *)(hwmgr->backend); 3355 struct vega20_od8_single_setting *od8_settings = 3356 data->od8_settings.od8_settings_array; 3357 OverDriveTable_t *od_table = 3358 &(data->smc_state_table.overdrive_table); 3359 PPTable_t *pptable = &(data->smc_state_table.pp_table); 3360 struct pp_clock_levels_with_latency clocks; 3361 struct vega20_single_dpm_table *fclk_dpm_table = 3362 &(data->dpm_table.fclk_table); 3363 int i, now, size = 0; 3364 int ret = 0; 3365 uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width; 3366 3367 switch (type) { 3368 case PP_SCLK: 3369 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now); 3370 PP_ASSERT_WITH_CODE(!ret, 3371 "Attempt to get current gfx clk Failed!", 3372 return ret); 3373 3374 if (vega20_get_sclks(hwmgr, &clocks)) { 3375 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3376 now / 100); 3377 break; 3378 } 3379 3380 for (i = 0; i < clocks.num_levels; i++) 3381 size += sprintf(buf + size, "%d: %uMhz %s\n", 3382 i, clocks.data[i].clocks_in_khz / 1000, 3383 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3384 break; 3385 3386 case PP_MCLK: 3387 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now); 3388 PP_ASSERT_WITH_CODE(!ret, 3389 "Attempt to get current mclk freq Failed!", 3390 return ret); 3391 3392 if (vega20_get_memclocks(hwmgr, &clocks)) { 3393 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3394 now / 100); 3395 break; 3396 } 3397 3398 for (i = 0; i < clocks.num_levels; i++) 3399 size += sprintf(buf + size, "%d: %uMhz %s\n", 3400 i, clocks.data[i].clocks_in_khz / 1000, 3401 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3402 break; 3403 3404 case PP_SOCCLK: 3405 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now); 3406 PP_ASSERT_WITH_CODE(!ret, 3407 "Attempt to get current socclk freq Failed!", 3408 return ret); 3409 3410 if (vega20_get_socclocks(hwmgr, &clocks)) { 3411 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3412 now / 100); 3413 break; 3414 } 3415 3416 for (i = 0; i < clocks.num_levels; i++) 3417 size += sprintf(buf + size, "%d: %uMhz %s\n", 3418 i, clocks.data[i].clocks_in_khz / 1000, 3419 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3420 break; 3421 3422 case PP_FCLK: 3423 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now); 3424 PP_ASSERT_WITH_CODE(!ret, 3425 "Attempt to get current fclk freq Failed!", 3426 return ret); 3427 3428 for (i = 0; i < fclk_dpm_table->count; i++) 3429 size += sprintf(buf + size, "%d: %uMhz %s\n", 3430 i, fclk_dpm_table->dpm_levels[i].value, 3431 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : ""); 3432 break; 3433 3434 case PP_DCEFCLK: 3435 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now); 3436 PP_ASSERT_WITH_CODE(!ret, 3437 "Attempt to get current dcefclk freq Failed!", 3438 return ret); 3439 3440 if (vega20_get_dcefclocks(hwmgr, &clocks)) { 3441 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", 3442 now / 100); 3443 break; 3444 } 3445 3446 for (i = 0; i < clocks.num_levels; i++) 3447 size += sprintf(buf + size, "%d: %uMhz %s\n", 3448 i, clocks.data[i].clocks_in_khz / 1000, 3449 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3450 break; 3451 3452 case PP_PCIE: 3453 current_gen_speed = 3454 vega20_get_current_pcie_link_speed_level(hwmgr); 3455 current_lane_width = 3456 vega20_get_current_pcie_link_width_level(hwmgr); 3457 for (i = 0; i < NUM_LINK_LEVELS; i++) { 3458 gen_speed = pptable->PcieGenSpeed[i]; 3459 lane_width = pptable->PcieLaneCount[i]; 3460 3461 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, 3462 (gen_speed == 0) ? "2.5GT/s," : 3463 (gen_speed == 1) ? "5.0GT/s," : 3464 (gen_speed == 2) ? "8.0GT/s," : 3465 (gen_speed == 3) ? "16.0GT/s," : "", 3466 (lane_width == 1) ? "x1" : 3467 (lane_width == 2) ? "x2" : 3468 (lane_width == 3) ? "x4" : 3469 (lane_width == 4) ? "x8" : 3470 (lane_width == 5) ? "x12" : 3471 (lane_width == 6) ? "x16" : "", 3472 pptable->LclkFreq[i], 3473 (current_gen_speed == gen_speed) && 3474 (current_lane_width == lane_width) ? 3475 "*" : ""); 3476 } 3477 break; 3478 3479 case OD_SCLK: 3480 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && 3481 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { 3482 size = sprintf(buf, "%s:\n", "OD_SCLK"); 3483 size += sprintf(buf + size, "0: %10uMhz\n", 3484 od_table->GfxclkFmin); 3485 size += sprintf(buf + size, "1: %10uMhz\n", 3486 od_table->GfxclkFmax); 3487 } 3488 break; 3489 3490 case OD_MCLK: 3491 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { 3492 size = sprintf(buf, "%s:\n", "OD_MCLK"); 3493 size += sprintf(buf + size, "1: %10uMhz\n", 3494 od_table->UclkFmax); 3495 } 3496 3497 break; 3498 3499 case OD_VDDC_CURVE: 3500 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && 3501 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && 3502 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && 3503 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 3504 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 3505 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { 3506 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE"); 3507 size += sprintf(buf + size, "0: %10uMhz %10dmV\n", 3508 od_table->GfxclkFreq1, 3509 od_table->GfxclkVolt1 / VOLTAGE_SCALE); 3510 size += sprintf(buf + size, "1: %10uMhz %10dmV\n", 3511 od_table->GfxclkFreq2, 3512 od_table->GfxclkVolt2 / VOLTAGE_SCALE); 3513 size += sprintf(buf + size, "2: %10uMhz %10dmV\n", 3514 od_table->GfxclkFreq3, 3515 od_table->GfxclkVolt3 / VOLTAGE_SCALE); 3516 } 3517 3518 break; 3519 3520 case OD_RANGE: 3521 size = sprintf(buf, "%s:\n", "OD_RANGE"); 3522 3523 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && 3524 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { 3525 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 3526 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, 3527 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); 3528 } 3529 3530 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { 3531 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", 3532 od8_settings[OD8_SETTING_UCLK_FMAX].min_value, 3533 od8_settings[OD8_SETTING_UCLK_FMAX].max_value); 3534 } 3535 3536 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && 3537 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && 3538 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && 3539 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 3540 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 3541 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { 3542 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", 3543 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, 3544 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value); 3545 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", 3546 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, 3547 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); 3548 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", 3549 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, 3550 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value); 3551 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", 3552 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, 3553 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); 3554 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", 3555 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, 3556 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value); 3557 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", 3558 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, 3559 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); 3560 } 3561 3562 break; 3563 default: 3564 break; 3565 } 3566 return size; 3567 } 3568 3569 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr, 3570 struct vega20_single_dpm_table *dpm_table) 3571 { 3572 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3573 int ret = 0; 3574 3575 if (data->smu_features[GNLD_DPM_UCLK].enabled) { 3576 PP_ASSERT_WITH_CODE(dpm_table->count > 0, 3577 "[SetUclkToHightestDpmLevel] Dpm table has no entry!", 3578 return -EINVAL); 3579 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS, 3580 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!", 3581 return -EINVAL); 3582 3583 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3584 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, 3585 PPSMC_MSG_SetHardMinByFreq, 3586 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, 3587 NULL)), 3588 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!", 3589 return ret); 3590 } 3591 3592 return ret; 3593 } 3594 3595 static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr) 3596 { 3597 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3598 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table); 3599 int ret = 0; 3600 3601 if (data->smu_features[GNLD_DPM_FCLK].enabled) { 3602 PP_ASSERT_WITH_CODE(dpm_table->count > 0, 3603 "[SetFclkToHightestDpmLevel] Dpm table has no entry!", 3604 return -EINVAL); 3605 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS, 3606 "[SetFclkToHightestDpmLevel] Dpm table has too many entries!", 3607 return -EINVAL); 3608 3609 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3610 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, 3611 PPSMC_MSG_SetSoftMinByFreq, 3612 (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level, 3613 NULL)), 3614 "[SetFclkToHightestDpmLevel] Set soft min fclk failed!", 3615 return ret); 3616 } 3617 3618 return ret; 3619 } 3620 3621 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 3622 { 3623 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3624 int ret = 0; 3625 3626 smum_send_msg_to_smc_with_parameter(hwmgr, 3627 PPSMC_MSG_NumOfDisplays, 0, NULL); 3628 3629 ret = vega20_set_uclk_to_highest_dpm_level(hwmgr, 3630 &data->dpm_table.mem_table); 3631 if (ret) 3632 return ret; 3633 3634 return vega20_set_fclk_to_highest_dpm_level(hwmgr); 3635 } 3636 3637 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 3638 { 3639 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3640 int result = 0; 3641 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); 3642 3643 if ((data->water_marks_bitmap & WaterMarksExist) && 3644 !(data->water_marks_bitmap & WaterMarksLoaded)) { 3645 result = smum_smc_table_manager(hwmgr, 3646 (uint8_t *)wm_table, TABLE_WATERMARKS, false); 3647 PP_ASSERT_WITH_CODE(!result, 3648 "Failed to update WMTABLE!", 3649 return result); 3650 data->water_marks_bitmap |= WaterMarksLoaded; 3651 } 3652 3653 if ((data->water_marks_bitmap & WaterMarksExist) && 3654 data->smu_features[GNLD_DPM_DCEFCLK].supported && 3655 data->smu_features[GNLD_DPM_SOCCLK].supported) { 3656 result = smum_send_msg_to_smc_with_parameter(hwmgr, 3657 PPSMC_MSG_NumOfDisplays, 3658 hwmgr->display_config->num_display, 3659 NULL); 3660 } 3661 3662 return result; 3663 } 3664 3665 static int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) 3666 { 3667 struct vega20_hwmgr *data = 3668 (struct vega20_hwmgr *)(hwmgr->backend); 3669 int ret = 0; 3670 3671 if (data->smu_features[GNLD_DPM_UVD].supported) { 3672 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) { 3673 if (enable) 3674 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n"); 3675 else 3676 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n"); 3677 } 3678 3679 ret = vega20_enable_smc_features(hwmgr, 3680 enable, 3681 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap); 3682 PP_ASSERT_WITH_CODE(!ret, 3683 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!", 3684 return ret); 3685 data->smu_features[GNLD_DPM_UVD].enabled = enable; 3686 } 3687 3688 return 0; 3689 } 3690 3691 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) 3692 { 3693 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3694 3695 if (data->vce_power_gated == bgate) 3696 return ; 3697 3698 data->vce_power_gated = bgate; 3699 if (bgate) { 3700 vega20_enable_disable_vce_dpm(hwmgr, !bgate); 3701 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 3702 AMD_IP_BLOCK_TYPE_VCE, 3703 AMD_PG_STATE_GATE); 3704 } else { 3705 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 3706 AMD_IP_BLOCK_TYPE_VCE, 3707 AMD_PG_STATE_UNGATE); 3708 vega20_enable_disable_vce_dpm(hwmgr, !bgate); 3709 } 3710 3711 } 3712 3713 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) 3714 { 3715 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3716 3717 if (data->uvd_power_gated == bgate) 3718 return ; 3719 3720 data->uvd_power_gated = bgate; 3721 vega20_enable_disable_uvd_dpm(hwmgr, !bgate); 3722 } 3723 3724 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr) 3725 { 3726 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3727 struct vega20_single_dpm_table *dpm_table; 3728 bool vblank_too_short = false; 3729 bool disable_mclk_switching; 3730 bool disable_fclk_switching; 3731 uint32_t i, latency; 3732 3733 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && 3734 !hwmgr->display_config->multi_monitor_in_sync) || 3735 vblank_too_short; 3736 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; 3737 3738 /* gfxclk */ 3739 dpm_table = &(data->dpm_table.gfx_table); 3740 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3741 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3742 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3743 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3744 3745 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3746 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { 3747 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 3748 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 3749 } 3750 3751 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 3752 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3753 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; 3754 } 3755 3756 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3757 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3758 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3759 } 3760 } 3761 3762 /* memclk */ 3763 dpm_table = &(data->dpm_table.mem_table); 3764 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3765 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3766 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3767 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3768 3769 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3770 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { 3771 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 3772 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 3773 } 3774 3775 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 3776 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3777 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; 3778 } 3779 3780 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3781 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3782 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3783 } 3784 } 3785 3786 /* honour DAL's UCLK Hardmin */ 3787 if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100)) 3788 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100; 3789 3790 /* Hardmin is dependent on displayconfig */ 3791 if (disable_mclk_switching) { 3792 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3793 for (i = 0; i < data->mclk_latency_table.count - 1; i++) { 3794 if (data->mclk_latency_table.entries[i].latency <= latency) { 3795 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) { 3796 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; 3797 break; 3798 } 3799 } 3800 } 3801 } 3802 3803 if (hwmgr->display_config->nb_pstate_switch_disable) 3804 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3805 3806 if ((disable_mclk_switching && 3807 (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) || 3808 hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value) 3809 disable_fclk_switching = true; 3810 else 3811 disable_fclk_switching = false; 3812 3813 /* fclk */ 3814 dpm_table = &(data->dpm_table.fclk_table); 3815 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3816 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3817 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3818 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3819 if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching) 3820 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3821 3822 /* vclk */ 3823 dpm_table = &(data->dpm_table.vclk_table); 3824 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3825 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3826 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3827 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3828 3829 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3830 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { 3831 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3832 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3833 } 3834 3835 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3836 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3837 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3838 } 3839 } 3840 3841 /* dclk */ 3842 dpm_table = &(data->dpm_table.dclk_table); 3843 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3844 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3845 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3846 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3847 3848 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3849 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { 3850 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3851 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 3852 } 3853 3854 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3855 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3856 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3857 } 3858 } 3859 3860 /* socclk */ 3861 dpm_table = &(data->dpm_table.soc_table); 3862 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3863 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3864 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3865 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3866 3867 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3868 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { 3869 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; 3870 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; 3871 } 3872 3873 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3874 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3875 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3876 } 3877 } 3878 3879 /* eclk */ 3880 dpm_table = &(data->dpm_table.eclk_table); 3881 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 3882 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; 3883 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 3884 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; 3885 3886 if (PP_CAP(PHM_PlatformCaps_UMDPState)) { 3887 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { 3888 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; 3889 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; 3890 } 3891 3892 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 3893 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3894 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 3895 } 3896 } 3897 3898 return 0; 3899 } 3900 3901 static bool 3902 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) 3903 { 3904 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3905 bool is_update_required = false; 3906 3907 if (data->display_timing.num_existing_displays != 3908 hwmgr->display_config->num_display) 3909 is_update_required = true; 3910 3911 if (data->registry_data.gfx_clk_deep_sleep_support && 3912 (data->display_timing.min_clock_in_sr != 3913 hwmgr->display_config->min_core_set_clock_in_sr)) 3914 is_update_required = true; 3915 3916 return is_update_required; 3917 } 3918 3919 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 3920 { 3921 int ret = 0; 3922 3923 ret = vega20_disable_all_smu_features(hwmgr); 3924 PP_ASSERT_WITH_CODE(!ret, 3925 "[DisableDpmTasks] Failed to disable all smu features!", 3926 return ret); 3927 3928 return 0; 3929 } 3930 3931 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr) 3932 { 3933 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); 3934 int result; 3935 3936 result = vega20_disable_dpm_tasks(hwmgr); 3937 PP_ASSERT_WITH_CODE((0 == result), 3938 "[PowerOffAsic] Failed to disable DPM!", 3939 ); 3940 data->water_marks_bitmap &= ~(WaterMarksLoaded); 3941 3942 return result; 3943 } 3944 3945 static int conv_power_profile_to_pplib_workload(int power_profile) 3946 { 3947 int pplib_workload = 0; 3948 3949 switch (power_profile) { 3950 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: 3951 pplib_workload = WORKLOAD_DEFAULT_BIT; 3952 break; 3953 case PP_SMC_POWER_PROFILE_FULLSCREEN3D: 3954 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; 3955 break; 3956 case PP_SMC_POWER_PROFILE_POWERSAVING: 3957 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; 3958 break; 3959 case PP_SMC_POWER_PROFILE_VIDEO: 3960 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; 3961 break; 3962 case PP_SMC_POWER_PROFILE_VR: 3963 pplib_workload = WORKLOAD_PPLIB_VR_BIT; 3964 break; 3965 case PP_SMC_POWER_PROFILE_COMPUTE: 3966 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; 3967 break; 3968 case PP_SMC_POWER_PROFILE_CUSTOM: 3969 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT; 3970 break; 3971 } 3972 3973 return pplib_workload; 3974 } 3975 3976 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) 3977 { 3978 DpmActivityMonitorCoeffInt_t activity_monitor; 3979 uint32_t i, size = 0; 3980 uint16_t workload_type = 0; 3981 static const char *profile_name[] = { 3982 "BOOTUP_DEFAULT", 3983 "3D_FULL_SCREEN", 3984 "POWER_SAVING", 3985 "VIDEO", 3986 "VR", 3987 "COMPUTE", 3988 "CUSTOM"}; 3989 static const char *title[] = { 3990 "PROFILE_INDEX(NAME)", 3991 "CLOCK_TYPE(NAME)", 3992 "FPS", 3993 "UseRlcBusy", 3994 "MinActiveFreqType", 3995 "MinActiveFreq", 3996 "BoosterFreqType", 3997 "BoosterFreq", 3998 "PD_Data_limit_c", 3999 "PD_Data_error_coeff", 4000 "PD_Data_error_rate_coeff"}; 4001 int result = 0; 4002 4003 if (!buf) 4004 return -EINVAL; 4005 4006 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", 4007 title[0], title[1], title[2], title[3], title[4], title[5], 4008 title[6], title[7], title[8], title[9], title[10]); 4009 4010 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { 4011 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 4012 workload_type = conv_power_profile_to_pplib_workload(i); 4013 result = vega20_get_activity_monitor_coeff(hwmgr, 4014 (uint8_t *)(&activity_monitor), workload_type); 4015 PP_ASSERT_WITH_CODE(!result, 4016 "[GetPowerProfile] Failed to get activity monitor!", 4017 return result); 4018 4019 size += sprintf(buf + size, "%2d %14s%s:\n", 4020 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " "); 4021 4022 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4023 " ", 4024 0, 4025 "GFXCLK", 4026 activity_monitor.Gfx_FPS, 4027 activity_monitor.Gfx_UseRlcBusy, 4028 activity_monitor.Gfx_MinActiveFreqType, 4029 activity_monitor.Gfx_MinActiveFreq, 4030 activity_monitor.Gfx_BoosterFreqType, 4031 activity_monitor.Gfx_BoosterFreq, 4032 activity_monitor.Gfx_PD_Data_limit_c, 4033 activity_monitor.Gfx_PD_Data_error_coeff, 4034 activity_monitor.Gfx_PD_Data_error_rate_coeff); 4035 4036 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4037 " ", 4038 1, 4039 "SOCCLK", 4040 activity_monitor.Soc_FPS, 4041 activity_monitor.Soc_UseRlcBusy, 4042 activity_monitor.Soc_MinActiveFreqType, 4043 activity_monitor.Soc_MinActiveFreq, 4044 activity_monitor.Soc_BoosterFreqType, 4045 activity_monitor.Soc_BoosterFreq, 4046 activity_monitor.Soc_PD_Data_limit_c, 4047 activity_monitor.Soc_PD_Data_error_coeff, 4048 activity_monitor.Soc_PD_Data_error_rate_coeff); 4049 4050 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4051 " ", 4052 2, 4053 "UCLK", 4054 activity_monitor.Mem_FPS, 4055 activity_monitor.Mem_UseRlcBusy, 4056 activity_monitor.Mem_MinActiveFreqType, 4057 activity_monitor.Mem_MinActiveFreq, 4058 activity_monitor.Mem_BoosterFreqType, 4059 activity_monitor.Mem_BoosterFreq, 4060 activity_monitor.Mem_PD_Data_limit_c, 4061 activity_monitor.Mem_PD_Data_error_coeff, 4062 activity_monitor.Mem_PD_Data_error_rate_coeff); 4063 4064 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 4065 " ", 4066 3, 4067 "FCLK", 4068 activity_monitor.Fclk_FPS, 4069 activity_monitor.Fclk_UseRlcBusy, 4070 activity_monitor.Fclk_MinActiveFreqType, 4071 activity_monitor.Fclk_MinActiveFreq, 4072 activity_monitor.Fclk_BoosterFreqType, 4073 activity_monitor.Fclk_BoosterFreq, 4074 activity_monitor.Fclk_PD_Data_limit_c, 4075 activity_monitor.Fclk_PD_Data_error_coeff, 4076 activity_monitor.Fclk_PD_Data_error_rate_coeff); 4077 } 4078 4079 return size; 4080 } 4081 4082 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) 4083 { 4084 DpmActivityMonitorCoeffInt_t activity_monitor; 4085 int workload_type, result = 0; 4086 uint32_t power_profile_mode = input[size]; 4087 4088 if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { 4089 pr_err("Invalid power profile mode %d\n", power_profile_mode); 4090 return -EINVAL; 4091 } 4092 4093 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { 4094 struct vega20_hwmgr *data = 4095 (struct vega20_hwmgr *)(hwmgr->backend); 4096 if (size == 0 && !data->is_custom_profile_set) 4097 return -EINVAL; 4098 if (size < 10 && size != 0) 4099 return -EINVAL; 4100 4101 result = vega20_get_activity_monitor_coeff(hwmgr, 4102 (uint8_t *)(&activity_monitor), 4103 WORKLOAD_PPLIB_CUSTOM_BIT); 4104 PP_ASSERT_WITH_CODE(!result, 4105 "[SetPowerProfile] Failed to get activity monitor!", 4106 return result); 4107 4108 /* If size==0, then we want to apply the already-configured 4109 * CUSTOM profile again. Just apply it, since we checked its 4110 * validity above 4111 */ 4112 if (size == 0) 4113 goto out; 4114 4115 switch (input[0]) { 4116 case 0: /* Gfxclk */ 4117 activity_monitor.Gfx_FPS = input[1]; 4118 activity_monitor.Gfx_UseRlcBusy = input[2]; 4119 activity_monitor.Gfx_MinActiveFreqType = input[3]; 4120 activity_monitor.Gfx_MinActiveFreq = input[4]; 4121 activity_monitor.Gfx_BoosterFreqType = input[5]; 4122 activity_monitor.Gfx_BoosterFreq = input[6]; 4123 activity_monitor.Gfx_PD_Data_limit_c = input[7]; 4124 activity_monitor.Gfx_PD_Data_error_coeff = input[8]; 4125 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; 4126 break; 4127 case 1: /* Socclk */ 4128 activity_monitor.Soc_FPS = input[1]; 4129 activity_monitor.Soc_UseRlcBusy = input[2]; 4130 activity_monitor.Soc_MinActiveFreqType = input[3]; 4131 activity_monitor.Soc_MinActiveFreq = input[4]; 4132 activity_monitor.Soc_BoosterFreqType = input[5]; 4133 activity_monitor.Soc_BoosterFreq = input[6]; 4134 activity_monitor.Soc_PD_Data_limit_c = input[7]; 4135 activity_monitor.Soc_PD_Data_error_coeff = input[8]; 4136 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; 4137 break; 4138 case 2: /* Uclk */ 4139 activity_monitor.Mem_FPS = input[1]; 4140 activity_monitor.Mem_UseRlcBusy = input[2]; 4141 activity_monitor.Mem_MinActiveFreqType = input[3]; 4142 activity_monitor.Mem_MinActiveFreq = input[4]; 4143 activity_monitor.Mem_BoosterFreqType = input[5]; 4144 activity_monitor.Mem_BoosterFreq = input[6]; 4145 activity_monitor.Mem_PD_Data_limit_c = input[7]; 4146 activity_monitor.Mem_PD_Data_error_coeff = input[8]; 4147 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; 4148 break; 4149 case 3: /* Fclk */ 4150 activity_monitor.Fclk_FPS = input[1]; 4151 activity_monitor.Fclk_UseRlcBusy = input[2]; 4152 activity_monitor.Fclk_MinActiveFreqType = input[3]; 4153 activity_monitor.Fclk_MinActiveFreq = input[4]; 4154 activity_monitor.Fclk_BoosterFreqType = input[5]; 4155 activity_monitor.Fclk_BoosterFreq = input[6]; 4156 activity_monitor.Fclk_PD_Data_limit_c = input[7]; 4157 activity_monitor.Fclk_PD_Data_error_coeff = input[8]; 4158 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; 4159 break; 4160 } 4161 4162 result = vega20_set_activity_monitor_coeff(hwmgr, 4163 (uint8_t *)(&activity_monitor), 4164 WORKLOAD_PPLIB_CUSTOM_BIT); 4165 data->is_custom_profile_set = true; 4166 PP_ASSERT_WITH_CODE(!result, 4167 "[SetPowerProfile] Failed to set activity monitor!", 4168 return result); 4169 } 4170 4171 out: 4172 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 4173 workload_type = 4174 conv_power_profile_to_pplib_workload(power_profile_mode); 4175 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, 4176 1 << workload_type, 4177 NULL); 4178 4179 hwmgr->power_profile_mode = power_profile_mode; 4180 4181 return 0; 4182 } 4183 4184 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, 4185 uint32_t virtual_addr_low, 4186 uint32_t virtual_addr_hi, 4187 uint32_t mc_addr_low, 4188 uint32_t mc_addr_hi, 4189 uint32_t size) 4190 { 4191 smum_send_msg_to_smc_with_parameter(hwmgr, 4192 PPSMC_MSG_SetSystemVirtualDramAddrHigh, 4193 virtual_addr_hi, 4194 NULL); 4195 smum_send_msg_to_smc_with_parameter(hwmgr, 4196 PPSMC_MSG_SetSystemVirtualDramAddrLow, 4197 virtual_addr_low, 4198 NULL); 4199 smum_send_msg_to_smc_with_parameter(hwmgr, 4200 PPSMC_MSG_DramLogSetDramAddrHigh, 4201 mc_addr_hi, 4202 NULL); 4203 4204 smum_send_msg_to_smc_with_parameter(hwmgr, 4205 PPSMC_MSG_DramLogSetDramAddrLow, 4206 mc_addr_low, 4207 NULL); 4208 4209 smum_send_msg_to_smc_with_parameter(hwmgr, 4210 PPSMC_MSG_DramLogSetDramSize, 4211 size, 4212 NULL); 4213 return 0; 4214 } 4215 4216 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, 4217 struct PP_TemperatureRange *thermal_data) 4218 { 4219 struct vega20_hwmgr *data = 4220 (struct vega20_hwmgr *)(hwmgr->backend); 4221 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 4222 4223 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); 4224 4225 thermal_data->max = pp_table->TedgeLimit * 4226 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4227 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * 4228 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4229 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * 4230 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4231 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * 4232 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4233 thermal_data->mem_crit_max = pp_table->ThbmLimit * 4234 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4235 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* 4236 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4237 4238 return 0; 4239 } 4240 4241 static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire) 4242 { 4243 int res; 4244 4245 /* I2C bus access can happen very early, when SMU not loaded yet */ 4246 if (!vega20_is_smc_ram_running(hwmgr)) 4247 return 0; 4248 4249 res = smum_send_msg_to_smc_with_parameter(hwmgr, 4250 (acquire ? 4251 PPSMC_MSG_RequestI2CBus : 4252 PPSMC_MSG_ReleaseI2CBus), 4253 0, 4254 NULL); 4255 4256 PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res); 4257 return res; 4258 } 4259 4260 static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr, 4261 enum pp_df_cstate state) 4262 { 4263 int ret; 4264 4265 /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */ 4266 if (hwmgr->smu_version < 0x283200) { 4267 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n"); 4268 return -EINVAL; 4269 } 4270 4271 ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state, 4272 NULL); 4273 if (ret) 4274 pr_err("SetDfCstate failed!\n"); 4275 4276 return ret; 4277 } 4278 4279 static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr, 4280 uint32_t pstate) 4281 { 4282 int ret; 4283 4284 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 4285 PPSMC_MSG_SetXgmiMode, 4286 pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, 4287 NULL); 4288 if (ret) 4289 pr_err("SetXgmiPstate failed!\n"); 4290 4291 return ret; 4292 } 4293 4294 static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) 4295 { 4296 memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); 4297 4298 gpu_metrics->common_header.structure_size = 4299 sizeof(struct gpu_metrics_v1_0); 4300 gpu_metrics->common_header.format_revision = 1; 4301 gpu_metrics->common_header.content_revision = 0; 4302 4303 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 4304 } 4305 4306 static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, 4307 void **table) 4308 { 4309 struct vega20_hwmgr *data = 4310 (struct vega20_hwmgr *)(hwmgr->backend); 4311 struct gpu_metrics_v1_0 *gpu_metrics = 4312 &data->gpu_metrics_table; 4313 SmuMetrics_t metrics; 4314 uint32_t fan_speed_rpm; 4315 int ret; 4316 4317 ret = vega20_get_metrics_table(hwmgr, &metrics, true); 4318 if (ret) 4319 return ret; 4320 4321 vega20_init_gpu_metrics_v1_0(gpu_metrics); 4322 4323 gpu_metrics->temperature_edge = metrics.TemperatureEdge; 4324 gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; 4325 gpu_metrics->temperature_mem = metrics.TemperatureHBM; 4326 gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; 4327 gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; 4328 gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; 4329 4330 gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; 4331 gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; 4332 4333 gpu_metrics->average_socket_power = metrics.AverageSocketPower; 4334 4335 gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; 4336 gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; 4337 gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; 4338 4339 gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; 4340 gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; 4341 gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; 4342 gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; 4343 gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; 4344 4345 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 4346 4347 vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); 4348 gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; 4349 4350 gpu_metrics->pcie_link_width = 4351 vega20_get_current_pcie_link_width(hwmgr); 4352 gpu_metrics->pcie_link_speed = 4353 vega20_get_current_pcie_link_speed(hwmgr); 4354 4355 *table = (void *)gpu_metrics; 4356 4357 return sizeof(struct gpu_metrics_v1_0); 4358 } 4359 4360 static const struct pp_hwmgr_func vega20_hwmgr_funcs = { 4361 /* init/fini related */ 4362 .backend_init = vega20_hwmgr_backend_init, 4363 .backend_fini = vega20_hwmgr_backend_fini, 4364 .asic_setup = vega20_setup_asic_task, 4365 .power_off_asic = vega20_power_off_asic, 4366 .dynamic_state_management_enable = vega20_enable_dpm_tasks, 4367 .dynamic_state_management_disable = vega20_disable_dpm_tasks, 4368 /* power state related */ 4369 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, 4370 .pre_display_config_changed = vega20_pre_display_configuration_changed_task, 4371 .display_config_changed = vega20_display_configuration_changed_task, 4372 .check_smc_update_required_for_display_configuration = 4373 vega20_check_smc_update_required_for_display_configuration, 4374 .notify_smc_display_config_after_ps_adjustment = 4375 vega20_notify_smc_display_config_after_ps_adjustment, 4376 /* export to DAL */ 4377 .get_sclk = vega20_dpm_get_sclk, 4378 .get_mclk = vega20_dpm_get_mclk, 4379 .get_dal_power_level = vega20_get_dal_power_level, 4380 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency, 4381 .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage, 4382 .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges, 4383 .display_clock_voltage_request = vega20_display_clock_voltage_request, 4384 .get_performance_level = vega20_get_performance_level, 4385 /* UMD pstate, profile related */ 4386 .force_dpm_level = vega20_dpm_force_dpm_level, 4387 .get_power_profile_mode = vega20_get_power_profile_mode, 4388 .set_power_profile_mode = vega20_set_power_profile_mode, 4389 /* od related */ 4390 .set_power_limit = vega20_set_power_limit, 4391 .get_sclk_od = vega20_get_sclk_od, 4392 .set_sclk_od = vega20_set_sclk_od, 4393 .get_mclk_od = vega20_get_mclk_od, 4394 .set_mclk_od = vega20_set_mclk_od, 4395 .odn_edit_dpm_table = vega20_odn_edit_dpm_table, 4396 /* for sysfs to retrive/set gfxclk/memclk */ 4397 .force_clock_level = vega20_force_clock_level, 4398 .print_clock_levels = vega20_print_clock_levels, 4399 .read_sensor = vega20_read_sensor, 4400 .get_ppfeature_status = vega20_get_ppfeature_status, 4401 .set_ppfeature_status = vega20_set_ppfeature_status, 4402 /* powergate related */ 4403 .powergate_uvd = vega20_power_gate_uvd, 4404 .powergate_vce = vega20_power_gate_vce, 4405 /* thermal related */ 4406 .start_thermal_controller = vega20_start_thermal_controller, 4407 .stop_thermal_controller = vega20_thermal_stop_thermal_controller, 4408 .get_thermal_temperature_range = vega20_get_thermal_temperature_range, 4409 .register_irq_handlers = smu9_register_irq_handlers, 4410 .disable_smc_firmware_ctf = vega20_thermal_disable_alert, 4411 /* fan control related */ 4412 .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent, 4413 .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent, 4414 .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info, 4415 .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm, 4416 .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm, 4417 .get_fan_control_mode = vega20_get_fan_control_mode, 4418 .set_fan_control_mode = vega20_set_fan_control_mode, 4419 /* smu memory related */ 4420 .notify_cac_buffer_info = vega20_notify_cac_buffer_info, 4421 .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost, 4422 /* BACO related */ 4423 .get_asic_baco_capability = vega20_baco_get_capability, 4424 .get_asic_baco_state = vega20_baco_get_state, 4425 .set_asic_baco_state = vega20_baco_set_state, 4426 .set_mp1_state = vega20_set_mp1_state, 4427 .smu_i2c_bus_access = vega20_smu_i2c_bus_access, 4428 .set_df_cstate = vega20_set_df_cstate, 4429 .set_xgmi_pstate = vega20_set_xgmi_pstate, 4430 .get_gpu_metrics = vega20_get_gpu_metrics, 4431 }; 4432 4433 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr) 4434 { 4435 hwmgr->hwmgr_func = &vega20_hwmgr_funcs; 4436 hwmgr->pptable_func = &vega20_pptable_funcs; 4437 4438 return 0; 4439 } 4440