0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/delay.h>
0025 #include <linux/fb.h>
0026 #include <linux/module.h>
0027 #include <linux/slab.h>
0028
0029 #include "hwmgr.h"
0030 #include "amd_powerplay.h"
0031 #include "vega20_smumgr.h"
0032 #include "hardwaremanager.h"
0033 #include "ppatomfwctrl.h"
0034 #include "atomfirmware.h"
0035 #include "cgs_common.h"
0036 #include "vega20_powertune.h"
0037 #include "vega20_inc.h"
0038 #include "pppcielanes.h"
0039 #include "vega20_hwmgr.h"
0040 #include "vega20_processpptables.h"
0041 #include "vega20_pptable.h"
0042 #include "vega20_thermal.h"
0043 #include "vega20_ppsmc.h"
0044 #include "pp_debug.h"
0045 #include "amd_pcie_helpers.h"
0046 #include "ppinterrupt.h"
0047 #include "pp_overdriver.h"
0048 #include "pp_thermal.h"
0049 #include "soc15_common.h"
0050 #include "vega20_baco.h"
0051 #include "smuio/smuio_9_0_offset.h"
0052 #include "smuio/smuio_9_0_sh_mask.h"
0053 #include "nbio/nbio_7_4_sh_mask.h"
0054
0055 #define smnPCIE_LC_SPEED_CNTL 0x11140290
0056 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288
0057
0058 #define LINK_WIDTH_MAX 6
0059 #define LINK_SPEED_MAX 3
0060 static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
0061 static const int link_speed[] = {25, 50, 80, 160};
0062
0063 static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
0064 {
0065 struct vega20_hwmgr *data =
0066 (struct vega20_hwmgr *)(hwmgr->backend);
0067
0068 data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT;
0069 data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT;
0070 data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT;
0071 data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT;
0072 data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT;
0073
0074 data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT;
0075 data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0076 data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0077 data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0078 data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0079 data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0080 data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0081 data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0082 data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0083 data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0084 data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0085 data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0086 data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 data->registry_data.disallowed_features = 0xE0041C00;
0099
0100 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version);
0101 if (hwmgr->smu_version < 0x282100)
0102 data->registry_data.disallowed_features |= FEATURE_ECC_MASK;
0103
0104 if (!(hwmgr->feature_mask & PP_PCIE_DPM_MASK))
0105 data->registry_data.disallowed_features |= FEATURE_DPM_LINK_MASK;
0106
0107 if (!(hwmgr->feature_mask & PP_SCLK_DPM_MASK))
0108 data->registry_data.disallowed_features |= FEATURE_DPM_GFXCLK_MASK;
0109
0110 if (!(hwmgr->feature_mask & PP_SOCCLK_DPM_MASK))
0111 data->registry_data.disallowed_features |= FEATURE_DPM_SOCCLK_MASK;
0112
0113 if (!(hwmgr->feature_mask & PP_MCLK_DPM_MASK))
0114 data->registry_data.disallowed_features |= FEATURE_DPM_UCLK_MASK;
0115
0116 if (!(hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK))
0117 data->registry_data.disallowed_features |= FEATURE_DPM_DCEFCLK_MASK;
0118
0119 if (!(hwmgr->feature_mask & PP_ULV_MASK))
0120 data->registry_data.disallowed_features |= FEATURE_ULV_MASK;
0121
0122 if (!(hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK))
0123 data->registry_data.disallowed_features |= FEATURE_DS_GFXCLK_MASK;
0124
0125 data->registry_data.od_state_in_dc_support = 0;
0126 data->registry_data.thermal_support = 1;
0127 data->registry_data.skip_baco_hardware = 0;
0128
0129 data->registry_data.log_avfs_param = 0;
0130 data->registry_data.sclk_throttle_low_notification = 1;
0131 data->registry_data.force_dpm_high = 0;
0132 data->registry_data.stable_pstate_sclk_dpm_percentage = 75;
0133
0134 data->registry_data.didt_support = 0;
0135 if (data->registry_data.didt_support) {
0136 data->registry_data.didt_mode = 6;
0137 data->registry_data.sq_ramping_support = 1;
0138 data->registry_data.db_ramping_support = 0;
0139 data->registry_data.td_ramping_support = 0;
0140 data->registry_data.tcp_ramping_support = 0;
0141 data->registry_data.dbr_ramping_support = 0;
0142 data->registry_data.edc_didt_support = 1;
0143 data->registry_data.gc_didt_support = 0;
0144 data->registry_data.psm_didt_support = 0;
0145 }
0146
0147 data->registry_data.pcie_lane_override = 0xff;
0148 data->registry_data.pcie_speed_override = 0xff;
0149 data->registry_data.pcie_clock_override = 0xffffffff;
0150 data->registry_data.regulator_hot_gpio_support = 1;
0151 data->registry_data.ac_dc_switch_gpio_support = 0;
0152 data->registry_data.quick_transition_support = 0;
0153 data->registry_data.zrpm_start_temp = 0xffff;
0154 data->registry_data.zrpm_stop_temp = 0xffff;
0155 data->registry_data.od8_feature_enable = 1;
0156 data->registry_data.disable_water_mark = 0;
0157 data->registry_data.disable_pp_tuning = 0;
0158 data->registry_data.disable_xlpp_tuning = 0;
0159 data->registry_data.disable_workload_policy = 0;
0160 data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F;
0161 data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919;
0162 data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A;
0163 data->registry_data.force_workload_policy_mask = 0;
0164 data->registry_data.disable_3d_fs_detection = 0;
0165 data->registry_data.fps_support = 1;
0166 data->registry_data.disable_auto_wattman = 1;
0167 data->registry_data.auto_wattman_debug = 0;
0168 data->registry_data.auto_wattman_sample_period = 100;
0169 data->registry_data.fclk_gfxclk_ratio = 0;
0170 data->registry_data.auto_wattman_threshold = 50;
0171 data->registry_data.gfxoff_controlled_by_driver = 1;
0172 data->gfxoff_allowed = false;
0173 data->counter_gfxoff = 0;
0174 data->registry_data.pcie_dpm_key_disabled = !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
0175 }
0176
0177 static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr)
0178 {
0179 struct vega20_hwmgr *data =
0180 (struct vega20_hwmgr *)(hwmgr->backend);
0181 struct amdgpu_device *adev = hwmgr->adev;
0182
0183 if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE)
0184 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0185 PHM_PlatformCaps_ControlVDDCI);
0186
0187 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0188 PHM_PlatformCaps_TablelessHardwareInterface);
0189
0190 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0191 PHM_PlatformCaps_BACO);
0192
0193 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0194 PHM_PlatformCaps_EnableSMU7ThermalManagement);
0195
0196 if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
0197 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0198 PHM_PlatformCaps_UVDPowerGating);
0199
0200 if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
0201 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0202 PHM_PlatformCaps_VCEPowerGating);
0203
0204 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0205 PHM_PlatformCaps_UnTabledHardwareInterface);
0206
0207 if (data->registry_data.od8_feature_enable)
0208 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0209 PHM_PlatformCaps_OD8inACSupport);
0210
0211 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0212 PHM_PlatformCaps_ActivityReporting);
0213 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0214 PHM_PlatformCaps_FanSpeedInTableIsRPM);
0215
0216 if (data->registry_data.od_state_in_dc_support) {
0217 if (data->registry_data.od8_feature_enable)
0218 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0219 PHM_PlatformCaps_OD8inDCSupport);
0220 }
0221
0222 if (data->registry_data.thermal_support &&
0223 data->registry_data.fuzzy_fan_control_support &&
0224 hwmgr->thermal_controller.advanceFanControlParameters.usTMax)
0225 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0226 PHM_PlatformCaps_ODFuzzyFanControlSupport);
0227
0228 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0229 PHM_PlatformCaps_DynamicPowerManagement);
0230 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0231 PHM_PlatformCaps_SMC);
0232 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0233 PHM_PlatformCaps_ThermalPolicyDelay);
0234
0235 if (data->registry_data.force_dpm_high)
0236 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0237 PHM_PlatformCaps_ExclusiveModeAlwaysHigh);
0238
0239 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0240 PHM_PlatformCaps_DynamicUVDState);
0241
0242 if (data->registry_data.sclk_throttle_low_notification)
0243 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0244 PHM_PlatformCaps_SclkThrottleLowNotification);
0245
0246
0247
0248 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0249 PHM_PlatformCaps_PowerContainment);
0250 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0251 PHM_PlatformCaps_DiDtSupport);
0252 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0253 PHM_PlatformCaps_SQRamping);
0254 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0255 PHM_PlatformCaps_DBRamping);
0256 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0257 PHM_PlatformCaps_TDRamping);
0258 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0259 PHM_PlatformCaps_TCPRamping);
0260 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0261 PHM_PlatformCaps_DBRRamping);
0262 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0263 PHM_PlatformCaps_DiDtEDCEnable);
0264 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0265 PHM_PlatformCaps_GCEDC);
0266 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0267 PHM_PlatformCaps_PSM);
0268
0269 if (data->registry_data.didt_support) {
0270 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0271 PHM_PlatformCaps_DiDtSupport);
0272 if (data->registry_data.sq_ramping_support)
0273 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0274 PHM_PlatformCaps_SQRamping);
0275 if (data->registry_data.db_ramping_support)
0276 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0277 PHM_PlatformCaps_DBRamping);
0278 if (data->registry_data.td_ramping_support)
0279 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0280 PHM_PlatformCaps_TDRamping);
0281 if (data->registry_data.tcp_ramping_support)
0282 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0283 PHM_PlatformCaps_TCPRamping);
0284 if (data->registry_data.dbr_ramping_support)
0285 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0286 PHM_PlatformCaps_DBRRamping);
0287 if (data->registry_data.edc_didt_support)
0288 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0289 PHM_PlatformCaps_DiDtEDCEnable);
0290 if (data->registry_data.gc_didt_support)
0291 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0292 PHM_PlatformCaps_GCEDC);
0293 if (data->registry_data.psm_didt_support)
0294 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0295 PHM_PlatformCaps_PSM);
0296 }
0297
0298 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0299 PHM_PlatformCaps_RegulatorHot);
0300
0301 if (data->registry_data.ac_dc_switch_gpio_support) {
0302 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0303 PHM_PlatformCaps_AutomaticDCTransition);
0304 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0305 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
0306 }
0307
0308 if (data->registry_data.quick_transition_support) {
0309 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0310 PHM_PlatformCaps_AutomaticDCTransition);
0311 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0312 PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme);
0313 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0314 PHM_PlatformCaps_Falcon_QuickTransition);
0315 }
0316
0317 if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) {
0318 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
0319 PHM_PlatformCaps_LowestUclkReservedForUlv);
0320 if (data->lowest_uclk_reserved_for_ulv == 1)
0321 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0322 PHM_PlatformCaps_LowestUclkReservedForUlv);
0323 }
0324
0325 if (data->registry_data.custom_fan_support)
0326 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0327 PHM_PlatformCaps_CustomFanControlSupport);
0328
0329 return 0;
0330 }
0331
0332 static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr)
0333 {
0334 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
0335 struct amdgpu_device *adev = hwmgr->adev;
0336 uint32_t top32, bottom32;
0337 int i;
0338
0339 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id =
0340 FEATURE_DPM_PREFETCHER_BIT;
0341 data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id =
0342 FEATURE_DPM_GFXCLK_BIT;
0343 data->smu_features[GNLD_DPM_UCLK].smu_feature_id =
0344 FEATURE_DPM_UCLK_BIT;
0345 data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id =
0346 FEATURE_DPM_SOCCLK_BIT;
0347 data->smu_features[GNLD_DPM_UVD].smu_feature_id =
0348 FEATURE_DPM_UVD_BIT;
0349 data->smu_features[GNLD_DPM_VCE].smu_feature_id =
0350 FEATURE_DPM_VCE_BIT;
0351 data->smu_features[GNLD_ULV].smu_feature_id =
0352 FEATURE_ULV_BIT;
0353 data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id =
0354 FEATURE_DPM_MP0CLK_BIT;
0355 data->smu_features[GNLD_DPM_LINK].smu_feature_id =
0356 FEATURE_DPM_LINK_BIT;
0357 data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id =
0358 FEATURE_DPM_DCEFCLK_BIT;
0359 data->smu_features[GNLD_DS_GFXCLK].smu_feature_id =
0360 FEATURE_DS_GFXCLK_BIT;
0361 data->smu_features[GNLD_DS_SOCCLK].smu_feature_id =
0362 FEATURE_DS_SOCCLK_BIT;
0363 data->smu_features[GNLD_DS_LCLK].smu_feature_id =
0364 FEATURE_DS_LCLK_BIT;
0365 data->smu_features[GNLD_PPT].smu_feature_id =
0366 FEATURE_PPT_BIT;
0367 data->smu_features[GNLD_TDC].smu_feature_id =
0368 FEATURE_TDC_BIT;
0369 data->smu_features[GNLD_THERMAL].smu_feature_id =
0370 FEATURE_THERMAL_BIT;
0371 data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id =
0372 FEATURE_GFX_PER_CU_CG_BIT;
0373 data->smu_features[GNLD_RM].smu_feature_id =
0374 FEATURE_RM_BIT;
0375 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id =
0376 FEATURE_DS_DCEFCLK_BIT;
0377 data->smu_features[GNLD_ACDC].smu_feature_id =
0378 FEATURE_ACDC_BIT;
0379 data->smu_features[GNLD_VR0HOT].smu_feature_id =
0380 FEATURE_VR0HOT_BIT;
0381 data->smu_features[GNLD_VR1HOT].smu_feature_id =
0382 FEATURE_VR1HOT_BIT;
0383 data->smu_features[GNLD_FW_CTF].smu_feature_id =
0384 FEATURE_FW_CTF_BIT;
0385 data->smu_features[GNLD_LED_DISPLAY].smu_feature_id =
0386 FEATURE_LED_DISPLAY_BIT;
0387 data->smu_features[GNLD_FAN_CONTROL].smu_feature_id =
0388 FEATURE_FAN_CONTROL_BIT;
0389 data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
0390 data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT;
0391 data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT;
0392 data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT;
0393 data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT;
0394 data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT;
0395 data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT;
0396 data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT;
0397 data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT;
0398
0399 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
0400 data->smu_features[i].smu_feature_bitmap =
0401 (uint64_t)(1ULL << data->smu_features[i].smu_feature_id);
0402 data->smu_features[i].allowed =
0403 ((data->registry_data.disallowed_features >> i) & 1) ?
0404 false : true;
0405 }
0406
0407
0408 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32);
0409 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32);
0410
0411 adev->unique_id = ((uint64_t)bottom32 << 32) | top32;
0412 }
0413
0414 static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
0415 {
0416 return 0;
0417 }
0418
0419 static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
0420 {
0421 kfree(hwmgr->backend);
0422 hwmgr->backend = NULL;
0423
0424 return 0;
0425 }
0426
0427 static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
0428 {
0429 struct vega20_hwmgr *data;
0430 struct amdgpu_device *adev = hwmgr->adev;
0431
0432 data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL);
0433 if (data == NULL)
0434 return -ENOMEM;
0435
0436 hwmgr->backend = data;
0437
0438 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
0439 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
0440 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
0441
0442 vega20_set_default_registry_data(hwmgr);
0443
0444 data->disable_dpm_mask = 0xff;
0445
0446
0447 data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE;
0448 data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE;
0449 data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE;
0450
0451 data->water_marks_bitmap = 0;
0452 data->avfs_exist = false;
0453
0454 vega20_set_features_platform_caps(hwmgr);
0455
0456 vega20_init_dpm_defaults(hwmgr);
0457
0458
0459 vega20_set_private_data_based_on_pptable(hwmgr);
0460
0461 data->is_tlu_enabled = false;
0462
0463 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
0464 VEGA20_MAX_HARDWARE_POWERLEVELS;
0465 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
0466 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
0467
0468 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400;
0469
0470 hwmgr->platform_descriptor.clockStep.engineClock = 500;
0471 hwmgr->platform_descriptor.clockStep.memoryClock = 500;
0472
0473 data->total_active_cus = adev->gfx.cu_info.number;
0474 data->is_custom_profile_set = false;
0475
0476 return 0;
0477 }
0478
0479 static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr)
0480 {
0481 struct vega20_hwmgr *data =
0482 (struct vega20_hwmgr *)(hwmgr->backend);
0483
0484 data->low_sclk_interrupt_threshold = 0;
0485
0486 return 0;
0487 }
0488
0489 static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr)
0490 {
0491 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
0492 int ret = 0;
0493 bool use_baco = (amdgpu_in_reset(adev) &&
0494 (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
0495 (adev->in_runpm && amdgpu_asic_supports_baco(adev));
0496
0497 ret = vega20_init_sclk_threshold(hwmgr);
0498 PP_ASSERT_WITH_CODE(!ret,
0499 "Failed to init sclk threshold!",
0500 return ret);
0501
0502 if (use_baco) {
0503 ret = vega20_baco_apply_vdci_flush_workaround(hwmgr);
0504 if (ret)
0505 pr_err("Failed to apply vega20 baco workaround!\n");
0506 }
0507
0508 return ret;
0509 }
0510
0511
0512
0513
0514
0515
0516
0517
0518 static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state)
0519 {
0520 dpm_state->soft_min_level = 0x0;
0521 dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT;
0522 dpm_state->hard_min_level = 0x0;
0523 dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT;
0524 }
0525
0526 static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr,
0527 PPCLK_e clk_id, uint32_t *num_of_levels)
0528 {
0529 int ret = 0;
0530
0531 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0532 PPSMC_MSG_GetDpmFreqByIndex,
0533 (clk_id << 16 | 0xFF),
0534 num_of_levels);
0535 PP_ASSERT_WITH_CODE(!ret,
0536 "[GetNumOfDpmLevel] failed to get dpm levels!",
0537 return ret);
0538
0539 return ret;
0540 }
0541
0542 static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr,
0543 PPCLK_e clk_id, uint32_t index, uint32_t *clk)
0544 {
0545 int ret = 0;
0546
0547 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0548 PPSMC_MSG_GetDpmFreqByIndex,
0549 (clk_id << 16 | index),
0550 clk);
0551 PP_ASSERT_WITH_CODE(!ret,
0552 "[GetDpmFreqByIndex] failed to get dpm freq by index!",
0553 return ret);
0554
0555 return ret;
0556 }
0557
0558 static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
0559 struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id)
0560 {
0561 int ret = 0;
0562 uint32_t i, num_of_levels, clk;
0563
0564 ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels);
0565 PP_ASSERT_WITH_CODE(!ret,
0566 "[SetupSingleDpmTable] failed to get clk levels!",
0567 return ret);
0568
0569 dpm_table->count = num_of_levels;
0570
0571 for (i = 0; i < num_of_levels; i++) {
0572 ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk);
0573 PP_ASSERT_WITH_CODE(!ret,
0574 "[SetupSingleDpmTable] failed to get clk of specific level!",
0575 return ret);
0576 dpm_table->dpm_levels[i].value = clk;
0577 dpm_table->dpm_levels[i].enabled = true;
0578 }
0579
0580 return ret;
0581 }
0582
0583 static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr)
0584 {
0585 struct vega20_hwmgr *data =
0586 (struct vega20_hwmgr *)(hwmgr->backend);
0587 struct vega20_single_dpm_table *dpm_table;
0588 int ret = 0;
0589
0590 dpm_table = &(data->dpm_table.gfx_table);
0591 if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
0592 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
0593 PP_ASSERT_WITH_CODE(!ret,
0594 "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
0595 return ret);
0596 } else {
0597 dpm_table->count = 1;
0598 dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
0599 }
0600
0601 return ret;
0602 }
0603
0604 static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr)
0605 {
0606 struct vega20_hwmgr *data =
0607 (struct vega20_hwmgr *)(hwmgr->backend);
0608 struct vega20_single_dpm_table *dpm_table;
0609 int ret = 0;
0610
0611 dpm_table = &(data->dpm_table.mem_table);
0612 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
0613 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
0614 PP_ASSERT_WITH_CODE(!ret,
0615 "[SetupDefaultDpmTable] failed to get memclk dpm levels!",
0616 return ret);
0617 } else {
0618 dpm_table->count = 1;
0619 dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
0620 }
0621
0622 return ret;
0623 }
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633 static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
0634 {
0635 struct vega20_hwmgr *data =
0636 (struct vega20_hwmgr *)(hwmgr->backend);
0637 struct vega20_single_dpm_table *dpm_table;
0638 int ret = 0;
0639
0640 memset(&data->dpm_table, 0, sizeof(data->dpm_table));
0641
0642
0643 dpm_table = &(data->dpm_table.soc_table);
0644 if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
0645 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK);
0646 PP_ASSERT_WITH_CODE(!ret,
0647 "[SetupDefaultDpmTable] failed to get socclk dpm levels!",
0648 return ret);
0649 } else {
0650 dpm_table->count = 1;
0651 dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100;
0652 }
0653 vega20_init_dpm_state(&(dpm_table->dpm_state));
0654
0655
0656 dpm_table = &(data->dpm_table.gfx_table);
0657 ret = vega20_setup_gfxclk_dpm_table(hwmgr);
0658 if (ret)
0659 return ret;
0660 vega20_init_dpm_state(&(dpm_table->dpm_state));
0661
0662
0663 dpm_table = &(data->dpm_table.mem_table);
0664 ret = vega20_setup_memclk_dpm_table(hwmgr);
0665 if (ret)
0666 return ret;
0667 vega20_init_dpm_state(&(dpm_table->dpm_state));
0668
0669
0670 dpm_table = &(data->dpm_table.eclk_table);
0671 if (data->smu_features[GNLD_DPM_VCE].enabled) {
0672 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK);
0673 PP_ASSERT_WITH_CODE(!ret,
0674 "[SetupDefaultDpmTable] failed to get eclk dpm levels!",
0675 return ret);
0676 } else {
0677 dpm_table->count = 1;
0678 dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100;
0679 }
0680 vega20_init_dpm_state(&(dpm_table->dpm_state));
0681
0682
0683 dpm_table = &(data->dpm_table.vclk_table);
0684 if (data->smu_features[GNLD_DPM_UVD].enabled) {
0685 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK);
0686 PP_ASSERT_WITH_CODE(!ret,
0687 "[SetupDefaultDpmTable] failed to get vclk dpm levels!",
0688 return ret);
0689 } else {
0690 dpm_table->count = 1;
0691 dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100;
0692 }
0693 vega20_init_dpm_state(&(dpm_table->dpm_state));
0694
0695
0696 dpm_table = &(data->dpm_table.dclk_table);
0697 if (data->smu_features[GNLD_DPM_UVD].enabled) {
0698 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK);
0699 PP_ASSERT_WITH_CODE(!ret,
0700 "[SetupDefaultDpmTable] failed to get dclk dpm levels!",
0701 return ret);
0702 } else {
0703 dpm_table->count = 1;
0704 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100;
0705 }
0706 vega20_init_dpm_state(&(dpm_table->dpm_state));
0707
0708
0709 dpm_table = &(data->dpm_table.dcef_table);
0710 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
0711 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK);
0712 PP_ASSERT_WITH_CODE(!ret,
0713 "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!",
0714 return ret);
0715 } else {
0716 dpm_table->count = 1;
0717 dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100;
0718 }
0719 vega20_init_dpm_state(&(dpm_table->dpm_state));
0720
0721
0722 dpm_table = &(data->dpm_table.pixel_table);
0723 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
0724 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK);
0725 PP_ASSERT_WITH_CODE(!ret,
0726 "[SetupDefaultDpmTable] failed to get pixclk dpm levels!",
0727 return ret);
0728 } else
0729 dpm_table->count = 0;
0730 vega20_init_dpm_state(&(dpm_table->dpm_state));
0731
0732
0733 dpm_table = &(data->dpm_table.display_table);
0734 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
0735 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK);
0736 PP_ASSERT_WITH_CODE(!ret,
0737 "[SetupDefaultDpmTable] failed to get dispclk dpm levels!",
0738 return ret);
0739 } else
0740 dpm_table->count = 0;
0741 vega20_init_dpm_state(&(dpm_table->dpm_state));
0742
0743
0744 dpm_table = &(data->dpm_table.phy_table);
0745 if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) {
0746 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK);
0747 PP_ASSERT_WITH_CODE(!ret,
0748 "[SetupDefaultDpmTable] failed to get phyclk dpm levels!",
0749 return ret);
0750 } else
0751 dpm_table->count = 0;
0752 vega20_init_dpm_state(&(dpm_table->dpm_state));
0753
0754
0755 dpm_table = &(data->dpm_table.fclk_table);
0756 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
0757 ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK);
0758 PP_ASSERT_WITH_CODE(!ret,
0759 "[SetupDefaultDpmTable] failed to get fclk dpm levels!",
0760 return ret);
0761 } else {
0762 dpm_table->count = 1;
0763 dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100;
0764 }
0765 vega20_init_dpm_state(&(dpm_table->dpm_state));
0766
0767
0768 memcpy(&(data->golden_dpm_table), &(data->dpm_table),
0769 sizeof(struct vega20_dpm_table));
0770
0771 return 0;
0772 }
0773
0774
0775
0776
0777
0778
0779
0780 static int vega20_init_smc_table(struct pp_hwmgr *hwmgr)
0781 {
0782 int result;
0783 struct vega20_hwmgr *data =
0784 (struct vega20_hwmgr *)(hwmgr->backend);
0785 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
0786 struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
0787 struct phm_ppt_v3_information *pptable_information =
0788 (struct phm_ppt_v3_information *)hwmgr->pptable;
0789
0790 result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
0791 PP_ASSERT_WITH_CODE(!result,
0792 "[InitSMCTable] Failed to get vbios bootup values!",
0793 return result);
0794
0795 data->vbios_boot_state.vddc = boot_up_values.usVddc;
0796 data->vbios_boot_state.vddci = boot_up_values.usVddci;
0797 data->vbios_boot_state.mvddc = boot_up_values.usMvddc;
0798 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
0799 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
0800 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
0801 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk;
0802 data->vbios_boot_state.eclock = boot_up_values.ulEClk;
0803 data->vbios_boot_state.vclock = boot_up_values.ulVClk;
0804 data->vbios_boot_state.dclock = boot_up_values.ulDClk;
0805 data->vbios_boot_state.fclock = boot_up_values.ulFClk;
0806 data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID;
0807
0808 smum_send_msg_to_smc_with_parameter(hwmgr,
0809 PPSMC_MSG_SetMinDeepSleepDcefclk,
0810 (uint32_t)(data->vbios_boot_state.dcef_clock / 100),
0811 NULL);
0812
0813 memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t));
0814
0815 result = smum_smc_table_manager(hwmgr,
0816 (uint8_t *)pp_table, TABLE_PPTABLE, false);
0817 PP_ASSERT_WITH_CODE(!result,
0818 "[InitSMCTable] Failed to upload PPtable!",
0819 return result);
0820
0821 return 0;
0822 }
0823
0824
0825
0826
0827
0828
0829
0830 static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr)
0831 {
0832 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
0833 struct vega20_hwmgr *data =
0834 (struct vega20_hwmgr *)(hwmgr->backend);
0835 uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg, pcie_gen_arg, pcie_width_arg;
0836 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
0837 int i;
0838 int ret;
0839
0840 if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
0841 pcie_gen = 3;
0842 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
0843 pcie_gen = 2;
0844 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
0845 pcie_gen = 1;
0846 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1)
0847 pcie_gen = 0;
0848
0849 if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
0850 pcie_width = 6;
0851 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
0852 pcie_width = 5;
0853 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8)
0854 pcie_width = 4;
0855 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4)
0856 pcie_width = 3;
0857 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2)
0858 pcie_width = 2;
0859 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1)
0860 pcie_width = 1;
0861
0862
0863
0864
0865
0866 for (i = 0; i < NUM_LINK_LEVELS; i++) {
0867 pcie_gen_arg = (pp_table->PcieGenSpeed[i] > pcie_gen) ? pcie_gen :
0868 pp_table->PcieGenSpeed[i];
0869 pcie_width_arg = (pp_table->PcieLaneCount[i] > pcie_width) ? pcie_width :
0870 pp_table->PcieLaneCount[i];
0871
0872 if (pcie_gen_arg != pp_table->PcieGenSpeed[i] || pcie_width_arg !=
0873 pp_table->PcieLaneCount[i]) {
0874 smu_pcie_arg = (i << 16) | (pcie_gen_arg << 8) | pcie_width_arg;
0875 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0876 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
0877 NULL);
0878 PP_ASSERT_WITH_CODE(!ret,
0879 "[OverridePcieParameters] Attempt to override pcie params failed!",
0880 return ret);
0881 }
0882
0883
0884 pp_table->PcieGenSpeed[i] = pcie_gen_arg;
0885 pp_table->PcieLaneCount[i] = pcie_width_arg;
0886 }
0887
0888
0889 if (data->registry_data.pcie_dpm_key_disabled) {
0890 for (i = 0; i < NUM_LINK_LEVELS; i++) {
0891 smu_pcie_arg = (i << 16) | (pcie_gen << 8) | pcie_width;
0892 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0893 PPSMC_MSG_OverridePcieParameters, smu_pcie_arg,
0894 NULL);
0895 PP_ASSERT_WITH_CODE(!ret,
0896 "[OverridePcieParameters] Attempt to override pcie params failed!",
0897 return ret);
0898
0899 pp_table->PcieGenSpeed[i] = pcie_gen;
0900 pp_table->PcieLaneCount[i] = pcie_width;
0901 }
0902 ret = vega20_enable_smc_features(hwmgr,
0903 false,
0904 data->smu_features[GNLD_DPM_LINK].smu_feature_bitmap);
0905 PP_ASSERT_WITH_CODE(!ret,
0906 "Attempt to Disable DPM LINK Failed!",
0907 return ret);
0908 data->smu_features[GNLD_DPM_LINK].enabled = false;
0909 data->smu_features[GNLD_DPM_LINK].supported = false;
0910 }
0911
0912 return 0;
0913 }
0914
0915 static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
0916 {
0917 struct vega20_hwmgr *data =
0918 (struct vega20_hwmgr *)(hwmgr->backend);
0919 uint32_t allowed_features_low = 0, allowed_features_high = 0;
0920 int i;
0921 int ret = 0;
0922
0923 for (i = 0; i < GNLD_FEATURES_MAX; i++)
0924 if (data->smu_features[i].allowed)
0925 data->smu_features[i].smu_feature_id > 31 ?
0926 (allowed_features_high |=
0927 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT)
0928 & 0xFFFFFFFF)) :
0929 (allowed_features_low |=
0930 ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT)
0931 & 0xFFFFFFFF));
0932
0933 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0934 PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, NULL);
0935 PP_ASSERT_WITH_CODE(!ret,
0936 "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!",
0937 return ret);
0938
0939 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
0940 PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, NULL);
0941 PP_ASSERT_WITH_CODE(!ret,
0942 "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!",
0943 return ret);
0944
0945 return 0;
0946 }
0947
0948 static int vega20_run_btc(struct pp_hwmgr *hwmgr)
0949 {
0950 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc, NULL);
0951 }
0952
0953 static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr)
0954 {
0955 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc, NULL);
0956 }
0957
0958 static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr)
0959 {
0960 struct vega20_hwmgr *data =
0961 (struct vega20_hwmgr *)(hwmgr->backend);
0962 uint64_t features_enabled;
0963 int i;
0964 bool enabled;
0965 int ret = 0;
0966
0967 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
0968 PPSMC_MSG_EnableAllSmuFeatures,
0969 NULL)) == 0,
0970 "[EnableAllSMUFeatures] Failed to enable all smu features!",
0971 return ret);
0972
0973 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
0974 PP_ASSERT_WITH_CODE(!ret,
0975 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
0976 return ret);
0977
0978 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
0979 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
0980 true : false;
0981 data->smu_features[i].enabled = enabled;
0982 data->smu_features[i].supported = enabled;
0983
0984 #if 0
0985 if (data->smu_features[i].allowed && !enabled)
0986 pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i);
0987 else if (!data->smu_features[i].allowed && enabled)
0988 pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i);
0989 #endif
0990 }
0991
0992 return 0;
0993 }
0994
0995 static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr)
0996 {
0997 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
0998
0999 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
1248 vega20_od8_set_feature_capabilities(hwmgr);
1249
1250
1251 vega20_od8_set_feature_id(hwmgr);
1252
1253
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
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
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
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
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
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
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
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
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
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
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
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_pwm(hwmgr, 255);
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
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
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 phm_get_sysfs_buf(&buf, &size);
3242
3243 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3244 PP_ASSERT_WITH_CODE(!ret,
3245 "[EnableAllSmuFeatures] Failed to get enabled smc features!",
3246 return ret);
3247
3248 size += sysfs_emit_at(buf, size, "Current ppfeatures: 0x%016llx\n", features_enabled);
3249 size += sysfs_emit_at(buf, size, "%-19s %-22s %s\n",
3250 output_title[0],
3251 output_title[1],
3252 output_title[2]);
3253 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
3254 size += sysfs_emit_at(buf, size, "%-19s 0x%016llx %6s\n",
3255 ppfeature_name[i],
3256 1ULL << i,
3257 (features_enabled & (1ULL << i)) ? "Y" : "N");
3258 }
3259
3260 return size;
3261 }
3262
3263 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
3264 {
3265 struct vega20_hwmgr *data =
3266 (struct vega20_hwmgr *)(hwmgr->backend);
3267 uint64_t features_enabled, features_to_enable, features_to_disable;
3268 int i, ret = 0;
3269 bool enabled;
3270
3271 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
3272 return -EINVAL;
3273
3274 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3275 if (ret)
3276 return ret;
3277
3278 features_to_disable =
3279 features_enabled & ~new_ppfeature_masks;
3280 features_to_enable =
3281 ~features_enabled & new_ppfeature_masks;
3282
3283 pr_debug("features_to_disable 0x%llx\n", features_to_disable);
3284 pr_debug("features_to_enable 0x%llx\n", features_to_enable);
3285
3286 if (features_to_disable) {
3287 ret = vega20_enable_smc_features(hwmgr, false, features_to_disable);
3288 if (ret)
3289 return ret;
3290 }
3291
3292 if (features_to_enable) {
3293 ret = vega20_enable_smc_features(hwmgr, true, features_to_enable);
3294 if (ret)
3295 return ret;
3296 }
3297
3298
3299 ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
3300 if (ret)
3301 return ret;
3302
3303 for (i = 0; i < GNLD_FEATURES_MAX; i++) {
3304 enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
3305 true : false;
3306 data->smu_features[i].enabled = enabled;
3307 }
3308
3309 return 0;
3310 }
3311
3312 static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr)
3313 {
3314 struct amdgpu_device *adev = hwmgr->adev;
3315
3316 return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
3317 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
3318 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
3319 }
3320
3321 static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr)
3322 {
3323 uint32_t width_level;
3324
3325 width_level = vega20_get_current_pcie_link_width_level(hwmgr);
3326 if (width_level > LINK_WIDTH_MAX)
3327 width_level = 0;
3328
3329 return link_width[width_level];
3330 }
3331
3332 static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr)
3333 {
3334 struct amdgpu_device *adev = hwmgr->adev;
3335
3336 return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
3337 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
3338 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
3339 }
3340
3341 static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr)
3342 {
3343 uint32_t speed_level;
3344
3345 speed_level = vega20_get_current_pcie_link_speed_level(hwmgr);
3346 if (speed_level > LINK_SPEED_MAX)
3347 speed_level = 0;
3348
3349 return link_speed[speed_level];
3350 }
3351
3352 static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
3353 enum pp_clock_type type, char *buf)
3354 {
3355 struct vega20_hwmgr *data =
3356 (struct vega20_hwmgr *)(hwmgr->backend);
3357 struct vega20_od8_single_setting *od8_settings =
3358 data->od8_settings.od8_settings_array;
3359 OverDriveTable_t *od_table =
3360 &(data->smc_state_table.overdrive_table);
3361 PPTable_t *pptable = &(data->smc_state_table.pp_table);
3362 struct pp_clock_levels_with_latency clocks;
3363 struct vega20_single_dpm_table *fclk_dpm_table =
3364 &(data->dpm_table.fclk_table);
3365 int i, now, size = 0;
3366 int ret = 0;
3367 uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width;
3368
3369 switch (type) {
3370 case PP_SCLK:
3371 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now);
3372 PP_ASSERT_WITH_CODE(!ret,
3373 "Attempt to get current gfx clk Failed!",
3374 return ret);
3375
3376 if (vega20_get_sclks(hwmgr, &clocks)) {
3377 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3378 now / 100);
3379 break;
3380 }
3381
3382 for (i = 0; i < clocks.num_levels; i++)
3383 size += sprintf(buf + size, "%d: %uMhz %s\n",
3384 i, clocks.data[i].clocks_in_khz / 1000,
3385 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3386 break;
3387
3388 case PP_MCLK:
3389 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now);
3390 PP_ASSERT_WITH_CODE(!ret,
3391 "Attempt to get current mclk freq Failed!",
3392 return ret);
3393
3394 if (vega20_get_memclocks(hwmgr, &clocks)) {
3395 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3396 now / 100);
3397 break;
3398 }
3399
3400 for (i = 0; i < clocks.num_levels; i++)
3401 size += sprintf(buf + size, "%d: %uMhz %s\n",
3402 i, clocks.data[i].clocks_in_khz / 1000,
3403 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3404 break;
3405
3406 case PP_SOCCLK:
3407 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now);
3408 PP_ASSERT_WITH_CODE(!ret,
3409 "Attempt to get current socclk freq Failed!",
3410 return ret);
3411
3412 if (vega20_get_socclocks(hwmgr, &clocks)) {
3413 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3414 now / 100);
3415 break;
3416 }
3417
3418 for (i = 0; i < clocks.num_levels; i++)
3419 size += sprintf(buf + size, "%d: %uMhz %s\n",
3420 i, clocks.data[i].clocks_in_khz / 1000,
3421 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3422 break;
3423
3424 case PP_FCLK:
3425 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
3426 PP_ASSERT_WITH_CODE(!ret,
3427 "Attempt to get current fclk freq Failed!",
3428 return ret);
3429
3430 for (i = 0; i < fclk_dpm_table->count; i++)
3431 size += sprintf(buf + size, "%d: %uMhz %s\n",
3432 i, fclk_dpm_table->dpm_levels[i].value,
3433 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
3434 break;
3435
3436 case PP_DCEFCLK:
3437 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
3438 PP_ASSERT_WITH_CODE(!ret,
3439 "Attempt to get current dcefclk freq Failed!",
3440 return ret);
3441
3442 if (vega20_get_dcefclocks(hwmgr, &clocks)) {
3443 size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n",
3444 now / 100);
3445 break;
3446 }
3447
3448 for (i = 0; i < clocks.num_levels; i++)
3449 size += sprintf(buf + size, "%d: %uMhz %s\n",
3450 i, clocks.data[i].clocks_in_khz / 1000,
3451 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
3452 break;
3453
3454 case PP_PCIE:
3455 current_gen_speed =
3456 vega20_get_current_pcie_link_speed_level(hwmgr);
3457 current_lane_width =
3458 vega20_get_current_pcie_link_width_level(hwmgr);
3459 for (i = 0; i < NUM_LINK_LEVELS; i++) {
3460 gen_speed = pptable->PcieGenSpeed[i];
3461 lane_width = pptable->PcieLaneCount[i];
3462
3463 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i,
3464 (gen_speed == 0) ? "2.5GT/s," :
3465 (gen_speed == 1) ? "5.0GT/s," :
3466 (gen_speed == 2) ? "8.0GT/s," :
3467 (gen_speed == 3) ? "16.0GT/s," : "",
3468 (lane_width == 1) ? "x1" :
3469 (lane_width == 2) ? "x2" :
3470 (lane_width == 3) ? "x4" :
3471 (lane_width == 4) ? "x8" :
3472 (lane_width == 5) ? "x12" :
3473 (lane_width == 6) ? "x16" : "",
3474 pptable->LclkFreq[i],
3475 (current_gen_speed == gen_speed) &&
3476 (current_lane_width == lane_width) ?
3477 "*" : "");
3478 }
3479 break;
3480
3481 case OD_SCLK:
3482 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3483 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3484 size += sprintf(buf + size, "%s:\n", "OD_SCLK");
3485 size += sprintf(buf + size, "0: %10uMhz\n",
3486 od_table->GfxclkFmin);
3487 size += sprintf(buf + size, "1: %10uMhz\n",
3488 od_table->GfxclkFmax);
3489 }
3490 break;
3491
3492 case OD_MCLK:
3493 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3494 size += sprintf(buf + size, "%s:\n", "OD_MCLK");
3495 size += sprintf(buf + size, "1: %10uMhz\n",
3496 od_table->UclkFmax);
3497 }
3498
3499 break;
3500
3501 case OD_VDDC_CURVE:
3502 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3503 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3504 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3505 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3506 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3507 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3508 size += sprintf(buf + size, "%s:\n", "OD_VDDC_CURVE");
3509 size += sprintf(buf + size, "0: %10uMhz %10dmV\n",
3510 od_table->GfxclkFreq1,
3511 od_table->GfxclkVolt1 / VOLTAGE_SCALE);
3512 size += sprintf(buf + size, "1: %10uMhz %10dmV\n",
3513 od_table->GfxclkFreq2,
3514 od_table->GfxclkVolt2 / VOLTAGE_SCALE);
3515 size += sprintf(buf + size, "2: %10uMhz %10dmV\n",
3516 od_table->GfxclkFreq3,
3517 od_table->GfxclkVolt3 / VOLTAGE_SCALE);
3518 }
3519
3520 break;
3521
3522 case OD_RANGE:
3523 size += sprintf(buf + size, "%s:\n", "OD_RANGE");
3524
3525 if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id &&
3526 od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) {
3527 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
3528 od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value,
3529 od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value);
3530 }
3531
3532 if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) {
3533 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n",
3534 od8_settings[OD8_SETTING_UCLK_FMAX].min_value,
3535 od8_settings[OD8_SETTING_UCLK_FMAX].max_value);
3536 }
3537
3538 if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id &&
3539 od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id &&
3540 od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id &&
3541 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id &&
3542 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id &&
3543 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) {
3544 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n",
3545 od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value,
3546 od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value);
3547 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n",
3548 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value,
3549 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value);
3550 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n",
3551 od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value,
3552 od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value);
3553 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n",
3554 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value,
3555 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value);
3556 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n",
3557 od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value,
3558 od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value);
3559 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n",
3560 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value,
3561 od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value);
3562 }
3563
3564 break;
3565 default:
3566 break;
3567 }
3568 return size;
3569 }
3570
3571 static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr,
3572 struct vega20_single_dpm_table *dpm_table)
3573 {
3574 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3575 int ret = 0;
3576
3577 if (data->smu_features[GNLD_DPM_UCLK].enabled) {
3578 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3579 "[SetUclkToHightestDpmLevel] Dpm table has no entry!",
3580 return -EINVAL);
3581 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS,
3582 "[SetUclkToHightestDpmLevel] Dpm table has too many entries!",
3583 return -EINVAL);
3584
3585 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3586 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3587 PPSMC_MSG_SetHardMinByFreq,
3588 (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level,
3589 NULL)),
3590 "[SetUclkToHightestDpmLevel] Set hard min uclk failed!",
3591 return ret);
3592 }
3593
3594 return ret;
3595 }
3596
3597 static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr)
3598 {
3599 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3600 struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table);
3601 int ret = 0;
3602
3603 if (data->smu_features[GNLD_DPM_FCLK].enabled) {
3604 PP_ASSERT_WITH_CODE(dpm_table->count > 0,
3605 "[SetFclkToHightestDpmLevel] Dpm table has no entry!",
3606 return -EINVAL);
3607 PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS,
3608 "[SetFclkToHightestDpmLevel] Dpm table has too many entries!",
3609 return -EINVAL);
3610
3611 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3612 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr,
3613 PPSMC_MSG_SetSoftMinByFreq,
3614 (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level,
3615 NULL)),
3616 "[SetFclkToHightestDpmLevel] Set soft min fclk failed!",
3617 return ret);
3618 }
3619
3620 return ret;
3621 }
3622
3623 static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3624 {
3625 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3626 int ret = 0;
3627
3628 smum_send_msg_to_smc_with_parameter(hwmgr,
3629 PPSMC_MSG_NumOfDisplays, 0, NULL);
3630
3631 ret = vega20_set_uclk_to_highest_dpm_level(hwmgr,
3632 &data->dpm_table.mem_table);
3633 if (ret)
3634 return ret;
3635
3636 return vega20_set_fclk_to_highest_dpm_level(hwmgr);
3637 }
3638
3639 static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
3640 {
3641 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3642 int result = 0;
3643 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table);
3644
3645 if ((data->water_marks_bitmap & WaterMarksExist) &&
3646 !(data->water_marks_bitmap & WaterMarksLoaded)) {
3647 result = smum_smc_table_manager(hwmgr,
3648 (uint8_t *)wm_table, TABLE_WATERMARKS, false);
3649 PP_ASSERT_WITH_CODE(!result,
3650 "Failed to update WMTABLE!",
3651 return result);
3652 data->water_marks_bitmap |= WaterMarksLoaded;
3653 }
3654
3655 if ((data->water_marks_bitmap & WaterMarksExist) &&
3656 data->smu_features[GNLD_DPM_DCEFCLK].supported &&
3657 data->smu_features[GNLD_DPM_SOCCLK].supported) {
3658 result = smum_send_msg_to_smc_with_parameter(hwmgr,
3659 PPSMC_MSG_NumOfDisplays,
3660 hwmgr->display_config->num_display,
3661 NULL);
3662 }
3663
3664 return result;
3665 }
3666
3667 static int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
3668 {
3669 struct vega20_hwmgr *data =
3670 (struct vega20_hwmgr *)(hwmgr->backend);
3671 int ret = 0;
3672
3673 if (data->smu_features[GNLD_DPM_UVD].supported) {
3674 if (data->smu_features[GNLD_DPM_UVD].enabled == enable) {
3675 if (enable)
3676 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n");
3677 else
3678 PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n");
3679 }
3680
3681 ret = vega20_enable_smc_features(hwmgr,
3682 enable,
3683 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap);
3684 PP_ASSERT_WITH_CODE(!ret,
3685 "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!",
3686 return ret);
3687 data->smu_features[GNLD_DPM_UVD].enabled = enable;
3688 }
3689
3690 return 0;
3691 }
3692
3693 static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate)
3694 {
3695 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3696
3697 if (data->vce_power_gated == bgate)
3698 return ;
3699
3700 data->vce_power_gated = bgate;
3701 if (bgate) {
3702 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3703 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3704 AMD_IP_BLOCK_TYPE_VCE,
3705 AMD_PG_STATE_GATE);
3706 } else {
3707 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
3708 AMD_IP_BLOCK_TYPE_VCE,
3709 AMD_PG_STATE_UNGATE);
3710 vega20_enable_disable_vce_dpm(hwmgr, !bgate);
3711 }
3712
3713 }
3714
3715 static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
3716 {
3717 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3718
3719 if (data->uvd_power_gated == bgate)
3720 return ;
3721
3722 data->uvd_power_gated = bgate;
3723 vega20_enable_disable_uvd_dpm(hwmgr, !bgate);
3724 }
3725
3726 static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr)
3727 {
3728 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3729 struct vega20_single_dpm_table *dpm_table;
3730 bool vblank_too_short = false;
3731 bool disable_mclk_switching;
3732 bool disable_fclk_switching;
3733 uint32_t i, latency;
3734
3735 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) &&
3736 !hwmgr->display_config->multi_monitor_in_sync) ||
3737 vblank_too_short;
3738 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency;
3739
3740
3741 dpm_table = &(data->dpm_table.gfx_table);
3742 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3743 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3744 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3745 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3746
3747 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3748 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) {
3749 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3750 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value;
3751 }
3752
3753 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
3754 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3755 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3756 }
3757
3758 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3759 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3760 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3761 }
3762 }
3763
3764
3765 dpm_table = &(data->dpm_table.mem_table);
3766 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3767 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3768 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3769 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3770
3771 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3772 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) {
3773 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3774 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value;
3775 }
3776
3777 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
3778 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3779 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value;
3780 }
3781
3782 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3783 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3784 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3785 }
3786 }
3787
3788
3789 if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100))
3790 dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100;
3791
3792
3793 if (disable_mclk_switching) {
3794 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3795 for (i = 0; i < data->mclk_latency_table.count - 1; i++) {
3796 if (data->mclk_latency_table.entries[i].latency <= latency) {
3797 if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) {
3798 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value;
3799 break;
3800 }
3801 }
3802 }
3803 }
3804
3805 if (hwmgr->display_config->nb_pstate_switch_disable)
3806 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3807
3808 if ((disable_mclk_switching &&
3809 (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) ||
3810 hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value)
3811 disable_fclk_switching = true;
3812 else
3813 disable_fclk_switching = false;
3814
3815
3816 dpm_table = &(data->dpm_table.fclk_table);
3817 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3818 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3819 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3820 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3821 if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching)
3822 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3823
3824
3825 dpm_table = &(data->dpm_table.vclk_table);
3826 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3827 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3828 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3829 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3830
3831 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3832 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3833 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3834 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3835 }
3836
3837 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3838 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3839 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3840 }
3841 }
3842
3843
3844 dpm_table = &(data->dpm_table.dclk_table);
3845 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3846 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3847 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3848 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3849
3850 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3851 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) {
3852 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3853 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value;
3854 }
3855
3856 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3857 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3858 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3859 }
3860 }
3861
3862
3863 dpm_table = &(data->dpm_table.soc_table);
3864 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3865 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3866 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3867 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3868
3869 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3870 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) {
3871 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3872 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value;
3873 }
3874
3875 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3876 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3877 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3878 }
3879 }
3880
3881
3882 dpm_table = &(data->dpm_table.eclk_table);
3883 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value;
3884 dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT;
3885 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value;
3886 dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT;
3887
3888 if (PP_CAP(PHM_PlatformCaps_UMDPState)) {
3889 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) {
3890 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3891 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value;
3892 }
3893
3894 if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
3895 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3896 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value;
3897 }
3898 }
3899
3900 return 0;
3901 }
3902
3903 static bool
3904 vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
3905 {
3906 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3907 bool is_update_required = false;
3908
3909 if (data->display_timing.num_existing_displays !=
3910 hwmgr->display_config->num_display)
3911 is_update_required = true;
3912
3913 if (data->registry_data.gfx_clk_deep_sleep_support &&
3914 (data->display_timing.min_clock_in_sr !=
3915 hwmgr->display_config->min_core_set_clock_in_sr))
3916 is_update_required = true;
3917
3918 return is_update_required;
3919 }
3920
3921 static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
3922 {
3923 int ret = 0;
3924
3925 ret = vega20_disable_all_smu_features(hwmgr);
3926 PP_ASSERT_WITH_CODE(!ret,
3927 "[DisableDpmTasks] Failed to disable all smu features!",
3928 return ret);
3929
3930 return 0;
3931 }
3932
3933 static int vega20_power_off_asic(struct pp_hwmgr *hwmgr)
3934 {
3935 struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
3936 int result;
3937
3938 result = vega20_disable_dpm_tasks(hwmgr);
3939 PP_ASSERT_WITH_CODE((0 == result),
3940 "[PowerOffAsic] Failed to disable DPM!",
3941 );
3942 data->water_marks_bitmap &= ~(WaterMarksLoaded);
3943
3944 return result;
3945 }
3946
3947 static int conv_power_profile_to_pplib_workload(int power_profile)
3948 {
3949 int pplib_workload = 0;
3950
3951 switch (power_profile) {
3952 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
3953 pplib_workload = WORKLOAD_DEFAULT_BIT;
3954 break;
3955 case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
3956 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
3957 break;
3958 case PP_SMC_POWER_PROFILE_POWERSAVING:
3959 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT;
3960 break;
3961 case PP_SMC_POWER_PROFILE_VIDEO:
3962 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
3963 break;
3964 case PP_SMC_POWER_PROFILE_VR:
3965 pplib_workload = WORKLOAD_PPLIB_VR_BIT;
3966 break;
3967 case PP_SMC_POWER_PROFILE_COMPUTE:
3968 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
3969 break;
3970 case PP_SMC_POWER_PROFILE_CUSTOM:
3971 pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
3972 break;
3973 }
3974
3975 return pplib_workload;
3976 }
3977
3978 static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
3979 {
3980 DpmActivityMonitorCoeffInt_t activity_monitor;
3981 uint32_t i, size = 0;
3982 uint16_t workload_type = 0;
3983 static const char *title[] = {
3984 "PROFILE_INDEX(NAME)",
3985 "CLOCK_TYPE(NAME)",
3986 "FPS",
3987 "UseRlcBusy",
3988 "MinActiveFreqType",
3989 "MinActiveFreq",
3990 "BoosterFreqType",
3991 "BoosterFreq",
3992 "PD_Data_limit_c",
3993 "PD_Data_error_coeff",
3994 "PD_Data_error_rate_coeff"};
3995 int result = 0;
3996
3997 if (!buf)
3998 return -EINVAL;
3999
4000 phm_get_sysfs_buf(&buf, &size);
4001
4002 size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
4003 title[0], title[1], title[2], title[3], title[4], title[5],
4004 title[6], title[7], title[8], title[9], title[10]);
4005
4006 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
4007
4008 workload_type = conv_power_profile_to_pplib_workload(i);
4009 result = vega20_get_activity_monitor_coeff(hwmgr,
4010 (uint8_t *)(&activity_monitor), workload_type);
4011 PP_ASSERT_WITH_CODE(!result,
4012 "[GetPowerProfile] Failed to get activity monitor!",
4013 return result);
4014
4015 size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
4016 i, amdgpu_pp_profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
4017
4018 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4019 " ",
4020 0,
4021 "GFXCLK",
4022 activity_monitor.Gfx_FPS,
4023 activity_monitor.Gfx_UseRlcBusy,
4024 activity_monitor.Gfx_MinActiveFreqType,
4025 activity_monitor.Gfx_MinActiveFreq,
4026 activity_monitor.Gfx_BoosterFreqType,
4027 activity_monitor.Gfx_BoosterFreq,
4028 activity_monitor.Gfx_PD_Data_limit_c,
4029 activity_monitor.Gfx_PD_Data_error_coeff,
4030 activity_monitor.Gfx_PD_Data_error_rate_coeff);
4031
4032 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4033 " ",
4034 1,
4035 "SOCCLK",
4036 activity_monitor.Soc_FPS,
4037 activity_monitor.Soc_UseRlcBusy,
4038 activity_monitor.Soc_MinActiveFreqType,
4039 activity_monitor.Soc_MinActiveFreq,
4040 activity_monitor.Soc_BoosterFreqType,
4041 activity_monitor.Soc_BoosterFreq,
4042 activity_monitor.Soc_PD_Data_limit_c,
4043 activity_monitor.Soc_PD_Data_error_coeff,
4044 activity_monitor.Soc_PD_Data_error_rate_coeff);
4045
4046 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4047 " ",
4048 2,
4049 "UCLK",
4050 activity_monitor.Mem_FPS,
4051 activity_monitor.Mem_UseRlcBusy,
4052 activity_monitor.Mem_MinActiveFreqType,
4053 activity_monitor.Mem_MinActiveFreq,
4054 activity_monitor.Mem_BoosterFreqType,
4055 activity_monitor.Mem_BoosterFreq,
4056 activity_monitor.Mem_PD_Data_limit_c,
4057 activity_monitor.Mem_PD_Data_error_coeff,
4058 activity_monitor.Mem_PD_Data_error_rate_coeff);
4059
4060 size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
4061 " ",
4062 3,
4063 "FCLK",
4064 activity_monitor.Fclk_FPS,
4065 activity_monitor.Fclk_UseRlcBusy,
4066 activity_monitor.Fclk_MinActiveFreqType,
4067 activity_monitor.Fclk_MinActiveFreq,
4068 activity_monitor.Fclk_BoosterFreqType,
4069 activity_monitor.Fclk_BoosterFreq,
4070 activity_monitor.Fclk_PD_Data_limit_c,
4071 activity_monitor.Fclk_PD_Data_error_coeff,
4072 activity_monitor.Fclk_PD_Data_error_rate_coeff);
4073 }
4074
4075 return size;
4076 }
4077
4078 static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
4079 {
4080 DpmActivityMonitorCoeffInt_t activity_monitor;
4081 int workload_type, result = 0;
4082 uint32_t power_profile_mode = input[size];
4083
4084 if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
4085 pr_err("Invalid power profile mode %d\n", power_profile_mode);
4086 return -EINVAL;
4087 }
4088
4089 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
4090 struct vega20_hwmgr *data =
4091 (struct vega20_hwmgr *)(hwmgr->backend);
4092 if (size == 0 && !data->is_custom_profile_set)
4093 return -EINVAL;
4094 if (size < 10 && size != 0)
4095 return -EINVAL;
4096
4097 result = vega20_get_activity_monitor_coeff(hwmgr,
4098 (uint8_t *)(&activity_monitor),
4099 WORKLOAD_PPLIB_CUSTOM_BIT);
4100 PP_ASSERT_WITH_CODE(!result,
4101 "[SetPowerProfile] Failed to get activity monitor!",
4102 return result);
4103
4104
4105
4106
4107
4108 if (size == 0)
4109 goto out;
4110
4111 switch (input[0]) {
4112 case 0:
4113 activity_monitor.Gfx_FPS = input[1];
4114 activity_monitor.Gfx_UseRlcBusy = input[2];
4115 activity_monitor.Gfx_MinActiveFreqType = input[3];
4116 activity_monitor.Gfx_MinActiveFreq = input[4];
4117 activity_monitor.Gfx_BoosterFreqType = input[5];
4118 activity_monitor.Gfx_BoosterFreq = input[6];
4119 activity_monitor.Gfx_PD_Data_limit_c = input[7];
4120 activity_monitor.Gfx_PD_Data_error_coeff = input[8];
4121 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
4122 break;
4123 case 1:
4124 activity_monitor.Soc_FPS = input[1];
4125 activity_monitor.Soc_UseRlcBusy = input[2];
4126 activity_monitor.Soc_MinActiveFreqType = input[3];
4127 activity_monitor.Soc_MinActiveFreq = input[4];
4128 activity_monitor.Soc_BoosterFreqType = input[5];
4129 activity_monitor.Soc_BoosterFreq = input[6];
4130 activity_monitor.Soc_PD_Data_limit_c = input[7];
4131 activity_monitor.Soc_PD_Data_error_coeff = input[8];
4132 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
4133 break;
4134 case 2:
4135 activity_monitor.Mem_FPS = input[1];
4136 activity_monitor.Mem_UseRlcBusy = input[2];
4137 activity_monitor.Mem_MinActiveFreqType = input[3];
4138 activity_monitor.Mem_MinActiveFreq = input[4];
4139 activity_monitor.Mem_BoosterFreqType = input[5];
4140 activity_monitor.Mem_BoosterFreq = input[6];
4141 activity_monitor.Mem_PD_Data_limit_c = input[7];
4142 activity_monitor.Mem_PD_Data_error_coeff = input[8];
4143 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
4144 break;
4145 case 3:
4146 activity_monitor.Fclk_FPS = input[1];
4147 activity_monitor.Fclk_UseRlcBusy = input[2];
4148 activity_monitor.Fclk_MinActiveFreqType = input[3];
4149 activity_monitor.Fclk_MinActiveFreq = input[4];
4150 activity_monitor.Fclk_BoosterFreqType = input[5];
4151 activity_monitor.Fclk_BoosterFreq = input[6];
4152 activity_monitor.Fclk_PD_Data_limit_c = input[7];
4153 activity_monitor.Fclk_PD_Data_error_coeff = input[8];
4154 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
4155 break;
4156 }
4157
4158 result = vega20_set_activity_monitor_coeff(hwmgr,
4159 (uint8_t *)(&activity_monitor),
4160 WORKLOAD_PPLIB_CUSTOM_BIT);
4161 data->is_custom_profile_set = true;
4162 PP_ASSERT_WITH_CODE(!result,
4163 "[SetPowerProfile] Failed to set activity monitor!",
4164 return result);
4165 }
4166
4167 out:
4168
4169 workload_type =
4170 conv_power_profile_to_pplib_workload(power_profile_mode);
4171 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
4172 1 << workload_type,
4173 NULL);
4174
4175 hwmgr->power_profile_mode = power_profile_mode;
4176
4177 return 0;
4178 }
4179
4180 static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
4181 uint32_t virtual_addr_low,
4182 uint32_t virtual_addr_hi,
4183 uint32_t mc_addr_low,
4184 uint32_t mc_addr_hi,
4185 uint32_t size)
4186 {
4187 smum_send_msg_to_smc_with_parameter(hwmgr,
4188 PPSMC_MSG_SetSystemVirtualDramAddrHigh,
4189 virtual_addr_hi,
4190 NULL);
4191 smum_send_msg_to_smc_with_parameter(hwmgr,
4192 PPSMC_MSG_SetSystemVirtualDramAddrLow,
4193 virtual_addr_low,
4194 NULL);
4195 smum_send_msg_to_smc_with_parameter(hwmgr,
4196 PPSMC_MSG_DramLogSetDramAddrHigh,
4197 mc_addr_hi,
4198 NULL);
4199
4200 smum_send_msg_to_smc_with_parameter(hwmgr,
4201 PPSMC_MSG_DramLogSetDramAddrLow,
4202 mc_addr_low,
4203 NULL);
4204
4205 smum_send_msg_to_smc_with_parameter(hwmgr,
4206 PPSMC_MSG_DramLogSetDramSize,
4207 size,
4208 NULL);
4209 return 0;
4210 }
4211
4212 static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
4213 struct PP_TemperatureRange *thermal_data)
4214 {
4215 struct vega20_hwmgr *data =
4216 (struct vega20_hwmgr *)(hwmgr->backend);
4217 PPTable_t *pp_table = &(data->smc_state_table.pp_table);
4218
4219 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
4220
4221 thermal_data->max = pp_table->TedgeLimit *
4222 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4223 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) *
4224 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4225 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit *
4226 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4227 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) *
4228 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4229 thermal_data->mem_crit_max = pp_table->ThbmLimit *
4230 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4231 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)*
4232 PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
4233
4234 return 0;
4235 }
4236
4237 static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire)
4238 {
4239 int res;
4240
4241
4242 if (!vega20_is_smc_ram_running(hwmgr))
4243 return 0;
4244
4245 res = smum_send_msg_to_smc_with_parameter(hwmgr,
4246 (acquire ?
4247 PPSMC_MSG_RequestI2CBus :
4248 PPSMC_MSG_ReleaseI2CBus),
4249 0,
4250 NULL);
4251
4252 PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res);
4253 return res;
4254 }
4255
4256 static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr,
4257 enum pp_df_cstate state)
4258 {
4259 int ret;
4260
4261
4262 if (hwmgr->smu_version < 0x283200) {
4263 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n");
4264 return -EINVAL;
4265 }
4266
4267 ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state,
4268 NULL);
4269 if (ret)
4270 pr_err("SetDfCstate failed!\n");
4271
4272 return ret;
4273 }
4274
4275 static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr,
4276 uint32_t pstate)
4277 {
4278 int ret;
4279
4280 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
4281 PPSMC_MSG_SetXgmiMode,
4282 pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3,
4283 NULL);
4284 if (ret)
4285 pr_err("SetXgmiPstate failed!\n");
4286
4287 return ret;
4288 }
4289
4290 static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
4291 {
4292 memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0));
4293
4294 gpu_metrics->common_header.structure_size =
4295 sizeof(struct gpu_metrics_v1_0);
4296 gpu_metrics->common_header.format_revision = 1;
4297 gpu_metrics->common_header.content_revision = 0;
4298
4299 gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
4300 }
4301
4302 static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr,
4303 void **table)
4304 {
4305 struct vega20_hwmgr *data =
4306 (struct vega20_hwmgr *)(hwmgr->backend);
4307 struct gpu_metrics_v1_0 *gpu_metrics =
4308 &data->gpu_metrics_table;
4309 SmuMetrics_t metrics;
4310 uint32_t fan_speed_rpm;
4311 int ret;
4312
4313 ret = vega20_get_metrics_table(hwmgr, &metrics, true);
4314 if (ret)
4315 return ret;
4316
4317 vega20_init_gpu_metrics_v1_0(gpu_metrics);
4318
4319 gpu_metrics->temperature_edge = metrics.TemperatureEdge;
4320 gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
4321 gpu_metrics->temperature_mem = metrics.TemperatureHBM;
4322 gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
4323 gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
4324 gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
4325
4326 gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
4327 gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
4328
4329 gpu_metrics->average_socket_power = metrics.AverageSocketPower;
4330
4331 gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
4332 gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
4333 gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency;
4334
4335 gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
4336 gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
4337 gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
4338 gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK];
4339 gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK];
4340
4341 gpu_metrics->throttle_status = metrics.ThrottlerStatus;
4342
4343 vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm);
4344 gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm;
4345
4346 gpu_metrics->pcie_link_width =
4347 vega20_get_current_pcie_link_width(hwmgr);
4348 gpu_metrics->pcie_link_speed =
4349 vega20_get_current_pcie_link_speed(hwmgr);
4350
4351 *table = (void *)gpu_metrics;
4352
4353 return sizeof(struct gpu_metrics_v1_0);
4354 }
4355
4356 static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
4357
4358 .backend_init = vega20_hwmgr_backend_init,
4359 .backend_fini = vega20_hwmgr_backend_fini,
4360 .asic_setup = vega20_setup_asic_task,
4361 .power_off_asic = vega20_power_off_asic,
4362 .dynamic_state_management_enable = vega20_enable_dpm_tasks,
4363 .dynamic_state_management_disable = vega20_disable_dpm_tasks,
4364
4365 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules,
4366 .pre_display_config_changed = vega20_pre_display_configuration_changed_task,
4367 .display_config_changed = vega20_display_configuration_changed_task,
4368 .check_smc_update_required_for_display_configuration =
4369 vega20_check_smc_update_required_for_display_configuration,
4370 .notify_smc_display_config_after_ps_adjustment =
4371 vega20_notify_smc_display_config_after_ps_adjustment,
4372
4373 .get_sclk = vega20_dpm_get_sclk,
4374 .get_mclk = vega20_dpm_get_mclk,
4375 .get_dal_power_level = vega20_get_dal_power_level,
4376 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency,
4377 .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage,
4378 .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges,
4379 .display_clock_voltage_request = vega20_display_clock_voltage_request,
4380 .get_performance_level = vega20_get_performance_level,
4381
4382 .force_dpm_level = vega20_dpm_force_dpm_level,
4383 .get_power_profile_mode = vega20_get_power_profile_mode,
4384 .set_power_profile_mode = vega20_set_power_profile_mode,
4385
4386 .set_power_limit = vega20_set_power_limit,
4387 .get_sclk_od = vega20_get_sclk_od,
4388 .set_sclk_od = vega20_set_sclk_od,
4389 .get_mclk_od = vega20_get_mclk_od,
4390 .set_mclk_od = vega20_set_mclk_od,
4391 .odn_edit_dpm_table = vega20_odn_edit_dpm_table,
4392
4393 .force_clock_level = vega20_force_clock_level,
4394 .print_clock_levels = vega20_print_clock_levels,
4395 .read_sensor = vega20_read_sensor,
4396 .get_ppfeature_status = vega20_get_ppfeature_status,
4397 .set_ppfeature_status = vega20_set_ppfeature_status,
4398
4399 .powergate_uvd = vega20_power_gate_uvd,
4400 .powergate_vce = vega20_power_gate_vce,
4401
4402 .start_thermal_controller = vega20_start_thermal_controller,
4403 .stop_thermal_controller = vega20_thermal_stop_thermal_controller,
4404 .get_thermal_temperature_range = vega20_get_thermal_temperature_range,
4405 .register_irq_handlers = smu9_register_irq_handlers,
4406 .disable_smc_firmware_ctf = vega20_thermal_disable_alert,
4407
4408 .get_fan_speed_pwm = vega20_fan_ctrl_get_fan_speed_pwm,
4409 .set_fan_speed_pwm = vega20_fan_ctrl_set_fan_speed_pwm,
4410 .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info,
4411 .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm,
4412 .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm,
4413 .get_fan_control_mode = vega20_get_fan_control_mode,
4414 .set_fan_control_mode = vega20_set_fan_control_mode,
4415
4416 .notify_cac_buffer_info = vega20_notify_cac_buffer_info,
4417 .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost,
4418
4419 .get_asic_baco_capability = vega20_baco_get_capability,
4420 .get_asic_baco_state = vega20_baco_get_state,
4421 .set_asic_baco_state = vega20_baco_set_state,
4422 .set_mp1_state = vega20_set_mp1_state,
4423 .smu_i2c_bus_access = vega20_smu_i2c_bus_access,
4424 .set_df_cstate = vega20_set_df_cstate,
4425 .set_xgmi_pstate = vega20_set_xgmi_pstate,
4426 .get_gpu_metrics = vega20_get_gpu_metrics,
4427 };
4428
4429 int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
4430 {
4431 hwmgr->hwmgr_func = &vega20_hwmgr_funcs;
4432 hwmgr->pptable_func = &vega20_pptable_funcs;
4433
4434 return 0;
4435 }