1 /* 2 * Copyright 2016 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24 #include <linux/delay.h> 25 #include <linux/fb.h> 26 #include <linux/module.h> 27 #include <linux/pci.h> 28 #include <linux/slab.h> 29 30 #include "hwmgr.h" 31 #include "amd_powerplay.h" 32 #include "hardwaremanager.h" 33 #include "ppatomfwctrl.h" 34 #include "atomfirmware.h" 35 #include "cgs_common.h" 36 #include "vega10_powertune.h" 37 #include "smu9.h" 38 #include "smu9_driver_if.h" 39 #include "vega10_inc.h" 40 #include "soc15_common.h" 41 #include "pppcielanes.h" 42 #include "vega10_hwmgr.h" 43 #include "vega10_smumgr.h" 44 #include "vega10_processpptables.h" 45 #include "vega10_pptable.h" 46 #include "vega10_thermal.h" 47 #include "pp_debug.h" 48 #include "amd_pcie_helpers.h" 49 #include "ppinterrupt.h" 50 #include "pp_overdriver.h" 51 #include "pp_thermal.h" 52 #include "vega10_baco.h" 53 54 #include "smuio/smuio_9_0_offset.h" 55 #include "smuio/smuio_9_0_sh_mask.h" 56 57 #define HBM_MEMORY_CHANNEL_WIDTH 128 58 59 static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; 60 61 #define mmDF_CS_AON0_DramBaseAddress0 0x0044 62 #define mmDF_CS_AON0_DramBaseAddress0_BASE_IDX 0 63 64 //DF_CS_AON0_DramBaseAddress0 65 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal__SHIFT 0x0 66 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT 0x1 67 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT 0x4 68 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT 0x8 69 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr__SHIFT 0xc 70 #define DF_CS_AON0_DramBaseAddress0__AddrRngVal_MASK 0x00000001L 71 #define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK 0x00000002L 72 #define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK 0x000000F0L 73 #define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK 0x00000700L 74 #define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK 0xFFFFF000L 75 76 typedef enum { 77 CLK_SMNCLK = 0, 78 CLK_SOCCLK, 79 CLK_MP0CLK, 80 CLK_MP1CLK, 81 CLK_LCLK, 82 CLK_DCEFCLK, 83 CLK_VCLK, 84 CLK_DCLK, 85 CLK_ECLK, 86 CLK_UCLK, 87 CLK_GFXCLK, 88 CLK_COUNT, 89 } CLOCK_ID_e; 90 91 static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic); 92 93 static struct vega10_power_state *cast_phw_vega10_power_state( 94 struct pp_hw_power_state *hw_ps) 95 { 96 PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic), 97 "Invalid Powerstate Type!", 98 return NULL;); 99 100 return (struct vega10_power_state *)hw_ps; 101 } 102 103 static const struct vega10_power_state *cast_const_phw_vega10_power_state( 104 const struct pp_hw_power_state *hw_ps) 105 { 106 PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic), 107 "Invalid Powerstate Type!", 108 return NULL;); 109 110 return (const struct vega10_power_state *)hw_ps; 111 } 112 113 static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) 114 { 115 struct vega10_hwmgr *data = hwmgr->backend; 116 117 data->registry_data.sclk_dpm_key_disabled = 118 hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; 119 data->registry_data.socclk_dpm_key_disabled = 120 hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true; 121 data->registry_data.mclk_dpm_key_disabled = 122 hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; 123 data->registry_data.pcie_dpm_key_disabled = 124 hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; 125 126 data->registry_data.dcefclk_dpm_key_disabled = 127 hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true; 128 129 if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) { 130 data->registry_data.power_containment_support = 1; 131 data->registry_data.enable_pkg_pwr_tracking_feature = 1; 132 data->registry_data.enable_tdc_limit_feature = 1; 133 } 134 135 data->registry_data.clock_stretcher_support = 136 hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false; 137 138 data->registry_data.ulv_support = 139 hwmgr->feature_mask & PP_ULV_MASK ? true : false; 140 141 data->registry_data.sclk_deep_sleep_support = 142 hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK ? true : false; 143 144 data->registry_data.disable_water_mark = 0; 145 146 data->registry_data.fan_control_support = 1; 147 data->registry_data.thermal_support = 1; 148 data->registry_data.fw_ctf_enabled = 1; 149 150 data->registry_data.avfs_support = 151 hwmgr->feature_mask & PP_AVFS_MASK ? true : false; 152 data->registry_data.led_dpm_enabled = 1; 153 154 data->registry_data.vr0hot_enabled = 1; 155 data->registry_data.vr1hot_enabled = 1; 156 data->registry_data.regulator_hot_gpio_support = 1; 157 158 data->registry_data.didt_support = 1; 159 if (data->registry_data.didt_support) { 160 data->registry_data.didt_mode = 6; 161 data->registry_data.sq_ramping_support = 1; 162 data->registry_data.db_ramping_support = 0; 163 data->registry_data.td_ramping_support = 0; 164 data->registry_data.tcp_ramping_support = 0; 165 data->registry_data.dbr_ramping_support = 0; 166 data->registry_data.edc_didt_support = 1; 167 data->registry_data.gc_didt_support = 0; 168 data->registry_data.psm_didt_support = 0; 169 } 170 171 data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT; 172 data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 173 data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 174 data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 175 data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 176 data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 177 data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 178 data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 179 data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 180 data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 181 data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 182 data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 183 data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; 184 185 data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT; 186 data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT; 187 data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT; 188 data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT; 189 } 190 191 static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr) 192 { 193 struct vega10_hwmgr *data = hwmgr->backend; 194 struct phm_ppt_v2_information *table_info = 195 (struct phm_ppt_v2_information *)hwmgr->pptable; 196 struct amdgpu_device *adev = hwmgr->adev; 197 198 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 199 PHM_PlatformCaps_SclkDeepSleep); 200 201 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 202 PHM_PlatformCaps_DynamicPatchPowerState); 203 204 if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) 205 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 206 PHM_PlatformCaps_ControlVDDCI); 207 208 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 209 PHM_PlatformCaps_EnableSMU7ThermalManagement); 210 211 if (adev->pg_flags & AMD_PG_SUPPORT_UVD) 212 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 213 PHM_PlatformCaps_UVDPowerGating); 214 215 if (adev->pg_flags & AMD_PG_SUPPORT_VCE) 216 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 217 PHM_PlatformCaps_VCEPowerGating); 218 219 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 220 PHM_PlatformCaps_UnTabledHardwareInterface); 221 222 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 223 PHM_PlatformCaps_FanSpeedInTableIsRPM); 224 225 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 226 PHM_PlatformCaps_ODFuzzyFanControlSupport); 227 228 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 229 PHM_PlatformCaps_DynamicPowerManagement); 230 231 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 232 PHM_PlatformCaps_SMC); 233 234 /* power tune caps */ 235 /* assume disabled */ 236 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 237 PHM_PlatformCaps_PowerContainment); 238 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 239 PHM_PlatformCaps_DiDtSupport); 240 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 241 PHM_PlatformCaps_SQRamping); 242 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 243 PHM_PlatformCaps_DBRamping); 244 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 245 PHM_PlatformCaps_TDRamping); 246 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 247 PHM_PlatformCaps_TCPRamping); 248 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 249 PHM_PlatformCaps_DBRRamping); 250 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 251 PHM_PlatformCaps_DiDtEDCEnable); 252 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 253 PHM_PlatformCaps_GCEDC); 254 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 255 PHM_PlatformCaps_PSM); 256 257 if (data->registry_data.didt_support) { 258 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport); 259 if (data->registry_data.sq_ramping_support) 260 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); 261 if (data->registry_data.db_ramping_support) 262 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping); 263 if (data->registry_data.td_ramping_support) 264 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping); 265 if (data->registry_data.tcp_ramping_support) 266 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); 267 if (data->registry_data.dbr_ramping_support) 268 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping); 269 if (data->registry_data.edc_didt_support) 270 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable); 271 if (data->registry_data.gc_didt_support) 272 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC); 273 if (data->registry_data.psm_didt_support) 274 phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM); 275 } 276 277 if (data->registry_data.power_containment_support) 278 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 279 PHM_PlatformCaps_PowerContainment); 280 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 281 PHM_PlatformCaps_CAC); 282 283 if (table_info->tdp_table->usClockStretchAmount && 284 data->registry_data.clock_stretcher_support) 285 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 286 PHM_PlatformCaps_ClockStretcher); 287 288 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 289 PHM_PlatformCaps_RegulatorHot); 290 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 291 PHM_PlatformCaps_AutomaticDCTransition); 292 293 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 294 PHM_PlatformCaps_UVDDPM); 295 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 296 PHM_PlatformCaps_VCEDPM); 297 298 return 0; 299 } 300 301 static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr) 302 { 303 struct vega10_hwmgr *data = hwmgr->backend; 304 struct phm_ppt_v2_information *table_info = 305 (struct phm_ppt_v2_information *)(hwmgr->pptable); 306 struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); 307 struct vega10_odn_vddc_lookup_table *od_lookup_table; 308 struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; 309 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table[3]; 310 struct phm_ppt_v1_clock_voltage_dependency_table *od_table[3]; 311 struct pp_atomfwctrl_avfs_parameters avfs_params = {0}; 312 uint32_t i; 313 int result; 314 315 result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); 316 if (!result) { 317 data->odn_dpm_table.max_vddc = avfs_params.ulMaxVddc; 318 data->odn_dpm_table.min_vddc = avfs_params.ulMinVddc; 319 } 320 321 od_lookup_table = &odn_table->vddc_lookup_table; 322 vddc_lookup_table = table_info->vddc_lookup_table; 323 324 for (i = 0; i < vddc_lookup_table->count; i++) 325 od_lookup_table->entries[i].us_vdd = vddc_lookup_table->entries[i].us_vdd; 326 327 od_lookup_table->count = vddc_lookup_table->count; 328 329 dep_table[0] = table_info->vdd_dep_on_sclk; 330 dep_table[1] = table_info->vdd_dep_on_mclk; 331 dep_table[2] = table_info->vdd_dep_on_socclk; 332 od_table[0] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_sclk; 333 od_table[1] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_mclk; 334 od_table[2] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_socclk; 335 336 for (i = 0; i < 3; i++) 337 smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]); 338 339 if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000) 340 odn_table->max_vddc = dep_table[0]->entries[dep_table[0]->count - 1].vddc; 341 if (odn_table->min_vddc == 0 || odn_table->min_vddc > 2000) 342 odn_table->min_vddc = dep_table[0]->entries[0].vddc; 343 344 i = od_table[2]->count - 1; 345 od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock > od_table[2]->entries[i].clk ? 346 hwmgr->platform_descriptor.overdriveLimit.memoryClock : 347 od_table[2]->entries[i].clk; 348 od_table[2]->entries[i].vddc = odn_table->max_vddc > od_table[2]->entries[i].vddc ? 349 odn_table->max_vddc : 350 od_table[2]->entries[i].vddc; 351 352 return 0; 353 } 354 355 static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) 356 { 357 struct vega10_hwmgr *data = hwmgr->backend; 358 int i; 359 uint32_t sub_vendor_id, hw_revision; 360 uint32_t top32, bottom32; 361 struct amdgpu_device *adev = hwmgr->adev; 362 363 vega10_initialize_power_tune_defaults(hwmgr); 364 365 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 366 data->smu_features[i].smu_feature_id = 0xffff; 367 data->smu_features[i].smu_feature_bitmap = 1 << i; 368 data->smu_features[i].enabled = false; 369 data->smu_features[i].supported = false; 370 } 371 372 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = 373 FEATURE_DPM_PREFETCHER_BIT; 374 data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = 375 FEATURE_DPM_GFXCLK_BIT; 376 data->smu_features[GNLD_DPM_UCLK].smu_feature_id = 377 FEATURE_DPM_UCLK_BIT; 378 data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = 379 FEATURE_DPM_SOCCLK_BIT; 380 data->smu_features[GNLD_DPM_UVD].smu_feature_id = 381 FEATURE_DPM_UVD_BIT; 382 data->smu_features[GNLD_DPM_VCE].smu_feature_id = 383 FEATURE_DPM_VCE_BIT; 384 data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = 385 FEATURE_DPM_MP0CLK_BIT; 386 data->smu_features[GNLD_DPM_LINK].smu_feature_id = 387 FEATURE_DPM_LINK_BIT; 388 data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = 389 FEATURE_DPM_DCEFCLK_BIT; 390 data->smu_features[GNLD_ULV].smu_feature_id = 391 FEATURE_ULV_BIT; 392 data->smu_features[GNLD_AVFS].smu_feature_id = 393 FEATURE_AVFS_BIT; 394 data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = 395 FEATURE_DS_GFXCLK_BIT; 396 data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = 397 FEATURE_DS_SOCCLK_BIT; 398 data->smu_features[GNLD_DS_LCLK].smu_feature_id = 399 FEATURE_DS_LCLK_BIT; 400 data->smu_features[GNLD_PPT].smu_feature_id = 401 FEATURE_PPT_BIT; 402 data->smu_features[GNLD_TDC].smu_feature_id = 403 FEATURE_TDC_BIT; 404 data->smu_features[GNLD_THERMAL].smu_feature_id = 405 FEATURE_THERMAL_BIT; 406 data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = 407 FEATURE_GFX_PER_CU_CG_BIT; 408 data->smu_features[GNLD_RM].smu_feature_id = 409 FEATURE_RM_BIT; 410 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = 411 FEATURE_DS_DCEFCLK_BIT; 412 data->smu_features[GNLD_ACDC].smu_feature_id = 413 FEATURE_ACDC_BIT; 414 data->smu_features[GNLD_VR0HOT].smu_feature_id = 415 FEATURE_VR0HOT_BIT; 416 data->smu_features[GNLD_VR1HOT].smu_feature_id = 417 FEATURE_VR1HOT_BIT; 418 data->smu_features[GNLD_FW_CTF].smu_feature_id = 419 FEATURE_FW_CTF_BIT; 420 data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = 421 FEATURE_LED_DISPLAY_BIT; 422 data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = 423 FEATURE_FAN_CONTROL_BIT; 424 data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; 425 data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; 426 data->smu_features[GNLD_PCC_LIMIT].smu_feature_id = FEATURE_PCC_LIMIT_CONTROL_BIT; 427 428 if (!data->registry_data.prefetcher_dpm_key_disabled) 429 data->smu_features[GNLD_DPM_PREFETCHER].supported = true; 430 431 if (!data->registry_data.sclk_dpm_key_disabled) 432 data->smu_features[GNLD_DPM_GFXCLK].supported = true; 433 434 if (!data->registry_data.mclk_dpm_key_disabled) 435 data->smu_features[GNLD_DPM_UCLK].supported = true; 436 437 if (!data->registry_data.socclk_dpm_key_disabled) 438 data->smu_features[GNLD_DPM_SOCCLK].supported = true; 439 440 if (PP_CAP(PHM_PlatformCaps_UVDDPM)) 441 data->smu_features[GNLD_DPM_UVD].supported = true; 442 443 if (PP_CAP(PHM_PlatformCaps_VCEDPM)) 444 data->smu_features[GNLD_DPM_VCE].supported = true; 445 446 if (!data->registry_data.pcie_dpm_key_disabled) 447 data->smu_features[GNLD_DPM_LINK].supported = true; 448 449 if (!data->registry_data.dcefclk_dpm_key_disabled) 450 data->smu_features[GNLD_DPM_DCEFCLK].supported = true; 451 452 if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) && 453 data->registry_data.sclk_deep_sleep_support) { 454 data->smu_features[GNLD_DS_GFXCLK].supported = true; 455 data->smu_features[GNLD_DS_SOCCLK].supported = true; 456 data->smu_features[GNLD_DS_LCLK].supported = true; 457 data->smu_features[GNLD_DS_DCEFCLK].supported = true; 458 } 459 460 if (data->registry_data.enable_pkg_pwr_tracking_feature) 461 data->smu_features[GNLD_PPT].supported = true; 462 463 if (data->registry_data.enable_tdc_limit_feature) 464 data->smu_features[GNLD_TDC].supported = true; 465 466 if (data->registry_data.thermal_support) 467 data->smu_features[GNLD_THERMAL].supported = true; 468 469 if (data->registry_data.fan_control_support) 470 data->smu_features[GNLD_FAN_CONTROL].supported = true; 471 472 if (data->registry_data.fw_ctf_enabled) 473 data->smu_features[GNLD_FW_CTF].supported = true; 474 475 if (data->registry_data.avfs_support) 476 data->smu_features[GNLD_AVFS].supported = true; 477 478 if (data->registry_data.led_dpm_enabled) 479 data->smu_features[GNLD_LED_DISPLAY].supported = true; 480 481 if (data->registry_data.vr1hot_enabled) 482 data->smu_features[GNLD_VR1HOT].supported = true; 483 484 if (data->registry_data.vr0hot_enabled) 485 data->smu_features[GNLD_VR0HOT].supported = true; 486 487 smum_send_msg_to_smc(hwmgr, 488 PPSMC_MSG_GetSmuVersion, 489 &hwmgr->smu_version); 490 /* ACG firmware has major version 5 */ 491 if ((hwmgr->smu_version & 0xff000000) == 0x5000000) 492 data->smu_features[GNLD_ACG].supported = true; 493 if (data->registry_data.didt_support) 494 data->smu_features[GNLD_DIDT].supported = true; 495 496 hw_revision = adev->pdev->revision; 497 sub_vendor_id = adev->pdev->subsystem_vendor; 498 499 if ((hwmgr->chip_id == 0x6862 || 500 hwmgr->chip_id == 0x6861 || 501 hwmgr->chip_id == 0x6868) && 502 (hw_revision == 0) && 503 (sub_vendor_id != 0x1002)) 504 data->smu_features[GNLD_PCC_LIMIT].supported = true; 505 506 /* Get the SN to turn into a Unique ID */ 507 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); 508 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); 509 510 adev->unique_id = ((uint64_t)bottom32 << 32) | top32; 511 } 512 513 #ifdef PPLIB_VEGA10_EVV_SUPPORT 514 static int vega10_get_socclk_for_voltage_evv(struct pp_hwmgr *hwmgr, 515 phm_ppt_v1_voltage_lookup_table *lookup_table, 516 uint16_t virtual_voltage_id, int32_t *socclk) 517 { 518 uint8_t entry_id; 519 uint8_t voltage_id; 520 struct phm_ppt_v2_information *table_info = 521 (struct phm_ppt_v2_information *)(hwmgr->pptable); 522 523 PP_ASSERT_WITH_CODE(lookup_table->count != 0, 524 "Lookup table is empty", 525 return -EINVAL); 526 527 /* search for leakage voltage ID 0xff01 ~ 0xff08 and sclk */ 528 for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { 529 voltage_id = table_info->vdd_dep_on_socclk->entries[entry_id].vddInd; 530 if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) 531 break; 532 } 533 534 PP_ASSERT_WITH_CODE(entry_id < table_info->vdd_dep_on_socclk->count, 535 "Can't find requested voltage id in vdd_dep_on_socclk table!", 536 return -EINVAL); 537 538 *socclk = table_info->vdd_dep_on_socclk->entries[entry_id].clk; 539 540 return 0; 541 } 542 543 #define ATOM_VIRTUAL_VOLTAGE_ID0 0xff01 544 /** 545 * Get Leakage VDDC based on leakage ID. 546 * 547 * @param hwmgr the address of the powerplay hardware manager. 548 * @return always 0. 549 */ 550 static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr) 551 { 552 struct vega10_hwmgr *data = hwmgr->backend; 553 uint16_t vv_id; 554 uint32_t vddc = 0; 555 uint16_t i, j; 556 uint32_t sclk = 0; 557 struct phm_ppt_v2_information *table_info = 558 (struct phm_ppt_v2_information *)hwmgr->pptable; 559 struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table = 560 table_info->vdd_dep_on_socclk; 561 int result; 562 563 for (i = 0; i < VEGA10_MAX_LEAKAGE_COUNT; i++) { 564 vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; 565 566 if (!vega10_get_socclk_for_voltage_evv(hwmgr, 567 table_info->vddc_lookup_table, vv_id, &sclk)) { 568 if (PP_CAP(PHM_PlatformCaps_ClockStretcher)) { 569 for (j = 1; j < socclk_table->count; j++) { 570 if (socclk_table->entries[j].clk == sclk && 571 socclk_table->entries[j].cks_enable == 0) { 572 sclk += 5000; 573 break; 574 } 575 } 576 } 577 578 PP_ASSERT_WITH_CODE(!atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, 579 VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc), 580 "Error retrieving EVV voltage value!", 581 continue); 582 583 584 /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */ 585 PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0), 586 "Invalid VDDC value", result = -EINVAL;); 587 588 /* the voltage should not be zero nor equal to leakage ID */ 589 if (vddc != 0 && vddc != vv_id) { 590 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100); 591 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id; 592 data->vddc_leakage.count++; 593 } 594 } 595 } 596 597 return 0; 598 } 599 600 /** 601 * Change virtual leakage voltage to actual value. 602 * 603 * @param hwmgr the address of the powerplay hardware manager. 604 * @param pointer to changing voltage 605 * @param pointer to leakage table 606 */ 607 static void vega10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr, 608 uint16_t *voltage, struct vega10_leakage_voltage *leakage_table) 609 { 610 uint32_t index; 611 612 /* search for leakage voltage ID 0xff01 ~ 0xff08 */ 613 for (index = 0; index < leakage_table->count; index++) { 614 /* if this voltage matches a leakage voltage ID */ 615 /* patch with actual leakage voltage */ 616 if (leakage_table->leakage_id[index] == *voltage) { 617 *voltage = leakage_table->actual_voltage[index]; 618 break; 619 } 620 } 621 622 if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) 623 pr_info("Voltage value looks like a Leakage ID but it's not patched\n"); 624 } 625 626 /** 627 * Patch voltage lookup table by EVV leakages. 628 * 629 * @param hwmgr the address of the powerplay hardware manager. 630 * @param pointer to voltage lookup table 631 * @param pointer to leakage table 632 * @return always 0 633 */ 634 static int vega10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, 635 phm_ppt_v1_voltage_lookup_table *lookup_table, 636 struct vega10_leakage_voltage *leakage_table) 637 { 638 uint32_t i; 639 640 for (i = 0; i < lookup_table->count; i++) 641 vega10_patch_with_vdd_leakage(hwmgr, 642 &lookup_table->entries[i].us_vdd, leakage_table); 643 644 return 0; 645 } 646 647 static int vega10_patch_clock_voltage_limits_with_vddc_leakage( 648 struct pp_hwmgr *hwmgr, struct vega10_leakage_voltage *leakage_table, 649 uint16_t *vddc) 650 { 651 vega10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); 652 653 return 0; 654 } 655 #endif 656 657 static int vega10_patch_voltage_dependency_tables_with_lookup_table( 658 struct pp_hwmgr *hwmgr) 659 { 660 uint8_t entry_id, voltage_id; 661 unsigned i; 662 struct phm_ppt_v2_information *table_info = 663 (struct phm_ppt_v2_information *)(hwmgr->pptable); 664 struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = 665 table_info->mm_dep_table; 666 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = 667 table_info->vdd_dep_on_mclk; 668 669 for (i = 0; i < 6; i++) { 670 struct phm_ppt_v1_clock_voltage_dependency_table *vdt; 671 switch (i) { 672 case 0: vdt = table_info->vdd_dep_on_socclk; break; 673 case 1: vdt = table_info->vdd_dep_on_sclk; break; 674 case 2: vdt = table_info->vdd_dep_on_dcefclk; break; 675 case 3: vdt = table_info->vdd_dep_on_pixclk; break; 676 case 4: vdt = table_info->vdd_dep_on_dispclk; break; 677 case 5: vdt = table_info->vdd_dep_on_phyclk; break; 678 } 679 680 for (entry_id = 0; entry_id < vdt->count; entry_id++) { 681 voltage_id = vdt->entries[entry_id].vddInd; 682 vdt->entries[entry_id].vddc = 683 table_info->vddc_lookup_table->entries[voltage_id].us_vdd; 684 } 685 } 686 687 for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { 688 voltage_id = mm_table->entries[entry_id].vddcInd; 689 mm_table->entries[entry_id].vddc = 690 table_info->vddc_lookup_table->entries[voltage_id].us_vdd; 691 } 692 693 for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { 694 voltage_id = mclk_table->entries[entry_id].vddInd; 695 mclk_table->entries[entry_id].vddc = 696 table_info->vddc_lookup_table->entries[voltage_id].us_vdd; 697 voltage_id = mclk_table->entries[entry_id].vddciInd; 698 mclk_table->entries[entry_id].vddci = 699 table_info->vddci_lookup_table->entries[voltage_id].us_vdd; 700 voltage_id = mclk_table->entries[entry_id].mvddInd; 701 mclk_table->entries[entry_id].mvdd = 702 table_info->vddmem_lookup_table->entries[voltage_id].us_vdd; 703 } 704 705 706 return 0; 707 708 } 709 710 static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr, 711 struct phm_ppt_v1_voltage_lookup_table *lookup_table) 712 { 713 uint32_t table_size, i, j; 714 715 PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count, 716 "Lookup table is empty", return -EINVAL); 717 718 table_size = lookup_table->count; 719 720 /* Sorting voltages */ 721 for (i = 0; i < table_size - 1; i++) { 722 for (j = i + 1; j > 0; j--) { 723 if (lookup_table->entries[j].us_vdd < 724 lookup_table->entries[j - 1].us_vdd) { 725 swap(lookup_table->entries[j - 1], 726 lookup_table->entries[j]); 727 } 728 } 729 } 730 731 return 0; 732 } 733 734 static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr) 735 { 736 int result = 0; 737 int tmp_result; 738 struct phm_ppt_v2_information *table_info = 739 (struct phm_ppt_v2_information *)(hwmgr->pptable); 740 #ifdef PPLIB_VEGA10_EVV_SUPPORT 741 struct vega10_hwmgr *data = hwmgr->backend; 742 743 tmp_result = vega10_patch_lookup_table_with_leakage(hwmgr, 744 table_info->vddc_lookup_table, &(data->vddc_leakage)); 745 if (tmp_result) 746 result = tmp_result; 747 748 tmp_result = vega10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, 749 &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); 750 if (tmp_result) 751 result = tmp_result; 752 #endif 753 754 tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr); 755 if (tmp_result) 756 result = tmp_result; 757 758 tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); 759 if (tmp_result) 760 result = tmp_result; 761 762 return result; 763 } 764 765 static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) 766 { 767 struct phm_ppt_v2_information *table_info = 768 (struct phm_ppt_v2_information *)(hwmgr->pptable); 769 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = 770 table_info->vdd_dep_on_socclk; 771 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = 772 table_info->vdd_dep_on_mclk; 773 774 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table, 775 "VDD dependency on SCLK table is missing. This table is mandatory", return -EINVAL); 776 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, 777 "VDD dependency on SCLK table is empty. This table is mandatory", return -EINVAL); 778 779 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table, 780 "VDD dependency on MCLK table is missing. This table is mandatory", return -EINVAL); 781 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, 782 "VDD dependency on MCLK table is empty. This table is mandatory", return -EINVAL); 783 784 table_info->max_clock_voltage_on_ac.sclk = 785 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; 786 table_info->max_clock_voltage_on_ac.mclk = 787 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; 788 table_info->max_clock_voltage_on_ac.vddc = 789 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; 790 table_info->max_clock_voltage_on_ac.vddci = 791 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; 792 793 hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = 794 table_info->max_clock_voltage_on_ac.sclk; 795 hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = 796 table_info->max_clock_voltage_on_ac.mclk; 797 hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = 798 table_info->max_clock_voltage_on_ac.vddc; 799 hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = 800 table_info->max_clock_voltage_on_ac.vddci; 801 802 return 0; 803 } 804 805 static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) 806 { 807 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); 808 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; 809 810 kfree(hwmgr->backend); 811 hwmgr->backend = NULL; 812 813 return 0; 814 } 815 816 static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) 817 { 818 int result = 0; 819 struct vega10_hwmgr *data; 820 uint32_t config_telemetry = 0; 821 struct pp_atomfwctrl_voltage_table vol_table; 822 struct amdgpu_device *adev = hwmgr->adev; 823 824 data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL); 825 if (data == NULL) 826 return -ENOMEM; 827 828 hwmgr->backend = data; 829 830 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; 831 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; 832 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; 833 834 vega10_set_default_registry_data(hwmgr); 835 data->disable_dpm_mask = 0xff; 836 837 /* need to set voltage control types before EVV patching */ 838 data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE; 839 data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE; 840 data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE; 841 842 /* VDDCR_SOC */ 843 if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, 844 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) { 845 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr, 846 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2, 847 &vol_table)) { 848 config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) | 849 (vol_table.telemetry_offset & 0xff); 850 data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2; 851 } 852 } else { 853 kfree(hwmgr->backend); 854 hwmgr->backend = NULL; 855 PP_ASSERT_WITH_CODE(false, 856 "VDDCR_SOC is not SVID2!", 857 return -1); 858 } 859 860 /* MVDDC */ 861 if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, 862 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) { 863 if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr, 864 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2, 865 &vol_table)) { 866 config_telemetry |= 867 ((vol_table.telemetry_slope << 24) & 0xff000000) | 868 ((vol_table.telemetry_offset << 16) & 0xff0000); 869 data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2; 870 } 871 } 872 873 /* VDDCI_MEM */ 874 if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) { 875 if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, 876 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) 877 data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO; 878 } 879 880 data->config_telemetry = config_telemetry; 881 882 vega10_set_features_platform_caps(hwmgr); 883 884 vega10_init_dpm_defaults(hwmgr); 885 886 #ifdef PPLIB_VEGA10_EVV_SUPPORT 887 /* Get leakage voltage based on leakage ID. */ 888 PP_ASSERT_WITH_CODE(!vega10_get_evv_voltages(hwmgr), 889 "Get EVV Voltage Failed. Abort Driver loading!", 890 return -1); 891 #endif 892 893 /* Patch our voltage dependency table with actual leakage voltage 894 * We need to perform leakage translation before it's used by other functions 895 */ 896 vega10_complete_dependency_tables(hwmgr); 897 898 /* Parse pptable data read from VBIOS */ 899 vega10_set_private_data_based_on_pptable(hwmgr); 900 901 data->is_tlu_enabled = false; 902 903 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = 904 VEGA10_MAX_HARDWARE_POWERLEVELS; 905 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; 906 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; 907 908 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ 909 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ 910 hwmgr->platform_descriptor.clockStep.engineClock = 500; 911 hwmgr->platform_descriptor.clockStep.memoryClock = 500; 912 913 data->total_active_cus = adev->gfx.cu_info.number; 914 if (!hwmgr->not_vf) 915 return result; 916 917 /* Setup default Overdrive Fan control settings */ 918 data->odn_fan_table.target_fan_speed = 919 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM; 920 data->odn_fan_table.target_temperature = 921 hwmgr->thermal_controller. 922 advanceFanControlParameters.ucTargetTemperature; 923 data->odn_fan_table.min_performance_clock = 924 hwmgr->thermal_controller.advanceFanControlParameters. 925 ulMinFanSCLKAcousticLimit; 926 data->odn_fan_table.min_fan_limit = 927 hwmgr->thermal_controller. 928 advanceFanControlParameters.usFanPWMMinLimit * 929 hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100; 930 931 data->mem_channels = (RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0) & 932 DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >> 933 DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT; 934 PP_ASSERT_WITH_CODE(data->mem_channels < ARRAY_SIZE(channel_number), 935 "Mem Channel Index Exceeded maximum!", 936 return -EINVAL); 937 938 return result; 939 } 940 941 static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr) 942 { 943 struct vega10_hwmgr *data = hwmgr->backend; 944 945 data->low_sclk_interrupt_threshold = 0; 946 947 return 0; 948 } 949 950 static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr) 951 { 952 struct vega10_hwmgr *data = hwmgr->backend; 953 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 954 955 struct pp_atomfwctrl_voltage_table table; 956 uint8_t i, j; 957 uint32_t mask = 0; 958 uint32_t tmp; 959 int32_t ret = 0; 960 961 ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM, 962 VOLTAGE_OBJ_GPIO_LUT, &table); 963 964 if (!ret) { 965 tmp = table.mask_low; 966 for (i = 0, j = 0; i < 32; i++) { 967 if (tmp & 1) { 968 mask |= (uint32_t)(i << (8 * j)); 969 if (++j >= 3) 970 break; 971 } 972 tmp >>= 1; 973 } 974 } 975 976 pp_table->LedPin0 = (uint8_t)(mask & 0xff); 977 pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff); 978 pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff); 979 return 0; 980 } 981 982 static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr) 983 { 984 if (!hwmgr->not_vf) 985 return 0; 986 987 PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr), 988 "Failed to init sclk threshold!", 989 return -EINVAL); 990 991 PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr), 992 "Failed to set up led dpm config!", 993 return -EINVAL); 994 995 smum_send_msg_to_smc_with_parameter(hwmgr, 996 PPSMC_MSG_NumOfDisplays, 997 0, 998 NULL); 999 1000 return 0; 1001 } 1002 1003 /** 1004 * Remove repeated voltage values and create table with unique values. 1005 * 1006 * @param hwmgr the address of the powerplay hardware manager. 1007 * @param vol_table the pointer to changing voltage table 1008 * @return 0 in success 1009 */ 1010 1011 static int vega10_trim_voltage_table(struct pp_hwmgr *hwmgr, 1012 struct pp_atomfwctrl_voltage_table *vol_table) 1013 { 1014 uint32_t i, j; 1015 uint16_t vvalue; 1016 bool found = false; 1017 struct pp_atomfwctrl_voltage_table *table; 1018 1019 PP_ASSERT_WITH_CODE(vol_table, 1020 "Voltage Table empty.", return -EINVAL); 1021 table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table), 1022 GFP_KERNEL); 1023 1024 if (!table) 1025 return -ENOMEM; 1026 1027 table->mask_low = vol_table->mask_low; 1028 table->phase_delay = vol_table->phase_delay; 1029 1030 for (i = 0; i < vol_table->count; i++) { 1031 vvalue = vol_table->entries[i].value; 1032 found = false; 1033 1034 for (j = 0; j < table->count; j++) { 1035 if (vvalue == table->entries[j].value) { 1036 found = true; 1037 break; 1038 } 1039 } 1040 1041 if (!found) { 1042 table->entries[table->count].value = vvalue; 1043 table->entries[table->count].smio_low = 1044 vol_table->entries[i].smio_low; 1045 table->count++; 1046 } 1047 } 1048 1049 memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table)); 1050 kfree(table); 1051 1052 return 0; 1053 } 1054 1055 static int vega10_get_mvdd_voltage_table(struct pp_hwmgr *hwmgr, 1056 phm_ppt_v1_clock_voltage_dependency_table *dep_table, 1057 struct pp_atomfwctrl_voltage_table *vol_table) 1058 { 1059 int i; 1060 1061 PP_ASSERT_WITH_CODE(dep_table->count, 1062 "Voltage Dependency Table empty.", 1063 return -EINVAL); 1064 1065 vol_table->mask_low = 0; 1066 vol_table->phase_delay = 0; 1067 vol_table->count = dep_table->count; 1068 1069 for (i = 0; i < vol_table->count; i++) { 1070 vol_table->entries[i].value = dep_table->entries[i].mvdd; 1071 vol_table->entries[i].smio_low = 0; 1072 } 1073 1074 PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, 1075 vol_table), 1076 "Failed to trim MVDD Table!", 1077 return -1); 1078 1079 return 0; 1080 } 1081 1082 static int vega10_get_vddci_voltage_table(struct pp_hwmgr *hwmgr, 1083 phm_ppt_v1_clock_voltage_dependency_table *dep_table, 1084 struct pp_atomfwctrl_voltage_table *vol_table) 1085 { 1086 uint32_t i; 1087 1088 PP_ASSERT_WITH_CODE(dep_table->count, 1089 "Voltage Dependency Table empty.", 1090 return -EINVAL); 1091 1092 vol_table->mask_low = 0; 1093 vol_table->phase_delay = 0; 1094 vol_table->count = dep_table->count; 1095 1096 for (i = 0; i < dep_table->count; i++) { 1097 vol_table->entries[i].value = dep_table->entries[i].vddci; 1098 vol_table->entries[i].smio_low = 0; 1099 } 1100 1101 PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, vol_table), 1102 "Failed to trim VDDCI table.", 1103 return -1); 1104 1105 return 0; 1106 } 1107 1108 static int vega10_get_vdd_voltage_table(struct pp_hwmgr *hwmgr, 1109 phm_ppt_v1_clock_voltage_dependency_table *dep_table, 1110 struct pp_atomfwctrl_voltage_table *vol_table) 1111 { 1112 int i; 1113 1114 PP_ASSERT_WITH_CODE(dep_table->count, 1115 "Voltage Dependency Table empty.", 1116 return -EINVAL); 1117 1118 vol_table->mask_low = 0; 1119 vol_table->phase_delay = 0; 1120 vol_table->count = dep_table->count; 1121 1122 for (i = 0; i < vol_table->count; i++) { 1123 vol_table->entries[i].value = dep_table->entries[i].vddc; 1124 vol_table->entries[i].smio_low = 0; 1125 } 1126 1127 return 0; 1128 } 1129 1130 /* ---- Voltage Tables ---- 1131 * If the voltage table would be bigger than 1132 * what will fit into the state table on 1133 * the SMC keep only the higher entries. 1134 */ 1135 static void vega10_trim_voltage_table_to_fit_state_table( 1136 struct pp_hwmgr *hwmgr, 1137 uint32_t max_vol_steps, 1138 struct pp_atomfwctrl_voltage_table *vol_table) 1139 { 1140 unsigned int i, diff; 1141 1142 if (vol_table->count <= max_vol_steps) 1143 return; 1144 1145 diff = vol_table->count - max_vol_steps; 1146 1147 for (i = 0; i < max_vol_steps; i++) 1148 vol_table->entries[i] = vol_table->entries[i + diff]; 1149 1150 vol_table->count = max_vol_steps; 1151 } 1152 1153 /** 1154 * Create Voltage Tables. 1155 * 1156 * @param hwmgr the address of the powerplay hardware manager. 1157 * @return always 0 1158 */ 1159 static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr) 1160 { 1161 struct vega10_hwmgr *data = hwmgr->backend; 1162 struct phm_ppt_v2_information *table_info = 1163 (struct phm_ppt_v2_information *)hwmgr->pptable; 1164 int result; 1165 1166 if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 || 1167 data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) { 1168 result = vega10_get_mvdd_voltage_table(hwmgr, 1169 table_info->vdd_dep_on_mclk, 1170 &(data->mvdd_voltage_table)); 1171 PP_ASSERT_WITH_CODE(!result, 1172 "Failed to retrieve MVDDC table!", 1173 return result); 1174 } 1175 1176 if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) { 1177 result = vega10_get_vddci_voltage_table(hwmgr, 1178 table_info->vdd_dep_on_mclk, 1179 &(data->vddci_voltage_table)); 1180 PP_ASSERT_WITH_CODE(!result, 1181 "Failed to retrieve VDDCI_MEM table!", 1182 return result); 1183 } 1184 1185 if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 || 1186 data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) { 1187 result = vega10_get_vdd_voltage_table(hwmgr, 1188 table_info->vdd_dep_on_sclk, 1189 &(data->vddc_voltage_table)); 1190 PP_ASSERT_WITH_CODE(!result, 1191 "Failed to retrieve VDDCR_SOC table!", 1192 return result); 1193 } 1194 1195 PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 16, 1196 "Too many voltage values for VDDC. Trimming to fit state table.", 1197 vega10_trim_voltage_table_to_fit_state_table(hwmgr, 1198 16, &(data->vddc_voltage_table))); 1199 1200 PP_ASSERT_WITH_CODE(data->vddci_voltage_table.count <= 16, 1201 "Too many voltage values for VDDCI. Trimming to fit state table.", 1202 vega10_trim_voltage_table_to_fit_state_table(hwmgr, 1203 16, &(data->vddci_voltage_table))); 1204 1205 PP_ASSERT_WITH_CODE(data->mvdd_voltage_table.count <= 16, 1206 "Too many voltage values for MVDD. Trimming to fit state table.", 1207 vega10_trim_voltage_table_to_fit_state_table(hwmgr, 1208 16, &(data->mvdd_voltage_table))); 1209 1210 1211 return 0; 1212 } 1213 1214 /* 1215 * @fn vega10_init_dpm_state 1216 * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. 1217 * 1218 * @param dpm_state - the address of the DPM Table to initiailize. 1219 * @return None. 1220 */ 1221 static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state) 1222 { 1223 dpm_state->soft_min_level = 0xff; 1224 dpm_state->soft_max_level = 0xff; 1225 dpm_state->hard_min_level = 0xff; 1226 dpm_state->hard_max_level = 0xff; 1227 } 1228 1229 static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr, 1230 struct vega10_single_dpm_table *dpm_table, 1231 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table) 1232 { 1233 int i; 1234 1235 dpm_table->count = 0; 1236 1237 for (i = 0; i < dep_table->count; i++) { 1238 if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <= 1239 dep_table->entries[i].clk) { 1240 dpm_table->dpm_levels[dpm_table->count].value = 1241 dep_table->entries[i].clk; 1242 dpm_table->dpm_levels[dpm_table->count].enabled = true; 1243 dpm_table->count++; 1244 } 1245 } 1246 } 1247 static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr) 1248 { 1249 struct vega10_hwmgr *data = hwmgr->backend; 1250 struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); 1251 struct phm_ppt_v2_information *table_info = 1252 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1253 struct phm_ppt_v1_pcie_table *bios_pcie_table = 1254 table_info->pcie_table; 1255 uint32_t i; 1256 1257 PP_ASSERT_WITH_CODE(bios_pcie_table->count, 1258 "Incorrect number of PCIE States from VBIOS!", 1259 return -1); 1260 1261 for (i = 0; i < NUM_LINK_LEVELS; i++) { 1262 if (data->registry_data.pcieSpeedOverride) 1263 pcie_table->pcie_gen[i] = 1264 data->registry_data.pcieSpeedOverride; 1265 else 1266 pcie_table->pcie_gen[i] = 1267 bios_pcie_table->entries[i].gen_speed; 1268 1269 if (data->registry_data.pcieLaneOverride) 1270 pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width( 1271 data->registry_data.pcieLaneOverride); 1272 else 1273 pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width( 1274 bios_pcie_table->entries[i].lane_width); 1275 if (data->registry_data.pcieClockOverride) 1276 pcie_table->lclk[i] = 1277 data->registry_data.pcieClockOverride; 1278 else 1279 pcie_table->lclk[i] = 1280 bios_pcie_table->entries[i].pcie_sclk; 1281 } 1282 1283 pcie_table->count = NUM_LINK_LEVELS; 1284 1285 return 0; 1286 } 1287 1288 /* 1289 * This function is to initialize all DPM state tables 1290 * for SMU based on the dependency table. 1291 * Dynamic state patching function will then trim these 1292 * state tables to the allowed range based 1293 * on the power policy or external client requests, 1294 * such as UVD request, etc. 1295 */ 1296 static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) 1297 { 1298 struct vega10_hwmgr *data = hwmgr->backend; 1299 struct phm_ppt_v2_information *table_info = 1300 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1301 struct vega10_single_dpm_table *dpm_table; 1302 uint32_t i; 1303 1304 struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table = 1305 table_info->vdd_dep_on_socclk; 1306 struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table = 1307 table_info->vdd_dep_on_sclk; 1308 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = 1309 table_info->vdd_dep_on_mclk; 1310 struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table = 1311 table_info->mm_dep_table; 1312 struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table = 1313 table_info->vdd_dep_on_dcefclk; 1314 struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table = 1315 table_info->vdd_dep_on_pixclk; 1316 struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table = 1317 table_info->vdd_dep_on_dispclk; 1318 struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table = 1319 table_info->vdd_dep_on_phyclk; 1320 1321 PP_ASSERT_WITH_CODE(dep_soc_table, 1322 "SOCCLK dependency table is missing. This table is mandatory", 1323 return -EINVAL); 1324 PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1, 1325 "SOCCLK dependency table is empty. This table is mandatory", 1326 return -EINVAL); 1327 1328 PP_ASSERT_WITH_CODE(dep_gfx_table, 1329 "GFXCLK dependency table is missing. This table is mandatory", 1330 return -EINVAL); 1331 PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1, 1332 "GFXCLK dependency table is empty. This table is mandatory", 1333 return -EINVAL); 1334 1335 PP_ASSERT_WITH_CODE(dep_mclk_table, 1336 "MCLK dependency table is missing. This table is mandatory", 1337 return -EINVAL); 1338 PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, 1339 "MCLK dependency table has to have is missing. This table is mandatory", 1340 return -EINVAL); 1341 1342 /* Initialize Sclk DPM table based on allow Sclk values */ 1343 dpm_table = &(data->dpm_table.soc_table); 1344 vega10_setup_default_single_dpm_table(hwmgr, 1345 dpm_table, 1346 dep_soc_table); 1347 1348 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1349 1350 dpm_table = &(data->dpm_table.gfx_table); 1351 vega10_setup_default_single_dpm_table(hwmgr, 1352 dpm_table, 1353 dep_gfx_table); 1354 if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0) 1355 hwmgr->platform_descriptor.overdriveLimit.engineClock = 1356 dpm_table->dpm_levels[dpm_table->count-1].value; 1357 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1358 1359 /* Initialize Mclk DPM table based on allow Mclk values */ 1360 data->dpm_table.mem_table.count = 0; 1361 dpm_table = &(data->dpm_table.mem_table); 1362 vega10_setup_default_single_dpm_table(hwmgr, 1363 dpm_table, 1364 dep_mclk_table); 1365 if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) 1366 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 1367 dpm_table->dpm_levels[dpm_table->count-1].value; 1368 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1369 1370 data->dpm_table.eclk_table.count = 0; 1371 dpm_table = &(data->dpm_table.eclk_table); 1372 for (i = 0; i < dep_mm_table->count; i++) { 1373 if (i == 0 || dpm_table->dpm_levels 1374 [dpm_table->count - 1].value <= 1375 dep_mm_table->entries[i].eclk) { 1376 dpm_table->dpm_levels[dpm_table->count].value = 1377 dep_mm_table->entries[i].eclk; 1378 dpm_table->dpm_levels[dpm_table->count].enabled = 1379 (i == 0) ? true : false; 1380 dpm_table->count++; 1381 } 1382 } 1383 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1384 1385 data->dpm_table.vclk_table.count = 0; 1386 data->dpm_table.dclk_table.count = 0; 1387 dpm_table = &(data->dpm_table.vclk_table); 1388 for (i = 0; i < dep_mm_table->count; i++) { 1389 if (i == 0 || dpm_table->dpm_levels 1390 [dpm_table->count - 1].value <= 1391 dep_mm_table->entries[i].vclk) { 1392 dpm_table->dpm_levels[dpm_table->count].value = 1393 dep_mm_table->entries[i].vclk; 1394 dpm_table->dpm_levels[dpm_table->count].enabled = 1395 (i == 0) ? true : false; 1396 dpm_table->count++; 1397 } 1398 } 1399 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1400 1401 dpm_table = &(data->dpm_table.dclk_table); 1402 for (i = 0; i < dep_mm_table->count; i++) { 1403 if (i == 0 || dpm_table->dpm_levels 1404 [dpm_table->count - 1].value <= 1405 dep_mm_table->entries[i].dclk) { 1406 dpm_table->dpm_levels[dpm_table->count].value = 1407 dep_mm_table->entries[i].dclk; 1408 dpm_table->dpm_levels[dpm_table->count].enabled = 1409 (i == 0) ? true : false; 1410 dpm_table->count++; 1411 } 1412 } 1413 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1414 1415 /* Assume there is no headless Vega10 for now */ 1416 dpm_table = &(data->dpm_table.dcef_table); 1417 vega10_setup_default_single_dpm_table(hwmgr, 1418 dpm_table, 1419 dep_dcef_table); 1420 1421 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1422 1423 dpm_table = &(data->dpm_table.pixel_table); 1424 vega10_setup_default_single_dpm_table(hwmgr, 1425 dpm_table, 1426 dep_pix_table); 1427 1428 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1429 1430 dpm_table = &(data->dpm_table.display_table); 1431 vega10_setup_default_single_dpm_table(hwmgr, 1432 dpm_table, 1433 dep_disp_table); 1434 1435 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1436 1437 dpm_table = &(data->dpm_table.phy_table); 1438 vega10_setup_default_single_dpm_table(hwmgr, 1439 dpm_table, 1440 dep_phy_table); 1441 1442 vega10_init_dpm_state(&(dpm_table->dpm_state)); 1443 1444 vega10_setup_default_pcie_table(hwmgr); 1445 1446 /* Zero out the saved copy of the CUSTOM profile 1447 * This will be checked when trying to set the profile 1448 * and will require that new values be passed in 1449 */ 1450 data->custom_profile_mode[0] = 0; 1451 data->custom_profile_mode[1] = 0; 1452 data->custom_profile_mode[2] = 0; 1453 data->custom_profile_mode[3] = 0; 1454 1455 /* save a copy of the default DPM table */ 1456 memcpy(&(data->golden_dpm_table), &(data->dpm_table), 1457 sizeof(struct vega10_dpm_table)); 1458 1459 return 0; 1460 } 1461 1462 /* 1463 * @fn vega10_populate_ulv_state 1464 * @brief Function to provide parameters for Utral Low Voltage state to SMC. 1465 * 1466 * @param hwmgr - the address of the hardware manager. 1467 * @return Always 0. 1468 */ 1469 static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr) 1470 { 1471 struct vega10_hwmgr *data = hwmgr->backend; 1472 struct phm_ppt_v2_information *table_info = 1473 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1474 1475 data->smc_state_table.pp_table.UlvOffsetVid = 1476 (uint8_t)table_info->us_ulv_voltage_offset; 1477 1478 data->smc_state_table.pp_table.UlvSmnclkDid = 1479 (uint8_t)(table_info->us_ulv_smnclk_did); 1480 data->smc_state_table.pp_table.UlvMp1clkDid = 1481 (uint8_t)(table_info->us_ulv_mp1clk_did); 1482 data->smc_state_table.pp_table.UlvGfxclkBypass = 1483 (uint8_t)(table_info->us_ulv_gfxclk_bypass); 1484 data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 = 1485 (uint8_t)(data->vddc_voltage_table.psi0_enable); 1486 data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 = 1487 (uint8_t)(data->vddc_voltage_table.psi1_enable); 1488 1489 return 0; 1490 } 1491 1492 static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr, 1493 uint32_t lclock, uint8_t *curr_lclk_did) 1494 { 1495 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 1496 1497 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10( 1498 hwmgr, 1499 COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 1500 lclock, ÷rs), 1501 "Failed to get LCLK clock settings from VBIOS!", 1502 return -1); 1503 1504 *curr_lclk_did = dividers.ulDid; 1505 1506 return 0; 1507 } 1508 1509 static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr) 1510 { 1511 int result = -1; 1512 struct vega10_hwmgr *data = hwmgr->backend; 1513 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1514 struct vega10_pcie_table *pcie_table = 1515 &(data->dpm_table.pcie_table); 1516 uint32_t i, j; 1517 1518 for (i = 0; i < pcie_table->count; i++) { 1519 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i]; 1520 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i]; 1521 1522 result = vega10_populate_single_lclk_level(hwmgr, 1523 pcie_table->lclk[i], &(pp_table->LclkDid[i])); 1524 if (result) { 1525 pr_info("Populate LClock Level %d Failed!\n", i); 1526 return result; 1527 } 1528 } 1529 1530 j = i - 1; 1531 while (i < NUM_LINK_LEVELS) { 1532 pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j]; 1533 pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j]; 1534 1535 result = vega10_populate_single_lclk_level(hwmgr, 1536 pcie_table->lclk[j], &(pp_table->LclkDid[i])); 1537 if (result) { 1538 pr_info("Populate LClock Level %d Failed!\n", i); 1539 return result; 1540 } 1541 i++; 1542 } 1543 1544 return result; 1545 } 1546 1547 /** 1548 * Populates single SMC GFXSCLK structure using the provided engine clock 1549 * 1550 * @param hwmgr the address of the hardware manager 1551 * @param gfx_clock the GFX clock to use to populate the structure. 1552 * @param current_gfxclk_level location in PPTable for the SMC GFXCLK structure. 1553 */ 1554 1555 static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr, 1556 uint32_t gfx_clock, PllSetting_t *current_gfxclk_level, 1557 uint32_t *acg_freq) 1558 { 1559 struct phm_ppt_v2_information *table_info = 1560 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1561 struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk; 1562 struct vega10_hwmgr *data = hwmgr->backend; 1563 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 1564 uint32_t gfx_max_clock = 1565 hwmgr->platform_descriptor.overdriveLimit.engineClock; 1566 uint32_t i = 0; 1567 1568 if (hwmgr->od_enabled) 1569 dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *) 1570 &(data->odn_dpm_table.vdd_dep_on_sclk); 1571 else 1572 dep_on_sclk = table_info->vdd_dep_on_sclk; 1573 1574 PP_ASSERT_WITH_CODE(dep_on_sclk, 1575 "Invalid SOC_VDD-GFX_CLK Dependency Table!", 1576 return -EINVAL); 1577 1578 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) 1579 gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock; 1580 else { 1581 for (i = 0; i < dep_on_sclk->count; i++) { 1582 if (dep_on_sclk->entries[i].clk == gfx_clock) 1583 break; 1584 } 1585 PP_ASSERT_WITH_CODE(dep_on_sclk->count > i, 1586 "Cannot find gfx_clk in SOC_VDD-GFX_CLK!", 1587 return -EINVAL); 1588 } 1589 1590 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, 1591 COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK, 1592 gfx_clock, ÷rs), 1593 "Failed to get GFX Clock settings from VBIOS!", 1594 return -EINVAL); 1595 1596 /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */ 1597 current_gfxclk_level->FbMult = 1598 cpu_to_le32(dividers.ulPll_fb_mult); 1599 /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */ 1600 current_gfxclk_level->SsOn = dividers.ucPll_ss_enable; 1601 current_gfxclk_level->SsFbMult = 1602 cpu_to_le32(dividers.ulPll_ss_fbsmult); 1603 current_gfxclk_level->SsSlewFrac = 1604 cpu_to_le16(dividers.usPll_ss_slew_frac); 1605 current_gfxclk_level->Did = (uint8_t)(dividers.ulDid); 1606 1607 *acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */ 1608 1609 return 0; 1610 } 1611 1612 /** 1613 * @brief Populates single SMC SOCCLK structure using the provided clock. 1614 * 1615 * @param hwmgr - the address of the hardware manager. 1616 * @param soc_clock - the SOC clock to use to populate the structure. 1617 * @param current_socclk_level - location in PPTable for the SMC SOCCLK structure. 1618 * @return 0 on success.. 1619 */ 1620 static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr, 1621 uint32_t soc_clock, uint8_t *current_soc_did, 1622 uint8_t *current_vol_index) 1623 { 1624 struct vega10_hwmgr *data = hwmgr->backend; 1625 struct phm_ppt_v2_information *table_info = 1626 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1627 struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc; 1628 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 1629 uint32_t i; 1630 1631 if (hwmgr->od_enabled) { 1632 dep_on_soc = (struct phm_ppt_v1_clock_voltage_dependency_table *) 1633 &data->odn_dpm_table.vdd_dep_on_socclk; 1634 for (i = 0; i < dep_on_soc->count; i++) { 1635 if (dep_on_soc->entries[i].clk >= soc_clock) 1636 break; 1637 } 1638 } else { 1639 dep_on_soc = table_info->vdd_dep_on_socclk; 1640 for (i = 0; i < dep_on_soc->count; i++) { 1641 if (dep_on_soc->entries[i].clk == soc_clock) 1642 break; 1643 } 1644 } 1645 1646 PP_ASSERT_WITH_CODE(dep_on_soc->count > i, 1647 "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table", 1648 return -EINVAL); 1649 1650 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, 1651 COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 1652 soc_clock, ÷rs), 1653 "Failed to get SOC Clock settings from VBIOS!", 1654 return -EINVAL); 1655 1656 *current_soc_did = (uint8_t)dividers.ulDid; 1657 *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd); 1658 return 0; 1659 } 1660 1661 /** 1662 * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states 1663 * 1664 * @param hwmgr the address of the hardware manager 1665 */ 1666 static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) 1667 { 1668 struct vega10_hwmgr *data = hwmgr->backend; 1669 struct phm_ppt_v2_information *table_info = 1670 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1671 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1672 struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); 1673 int result = 0; 1674 uint32_t i, j; 1675 1676 for (i = 0; i < dpm_table->count; i++) { 1677 result = vega10_populate_single_gfx_level(hwmgr, 1678 dpm_table->dpm_levels[i].value, 1679 &(pp_table->GfxclkLevel[i]), 1680 &(pp_table->AcgFreqTable[i])); 1681 if (result) 1682 return result; 1683 } 1684 1685 j = i - 1; 1686 while (i < NUM_GFXCLK_DPM_LEVELS) { 1687 result = vega10_populate_single_gfx_level(hwmgr, 1688 dpm_table->dpm_levels[j].value, 1689 &(pp_table->GfxclkLevel[i]), 1690 &(pp_table->AcgFreqTable[i])); 1691 if (result) 1692 return result; 1693 i++; 1694 } 1695 1696 pp_table->GfxclkSlewRate = 1697 cpu_to_le16(table_info->us_gfxclk_slew_rate); 1698 1699 dpm_table = &(data->dpm_table.soc_table); 1700 for (i = 0; i < dpm_table->count; i++) { 1701 result = vega10_populate_single_soc_level(hwmgr, 1702 dpm_table->dpm_levels[i].value, 1703 &(pp_table->SocclkDid[i]), 1704 &(pp_table->SocDpmVoltageIndex[i])); 1705 if (result) 1706 return result; 1707 } 1708 1709 j = i - 1; 1710 while (i < NUM_SOCCLK_DPM_LEVELS) { 1711 result = vega10_populate_single_soc_level(hwmgr, 1712 dpm_table->dpm_levels[j].value, 1713 &(pp_table->SocclkDid[i]), 1714 &(pp_table->SocDpmVoltageIndex[i])); 1715 if (result) 1716 return result; 1717 i++; 1718 } 1719 1720 return result; 1721 } 1722 1723 static void vega10_populate_vddc_soc_levels(struct pp_hwmgr *hwmgr) 1724 { 1725 struct vega10_hwmgr *data = hwmgr->backend; 1726 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1727 struct phm_ppt_v2_information *table_info = hwmgr->pptable; 1728 struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; 1729 1730 uint8_t soc_vid = 0; 1731 uint32_t i, max_vddc_level; 1732 1733 if (hwmgr->od_enabled) 1734 vddc_lookup_table = (struct phm_ppt_v1_voltage_lookup_table *)&data->odn_dpm_table.vddc_lookup_table; 1735 else 1736 vddc_lookup_table = table_info->vddc_lookup_table; 1737 1738 max_vddc_level = vddc_lookup_table->count; 1739 for (i = 0; i < max_vddc_level; i++) { 1740 soc_vid = (uint8_t)convert_to_vid(vddc_lookup_table->entries[i].us_vdd); 1741 pp_table->SocVid[i] = soc_vid; 1742 } 1743 while (i < MAX_REGULAR_DPM_NUMBER) { 1744 pp_table->SocVid[i] = soc_vid; 1745 i++; 1746 } 1747 } 1748 1749 /** 1750 * @brief Populates single SMC GFXCLK structure using the provided clock. 1751 * 1752 * @param hwmgr - the address of the hardware manager. 1753 * @param mem_clock - the memory clock to use to populate the structure. 1754 * @return 0 on success.. 1755 */ 1756 static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr, 1757 uint32_t mem_clock, uint8_t *current_mem_vid, 1758 PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind) 1759 { 1760 struct vega10_hwmgr *data = hwmgr->backend; 1761 struct phm_ppt_v2_information *table_info = 1762 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1763 struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk; 1764 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 1765 uint32_t mem_max_clock = 1766 hwmgr->platform_descriptor.overdriveLimit.memoryClock; 1767 uint32_t i = 0; 1768 1769 if (hwmgr->od_enabled) 1770 dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *) 1771 &data->odn_dpm_table.vdd_dep_on_mclk; 1772 else 1773 dep_on_mclk = table_info->vdd_dep_on_mclk; 1774 1775 PP_ASSERT_WITH_CODE(dep_on_mclk, 1776 "Invalid SOC_VDD-UCLK Dependency Table!", 1777 return -EINVAL); 1778 1779 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { 1780 mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock; 1781 } else { 1782 for (i = 0; i < dep_on_mclk->count; i++) { 1783 if (dep_on_mclk->entries[i].clk == mem_clock) 1784 break; 1785 } 1786 PP_ASSERT_WITH_CODE(dep_on_mclk->count > i, 1787 "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!", 1788 return -EINVAL); 1789 } 1790 1791 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10( 1792 hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, ÷rs), 1793 "Failed to get UCLK settings from VBIOS!", 1794 return -1); 1795 1796 *current_mem_vid = 1797 (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd)); 1798 *current_mem_soc_vind = 1799 (uint8_t)(dep_on_mclk->entries[i].vddInd); 1800 current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult); 1801 current_memclk_level->Did = (uint8_t)(dividers.ulDid); 1802 1803 PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1, 1804 "Invalid Divider ID!", 1805 return -EINVAL); 1806 1807 return 0; 1808 } 1809 1810 /** 1811 * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states. 1812 * 1813 * @param pHwMgr - the address of the hardware manager. 1814 * @return PP_Result_OK on success. 1815 */ 1816 static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) 1817 { 1818 struct vega10_hwmgr *data = hwmgr->backend; 1819 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1820 struct vega10_single_dpm_table *dpm_table = 1821 &(data->dpm_table.mem_table); 1822 int result = 0; 1823 uint32_t i, j; 1824 1825 for (i = 0; i < dpm_table->count; i++) { 1826 result = vega10_populate_single_memory_level(hwmgr, 1827 dpm_table->dpm_levels[i].value, 1828 &(pp_table->MemVid[i]), 1829 &(pp_table->UclkLevel[i]), 1830 &(pp_table->MemSocVoltageIndex[i])); 1831 if (result) 1832 return result; 1833 } 1834 1835 j = i - 1; 1836 while (i < NUM_UCLK_DPM_LEVELS) { 1837 result = vega10_populate_single_memory_level(hwmgr, 1838 dpm_table->dpm_levels[j].value, 1839 &(pp_table->MemVid[i]), 1840 &(pp_table->UclkLevel[i]), 1841 &(pp_table->MemSocVoltageIndex[i])); 1842 if (result) 1843 return result; 1844 i++; 1845 } 1846 1847 pp_table->NumMemoryChannels = (uint16_t)(data->mem_channels); 1848 pp_table->MemoryChannelWidth = 1849 (uint16_t)(HBM_MEMORY_CHANNEL_WIDTH * 1850 channel_number[data->mem_channels]); 1851 1852 pp_table->LowestUclkReservedForUlv = 1853 (uint8_t)(data->lowest_uclk_reserved_for_ulv); 1854 1855 return result; 1856 } 1857 1858 static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr, 1859 DSPCLK_e disp_clock) 1860 { 1861 struct vega10_hwmgr *data = hwmgr->backend; 1862 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1863 struct phm_ppt_v2_information *table_info = 1864 (struct phm_ppt_v2_information *) 1865 (hwmgr->pptable); 1866 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; 1867 uint32_t i; 1868 uint16_t clk = 0, vddc = 0; 1869 uint8_t vid = 0; 1870 1871 switch (disp_clock) { 1872 case DSPCLK_DCEFCLK: 1873 dep_table = table_info->vdd_dep_on_dcefclk; 1874 break; 1875 case DSPCLK_DISPCLK: 1876 dep_table = table_info->vdd_dep_on_dispclk; 1877 break; 1878 case DSPCLK_PIXCLK: 1879 dep_table = table_info->vdd_dep_on_pixclk; 1880 break; 1881 case DSPCLK_PHYCLK: 1882 dep_table = table_info->vdd_dep_on_phyclk; 1883 break; 1884 default: 1885 return -1; 1886 } 1887 1888 PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS, 1889 "Number Of Entries Exceeded maximum!", 1890 return -1); 1891 1892 for (i = 0; i < dep_table->count; i++) { 1893 clk = (uint16_t)(dep_table->entries[i].clk / 100); 1894 vddc = table_info->vddc_lookup_table-> 1895 entries[dep_table->entries[i].vddInd].us_vdd; 1896 vid = (uint8_t)convert_to_vid(vddc); 1897 pp_table->DisplayClockTable[disp_clock][i].Freq = 1898 cpu_to_le16(clk); 1899 pp_table->DisplayClockTable[disp_clock][i].Vid = 1900 cpu_to_le16(vid); 1901 } 1902 1903 while (i < NUM_DSPCLK_LEVELS) { 1904 pp_table->DisplayClockTable[disp_clock][i].Freq = 1905 cpu_to_le16(clk); 1906 pp_table->DisplayClockTable[disp_clock][i].Vid = 1907 cpu_to_le16(vid); 1908 i++; 1909 } 1910 1911 return 0; 1912 } 1913 1914 static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr) 1915 { 1916 uint32_t i; 1917 1918 for (i = 0; i < DSPCLK_COUNT; i++) { 1919 PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i), 1920 "Failed to populate Clock in DisplayClockTable!", 1921 return -1); 1922 } 1923 1924 return 0; 1925 } 1926 1927 static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr, 1928 uint32_t eclock, uint8_t *current_eclk_did, 1929 uint8_t *current_soc_vol) 1930 { 1931 struct phm_ppt_v2_information *table_info = 1932 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1933 struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table = 1934 table_info->mm_dep_table; 1935 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 1936 uint32_t i; 1937 1938 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, 1939 COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 1940 eclock, ÷rs), 1941 "Failed to get ECLK clock settings from VBIOS!", 1942 return -1); 1943 1944 *current_eclk_did = (uint8_t)dividers.ulDid; 1945 1946 for (i = 0; i < dep_table->count; i++) { 1947 if (dep_table->entries[i].eclk == eclock) 1948 *current_soc_vol = dep_table->entries[i].vddcInd; 1949 } 1950 1951 return 0; 1952 } 1953 1954 static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr) 1955 { 1956 struct vega10_hwmgr *data = hwmgr->backend; 1957 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 1958 struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table); 1959 int result = -EINVAL; 1960 uint32_t i, j; 1961 1962 for (i = 0; i < dpm_table->count; i++) { 1963 result = vega10_populate_single_eclock_level(hwmgr, 1964 dpm_table->dpm_levels[i].value, 1965 &(pp_table->EclkDid[i]), 1966 &(pp_table->VceDpmVoltageIndex[i])); 1967 if (result) 1968 return result; 1969 } 1970 1971 j = i - 1; 1972 while (i < NUM_VCE_DPM_LEVELS) { 1973 result = vega10_populate_single_eclock_level(hwmgr, 1974 dpm_table->dpm_levels[j].value, 1975 &(pp_table->EclkDid[i]), 1976 &(pp_table->VceDpmVoltageIndex[i])); 1977 if (result) 1978 return result; 1979 i++; 1980 } 1981 1982 return result; 1983 } 1984 1985 static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr, 1986 uint32_t vclock, uint8_t *current_vclk_did) 1987 { 1988 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 1989 1990 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, 1991 COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 1992 vclock, ÷rs), 1993 "Failed to get VCLK clock settings from VBIOS!", 1994 return -EINVAL); 1995 1996 *current_vclk_did = (uint8_t)dividers.ulDid; 1997 1998 return 0; 1999 } 2000 2001 static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr, 2002 uint32_t dclock, uint8_t *current_dclk_did) 2003 { 2004 struct pp_atomfwctrl_clock_dividers_soc15 dividers; 2005 2006 PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, 2007 COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 2008 dclock, ÷rs), 2009 "Failed to get DCLK clock settings from VBIOS!", 2010 return -EINVAL); 2011 2012 *current_dclk_did = (uint8_t)dividers.ulDid; 2013 2014 return 0; 2015 } 2016 2017 static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr) 2018 { 2019 struct vega10_hwmgr *data = hwmgr->backend; 2020 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 2021 struct vega10_single_dpm_table *vclk_dpm_table = 2022 &(data->dpm_table.vclk_table); 2023 struct vega10_single_dpm_table *dclk_dpm_table = 2024 &(data->dpm_table.dclk_table); 2025 struct phm_ppt_v2_information *table_info = 2026 (struct phm_ppt_v2_information *)(hwmgr->pptable); 2027 struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table = 2028 table_info->mm_dep_table; 2029 int result = -EINVAL; 2030 uint32_t i, j; 2031 2032 for (i = 0; i < vclk_dpm_table->count; i++) { 2033 result = vega10_populate_single_vclock_level(hwmgr, 2034 vclk_dpm_table->dpm_levels[i].value, 2035 &(pp_table->VclkDid[i])); 2036 if (result) 2037 return result; 2038 } 2039 2040 j = i - 1; 2041 while (i < NUM_UVD_DPM_LEVELS) { 2042 result = vega10_populate_single_vclock_level(hwmgr, 2043 vclk_dpm_table->dpm_levels[j].value, 2044 &(pp_table->VclkDid[i])); 2045 if (result) 2046 return result; 2047 i++; 2048 } 2049 2050 for (i = 0; i < dclk_dpm_table->count; i++) { 2051 result = vega10_populate_single_dclock_level(hwmgr, 2052 dclk_dpm_table->dpm_levels[i].value, 2053 &(pp_table->DclkDid[i])); 2054 if (result) 2055 return result; 2056 } 2057 2058 j = i - 1; 2059 while (i < NUM_UVD_DPM_LEVELS) { 2060 result = vega10_populate_single_dclock_level(hwmgr, 2061 dclk_dpm_table->dpm_levels[j].value, 2062 &(pp_table->DclkDid[i])); 2063 if (result) 2064 return result; 2065 i++; 2066 } 2067 2068 for (i = 0; i < dep_table->count; i++) { 2069 if (dep_table->entries[i].vclk == 2070 vclk_dpm_table->dpm_levels[i].value && 2071 dep_table->entries[i].dclk == 2072 dclk_dpm_table->dpm_levels[i].value) 2073 pp_table->UvdDpmVoltageIndex[i] = 2074 dep_table->entries[i].vddcInd; 2075 else 2076 return -1; 2077 } 2078 2079 j = i - 1; 2080 while (i < NUM_UVD_DPM_LEVELS) { 2081 pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd; 2082 i++; 2083 } 2084 2085 return 0; 2086 } 2087 2088 static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr) 2089 { 2090 struct vega10_hwmgr *data = hwmgr->backend; 2091 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 2092 struct phm_ppt_v2_information *table_info = 2093 (struct phm_ppt_v2_information *)(hwmgr->pptable); 2094 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 2095 table_info->vdd_dep_on_sclk; 2096 uint32_t i; 2097 2098 for (i = 0; i < dep_table->count; i++) { 2099 pp_table->CksEnable[i] = dep_table->entries[i].cks_enable; 2100 pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset 2101 * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); 2102 } 2103 2104 return 0; 2105 } 2106 2107 static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) 2108 { 2109 struct vega10_hwmgr *data = hwmgr->backend; 2110 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 2111 struct phm_ppt_v2_information *table_info = 2112 (struct phm_ppt_v2_information *)(hwmgr->pptable); 2113 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 2114 table_info->vdd_dep_on_sclk; 2115 struct pp_atomfwctrl_avfs_parameters avfs_params = {0}; 2116 int result = 0; 2117 uint32_t i; 2118 2119 pp_table->MinVoltageVid = (uint8_t)0xff; 2120 pp_table->MaxVoltageVid = (uint8_t)0; 2121 2122 if (data->smu_features[GNLD_AVFS].supported) { 2123 result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); 2124 if (!result) { 2125 pp_table->MinVoltageVid = (uint8_t) 2126 convert_to_vid((uint16_t)(avfs_params.ulMinVddc)); 2127 pp_table->MaxVoltageVid = (uint8_t) 2128 convert_to_vid((uint16_t)(avfs_params.ulMaxVddc)); 2129 2130 pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0); 2131 pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1); 2132 pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2); 2133 pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); 2134 pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean); 2135 pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); 2136 pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor); 2137 2138 pp_table->BtcGbVdroopTableCksOff.a0 = 2139 cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0); 2140 pp_table->BtcGbVdroopTableCksOff.a0_shift = 20; 2141 pp_table->BtcGbVdroopTableCksOff.a1 = 2142 cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1); 2143 pp_table->BtcGbVdroopTableCksOff.a1_shift = 20; 2144 pp_table->BtcGbVdroopTableCksOff.a2 = 2145 cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2); 2146 pp_table->BtcGbVdroopTableCksOff.a2_shift = 20; 2147 2148 pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson; 2149 pp_table->BtcGbVdroopTableCksOn.a0 = 2150 cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0); 2151 pp_table->BtcGbVdroopTableCksOn.a0_shift = 20; 2152 pp_table->BtcGbVdroopTableCksOn.a1 = 2153 cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1); 2154 pp_table->BtcGbVdroopTableCksOn.a1_shift = 20; 2155 pp_table->BtcGbVdroopTableCksOn.a2 = 2156 cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2); 2157 pp_table->BtcGbVdroopTableCksOn.a2_shift = 20; 2158 2159 pp_table->AvfsGbCksOn.m1 = 2160 cpu_to_le32(avfs_params.ulGbFuseTableCksonM1); 2161 pp_table->AvfsGbCksOn.m2 = 2162 cpu_to_le32(avfs_params.ulGbFuseTableCksonM2); 2163 pp_table->AvfsGbCksOn.b = 2164 cpu_to_le32(avfs_params.ulGbFuseTableCksonB); 2165 pp_table->AvfsGbCksOn.m1_shift = 24; 2166 pp_table->AvfsGbCksOn.m2_shift = 12; 2167 pp_table->AvfsGbCksOn.b_shift = 0; 2168 2169 pp_table->OverrideAvfsGbCksOn = 2170 avfs_params.ucEnableGbFuseTableCkson; 2171 pp_table->AvfsGbCksOff.m1 = 2172 cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1); 2173 pp_table->AvfsGbCksOff.m2 = 2174 cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2); 2175 pp_table->AvfsGbCksOff.b = 2176 cpu_to_le32(avfs_params.ulGbFuseTableCksoffB); 2177 pp_table->AvfsGbCksOff.m1_shift = 24; 2178 pp_table->AvfsGbCksOff.m2_shift = 12; 2179 pp_table->AvfsGbCksOff.b_shift = 0; 2180 2181 for (i = 0; i < dep_table->count; i++) 2182 pp_table->StaticVoltageOffsetVid[i] = 2183 convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset)); 2184 2185 if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2186 data->disp_clk_quad_eqn_a) && 2187 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2188 data->disp_clk_quad_eqn_b)) { 2189 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = 2190 (int32_t)data->disp_clk_quad_eqn_a; 2191 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = 2192 (int32_t)data->disp_clk_quad_eqn_b; 2193 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = 2194 (int32_t)data->disp_clk_quad_eqn_c; 2195 } else { 2196 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = 2197 (int32_t)avfs_params.ulDispclk2GfxclkM1; 2198 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = 2199 (int32_t)avfs_params.ulDispclk2GfxclkM2; 2200 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = 2201 (int32_t)avfs_params.ulDispclk2GfxclkB; 2202 } 2203 2204 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24; 2205 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12; 2206 pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12; 2207 2208 if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2209 data->dcef_clk_quad_eqn_a) && 2210 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2211 data->dcef_clk_quad_eqn_b)) { 2212 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = 2213 (int32_t)data->dcef_clk_quad_eqn_a; 2214 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = 2215 (int32_t)data->dcef_clk_quad_eqn_b; 2216 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = 2217 (int32_t)data->dcef_clk_quad_eqn_c; 2218 } else { 2219 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = 2220 (int32_t)avfs_params.ulDcefclk2GfxclkM1; 2221 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = 2222 (int32_t)avfs_params.ulDcefclk2GfxclkM2; 2223 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = 2224 (int32_t)avfs_params.ulDcefclk2GfxclkB; 2225 } 2226 2227 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24; 2228 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12; 2229 pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12; 2230 2231 if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2232 data->pixel_clk_quad_eqn_a) && 2233 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2234 data->pixel_clk_quad_eqn_b)) { 2235 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = 2236 (int32_t)data->pixel_clk_quad_eqn_a; 2237 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = 2238 (int32_t)data->pixel_clk_quad_eqn_b; 2239 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = 2240 (int32_t)data->pixel_clk_quad_eqn_c; 2241 } else { 2242 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = 2243 (int32_t)avfs_params.ulPixelclk2GfxclkM1; 2244 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = 2245 (int32_t)avfs_params.ulPixelclk2GfxclkM2; 2246 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = 2247 (int32_t)avfs_params.ulPixelclk2GfxclkB; 2248 } 2249 2250 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24; 2251 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12; 2252 pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12; 2253 if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2254 data->phy_clk_quad_eqn_a) && 2255 (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != 2256 data->phy_clk_quad_eqn_b)) { 2257 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = 2258 (int32_t)data->phy_clk_quad_eqn_a; 2259 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = 2260 (int32_t)data->phy_clk_quad_eqn_b; 2261 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = 2262 (int32_t)data->phy_clk_quad_eqn_c; 2263 } else { 2264 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = 2265 (int32_t)avfs_params.ulPhyclk2GfxclkM1; 2266 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = 2267 (int32_t)avfs_params.ulPhyclk2GfxclkM2; 2268 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = 2269 (int32_t)avfs_params.ulPhyclk2GfxclkB; 2270 } 2271 2272 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24; 2273 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12; 2274 pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12; 2275 2276 pp_table->AcgBtcGbVdroopTable.a0 = avfs_params.ulAcgGbVdroopTableA0; 2277 pp_table->AcgBtcGbVdroopTable.a0_shift = 20; 2278 pp_table->AcgBtcGbVdroopTable.a1 = avfs_params.ulAcgGbVdroopTableA1; 2279 pp_table->AcgBtcGbVdroopTable.a1_shift = 20; 2280 pp_table->AcgBtcGbVdroopTable.a2 = avfs_params.ulAcgGbVdroopTableA2; 2281 pp_table->AcgBtcGbVdroopTable.a2_shift = 20; 2282 2283 pp_table->AcgAvfsGb.m1 = avfs_params.ulAcgGbFuseTableM1; 2284 pp_table->AcgAvfsGb.m2 = avfs_params.ulAcgGbFuseTableM2; 2285 pp_table->AcgAvfsGb.b = avfs_params.ulAcgGbFuseTableB; 2286 pp_table->AcgAvfsGb.m1_shift = 24; 2287 pp_table->AcgAvfsGb.m2_shift = 12; 2288 pp_table->AcgAvfsGb.b_shift = 0; 2289 2290 } else { 2291 data->smu_features[GNLD_AVFS].supported = false; 2292 } 2293 } 2294 2295 return 0; 2296 } 2297 2298 static int vega10_acg_enable(struct pp_hwmgr *hwmgr) 2299 { 2300 struct vega10_hwmgr *data = hwmgr->backend; 2301 uint32_t agc_btc_response; 2302 2303 if (data->smu_features[GNLD_ACG].supported) { 2304 if (0 == vega10_enable_smc_features(hwmgr, true, 2305 data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap)) 2306 data->smu_features[GNLD_DPM_PREFETCHER].enabled = true; 2307 2308 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg, NULL); 2309 2310 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &agc_btc_response); 2311 2312 if (1 == agc_btc_response) { 2313 if (1 == data->acg_loop_state) 2314 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop, NULL); 2315 else if (2 == data->acg_loop_state) 2316 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop, NULL); 2317 if (0 == vega10_enable_smc_features(hwmgr, true, 2318 data->smu_features[GNLD_ACG].smu_feature_bitmap)) 2319 data->smu_features[GNLD_ACG].enabled = true; 2320 } else { 2321 pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n"); 2322 data->smu_features[GNLD_ACG].enabled = false; 2323 } 2324 } 2325 2326 return 0; 2327 } 2328 2329 static int vega10_acg_disable(struct pp_hwmgr *hwmgr) 2330 { 2331 struct vega10_hwmgr *data = hwmgr->backend; 2332 2333 if (data->smu_features[GNLD_ACG].supported && 2334 data->smu_features[GNLD_ACG].enabled) 2335 if (!vega10_enable_smc_features(hwmgr, false, 2336 data->smu_features[GNLD_ACG].smu_feature_bitmap)) 2337 data->smu_features[GNLD_ACG].enabled = false; 2338 2339 return 0; 2340 } 2341 2342 static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr) 2343 { 2344 struct vega10_hwmgr *data = hwmgr->backend; 2345 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 2346 struct pp_atomfwctrl_gpio_parameters gpio_params = {0}; 2347 int result; 2348 2349 result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params); 2350 if (!result) { 2351 if (PP_CAP(PHM_PlatformCaps_RegulatorHot) && 2352 data->registry_data.regulator_hot_gpio_support) { 2353 pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio; 2354 pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity; 2355 pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio; 2356 pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity; 2357 } else { 2358 pp_table->VR0HotGpio = 0; 2359 pp_table->VR0HotPolarity = 0; 2360 pp_table->VR1HotGpio = 0; 2361 pp_table->VR1HotPolarity = 0; 2362 } 2363 2364 if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) && 2365 data->registry_data.ac_dc_switch_gpio_support) { 2366 pp_table->AcDcGpio = gpio_params.ucAcDcGpio; 2367 pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity; 2368 } else { 2369 pp_table->AcDcGpio = 0; 2370 pp_table->AcDcPolarity = 0; 2371 } 2372 } 2373 2374 return result; 2375 } 2376 2377 static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable) 2378 { 2379 struct vega10_hwmgr *data = hwmgr->backend; 2380 2381 if (data->smu_features[GNLD_AVFS].supported) { 2382 /* Already enabled or disabled */ 2383 if (!(enable ^ data->smu_features[GNLD_AVFS].enabled)) 2384 return 0; 2385 2386 if (enable) { 2387 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2388 true, 2389 data->smu_features[GNLD_AVFS].smu_feature_bitmap), 2390 "[avfs_control] Attempt to Enable AVFS feature Failed!", 2391 return -1); 2392 data->smu_features[GNLD_AVFS].enabled = true; 2393 } else { 2394 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2395 false, 2396 data->smu_features[GNLD_AVFS].smu_feature_bitmap), 2397 "[avfs_control] Attempt to Disable AVFS feature Failed!", 2398 return -1); 2399 data->smu_features[GNLD_AVFS].enabled = false; 2400 } 2401 } 2402 2403 return 0; 2404 } 2405 2406 static int vega10_update_avfs(struct pp_hwmgr *hwmgr) 2407 { 2408 struct vega10_hwmgr *data = hwmgr->backend; 2409 2410 if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { 2411 vega10_avfs_enable(hwmgr, false); 2412 } else if (data->need_update_dpm_table) { 2413 vega10_avfs_enable(hwmgr, false); 2414 vega10_avfs_enable(hwmgr, true); 2415 } else { 2416 vega10_avfs_enable(hwmgr, true); 2417 } 2418 2419 return 0; 2420 } 2421 2422 static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr) 2423 { 2424 int result = 0; 2425 2426 uint64_t serial_number = 0; 2427 uint32_t top32, bottom32; 2428 struct phm_fuses_default fuse; 2429 2430 struct vega10_hwmgr *data = hwmgr->backend; 2431 AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table); 2432 2433 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); 2434 2435 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); 2436 2437 serial_number = ((uint64_t)bottom32 << 32) | top32; 2438 2439 if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) { 2440 avfs_fuse_table->VFT0_b = fuse.VFT0_b; 2441 avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1; 2442 avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2; 2443 avfs_fuse_table->VFT1_b = fuse.VFT1_b; 2444 avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1; 2445 avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2; 2446 avfs_fuse_table->VFT2_b = fuse.VFT2_b; 2447 avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1; 2448 avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2; 2449 result = smum_smc_table_manager(hwmgr, (uint8_t *)avfs_fuse_table, 2450 AVFSFUSETABLE, false); 2451 PP_ASSERT_WITH_CODE(!result, 2452 "Failed to upload FuseOVerride!", 2453 ); 2454 } 2455 2456 return result; 2457 } 2458 2459 static void vega10_check_dpm_table_updated(struct pp_hwmgr *hwmgr) 2460 { 2461 struct vega10_hwmgr *data = hwmgr->backend; 2462 struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); 2463 struct phm_ppt_v2_information *table_info = hwmgr->pptable; 2464 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; 2465 struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table; 2466 uint32_t i; 2467 2468 dep_table = table_info->vdd_dep_on_mclk; 2469 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_mclk); 2470 2471 for (i = 0; i < dep_table->count; i++) { 2472 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { 2473 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK; 2474 return; 2475 } 2476 } 2477 2478 dep_table = table_info->vdd_dep_on_sclk; 2479 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_sclk); 2480 for (i = 0; i < dep_table->count; i++) { 2481 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { 2482 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK; 2483 return; 2484 } 2485 } 2486 } 2487 2488 /** 2489 * Initializes the SMC table and uploads it 2490 * 2491 * @param hwmgr the address of the powerplay hardware manager. 2492 * @param pInput the pointer to input data (PowerState) 2493 * @return always 0 2494 */ 2495 static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) 2496 { 2497 int result; 2498 struct vega10_hwmgr *data = hwmgr->backend; 2499 struct phm_ppt_v2_information *table_info = 2500 (struct phm_ppt_v2_information *)(hwmgr->pptable); 2501 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 2502 struct pp_atomfwctrl_voltage_table voltage_table; 2503 struct pp_atomfwctrl_bios_boot_up_values boot_up_values; 2504 struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); 2505 2506 result = vega10_setup_default_dpm_tables(hwmgr); 2507 PP_ASSERT_WITH_CODE(!result, 2508 "Failed to setup default DPM tables!", 2509 return result); 2510 2511 if (!hwmgr->not_vf) 2512 return 0; 2513 2514 /* initialize ODN table */ 2515 if (hwmgr->od_enabled) { 2516 if (odn_table->max_vddc) { 2517 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK; 2518 vega10_check_dpm_table_updated(hwmgr); 2519 } else { 2520 vega10_odn_initial_default_setting(hwmgr); 2521 } 2522 } 2523 2524 pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC, 2525 VOLTAGE_OBJ_SVID2, &voltage_table); 2526 pp_table->MaxVidStep = voltage_table.max_vid_step; 2527 2528 pp_table->GfxDpmVoltageMode = 2529 (uint8_t)(table_info->uc_gfx_dpm_voltage_mode); 2530 pp_table->SocDpmVoltageMode = 2531 (uint8_t)(table_info->uc_soc_dpm_voltage_mode); 2532 pp_table->UclkDpmVoltageMode = 2533 (uint8_t)(table_info->uc_uclk_dpm_voltage_mode); 2534 pp_table->UvdDpmVoltageMode = 2535 (uint8_t)(table_info->uc_uvd_dpm_voltage_mode); 2536 pp_table->VceDpmVoltageMode = 2537 (uint8_t)(table_info->uc_vce_dpm_voltage_mode); 2538 pp_table->Mp0DpmVoltageMode = 2539 (uint8_t)(table_info->uc_mp0_dpm_voltage_mode); 2540 2541 pp_table->DisplayDpmVoltageMode = 2542 (uint8_t)(table_info->uc_dcef_dpm_voltage_mode); 2543 2544 data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable; 2545 data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable; 2546 2547 if (data->registry_data.ulv_support && 2548 table_info->us_ulv_voltage_offset) { 2549 result = vega10_populate_ulv_state(hwmgr); 2550 PP_ASSERT_WITH_CODE(!result, 2551 "Failed to initialize ULV state!", 2552 return result); 2553 } 2554 2555 result = vega10_populate_smc_link_levels(hwmgr); 2556 PP_ASSERT_WITH_CODE(!result, 2557 "Failed to initialize Link Level!", 2558 return result); 2559 2560 result = vega10_populate_all_graphic_levels(hwmgr); 2561 PP_ASSERT_WITH_CODE(!result, 2562 "Failed to initialize Graphics Level!", 2563 return result); 2564 2565 result = vega10_populate_all_memory_levels(hwmgr); 2566 PP_ASSERT_WITH_CODE(!result, 2567 "Failed to initialize Memory Level!", 2568 return result); 2569 2570 vega10_populate_vddc_soc_levels(hwmgr); 2571 2572 result = vega10_populate_all_display_clock_levels(hwmgr); 2573 PP_ASSERT_WITH_CODE(!result, 2574 "Failed to initialize Display Level!", 2575 return result); 2576 2577 result = vega10_populate_smc_vce_levels(hwmgr); 2578 PP_ASSERT_WITH_CODE(!result, 2579 "Failed to initialize VCE Level!", 2580 return result); 2581 2582 result = vega10_populate_smc_uvd_levels(hwmgr); 2583 PP_ASSERT_WITH_CODE(!result, 2584 "Failed to initialize UVD Level!", 2585 return result); 2586 2587 if (data->registry_data.clock_stretcher_support) { 2588 result = vega10_populate_clock_stretcher_table(hwmgr); 2589 PP_ASSERT_WITH_CODE(!result, 2590 "Failed to populate Clock Stretcher Table!", 2591 return result); 2592 } 2593 2594 result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); 2595 if (!result) { 2596 data->vbios_boot_state.vddc = boot_up_values.usVddc; 2597 data->vbios_boot_state.vddci = boot_up_values.usVddci; 2598 data->vbios_boot_state.mvddc = boot_up_values.usMvddc; 2599 data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; 2600 data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; 2601 pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, 2602 SMU9_SYSPLL0_SOCCLK_ID, 0, &boot_up_values.ulSocClk); 2603 2604 pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, 2605 SMU9_SYSPLL0_DCEFCLK_ID, 0, &boot_up_values.ulDCEFClk); 2606 2607 data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; 2608 data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; 2609 if (0 != boot_up_values.usVddc) { 2610 smum_send_msg_to_smc_with_parameter(hwmgr, 2611 PPSMC_MSG_SetFloorSocVoltage, 2612 (boot_up_values.usVddc * 4), 2613 NULL); 2614 data->vbios_boot_state.bsoc_vddc_lock = true; 2615 } else { 2616 data->vbios_boot_state.bsoc_vddc_lock = false; 2617 } 2618 smum_send_msg_to_smc_with_parameter(hwmgr, 2619 PPSMC_MSG_SetMinDeepSleepDcefclk, 2620 (uint32_t)(data->vbios_boot_state.dcef_clock / 100), 2621 NULL); 2622 } 2623 2624 result = vega10_populate_avfs_parameters(hwmgr); 2625 PP_ASSERT_WITH_CODE(!result, 2626 "Failed to initialize AVFS Parameters!", 2627 return result); 2628 2629 result = vega10_populate_gpio_parameters(hwmgr); 2630 PP_ASSERT_WITH_CODE(!result, 2631 "Failed to initialize GPIO Parameters!", 2632 return result); 2633 2634 pp_table->GfxclkAverageAlpha = (uint8_t) 2635 (data->gfxclk_average_alpha); 2636 pp_table->SocclkAverageAlpha = (uint8_t) 2637 (data->socclk_average_alpha); 2638 pp_table->UclkAverageAlpha = (uint8_t) 2639 (data->uclk_average_alpha); 2640 pp_table->GfxActivityAverageAlpha = (uint8_t) 2641 (data->gfx_activity_average_alpha); 2642 2643 vega10_populate_and_upload_avfs_fuse_override(hwmgr); 2644 2645 result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); 2646 2647 PP_ASSERT_WITH_CODE(!result, 2648 "Failed to upload PPtable!", return result); 2649 2650 result = vega10_avfs_enable(hwmgr, true); 2651 PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!", 2652 return result); 2653 vega10_acg_enable(hwmgr); 2654 2655 return 0; 2656 } 2657 2658 static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr) 2659 { 2660 struct vega10_hwmgr *data = hwmgr->backend; 2661 2662 if (data->smu_features[GNLD_THERMAL].supported) { 2663 if (data->smu_features[GNLD_THERMAL].enabled) 2664 pr_info("THERMAL Feature Already enabled!"); 2665 2666 PP_ASSERT_WITH_CODE( 2667 !vega10_enable_smc_features(hwmgr, 2668 true, 2669 data->smu_features[GNLD_THERMAL].smu_feature_bitmap), 2670 "Enable THERMAL Feature Failed!", 2671 return -1); 2672 data->smu_features[GNLD_THERMAL].enabled = true; 2673 } 2674 2675 return 0; 2676 } 2677 2678 static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr) 2679 { 2680 struct vega10_hwmgr *data = hwmgr->backend; 2681 2682 if (data->smu_features[GNLD_THERMAL].supported) { 2683 if (!data->smu_features[GNLD_THERMAL].enabled) 2684 pr_info("THERMAL Feature Already disabled!"); 2685 2686 PP_ASSERT_WITH_CODE( 2687 !vega10_enable_smc_features(hwmgr, 2688 false, 2689 data->smu_features[GNLD_THERMAL].smu_feature_bitmap), 2690 "disable THERMAL Feature Failed!", 2691 return -1); 2692 data->smu_features[GNLD_THERMAL].enabled = false; 2693 } 2694 2695 return 0; 2696 } 2697 2698 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr) 2699 { 2700 struct vega10_hwmgr *data = hwmgr->backend; 2701 2702 if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) { 2703 if (data->smu_features[GNLD_VR0HOT].supported) { 2704 PP_ASSERT_WITH_CODE( 2705 !vega10_enable_smc_features(hwmgr, 2706 true, 2707 data->smu_features[GNLD_VR0HOT].smu_feature_bitmap), 2708 "Attempt to Enable VR0 Hot feature Failed!", 2709 return -1); 2710 data->smu_features[GNLD_VR0HOT].enabled = true; 2711 } else { 2712 if (data->smu_features[GNLD_VR1HOT].supported) { 2713 PP_ASSERT_WITH_CODE( 2714 !vega10_enable_smc_features(hwmgr, 2715 true, 2716 data->smu_features[GNLD_VR1HOT].smu_feature_bitmap), 2717 "Attempt to Enable VR0 Hot feature Failed!", 2718 return -1); 2719 data->smu_features[GNLD_VR1HOT].enabled = true; 2720 } 2721 } 2722 } 2723 return 0; 2724 } 2725 2726 static int vega10_enable_ulv(struct pp_hwmgr *hwmgr) 2727 { 2728 struct vega10_hwmgr *data = hwmgr->backend; 2729 2730 if (data->registry_data.ulv_support) { 2731 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2732 true, data->smu_features[GNLD_ULV].smu_feature_bitmap), 2733 "Enable ULV Feature Failed!", 2734 return -1); 2735 data->smu_features[GNLD_ULV].enabled = true; 2736 } 2737 2738 return 0; 2739 } 2740 2741 static int vega10_disable_ulv(struct pp_hwmgr *hwmgr) 2742 { 2743 struct vega10_hwmgr *data = hwmgr->backend; 2744 2745 if (data->registry_data.ulv_support) { 2746 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2747 false, data->smu_features[GNLD_ULV].smu_feature_bitmap), 2748 "disable ULV Feature Failed!", 2749 return -EINVAL); 2750 data->smu_features[GNLD_ULV].enabled = false; 2751 } 2752 2753 return 0; 2754 } 2755 2756 static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) 2757 { 2758 struct vega10_hwmgr *data = hwmgr->backend; 2759 2760 if (data->smu_features[GNLD_DS_GFXCLK].supported) { 2761 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2762 true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), 2763 "Attempt to Enable DS_GFXCLK Feature Failed!", 2764 return -EINVAL); 2765 data->smu_features[GNLD_DS_GFXCLK].enabled = true; 2766 } 2767 2768 if (data->smu_features[GNLD_DS_SOCCLK].supported) { 2769 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2770 true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), 2771 "Attempt to Enable DS_SOCCLK Feature Failed!", 2772 return -EINVAL); 2773 data->smu_features[GNLD_DS_SOCCLK].enabled = true; 2774 } 2775 2776 if (data->smu_features[GNLD_DS_LCLK].supported) { 2777 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2778 true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), 2779 "Attempt to Enable DS_LCLK Feature Failed!", 2780 return -EINVAL); 2781 data->smu_features[GNLD_DS_LCLK].enabled = true; 2782 } 2783 2784 if (data->smu_features[GNLD_DS_DCEFCLK].supported) { 2785 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2786 true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), 2787 "Attempt to Enable DS_DCEFCLK Feature Failed!", 2788 return -EINVAL); 2789 data->smu_features[GNLD_DS_DCEFCLK].enabled = true; 2790 } 2791 2792 return 0; 2793 } 2794 2795 static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) 2796 { 2797 struct vega10_hwmgr *data = hwmgr->backend; 2798 2799 if (data->smu_features[GNLD_DS_GFXCLK].supported) { 2800 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2801 false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), 2802 "Attempt to disable DS_GFXCLK Feature Failed!", 2803 return -EINVAL); 2804 data->smu_features[GNLD_DS_GFXCLK].enabled = false; 2805 } 2806 2807 if (data->smu_features[GNLD_DS_SOCCLK].supported) { 2808 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2809 false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), 2810 "Attempt to disable DS_ Feature Failed!", 2811 return -EINVAL); 2812 data->smu_features[GNLD_DS_SOCCLK].enabled = false; 2813 } 2814 2815 if (data->smu_features[GNLD_DS_LCLK].supported) { 2816 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2817 false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), 2818 "Attempt to disable DS_LCLK Feature Failed!", 2819 return -EINVAL); 2820 data->smu_features[GNLD_DS_LCLK].enabled = false; 2821 } 2822 2823 if (data->smu_features[GNLD_DS_DCEFCLK].supported) { 2824 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2825 false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), 2826 "Attempt to disable DS_DCEFCLK Feature Failed!", 2827 return -EINVAL); 2828 data->smu_features[GNLD_DS_DCEFCLK].enabled = false; 2829 } 2830 2831 return 0; 2832 } 2833 2834 static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) 2835 { 2836 struct vega10_hwmgr *data = hwmgr->backend; 2837 uint32_t i, feature_mask = 0; 2838 2839 if (!hwmgr->not_vf) 2840 return 0; 2841 2842 if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ 2843 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2844 false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), 2845 "Attempt to disable LED DPM feature failed!", return -EINVAL); 2846 data->smu_features[GNLD_LED_DISPLAY].enabled = false; 2847 } 2848 2849 for (i = 0; i < GNLD_DPM_MAX; i++) { 2850 if (data->smu_features[i].smu_feature_bitmap & bitmap) { 2851 if (data->smu_features[i].supported) { 2852 if (data->smu_features[i].enabled) { 2853 feature_mask |= data->smu_features[i]. 2854 smu_feature_bitmap; 2855 data->smu_features[i].enabled = false; 2856 } 2857 } 2858 } 2859 } 2860 2861 vega10_enable_smc_features(hwmgr, false, feature_mask); 2862 2863 return 0; 2864 } 2865 2866 /** 2867 * @brief Tell SMC to enabled the supported DPMs. 2868 * 2869 * @param hwmgr - the address of the powerplay hardware manager. 2870 * @Param bitmap - bitmap for the features to enabled. 2871 * @return 0 on at least one DPM is successfully enabled. 2872 */ 2873 static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) 2874 { 2875 struct vega10_hwmgr *data = hwmgr->backend; 2876 uint32_t i, feature_mask = 0; 2877 2878 for (i = 0; i < GNLD_DPM_MAX; i++) { 2879 if (data->smu_features[i].smu_feature_bitmap & bitmap) { 2880 if (data->smu_features[i].supported) { 2881 if (!data->smu_features[i].enabled) { 2882 feature_mask |= data->smu_features[i]. 2883 smu_feature_bitmap; 2884 data->smu_features[i].enabled = true; 2885 } 2886 } 2887 } 2888 } 2889 2890 if (vega10_enable_smc_features(hwmgr, 2891 true, feature_mask)) { 2892 for (i = 0; i < GNLD_DPM_MAX; i++) { 2893 if (data->smu_features[i].smu_feature_bitmap & 2894 feature_mask) 2895 data->smu_features[i].enabled = false; 2896 } 2897 } 2898 2899 if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ 2900 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2901 true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), 2902 "Attempt to Enable LED DPM feature Failed!", return -EINVAL); 2903 data->smu_features[GNLD_LED_DISPLAY].enabled = true; 2904 } 2905 2906 if (data->vbios_boot_state.bsoc_vddc_lock) { 2907 smum_send_msg_to_smc_with_parameter(hwmgr, 2908 PPSMC_MSG_SetFloorSocVoltage, 0, 2909 NULL); 2910 data->vbios_boot_state.bsoc_vddc_lock = false; 2911 } 2912 2913 if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) { 2914 if (data->smu_features[GNLD_ACDC].supported) { 2915 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2916 true, data->smu_features[GNLD_ACDC].smu_feature_bitmap), 2917 "Attempt to Enable DS_GFXCLK Feature Failed!", 2918 return -1); 2919 data->smu_features[GNLD_ACDC].enabled = true; 2920 } 2921 } 2922 2923 return 0; 2924 } 2925 2926 static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable) 2927 { 2928 struct vega10_hwmgr *data = hwmgr->backend; 2929 2930 if (data->smu_features[GNLD_PCC_LIMIT].supported) { 2931 if (enable == data->smu_features[GNLD_PCC_LIMIT].enabled) 2932 pr_info("GNLD_PCC_LIMIT has been %s \n", enable ? "enabled" : "disabled"); 2933 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 2934 enable, data->smu_features[GNLD_PCC_LIMIT].smu_feature_bitmap), 2935 "Attempt to Enable PCC Limit feature Failed!", 2936 return -EINVAL); 2937 data->smu_features[GNLD_PCC_LIMIT].enabled = enable; 2938 } 2939 2940 return 0; 2941 } 2942 2943 static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) 2944 { 2945 struct vega10_hwmgr *data = hwmgr->backend; 2946 int tmp_result, result = 0; 2947 2948 if (hwmgr->not_vf) { 2949 vega10_enable_disable_PCC_limit_feature(hwmgr, true); 2950 2951 smum_send_msg_to_smc_with_parameter(hwmgr, 2952 PPSMC_MSG_ConfigureTelemetry, data->config_telemetry, 2953 NULL); 2954 2955 tmp_result = vega10_construct_voltage_tables(hwmgr); 2956 PP_ASSERT_WITH_CODE(!tmp_result, 2957 "Failed to construct voltage tables!", 2958 result = tmp_result); 2959 } 2960 2961 if (hwmgr->not_vf || hwmgr->pp_one_vf) { 2962 tmp_result = vega10_init_smc_table(hwmgr); 2963 PP_ASSERT_WITH_CODE(!tmp_result, 2964 "Failed to initialize SMC table!", 2965 result = tmp_result); 2966 } 2967 2968 if (hwmgr->not_vf) { 2969 if (PP_CAP(PHM_PlatformCaps_ThermalController)) { 2970 tmp_result = vega10_enable_thermal_protection(hwmgr); 2971 PP_ASSERT_WITH_CODE(!tmp_result, 2972 "Failed to enable thermal protection!", 2973 result = tmp_result); 2974 } 2975 2976 tmp_result = vega10_enable_vrhot_feature(hwmgr); 2977 PP_ASSERT_WITH_CODE(!tmp_result, 2978 "Failed to enable VR hot feature!", 2979 result = tmp_result); 2980 2981 tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr); 2982 PP_ASSERT_WITH_CODE(!tmp_result, 2983 "Failed to enable deep sleep master switch!", 2984 result = tmp_result); 2985 } 2986 2987 if (hwmgr->not_vf) { 2988 tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES); 2989 PP_ASSERT_WITH_CODE(!tmp_result, 2990 "Failed to start DPM!", result = tmp_result); 2991 } 2992 2993 if (hwmgr->not_vf) { 2994 /* enable didt, do not abort if failed didt */ 2995 tmp_result = vega10_enable_didt_config(hwmgr); 2996 PP_ASSERT(!tmp_result, 2997 "Failed to enable didt config!"); 2998 } 2999 3000 tmp_result = vega10_enable_power_containment(hwmgr); 3001 PP_ASSERT_WITH_CODE(!tmp_result, 3002 "Failed to enable power containment!", 3003 result = tmp_result); 3004 3005 if (hwmgr->not_vf) { 3006 tmp_result = vega10_power_control_set_level(hwmgr); 3007 PP_ASSERT_WITH_CODE(!tmp_result, 3008 "Failed to power control set level!", 3009 result = tmp_result); 3010 3011 tmp_result = vega10_enable_ulv(hwmgr); 3012 PP_ASSERT_WITH_CODE(!tmp_result, 3013 "Failed to enable ULV!", 3014 result = tmp_result); 3015 } 3016 3017 return result; 3018 } 3019 3020 static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr) 3021 { 3022 return sizeof(struct vega10_power_state); 3023 } 3024 3025 static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr, 3026 void *state, struct pp_power_state *power_state, 3027 void *pp_table, uint32_t classification_flag) 3028 { 3029 ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_V2; 3030 struct vega10_power_state *vega10_power_state = 3031 cast_phw_vega10_power_state(&(power_state->hardware)); 3032 struct vega10_performance_level *performance_level; 3033 ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state; 3034 ATOM_Vega10_POWERPLAYTABLE *powerplay_table = 3035 (ATOM_Vega10_POWERPLAYTABLE *)pp_table; 3036 ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = 3037 (ATOM_Vega10_SOCCLK_Dependency_Table *) 3038 (((unsigned long)powerplay_table) + 3039 le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); 3040 ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = 3041 (ATOM_Vega10_GFXCLK_Dependency_Table *) 3042 (((unsigned long)powerplay_table) + 3043 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); 3044 ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = 3045 (ATOM_Vega10_MCLK_Dependency_Table *) 3046 (((unsigned long)powerplay_table) + 3047 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); 3048 3049 3050 /* The following fields are not initialized here: 3051 * id orderedList allStatesList 3052 */ 3053 power_state->classification.ui_label = 3054 (le16_to_cpu(state_entry->usClassification) & 3055 ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> 3056 ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; 3057 power_state->classification.flags = classification_flag; 3058 /* NOTE: There is a classification2 flag in BIOS 3059 * that is not being used right now 3060 */ 3061 power_state->classification.temporary_state = false; 3062 power_state->classification.to_be_deleted = false; 3063 3064 power_state->validation.disallowOnDC = 3065 ((le32_to_cpu(state_entry->ulCapsAndSettings) & 3066 ATOM_Vega10_DISALLOW_ON_DC) != 0); 3067 3068 power_state->display.disableFrameModulation = false; 3069 power_state->display.limitRefreshrate = false; 3070 power_state->display.enableVariBright = 3071 ((le32_to_cpu(state_entry->ulCapsAndSettings) & 3072 ATOM_Vega10_ENABLE_VARIBRIGHT) != 0); 3073 3074 power_state->validation.supportedPowerLevels = 0; 3075 power_state->uvd_clocks.VCLK = 0; 3076 power_state->uvd_clocks.DCLK = 0; 3077 power_state->temperatures.min = 0; 3078 power_state->temperatures.max = 0; 3079 3080 performance_level = &(vega10_power_state->performance_levels 3081 [vega10_power_state->performance_level_count++]); 3082 3083 PP_ASSERT_WITH_CODE( 3084 (vega10_power_state->performance_level_count < 3085 NUM_GFXCLK_DPM_LEVELS), 3086 "Performance levels exceeds SMC limit!", 3087 return -1); 3088 3089 PP_ASSERT_WITH_CODE( 3090 (vega10_power_state->performance_level_count <= 3091 hwmgr->platform_descriptor. 3092 hardwareActivityPerformanceLevels), 3093 "Performance levels exceeds Driver limit!", 3094 return -1); 3095 3096 /* Performance levels are arranged from low to high. */ 3097 performance_level->soc_clock = socclk_dep_table->entries 3098 [state_entry->ucSocClockIndexLow].ulClk; 3099 performance_level->gfx_clock = gfxclk_dep_table->entries 3100 [state_entry->ucGfxClockIndexLow].ulClk; 3101 performance_level->mem_clock = mclk_dep_table->entries 3102 [state_entry->ucMemClockIndexLow].ulMemClk; 3103 3104 performance_level = &(vega10_power_state->performance_levels 3105 [vega10_power_state->performance_level_count++]); 3106 performance_level->soc_clock = socclk_dep_table->entries 3107 [state_entry->ucSocClockIndexHigh].ulClk; 3108 if (gfxclk_dep_table->ucRevId == 0) { 3109 /* under vega10 pp one vf mode, the gfx clk dpm need be lower 3110 * to level-4 due to the limited 110w-power 3111 */ 3112 if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0)) 3113 performance_level->gfx_clock = 3114 gfxclk_dep_table->entries[4].ulClk; 3115 else 3116 performance_level->gfx_clock = gfxclk_dep_table->entries 3117 [state_entry->ucGfxClockIndexHigh].ulClk; 3118 } else if (gfxclk_dep_table->ucRevId == 1) { 3119 patom_record_V2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; 3120 if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0)) 3121 performance_level->gfx_clock = patom_record_V2[4].ulClk; 3122 else 3123 performance_level->gfx_clock = 3124 patom_record_V2[state_entry->ucGfxClockIndexHigh].ulClk; 3125 } 3126 3127 performance_level->mem_clock = mclk_dep_table->entries 3128 [state_entry->ucMemClockIndexHigh].ulMemClk; 3129 return 0; 3130 } 3131 3132 static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr, 3133 unsigned long entry_index, struct pp_power_state *state) 3134 { 3135 int result; 3136 struct vega10_power_state *ps; 3137 3138 state->hardware.magic = PhwVega10_Magic; 3139 3140 ps = cast_phw_vega10_power_state(&state->hardware); 3141 3142 result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state, 3143 vega10_get_pp_table_entry_callback_func); 3144 if (result) 3145 return result; 3146 3147 /* 3148 * This is the earliest time we have all the dependency table 3149 * and the VBIOS boot state 3150 */ 3151 /* set DC compatible flag if this state supports DC */ 3152 if (!state->validation.disallowOnDC) 3153 ps->dc_compatible = true; 3154 3155 ps->uvd_clks.vclk = state->uvd_clocks.VCLK; 3156 ps->uvd_clks.dclk = state->uvd_clocks.DCLK; 3157 3158 return 0; 3159 } 3160 3161 static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr, 3162 struct pp_hw_power_state *hw_ps) 3163 { 3164 return 0; 3165 } 3166 3167 static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, 3168 struct pp_power_state *request_ps, 3169 const struct pp_power_state *current_ps) 3170 { 3171 struct amdgpu_device *adev = hwmgr->adev; 3172 struct vega10_power_state *vega10_ps = 3173 cast_phw_vega10_power_state(&request_ps->hardware); 3174 uint32_t sclk; 3175 uint32_t mclk; 3176 struct PP_Clocks minimum_clocks = {0}; 3177 bool disable_mclk_switching; 3178 bool disable_mclk_switching_for_frame_lock; 3179 bool disable_mclk_switching_for_vr; 3180 bool force_mclk_high; 3181 const struct phm_clock_and_voltage_limits *max_limits; 3182 uint32_t i; 3183 struct vega10_hwmgr *data = hwmgr->backend; 3184 struct phm_ppt_v2_information *table_info = 3185 (struct phm_ppt_v2_information *)(hwmgr->pptable); 3186 int32_t count; 3187 uint32_t stable_pstate_sclk_dpm_percentage; 3188 uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; 3189 uint32_t latency; 3190 3191 data->battery_state = (PP_StateUILabel_Battery == 3192 request_ps->classification.ui_label); 3193 3194 if (vega10_ps->performance_level_count != 2) 3195 pr_info("VI should always have 2 performance levels"); 3196 3197 max_limits = adev->pm.ac_power ? 3198 &(hwmgr->dyn_state.max_clock_voltage_on_ac) : 3199 &(hwmgr->dyn_state.max_clock_voltage_on_dc); 3200 3201 /* Cap clock DPM tables at DC MAX if it is in DC. */ 3202 if (!adev->pm.ac_power) { 3203 for (i = 0; i < vega10_ps->performance_level_count; i++) { 3204 if (vega10_ps->performance_levels[i].mem_clock > 3205 max_limits->mclk) 3206 vega10_ps->performance_levels[i].mem_clock = 3207 max_limits->mclk; 3208 if (vega10_ps->performance_levels[i].gfx_clock > 3209 max_limits->sclk) 3210 vega10_ps->performance_levels[i].gfx_clock = 3211 max_limits->sclk; 3212 } 3213 } 3214 3215 /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ 3216 minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; 3217 minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 3218 3219 if (PP_CAP(PHM_PlatformCaps_StablePState)) { 3220 stable_pstate_sclk_dpm_percentage = 3221 data->registry_data.stable_pstate_sclk_dpm_percentage; 3222 PP_ASSERT_WITH_CODE( 3223 data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 && 3224 data->registry_data.stable_pstate_sclk_dpm_percentage <= 100, 3225 "percent sclk value must range from 1% to 100%, setting default value", 3226 stable_pstate_sclk_dpm_percentage = 75); 3227 3228 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); 3229 stable_pstate_sclk = (max_limits->sclk * 3230 stable_pstate_sclk_dpm_percentage) / 100; 3231 3232 for (count = table_info->vdd_dep_on_sclk->count - 1; 3233 count >= 0; count--) { 3234 if (stable_pstate_sclk >= 3235 table_info->vdd_dep_on_sclk->entries[count].clk) { 3236 stable_pstate_sclk = 3237 table_info->vdd_dep_on_sclk->entries[count].clk; 3238 break; 3239 } 3240 } 3241 3242 if (count < 0) 3243 stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; 3244 3245 stable_pstate_mclk = max_limits->mclk; 3246 3247 minimum_clocks.engineClock = stable_pstate_sclk; 3248 minimum_clocks.memoryClock = stable_pstate_mclk; 3249 } 3250 3251 disable_mclk_switching_for_frame_lock = 3252 PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); 3253 disable_mclk_switching_for_vr = 3254 PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR); 3255 force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh); 3256 3257 if (hwmgr->display_config->num_display == 0) 3258 disable_mclk_switching = false; 3259 else 3260 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && 3261 !hwmgr->display_config->multi_monitor_in_sync) || 3262 disable_mclk_switching_for_frame_lock || 3263 disable_mclk_switching_for_vr || 3264 force_mclk_high; 3265 3266 sclk = vega10_ps->performance_levels[0].gfx_clock; 3267 mclk = vega10_ps->performance_levels[0].mem_clock; 3268 3269 if (sclk < minimum_clocks.engineClock) 3270 sclk = (minimum_clocks.engineClock > max_limits->sclk) ? 3271 max_limits->sclk : minimum_clocks.engineClock; 3272 3273 if (mclk < minimum_clocks.memoryClock) 3274 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? 3275 max_limits->mclk : minimum_clocks.memoryClock; 3276 3277 vega10_ps->performance_levels[0].gfx_clock = sclk; 3278 vega10_ps->performance_levels[0].mem_clock = mclk; 3279 3280 if (vega10_ps->performance_levels[1].gfx_clock < 3281 vega10_ps->performance_levels[0].gfx_clock) 3282 vega10_ps->performance_levels[0].gfx_clock = 3283 vega10_ps->performance_levels[1].gfx_clock; 3284 3285 if (disable_mclk_switching) { 3286 /* Set Mclk the max of level 0 and level 1 */ 3287 if (mclk < vega10_ps->performance_levels[1].mem_clock) 3288 mclk = vega10_ps->performance_levels[1].mem_clock; 3289 3290 /* Find the lowest MCLK frequency that is within 3291 * the tolerable latency defined in DAL 3292 */ 3293 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; 3294 for (i = 0; i < data->mclk_latency_table.count; i++) { 3295 if ((data->mclk_latency_table.entries[i].latency <= latency) && 3296 (data->mclk_latency_table.entries[i].frequency >= 3297 vega10_ps->performance_levels[0].mem_clock) && 3298 (data->mclk_latency_table.entries[i].frequency <= 3299 vega10_ps->performance_levels[1].mem_clock)) 3300 mclk = data->mclk_latency_table.entries[i].frequency; 3301 } 3302 vega10_ps->performance_levels[0].mem_clock = mclk; 3303 } else { 3304 if (vega10_ps->performance_levels[1].mem_clock < 3305 vega10_ps->performance_levels[0].mem_clock) 3306 vega10_ps->performance_levels[0].mem_clock = 3307 vega10_ps->performance_levels[1].mem_clock; 3308 } 3309 3310 if (PP_CAP(PHM_PlatformCaps_StablePState)) { 3311 for (i = 0; i < vega10_ps->performance_level_count; i++) { 3312 vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk; 3313 vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk; 3314 } 3315 } 3316 3317 return 0; 3318 } 3319 3320 static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) 3321 { 3322 struct vega10_hwmgr *data = hwmgr->backend; 3323 const struct phm_set_power_state_input *states = 3324 (const struct phm_set_power_state_input *)input; 3325 const struct vega10_power_state *vega10_ps = 3326 cast_const_phw_vega10_power_state(states->pnew_state); 3327 struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); 3328 uint32_t sclk = vega10_ps->performance_levels 3329 [vega10_ps->performance_level_count - 1].gfx_clock; 3330 struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); 3331 uint32_t mclk = vega10_ps->performance_levels 3332 [vega10_ps->performance_level_count - 1].mem_clock; 3333 uint32_t i; 3334 3335 for (i = 0; i < sclk_table->count; i++) { 3336 if (sclk == sclk_table->dpm_levels[i].value) 3337 break; 3338 } 3339 3340 if (i >= sclk_table->count) { 3341 if (sclk > sclk_table->dpm_levels[i-1].value) { 3342 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; 3343 sclk_table->dpm_levels[i-1].value = sclk; 3344 } 3345 } 3346 3347 for (i = 0; i < mclk_table->count; i++) { 3348 if (mclk == mclk_table->dpm_levels[i].value) 3349 break; 3350 } 3351 3352 if (i >= mclk_table->count) { 3353 if (mclk > mclk_table->dpm_levels[i-1].value) { 3354 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; 3355 mclk_table->dpm_levels[i-1].value = mclk; 3356 } 3357 } 3358 3359 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) 3360 data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; 3361 3362 return 0; 3363 } 3364 3365 static int vega10_populate_and_upload_sclk_mclk_dpm_levels( 3366 struct pp_hwmgr *hwmgr, const void *input) 3367 { 3368 int result = 0; 3369 struct vega10_hwmgr *data = hwmgr->backend; 3370 struct vega10_dpm_table *dpm_table = &data->dpm_table; 3371 struct vega10_odn_dpm_table *odn_table = &data->odn_dpm_table; 3372 struct vega10_odn_clock_voltage_dependency_table *odn_clk_table = &odn_table->vdd_dep_on_sclk; 3373 int count; 3374 3375 if (!data->need_update_dpm_table) 3376 return 0; 3377 3378 if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { 3379 for (count = 0; count < dpm_table->gfx_table.count; count++) 3380 dpm_table->gfx_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; 3381 } 3382 3383 odn_clk_table = &odn_table->vdd_dep_on_mclk; 3384 if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { 3385 for (count = 0; count < dpm_table->mem_table.count; count++) 3386 dpm_table->mem_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; 3387 } 3388 3389 if (data->need_update_dpm_table & 3390 (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK | DPMTABLE_UPDATE_SOCCLK)) { 3391 result = vega10_populate_all_graphic_levels(hwmgr); 3392 PP_ASSERT_WITH_CODE((0 == result), 3393 "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", 3394 return result); 3395 } 3396 3397 if (data->need_update_dpm_table & 3398 (DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) { 3399 result = vega10_populate_all_memory_levels(hwmgr); 3400 PP_ASSERT_WITH_CODE((0 == result), 3401 "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", 3402 return result); 3403 } 3404 3405 vega10_populate_vddc_soc_levels(hwmgr); 3406 3407 return result; 3408 } 3409 3410 static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr, 3411 struct vega10_single_dpm_table *dpm_table, 3412 uint32_t low_limit, uint32_t high_limit) 3413 { 3414 uint32_t i; 3415 3416 for (i = 0; i < dpm_table->count; i++) { 3417 if ((dpm_table->dpm_levels[i].value < low_limit) || 3418 (dpm_table->dpm_levels[i].value > high_limit)) 3419 dpm_table->dpm_levels[i].enabled = false; 3420 else 3421 dpm_table->dpm_levels[i].enabled = true; 3422 } 3423 return 0; 3424 } 3425 3426 static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr, 3427 struct vega10_single_dpm_table *dpm_table, 3428 uint32_t low_limit, uint32_t high_limit, 3429 uint32_t disable_dpm_mask) 3430 { 3431 uint32_t i; 3432 3433 for (i = 0; i < dpm_table->count; i++) { 3434 if ((dpm_table->dpm_levels[i].value < low_limit) || 3435 (dpm_table->dpm_levels[i].value > high_limit)) 3436 dpm_table->dpm_levels[i].enabled = false; 3437 else if (!((1 << i) & disable_dpm_mask)) 3438 dpm_table->dpm_levels[i].enabled = false; 3439 else 3440 dpm_table->dpm_levels[i].enabled = true; 3441 } 3442 return 0; 3443 } 3444 3445 static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr, 3446 const struct vega10_power_state *vega10_ps) 3447 { 3448 struct vega10_hwmgr *data = hwmgr->backend; 3449 uint32_t high_limit_count; 3450 3451 PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1), 3452 "power state did not have any performance level", 3453 return -1); 3454 3455 high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1; 3456 3457 vega10_trim_single_dpm_states(hwmgr, 3458 &(data->dpm_table.soc_table), 3459 vega10_ps->performance_levels[0].soc_clock, 3460 vega10_ps->performance_levels[high_limit_count].soc_clock); 3461 3462 vega10_trim_single_dpm_states_with_mask(hwmgr, 3463 &(data->dpm_table.gfx_table), 3464 vega10_ps->performance_levels[0].gfx_clock, 3465 vega10_ps->performance_levels[high_limit_count].gfx_clock, 3466 data->disable_dpm_mask); 3467 3468 vega10_trim_single_dpm_states(hwmgr, 3469 &(data->dpm_table.mem_table), 3470 vega10_ps->performance_levels[0].mem_clock, 3471 vega10_ps->performance_levels[high_limit_count].mem_clock); 3472 3473 return 0; 3474 } 3475 3476 static uint32_t vega10_find_lowest_dpm_level( 3477 struct vega10_single_dpm_table *table) 3478 { 3479 uint32_t i; 3480 3481 for (i = 0; i < table->count; i++) { 3482 if (table->dpm_levels[i].enabled) 3483 break; 3484 } 3485 3486 return i; 3487 } 3488 3489 static uint32_t vega10_find_highest_dpm_level( 3490 struct vega10_single_dpm_table *table) 3491 { 3492 uint32_t i = 0; 3493 3494 if (table->count <= MAX_REGULAR_DPM_NUMBER) { 3495 for (i = table->count; i > 0; i--) { 3496 if (table->dpm_levels[i - 1].enabled) 3497 return i - 1; 3498 } 3499 } else { 3500 pr_info("DPM Table Has Too Many Entries!"); 3501 return MAX_REGULAR_DPM_NUMBER - 1; 3502 } 3503 3504 return i; 3505 } 3506 3507 static void vega10_apply_dal_minimum_voltage_request( 3508 struct pp_hwmgr *hwmgr) 3509 { 3510 return; 3511 } 3512 3513 static int vega10_get_soc_index_for_max_uclk(struct pp_hwmgr *hwmgr) 3514 { 3515 struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table_on_mclk; 3516 struct phm_ppt_v2_information *table_info = 3517 (struct phm_ppt_v2_information *)(hwmgr->pptable); 3518 3519 vdd_dep_table_on_mclk = table_info->vdd_dep_on_mclk; 3520 3521 return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1; 3522 } 3523 3524 static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr) 3525 { 3526 struct vega10_hwmgr *data = hwmgr->backend; 3527 uint32_t socclk_idx; 3528 3529 vega10_apply_dal_minimum_voltage_request(hwmgr); 3530 3531 if (!data->registry_data.sclk_dpm_key_disabled) { 3532 if (data->smc_state_table.gfx_boot_level != 3533 data->dpm_table.gfx_table.dpm_state.soft_min_level) { 3534 smum_send_msg_to_smc_with_parameter(hwmgr, 3535 PPSMC_MSG_SetSoftMinGfxclkByIndex, 3536 data->smc_state_table.gfx_boot_level, 3537 NULL); 3538 3539 data->dpm_table.gfx_table.dpm_state.soft_min_level = 3540 data->smc_state_table.gfx_boot_level; 3541 } 3542 } 3543 3544 if (!data->registry_data.mclk_dpm_key_disabled) { 3545 if (data->smc_state_table.mem_boot_level != 3546 data->dpm_table.mem_table.dpm_state.soft_min_level) { 3547 if ((data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) 3548 && hwmgr->not_vf) { 3549 socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr); 3550 smum_send_msg_to_smc_with_parameter(hwmgr, 3551 PPSMC_MSG_SetSoftMinSocclkByIndex, 3552 socclk_idx, 3553 NULL); 3554 } else { 3555 smum_send_msg_to_smc_with_parameter(hwmgr, 3556 PPSMC_MSG_SetSoftMinUclkByIndex, 3557 data->smc_state_table.mem_boot_level, 3558 NULL); 3559 } 3560 data->dpm_table.mem_table.dpm_state.soft_min_level = 3561 data->smc_state_table.mem_boot_level; 3562 } 3563 } 3564 3565 if (!hwmgr->not_vf) 3566 return 0; 3567 3568 if (!data->registry_data.socclk_dpm_key_disabled) { 3569 if (data->smc_state_table.soc_boot_level != 3570 data->dpm_table.soc_table.dpm_state.soft_min_level) { 3571 smum_send_msg_to_smc_with_parameter(hwmgr, 3572 PPSMC_MSG_SetSoftMinSocclkByIndex, 3573 data->smc_state_table.soc_boot_level, 3574 NULL); 3575 data->dpm_table.soc_table.dpm_state.soft_min_level = 3576 data->smc_state_table.soc_boot_level; 3577 } 3578 } 3579 3580 return 0; 3581 } 3582 3583 static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr) 3584 { 3585 struct vega10_hwmgr *data = hwmgr->backend; 3586 3587 vega10_apply_dal_minimum_voltage_request(hwmgr); 3588 3589 if (!data->registry_data.sclk_dpm_key_disabled) { 3590 if (data->smc_state_table.gfx_max_level != 3591 data->dpm_table.gfx_table.dpm_state.soft_max_level) { 3592 smum_send_msg_to_smc_with_parameter(hwmgr, 3593 PPSMC_MSG_SetSoftMaxGfxclkByIndex, 3594 data->smc_state_table.gfx_max_level, 3595 NULL); 3596 data->dpm_table.gfx_table.dpm_state.soft_max_level = 3597 data->smc_state_table.gfx_max_level; 3598 } 3599 } 3600 3601 if (!data->registry_data.mclk_dpm_key_disabled) { 3602 if (data->smc_state_table.mem_max_level != 3603 data->dpm_table.mem_table.dpm_state.soft_max_level) { 3604 smum_send_msg_to_smc_with_parameter(hwmgr, 3605 PPSMC_MSG_SetSoftMaxUclkByIndex, 3606 data->smc_state_table.mem_max_level, 3607 NULL); 3608 data->dpm_table.mem_table.dpm_state.soft_max_level = 3609 data->smc_state_table.mem_max_level; 3610 } 3611 } 3612 3613 if (!hwmgr->not_vf) 3614 return 0; 3615 3616 if (!data->registry_data.socclk_dpm_key_disabled) { 3617 if (data->smc_state_table.soc_max_level != 3618 data->dpm_table.soc_table.dpm_state.soft_max_level) { 3619 smum_send_msg_to_smc_with_parameter(hwmgr, 3620 PPSMC_MSG_SetSoftMaxSocclkByIndex, 3621 data->smc_state_table.soc_max_level, 3622 NULL); 3623 data->dpm_table.soc_table.dpm_state.soft_max_level = 3624 data->smc_state_table.soc_max_level; 3625 } 3626 } 3627 3628 return 0; 3629 } 3630 3631 static int vega10_generate_dpm_level_enable_mask( 3632 struct pp_hwmgr *hwmgr, const void *input) 3633 { 3634 struct vega10_hwmgr *data = hwmgr->backend; 3635 const struct phm_set_power_state_input *states = 3636 (const struct phm_set_power_state_input *)input; 3637 const struct vega10_power_state *vega10_ps = 3638 cast_const_phw_vega10_power_state(states->pnew_state); 3639 int i; 3640 3641 PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps), 3642 "Attempt to Trim DPM States Failed!", 3643 return -1); 3644 3645 data->smc_state_table.gfx_boot_level = 3646 vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 3647 data->smc_state_table.gfx_max_level = 3648 vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 3649 data->smc_state_table.mem_boot_level = 3650 vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 3651 data->smc_state_table.mem_max_level = 3652 vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); 3653 data->smc_state_table.soc_boot_level = 3654 vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table)); 3655 data->smc_state_table.soc_max_level = 3656 vega10_find_highest_dpm_level(&(data->dpm_table.soc_table)); 3657 3658 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 3659 "Attempt to upload DPM Bootup Levels Failed!", 3660 return -1); 3661 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 3662 "Attempt to upload DPM Max Levels Failed!", 3663 return -1); 3664 for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++) 3665 data->dpm_table.gfx_table.dpm_levels[i].enabled = true; 3666 3667 3668 for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++) 3669 data->dpm_table.mem_table.dpm_levels[i].enabled = true; 3670 3671 for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++) 3672 data->dpm_table.soc_table.dpm_levels[i].enabled = true; 3673 3674 return 0; 3675 } 3676 3677 int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) 3678 { 3679 struct vega10_hwmgr *data = hwmgr->backend; 3680 3681 if (data->smu_features[GNLD_DPM_VCE].supported) { 3682 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 3683 enable, 3684 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), 3685 "Attempt to Enable/Disable DPM VCE Failed!", 3686 return -1); 3687 data->smu_features[GNLD_DPM_VCE].enabled = enable; 3688 } 3689 3690 return 0; 3691 } 3692 3693 static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr) 3694 { 3695 struct vega10_hwmgr *data = hwmgr->backend; 3696 uint32_t low_sclk_interrupt_threshold = 0; 3697 3698 if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) && 3699 (data->low_sclk_interrupt_threshold != 0)) { 3700 low_sclk_interrupt_threshold = 3701 data->low_sclk_interrupt_threshold; 3702 3703 data->smc_state_table.pp_table.LowGfxclkInterruptThreshold = 3704 cpu_to_le32(low_sclk_interrupt_threshold); 3705 3706 /* This message will also enable SmcToHost Interrupt */ 3707 smum_send_msg_to_smc_with_parameter(hwmgr, 3708 PPSMC_MSG_SetLowGfxclkInterruptThreshold, 3709 (uint32_t)low_sclk_interrupt_threshold, 3710 NULL); 3711 } 3712 3713 return 0; 3714 } 3715 3716 static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr, 3717 const void *input) 3718 { 3719 int tmp_result, result = 0; 3720 struct vega10_hwmgr *data = hwmgr->backend; 3721 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 3722 3723 tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input); 3724 PP_ASSERT_WITH_CODE(!tmp_result, 3725 "Failed to find DPM states clocks in DPM table!", 3726 result = tmp_result); 3727 3728 tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); 3729 PP_ASSERT_WITH_CODE(!tmp_result, 3730 "Failed to populate and upload SCLK MCLK DPM levels!", 3731 result = tmp_result); 3732 3733 tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input); 3734 PP_ASSERT_WITH_CODE(!tmp_result, 3735 "Failed to generate DPM level enabled mask!", 3736 result = tmp_result); 3737 3738 tmp_result = vega10_update_sclk_threshold(hwmgr); 3739 PP_ASSERT_WITH_CODE(!tmp_result, 3740 "Failed to update SCLK threshold!", 3741 result = tmp_result); 3742 3743 result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); 3744 PP_ASSERT_WITH_CODE(!result, 3745 "Failed to upload PPtable!", return result); 3746 3747 /* 3748 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. 3749 * That effectively disables AVFS feature. 3750 */ 3751 if(hwmgr->hardcode_pp_table != NULL) 3752 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; 3753 3754 vega10_update_avfs(hwmgr); 3755 3756 /* 3757 * Clear all OD flags except DPMTABLE_OD_UPDATE_VDDC. 3758 * That will help to keep AVFS disabled. 3759 */ 3760 data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; 3761 3762 return 0; 3763 } 3764 3765 static uint32_t vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 3766 { 3767 struct pp_power_state *ps; 3768 struct vega10_power_state *vega10_ps; 3769 3770 if (hwmgr == NULL) 3771 return -EINVAL; 3772 3773 ps = hwmgr->request_ps; 3774 3775 if (ps == NULL) 3776 return -EINVAL; 3777 3778 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 3779 3780 if (low) 3781 return vega10_ps->performance_levels[0].gfx_clock; 3782 else 3783 return vega10_ps->performance_levels 3784 [vega10_ps->performance_level_count - 1].gfx_clock; 3785 } 3786 3787 static uint32_t vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 3788 { 3789 struct pp_power_state *ps; 3790 struct vega10_power_state *vega10_ps; 3791 3792 if (hwmgr == NULL) 3793 return -EINVAL; 3794 3795 ps = hwmgr->request_ps; 3796 3797 if (ps == NULL) 3798 return -EINVAL; 3799 3800 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 3801 3802 if (low) 3803 return vega10_ps->performance_levels[0].mem_clock; 3804 else 3805 return vega10_ps->performance_levels 3806 [vega10_ps->performance_level_count-1].mem_clock; 3807 } 3808 3809 static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr, 3810 uint32_t *query) 3811 { 3812 uint32_t value; 3813 3814 if (!query) 3815 return -EINVAL; 3816 3817 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr, &value); 3818 3819 /* SMC returning actual watts, keep consistent with legacy asics, low 8 bit as 8 fractional bits */ 3820 *query = value << 8; 3821 3822 return 0; 3823 } 3824 3825 static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx, 3826 void *value, int *size) 3827 { 3828 struct amdgpu_device *adev = hwmgr->adev; 3829 uint32_t sclk_mhz, mclk_idx, activity_percent = 0; 3830 struct vega10_hwmgr *data = hwmgr->backend; 3831 struct vega10_dpm_table *dpm_table = &data->dpm_table; 3832 int ret = 0; 3833 uint32_t val_vid; 3834 3835 switch (idx) { 3836 case AMDGPU_PP_SENSOR_GFX_SCLK: 3837 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGfxclkActualFrequency, &sclk_mhz); 3838 *((uint32_t *)value) = sclk_mhz * 100; 3839 break; 3840 case AMDGPU_PP_SENSOR_GFX_MCLK: 3841 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &mclk_idx); 3842 if (mclk_idx < dpm_table->mem_table.count) { 3843 *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value; 3844 *size = 4; 3845 } else { 3846 ret = -EINVAL; 3847 } 3848 break; 3849 case AMDGPU_PP_SENSOR_GPU_LOAD: 3850 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0, 3851 &activity_percent); 3852 *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; 3853 *size = 4; 3854 break; 3855 case AMDGPU_PP_SENSOR_GPU_TEMP: 3856 *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr); 3857 *size = 4; 3858 break; 3859 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 3860 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHotspot, (uint32_t *)value); 3861 *((uint32_t *)value) = *((uint32_t *)value) * 3862 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 3863 *size = 4; 3864 break; 3865 case AMDGPU_PP_SENSOR_MEM_TEMP: 3866 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHBM, (uint32_t *)value); 3867 *((uint32_t *)value) = *((uint32_t *)value) * 3868 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 3869 *size = 4; 3870 break; 3871 case AMDGPU_PP_SENSOR_UVD_POWER: 3872 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; 3873 *size = 4; 3874 break; 3875 case AMDGPU_PP_SENSOR_VCE_POWER: 3876 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; 3877 *size = 4; 3878 break; 3879 case AMDGPU_PP_SENSOR_GPU_POWER: 3880 ret = vega10_get_gpu_power(hwmgr, (uint32_t *)value); 3881 break; 3882 case AMDGPU_PP_SENSOR_VDDGFX: 3883 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_PLANE0_CURRENTVID) & 3884 SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >> 3885 SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT; 3886 *((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid); 3887 return 0; 3888 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: 3889 ret = vega10_get_enabled_smc_features(hwmgr, (uint64_t *)value); 3890 if (!ret) 3891 *size = 8; 3892 break; 3893 default: 3894 ret = -EINVAL; 3895 break; 3896 } 3897 3898 return ret; 3899 } 3900 3901 static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr, 3902 bool has_disp) 3903 { 3904 smum_send_msg_to_smc_with_parameter(hwmgr, 3905 PPSMC_MSG_SetUclkFastSwitch, 3906 has_disp ? 1 : 0, 3907 NULL); 3908 } 3909 3910 static int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, 3911 struct pp_display_clock_request *clock_req) 3912 { 3913 int result = 0; 3914 enum amd_pp_clock_type clk_type = clock_req->clock_type; 3915 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; 3916 DSPCLK_e clk_select = 0; 3917 uint32_t clk_request = 0; 3918 3919 switch (clk_type) { 3920 case amd_pp_dcef_clock: 3921 clk_select = DSPCLK_DCEFCLK; 3922 break; 3923 case amd_pp_disp_clock: 3924 clk_select = DSPCLK_DISPCLK; 3925 break; 3926 case amd_pp_pixel_clock: 3927 clk_select = DSPCLK_PIXCLK; 3928 break; 3929 case amd_pp_phy_clock: 3930 clk_select = DSPCLK_PHYCLK; 3931 break; 3932 default: 3933 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); 3934 result = -1; 3935 break; 3936 } 3937 3938 if (!result) { 3939 clk_request = (clk_freq << 16) | clk_select; 3940 smum_send_msg_to_smc_with_parameter(hwmgr, 3941 PPSMC_MSG_RequestDisplayClockByFreq, 3942 clk_request, 3943 NULL); 3944 } 3945 3946 return result; 3947 } 3948 3949 static uint8_t vega10_get_uclk_index(struct pp_hwmgr *hwmgr, 3950 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table, 3951 uint32_t frequency) 3952 { 3953 uint8_t count; 3954 uint8_t i; 3955 3956 if (mclk_table == NULL || mclk_table->count == 0) 3957 return 0; 3958 3959 count = (uint8_t)(mclk_table->count); 3960 3961 for(i = 0; i < count; i++) { 3962 if(mclk_table->entries[i].clk >= frequency) 3963 return i; 3964 } 3965 3966 return i-1; 3967 } 3968 3969 static int vega10_notify_smc_display_config_after_ps_adjustment( 3970 struct pp_hwmgr *hwmgr) 3971 { 3972 struct vega10_hwmgr *data = hwmgr->backend; 3973 struct vega10_single_dpm_table *dpm_table = 3974 &data->dpm_table.dcef_table; 3975 struct phm_ppt_v2_information *table_info = 3976 (struct phm_ppt_v2_information *)hwmgr->pptable; 3977 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = table_info->vdd_dep_on_mclk; 3978 uint32_t idx; 3979 struct PP_Clocks min_clocks = {0}; 3980 uint32_t i; 3981 struct pp_display_clock_request clock_req; 3982 3983 if ((hwmgr->display_config->num_display > 1) && 3984 !hwmgr->display_config->multi_monitor_in_sync && 3985 !hwmgr->display_config->nb_pstate_switch_disable) 3986 vega10_notify_smc_display_change(hwmgr, false); 3987 else 3988 vega10_notify_smc_display_change(hwmgr, true); 3989 3990 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; 3991 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; 3992 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 3993 3994 for (i = 0; i < dpm_table->count; i++) { 3995 if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock) 3996 break; 3997 } 3998 3999 if (i < dpm_table->count) { 4000 clock_req.clock_type = amd_pp_dcef_clock; 4001 clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 10; 4002 if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) { 4003 smum_send_msg_to_smc_with_parameter( 4004 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, 4005 min_clocks.dcefClockInSR / 100, 4006 NULL); 4007 } else { 4008 pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); 4009 } 4010 } else { 4011 pr_debug("Cannot find requested DCEFCLK!"); 4012 } 4013 4014 if (min_clocks.memoryClock != 0) { 4015 idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock); 4016 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx, 4017 NULL); 4018 data->dpm_table.mem_table.dpm_state.soft_min_level= idx; 4019 } 4020 4021 return 0; 4022 } 4023 4024 static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr) 4025 { 4026 struct vega10_hwmgr *data = hwmgr->backend; 4027 4028 data->smc_state_table.gfx_boot_level = 4029 data->smc_state_table.gfx_max_level = 4030 vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 4031 data->smc_state_table.mem_boot_level = 4032 data->smc_state_table.mem_max_level = 4033 vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); 4034 4035 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4036 "Failed to upload boot level to highest!", 4037 return -1); 4038 4039 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4040 "Failed to upload dpm max level to highest!", 4041 return -1); 4042 4043 return 0; 4044 } 4045 4046 static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr) 4047 { 4048 struct vega10_hwmgr *data = hwmgr->backend; 4049 4050 data->smc_state_table.gfx_boot_level = 4051 data->smc_state_table.gfx_max_level = 4052 vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 4053 data->smc_state_table.mem_boot_level = 4054 data->smc_state_table.mem_max_level = 4055 vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 4056 4057 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4058 "Failed to upload boot level to highest!", 4059 return -1); 4060 4061 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4062 "Failed to upload dpm max level to highest!", 4063 return -1); 4064 4065 return 0; 4066 4067 } 4068 4069 static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr) 4070 { 4071 struct vega10_hwmgr *data = hwmgr->backend; 4072 4073 data->smc_state_table.gfx_boot_level = 4074 vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 4075 data->smc_state_table.gfx_max_level = 4076 vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 4077 data->smc_state_table.mem_boot_level = 4078 vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 4079 data->smc_state_table.mem_max_level = 4080 vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); 4081 4082 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4083 "Failed to upload DPM Bootup Levels!", 4084 return -1); 4085 4086 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4087 "Failed to upload DPM Max Levels!", 4088 return -1); 4089 return 0; 4090 } 4091 4092 static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, 4093 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) 4094 { 4095 struct phm_ppt_v2_information *table_info = 4096 (struct phm_ppt_v2_information *)(hwmgr->pptable); 4097 4098 if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL && 4099 table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL && 4100 table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) { 4101 *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL; 4102 *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL; 4103 *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL; 4104 hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk; 4105 hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk; 4106 } 4107 4108 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 4109 *sclk_mask = 0; 4110 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 4111 *mclk_mask = 0; 4112 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 4113 /* under vega10 pp one vf mode, the gfx clk dpm need be lower 4114 * to level-4 due to the limited power 4115 */ 4116 if (hwmgr->pp_one_vf) 4117 *sclk_mask = 4; 4118 else 4119 *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; 4120 *soc_mask = table_info->vdd_dep_on_socclk->count - 1; 4121 *mclk_mask = table_info->vdd_dep_on_mclk->count - 1; 4122 } 4123 4124 return 0; 4125 } 4126 4127 static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) 4128 { 4129 if (!hwmgr->not_vf) 4130 return; 4131 4132 switch (mode) { 4133 case AMD_FAN_CTRL_NONE: 4134 vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); 4135 break; 4136 case AMD_FAN_CTRL_MANUAL: 4137 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 4138 vega10_fan_ctrl_stop_smc_fan_control(hwmgr); 4139 break; 4140 case AMD_FAN_CTRL_AUTO: 4141 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 4142 vega10_fan_ctrl_start_smc_fan_control(hwmgr); 4143 break; 4144 default: 4145 break; 4146 } 4147 } 4148 4149 static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, 4150 enum pp_clock_type type, uint32_t mask) 4151 { 4152 struct vega10_hwmgr *data = hwmgr->backend; 4153 4154 switch (type) { 4155 case PP_SCLK: 4156 data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0; 4157 data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0; 4158 4159 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4160 "Failed to upload boot level to lowest!", 4161 return -EINVAL); 4162 4163 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4164 "Failed to upload dpm max level to highest!", 4165 return -EINVAL); 4166 break; 4167 4168 case PP_MCLK: 4169 data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0; 4170 data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0; 4171 4172 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4173 "Failed to upload boot level to lowest!", 4174 return -EINVAL); 4175 4176 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4177 "Failed to upload dpm max level to highest!", 4178 return -EINVAL); 4179 4180 break; 4181 4182 case PP_SOCCLK: 4183 data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0; 4184 data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0; 4185 4186 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4187 "Failed to upload boot level to lowest!", 4188 return -EINVAL); 4189 4190 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4191 "Failed to upload dpm max level to highest!", 4192 return -EINVAL); 4193 4194 break; 4195 4196 case PP_DCEFCLK: 4197 pr_info("Setting DCEFCLK min/max dpm level is not supported!\n"); 4198 break; 4199 4200 case PP_PCIE: 4201 default: 4202 break; 4203 } 4204 4205 return 0; 4206 } 4207 4208 static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, 4209 enum amd_dpm_forced_level level) 4210 { 4211 int ret = 0; 4212 uint32_t sclk_mask = 0; 4213 uint32_t mclk_mask = 0; 4214 uint32_t soc_mask = 0; 4215 4216 if (hwmgr->pstate_sclk == 0) 4217 vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); 4218 4219 switch (level) { 4220 case AMD_DPM_FORCED_LEVEL_HIGH: 4221 ret = vega10_force_dpm_highest(hwmgr); 4222 break; 4223 case AMD_DPM_FORCED_LEVEL_LOW: 4224 ret = vega10_force_dpm_lowest(hwmgr); 4225 break; 4226 case AMD_DPM_FORCED_LEVEL_AUTO: 4227 ret = vega10_unforce_dpm_levels(hwmgr); 4228 break; 4229 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 4230 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 4231 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 4232 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 4233 ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); 4234 if (ret) 4235 return ret; 4236 vega10_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask); 4237 vega10_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask); 4238 break; 4239 case AMD_DPM_FORCED_LEVEL_MANUAL: 4240 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 4241 default: 4242 break; 4243 } 4244 4245 if (!hwmgr->not_vf) 4246 return ret; 4247 4248 if (!ret) { 4249 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 4250 vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); 4251 else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 4252 vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); 4253 } 4254 4255 return ret; 4256 } 4257 4258 static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) 4259 { 4260 struct vega10_hwmgr *data = hwmgr->backend; 4261 4262 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) 4263 return AMD_FAN_CTRL_MANUAL; 4264 else 4265 return AMD_FAN_CTRL_AUTO; 4266 } 4267 4268 static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr, 4269 struct amd_pp_simple_clock_info *info) 4270 { 4271 struct phm_ppt_v2_information *table_info = 4272 (struct phm_ppt_v2_information *)hwmgr->pptable; 4273 struct phm_clock_and_voltage_limits *max_limits = 4274 &table_info->max_clock_voltage_on_ac; 4275 4276 info->engine_max_clock = max_limits->sclk; 4277 info->memory_max_clock = max_limits->mclk; 4278 4279 return 0; 4280 } 4281 4282 static void vega10_get_sclks(struct pp_hwmgr *hwmgr, 4283 struct pp_clock_levels_with_latency *clocks) 4284 { 4285 struct phm_ppt_v2_information *table_info = 4286 (struct phm_ppt_v2_information *)hwmgr->pptable; 4287 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4288 table_info->vdd_dep_on_sclk; 4289 uint32_t i; 4290 4291 clocks->num_levels = 0; 4292 for (i = 0; i < dep_table->count; i++) { 4293 if (dep_table->entries[i].clk) { 4294 clocks->data[clocks->num_levels].clocks_in_khz = 4295 dep_table->entries[i].clk * 10; 4296 clocks->num_levels++; 4297 } 4298 } 4299 4300 } 4301 4302 static void vega10_get_memclocks(struct pp_hwmgr *hwmgr, 4303 struct pp_clock_levels_with_latency *clocks) 4304 { 4305 struct phm_ppt_v2_information *table_info = 4306 (struct phm_ppt_v2_information *)hwmgr->pptable; 4307 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4308 table_info->vdd_dep_on_mclk; 4309 struct vega10_hwmgr *data = hwmgr->backend; 4310 uint32_t j = 0; 4311 uint32_t i; 4312 4313 for (i = 0; i < dep_table->count; i++) { 4314 if (dep_table->entries[i].clk) { 4315 4316 clocks->data[j].clocks_in_khz = 4317 dep_table->entries[i].clk * 10; 4318 data->mclk_latency_table.entries[j].frequency = 4319 dep_table->entries[i].clk; 4320 clocks->data[j].latency_in_us = 4321 data->mclk_latency_table.entries[j].latency = 25; 4322 j++; 4323 } 4324 } 4325 clocks->num_levels = data->mclk_latency_table.count = j; 4326 } 4327 4328 static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr, 4329 struct pp_clock_levels_with_latency *clocks) 4330 { 4331 struct phm_ppt_v2_information *table_info = 4332 (struct phm_ppt_v2_information *)hwmgr->pptable; 4333 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4334 table_info->vdd_dep_on_dcefclk; 4335 uint32_t i; 4336 4337 for (i = 0; i < dep_table->count; i++) { 4338 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; 4339 clocks->data[i].latency_in_us = 0; 4340 clocks->num_levels++; 4341 } 4342 } 4343 4344 static void vega10_get_socclocks(struct pp_hwmgr *hwmgr, 4345 struct pp_clock_levels_with_latency *clocks) 4346 { 4347 struct phm_ppt_v2_information *table_info = 4348 (struct phm_ppt_v2_information *)hwmgr->pptable; 4349 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4350 table_info->vdd_dep_on_socclk; 4351 uint32_t i; 4352 4353 for (i = 0; i < dep_table->count; i++) { 4354 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; 4355 clocks->data[i].latency_in_us = 0; 4356 clocks->num_levels++; 4357 } 4358 } 4359 4360 static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, 4361 enum amd_pp_clock_type type, 4362 struct pp_clock_levels_with_latency *clocks) 4363 { 4364 switch (type) { 4365 case amd_pp_sys_clock: 4366 vega10_get_sclks(hwmgr, clocks); 4367 break; 4368 case amd_pp_mem_clock: 4369 vega10_get_memclocks(hwmgr, clocks); 4370 break; 4371 case amd_pp_dcef_clock: 4372 vega10_get_dcefclocks(hwmgr, clocks); 4373 break; 4374 case amd_pp_soc_clock: 4375 vega10_get_socclocks(hwmgr, clocks); 4376 break; 4377 default: 4378 return -1; 4379 } 4380 4381 return 0; 4382 } 4383 4384 static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, 4385 enum amd_pp_clock_type type, 4386 struct pp_clock_levels_with_voltage *clocks) 4387 { 4388 struct phm_ppt_v2_information *table_info = 4389 (struct phm_ppt_v2_information *)hwmgr->pptable; 4390 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; 4391 uint32_t i; 4392 4393 switch (type) { 4394 case amd_pp_mem_clock: 4395 dep_table = table_info->vdd_dep_on_mclk; 4396 break; 4397 case amd_pp_dcef_clock: 4398 dep_table = table_info->vdd_dep_on_dcefclk; 4399 break; 4400 case amd_pp_disp_clock: 4401 dep_table = table_info->vdd_dep_on_dispclk; 4402 break; 4403 case amd_pp_pixel_clock: 4404 dep_table = table_info->vdd_dep_on_pixclk; 4405 break; 4406 case amd_pp_phy_clock: 4407 dep_table = table_info->vdd_dep_on_phyclk; 4408 break; 4409 default: 4410 return -1; 4411 } 4412 4413 for (i = 0; i < dep_table->count; i++) { 4414 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; 4415 clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table-> 4416 entries[dep_table->entries[i].vddInd].us_vdd); 4417 clocks->num_levels++; 4418 } 4419 4420 if (i < dep_table->count) 4421 return -1; 4422 4423 return 0; 4424 } 4425 4426 static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, 4427 void *clock_range) 4428 { 4429 struct vega10_hwmgr *data = hwmgr->backend; 4430 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_range; 4431 Watermarks_t *table = &(data->smc_state_table.water_marks_table); 4432 4433 if (!data->registry_data.disable_water_mark) { 4434 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); 4435 data->water_marks_bitmap = WaterMarksExist; 4436 } 4437 4438 return 0; 4439 } 4440 4441 static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) 4442 { 4443 static const char *ppfeature_name[] = { 4444 "DPM_PREFETCHER", 4445 "GFXCLK_DPM", 4446 "UCLK_DPM", 4447 "SOCCLK_DPM", 4448 "UVD_DPM", 4449 "VCE_DPM", 4450 "ULV", 4451 "MP0CLK_DPM", 4452 "LINK_DPM", 4453 "DCEFCLK_DPM", 4454 "AVFS", 4455 "GFXCLK_DS", 4456 "SOCCLK_DS", 4457 "LCLK_DS", 4458 "PPT", 4459 "TDC", 4460 "THERMAL", 4461 "GFX_PER_CU_CG", 4462 "RM", 4463 "DCEFCLK_DS", 4464 "ACDC", 4465 "VR0HOT", 4466 "VR1HOT", 4467 "FW_CTF", 4468 "LED_DISPLAY", 4469 "FAN_CONTROL", 4470 "FAST_PPT", 4471 "DIDT", 4472 "ACG", 4473 "PCC_LIMIT"}; 4474 static const char *output_title[] = { 4475 "FEATURES", 4476 "BITMASK", 4477 "ENABLEMENT"}; 4478 uint64_t features_enabled; 4479 int i; 4480 int ret = 0; 4481 int size = 0; 4482 4483 ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); 4484 PP_ASSERT_WITH_CODE(!ret, 4485 "[EnableAllSmuFeatures] Failed to get enabled smc features!", 4486 return ret); 4487 4488 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); 4489 size += sprintf(buf + size, "%-19s %-22s %s\n", 4490 output_title[0], 4491 output_title[1], 4492 output_title[2]); 4493 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 4494 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", 4495 ppfeature_name[i], 4496 1ULL << i, 4497 (features_enabled & (1ULL << i)) ? "Y" : "N"); 4498 } 4499 4500 return size; 4501 } 4502 4503 static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) 4504 { 4505 uint64_t features_enabled; 4506 uint64_t features_to_enable; 4507 uint64_t features_to_disable; 4508 int ret = 0; 4509 4510 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) 4511 return -EINVAL; 4512 4513 ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); 4514 if (ret) 4515 return ret; 4516 4517 features_to_disable = 4518 features_enabled & ~new_ppfeature_masks; 4519 features_to_enable = 4520 ~features_enabled & new_ppfeature_masks; 4521 4522 pr_debug("features_to_disable 0x%llx\n", features_to_disable); 4523 pr_debug("features_to_enable 0x%llx\n", features_to_enable); 4524 4525 if (features_to_disable) { 4526 ret = vega10_enable_smc_features(hwmgr, false, features_to_disable); 4527 if (ret) 4528 return ret; 4529 } 4530 4531 if (features_to_enable) { 4532 ret = vega10_enable_smc_features(hwmgr, true, features_to_enable); 4533 if (ret) 4534 return ret; 4535 } 4536 4537 return 0; 4538 } 4539 4540 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, 4541 enum pp_clock_type type, char *buf) 4542 { 4543 struct vega10_hwmgr *data = hwmgr->backend; 4544 struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); 4545 struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); 4546 struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table); 4547 struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table); 4548 struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); 4549 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL; 4550 4551 int i, now, size = 0, count = 0; 4552 4553 switch (type) { 4554 case PP_SCLK: 4555 if (data->registry_data.sclk_dpm_key_disabled) 4556 break; 4557 4558 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now); 4559 4560 if (hwmgr->pp_one_vf && 4561 (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) 4562 count = 5; 4563 else 4564 count = sclk_table->count; 4565 for (i = 0; i < count; i++) 4566 size += sprintf(buf + size, "%d: %uMhz %s\n", 4567 i, sclk_table->dpm_levels[i].value / 100, 4568 (i == now) ? "*" : ""); 4569 break; 4570 case PP_MCLK: 4571 if (data->registry_data.mclk_dpm_key_disabled) 4572 break; 4573 4574 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); 4575 4576 for (i = 0; i < mclk_table->count; i++) 4577 size += sprintf(buf + size, "%d: %uMhz %s\n", 4578 i, mclk_table->dpm_levels[i].value / 100, 4579 (i == now) ? "*" : ""); 4580 break; 4581 case PP_SOCCLK: 4582 if (data->registry_data.socclk_dpm_key_disabled) 4583 break; 4584 4585 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); 4586 4587 for (i = 0; i < soc_table->count; i++) 4588 size += sprintf(buf + size, "%d: %uMhz %s\n", 4589 i, soc_table->dpm_levels[i].value / 100, 4590 (i == now) ? "*" : ""); 4591 break; 4592 case PP_DCEFCLK: 4593 if (data->registry_data.dcefclk_dpm_key_disabled) 4594 break; 4595 4596 smum_send_msg_to_smc_with_parameter(hwmgr, 4597 PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now); 4598 4599 for (i = 0; i < dcef_table->count; i++) 4600 size += sprintf(buf + size, "%d: %uMhz %s\n", 4601 i, dcef_table->dpm_levels[i].value / 100, 4602 (dcef_table->dpm_levels[i].value / 100 == now) ? 4603 "*" : ""); 4604 break; 4605 case PP_PCIE: 4606 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex, &now); 4607 4608 for (i = 0; i < pcie_table->count; i++) 4609 size += sprintf(buf + size, "%d: %s %s\n", i, 4610 (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s, x1" : 4611 (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s, x16" : 4612 (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "", 4613 (i == now) ? "*" : ""); 4614 break; 4615 case OD_SCLK: 4616 if (hwmgr->od_enabled) { 4617 size = sprintf(buf, "%s:\n", "OD_SCLK"); 4618 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; 4619 for (i = 0; i < podn_vdd_dep->count; i++) 4620 size += sprintf(buf + size, "%d: %10uMhz %10umV\n", 4621 i, podn_vdd_dep->entries[i].clk / 100, 4622 podn_vdd_dep->entries[i].vddc); 4623 } 4624 break; 4625 case OD_MCLK: 4626 if (hwmgr->od_enabled) { 4627 size = sprintf(buf, "%s:\n", "OD_MCLK"); 4628 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; 4629 for (i = 0; i < podn_vdd_dep->count; i++) 4630 size += sprintf(buf + size, "%d: %10uMhz %10umV\n", 4631 i, podn_vdd_dep->entries[i].clk/100, 4632 podn_vdd_dep->entries[i].vddc); 4633 } 4634 break; 4635 case OD_RANGE: 4636 if (hwmgr->od_enabled) { 4637 size = sprintf(buf, "%s:\n", "OD_RANGE"); 4638 size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", 4639 data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, 4640 hwmgr->platform_descriptor.overdriveLimit.engineClock/100); 4641 size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", 4642 data->golden_dpm_table.mem_table.dpm_levels[0].value/100, 4643 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); 4644 size += sprintf(buf + size, "VDDC: %7umV %11umV\n", 4645 data->odn_dpm_table.min_vddc, 4646 data->odn_dpm_table.max_vddc); 4647 } 4648 break; 4649 default: 4650 break; 4651 } 4652 return size; 4653 } 4654 4655 static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 4656 { 4657 struct vega10_hwmgr *data = hwmgr->backend; 4658 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); 4659 int result = 0; 4660 4661 if ((data->water_marks_bitmap & WaterMarksExist) && 4662 !(data->water_marks_bitmap & WaterMarksLoaded)) { 4663 result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false); 4664 PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return -EINVAL); 4665 data->water_marks_bitmap |= WaterMarksLoaded; 4666 } 4667 4668 if (data->water_marks_bitmap & WaterMarksLoaded) { 4669 smum_send_msg_to_smc_with_parameter(hwmgr, 4670 PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display, 4671 NULL); 4672 } 4673 4674 return result; 4675 } 4676 4677 static int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) 4678 { 4679 struct vega10_hwmgr *data = hwmgr->backend; 4680 4681 if (data->smu_features[GNLD_DPM_UVD].supported) { 4682 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 4683 enable, 4684 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), 4685 "Attempt to Enable/Disable DPM UVD Failed!", 4686 return -1); 4687 data->smu_features[GNLD_DPM_UVD].enabled = enable; 4688 } 4689 return 0; 4690 } 4691 4692 static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) 4693 { 4694 struct vega10_hwmgr *data = hwmgr->backend; 4695 4696 data->vce_power_gated = bgate; 4697 vega10_enable_disable_vce_dpm(hwmgr, !bgate); 4698 } 4699 4700 static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) 4701 { 4702 struct vega10_hwmgr *data = hwmgr->backend; 4703 4704 data->uvd_power_gated = bgate; 4705 vega10_enable_disable_uvd_dpm(hwmgr, !bgate); 4706 } 4707 4708 static inline bool vega10_are_power_levels_equal( 4709 const struct vega10_performance_level *pl1, 4710 const struct vega10_performance_level *pl2) 4711 { 4712 return ((pl1->soc_clock == pl2->soc_clock) && 4713 (pl1->gfx_clock == pl2->gfx_clock) && 4714 (pl1->mem_clock == pl2->mem_clock)); 4715 } 4716 4717 static int vega10_check_states_equal(struct pp_hwmgr *hwmgr, 4718 const struct pp_hw_power_state *pstate1, 4719 const struct pp_hw_power_state *pstate2, bool *equal) 4720 { 4721 const struct vega10_power_state *psa; 4722 const struct vega10_power_state *psb; 4723 int i; 4724 4725 if (pstate1 == NULL || pstate2 == NULL || equal == NULL) 4726 return -EINVAL; 4727 4728 psa = cast_const_phw_vega10_power_state(pstate1); 4729 psb = cast_const_phw_vega10_power_state(pstate2); 4730 /* If the two states don't even have the same number of performance levels they cannot be the same state. */ 4731 if (psa->performance_level_count != psb->performance_level_count) { 4732 *equal = false; 4733 return 0; 4734 } 4735 4736 for (i = 0; i < psa->performance_level_count; i++) { 4737 if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { 4738 /* If we have found even one performance level pair that is different the states are different. */ 4739 *equal = false; 4740 return 0; 4741 } 4742 } 4743 4744 /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ 4745 *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); 4746 *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); 4747 *equal &= (psa->sclk_threshold == psb->sclk_threshold); 4748 4749 return 0; 4750 } 4751 4752 static bool 4753 vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) 4754 { 4755 struct vega10_hwmgr *data = hwmgr->backend; 4756 bool is_update_required = false; 4757 4758 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) 4759 is_update_required = true; 4760 4761 if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) { 4762 if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr) 4763 is_update_required = true; 4764 } 4765 4766 return is_update_required; 4767 } 4768 4769 static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 4770 { 4771 int tmp_result, result = 0; 4772 4773 if (!hwmgr->not_vf) 4774 return 0; 4775 4776 if (PP_CAP(PHM_PlatformCaps_ThermalController)) 4777 vega10_disable_thermal_protection(hwmgr); 4778 4779 tmp_result = vega10_disable_power_containment(hwmgr); 4780 PP_ASSERT_WITH_CODE((tmp_result == 0), 4781 "Failed to disable power containment!", result = tmp_result); 4782 4783 tmp_result = vega10_disable_didt_config(hwmgr); 4784 PP_ASSERT_WITH_CODE((tmp_result == 0), 4785 "Failed to disable didt config!", result = tmp_result); 4786 4787 tmp_result = vega10_avfs_enable(hwmgr, false); 4788 PP_ASSERT_WITH_CODE((tmp_result == 0), 4789 "Failed to disable AVFS!", result = tmp_result); 4790 4791 tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES); 4792 PP_ASSERT_WITH_CODE((tmp_result == 0), 4793 "Failed to stop DPM!", result = tmp_result); 4794 4795 tmp_result = vega10_disable_deep_sleep_master_switch(hwmgr); 4796 PP_ASSERT_WITH_CODE((tmp_result == 0), 4797 "Failed to disable deep sleep!", result = tmp_result); 4798 4799 tmp_result = vega10_disable_ulv(hwmgr); 4800 PP_ASSERT_WITH_CODE((tmp_result == 0), 4801 "Failed to disable ulv!", result = tmp_result); 4802 4803 tmp_result = vega10_acg_disable(hwmgr); 4804 PP_ASSERT_WITH_CODE((tmp_result == 0), 4805 "Failed to disable acg!", result = tmp_result); 4806 4807 vega10_enable_disable_PCC_limit_feature(hwmgr, false); 4808 return result; 4809 } 4810 4811 static int vega10_power_off_asic(struct pp_hwmgr *hwmgr) 4812 { 4813 struct vega10_hwmgr *data = hwmgr->backend; 4814 int result; 4815 4816 result = vega10_disable_dpm_tasks(hwmgr); 4817 PP_ASSERT_WITH_CODE((0 == result), 4818 "[disable_dpm_tasks] Failed to disable DPM!", 4819 ); 4820 data->water_marks_bitmap &= ~(WaterMarksLoaded); 4821 4822 return result; 4823 } 4824 4825 static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr) 4826 { 4827 struct vega10_hwmgr *data = hwmgr->backend; 4828 struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); 4829 struct vega10_single_dpm_table *golden_sclk_table = 4830 &(data->golden_dpm_table.gfx_table); 4831 int value = sclk_table->dpm_levels[sclk_table->count - 1].value; 4832 int golden_value = golden_sclk_table->dpm_levels 4833 [golden_sclk_table->count - 1].value; 4834 4835 value -= golden_value; 4836 value = DIV_ROUND_UP(value * 100, golden_value); 4837 4838 return value; 4839 } 4840 4841 static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) 4842 { 4843 struct vega10_hwmgr *data = hwmgr->backend; 4844 struct vega10_single_dpm_table *golden_sclk_table = 4845 &(data->golden_dpm_table.gfx_table); 4846 struct pp_power_state *ps; 4847 struct vega10_power_state *vega10_ps; 4848 4849 ps = hwmgr->request_ps; 4850 4851 if (ps == NULL) 4852 return -EINVAL; 4853 4854 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 4855 4856 vega10_ps->performance_levels 4857 [vega10_ps->performance_level_count - 1].gfx_clock = 4858 golden_sclk_table->dpm_levels 4859 [golden_sclk_table->count - 1].value * 4860 value / 100 + 4861 golden_sclk_table->dpm_levels 4862 [golden_sclk_table->count - 1].value; 4863 4864 if (vega10_ps->performance_levels 4865 [vega10_ps->performance_level_count - 1].gfx_clock > 4866 hwmgr->platform_descriptor.overdriveLimit.engineClock) { 4867 vega10_ps->performance_levels 4868 [vega10_ps->performance_level_count - 1].gfx_clock = 4869 hwmgr->platform_descriptor.overdriveLimit.engineClock; 4870 pr_warn("max sclk supported by vbios is %d\n", 4871 hwmgr->platform_descriptor.overdriveLimit.engineClock); 4872 } 4873 return 0; 4874 } 4875 4876 static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr) 4877 { 4878 struct vega10_hwmgr *data = hwmgr->backend; 4879 struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); 4880 struct vega10_single_dpm_table *golden_mclk_table = 4881 &(data->golden_dpm_table.mem_table); 4882 int value = mclk_table->dpm_levels[mclk_table->count - 1].value; 4883 int golden_value = golden_mclk_table->dpm_levels 4884 [golden_mclk_table->count - 1].value; 4885 4886 value -= golden_value; 4887 value = DIV_ROUND_UP(value * 100, golden_value); 4888 4889 return value; 4890 } 4891 4892 static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) 4893 { 4894 struct vega10_hwmgr *data = hwmgr->backend; 4895 struct vega10_single_dpm_table *golden_mclk_table = 4896 &(data->golden_dpm_table.mem_table); 4897 struct pp_power_state *ps; 4898 struct vega10_power_state *vega10_ps; 4899 4900 ps = hwmgr->request_ps; 4901 4902 if (ps == NULL) 4903 return -EINVAL; 4904 4905 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 4906 4907 vega10_ps->performance_levels 4908 [vega10_ps->performance_level_count - 1].mem_clock = 4909 golden_mclk_table->dpm_levels 4910 [golden_mclk_table->count - 1].value * 4911 value / 100 + 4912 golden_mclk_table->dpm_levels 4913 [golden_mclk_table->count - 1].value; 4914 4915 if (vega10_ps->performance_levels 4916 [vega10_ps->performance_level_count - 1].mem_clock > 4917 hwmgr->platform_descriptor.overdriveLimit.memoryClock) { 4918 vega10_ps->performance_levels 4919 [vega10_ps->performance_level_count - 1].mem_clock = 4920 hwmgr->platform_descriptor.overdriveLimit.memoryClock; 4921 pr_warn("max mclk supported by vbios is %d\n", 4922 hwmgr->platform_descriptor.overdriveLimit.memoryClock); 4923 } 4924 4925 return 0; 4926 } 4927 4928 static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, 4929 uint32_t virtual_addr_low, 4930 uint32_t virtual_addr_hi, 4931 uint32_t mc_addr_low, 4932 uint32_t mc_addr_hi, 4933 uint32_t size) 4934 { 4935 smum_send_msg_to_smc_with_parameter(hwmgr, 4936 PPSMC_MSG_SetSystemVirtualDramAddrHigh, 4937 virtual_addr_hi, 4938 NULL); 4939 smum_send_msg_to_smc_with_parameter(hwmgr, 4940 PPSMC_MSG_SetSystemVirtualDramAddrLow, 4941 virtual_addr_low, 4942 NULL); 4943 smum_send_msg_to_smc_with_parameter(hwmgr, 4944 PPSMC_MSG_DramLogSetDramAddrHigh, 4945 mc_addr_hi, 4946 NULL); 4947 4948 smum_send_msg_to_smc_with_parameter(hwmgr, 4949 PPSMC_MSG_DramLogSetDramAddrLow, 4950 mc_addr_low, 4951 NULL); 4952 4953 smum_send_msg_to_smc_with_parameter(hwmgr, 4954 PPSMC_MSG_DramLogSetDramSize, 4955 size, 4956 NULL); 4957 return 0; 4958 } 4959 4960 static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, 4961 struct PP_TemperatureRange *thermal_data) 4962 { 4963 struct vega10_hwmgr *data = hwmgr->backend; 4964 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 4965 4966 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); 4967 4968 thermal_data->max = pp_table->TedgeLimit * 4969 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4970 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * 4971 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4972 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * 4973 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4974 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * 4975 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4976 thermal_data->mem_crit_max = pp_table->ThbmLimit * 4977 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4978 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* 4979 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4980 4981 return 0; 4982 } 4983 4984 static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) 4985 { 4986 struct vega10_hwmgr *data = hwmgr->backend; 4987 uint32_t i, size = 0; 4988 static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,}, 4989 {70, 60, 1, 3,}, 4990 {90, 60, 0, 0,}, 4991 {70, 60, 0, 0,}, 4992 {70, 90, 0, 0,}, 4993 {30, 60, 0, 6,}, 4994 }; 4995 static const char *profile_name[7] = {"BOOTUP_DEFAULT", 4996 "3D_FULL_SCREEN", 4997 "POWER_SAVING", 4998 "VIDEO", 4999 "VR", 5000 "COMPUTE", 5001 "CUSTOM"}; 5002 static const char *title[6] = {"NUM", 5003 "MODE_NAME", 5004 "BUSY_SET_POINT", 5005 "FPS", 5006 "USE_RLC_BUSY", 5007 "MIN_ACTIVE_LEVEL"}; 5008 5009 if (!buf) 5010 return -EINVAL; 5011 5012 size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], 5013 title[1], title[2], title[3], title[4], title[5]); 5014 5015 for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++) 5016 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", 5017 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", 5018 profile_mode_setting[i][0], profile_mode_setting[i][1], 5019 profile_mode_setting[i][2], profile_mode_setting[i][3]); 5020 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i, 5021 profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", 5022 data->custom_profile_mode[0], data->custom_profile_mode[1], 5023 data->custom_profile_mode[2], data->custom_profile_mode[3]); 5024 return size; 5025 } 5026 5027 static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) 5028 { 5029 struct vega10_hwmgr *data = hwmgr->backend; 5030 uint8_t busy_set_point; 5031 uint8_t FPS; 5032 uint8_t use_rlc_busy; 5033 uint8_t min_active_level; 5034 uint32_t power_profile_mode = input[size]; 5035 5036 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { 5037 if (size != 0 && size != 4) 5038 return -EINVAL; 5039 5040 /* If size = 0 and the CUSTOM profile has been set already 5041 * then just apply the profile. The copy stored in the hwmgr 5042 * is zeroed out on init 5043 */ 5044 if (size == 0) { 5045 if (data->custom_profile_mode[0] != 0) 5046 goto out; 5047 else 5048 return -EINVAL; 5049 } 5050 5051 data->custom_profile_mode[0] = busy_set_point = input[0]; 5052 data->custom_profile_mode[1] = FPS = input[1]; 5053 data->custom_profile_mode[2] = use_rlc_busy = input[2]; 5054 data->custom_profile_mode[3] = min_active_level = input[3]; 5055 smum_send_msg_to_smc_with_parameter(hwmgr, 5056 PPSMC_MSG_SetCustomGfxDpmParameters, 5057 busy_set_point | FPS<<8 | 5058 use_rlc_busy << 16 | min_active_level<<24, 5059 NULL); 5060 } 5061 5062 out: 5063 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, 5064 1 << power_profile_mode, 5065 NULL); 5066 hwmgr->power_profile_mode = power_profile_mode; 5067 5068 return 0; 5069 } 5070 5071 5072 static bool vega10_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, 5073 enum PP_OD_DPM_TABLE_COMMAND type, 5074 uint32_t clk, 5075 uint32_t voltage) 5076 { 5077 struct vega10_hwmgr *data = hwmgr->backend; 5078 struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); 5079 struct vega10_single_dpm_table *golden_table; 5080 5081 if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) { 5082 pr_info("OD voltage is out of range [%d - %d] mV\n", odn_table->min_vddc, odn_table->max_vddc); 5083 return false; 5084 } 5085 5086 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { 5087 golden_table = &(data->golden_dpm_table.gfx_table); 5088 if (golden_table->dpm_levels[0].value > clk || 5089 hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { 5090 pr_info("OD engine clock is out of range [%d - %d] MHz\n", 5091 golden_table->dpm_levels[0].value/100, 5092 hwmgr->platform_descriptor.overdriveLimit.engineClock/100); 5093 return false; 5094 } 5095 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { 5096 golden_table = &(data->golden_dpm_table.mem_table); 5097 if (golden_table->dpm_levels[0].value > clk || 5098 hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { 5099 pr_info("OD memory clock is out of range [%d - %d] MHz\n", 5100 golden_table->dpm_levels[0].value/100, 5101 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); 5102 return false; 5103 } 5104 } else { 5105 return false; 5106 } 5107 5108 return true; 5109 } 5110 5111 static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr) 5112 { 5113 struct vega10_hwmgr *data = hwmgr->backend; 5114 struct pp_power_state *ps = hwmgr->request_ps; 5115 struct vega10_power_state *vega10_ps; 5116 struct vega10_single_dpm_table *gfx_dpm_table = 5117 &data->dpm_table.gfx_table; 5118 struct vega10_single_dpm_table *soc_dpm_table = 5119 &data->dpm_table.soc_table; 5120 struct vega10_single_dpm_table *mem_dpm_table = 5121 &data->dpm_table.mem_table; 5122 int max_level; 5123 5124 if (!ps) 5125 return; 5126 5127 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 5128 max_level = vega10_ps->performance_level_count - 1; 5129 5130 if (vega10_ps->performance_levels[max_level].gfx_clock != 5131 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) 5132 vega10_ps->performance_levels[max_level].gfx_clock = 5133 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; 5134 5135 if (vega10_ps->performance_levels[max_level].soc_clock != 5136 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) 5137 vega10_ps->performance_levels[max_level].soc_clock = 5138 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; 5139 5140 if (vega10_ps->performance_levels[max_level].mem_clock != 5141 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) 5142 vega10_ps->performance_levels[max_level].mem_clock = 5143 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; 5144 5145 if (!hwmgr->ps) 5146 return; 5147 5148 ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1)); 5149 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 5150 max_level = vega10_ps->performance_level_count - 1; 5151 5152 if (vega10_ps->performance_levels[max_level].gfx_clock != 5153 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) 5154 vega10_ps->performance_levels[max_level].gfx_clock = 5155 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; 5156 5157 if (vega10_ps->performance_levels[max_level].soc_clock != 5158 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) 5159 vega10_ps->performance_levels[max_level].soc_clock = 5160 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; 5161 5162 if (vega10_ps->performance_levels[max_level].mem_clock != 5163 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) 5164 vega10_ps->performance_levels[max_level].mem_clock = 5165 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; 5166 } 5167 5168 static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr, 5169 enum PP_OD_DPM_TABLE_COMMAND type) 5170 { 5171 struct vega10_hwmgr *data = hwmgr->backend; 5172 struct phm_ppt_v2_information *table_info = hwmgr->pptable; 5173 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk; 5174 struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.mem_table; 5175 5176 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk = 5177 &data->odn_dpm_table.vdd_dep_on_socclk; 5178 struct vega10_odn_vddc_lookup_table *od_vddc_lookup_table = &data->odn_dpm_table.vddc_lookup_table; 5179 5180 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep; 5181 uint8_t i, j; 5182 5183 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { 5184 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; 5185 for (i = 0; i < podn_vdd_dep->count; i++) 5186 od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc; 5187 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { 5188 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; 5189 for (i = 0; i < dpm_table->count; i++) { 5190 for (j = 0; j < od_vddc_lookup_table->count; j++) { 5191 if (od_vddc_lookup_table->entries[j].us_vdd > 5192 podn_vdd_dep->entries[i].vddc) 5193 break; 5194 } 5195 if (j == od_vddc_lookup_table->count) { 5196 j = od_vddc_lookup_table->count - 1; 5197 od_vddc_lookup_table->entries[j].us_vdd = 5198 podn_vdd_dep->entries[i].vddc; 5199 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; 5200 } 5201 podn_vdd_dep->entries[i].vddInd = j; 5202 } 5203 dpm_table = &data->dpm_table.soc_table; 5204 for (i = 0; i < dep_table->count; i++) { 5205 if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[podn_vdd_dep->count-1].vddInd && 5206 dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count-1].clk) { 5207 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; 5208 for (; (i < dep_table->count) && 5209 (dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk); i++) { 5210 podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[podn_vdd_dep->count-1].clk; 5211 dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk; 5212 } 5213 break; 5214 } else { 5215 dpm_table->dpm_levels[i].value = dep_table->entries[i].clk; 5216 podn_vdd_dep_on_socclk->entries[i].vddc = dep_table->entries[i].vddc; 5217 podn_vdd_dep_on_socclk->entries[i].vddInd = dep_table->entries[i].vddInd; 5218 podn_vdd_dep_on_socclk->entries[i].clk = dep_table->entries[i].clk; 5219 } 5220 } 5221 if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk < 5222 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk) { 5223 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; 5224 podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk = 5225 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; 5226 dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value = 5227 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; 5228 } 5229 if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd < 5230 podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd) { 5231 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; 5232 podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd = 5233 podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd; 5234 } 5235 } 5236 vega10_odn_update_power_state(hwmgr); 5237 } 5238 5239 static int vega10_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, 5240 enum PP_OD_DPM_TABLE_COMMAND type, 5241 long *input, uint32_t size) 5242 { 5243 struct vega10_hwmgr *data = hwmgr->backend; 5244 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_table; 5245 struct vega10_single_dpm_table *dpm_table; 5246 5247 uint32_t input_clk; 5248 uint32_t input_vol; 5249 uint32_t input_level; 5250 uint32_t i; 5251 5252 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", 5253 return -EINVAL); 5254 5255 if (!hwmgr->od_enabled) { 5256 pr_info("OverDrive feature not enabled\n"); 5257 return -EINVAL; 5258 } 5259 5260 if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { 5261 dpm_table = &data->dpm_table.gfx_table; 5262 podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk; 5263 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; 5264 } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { 5265 dpm_table = &data->dpm_table.mem_table; 5266 podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk; 5267 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; 5268 } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { 5269 memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table)); 5270 vega10_odn_initial_default_setting(hwmgr); 5271 vega10_odn_update_power_state(hwmgr); 5272 /* force to update all clock tables */ 5273 data->need_update_dpm_table = DPMTABLE_UPDATE_SCLK | 5274 DPMTABLE_UPDATE_MCLK | 5275 DPMTABLE_UPDATE_SOCCLK; 5276 return 0; 5277 } else if (PP_OD_COMMIT_DPM_TABLE == type) { 5278 vega10_check_dpm_table_updated(hwmgr); 5279 return 0; 5280 } else { 5281 return -EINVAL; 5282 } 5283 5284 for (i = 0; i < size; i += 3) { 5285 if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) { 5286 pr_info("invalid clock voltage input\n"); 5287 return 0; 5288 } 5289 input_level = input[i]; 5290 input_clk = input[i+1] * 100; 5291 input_vol = input[i+2]; 5292 5293 if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { 5294 dpm_table->dpm_levels[input_level].value = input_clk; 5295 podn_vdd_dep_table->entries[input_level].clk = input_clk; 5296 podn_vdd_dep_table->entries[input_level].vddc = input_vol; 5297 } else { 5298 return -EINVAL; 5299 } 5300 } 5301 vega10_odn_update_soc_table(hwmgr, type); 5302 return 0; 5303 } 5304 5305 static int vega10_set_mp1_state(struct pp_hwmgr *hwmgr, 5306 enum pp_mp1_state mp1_state) 5307 { 5308 uint16_t msg; 5309 int ret; 5310 5311 switch (mp1_state) { 5312 case PP_MP1_STATE_UNLOAD: 5313 msg = PPSMC_MSG_PrepareMp1ForUnload; 5314 break; 5315 case PP_MP1_STATE_SHUTDOWN: 5316 case PP_MP1_STATE_RESET: 5317 case PP_MP1_STATE_NONE: 5318 default: 5319 return 0; 5320 } 5321 5322 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, 5323 "[PrepareMp1] Failed!", 5324 return ret); 5325 5326 return 0; 5327 } 5328 5329 static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 5330 PHM_PerformanceLevelDesignation designation, uint32_t index, 5331 PHM_PerformanceLevel *level) 5332 { 5333 const struct vega10_power_state *ps; 5334 uint32_t i; 5335 5336 if (level == NULL || hwmgr == NULL || state == NULL) 5337 return -EINVAL; 5338 5339 ps = cast_const_phw_vega10_power_state(state); 5340 5341 i = index > ps->performance_level_count - 1 ? 5342 ps->performance_level_count - 1 : index; 5343 5344 level->coreClock = ps->performance_levels[i].gfx_clock; 5345 level->memory_clock = ps->performance_levels[i].mem_clock; 5346 5347 return 0; 5348 } 5349 5350 static int vega10_disable_power_features_for_compute_performance(struct pp_hwmgr *hwmgr, bool disable) 5351 { 5352 struct vega10_hwmgr *data = hwmgr->backend; 5353 uint32_t feature_mask = 0; 5354 5355 if (disable) { 5356 feature_mask |= data->smu_features[GNLD_ULV].enabled ? 5357 data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; 5358 feature_mask |= data->smu_features[GNLD_DS_GFXCLK].enabled ? 5359 data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; 5360 feature_mask |= data->smu_features[GNLD_DS_SOCCLK].enabled ? 5361 data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; 5362 feature_mask |= data->smu_features[GNLD_DS_LCLK].enabled ? 5363 data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; 5364 feature_mask |= data->smu_features[GNLD_DS_DCEFCLK].enabled ? 5365 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; 5366 } else { 5367 feature_mask |= (!data->smu_features[GNLD_ULV].enabled) ? 5368 data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; 5369 feature_mask |= (!data->smu_features[GNLD_DS_GFXCLK].enabled) ? 5370 data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; 5371 feature_mask |= (!data->smu_features[GNLD_DS_SOCCLK].enabled) ? 5372 data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; 5373 feature_mask |= (!data->smu_features[GNLD_DS_LCLK].enabled) ? 5374 data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; 5375 feature_mask |= (!data->smu_features[GNLD_DS_DCEFCLK].enabled) ? 5376 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; 5377 } 5378 5379 if (feature_mask) 5380 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 5381 !disable, feature_mask), 5382 "enable/disable power features for compute performance Failed!", 5383 return -EINVAL); 5384 5385 if (disable) { 5386 data->smu_features[GNLD_ULV].enabled = false; 5387 data->smu_features[GNLD_DS_GFXCLK].enabled = false; 5388 data->smu_features[GNLD_DS_SOCCLK].enabled = false; 5389 data->smu_features[GNLD_DS_LCLK].enabled = false; 5390 data->smu_features[GNLD_DS_DCEFCLK].enabled = false; 5391 } else { 5392 data->smu_features[GNLD_ULV].enabled = true; 5393 data->smu_features[GNLD_DS_GFXCLK].enabled = true; 5394 data->smu_features[GNLD_DS_SOCCLK].enabled = true; 5395 data->smu_features[GNLD_DS_LCLK].enabled = true; 5396 data->smu_features[GNLD_DS_DCEFCLK].enabled = true; 5397 } 5398 5399 return 0; 5400 5401 } 5402 5403 static const struct pp_hwmgr_func vega10_hwmgr_funcs = { 5404 .backend_init = vega10_hwmgr_backend_init, 5405 .backend_fini = vega10_hwmgr_backend_fini, 5406 .asic_setup = vega10_setup_asic_task, 5407 .dynamic_state_management_enable = vega10_enable_dpm_tasks, 5408 .dynamic_state_management_disable = vega10_disable_dpm_tasks, 5409 .get_num_of_pp_table_entries = 5410 vega10_get_number_of_powerplay_table_entries, 5411 .get_power_state_size = vega10_get_power_state_size, 5412 .get_pp_table_entry = vega10_get_pp_table_entry, 5413 .patch_boot_state = vega10_patch_boot_state, 5414 .apply_state_adjust_rules = vega10_apply_state_adjust_rules, 5415 .power_state_set = vega10_set_power_state_tasks, 5416 .get_sclk = vega10_dpm_get_sclk, 5417 .get_mclk = vega10_dpm_get_mclk, 5418 .notify_smc_display_config_after_ps_adjustment = 5419 vega10_notify_smc_display_config_after_ps_adjustment, 5420 .force_dpm_level = vega10_dpm_force_dpm_level, 5421 .stop_thermal_controller = vega10_thermal_stop_thermal_controller, 5422 .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info, 5423 .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent, 5424 .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent, 5425 .reset_fan_speed_to_default = 5426 vega10_fan_ctrl_reset_fan_speed_to_default, 5427 .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm, 5428 .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm, 5429 .uninitialize_thermal_controller = 5430 vega10_thermal_ctrl_uninitialize_thermal_controller, 5431 .set_fan_control_mode = vega10_set_fan_control_mode, 5432 .get_fan_control_mode = vega10_get_fan_control_mode, 5433 .read_sensor = vega10_read_sensor, 5434 .get_dal_power_level = vega10_get_dal_power_level, 5435 .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency, 5436 .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage, 5437 .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges, 5438 .display_clock_voltage_request = vega10_display_clock_voltage_request, 5439 .force_clock_level = vega10_force_clock_level, 5440 .print_clock_levels = vega10_print_clock_levels, 5441 .display_config_changed = vega10_display_configuration_changed_task, 5442 .powergate_uvd = vega10_power_gate_uvd, 5443 .powergate_vce = vega10_power_gate_vce, 5444 .check_states_equal = vega10_check_states_equal, 5445 .check_smc_update_required_for_display_configuration = 5446 vega10_check_smc_update_required_for_display_configuration, 5447 .power_off_asic = vega10_power_off_asic, 5448 .disable_smc_firmware_ctf = vega10_thermal_disable_alert, 5449 .get_sclk_od = vega10_get_sclk_od, 5450 .set_sclk_od = vega10_set_sclk_od, 5451 .get_mclk_od = vega10_get_mclk_od, 5452 .set_mclk_od = vega10_set_mclk_od, 5453 .avfs_control = vega10_avfs_enable, 5454 .notify_cac_buffer_info = vega10_notify_cac_buffer_info, 5455 .get_thermal_temperature_range = vega10_get_thermal_temperature_range, 5456 .register_irq_handlers = smu9_register_irq_handlers, 5457 .start_thermal_controller = vega10_start_thermal_controller, 5458 .get_power_profile_mode = vega10_get_power_profile_mode, 5459 .set_power_profile_mode = vega10_set_power_profile_mode, 5460 .set_power_limit = vega10_set_power_limit, 5461 .odn_edit_dpm_table = vega10_odn_edit_dpm_table, 5462 .get_performance_level = vega10_get_performance_level, 5463 .get_asic_baco_capability = smu9_baco_get_capability, 5464 .get_asic_baco_state = smu9_baco_get_state, 5465 .set_asic_baco_state = vega10_baco_set_state, 5466 .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost, 5467 .get_ppfeature_status = vega10_get_ppfeature_status, 5468 .set_ppfeature_status = vega10_set_ppfeature_status, 5469 .set_mp1_state = vega10_set_mp1_state, 5470 .disable_power_features_for_compute_performance = 5471 vega10_disable_power_features_for_compute_performance, 5472 }; 5473 5474 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) 5475 { 5476 struct amdgpu_device *adev = hwmgr->adev; 5477 5478 hwmgr->hwmgr_func = &vega10_hwmgr_funcs; 5479 hwmgr->pptable_func = &vega10_pptable_funcs; 5480 if (amdgpu_passthrough(adev)) 5481 return vega10_baco_set_cap(hwmgr); 5482 5483 return 0; 5484 } 5485