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 3145 /* 3146 * This is the earliest time we have all the dependency table 3147 * and the VBIOS boot state 3148 */ 3149 /* set DC compatible flag if this state supports DC */ 3150 if (!state->validation.disallowOnDC) 3151 ps->dc_compatible = true; 3152 3153 ps->uvd_clks.vclk = state->uvd_clocks.VCLK; 3154 ps->uvd_clks.dclk = state->uvd_clocks.DCLK; 3155 3156 return 0; 3157 } 3158 3159 static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr, 3160 struct pp_hw_power_state *hw_ps) 3161 { 3162 return 0; 3163 } 3164 3165 static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, 3166 struct pp_power_state *request_ps, 3167 const struct pp_power_state *current_ps) 3168 { 3169 struct amdgpu_device *adev = hwmgr->adev; 3170 struct vega10_power_state *vega10_ps = 3171 cast_phw_vega10_power_state(&request_ps->hardware); 3172 uint32_t sclk; 3173 uint32_t mclk; 3174 struct PP_Clocks minimum_clocks = {0}; 3175 bool disable_mclk_switching; 3176 bool disable_mclk_switching_for_frame_lock; 3177 bool disable_mclk_switching_for_vr; 3178 bool force_mclk_high; 3179 const struct phm_clock_and_voltage_limits *max_limits; 3180 uint32_t i; 3181 struct vega10_hwmgr *data = hwmgr->backend; 3182 struct phm_ppt_v2_information *table_info = 3183 (struct phm_ppt_v2_information *)(hwmgr->pptable); 3184 int32_t count; 3185 uint32_t stable_pstate_sclk_dpm_percentage; 3186 uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; 3187 uint32_t latency; 3188 3189 data->battery_state = (PP_StateUILabel_Battery == 3190 request_ps->classification.ui_label); 3191 3192 if (vega10_ps->performance_level_count != 2) 3193 pr_info("VI should always have 2 performance levels"); 3194 3195 max_limits = adev->pm.ac_power ? 3196 &(hwmgr->dyn_state.max_clock_voltage_on_ac) : 3197 &(hwmgr->dyn_state.max_clock_voltage_on_dc); 3198 3199 /* Cap clock DPM tables at DC MAX if it is in DC. */ 3200 if (!adev->pm.ac_power) { 3201 for (i = 0; i < vega10_ps->performance_level_count; i++) { 3202 if (vega10_ps->performance_levels[i].mem_clock > 3203 max_limits->mclk) 3204 vega10_ps->performance_levels[i].mem_clock = 3205 max_limits->mclk; 3206 if (vega10_ps->performance_levels[i].gfx_clock > 3207 max_limits->sclk) 3208 vega10_ps->performance_levels[i].gfx_clock = 3209 max_limits->sclk; 3210 } 3211 } 3212 3213 /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ 3214 minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; 3215 minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 3216 3217 if (PP_CAP(PHM_PlatformCaps_StablePState)) { 3218 stable_pstate_sclk_dpm_percentage = 3219 data->registry_data.stable_pstate_sclk_dpm_percentage; 3220 PP_ASSERT_WITH_CODE( 3221 data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 && 3222 data->registry_data.stable_pstate_sclk_dpm_percentage <= 100, 3223 "percent sclk value must range from 1% to 100%, setting default value", 3224 stable_pstate_sclk_dpm_percentage = 75); 3225 3226 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); 3227 stable_pstate_sclk = (max_limits->sclk * 3228 stable_pstate_sclk_dpm_percentage) / 100; 3229 3230 for (count = table_info->vdd_dep_on_sclk->count - 1; 3231 count >= 0; count--) { 3232 if (stable_pstate_sclk >= 3233 table_info->vdd_dep_on_sclk->entries[count].clk) { 3234 stable_pstate_sclk = 3235 table_info->vdd_dep_on_sclk->entries[count].clk; 3236 break; 3237 } 3238 } 3239 3240 if (count < 0) 3241 stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; 3242 3243 stable_pstate_mclk = max_limits->mclk; 3244 3245 minimum_clocks.engineClock = stable_pstate_sclk; 3246 minimum_clocks.memoryClock = stable_pstate_mclk; 3247 } 3248 3249 disable_mclk_switching_for_frame_lock = 3250 PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); 3251 disable_mclk_switching_for_vr = 3252 PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR); 3253 force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh); 3254 3255 if (hwmgr->display_config->num_display == 0) 3256 disable_mclk_switching = false; 3257 else 3258 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && 3259 !hwmgr->display_config->multi_monitor_in_sync) || 3260 disable_mclk_switching_for_frame_lock || 3261 disable_mclk_switching_for_vr || 3262 force_mclk_high; 3263 3264 sclk = vega10_ps->performance_levels[0].gfx_clock; 3265 mclk = vega10_ps->performance_levels[0].mem_clock; 3266 3267 if (sclk < minimum_clocks.engineClock) 3268 sclk = (minimum_clocks.engineClock > max_limits->sclk) ? 3269 max_limits->sclk : minimum_clocks.engineClock; 3270 3271 if (mclk < minimum_clocks.memoryClock) 3272 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? 3273 max_limits->mclk : minimum_clocks.memoryClock; 3274 3275 vega10_ps->performance_levels[0].gfx_clock = sclk; 3276 vega10_ps->performance_levels[0].mem_clock = mclk; 3277 3278 if (vega10_ps->performance_levels[1].gfx_clock < 3279 vega10_ps->performance_levels[0].gfx_clock) 3280 vega10_ps->performance_levels[0].gfx_clock = 3281 vega10_ps->performance_levels[1].gfx_clock; 3282 3283 if (disable_mclk_switching) { 3284 /* Set Mclk the max of level 0 and level 1 */ 3285 if (mclk < vega10_ps->performance_levels[1].mem_clock) 3286 mclk = vega10_ps->performance_levels[1].mem_clock; 3287 3288 /* Find the lowest MCLK frequency that is within 3289 * the tolerable latency defined in DAL 3290 */ 3291 latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; 3292 for (i = 0; i < data->mclk_latency_table.count; i++) { 3293 if ((data->mclk_latency_table.entries[i].latency <= latency) && 3294 (data->mclk_latency_table.entries[i].frequency >= 3295 vega10_ps->performance_levels[0].mem_clock) && 3296 (data->mclk_latency_table.entries[i].frequency <= 3297 vega10_ps->performance_levels[1].mem_clock)) 3298 mclk = data->mclk_latency_table.entries[i].frequency; 3299 } 3300 vega10_ps->performance_levels[0].mem_clock = mclk; 3301 } else { 3302 if (vega10_ps->performance_levels[1].mem_clock < 3303 vega10_ps->performance_levels[0].mem_clock) 3304 vega10_ps->performance_levels[0].mem_clock = 3305 vega10_ps->performance_levels[1].mem_clock; 3306 } 3307 3308 if (PP_CAP(PHM_PlatformCaps_StablePState)) { 3309 for (i = 0; i < vega10_ps->performance_level_count; i++) { 3310 vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk; 3311 vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk; 3312 } 3313 } 3314 3315 return 0; 3316 } 3317 3318 static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) 3319 { 3320 struct vega10_hwmgr *data = hwmgr->backend; 3321 const struct phm_set_power_state_input *states = 3322 (const struct phm_set_power_state_input *)input; 3323 const struct vega10_power_state *vega10_ps = 3324 cast_const_phw_vega10_power_state(states->pnew_state); 3325 struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); 3326 uint32_t sclk = vega10_ps->performance_levels 3327 [vega10_ps->performance_level_count - 1].gfx_clock; 3328 struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); 3329 uint32_t mclk = vega10_ps->performance_levels 3330 [vega10_ps->performance_level_count - 1].mem_clock; 3331 uint32_t i; 3332 3333 for (i = 0; i < sclk_table->count; i++) { 3334 if (sclk == sclk_table->dpm_levels[i].value) 3335 break; 3336 } 3337 3338 if (i >= sclk_table->count) { 3339 if (sclk > sclk_table->dpm_levels[i-1].value) { 3340 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; 3341 sclk_table->dpm_levels[i-1].value = sclk; 3342 } 3343 } 3344 3345 for (i = 0; i < mclk_table->count; i++) { 3346 if (mclk == mclk_table->dpm_levels[i].value) 3347 break; 3348 } 3349 3350 if (i >= mclk_table->count) { 3351 if (mclk > mclk_table->dpm_levels[i-1].value) { 3352 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; 3353 mclk_table->dpm_levels[i-1].value = mclk; 3354 } 3355 } 3356 3357 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) 3358 data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; 3359 3360 return 0; 3361 } 3362 3363 static int vega10_populate_and_upload_sclk_mclk_dpm_levels( 3364 struct pp_hwmgr *hwmgr, const void *input) 3365 { 3366 int result = 0; 3367 struct vega10_hwmgr *data = hwmgr->backend; 3368 struct vega10_dpm_table *dpm_table = &data->dpm_table; 3369 struct vega10_odn_dpm_table *odn_table = &data->odn_dpm_table; 3370 struct vega10_odn_clock_voltage_dependency_table *odn_clk_table = &odn_table->vdd_dep_on_sclk; 3371 int count; 3372 3373 if (!data->need_update_dpm_table) 3374 return 0; 3375 3376 if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { 3377 for (count = 0; count < dpm_table->gfx_table.count; count++) 3378 dpm_table->gfx_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; 3379 } 3380 3381 odn_clk_table = &odn_table->vdd_dep_on_mclk; 3382 if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { 3383 for (count = 0; count < dpm_table->mem_table.count; count++) 3384 dpm_table->mem_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; 3385 } 3386 3387 if (data->need_update_dpm_table & 3388 (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK | DPMTABLE_UPDATE_SOCCLK)) { 3389 result = vega10_populate_all_graphic_levels(hwmgr); 3390 PP_ASSERT_WITH_CODE((0 == result), 3391 "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", 3392 return result); 3393 } 3394 3395 if (data->need_update_dpm_table & 3396 (DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) { 3397 result = vega10_populate_all_memory_levels(hwmgr); 3398 PP_ASSERT_WITH_CODE((0 == result), 3399 "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", 3400 return result); 3401 } 3402 3403 vega10_populate_vddc_soc_levels(hwmgr); 3404 3405 return result; 3406 } 3407 3408 static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr, 3409 struct vega10_single_dpm_table *dpm_table, 3410 uint32_t low_limit, uint32_t high_limit) 3411 { 3412 uint32_t i; 3413 3414 for (i = 0; i < dpm_table->count; i++) { 3415 if ((dpm_table->dpm_levels[i].value < low_limit) || 3416 (dpm_table->dpm_levels[i].value > high_limit)) 3417 dpm_table->dpm_levels[i].enabled = false; 3418 else 3419 dpm_table->dpm_levels[i].enabled = true; 3420 } 3421 return 0; 3422 } 3423 3424 static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr, 3425 struct vega10_single_dpm_table *dpm_table, 3426 uint32_t low_limit, uint32_t high_limit, 3427 uint32_t disable_dpm_mask) 3428 { 3429 uint32_t i; 3430 3431 for (i = 0; i < dpm_table->count; i++) { 3432 if ((dpm_table->dpm_levels[i].value < low_limit) || 3433 (dpm_table->dpm_levels[i].value > high_limit)) 3434 dpm_table->dpm_levels[i].enabled = false; 3435 else if (!((1 << i) & disable_dpm_mask)) 3436 dpm_table->dpm_levels[i].enabled = false; 3437 else 3438 dpm_table->dpm_levels[i].enabled = true; 3439 } 3440 return 0; 3441 } 3442 3443 static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr, 3444 const struct vega10_power_state *vega10_ps) 3445 { 3446 struct vega10_hwmgr *data = hwmgr->backend; 3447 uint32_t high_limit_count; 3448 3449 PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1), 3450 "power state did not have any performance level", 3451 return -1); 3452 3453 high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1; 3454 3455 vega10_trim_single_dpm_states(hwmgr, 3456 &(data->dpm_table.soc_table), 3457 vega10_ps->performance_levels[0].soc_clock, 3458 vega10_ps->performance_levels[high_limit_count].soc_clock); 3459 3460 vega10_trim_single_dpm_states_with_mask(hwmgr, 3461 &(data->dpm_table.gfx_table), 3462 vega10_ps->performance_levels[0].gfx_clock, 3463 vega10_ps->performance_levels[high_limit_count].gfx_clock, 3464 data->disable_dpm_mask); 3465 3466 vega10_trim_single_dpm_states(hwmgr, 3467 &(data->dpm_table.mem_table), 3468 vega10_ps->performance_levels[0].mem_clock, 3469 vega10_ps->performance_levels[high_limit_count].mem_clock); 3470 3471 return 0; 3472 } 3473 3474 static uint32_t vega10_find_lowest_dpm_level( 3475 struct vega10_single_dpm_table *table) 3476 { 3477 uint32_t i; 3478 3479 for (i = 0; i < table->count; i++) { 3480 if (table->dpm_levels[i].enabled) 3481 break; 3482 } 3483 3484 return i; 3485 } 3486 3487 static uint32_t vega10_find_highest_dpm_level( 3488 struct vega10_single_dpm_table *table) 3489 { 3490 uint32_t i = 0; 3491 3492 if (table->count <= MAX_REGULAR_DPM_NUMBER) { 3493 for (i = table->count; i > 0; i--) { 3494 if (table->dpm_levels[i - 1].enabled) 3495 return i - 1; 3496 } 3497 } else { 3498 pr_info("DPM Table Has Too Many Entries!"); 3499 return MAX_REGULAR_DPM_NUMBER - 1; 3500 } 3501 3502 return i; 3503 } 3504 3505 static void vega10_apply_dal_minimum_voltage_request( 3506 struct pp_hwmgr *hwmgr) 3507 { 3508 return; 3509 } 3510 3511 static int vega10_get_soc_index_for_max_uclk(struct pp_hwmgr *hwmgr) 3512 { 3513 struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table_on_mclk; 3514 struct phm_ppt_v2_information *table_info = 3515 (struct phm_ppt_v2_information *)(hwmgr->pptable); 3516 3517 vdd_dep_table_on_mclk = table_info->vdd_dep_on_mclk; 3518 3519 return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1; 3520 } 3521 3522 static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr) 3523 { 3524 struct vega10_hwmgr *data = hwmgr->backend; 3525 uint32_t socclk_idx; 3526 3527 vega10_apply_dal_minimum_voltage_request(hwmgr); 3528 3529 if (!data->registry_data.sclk_dpm_key_disabled) { 3530 if (data->smc_state_table.gfx_boot_level != 3531 data->dpm_table.gfx_table.dpm_state.soft_min_level) { 3532 smum_send_msg_to_smc_with_parameter(hwmgr, 3533 PPSMC_MSG_SetSoftMinGfxclkByIndex, 3534 data->smc_state_table.gfx_boot_level, 3535 NULL); 3536 3537 data->dpm_table.gfx_table.dpm_state.soft_min_level = 3538 data->smc_state_table.gfx_boot_level; 3539 } 3540 } 3541 3542 if (!data->registry_data.mclk_dpm_key_disabled) { 3543 if (data->smc_state_table.mem_boot_level != 3544 data->dpm_table.mem_table.dpm_state.soft_min_level) { 3545 if ((data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) 3546 && hwmgr->not_vf) { 3547 socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr); 3548 smum_send_msg_to_smc_with_parameter(hwmgr, 3549 PPSMC_MSG_SetSoftMinSocclkByIndex, 3550 socclk_idx, 3551 NULL); 3552 } else { 3553 smum_send_msg_to_smc_with_parameter(hwmgr, 3554 PPSMC_MSG_SetSoftMinUclkByIndex, 3555 data->smc_state_table.mem_boot_level, 3556 NULL); 3557 } 3558 data->dpm_table.mem_table.dpm_state.soft_min_level = 3559 data->smc_state_table.mem_boot_level; 3560 } 3561 } 3562 3563 if (!hwmgr->not_vf) 3564 return 0; 3565 3566 if (!data->registry_data.socclk_dpm_key_disabled) { 3567 if (data->smc_state_table.soc_boot_level != 3568 data->dpm_table.soc_table.dpm_state.soft_min_level) { 3569 smum_send_msg_to_smc_with_parameter(hwmgr, 3570 PPSMC_MSG_SetSoftMinSocclkByIndex, 3571 data->smc_state_table.soc_boot_level, 3572 NULL); 3573 data->dpm_table.soc_table.dpm_state.soft_min_level = 3574 data->smc_state_table.soc_boot_level; 3575 } 3576 } 3577 3578 return 0; 3579 } 3580 3581 static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr) 3582 { 3583 struct vega10_hwmgr *data = hwmgr->backend; 3584 3585 vega10_apply_dal_minimum_voltage_request(hwmgr); 3586 3587 if (!data->registry_data.sclk_dpm_key_disabled) { 3588 if (data->smc_state_table.gfx_max_level != 3589 data->dpm_table.gfx_table.dpm_state.soft_max_level) { 3590 smum_send_msg_to_smc_with_parameter(hwmgr, 3591 PPSMC_MSG_SetSoftMaxGfxclkByIndex, 3592 data->smc_state_table.gfx_max_level, 3593 NULL); 3594 data->dpm_table.gfx_table.dpm_state.soft_max_level = 3595 data->smc_state_table.gfx_max_level; 3596 } 3597 } 3598 3599 if (!data->registry_data.mclk_dpm_key_disabled) { 3600 if (data->smc_state_table.mem_max_level != 3601 data->dpm_table.mem_table.dpm_state.soft_max_level) { 3602 smum_send_msg_to_smc_with_parameter(hwmgr, 3603 PPSMC_MSG_SetSoftMaxUclkByIndex, 3604 data->smc_state_table.mem_max_level, 3605 NULL); 3606 data->dpm_table.mem_table.dpm_state.soft_max_level = 3607 data->smc_state_table.mem_max_level; 3608 } 3609 } 3610 3611 if (!hwmgr->not_vf) 3612 return 0; 3613 3614 if (!data->registry_data.socclk_dpm_key_disabled) { 3615 if (data->smc_state_table.soc_max_level != 3616 data->dpm_table.soc_table.dpm_state.soft_max_level) { 3617 smum_send_msg_to_smc_with_parameter(hwmgr, 3618 PPSMC_MSG_SetSoftMaxSocclkByIndex, 3619 data->smc_state_table.soc_max_level, 3620 NULL); 3621 data->dpm_table.soc_table.dpm_state.soft_max_level = 3622 data->smc_state_table.soc_max_level; 3623 } 3624 } 3625 3626 return 0; 3627 } 3628 3629 static int vega10_generate_dpm_level_enable_mask( 3630 struct pp_hwmgr *hwmgr, const void *input) 3631 { 3632 struct vega10_hwmgr *data = hwmgr->backend; 3633 const struct phm_set_power_state_input *states = 3634 (const struct phm_set_power_state_input *)input; 3635 const struct vega10_power_state *vega10_ps = 3636 cast_const_phw_vega10_power_state(states->pnew_state); 3637 int i; 3638 3639 PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps), 3640 "Attempt to Trim DPM States Failed!", 3641 return -1); 3642 3643 data->smc_state_table.gfx_boot_level = 3644 vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 3645 data->smc_state_table.gfx_max_level = 3646 vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 3647 data->smc_state_table.mem_boot_level = 3648 vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 3649 data->smc_state_table.mem_max_level = 3650 vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); 3651 data->smc_state_table.soc_boot_level = 3652 vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table)); 3653 data->smc_state_table.soc_max_level = 3654 vega10_find_highest_dpm_level(&(data->dpm_table.soc_table)); 3655 3656 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 3657 "Attempt to upload DPM Bootup Levels Failed!", 3658 return -1); 3659 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 3660 "Attempt to upload DPM Max Levels Failed!", 3661 return -1); 3662 for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++) 3663 data->dpm_table.gfx_table.dpm_levels[i].enabled = true; 3664 3665 3666 for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++) 3667 data->dpm_table.mem_table.dpm_levels[i].enabled = true; 3668 3669 for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++) 3670 data->dpm_table.soc_table.dpm_levels[i].enabled = true; 3671 3672 return 0; 3673 } 3674 3675 int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) 3676 { 3677 struct vega10_hwmgr *data = hwmgr->backend; 3678 3679 if (data->smu_features[GNLD_DPM_VCE].supported) { 3680 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 3681 enable, 3682 data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), 3683 "Attempt to Enable/Disable DPM VCE Failed!", 3684 return -1); 3685 data->smu_features[GNLD_DPM_VCE].enabled = enable; 3686 } 3687 3688 return 0; 3689 } 3690 3691 static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr) 3692 { 3693 struct vega10_hwmgr *data = hwmgr->backend; 3694 uint32_t low_sclk_interrupt_threshold = 0; 3695 3696 if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) && 3697 (data->low_sclk_interrupt_threshold != 0)) { 3698 low_sclk_interrupt_threshold = 3699 data->low_sclk_interrupt_threshold; 3700 3701 data->smc_state_table.pp_table.LowGfxclkInterruptThreshold = 3702 cpu_to_le32(low_sclk_interrupt_threshold); 3703 3704 /* This message will also enable SmcToHost Interrupt */ 3705 smum_send_msg_to_smc_with_parameter(hwmgr, 3706 PPSMC_MSG_SetLowGfxclkInterruptThreshold, 3707 (uint32_t)low_sclk_interrupt_threshold, 3708 NULL); 3709 } 3710 3711 return 0; 3712 } 3713 3714 static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr, 3715 const void *input) 3716 { 3717 int tmp_result, result = 0; 3718 struct vega10_hwmgr *data = hwmgr->backend; 3719 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 3720 3721 tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input); 3722 PP_ASSERT_WITH_CODE(!tmp_result, 3723 "Failed to find DPM states clocks in DPM table!", 3724 result = tmp_result); 3725 3726 tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); 3727 PP_ASSERT_WITH_CODE(!tmp_result, 3728 "Failed to populate and upload SCLK MCLK DPM levels!", 3729 result = tmp_result); 3730 3731 tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input); 3732 PP_ASSERT_WITH_CODE(!tmp_result, 3733 "Failed to generate DPM level enabled mask!", 3734 result = tmp_result); 3735 3736 tmp_result = vega10_update_sclk_threshold(hwmgr); 3737 PP_ASSERT_WITH_CODE(!tmp_result, 3738 "Failed to update SCLK threshold!", 3739 result = tmp_result); 3740 3741 result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); 3742 PP_ASSERT_WITH_CODE(!result, 3743 "Failed to upload PPtable!", return result); 3744 3745 /* 3746 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. 3747 * That effectively disables AVFS feature. 3748 */ 3749 if(hwmgr->hardcode_pp_table != NULL) 3750 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; 3751 3752 vega10_update_avfs(hwmgr); 3753 3754 /* 3755 * Clear all OD flags except DPMTABLE_OD_UPDATE_VDDC. 3756 * That will help to keep AVFS disabled. 3757 */ 3758 data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; 3759 3760 return 0; 3761 } 3762 3763 static uint32_t vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 3764 { 3765 struct pp_power_state *ps; 3766 struct vega10_power_state *vega10_ps; 3767 3768 if (hwmgr == NULL) 3769 return -EINVAL; 3770 3771 ps = hwmgr->request_ps; 3772 3773 if (ps == NULL) 3774 return -EINVAL; 3775 3776 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 3777 3778 if (low) 3779 return vega10_ps->performance_levels[0].gfx_clock; 3780 else 3781 return vega10_ps->performance_levels 3782 [vega10_ps->performance_level_count - 1].gfx_clock; 3783 } 3784 3785 static uint32_t vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 3786 { 3787 struct pp_power_state *ps; 3788 struct vega10_power_state *vega10_ps; 3789 3790 if (hwmgr == NULL) 3791 return -EINVAL; 3792 3793 ps = hwmgr->request_ps; 3794 3795 if (ps == NULL) 3796 return -EINVAL; 3797 3798 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 3799 3800 if (low) 3801 return vega10_ps->performance_levels[0].mem_clock; 3802 else 3803 return vega10_ps->performance_levels 3804 [vega10_ps->performance_level_count-1].mem_clock; 3805 } 3806 3807 static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr, 3808 uint32_t *query) 3809 { 3810 uint32_t value; 3811 3812 if (!query) 3813 return -EINVAL; 3814 3815 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr, &value); 3816 3817 /* SMC returning actual watts, keep consistent with legacy asics, low 8 bit as 8 fractional bits */ 3818 *query = value << 8; 3819 3820 return 0; 3821 } 3822 3823 static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx, 3824 void *value, int *size) 3825 { 3826 struct amdgpu_device *adev = hwmgr->adev; 3827 uint32_t sclk_mhz, mclk_idx, activity_percent = 0; 3828 struct vega10_hwmgr *data = hwmgr->backend; 3829 struct vega10_dpm_table *dpm_table = &data->dpm_table; 3830 int ret = 0; 3831 uint32_t val_vid; 3832 3833 switch (idx) { 3834 case AMDGPU_PP_SENSOR_GFX_SCLK: 3835 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGfxclkActualFrequency, &sclk_mhz); 3836 *((uint32_t *)value) = sclk_mhz * 100; 3837 break; 3838 case AMDGPU_PP_SENSOR_GFX_MCLK: 3839 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &mclk_idx); 3840 if (mclk_idx < dpm_table->mem_table.count) { 3841 *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value; 3842 *size = 4; 3843 } else { 3844 ret = -EINVAL; 3845 } 3846 break; 3847 case AMDGPU_PP_SENSOR_GPU_LOAD: 3848 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0, 3849 &activity_percent); 3850 *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; 3851 *size = 4; 3852 break; 3853 case AMDGPU_PP_SENSOR_GPU_TEMP: 3854 *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr); 3855 *size = 4; 3856 break; 3857 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 3858 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHotspot, (uint32_t *)value); 3859 *((uint32_t *)value) = *((uint32_t *)value) * 3860 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 3861 *size = 4; 3862 break; 3863 case AMDGPU_PP_SENSOR_MEM_TEMP: 3864 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHBM, (uint32_t *)value); 3865 *((uint32_t *)value) = *((uint32_t *)value) * 3866 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 3867 *size = 4; 3868 break; 3869 case AMDGPU_PP_SENSOR_UVD_POWER: 3870 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; 3871 *size = 4; 3872 break; 3873 case AMDGPU_PP_SENSOR_VCE_POWER: 3874 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; 3875 *size = 4; 3876 break; 3877 case AMDGPU_PP_SENSOR_GPU_POWER: 3878 ret = vega10_get_gpu_power(hwmgr, (uint32_t *)value); 3879 break; 3880 case AMDGPU_PP_SENSOR_VDDGFX: 3881 val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_PLANE0_CURRENTVID) & 3882 SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >> 3883 SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT; 3884 *((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid); 3885 return 0; 3886 case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: 3887 ret = vega10_get_enabled_smc_features(hwmgr, (uint64_t *)value); 3888 if (!ret) 3889 *size = 8; 3890 break; 3891 default: 3892 ret = -EINVAL; 3893 break; 3894 } 3895 3896 return ret; 3897 } 3898 3899 static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr, 3900 bool has_disp) 3901 { 3902 smum_send_msg_to_smc_with_parameter(hwmgr, 3903 PPSMC_MSG_SetUclkFastSwitch, 3904 has_disp ? 1 : 0, 3905 NULL); 3906 } 3907 3908 static int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, 3909 struct pp_display_clock_request *clock_req) 3910 { 3911 int result = 0; 3912 enum amd_pp_clock_type clk_type = clock_req->clock_type; 3913 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; 3914 DSPCLK_e clk_select = 0; 3915 uint32_t clk_request = 0; 3916 3917 switch (clk_type) { 3918 case amd_pp_dcef_clock: 3919 clk_select = DSPCLK_DCEFCLK; 3920 break; 3921 case amd_pp_disp_clock: 3922 clk_select = DSPCLK_DISPCLK; 3923 break; 3924 case amd_pp_pixel_clock: 3925 clk_select = DSPCLK_PIXCLK; 3926 break; 3927 case amd_pp_phy_clock: 3928 clk_select = DSPCLK_PHYCLK; 3929 break; 3930 default: 3931 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); 3932 result = -1; 3933 break; 3934 } 3935 3936 if (!result) { 3937 clk_request = (clk_freq << 16) | clk_select; 3938 smum_send_msg_to_smc_with_parameter(hwmgr, 3939 PPSMC_MSG_RequestDisplayClockByFreq, 3940 clk_request, 3941 NULL); 3942 } 3943 3944 return result; 3945 } 3946 3947 static uint8_t vega10_get_uclk_index(struct pp_hwmgr *hwmgr, 3948 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table, 3949 uint32_t frequency) 3950 { 3951 uint8_t count; 3952 uint8_t i; 3953 3954 if (mclk_table == NULL || mclk_table->count == 0) 3955 return 0; 3956 3957 count = (uint8_t)(mclk_table->count); 3958 3959 for(i = 0; i < count; i++) { 3960 if(mclk_table->entries[i].clk >= frequency) 3961 return i; 3962 } 3963 3964 return i-1; 3965 } 3966 3967 static int vega10_notify_smc_display_config_after_ps_adjustment( 3968 struct pp_hwmgr *hwmgr) 3969 { 3970 struct vega10_hwmgr *data = hwmgr->backend; 3971 struct vega10_single_dpm_table *dpm_table = 3972 &data->dpm_table.dcef_table; 3973 struct phm_ppt_v2_information *table_info = 3974 (struct phm_ppt_v2_information *)hwmgr->pptable; 3975 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = table_info->vdd_dep_on_mclk; 3976 uint32_t idx; 3977 struct PP_Clocks min_clocks = {0}; 3978 uint32_t i; 3979 struct pp_display_clock_request clock_req; 3980 3981 if ((hwmgr->display_config->num_display > 1) && 3982 !hwmgr->display_config->multi_monitor_in_sync && 3983 !hwmgr->display_config->nb_pstate_switch_disable) 3984 vega10_notify_smc_display_change(hwmgr, false); 3985 else 3986 vega10_notify_smc_display_change(hwmgr, true); 3987 3988 min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; 3989 min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; 3990 min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 3991 3992 for (i = 0; i < dpm_table->count; i++) { 3993 if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock) 3994 break; 3995 } 3996 3997 if (i < dpm_table->count) { 3998 clock_req.clock_type = amd_pp_dcef_clock; 3999 clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 10; 4000 if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) { 4001 smum_send_msg_to_smc_with_parameter( 4002 hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, 4003 min_clocks.dcefClockInSR / 100, 4004 NULL); 4005 } else { 4006 pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); 4007 } 4008 } else { 4009 pr_debug("Cannot find requested DCEFCLK!"); 4010 } 4011 4012 if (min_clocks.memoryClock != 0) { 4013 idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock); 4014 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx, 4015 NULL); 4016 data->dpm_table.mem_table.dpm_state.soft_min_level= idx; 4017 } 4018 4019 return 0; 4020 } 4021 4022 static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr) 4023 { 4024 struct vega10_hwmgr *data = hwmgr->backend; 4025 4026 data->smc_state_table.gfx_boot_level = 4027 data->smc_state_table.gfx_max_level = 4028 vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 4029 data->smc_state_table.mem_boot_level = 4030 data->smc_state_table.mem_max_level = 4031 vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); 4032 4033 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4034 "Failed to upload boot level to highest!", 4035 return -1); 4036 4037 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4038 "Failed to upload dpm max level to highest!", 4039 return -1); 4040 4041 return 0; 4042 } 4043 4044 static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr) 4045 { 4046 struct vega10_hwmgr *data = hwmgr->backend; 4047 4048 data->smc_state_table.gfx_boot_level = 4049 data->smc_state_table.gfx_max_level = 4050 vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 4051 data->smc_state_table.mem_boot_level = 4052 data->smc_state_table.mem_max_level = 4053 vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 4054 4055 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4056 "Failed to upload boot level to highest!", 4057 return -1); 4058 4059 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4060 "Failed to upload dpm max level to highest!", 4061 return -1); 4062 4063 return 0; 4064 4065 } 4066 4067 static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr) 4068 { 4069 struct vega10_hwmgr *data = hwmgr->backend; 4070 4071 data->smc_state_table.gfx_boot_level = 4072 vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); 4073 data->smc_state_table.gfx_max_level = 4074 vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); 4075 data->smc_state_table.mem_boot_level = 4076 vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); 4077 data->smc_state_table.mem_max_level = 4078 vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); 4079 4080 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4081 "Failed to upload DPM Bootup Levels!", 4082 return -1); 4083 4084 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4085 "Failed to upload DPM Max Levels!", 4086 return -1); 4087 return 0; 4088 } 4089 4090 static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, 4091 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) 4092 { 4093 struct phm_ppt_v2_information *table_info = 4094 (struct phm_ppt_v2_information *)(hwmgr->pptable); 4095 4096 if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL && 4097 table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL && 4098 table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) { 4099 *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL; 4100 *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL; 4101 *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL; 4102 hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk; 4103 hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk; 4104 } 4105 4106 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 4107 *sclk_mask = 0; 4108 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 4109 *mclk_mask = 0; 4110 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 4111 /* under vega10 pp one vf mode, the gfx clk dpm need be lower 4112 * to level-4 due to the limited power 4113 */ 4114 if (hwmgr->pp_one_vf) 4115 *sclk_mask = 4; 4116 else 4117 *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; 4118 *soc_mask = table_info->vdd_dep_on_socclk->count - 1; 4119 *mclk_mask = table_info->vdd_dep_on_mclk->count - 1; 4120 } 4121 4122 return 0; 4123 } 4124 4125 static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) 4126 { 4127 if (!hwmgr->not_vf) 4128 return; 4129 4130 switch (mode) { 4131 case AMD_FAN_CTRL_NONE: 4132 vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); 4133 break; 4134 case AMD_FAN_CTRL_MANUAL: 4135 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 4136 vega10_fan_ctrl_stop_smc_fan_control(hwmgr); 4137 break; 4138 case AMD_FAN_CTRL_AUTO: 4139 if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) 4140 vega10_fan_ctrl_start_smc_fan_control(hwmgr); 4141 break; 4142 default: 4143 break; 4144 } 4145 } 4146 4147 static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, 4148 enum pp_clock_type type, uint32_t mask) 4149 { 4150 struct vega10_hwmgr *data = hwmgr->backend; 4151 4152 switch (type) { 4153 case PP_SCLK: 4154 data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0; 4155 data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0; 4156 4157 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4158 "Failed to upload boot level to lowest!", 4159 return -EINVAL); 4160 4161 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4162 "Failed to upload dpm max level to highest!", 4163 return -EINVAL); 4164 break; 4165 4166 case PP_MCLK: 4167 data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0; 4168 data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0; 4169 4170 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4171 "Failed to upload boot level to lowest!", 4172 return -EINVAL); 4173 4174 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4175 "Failed to upload dpm max level to highest!", 4176 return -EINVAL); 4177 4178 break; 4179 4180 case PP_SOCCLK: 4181 data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0; 4182 data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0; 4183 4184 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), 4185 "Failed to upload boot level to lowest!", 4186 return -EINVAL); 4187 4188 PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), 4189 "Failed to upload dpm max level to highest!", 4190 return -EINVAL); 4191 4192 break; 4193 4194 case PP_DCEFCLK: 4195 pr_info("Setting DCEFCLK min/max dpm level is not supported!\n"); 4196 break; 4197 4198 case PP_PCIE: 4199 default: 4200 break; 4201 } 4202 4203 return 0; 4204 } 4205 4206 static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, 4207 enum amd_dpm_forced_level level) 4208 { 4209 int ret = 0; 4210 uint32_t sclk_mask = 0; 4211 uint32_t mclk_mask = 0; 4212 uint32_t soc_mask = 0; 4213 4214 if (hwmgr->pstate_sclk == 0) 4215 vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); 4216 4217 switch (level) { 4218 case AMD_DPM_FORCED_LEVEL_HIGH: 4219 ret = vega10_force_dpm_highest(hwmgr); 4220 break; 4221 case AMD_DPM_FORCED_LEVEL_LOW: 4222 ret = vega10_force_dpm_lowest(hwmgr); 4223 break; 4224 case AMD_DPM_FORCED_LEVEL_AUTO: 4225 ret = vega10_unforce_dpm_levels(hwmgr); 4226 break; 4227 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 4228 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 4229 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 4230 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 4231 ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); 4232 if (ret) 4233 return ret; 4234 vega10_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask); 4235 vega10_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask); 4236 break; 4237 case AMD_DPM_FORCED_LEVEL_MANUAL: 4238 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 4239 default: 4240 break; 4241 } 4242 4243 if (!hwmgr->not_vf) 4244 return ret; 4245 4246 if (!ret) { 4247 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 4248 vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); 4249 else 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_AUTO); 4251 } 4252 4253 return ret; 4254 } 4255 4256 static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) 4257 { 4258 struct vega10_hwmgr *data = hwmgr->backend; 4259 4260 if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) 4261 return AMD_FAN_CTRL_MANUAL; 4262 else 4263 return AMD_FAN_CTRL_AUTO; 4264 } 4265 4266 static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr, 4267 struct amd_pp_simple_clock_info *info) 4268 { 4269 struct phm_ppt_v2_information *table_info = 4270 (struct phm_ppt_v2_information *)hwmgr->pptable; 4271 struct phm_clock_and_voltage_limits *max_limits = 4272 &table_info->max_clock_voltage_on_ac; 4273 4274 info->engine_max_clock = max_limits->sclk; 4275 info->memory_max_clock = max_limits->mclk; 4276 4277 return 0; 4278 } 4279 4280 static void vega10_get_sclks(struct pp_hwmgr *hwmgr, 4281 struct pp_clock_levels_with_latency *clocks) 4282 { 4283 struct phm_ppt_v2_information *table_info = 4284 (struct phm_ppt_v2_information *)hwmgr->pptable; 4285 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4286 table_info->vdd_dep_on_sclk; 4287 uint32_t i; 4288 4289 clocks->num_levels = 0; 4290 for (i = 0; i < dep_table->count; i++) { 4291 if (dep_table->entries[i].clk) { 4292 clocks->data[clocks->num_levels].clocks_in_khz = 4293 dep_table->entries[i].clk * 10; 4294 clocks->num_levels++; 4295 } 4296 } 4297 4298 } 4299 4300 static void vega10_get_memclocks(struct pp_hwmgr *hwmgr, 4301 struct pp_clock_levels_with_latency *clocks) 4302 { 4303 struct phm_ppt_v2_information *table_info = 4304 (struct phm_ppt_v2_information *)hwmgr->pptable; 4305 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4306 table_info->vdd_dep_on_mclk; 4307 struct vega10_hwmgr *data = hwmgr->backend; 4308 uint32_t j = 0; 4309 uint32_t i; 4310 4311 for (i = 0; i < dep_table->count; i++) { 4312 if (dep_table->entries[i].clk) { 4313 4314 clocks->data[j].clocks_in_khz = 4315 dep_table->entries[i].clk * 10; 4316 data->mclk_latency_table.entries[j].frequency = 4317 dep_table->entries[i].clk; 4318 clocks->data[j].latency_in_us = 4319 data->mclk_latency_table.entries[j].latency = 25; 4320 j++; 4321 } 4322 } 4323 clocks->num_levels = data->mclk_latency_table.count = j; 4324 } 4325 4326 static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr, 4327 struct pp_clock_levels_with_latency *clocks) 4328 { 4329 struct phm_ppt_v2_information *table_info = 4330 (struct phm_ppt_v2_information *)hwmgr->pptable; 4331 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4332 table_info->vdd_dep_on_dcefclk; 4333 uint32_t i; 4334 4335 for (i = 0; i < dep_table->count; i++) { 4336 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; 4337 clocks->data[i].latency_in_us = 0; 4338 clocks->num_levels++; 4339 } 4340 } 4341 4342 static void vega10_get_socclocks(struct pp_hwmgr *hwmgr, 4343 struct pp_clock_levels_with_latency *clocks) 4344 { 4345 struct phm_ppt_v2_information *table_info = 4346 (struct phm_ppt_v2_information *)hwmgr->pptable; 4347 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = 4348 table_info->vdd_dep_on_socclk; 4349 uint32_t i; 4350 4351 for (i = 0; i < dep_table->count; i++) { 4352 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; 4353 clocks->data[i].latency_in_us = 0; 4354 clocks->num_levels++; 4355 } 4356 } 4357 4358 static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, 4359 enum amd_pp_clock_type type, 4360 struct pp_clock_levels_with_latency *clocks) 4361 { 4362 switch (type) { 4363 case amd_pp_sys_clock: 4364 vega10_get_sclks(hwmgr, clocks); 4365 break; 4366 case amd_pp_mem_clock: 4367 vega10_get_memclocks(hwmgr, clocks); 4368 break; 4369 case amd_pp_dcef_clock: 4370 vega10_get_dcefclocks(hwmgr, clocks); 4371 break; 4372 case amd_pp_soc_clock: 4373 vega10_get_socclocks(hwmgr, clocks); 4374 break; 4375 default: 4376 return -1; 4377 } 4378 4379 return 0; 4380 } 4381 4382 static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, 4383 enum amd_pp_clock_type type, 4384 struct pp_clock_levels_with_voltage *clocks) 4385 { 4386 struct phm_ppt_v2_information *table_info = 4387 (struct phm_ppt_v2_information *)hwmgr->pptable; 4388 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; 4389 uint32_t i; 4390 4391 switch (type) { 4392 case amd_pp_mem_clock: 4393 dep_table = table_info->vdd_dep_on_mclk; 4394 break; 4395 case amd_pp_dcef_clock: 4396 dep_table = table_info->vdd_dep_on_dcefclk; 4397 break; 4398 case amd_pp_disp_clock: 4399 dep_table = table_info->vdd_dep_on_dispclk; 4400 break; 4401 case amd_pp_pixel_clock: 4402 dep_table = table_info->vdd_dep_on_pixclk; 4403 break; 4404 case amd_pp_phy_clock: 4405 dep_table = table_info->vdd_dep_on_phyclk; 4406 break; 4407 default: 4408 return -1; 4409 } 4410 4411 for (i = 0; i < dep_table->count; i++) { 4412 clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; 4413 clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table-> 4414 entries[dep_table->entries[i].vddInd].us_vdd); 4415 clocks->num_levels++; 4416 } 4417 4418 if (i < dep_table->count) 4419 return -1; 4420 4421 return 0; 4422 } 4423 4424 static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, 4425 void *clock_range) 4426 { 4427 struct vega10_hwmgr *data = hwmgr->backend; 4428 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_range; 4429 Watermarks_t *table = &(data->smc_state_table.water_marks_table); 4430 4431 if (!data->registry_data.disable_water_mark) { 4432 smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); 4433 data->water_marks_bitmap = WaterMarksExist; 4434 } 4435 4436 return 0; 4437 } 4438 4439 static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) 4440 { 4441 static const char *ppfeature_name[] = { 4442 "DPM_PREFETCHER", 4443 "GFXCLK_DPM", 4444 "UCLK_DPM", 4445 "SOCCLK_DPM", 4446 "UVD_DPM", 4447 "VCE_DPM", 4448 "ULV", 4449 "MP0CLK_DPM", 4450 "LINK_DPM", 4451 "DCEFCLK_DPM", 4452 "AVFS", 4453 "GFXCLK_DS", 4454 "SOCCLK_DS", 4455 "LCLK_DS", 4456 "PPT", 4457 "TDC", 4458 "THERMAL", 4459 "GFX_PER_CU_CG", 4460 "RM", 4461 "DCEFCLK_DS", 4462 "ACDC", 4463 "VR0HOT", 4464 "VR1HOT", 4465 "FW_CTF", 4466 "LED_DISPLAY", 4467 "FAN_CONTROL", 4468 "FAST_PPT", 4469 "DIDT", 4470 "ACG", 4471 "PCC_LIMIT"}; 4472 static const char *output_title[] = { 4473 "FEATURES", 4474 "BITMASK", 4475 "ENABLEMENT"}; 4476 uint64_t features_enabled; 4477 int i; 4478 int ret = 0; 4479 int size = 0; 4480 4481 ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); 4482 PP_ASSERT_WITH_CODE(!ret, 4483 "[EnableAllSmuFeatures] Failed to get enabled smc features!", 4484 return ret); 4485 4486 size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); 4487 size += sprintf(buf + size, "%-19s %-22s %s\n", 4488 output_title[0], 4489 output_title[1], 4490 output_title[2]); 4491 for (i = 0; i < GNLD_FEATURES_MAX; i++) { 4492 size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", 4493 ppfeature_name[i], 4494 1ULL << i, 4495 (features_enabled & (1ULL << i)) ? "Y" : "N"); 4496 } 4497 4498 return size; 4499 } 4500 4501 static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) 4502 { 4503 uint64_t features_enabled; 4504 uint64_t features_to_enable; 4505 uint64_t features_to_disable; 4506 int ret = 0; 4507 4508 if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) 4509 return -EINVAL; 4510 4511 ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); 4512 if (ret) 4513 return ret; 4514 4515 features_to_disable = 4516 features_enabled & ~new_ppfeature_masks; 4517 features_to_enable = 4518 ~features_enabled & new_ppfeature_masks; 4519 4520 pr_debug("features_to_disable 0x%llx\n", features_to_disable); 4521 pr_debug("features_to_enable 0x%llx\n", features_to_enable); 4522 4523 if (features_to_disable) { 4524 ret = vega10_enable_smc_features(hwmgr, false, features_to_disable); 4525 if (ret) 4526 return ret; 4527 } 4528 4529 if (features_to_enable) { 4530 ret = vega10_enable_smc_features(hwmgr, true, features_to_enable); 4531 if (ret) 4532 return ret; 4533 } 4534 4535 return 0; 4536 } 4537 4538 static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, 4539 enum pp_clock_type type, char *buf) 4540 { 4541 struct vega10_hwmgr *data = hwmgr->backend; 4542 struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); 4543 struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); 4544 struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table); 4545 struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table); 4546 struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); 4547 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL; 4548 4549 int i, now, size = 0, count = 0; 4550 4551 switch (type) { 4552 case PP_SCLK: 4553 if (data->registry_data.sclk_dpm_key_disabled) 4554 break; 4555 4556 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now); 4557 4558 if (hwmgr->pp_one_vf && 4559 (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) 4560 count = 5; 4561 else 4562 count = sclk_table->count; 4563 for (i = 0; i < count; i++) 4564 size += sprintf(buf + size, "%d: %uMhz %s\n", 4565 i, sclk_table->dpm_levels[i].value / 100, 4566 (i == now) ? "*" : ""); 4567 break; 4568 case PP_MCLK: 4569 if (data->registry_data.mclk_dpm_key_disabled) 4570 break; 4571 4572 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); 4573 4574 for (i = 0; i < mclk_table->count; i++) 4575 size += sprintf(buf + size, "%d: %uMhz %s\n", 4576 i, mclk_table->dpm_levels[i].value / 100, 4577 (i == now) ? "*" : ""); 4578 break; 4579 case PP_SOCCLK: 4580 if (data->registry_data.socclk_dpm_key_disabled) 4581 break; 4582 4583 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); 4584 4585 for (i = 0; i < soc_table->count; i++) 4586 size += sprintf(buf + size, "%d: %uMhz %s\n", 4587 i, soc_table->dpm_levels[i].value / 100, 4588 (i == now) ? "*" : ""); 4589 break; 4590 case PP_DCEFCLK: 4591 if (data->registry_data.dcefclk_dpm_key_disabled) 4592 break; 4593 4594 smum_send_msg_to_smc_with_parameter(hwmgr, 4595 PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now); 4596 4597 for (i = 0; i < dcef_table->count; i++) 4598 size += sprintf(buf + size, "%d: %uMhz %s\n", 4599 i, dcef_table->dpm_levels[i].value / 100, 4600 (dcef_table->dpm_levels[i].value / 100 == now) ? 4601 "*" : ""); 4602 break; 4603 case PP_PCIE: 4604 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex, &now); 4605 4606 for (i = 0; i < pcie_table->count; i++) 4607 size += sprintf(buf + size, "%d: %s %s\n", i, 4608 (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s, x1" : 4609 (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s, x16" : 4610 (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "", 4611 (i == now) ? "*" : ""); 4612 break; 4613 case OD_SCLK: 4614 if (hwmgr->od_enabled) { 4615 size = sprintf(buf, "%s:\n", "OD_SCLK"); 4616 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; 4617 for (i = 0; i < podn_vdd_dep->count; i++) 4618 size += sprintf(buf + size, "%d: %10uMhz %10umV\n", 4619 i, podn_vdd_dep->entries[i].clk / 100, 4620 podn_vdd_dep->entries[i].vddc); 4621 } 4622 break; 4623 case OD_MCLK: 4624 if (hwmgr->od_enabled) { 4625 size = sprintf(buf, "%s:\n", "OD_MCLK"); 4626 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; 4627 for (i = 0; i < podn_vdd_dep->count; i++) 4628 size += sprintf(buf + size, "%d: %10uMhz %10umV\n", 4629 i, podn_vdd_dep->entries[i].clk/100, 4630 podn_vdd_dep->entries[i].vddc); 4631 } 4632 break; 4633 case OD_RANGE: 4634 if (hwmgr->od_enabled) { 4635 size = sprintf(buf, "%s:\n", "OD_RANGE"); 4636 size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", 4637 data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, 4638 hwmgr->platform_descriptor.overdriveLimit.engineClock/100); 4639 size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", 4640 data->golden_dpm_table.mem_table.dpm_levels[0].value/100, 4641 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); 4642 size += sprintf(buf + size, "VDDC: %7umV %11umV\n", 4643 data->odn_dpm_table.min_vddc, 4644 data->odn_dpm_table.max_vddc); 4645 } 4646 break; 4647 default: 4648 break; 4649 } 4650 return size; 4651 } 4652 4653 static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 4654 { 4655 struct vega10_hwmgr *data = hwmgr->backend; 4656 Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); 4657 int result = 0; 4658 4659 if ((data->water_marks_bitmap & WaterMarksExist) && 4660 !(data->water_marks_bitmap & WaterMarksLoaded)) { 4661 result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false); 4662 PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return -EINVAL); 4663 data->water_marks_bitmap |= WaterMarksLoaded; 4664 } 4665 4666 if (data->water_marks_bitmap & WaterMarksLoaded) { 4667 smum_send_msg_to_smc_with_parameter(hwmgr, 4668 PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display, 4669 NULL); 4670 } 4671 4672 return result; 4673 } 4674 4675 static int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) 4676 { 4677 struct vega10_hwmgr *data = hwmgr->backend; 4678 4679 if (data->smu_features[GNLD_DPM_UVD].supported) { 4680 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 4681 enable, 4682 data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), 4683 "Attempt to Enable/Disable DPM UVD Failed!", 4684 return -1); 4685 data->smu_features[GNLD_DPM_UVD].enabled = enable; 4686 } 4687 return 0; 4688 } 4689 4690 static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) 4691 { 4692 struct vega10_hwmgr *data = hwmgr->backend; 4693 4694 data->vce_power_gated = bgate; 4695 vega10_enable_disable_vce_dpm(hwmgr, !bgate); 4696 } 4697 4698 static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) 4699 { 4700 struct vega10_hwmgr *data = hwmgr->backend; 4701 4702 data->uvd_power_gated = bgate; 4703 vega10_enable_disable_uvd_dpm(hwmgr, !bgate); 4704 } 4705 4706 static inline bool vega10_are_power_levels_equal( 4707 const struct vega10_performance_level *pl1, 4708 const struct vega10_performance_level *pl2) 4709 { 4710 return ((pl1->soc_clock == pl2->soc_clock) && 4711 (pl1->gfx_clock == pl2->gfx_clock) && 4712 (pl1->mem_clock == pl2->mem_clock)); 4713 } 4714 4715 static int vega10_check_states_equal(struct pp_hwmgr *hwmgr, 4716 const struct pp_hw_power_state *pstate1, 4717 const struct pp_hw_power_state *pstate2, bool *equal) 4718 { 4719 const struct vega10_power_state *psa; 4720 const struct vega10_power_state *psb; 4721 int i; 4722 4723 if (pstate1 == NULL || pstate2 == NULL || equal == NULL) 4724 return -EINVAL; 4725 4726 psa = cast_const_phw_vega10_power_state(pstate1); 4727 psb = cast_const_phw_vega10_power_state(pstate2); 4728 /* If the two states don't even have the same number of performance levels they cannot be the same state. */ 4729 if (psa->performance_level_count != psb->performance_level_count) { 4730 *equal = false; 4731 return 0; 4732 } 4733 4734 for (i = 0; i < psa->performance_level_count; i++) { 4735 if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { 4736 /* If we have found even one performance level pair that is different the states are different. */ 4737 *equal = false; 4738 return 0; 4739 } 4740 } 4741 4742 /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ 4743 *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); 4744 *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); 4745 *equal &= (psa->sclk_threshold == psb->sclk_threshold); 4746 4747 return 0; 4748 } 4749 4750 static bool 4751 vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) 4752 { 4753 struct vega10_hwmgr *data = hwmgr->backend; 4754 bool is_update_required = false; 4755 4756 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) 4757 is_update_required = true; 4758 4759 if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) { 4760 if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr) 4761 is_update_required = true; 4762 } 4763 4764 return is_update_required; 4765 } 4766 4767 static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 4768 { 4769 int tmp_result, result = 0; 4770 4771 if (!hwmgr->not_vf) 4772 return 0; 4773 4774 if (PP_CAP(PHM_PlatformCaps_ThermalController)) 4775 vega10_disable_thermal_protection(hwmgr); 4776 4777 tmp_result = vega10_disable_power_containment(hwmgr); 4778 PP_ASSERT_WITH_CODE((tmp_result == 0), 4779 "Failed to disable power containment!", result = tmp_result); 4780 4781 tmp_result = vega10_disable_didt_config(hwmgr); 4782 PP_ASSERT_WITH_CODE((tmp_result == 0), 4783 "Failed to disable didt config!", result = tmp_result); 4784 4785 tmp_result = vega10_avfs_enable(hwmgr, false); 4786 PP_ASSERT_WITH_CODE((tmp_result == 0), 4787 "Failed to disable AVFS!", result = tmp_result); 4788 4789 tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES); 4790 PP_ASSERT_WITH_CODE((tmp_result == 0), 4791 "Failed to stop DPM!", result = tmp_result); 4792 4793 tmp_result = vega10_disable_deep_sleep_master_switch(hwmgr); 4794 PP_ASSERT_WITH_CODE((tmp_result == 0), 4795 "Failed to disable deep sleep!", result = tmp_result); 4796 4797 tmp_result = vega10_disable_ulv(hwmgr); 4798 PP_ASSERT_WITH_CODE((tmp_result == 0), 4799 "Failed to disable ulv!", result = tmp_result); 4800 4801 tmp_result = vega10_acg_disable(hwmgr); 4802 PP_ASSERT_WITH_CODE((tmp_result == 0), 4803 "Failed to disable acg!", result = tmp_result); 4804 4805 vega10_enable_disable_PCC_limit_feature(hwmgr, false); 4806 return result; 4807 } 4808 4809 static int vega10_power_off_asic(struct pp_hwmgr *hwmgr) 4810 { 4811 struct vega10_hwmgr *data = hwmgr->backend; 4812 int result; 4813 4814 result = vega10_disable_dpm_tasks(hwmgr); 4815 PP_ASSERT_WITH_CODE((0 == result), 4816 "[disable_dpm_tasks] Failed to disable DPM!", 4817 ); 4818 data->water_marks_bitmap &= ~(WaterMarksLoaded); 4819 4820 return result; 4821 } 4822 4823 static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr) 4824 { 4825 struct vega10_hwmgr *data = hwmgr->backend; 4826 struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); 4827 struct vega10_single_dpm_table *golden_sclk_table = 4828 &(data->golden_dpm_table.gfx_table); 4829 int value = sclk_table->dpm_levels[sclk_table->count - 1].value; 4830 int golden_value = golden_sclk_table->dpm_levels 4831 [golden_sclk_table->count - 1].value; 4832 4833 value -= golden_value; 4834 value = DIV_ROUND_UP(value * 100, golden_value); 4835 4836 return value; 4837 } 4838 4839 static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) 4840 { 4841 struct vega10_hwmgr *data = hwmgr->backend; 4842 struct vega10_single_dpm_table *golden_sclk_table = 4843 &(data->golden_dpm_table.gfx_table); 4844 struct pp_power_state *ps; 4845 struct vega10_power_state *vega10_ps; 4846 4847 ps = hwmgr->request_ps; 4848 4849 if (ps == NULL) 4850 return -EINVAL; 4851 4852 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 4853 4854 vega10_ps->performance_levels 4855 [vega10_ps->performance_level_count - 1].gfx_clock = 4856 golden_sclk_table->dpm_levels 4857 [golden_sclk_table->count - 1].value * 4858 value / 100 + 4859 golden_sclk_table->dpm_levels 4860 [golden_sclk_table->count - 1].value; 4861 4862 if (vega10_ps->performance_levels 4863 [vega10_ps->performance_level_count - 1].gfx_clock > 4864 hwmgr->platform_descriptor.overdriveLimit.engineClock) { 4865 vega10_ps->performance_levels 4866 [vega10_ps->performance_level_count - 1].gfx_clock = 4867 hwmgr->platform_descriptor.overdriveLimit.engineClock; 4868 pr_warn("max sclk supported by vbios is %d\n", 4869 hwmgr->platform_descriptor.overdriveLimit.engineClock); 4870 } 4871 return 0; 4872 } 4873 4874 static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr) 4875 { 4876 struct vega10_hwmgr *data = hwmgr->backend; 4877 struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); 4878 struct vega10_single_dpm_table *golden_mclk_table = 4879 &(data->golden_dpm_table.mem_table); 4880 int value = mclk_table->dpm_levels[mclk_table->count - 1].value; 4881 int golden_value = golden_mclk_table->dpm_levels 4882 [golden_mclk_table->count - 1].value; 4883 4884 value -= golden_value; 4885 value = DIV_ROUND_UP(value * 100, golden_value); 4886 4887 return value; 4888 } 4889 4890 static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) 4891 { 4892 struct vega10_hwmgr *data = hwmgr->backend; 4893 struct vega10_single_dpm_table *golden_mclk_table = 4894 &(data->golden_dpm_table.mem_table); 4895 struct pp_power_state *ps; 4896 struct vega10_power_state *vega10_ps; 4897 4898 ps = hwmgr->request_ps; 4899 4900 if (ps == NULL) 4901 return -EINVAL; 4902 4903 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 4904 4905 vega10_ps->performance_levels 4906 [vega10_ps->performance_level_count - 1].mem_clock = 4907 golden_mclk_table->dpm_levels 4908 [golden_mclk_table->count - 1].value * 4909 value / 100 + 4910 golden_mclk_table->dpm_levels 4911 [golden_mclk_table->count - 1].value; 4912 4913 if (vega10_ps->performance_levels 4914 [vega10_ps->performance_level_count - 1].mem_clock > 4915 hwmgr->platform_descriptor.overdriveLimit.memoryClock) { 4916 vega10_ps->performance_levels 4917 [vega10_ps->performance_level_count - 1].mem_clock = 4918 hwmgr->platform_descriptor.overdriveLimit.memoryClock; 4919 pr_warn("max mclk supported by vbios is %d\n", 4920 hwmgr->platform_descriptor.overdriveLimit.memoryClock); 4921 } 4922 4923 return 0; 4924 } 4925 4926 static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, 4927 uint32_t virtual_addr_low, 4928 uint32_t virtual_addr_hi, 4929 uint32_t mc_addr_low, 4930 uint32_t mc_addr_hi, 4931 uint32_t size) 4932 { 4933 smum_send_msg_to_smc_with_parameter(hwmgr, 4934 PPSMC_MSG_SetSystemVirtualDramAddrHigh, 4935 virtual_addr_hi, 4936 NULL); 4937 smum_send_msg_to_smc_with_parameter(hwmgr, 4938 PPSMC_MSG_SetSystemVirtualDramAddrLow, 4939 virtual_addr_low, 4940 NULL); 4941 smum_send_msg_to_smc_with_parameter(hwmgr, 4942 PPSMC_MSG_DramLogSetDramAddrHigh, 4943 mc_addr_hi, 4944 NULL); 4945 4946 smum_send_msg_to_smc_with_parameter(hwmgr, 4947 PPSMC_MSG_DramLogSetDramAddrLow, 4948 mc_addr_low, 4949 NULL); 4950 4951 smum_send_msg_to_smc_with_parameter(hwmgr, 4952 PPSMC_MSG_DramLogSetDramSize, 4953 size, 4954 NULL); 4955 return 0; 4956 } 4957 4958 static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, 4959 struct PP_TemperatureRange *thermal_data) 4960 { 4961 struct vega10_hwmgr *data = hwmgr->backend; 4962 PPTable_t *pp_table = &(data->smc_state_table.pp_table); 4963 4964 memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); 4965 4966 thermal_data->max = pp_table->TedgeLimit * 4967 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4968 thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * 4969 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4970 thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * 4971 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4972 thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * 4973 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4974 thermal_data->mem_crit_max = pp_table->ThbmLimit * 4975 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4976 thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* 4977 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4978 4979 return 0; 4980 } 4981 4982 static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) 4983 { 4984 struct vega10_hwmgr *data = hwmgr->backend; 4985 uint32_t i, size = 0; 4986 static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,}, 4987 {70, 60, 1, 3,}, 4988 {90, 60, 0, 0,}, 4989 {70, 60, 0, 0,}, 4990 {70, 90, 0, 0,}, 4991 {30, 60, 0, 6,}, 4992 }; 4993 static const char *profile_name[7] = {"BOOTUP_DEFAULT", 4994 "3D_FULL_SCREEN", 4995 "POWER_SAVING", 4996 "VIDEO", 4997 "VR", 4998 "COMPUTE", 4999 "CUSTOM"}; 5000 static const char *title[6] = {"NUM", 5001 "MODE_NAME", 5002 "BUSY_SET_POINT", 5003 "FPS", 5004 "USE_RLC_BUSY", 5005 "MIN_ACTIVE_LEVEL"}; 5006 5007 if (!buf) 5008 return -EINVAL; 5009 5010 size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], 5011 title[1], title[2], title[3], title[4], title[5]); 5012 5013 for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++) 5014 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", 5015 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", 5016 profile_mode_setting[i][0], profile_mode_setting[i][1], 5017 profile_mode_setting[i][2], profile_mode_setting[i][3]); 5018 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i, 5019 profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", 5020 data->custom_profile_mode[0], data->custom_profile_mode[1], 5021 data->custom_profile_mode[2], data->custom_profile_mode[3]); 5022 return size; 5023 } 5024 5025 static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) 5026 { 5027 struct vega10_hwmgr *data = hwmgr->backend; 5028 uint8_t busy_set_point; 5029 uint8_t FPS; 5030 uint8_t use_rlc_busy; 5031 uint8_t min_active_level; 5032 uint32_t power_profile_mode = input[size]; 5033 5034 if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { 5035 if (size != 0 && size != 4) 5036 return -EINVAL; 5037 5038 /* If size = 0 and the CUSTOM profile has been set already 5039 * then just apply the profile. The copy stored in the hwmgr 5040 * is zeroed out on init 5041 */ 5042 if (size == 0) { 5043 if (data->custom_profile_mode[0] != 0) 5044 goto out; 5045 else 5046 return -EINVAL; 5047 } 5048 5049 data->custom_profile_mode[0] = busy_set_point = input[0]; 5050 data->custom_profile_mode[1] = FPS = input[1]; 5051 data->custom_profile_mode[2] = use_rlc_busy = input[2]; 5052 data->custom_profile_mode[3] = min_active_level = input[3]; 5053 smum_send_msg_to_smc_with_parameter(hwmgr, 5054 PPSMC_MSG_SetCustomGfxDpmParameters, 5055 busy_set_point | FPS<<8 | 5056 use_rlc_busy << 16 | min_active_level<<24, 5057 NULL); 5058 } 5059 5060 out: 5061 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, 5062 1 << power_profile_mode, 5063 NULL); 5064 hwmgr->power_profile_mode = power_profile_mode; 5065 5066 return 0; 5067 } 5068 5069 5070 static bool vega10_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, 5071 enum PP_OD_DPM_TABLE_COMMAND type, 5072 uint32_t clk, 5073 uint32_t voltage) 5074 { 5075 struct vega10_hwmgr *data = hwmgr->backend; 5076 struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); 5077 struct vega10_single_dpm_table *golden_table; 5078 5079 if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) { 5080 pr_info("OD voltage is out of range [%d - %d] mV\n", odn_table->min_vddc, odn_table->max_vddc); 5081 return false; 5082 } 5083 5084 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { 5085 golden_table = &(data->golden_dpm_table.gfx_table); 5086 if (golden_table->dpm_levels[0].value > clk || 5087 hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { 5088 pr_info("OD engine clock is out of range [%d - %d] MHz\n", 5089 golden_table->dpm_levels[0].value/100, 5090 hwmgr->platform_descriptor.overdriveLimit.engineClock/100); 5091 return false; 5092 } 5093 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { 5094 golden_table = &(data->golden_dpm_table.mem_table); 5095 if (golden_table->dpm_levels[0].value > clk || 5096 hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { 5097 pr_info("OD memory clock is out of range [%d - %d] MHz\n", 5098 golden_table->dpm_levels[0].value/100, 5099 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); 5100 return false; 5101 } 5102 } else { 5103 return false; 5104 } 5105 5106 return true; 5107 } 5108 5109 static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr) 5110 { 5111 struct vega10_hwmgr *data = hwmgr->backend; 5112 struct pp_power_state *ps = hwmgr->request_ps; 5113 struct vega10_power_state *vega10_ps; 5114 struct vega10_single_dpm_table *gfx_dpm_table = 5115 &data->dpm_table.gfx_table; 5116 struct vega10_single_dpm_table *soc_dpm_table = 5117 &data->dpm_table.soc_table; 5118 struct vega10_single_dpm_table *mem_dpm_table = 5119 &data->dpm_table.mem_table; 5120 int max_level; 5121 5122 if (!ps) 5123 return; 5124 5125 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 5126 max_level = vega10_ps->performance_level_count - 1; 5127 5128 if (vega10_ps->performance_levels[max_level].gfx_clock != 5129 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) 5130 vega10_ps->performance_levels[max_level].gfx_clock = 5131 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; 5132 5133 if (vega10_ps->performance_levels[max_level].soc_clock != 5134 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) 5135 vega10_ps->performance_levels[max_level].soc_clock = 5136 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; 5137 5138 if (vega10_ps->performance_levels[max_level].mem_clock != 5139 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) 5140 vega10_ps->performance_levels[max_level].mem_clock = 5141 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; 5142 5143 if (!hwmgr->ps) 5144 return; 5145 5146 ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1)); 5147 vega10_ps = cast_phw_vega10_power_state(&ps->hardware); 5148 max_level = vega10_ps->performance_level_count - 1; 5149 5150 if (vega10_ps->performance_levels[max_level].gfx_clock != 5151 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) 5152 vega10_ps->performance_levels[max_level].gfx_clock = 5153 gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; 5154 5155 if (vega10_ps->performance_levels[max_level].soc_clock != 5156 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) 5157 vega10_ps->performance_levels[max_level].soc_clock = 5158 soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; 5159 5160 if (vega10_ps->performance_levels[max_level].mem_clock != 5161 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) 5162 vega10_ps->performance_levels[max_level].mem_clock = 5163 mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; 5164 } 5165 5166 static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr, 5167 enum PP_OD_DPM_TABLE_COMMAND type) 5168 { 5169 struct vega10_hwmgr *data = hwmgr->backend; 5170 struct phm_ppt_v2_information *table_info = hwmgr->pptable; 5171 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk; 5172 struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.mem_table; 5173 5174 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk = 5175 &data->odn_dpm_table.vdd_dep_on_socclk; 5176 struct vega10_odn_vddc_lookup_table *od_vddc_lookup_table = &data->odn_dpm_table.vddc_lookup_table; 5177 5178 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep; 5179 uint8_t i, j; 5180 5181 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { 5182 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; 5183 for (i = 0; i < podn_vdd_dep->count; i++) 5184 od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc; 5185 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { 5186 podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; 5187 for (i = 0; i < dpm_table->count; i++) { 5188 for (j = 0; j < od_vddc_lookup_table->count; j++) { 5189 if (od_vddc_lookup_table->entries[j].us_vdd > 5190 podn_vdd_dep->entries[i].vddc) 5191 break; 5192 } 5193 if (j == od_vddc_lookup_table->count) { 5194 j = od_vddc_lookup_table->count - 1; 5195 od_vddc_lookup_table->entries[j].us_vdd = 5196 podn_vdd_dep->entries[i].vddc; 5197 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; 5198 } 5199 podn_vdd_dep->entries[i].vddInd = j; 5200 } 5201 dpm_table = &data->dpm_table.soc_table; 5202 for (i = 0; i < dep_table->count; i++) { 5203 if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[podn_vdd_dep->count-1].vddInd && 5204 dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count-1].clk) { 5205 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; 5206 for (; (i < dep_table->count) && 5207 (dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk); i++) { 5208 podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[podn_vdd_dep->count-1].clk; 5209 dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk; 5210 } 5211 break; 5212 } else { 5213 dpm_table->dpm_levels[i].value = dep_table->entries[i].clk; 5214 podn_vdd_dep_on_socclk->entries[i].vddc = dep_table->entries[i].vddc; 5215 podn_vdd_dep_on_socclk->entries[i].vddInd = dep_table->entries[i].vddInd; 5216 podn_vdd_dep_on_socclk->entries[i].clk = dep_table->entries[i].clk; 5217 } 5218 } 5219 if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk < 5220 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk) { 5221 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; 5222 podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk = 5223 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; 5224 dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value = 5225 podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; 5226 } 5227 if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd < 5228 podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd) { 5229 data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; 5230 podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd = 5231 podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd; 5232 } 5233 } 5234 vega10_odn_update_power_state(hwmgr); 5235 } 5236 5237 static int vega10_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, 5238 enum PP_OD_DPM_TABLE_COMMAND type, 5239 long *input, uint32_t size) 5240 { 5241 struct vega10_hwmgr *data = hwmgr->backend; 5242 struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_table; 5243 struct vega10_single_dpm_table *dpm_table; 5244 5245 uint32_t input_clk; 5246 uint32_t input_vol; 5247 uint32_t input_level; 5248 uint32_t i; 5249 5250 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", 5251 return -EINVAL); 5252 5253 if (!hwmgr->od_enabled) { 5254 pr_info("OverDrive feature not enabled\n"); 5255 return -EINVAL; 5256 } 5257 5258 if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { 5259 dpm_table = &data->dpm_table.gfx_table; 5260 podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk; 5261 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; 5262 } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { 5263 dpm_table = &data->dpm_table.mem_table; 5264 podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk; 5265 data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; 5266 } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { 5267 memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table)); 5268 vega10_odn_initial_default_setting(hwmgr); 5269 vega10_odn_update_power_state(hwmgr); 5270 /* force to update all clock tables */ 5271 data->need_update_dpm_table = DPMTABLE_UPDATE_SCLK | 5272 DPMTABLE_UPDATE_MCLK | 5273 DPMTABLE_UPDATE_SOCCLK; 5274 return 0; 5275 } else if (PP_OD_COMMIT_DPM_TABLE == type) { 5276 vega10_check_dpm_table_updated(hwmgr); 5277 return 0; 5278 } else { 5279 return -EINVAL; 5280 } 5281 5282 for (i = 0; i < size; i += 3) { 5283 if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) { 5284 pr_info("invalid clock voltage input\n"); 5285 return 0; 5286 } 5287 input_level = input[i]; 5288 input_clk = input[i+1] * 100; 5289 input_vol = input[i+2]; 5290 5291 if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { 5292 dpm_table->dpm_levels[input_level].value = input_clk; 5293 podn_vdd_dep_table->entries[input_level].clk = input_clk; 5294 podn_vdd_dep_table->entries[input_level].vddc = input_vol; 5295 } else { 5296 return -EINVAL; 5297 } 5298 } 5299 vega10_odn_update_soc_table(hwmgr, type); 5300 return 0; 5301 } 5302 5303 static int vega10_set_mp1_state(struct pp_hwmgr *hwmgr, 5304 enum pp_mp1_state mp1_state) 5305 { 5306 uint16_t msg; 5307 int ret; 5308 5309 switch (mp1_state) { 5310 case PP_MP1_STATE_UNLOAD: 5311 msg = PPSMC_MSG_PrepareMp1ForUnload; 5312 break; 5313 case PP_MP1_STATE_SHUTDOWN: 5314 case PP_MP1_STATE_RESET: 5315 case PP_MP1_STATE_NONE: 5316 default: 5317 return 0; 5318 } 5319 5320 PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, 5321 "[PrepareMp1] Failed!", 5322 return ret); 5323 5324 return 0; 5325 } 5326 5327 static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 5328 PHM_PerformanceLevelDesignation designation, uint32_t index, 5329 PHM_PerformanceLevel *level) 5330 { 5331 const struct vega10_power_state *ps; 5332 uint32_t i; 5333 5334 if (level == NULL || hwmgr == NULL || state == NULL) 5335 return -EINVAL; 5336 5337 ps = cast_const_phw_vega10_power_state(state); 5338 5339 i = index > ps->performance_level_count - 1 ? 5340 ps->performance_level_count - 1 : index; 5341 5342 level->coreClock = ps->performance_levels[i].gfx_clock; 5343 level->memory_clock = ps->performance_levels[i].mem_clock; 5344 5345 return 0; 5346 } 5347 5348 static int vega10_disable_power_features_for_compute_performance(struct pp_hwmgr *hwmgr, bool disable) 5349 { 5350 struct vega10_hwmgr *data = hwmgr->backend; 5351 uint32_t feature_mask = 0; 5352 5353 if (disable) { 5354 feature_mask |= data->smu_features[GNLD_ULV].enabled ? 5355 data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; 5356 feature_mask |= data->smu_features[GNLD_DS_GFXCLK].enabled ? 5357 data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; 5358 feature_mask |= data->smu_features[GNLD_DS_SOCCLK].enabled ? 5359 data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; 5360 feature_mask |= data->smu_features[GNLD_DS_LCLK].enabled ? 5361 data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; 5362 feature_mask |= data->smu_features[GNLD_DS_DCEFCLK].enabled ? 5363 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; 5364 } else { 5365 feature_mask |= (!data->smu_features[GNLD_ULV].enabled) ? 5366 data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; 5367 feature_mask |= (!data->smu_features[GNLD_DS_GFXCLK].enabled) ? 5368 data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; 5369 feature_mask |= (!data->smu_features[GNLD_DS_SOCCLK].enabled) ? 5370 data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; 5371 feature_mask |= (!data->smu_features[GNLD_DS_LCLK].enabled) ? 5372 data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; 5373 feature_mask |= (!data->smu_features[GNLD_DS_DCEFCLK].enabled) ? 5374 data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; 5375 } 5376 5377 if (feature_mask) 5378 PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, 5379 !disable, feature_mask), 5380 "enable/disable power features for compute performance Failed!", 5381 return -EINVAL); 5382 5383 if (disable) { 5384 data->smu_features[GNLD_ULV].enabled = false; 5385 data->smu_features[GNLD_DS_GFXCLK].enabled = false; 5386 data->smu_features[GNLD_DS_SOCCLK].enabled = false; 5387 data->smu_features[GNLD_DS_LCLK].enabled = false; 5388 data->smu_features[GNLD_DS_DCEFCLK].enabled = false; 5389 } else { 5390 data->smu_features[GNLD_ULV].enabled = true; 5391 data->smu_features[GNLD_DS_GFXCLK].enabled = true; 5392 data->smu_features[GNLD_DS_SOCCLK].enabled = true; 5393 data->smu_features[GNLD_DS_LCLK].enabled = true; 5394 data->smu_features[GNLD_DS_DCEFCLK].enabled = true; 5395 } 5396 5397 return 0; 5398 5399 } 5400 5401 static const struct pp_hwmgr_func vega10_hwmgr_funcs = { 5402 .backend_init = vega10_hwmgr_backend_init, 5403 .backend_fini = vega10_hwmgr_backend_fini, 5404 .asic_setup = vega10_setup_asic_task, 5405 .dynamic_state_management_enable = vega10_enable_dpm_tasks, 5406 .dynamic_state_management_disable = vega10_disable_dpm_tasks, 5407 .get_num_of_pp_table_entries = 5408 vega10_get_number_of_powerplay_table_entries, 5409 .get_power_state_size = vega10_get_power_state_size, 5410 .get_pp_table_entry = vega10_get_pp_table_entry, 5411 .patch_boot_state = vega10_patch_boot_state, 5412 .apply_state_adjust_rules = vega10_apply_state_adjust_rules, 5413 .power_state_set = vega10_set_power_state_tasks, 5414 .get_sclk = vega10_dpm_get_sclk, 5415 .get_mclk = vega10_dpm_get_mclk, 5416 .notify_smc_display_config_after_ps_adjustment = 5417 vega10_notify_smc_display_config_after_ps_adjustment, 5418 .force_dpm_level = vega10_dpm_force_dpm_level, 5419 .stop_thermal_controller = vega10_thermal_stop_thermal_controller, 5420 .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info, 5421 .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent, 5422 .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent, 5423 .reset_fan_speed_to_default = 5424 vega10_fan_ctrl_reset_fan_speed_to_default, 5425 .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm, 5426 .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm, 5427 .uninitialize_thermal_controller = 5428 vega10_thermal_ctrl_uninitialize_thermal_controller, 5429 .set_fan_control_mode = vega10_set_fan_control_mode, 5430 .get_fan_control_mode = vega10_get_fan_control_mode, 5431 .read_sensor = vega10_read_sensor, 5432 .get_dal_power_level = vega10_get_dal_power_level, 5433 .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency, 5434 .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage, 5435 .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges, 5436 .display_clock_voltage_request = vega10_display_clock_voltage_request, 5437 .force_clock_level = vega10_force_clock_level, 5438 .print_clock_levels = vega10_print_clock_levels, 5439 .display_config_changed = vega10_display_configuration_changed_task, 5440 .powergate_uvd = vega10_power_gate_uvd, 5441 .powergate_vce = vega10_power_gate_vce, 5442 .check_states_equal = vega10_check_states_equal, 5443 .check_smc_update_required_for_display_configuration = 5444 vega10_check_smc_update_required_for_display_configuration, 5445 .power_off_asic = vega10_power_off_asic, 5446 .disable_smc_firmware_ctf = vega10_thermal_disable_alert, 5447 .get_sclk_od = vega10_get_sclk_od, 5448 .set_sclk_od = vega10_set_sclk_od, 5449 .get_mclk_od = vega10_get_mclk_od, 5450 .set_mclk_od = vega10_set_mclk_od, 5451 .avfs_control = vega10_avfs_enable, 5452 .notify_cac_buffer_info = vega10_notify_cac_buffer_info, 5453 .get_thermal_temperature_range = vega10_get_thermal_temperature_range, 5454 .register_irq_handlers = smu9_register_irq_handlers, 5455 .start_thermal_controller = vega10_start_thermal_controller, 5456 .get_power_profile_mode = vega10_get_power_profile_mode, 5457 .set_power_profile_mode = vega10_set_power_profile_mode, 5458 .set_power_limit = vega10_set_power_limit, 5459 .odn_edit_dpm_table = vega10_odn_edit_dpm_table, 5460 .get_performance_level = vega10_get_performance_level, 5461 .get_asic_baco_capability = smu9_baco_get_capability, 5462 .get_asic_baco_state = smu9_baco_get_state, 5463 .set_asic_baco_state = vega10_baco_set_state, 5464 .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost, 5465 .get_ppfeature_status = vega10_get_ppfeature_status, 5466 .set_ppfeature_status = vega10_set_ppfeature_status, 5467 .set_mp1_state = vega10_set_mp1_state, 5468 .disable_power_features_for_compute_performance = 5469 vega10_disable_power_features_for_compute_performance, 5470 }; 5471 5472 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) 5473 { 5474 struct amdgpu_device *adev = hwmgr->adev; 5475 5476 hwmgr->hwmgr_func = &vega10_hwmgr_funcs; 5477 hwmgr->pptable_func = &vega10_pptable_funcs; 5478 if (amdgpu_passthrough(adev)) 5479 return vega10_baco_set_cap(hwmgr); 5480 5481 return 0; 5482 } 5483