1 /* $NetBSD: amdgpu_smu8_hwmgr.c,v 1.4 2021/12/19 12:37:54 riastradh Exp $ */ 2 3 /* 4 * Copyright 2015 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 #include <sys/cdefs.h> 26 __KERNEL_RCSID(0, "$NetBSD: amdgpu_smu8_hwmgr.c,v 1.4 2021/12/19 12:37:54 riastradh Exp $"); 27 28 #include "pp_debug.h" 29 #include <linux/types.h> 30 #include <linux/kernel.h> 31 #include <linux/slab.h> 32 #include "atom-types.h" 33 #include "atombios.h" 34 #include "processpptables.h" 35 #include "cgs_common.h" 36 #include "smu/smu_8_0_d.h" 37 #include "smu8_fusion.h" 38 #include "smu/smu_8_0_sh_mask.h" 39 #include "smumgr.h" 40 #include "hwmgr.h" 41 #include "hardwaremanager.h" 42 #include "cz_ppsmc.h" 43 #include "smu8_hwmgr.h" 44 #include "power_state.h" 45 #include "pp_thermal.h" 46 47 #include <linux/nbsd-namespace.h> 48 49 #define ixSMUSVI_NB_CURRENTVID 0xD8230044 50 #define CURRENT_NB_VID_MASK 0xff000000 51 #define CURRENT_NB_VID__SHIFT 24 52 #define ixSMUSVI_GFX_CURRENTVID 0xD8230048 53 #define CURRENT_GFX_VID_MASK 0xff000000 54 #define CURRENT_GFX_VID__SHIFT 24 55 56 static const unsigned long smu8_magic = (unsigned long) PHM_Cz_Magic; 57 58 static struct smu8_power_state *cast_smu8_power_state(struct pp_hw_power_state *hw_ps) 59 { 60 if (smu8_magic != hw_ps->magic) 61 return NULL; 62 63 return (struct smu8_power_state *)hw_ps; 64 } 65 66 static const struct smu8_power_state *cast_const_smu8_power_state( 67 const struct pp_hw_power_state *hw_ps) 68 { 69 if (smu8_magic != hw_ps->magic) 70 return NULL; 71 72 return (const struct smu8_power_state *)hw_ps; 73 } 74 75 static uint32_t smu8_get_eclk_level(struct pp_hwmgr *hwmgr, 76 uint32_t clock, uint32_t msg) 77 { 78 int i = 0; 79 struct phm_vce_clock_voltage_dependency_table *ptable = 80 hwmgr->dyn_state.vce_clock_voltage_dependency_table; 81 82 switch (msg) { 83 case PPSMC_MSG_SetEclkSoftMin: 84 case PPSMC_MSG_SetEclkHardMin: 85 for (i = 0; i < (int)ptable->count; i++) { 86 if (clock <= ptable->entries[i].ecclk) 87 break; 88 } 89 break; 90 91 case PPSMC_MSG_SetEclkSoftMax: 92 case PPSMC_MSG_SetEclkHardMax: 93 for (i = ptable->count - 1; i >= 0; i--) { 94 if (clock >= ptable->entries[i].ecclk) 95 break; 96 } 97 break; 98 99 default: 100 break; 101 } 102 103 return i; 104 } 105 106 static uint32_t smu8_get_sclk_level(struct pp_hwmgr *hwmgr, 107 uint32_t clock, uint32_t msg) 108 { 109 int i = 0; 110 struct phm_clock_voltage_dependency_table *table = 111 hwmgr->dyn_state.vddc_dependency_on_sclk; 112 113 switch (msg) { 114 case PPSMC_MSG_SetSclkSoftMin: 115 case PPSMC_MSG_SetSclkHardMin: 116 for (i = 0; i < (int)table->count; i++) { 117 if (clock <= table->entries[i].clk) 118 break; 119 } 120 break; 121 122 case PPSMC_MSG_SetSclkSoftMax: 123 case PPSMC_MSG_SetSclkHardMax: 124 for (i = table->count - 1; i >= 0; i--) { 125 if (clock >= table->entries[i].clk) 126 break; 127 } 128 break; 129 130 default: 131 break; 132 } 133 return i; 134 } 135 136 static uint32_t smu8_get_uvd_level(struct pp_hwmgr *hwmgr, 137 uint32_t clock, uint32_t msg) 138 { 139 int i = 0; 140 struct phm_uvd_clock_voltage_dependency_table *ptable = 141 hwmgr->dyn_state.uvd_clock_voltage_dependency_table; 142 143 switch (msg) { 144 case PPSMC_MSG_SetUvdSoftMin: 145 case PPSMC_MSG_SetUvdHardMin: 146 for (i = 0; i < (int)ptable->count; i++) { 147 if (clock <= ptable->entries[i].vclk) 148 break; 149 } 150 break; 151 152 case PPSMC_MSG_SetUvdSoftMax: 153 case PPSMC_MSG_SetUvdHardMax: 154 for (i = ptable->count - 1; i >= 0; i--) { 155 if (clock >= ptable->entries[i].vclk) 156 break; 157 } 158 break; 159 160 default: 161 break; 162 } 163 164 return i; 165 } 166 167 static uint32_t smu8_get_max_sclk_level(struct pp_hwmgr *hwmgr) 168 { 169 struct smu8_hwmgr *data = hwmgr->backend; 170 171 if (data->max_sclk_level == 0) { 172 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxSclkLevel); 173 data->max_sclk_level = smum_get_argument(hwmgr) + 1; 174 } 175 176 return data->max_sclk_level; 177 } 178 179 static int smu8_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) 180 { 181 struct smu8_hwmgr *data = hwmgr->backend; 182 struct amdgpu_device *adev = hwmgr->adev; 183 184 data->gfx_ramp_step = 256*25/100; 185 data->gfx_ramp_delay = 1; /* by default, we delay 1us */ 186 187 data->mgcg_cgtt_local0 = 0x00000000; 188 data->mgcg_cgtt_local1 = 0x00000000; 189 data->clock_slow_down_freq = 25000; 190 data->skip_clock_slow_down = 1; 191 data->enable_nb_ps_policy = 1; /* disable until UNB is ready, Enabled */ 192 data->voltage_drop_in_dce_power_gating = 0; /* disable until fully verified */ 193 data->voting_rights_clients = 0x00C00033; 194 data->static_screen_threshold = 8; 195 data->ddi_power_gating_disabled = 0; 196 data->bapm_enabled = 1; 197 data->voltage_drop_threshold = 0; 198 data->gfx_power_gating_threshold = 500; 199 data->vce_slow_sclk_threshold = 20000; 200 data->dce_slow_sclk_threshold = 30000; 201 data->disable_driver_thermal_policy = 1; 202 data->disable_nb_ps3_in_battery = 0; 203 204 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 205 PHM_PlatformCaps_ABM); 206 207 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 208 PHM_PlatformCaps_NonABMSupportInPPLib); 209 210 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 211 PHM_PlatformCaps_DynamicM3Arbiter); 212 213 data->override_dynamic_mgpg = 1; 214 215 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 216 PHM_PlatformCaps_DynamicPatchPowerState); 217 218 data->thermal_auto_throttling_treshold = 0; 219 data->tdr_clock = 0; 220 data->disable_gfx_power_gating_in_uvd = 0; 221 222 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 223 PHM_PlatformCaps_DynamicUVDState); 224 225 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 226 PHM_PlatformCaps_UVDDPM); 227 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 228 PHM_PlatformCaps_VCEDPM); 229 230 data->cc6_settings.cpu_cc6_disable = false; 231 data->cc6_settings.cpu_pstate_disable = false; 232 data->cc6_settings.nb_pstate_switch_disable = false; 233 data->cc6_settings.cpu_pstate_separation_time = 0; 234 235 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 236 PHM_PlatformCaps_DisableVoltageIsland); 237 238 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 239 PHM_PlatformCaps_UVDPowerGating); 240 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 241 PHM_PlatformCaps_VCEPowerGating); 242 243 if (adev->pg_flags & AMD_PG_SUPPORT_UVD) 244 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 245 PHM_PlatformCaps_UVDPowerGating); 246 if (adev->pg_flags & AMD_PG_SUPPORT_VCE) 247 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 248 PHM_PlatformCaps_VCEPowerGating); 249 250 251 return 0; 252 } 253 254 /* convert form 8bit vid to real voltage in mV*4 */ 255 static uint32_t smu8_convert_8Bit_index_to_voltage( 256 struct pp_hwmgr *hwmgr, uint16_t voltage) 257 { 258 return 6200 - (voltage * 25); 259 } 260 261 static int smu8_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, 262 struct phm_clock_and_voltage_limits *table) 263 { 264 struct smu8_hwmgr *data = hwmgr->backend; 265 struct smu8_sys_info *sys_info = &data->sys_info; 266 struct phm_clock_voltage_dependency_table *dep_table = 267 hwmgr->dyn_state.vddc_dependency_on_sclk; 268 269 if (dep_table->count > 0) { 270 table->sclk = dep_table->entries[dep_table->count-1].clk; 271 table->vddc = smu8_convert_8Bit_index_to_voltage(hwmgr, 272 (uint16_t)dep_table->entries[dep_table->count-1].v); 273 } 274 table->mclk = sys_info->nbp_memory_clock[0]; 275 return 0; 276 } 277 278 static int smu8_init_dynamic_state_adjustment_rule_settings( 279 struct pp_hwmgr *hwmgr, 280 ATOM_CLK_VOLT_CAPABILITY *disp_voltage_table) 281 { 282 struct phm_clock_voltage_dependency_table *table_clk_vlt; 283 284 table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), 285 GFP_KERNEL); 286 287 if (NULL == table_clk_vlt) { 288 pr_err("Can not allocate memory!\n"); 289 return -ENOMEM; 290 } 291 292 table_clk_vlt->count = 8; 293 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; 294 table_clk_vlt->entries[0].v = 0; 295 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; 296 table_clk_vlt->entries[1].v = 1; 297 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; 298 table_clk_vlt->entries[2].v = 2; 299 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; 300 table_clk_vlt->entries[3].v = 3; 301 table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; 302 table_clk_vlt->entries[4].v = 4; 303 table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; 304 table_clk_vlt->entries[5].v = 5; 305 table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; 306 table_clk_vlt->entries[6].v = 6; 307 table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; 308 table_clk_vlt->entries[7].v = 7; 309 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; 310 311 return 0; 312 } 313 314 static int smu8_get_system_info_data(struct pp_hwmgr *hwmgr) 315 { 316 struct smu8_hwmgr *data = hwmgr->backend; 317 ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info = NULL; 318 uint32_t i; 319 int result = 0; 320 uint8_t frev, crev; 321 uint16_t size; 322 323 info = (ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *)smu_atom_get_data_table(hwmgr->adev, 324 GetIndexIntoMasterTable(DATA, IntegratedSystemInfo), 325 &size, &frev, &crev); 326 327 if (info == NULL) { 328 pr_err("Could not retrieve the Integrated System Info Table!\n"); 329 return -EINVAL; 330 } 331 332 if (crev != 9) { 333 pr_err("Unsupported IGP table: %d %d\n", frev, crev); 334 return -EINVAL; 335 } 336 337 data->sys_info.bootup_uma_clock = 338 le32_to_cpu(info->ulBootUpUMAClock); 339 340 data->sys_info.bootup_engine_clock = 341 le32_to_cpu(info->ulBootUpEngineClock); 342 343 data->sys_info.dentist_vco_freq = 344 le32_to_cpu(info->ulDentistVCOFreq); 345 346 data->sys_info.system_config = 347 le32_to_cpu(info->ulSystemConfig); 348 349 data->sys_info.bootup_nb_voltage_index = 350 le16_to_cpu(info->usBootUpNBVoltage); 351 352 data->sys_info.htc_hyst_lmt = 353 (info->ucHtcHystLmt == 0) ? 5 : info->ucHtcHystLmt; 354 355 data->sys_info.htc_tmp_lmt = 356 (info->ucHtcTmpLmt == 0) ? 203 : info->ucHtcTmpLmt; 357 358 if (data->sys_info.htc_tmp_lmt <= 359 data->sys_info.htc_hyst_lmt) { 360 pr_err("The htcTmpLmt should be larger than htcHystLmt.\n"); 361 return -EINVAL; 362 } 363 364 data->sys_info.nb_dpm_enable = 365 data->enable_nb_ps_policy && 366 (le32_to_cpu(info->ulSystemConfig) >> 3 & 0x1); 367 368 for (i = 0; i < SMU8_NUM_NBPSTATES; i++) { 369 if (i < SMU8_NUM_NBPMEMORYCLOCK) { 370 data->sys_info.nbp_memory_clock[i] = 371 le32_to_cpu(info->ulNbpStateMemclkFreq[i]); 372 } 373 data->sys_info.nbp_n_clock[i] = 374 le32_to_cpu(info->ulNbpStateNClkFreq[i]); 375 } 376 377 for (i = 0; i < MAX_DISPLAY_CLOCK_LEVEL; i++) { 378 data->sys_info.display_clock[i] = 379 le32_to_cpu(info->sDispClkVoltageMapping[i].ulMaximumSupportedCLK); 380 } 381 382 /* Here use 4 levels, make sure not exceed */ 383 for (i = 0; i < SMU8_NUM_NBPSTATES; i++) { 384 data->sys_info.nbp_voltage_index[i] = 385 le16_to_cpu(info->usNBPStateVoltage[i]); 386 } 387 388 if (!data->sys_info.nb_dpm_enable) { 389 for (i = 1; i < SMU8_NUM_NBPSTATES; i++) { 390 if (i < SMU8_NUM_NBPMEMORYCLOCK) { 391 data->sys_info.nbp_memory_clock[i] = 392 data->sys_info.nbp_memory_clock[0]; 393 } 394 data->sys_info.nbp_n_clock[i] = 395 data->sys_info.nbp_n_clock[0]; 396 data->sys_info.nbp_voltage_index[i] = 397 data->sys_info.nbp_voltage_index[0]; 398 } 399 } 400 401 if (le32_to_cpu(info->ulGPUCapInfo) & 402 SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) { 403 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 404 PHM_PlatformCaps_EnableDFSBypass); 405 } 406 407 data->sys_info.uma_channel_number = info->ucUMAChannelNumber; 408 409 smu8_construct_max_power_limits_table (hwmgr, 410 &hwmgr->dyn_state.max_clock_voltage_on_ac); 411 412 smu8_init_dynamic_state_adjustment_rule_settings(hwmgr, 413 &info->sDISPCLK_Voltage[0]); 414 415 return result; 416 } 417 418 static int smu8_construct_boot_state(struct pp_hwmgr *hwmgr) 419 { 420 struct smu8_hwmgr *data = hwmgr->backend; 421 422 data->boot_power_level.engineClock = 423 data->sys_info.bootup_engine_clock; 424 425 data->boot_power_level.vddcIndex = 426 (uint8_t)data->sys_info.bootup_nb_voltage_index; 427 428 data->boot_power_level.dsDividerIndex = 0; 429 data->boot_power_level.ssDividerIndex = 0; 430 data->boot_power_level.allowGnbSlow = 1; 431 data->boot_power_level.forceNBPstate = 0; 432 data->boot_power_level.hysteresis_up = 0; 433 data->boot_power_level.numSIMDToPowerDown = 0; 434 data->boot_power_level.display_wm = 0; 435 data->boot_power_level.vce_wm = 0; 436 437 return 0; 438 } 439 440 static int smu8_upload_pptable_to_smu(struct pp_hwmgr *hwmgr) 441 { 442 struct SMU8_Fusion_ClkTable *clock_table; 443 int ret; 444 uint32_t i; 445 void *table = NULL; 446 pp_atomctrl_clock_dividers_kong dividers; 447 448 struct phm_clock_voltage_dependency_table *vddc_table = 449 hwmgr->dyn_state.vddc_dependency_on_sclk; 450 struct phm_clock_voltage_dependency_table *vdd_gfx_table = 451 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk; 452 struct phm_acp_clock_voltage_dependency_table *acp_table = 453 hwmgr->dyn_state.acp_clock_voltage_dependency_table; 454 struct phm_uvd_clock_voltage_dependency_table *uvd_table = 455 hwmgr->dyn_state.uvd_clock_voltage_dependency_table; 456 struct phm_vce_clock_voltage_dependency_table *vce_table = 457 hwmgr->dyn_state.vce_clock_voltage_dependency_table; 458 459 if (!hwmgr->need_pp_table_upload) 460 return 0; 461 462 ret = smum_download_powerplay_table(hwmgr, &table); 463 464 PP_ASSERT_WITH_CODE((0 == ret && NULL != table), 465 "Fail to get clock table from SMU!", return -EINVAL;); 466 467 clock_table = (struct SMU8_Fusion_ClkTable *)table; 468 469 /* patch clock table */ 470 PP_ASSERT_WITH_CODE((vddc_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), 471 "Dependency table entry exceeds max limit!", return -EINVAL;); 472 PP_ASSERT_WITH_CODE((vdd_gfx_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), 473 "Dependency table entry exceeds max limit!", return -EINVAL;); 474 PP_ASSERT_WITH_CODE((acp_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), 475 "Dependency table entry exceeds max limit!", return -EINVAL;); 476 PP_ASSERT_WITH_CODE((uvd_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), 477 "Dependency table entry exceeds max limit!", return -EINVAL;); 478 PP_ASSERT_WITH_CODE((vce_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), 479 "Dependency table entry exceeds max limit!", return -EINVAL;); 480 481 for (i = 0; i < SMU8_MAX_HARDWARE_POWERLEVELS; i++) { 482 483 /* vddc_sclk */ 484 clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid = 485 (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0; 486 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency = 487 (i < vddc_table->count) ? vddc_table->entries[i].clk : 0; 488 489 atomctrl_get_engine_pll_dividers_kong(hwmgr, 490 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency, 491 ÷rs); 492 493 clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid = 494 (uint8_t)dividers.pll_post_divider; 495 496 /* vddgfx_sclk */ 497 clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid = 498 (i < vdd_gfx_table->count) ? (uint8_t)vdd_gfx_table->entries[i].v : 0; 499 500 /* acp breakdown */ 501 clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid = 502 (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0; 503 clock_table->AclkBreakdownTable.ClkLevel[i].Frequency = 504 (i < acp_table->count) ? acp_table->entries[i].acpclk : 0; 505 506 atomctrl_get_engine_pll_dividers_kong(hwmgr, 507 clock_table->AclkBreakdownTable.ClkLevel[i].Frequency, 508 ÷rs); 509 510 clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid = 511 (uint8_t)dividers.pll_post_divider; 512 513 514 /* uvd breakdown */ 515 clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid = 516 (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; 517 clock_table->VclkBreakdownTable.ClkLevel[i].Frequency = 518 (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0; 519 520 atomctrl_get_engine_pll_dividers_kong(hwmgr, 521 clock_table->VclkBreakdownTable.ClkLevel[i].Frequency, 522 ÷rs); 523 524 clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid = 525 (uint8_t)dividers.pll_post_divider; 526 527 clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid = 528 (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; 529 clock_table->DclkBreakdownTable.ClkLevel[i].Frequency = 530 (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0; 531 532 atomctrl_get_engine_pll_dividers_kong(hwmgr, 533 clock_table->DclkBreakdownTable.ClkLevel[i].Frequency, 534 ÷rs); 535 536 clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid = 537 (uint8_t)dividers.pll_post_divider; 538 539 /* vce breakdown */ 540 clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid = 541 (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0; 542 clock_table->EclkBreakdownTable.ClkLevel[i].Frequency = 543 (i < vce_table->count) ? vce_table->entries[i].ecclk : 0; 544 545 546 atomctrl_get_engine_pll_dividers_kong(hwmgr, 547 clock_table->EclkBreakdownTable.ClkLevel[i].Frequency, 548 ÷rs); 549 550 clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid = 551 (uint8_t)dividers.pll_post_divider; 552 553 } 554 ret = smum_upload_powerplay_table(hwmgr); 555 556 return ret; 557 } 558 559 static int smu8_init_sclk_limit(struct pp_hwmgr *hwmgr) 560 { 561 struct smu8_hwmgr *data = hwmgr->backend; 562 struct phm_clock_voltage_dependency_table *table = 563 hwmgr->dyn_state.vddc_dependency_on_sclk; 564 unsigned long clock = 0, level; 565 566 if (NULL == table || table->count <= 0) 567 return -EINVAL; 568 569 data->sclk_dpm.soft_min_clk = table->entries[0].clk; 570 data->sclk_dpm.hard_min_clk = table->entries[0].clk; 571 572 level = smu8_get_max_sclk_level(hwmgr) - 1; 573 574 if (level < table->count) 575 clock = table->entries[level].clk; 576 else 577 clock = table->entries[table->count - 1].clk; 578 579 data->sclk_dpm.soft_max_clk = clock; 580 data->sclk_dpm.hard_max_clk = clock; 581 582 return 0; 583 } 584 585 static int smu8_init_uvd_limit(struct pp_hwmgr *hwmgr) 586 { 587 struct smu8_hwmgr *data = hwmgr->backend; 588 struct phm_uvd_clock_voltage_dependency_table *table = 589 hwmgr->dyn_state.uvd_clock_voltage_dependency_table; 590 unsigned long clock = 0, level; 591 592 if (NULL == table || table->count <= 0) 593 return -EINVAL; 594 595 data->uvd_dpm.soft_min_clk = 0; 596 data->uvd_dpm.hard_min_clk = 0; 597 598 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxUvdLevel); 599 level = smum_get_argument(hwmgr); 600 601 if (level < table->count) 602 clock = table->entries[level].vclk; 603 else 604 clock = table->entries[table->count - 1].vclk; 605 606 data->uvd_dpm.soft_max_clk = clock; 607 data->uvd_dpm.hard_max_clk = clock; 608 609 return 0; 610 } 611 612 static int smu8_init_vce_limit(struct pp_hwmgr *hwmgr) 613 { 614 struct smu8_hwmgr *data = hwmgr->backend; 615 struct phm_vce_clock_voltage_dependency_table *table = 616 hwmgr->dyn_state.vce_clock_voltage_dependency_table; 617 unsigned long clock = 0, level; 618 619 if (NULL == table || table->count <= 0) 620 return -EINVAL; 621 622 data->vce_dpm.soft_min_clk = 0; 623 data->vce_dpm.hard_min_clk = 0; 624 625 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxEclkLevel); 626 level = smum_get_argument(hwmgr); 627 628 if (level < table->count) 629 clock = table->entries[level].ecclk; 630 else 631 clock = table->entries[table->count - 1].ecclk; 632 633 data->vce_dpm.soft_max_clk = clock; 634 data->vce_dpm.hard_max_clk = clock; 635 636 return 0; 637 } 638 639 static int smu8_init_acp_limit(struct pp_hwmgr *hwmgr) 640 { 641 struct smu8_hwmgr *data = hwmgr->backend; 642 struct phm_acp_clock_voltage_dependency_table *table = 643 hwmgr->dyn_state.acp_clock_voltage_dependency_table; 644 unsigned long clock = 0, level; 645 646 if (NULL == table || table->count <= 0) 647 return -EINVAL; 648 649 data->acp_dpm.soft_min_clk = 0; 650 data->acp_dpm.hard_min_clk = 0; 651 652 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxAclkLevel); 653 level = smum_get_argument(hwmgr); 654 655 if (level < table->count) 656 clock = table->entries[level].acpclk; 657 else 658 clock = table->entries[table->count - 1].acpclk; 659 660 data->acp_dpm.soft_max_clk = clock; 661 data->acp_dpm.hard_max_clk = clock; 662 return 0; 663 } 664 665 static void smu8_init_power_gate_state(struct pp_hwmgr *hwmgr) 666 { 667 struct smu8_hwmgr *data = hwmgr->backend; 668 669 data->uvd_power_gated = false; 670 data->vce_power_gated = false; 671 data->samu_power_gated = false; 672 #ifdef CONFIG_DRM_AMD_ACP 673 data->acp_power_gated = false; 674 #else 675 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerOFF); 676 data->acp_power_gated = true; 677 #endif 678 679 } 680 681 static void smu8_init_sclk_threshold(struct pp_hwmgr *hwmgr) 682 { 683 struct smu8_hwmgr *data = hwmgr->backend; 684 685 data->low_sclk_interrupt_threshold = 0; 686 } 687 688 static int smu8_update_sclk_limit(struct pp_hwmgr *hwmgr) 689 { 690 struct smu8_hwmgr *data = hwmgr->backend; 691 struct phm_clock_voltage_dependency_table *table = 692 hwmgr->dyn_state.vddc_dependency_on_sclk; 693 694 unsigned long clock = 0; 695 unsigned long level; 696 unsigned long stable_pstate_sclk; 697 unsigned long percentage; 698 699 data->sclk_dpm.soft_min_clk = table->entries[0].clk; 700 level = smu8_get_max_sclk_level(hwmgr) - 1; 701 702 if (level < table->count) 703 data->sclk_dpm.soft_max_clk = table->entries[level].clk; 704 else 705 data->sclk_dpm.soft_max_clk = table->entries[table->count - 1].clk; 706 707 clock = hwmgr->display_config->min_core_set_clock; 708 if (clock == 0) 709 pr_debug("min_core_set_clock not set\n"); 710 711 if (data->sclk_dpm.hard_min_clk != clock) { 712 data->sclk_dpm.hard_min_clk = clock; 713 714 smum_send_msg_to_smc_with_parameter(hwmgr, 715 PPSMC_MSG_SetSclkHardMin, 716 smu8_get_sclk_level(hwmgr, 717 data->sclk_dpm.hard_min_clk, 718 PPSMC_MSG_SetSclkHardMin)); 719 } 720 721 clock = data->sclk_dpm.soft_min_clk; 722 723 /* update minimum clocks for Stable P-State feature */ 724 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 725 PHM_PlatformCaps_StablePState)) { 726 percentage = 75; 727 /*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table */ 728 stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk * 729 percentage) / 100; 730 731 if (clock < stable_pstate_sclk) 732 clock = stable_pstate_sclk; 733 } 734 735 if (data->sclk_dpm.soft_min_clk != clock) { 736 data->sclk_dpm.soft_min_clk = clock; 737 smum_send_msg_to_smc_with_parameter(hwmgr, 738 PPSMC_MSG_SetSclkSoftMin, 739 smu8_get_sclk_level(hwmgr, 740 data->sclk_dpm.soft_min_clk, 741 PPSMC_MSG_SetSclkSoftMin)); 742 } 743 744 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 745 PHM_PlatformCaps_StablePState) && 746 data->sclk_dpm.soft_max_clk != clock) { 747 data->sclk_dpm.soft_max_clk = clock; 748 smum_send_msg_to_smc_with_parameter(hwmgr, 749 PPSMC_MSG_SetSclkSoftMax, 750 smu8_get_sclk_level(hwmgr, 751 data->sclk_dpm.soft_max_clk, 752 PPSMC_MSG_SetSclkSoftMax)); 753 } 754 755 return 0; 756 } 757 758 static int smu8_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr) 759 { 760 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 761 PHM_PlatformCaps_SclkDeepSleep)) { 762 uint32_t clks = hwmgr->display_config->min_core_set_clock_in_sr; 763 if (clks == 0) 764 clks = SMU8_MIN_DEEP_SLEEP_SCLK; 765 766 PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks); 767 768 smum_send_msg_to_smc_with_parameter(hwmgr, 769 PPSMC_MSG_SetMinDeepSleepSclk, 770 clks); 771 } 772 773 return 0; 774 } 775 776 static int smu8_set_watermark_threshold(struct pp_hwmgr *hwmgr) 777 { 778 struct smu8_hwmgr *data = 779 hwmgr->backend; 780 781 smum_send_msg_to_smc_with_parameter(hwmgr, 782 PPSMC_MSG_SetWatermarkFrequency, 783 data->sclk_dpm.soft_max_clk); 784 785 return 0; 786 } 787 788 static int smu8_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock) 789 { 790 struct smu8_hwmgr *hw_data = hwmgr->backend; 791 792 if (hw_data->is_nb_dpm_enabled) { 793 if (enable) { 794 PP_DBG_LOG("enable Low Memory PState.\n"); 795 796 return smum_send_msg_to_smc_with_parameter(hwmgr, 797 PPSMC_MSG_EnableLowMemoryPstate, 798 (lock ? 1 : 0)); 799 } else { 800 PP_DBG_LOG("disable Low Memory PState.\n"); 801 802 return smum_send_msg_to_smc_with_parameter(hwmgr, 803 PPSMC_MSG_DisableLowMemoryPstate, 804 (lock ? 1 : 0)); 805 } 806 } 807 808 return 0; 809 } 810 811 static int smu8_disable_nb_dpm(struct pp_hwmgr *hwmgr) 812 { 813 int ret = 0; 814 815 struct smu8_hwmgr *data = hwmgr->backend; 816 unsigned long dpm_features = 0; 817 818 if (data->is_nb_dpm_enabled) { 819 smu8_nbdpm_pstate_enable_disable(hwmgr, true, true); 820 dpm_features |= NB_DPM_MASK; 821 ret = smum_send_msg_to_smc_with_parameter( 822 hwmgr, 823 PPSMC_MSG_DisableAllSmuFeatures, 824 dpm_features); 825 if (ret == 0) 826 data->is_nb_dpm_enabled = false; 827 } 828 829 return ret; 830 } 831 832 static int smu8_enable_nb_dpm(struct pp_hwmgr *hwmgr) 833 { 834 int ret = 0; 835 836 struct smu8_hwmgr *data = hwmgr->backend; 837 unsigned long dpm_features = 0; 838 839 if (!data->is_nb_dpm_enabled) { 840 PP_DBG_LOG("enabling ALL SMU features.\n"); 841 dpm_features |= NB_DPM_MASK; 842 ret = smum_send_msg_to_smc_with_parameter( 843 hwmgr, 844 PPSMC_MSG_EnableAllSmuFeatures, 845 dpm_features); 846 if (ret == 0) 847 data->is_nb_dpm_enabled = true; 848 } 849 850 return ret; 851 } 852 853 static int smu8_update_low_mem_pstate(struct pp_hwmgr *hwmgr, const void *input) 854 { 855 bool disable_switch; 856 bool enable_low_mem_state; 857 struct smu8_hwmgr *hw_data = hwmgr->backend; 858 const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; 859 const struct smu8_power_state *pnew_state = cast_const_smu8_power_state(states->pnew_state); 860 861 if (hw_data->sys_info.nb_dpm_enable) { 862 disable_switch = hw_data->cc6_settings.nb_pstate_switch_disable ? true : false; 863 enable_low_mem_state = hw_data->cc6_settings.nb_pstate_switch_disable ? false : true; 864 865 if (pnew_state->action == FORCE_HIGH) 866 smu8_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch); 867 else if (pnew_state->action == CANCEL_FORCE_HIGH) 868 smu8_nbdpm_pstate_enable_disable(hwmgr, true, disable_switch); 869 else 870 smu8_nbdpm_pstate_enable_disable(hwmgr, enable_low_mem_state, disable_switch); 871 } 872 return 0; 873 } 874 875 static int smu8_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) 876 { 877 int ret = 0; 878 879 smu8_update_sclk_limit(hwmgr); 880 smu8_set_deep_sleep_sclk_threshold(hwmgr); 881 smu8_set_watermark_threshold(hwmgr); 882 ret = smu8_enable_nb_dpm(hwmgr); 883 if (ret) 884 return ret; 885 smu8_update_low_mem_pstate(hwmgr, input); 886 887 return 0; 888 } 889 890 891 static int smu8_setup_asic_task(struct pp_hwmgr *hwmgr) 892 { 893 int ret; 894 895 ret = smu8_upload_pptable_to_smu(hwmgr); 896 if (ret) 897 return ret; 898 ret = smu8_init_sclk_limit(hwmgr); 899 if (ret) 900 return ret; 901 ret = smu8_init_uvd_limit(hwmgr); 902 if (ret) 903 return ret; 904 ret = smu8_init_vce_limit(hwmgr); 905 if (ret) 906 return ret; 907 ret = smu8_init_acp_limit(hwmgr); 908 if (ret) 909 return ret; 910 911 smu8_init_power_gate_state(hwmgr); 912 smu8_init_sclk_threshold(hwmgr); 913 914 return 0; 915 } 916 917 static void smu8_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr) 918 { 919 struct smu8_hwmgr *hw_data = hwmgr->backend; 920 921 hw_data->disp_clk_bypass_pending = false; 922 hw_data->disp_clk_bypass = false; 923 } 924 925 static void smu8_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr) 926 { 927 struct smu8_hwmgr *hw_data = hwmgr->backend; 928 929 hw_data->is_nb_dpm_enabled = false; 930 } 931 932 static void smu8_reset_cc6_data(struct pp_hwmgr *hwmgr) 933 { 934 struct smu8_hwmgr *hw_data = hwmgr->backend; 935 936 hw_data->cc6_settings.cc6_setting_changed = false; 937 hw_data->cc6_settings.cpu_pstate_separation_time = 0; 938 hw_data->cc6_settings.cpu_cc6_disable = false; 939 hw_data->cc6_settings.cpu_pstate_disable = false; 940 } 941 942 static void smu8_program_voting_clients(struct pp_hwmgr *hwmgr) 943 { 944 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 945 ixCG_FREQ_TRAN_VOTING_0, 946 SMU8_VOTINGRIGHTSCLIENTS_DFLT0); 947 } 948 949 static void smu8_clear_voting_clients(struct pp_hwmgr *hwmgr) 950 { 951 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 952 ixCG_FREQ_TRAN_VOTING_0, 0); 953 } 954 955 static int smu8_start_dpm(struct pp_hwmgr *hwmgr) 956 { 957 struct smu8_hwmgr *data = hwmgr->backend; 958 959 data->dpm_flags |= DPMFlags_SCLK_Enabled; 960 961 return smum_send_msg_to_smc_with_parameter(hwmgr, 962 PPSMC_MSG_EnableAllSmuFeatures, 963 SCLK_DPM_MASK); 964 } 965 966 static int smu8_stop_dpm(struct pp_hwmgr *hwmgr) 967 { 968 int ret = 0; 969 struct smu8_hwmgr *data = hwmgr->backend; 970 unsigned long dpm_features = 0; 971 972 if (data->dpm_flags & DPMFlags_SCLK_Enabled) { 973 dpm_features |= SCLK_DPM_MASK; 974 data->dpm_flags &= ~DPMFlags_SCLK_Enabled; 975 ret = smum_send_msg_to_smc_with_parameter(hwmgr, 976 PPSMC_MSG_DisableAllSmuFeatures, 977 dpm_features); 978 } 979 return ret; 980 } 981 982 static int smu8_program_bootup_state(struct pp_hwmgr *hwmgr) 983 { 984 struct smu8_hwmgr *data = hwmgr->backend; 985 986 data->sclk_dpm.soft_min_clk = data->sys_info.bootup_engine_clock; 987 data->sclk_dpm.soft_max_clk = data->sys_info.bootup_engine_clock; 988 989 smum_send_msg_to_smc_with_parameter(hwmgr, 990 PPSMC_MSG_SetSclkSoftMin, 991 smu8_get_sclk_level(hwmgr, 992 data->sclk_dpm.soft_min_clk, 993 PPSMC_MSG_SetSclkSoftMin)); 994 995 smum_send_msg_to_smc_with_parameter(hwmgr, 996 PPSMC_MSG_SetSclkSoftMax, 997 smu8_get_sclk_level(hwmgr, 998 data->sclk_dpm.soft_max_clk, 999 PPSMC_MSG_SetSclkSoftMax)); 1000 1001 return 0; 1002 } 1003 1004 static void smu8_reset_acp_boot_level(struct pp_hwmgr *hwmgr) 1005 { 1006 struct smu8_hwmgr *data = hwmgr->backend; 1007 1008 data->acp_boot_level = 0xff; 1009 } 1010 1011 static int smu8_enable_dpm_tasks(struct pp_hwmgr *hwmgr) 1012 { 1013 smu8_program_voting_clients(hwmgr); 1014 if (smu8_start_dpm(hwmgr)) 1015 return -EINVAL; 1016 smu8_program_bootup_state(hwmgr); 1017 smu8_reset_acp_boot_level(hwmgr); 1018 1019 return 0; 1020 } 1021 1022 static int smu8_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 1023 { 1024 smu8_disable_nb_dpm(hwmgr); 1025 1026 smu8_clear_voting_clients(hwmgr); 1027 if (smu8_stop_dpm(hwmgr)) 1028 return -EINVAL; 1029 1030 return 0; 1031 } 1032 1033 static int smu8_power_off_asic(struct pp_hwmgr *hwmgr) 1034 { 1035 smu8_disable_dpm_tasks(hwmgr); 1036 smu8_power_up_display_clock_sys_pll(hwmgr); 1037 smu8_clear_nb_dpm_flag(hwmgr); 1038 smu8_reset_cc6_data(hwmgr); 1039 return 0; 1040 } 1041 1042 static int smu8_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, 1043 struct pp_power_state *prequest_ps, 1044 const struct pp_power_state *pcurrent_ps) 1045 { 1046 struct smu8_power_state *smu8_ps = 1047 cast_smu8_power_state(&prequest_ps->hardware); 1048 1049 const struct smu8_power_state *smu8_current_ps = 1050 cast_const_smu8_power_state(&pcurrent_ps->hardware); 1051 1052 struct smu8_hwmgr *data = hwmgr->backend; 1053 struct PP_Clocks clocks = {0, 0, 0, 0}; 1054 bool force_high; 1055 1056 smu8_ps->need_dfs_bypass = true; 1057 1058 data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label); 1059 1060 clocks.memoryClock = hwmgr->display_config->min_mem_set_clock != 0 ? 1061 hwmgr->display_config->min_mem_set_clock : 1062 data->sys_info.nbp_memory_clock[1]; 1063 1064 1065 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) 1066 clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk; 1067 1068 force_high = (clocks.memoryClock > data->sys_info.nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK - 1]) 1069 || (hwmgr->display_config->num_display >= 3); 1070 1071 smu8_ps->action = smu8_current_ps->action; 1072 1073 if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 1074 smu8_nbdpm_pstate_enable_disable(hwmgr, false, false); 1075 else if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) 1076 smu8_nbdpm_pstate_enable_disable(hwmgr, false, true); 1077 else if (!force_high && (smu8_ps->action == FORCE_HIGH)) 1078 smu8_ps->action = CANCEL_FORCE_HIGH; 1079 else if (force_high && (smu8_ps->action != FORCE_HIGH)) 1080 smu8_ps->action = FORCE_HIGH; 1081 else 1082 smu8_ps->action = DO_NOTHING; 1083 1084 return 0; 1085 } 1086 1087 static int smu8_hwmgr_backend_init(struct pp_hwmgr *hwmgr) 1088 { 1089 int result = 0; 1090 struct smu8_hwmgr *data; 1091 1092 data = kzalloc(sizeof(struct smu8_hwmgr), GFP_KERNEL); 1093 if (data == NULL) 1094 return -ENOMEM; 1095 1096 hwmgr->backend = data; 1097 1098 result = smu8_initialize_dpm_defaults(hwmgr); 1099 if (result != 0) { 1100 pr_err("smu8_initialize_dpm_defaults failed\n"); 1101 return result; 1102 } 1103 1104 result = smu8_get_system_info_data(hwmgr); 1105 if (result != 0) { 1106 pr_err("smu8_get_system_info_data failed\n"); 1107 return result; 1108 } 1109 1110 smu8_construct_boot_state(hwmgr); 1111 1112 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = SMU8_MAX_HARDWARE_POWERLEVELS; 1113 1114 return result; 1115 } 1116 1117 static int smu8_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) 1118 { 1119 if (hwmgr != NULL) { 1120 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); 1121 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; 1122 1123 kfree(hwmgr->backend); 1124 hwmgr->backend = NULL; 1125 } 1126 return 0; 1127 } 1128 1129 static int smu8_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) 1130 { 1131 struct smu8_hwmgr *data = hwmgr->backend; 1132 1133 smum_send_msg_to_smc_with_parameter(hwmgr, 1134 PPSMC_MSG_SetSclkSoftMin, 1135 smu8_get_sclk_level(hwmgr, 1136 data->sclk_dpm.soft_max_clk, 1137 PPSMC_MSG_SetSclkSoftMin)); 1138 1139 smum_send_msg_to_smc_with_parameter(hwmgr, 1140 PPSMC_MSG_SetSclkSoftMax, 1141 smu8_get_sclk_level(hwmgr, 1142 data->sclk_dpm.soft_max_clk, 1143 PPSMC_MSG_SetSclkSoftMax)); 1144 1145 return 0; 1146 } 1147 1148 static int smu8_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) 1149 { 1150 struct smu8_hwmgr *data = hwmgr->backend; 1151 struct phm_clock_voltage_dependency_table *table = 1152 hwmgr->dyn_state.vddc_dependency_on_sclk; 1153 unsigned long clock = 0, level; 1154 1155 if (NULL == table || table->count <= 0) 1156 return -EINVAL; 1157 1158 data->sclk_dpm.soft_min_clk = table->entries[0].clk; 1159 data->sclk_dpm.hard_min_clk = table->entries[0].clk; 1160 hwmgr->pstate_sclk = table->entries[0].clk; 1161 hwmgr->pstate_mclk = 0; 1162 1163 level = smu8_get_max_sclk_level(hwmgr) - 1; 1164 1165 if (level < table->count) 1166 clock = table->entries[level].clk; 1167 else 1168 clock = table->entries[table->count - 1].clk; 1169 1170 data->sclk_dpm.soft_max_clk = clock; 1171 data->sclk_dpm.hard_max_clk = clock; 1172 1173 smum_send_msg_to_smc_with_parameter(hwmgr, 1174 PPSMC_MSG_SetSclkSoftMin, 1175 smu8_get_sclk_level(hwmgr, 1176 data->sclk_dpm.soft_min_clk, 1177 PPSMC_MSG_SetSclkSoftMin)); 1178 1179 smum_send_msg_to_smc_with_parameter(hwmgr, 1180 PPSMC_MSG_SetSclkSoftMax, 1181 smu8_get_sclk_level(hwmgr, 1182 data->sclk_dpm.soft_max_clk, 1183 PPSMC_MSG_SetSclkSoftMax)); 1184 1185 return 0; 1186 } 1187 1188 static int smu8_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) 1189 { 1190 struct smu8_hwmgr *data = hwmgr->backend; 1191 1192 smum_send_msg_to_smc_with_parameter(hwmgr, 1193 PPSMC_MSG_SetSclkSoftMax, 1194 smu8_get_sclk_level(hwmgr, 1195 data->sclk_dpm.soft_min_clk, 1196 PPSMC_MSG_SetSclkSoftMax)); 1197 1198 smum_send_msg_to_smc_with_parameter(hwmgr, 1199 PPSMC_MSG_SetSclkSoftMin, 1200 smu8_get_sclk_level(hwmgr, 1201 data->sclk_dpm.soft_min_clk, 1202 PPSMC_MSG_SetSclkSoftMin)); 1203 1204 return 0; 1205 } 1206 1207 static int smu8_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, 1208 enum amd_dpm_forced_level level) 1209 { 1210 int ret = 0; 1211 1212 switch (level) { 1213 case AMD_DPM_FORCED_LEVEL_HIGH: 1214 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 1215 ret = smu8_phm_force_dpm_highest(hwmgr); 1216 break; 1217 case AMD_DPM_FORCED_LEVEL_LOW: 1218 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 1219 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 1220 ret = smu8_phm_force_dpm_lowest(hwmgr); 1221 break; 1222 case AMD_DPM_FORCED_LEVEL_AUTO: 1223 ret = smu8_phm_unforce_dpm_levels(hwmgr); 1224 break; 1225 case AMD_DPM_FORCED_LEVEL_MANUAL: 1226 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 1227 default: 1228 break; 1229 } 1230 1231 return ret; 1232 } 1233 1234 static int smu8_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) 1235 { 1236 if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) 1237 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF); 1238 return 0; 1239 } 1240 1241 static int smu8_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) 1242 { 1243 if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) { 1244 return smum_send_msg_to_smc_with_parameter( 1245 hwmgr, 1246 PPSMC_MSG_UVDPowerON, 1247 PP_CAP(PHM_PlatformCaps_UVDDynamicPowerGating) ? 1 : 0); 1248 } 1249 1250 return 0; 1251 } 1252 1253 static int smu8_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) 1254 { 1255 struct smu8_hwmgr *data = hwmgr->backend; 1256 struct phm_vce_clock_voltage_dependency_table *ptable = 1257 hwmgr->dyn_state.vce_clock_voltage_dependency_table; 1258 1259 /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ 1260 if (PP_CAP(PHM_PlatformCaps_StablePState) || 1261 hwmgr->en_umd_pstate) { 1262 data->vce_dpm.hard_min_clk = 1263 ptable->entries[ptable->count - 1].ecclk; 1264 1265 smum_send_msg_to_smc_with_parameter(hwmgr, 1266 PPSMC_MSG_SetEclkHardMin, 1267 smu8_get_eclk_level(hwmgr, 1268 data->vce_dpm.hard_min_clk, 1269 PPSMC_MSG_SetEclkHardMin)); 1270 } else { 1271 1272 smum_send_msg_to_smc_with_parameter(hwmgr, 1273 PPSMC_MSG_SetEclkHardMin, 0); 1274 /* disable ECLK DPM 0. Otherwise VCE could hang if 1275 * switching SCLK from DPM 0 to 6/7 */ 1276 smum_send_msg_to_smc_with_parameter(hwmgr, 1277 PPSMC_MSG_SetEclkSoftMin, 1); 1278 } 1279 return 0; 1280 } 1281 1282 static int smu8_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) 1283 { 1284 if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) 1285 return smum_send_msg_to_smc(hwmgr, 1286 PPSMC_MSG_VCEPowerOFF); 1287 return 0; 1288 } 1289 1290 static int smu8_dpm_powerup_vce(struct pp_hwmgr *hwmgr) 1291 { 1292 if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) 1293 return smum_send_msg_to_smc(hwmgr, 1294 PPSMC_MSG_VCEPowerON); 1295 return 0; 1296 } 1297 1298 static uint32_t smu8_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 1299 { 1300 struct smu8_hwmgr *data = hwmgr->backend; 1301 1302 return data->sys_info.bootup_uma_clock; 1303 } 1304 1305 static uint32_t smu8_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 1306 { 1307 struct pp_power_state *ps; 1308 struct smu8_power_state *smu8_ps; 1309 1310 if (hwmgr == NULL) 1311 return -EINVAL; 1312 1313 ps = hwmgr->request_ps; 1314 1315 if (ps == NULL) 1316 return -EINVAL; 1317 1318 smu8_ps = cast_smu8_power_state(&ps->hardware); 1319 1320 if (low) 1321 return smu8_ps->levels[0].engineClock; 1322 else 1323 return smu8_ps->levels[smu8_ps->level-1].engineClock; 1324 } 1325 1326 static int smu8_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, 1327 struct pp_hw_power_state *hw_ps) 1328 { 1329 struct smu8_hwmgr *data = hwmgr->backend; 1330 struct smu8_power_state *smu8_ps = cast_smu8_power_state(hw_ps); 1331 1332 smu8_ps->level = 1; 1333 smu8_ps->nbps_flags = 0; 1334 smu8_ps->bapm_flags = 0; 1335 smu8_ps->levels[0] = data->boot_power_level; 1336 1337 return 0; 1338 } 1339 1340 static int smu8_dpm_get_pp_table_entry_callback( 1341 struct pp_hwmgr *hwmgr, 1342 struct pp_hw_power_state *hw_ps, 1343 unsigned int index, 1344 const void *clock_info) 1345 { 1346 struct smu8_power_state *smu8_ps = cast_smu8_power_state(hw_ps); 1347 1348 const ATOM_PPLIB_CZ_CLOCK_INFO *smu8_clock_info = clock_info; 1349 1350 struct phm_clock_voltage_dependency_table *table = 1351 hwmgr->dyn_state.vddc_dependency_on_sclk; 1352 uint8_t clock_info_index = smu8_clock_info->index; 1353 1354 if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1)) 1355 clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1); 1356 1357 smu8_ps->levels[index].engineClock = table->entries[clock_info_index].clk; 1358 smu8_ps->levels[index].vddcIndex = (uint8_t)table->entries[clock_info_index].v; 1359 1360 smu8_ps->level = index + 1; 1361 1362 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { 1363 smu8_ps->levels[index].dsDividerIndex = 5; 1364 smu8_ps->levels[index].ssDividerIndex = 5; 1365 } 1366 1367 return 0; 1368 } 1369 1370 static int smu8_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) 1371 { 1372 int result; 1373 unsigned long ret = 0; 1374 1375 result = pp_tables_get_num_of_entries(hwmgr, &ret); 1376 1377 return result ? 0 : ret; 1378 } 1379 1380 static int smu8_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, 1381 unsigned long entry, struct pp_power_state *ps) 1382 { 1383 int result; 1384 struct smu8_power_state *smu8_ps; 1385 1386 ps->hardware.magic = smu8_magic; 1387 1388 smu8_ps = cast_smu8_power_state(&(ps->hardware)); 1389 1390 result = pp_tables_get_entry(hwmgr, entry, ps, 1391 smu8_dpm_get_pp_table_entry_callback); 1392 1393 smu8_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; 1394 smu8_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; 1395 1396 return result; 1397 } 1398 1399 static int smu8_get_power_state_size(struct pp_hwmgr *hwmgr) 1400 { 1401 return sizeof(struct smu8_power_state); 1402 } 1403 1404 static void smu8_hw_print_display_cfg( 1405 const struct cc6_settings *cc6_settings) 1406 { 1407 PP_DBG_LOG("New Display Configuration:\n"); 1408 1409 PP_DBG_LOG(" cpu_cc6_disable: %d\n", 1410 cc6_settings->cpu_cc6_disable); 1411 PP_DBG_LOG(" cpu_pstate_disable: %d\n", 1412 cc6_settings->cpu_pstate_disable); 1413 PP_DBG_LOG(" nb_pstate_switch_disable: %d\n", 1414 cc6_settings->nb_pstate_switch_disable); 1415 PP_DBG_LOG(" cpu_pstate_separation_time: %d\n\n", 1416 cc6_settings->cpu_pstate_separation_time); 1417 } 1418 1419 static int smu8_set_cpu_power_state(struct pp_hwmgr *hwmgr) 1420 { 1421 struct smu8_hwmgr *hw_data = hwmgr->backend; 1422 uint32_t data = 0; 1423 1424 if (hw_data->cc6_settings.cc6_setting_changed) { 1425 1426 hw_data->cc6_settings.cc6_setting_changed = false; 1427 1428 smu8_hw_print_display_cfg(&hw_data->cc6_settings); 1429 1430 data |= (hw_data->cc6_settings.cpu_pstate_separation_time 1431 & PWRMGT_SEPARATION_TIME_MASK) 1432 << PWRMGT_SEPARATION_TIME_SHIFT; 1433 1434 data |= (hw_data->cc6_settings.cpu_cc6_disable ? 0x1 : 0x0) 1435 << PWRMGT_DISABLE_CPU_CSTATES_SHIFT; 1436 1437 data |= (hw_data->cc6_settings.cpu_pstate_disable ? 0x1 : 0x0) 1438 << PWRMGT_DISABLE_CPU_PSTATES_SHIFT; 1439 1440 PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n", 1441 data); 1442 1443 smum_send_msg_to_smc_with_parameter(hwmgr, 1444 PPSMC_MSG_SetDisplaySizePowerParams, 1445 data); 1446 } 1447 1448 return 0; 1449 } 1450 1451 1452 static int smu8_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, 1453 bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) 1454 { 1455 struct smu8_hwmgr *hw_data = hwmgr->backend; 1456 1457 if (separation_time != 1458 hw_data->cc6_settings.cpu_pstate_separation_time || 1459 cc6_disable != hw_data->cc6_settings.cpu_cc6_disable || 1460 pstate_disable != hw_data->cc6_settings.cpu_pstate_disable || 1461 pstate_switch_disable != hw_data->cc6_settings.nb_pstate_switch_disable) { 1462 1463 hw_data->cc6_settings.cc6_setting_changed = true; 1464 1465 hw_data->cc6_settings.cpu_pstate_separation_time = 1466 separation_time; 1467 hw_data->cc6_settings.cpu_cc6_disable = 1468 cc6_disable; 1469 hw_data->cc6_settings.cpu_pstate_disable = 1470 pstate_disable; 1471 hw_data->cc6_settings.nb_pstate_switch_disable = 1472 pstate_switch_disable; 1473 1474 } 1475 1476 return 0; 1477 } 1478 1479 static int smu8_get_dal_power_level(struct pp_hwmgr *hwmgr, 1480 struct amd_pp_simple_clock_info *info) 1481 { 1482 uint32_t i; 1483 const struct phm_clock_voltage_dependency_table *table = 1484 hwmgr->dyn_state.vddc_dep_on_dal_pwrl; 1485 const struct phm_clock_and_voltage_limits *limits = 1486 &hwmgr->dyn_state.max_clock_voltage_on_ac; 1487 1488 info->engine_max_clock = limits->sclk; 1489 info->memory_max_clock = limits->mclk; 1490 1491 for (i = table->count - 1; i > 0; i--) { 1492 if (limits->vddc >= table->entries[i].v) { 1493 info->level = table->entries[i].clk; 1494 return 0; 1495 } 1496 } 1497 return -EINVAL; 1498 } 1499 1500 static int smu8_force_clock_level(struct pp_hwmgr *hwmgr, 1501 enum pp_clock_type type, uint32_t mask) 1502 { 1503 switch (type) { 1504 case PP_SCLK: 1505 smum_send_msg_to_smc_with_parameter(hwmgr, 1506 PPSMC_MSG_SetSclkSoftMin, 1507 mask); 1508 smum_send_msg_to_smc_with_parameter(hwmgr, 1509 PPSMC_MSG_SetSclkSoftMax, 1510 mask); 1511 break; 1512 default: 1513 break; 1514 } 1515 1516 return 0; 1517 } 1518 1519 static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, 1520 enum pp_clock_type type, char *buf) 1521 { 1522 struct smu8_hwmgr *data = hwmgr->backend; 1523 struct phm_clock_voltage_dependency_table *sclk_table = 1524 hwmgr->dyn_state.vddc_dependency_on_sclk; 1525 int i, now, size = 0; 1526 1527 switch (type) { 1528 case PP_SCLK: 1529 now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, 1530 CGS_IND_REG__SMC, 1531 ixTARGET_AND_CURRENT_PROFILE_INDEX), 1532 TARGET_AND_CURRENT_PROFILE_INDEX, 1533 CURR_SCLK_INDEX); 1534 1535 for (i = 0; i < sclk_table->count; i++) 1536 size += sprintf(buf + size, "%d: %uMhz %s\n", 1537 i, sclk_table->entries[i].clk / 100, 1538 (i == now) ? "*" : ""); 1539 break; 1540 case PP_MCLK: 1541 now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, 1542 CGS_IND_REG__SMC, 1543 ixTARGET_AND_CURRENT_PROFILE_INDEX), 1544 TARGET_AND_CURRENT_PROFILE_INDEX, 1545 CURR_MCLK_INDEX); 1546 1547 for (i = SMU8_NUM_NBPMEMORYCLOCK; i > 0; i--) 1548 size += sprintf(buf + size, "%d: %uMhz %s\n", 1549 SMU8_NUM_NBPMEMORYCLOCK-i, data->sys_info.nbp_memory_clock[i-1] / 100, 1550 (SMU8_NUM_NBPMEMORYCLOCK-i == now) ? "*" : ""); 1551 break; 1552 default: 1553 break; 1554 } 1555 return size; 1556 } 1557 1558 static int smu8_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 1559 PHM_PerformanceLevelDesignation designation, uint32_t index, 1560 PHM_PerformanceLevel *level) 1561 { 1562 const struct smu8_power_state *ps; 1563 struct smu8_hwmgr *data; 1564 uint32_t level_index; 1565 uint32_t i; 1566 1567 if (level == NULL || hwmgr == NULL || state == NULL) 1568 return -EINVAL; 1569 1570 data = hwmgr->backend; 1571 ps = cast_const_smu8_power_state(state); 1572 1573 level_index = index > ps->level - 1 ? ps->level - 1 : index; 1574 level->coreClock = ps->levels[level_index].engineClock; 1575 1576 if (designation == PHM_PerformanceLevelDesignation_PowerContainment) { 1577 for (i = 1; i < ps->level; i++) { 1578 if (ps->levels[i].engineClock > data->dce_slow_sclk_threshold) { 1579 level->coreClock = ps->levels[i].engineClock; 1580 break; 1581 } 1582 } 1583 } 1584 1585 if (level_index == 0) 1586 level->memory_clock = data->sys_info.nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK - 1]; 1587 else 1588 level->memory_clock = data->sys_info.nbp_memory_clock[0]; 1589 1590 level->vddc = (smu8_convert_8Bit_index_to_voltage(hwmgr, ps->levels[level_index].vddcIndex) + 2) / 4; 1591 level->nonLocalMemoryFreq = 0; 1592 level->nonLocalMemoryWidth = 0; 1593 1594 return 0; 1595 } 1596 1597 static int smu8_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, 1598 const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) 1599 { 1600 const struct smu8_power_state *ps = cast_const_smu8_power_state(state); 1601 1602 clock_info->min_eng_clk = ps->levels[0].engineClock / (1 << (ps->levels[0].ssDividerIndex)); 1603 clock_info->max_eng_clk = ps->levels[ps->level - 1].engineClock / (1 << (ps->levels[ps->level - 1].ssDividerIndex)); 1604 1605 return 0; 1606 } 1607 1608 static int smu8_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, 1609 struct amd_pp_clocks *clocks) 1610 { 1611 struct smu8_hwmgr *data = hwmgr->backend; 1612 int i; 1613 struct phm_clock_voltage_dependency_table *table; 1614 1615 clocks->count = smu8_get_max_sclk_level(hwmgr); 1616 switch (type) { 1617 case amd_pp_disp_clock: 1618 for (i = 0; i < clocks->count; i++) 1619 clocks->clock[i] = data->sys_info.display_clock[i] * 10; 1620 break; 1621 case amd_pp_sys_clock: 1622 table = hwmgr->dyn_state.vddc_dependency_on_sclk; 1623 for (i = 0; i < clocks->count; i++) 1624 clocks->clock[i] = table->entries[i].clk * 10; 1625 break; 1626 case amd_pp_mem_clock: 1627 clocks->count = SMU8_NUM_NBPMEMORYCLOCK; 1628 for (i = 0; i < clocks->count; i++) 1629 clocks->clock[i] = data->sys_info.nbp_memory_clock[clocks->count - 1 - i] * 10; 1630 break; 1631 default: 1632 return -1; 1633 } 1634 1635 return 0; 1636 } 1637 1638 static int smu8_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) 1639 { 1640 struct phm_clock_voltage_dependency_table *table = 1641 hwmgr->dyn_state.vddc_dependency_on_sclk; 1642 unsigned long level; 1643 const struct phm_clock_and_voltage_limits *limits = 1644 &hwmgr->dyn_state.max_clock_voltage_on_ac; 1645 1646 if ((NULL == table) || (table->count <= 0) || (clocks == NULL)) 1647 return -EINVAL; 1648 1649 level = smu8_get_max_sclk_level(hwmgr) - 1; 1650 1651 if (level < table->count) 1652 clocks->engine_max_clock = table->entries[level].clk; 1653 else 1654 clocks->engine_max_clock = table->entries[table->count - 1].clk; 1655 1656 clocks->memory_max_clock = limits->mclk; 1657 1658 return 0; 1659 } 1660 1661 static int smu8_thermal_get_temperature(struct pp_hwmgr *hwmgr) 1662 { 1663 int actual_temp = 0; 1664 uint32_t val = cgs_read_ind_register(hwmgr->device, 1665 CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP); 1666 uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); 1667 1668 if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL)) 1669 actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 1670 else 1671 actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 1672 1673 return actual_temp; 1674 } 1675 1676 static int smu8_read_sensor(struct pp_hwmgr *hwmgr, int idx, 1677 void *value, int *size) 1678 { 1679 struct smu8_hwmgr *data = hwmgr->backend; 1680 1681 struct phm_clock_voltage_dependency_table *table = 1682 hwmgr->dyn_state.vddc_dependency_on_sclk; 1683 1684 struct phm_vce_clock_voltage_dependency_table *vce_table = 1685 hwmgr->dyn_state.vce_clock_voltage_dependency_table; 1686 1687 struct phm_uvd_clock_voltage_dependency_table *uvd_table = 1688 hwmgr->dyn_state.uvd_clock_voltage_dependency_table; 1689 1690 uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX), 1691 TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); 1692 uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), 1693 TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); 1694 uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), 1695 TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); 1696 1697 uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent; 1698 uint16_t vddnb, vddgfx; 1699 int result; 1700 1701 /* size must be at least 4 bytes for all sensors */ 1702 if (*size < 4) 1703 return -EINVAL; 1704 *size = 4; 1705 1706 switch (idx) { 1707 case AMDGPU_PP_SENSOR_GFX_SCLK: 1708 if (sclk_index < NUM_SCLK_LEVELS) { 1709 sclk = table->entries[sclk_index].clk; 1710 *((uint32_t *)value) = sclk; 1711 return 0; 1712 } 1713 return -EINVAL; 1714 case AMDGPU_PP_SENSOR_VDDNB: 1715 tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & 1716 CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; 1717 vddnb = smu8_convert_8Bit_index_to_voltage(hwmgr, tmp) / 4; 1718 *((uint32_t *)value) = vddnb; 1719 return 0; 1720 case AMDGPU_PP_SENSOR_VDDGFX: 1721 tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & 1722 CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; 1723 vddgfx = smu8_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp) / 4; 1724 *((uint32_t *)value) = vddgfx; 1725 return 0; 1726 case AMDGPU_PP_SENSOR_UVD_VCLK: 1727 if (!data->uvd_power_gated) { 1728 if (uvd_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { 1729 return -EINVAL; 1730 } else { 1731 vclk = uvd_table->entries[uvd_index].vclk; 1732 *((uint32_t *)value) = vclk; 1733 return 0; 1734 } 1735 } 1736 *((uint32_t *)value) = 0; 1737 return 0; 1738 case AMDGPU_PP_SENSOR_UVD_DCLK: 1739 if (!data->uvd_power_gated) { 1740 if (uvd_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { 1741 return -EINVAL; 1742 } else { 1743 dclk = uvd_table->entries[uvd_index].dclk; 1744 *((uint32_t *)value) = dclk; 1745 return 0; 1746 } 1747 } 1748 *((uint32_t *)value) = 0; 1749 return 0; 1750 case AMDGPU_PP_SENSOR_VCE_ECCLK: 1751 if (!data->vce_power_gated) { 1752 if (vce_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { 1753 return -EINVAL; 1754 } else { 1755 ecclk = vce_table->entries[vce_index].ecclk; 1756 *((uint32_t *)value) = ecclk; 1757 return 0; 1758 } 1759 } 1760 *((uint32_t *)value) = 0; 1761 return 0; 1762 case AMDGPU_PP_SENSOR_GPU_LOAD: 1763 result = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGraphicsActivity); 1764 if (0 == result) { 1765 activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); 1766 activity_percent = activity_percent > 100 ? 100 : activity_percent; 1767 } else { 1768 activity_percent = 50; 1769 } 1770 *((uint32_t *)value) = activity_percent; 1771 return 0; 1772 case AMDGPU_PP_SENSOR_UVD_POWER: 1773 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; 1774 return 0; 1775 case AMDGPU_PP_SENSOR_VCE_POWER: 1776 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; 1777 return 0; 1778 case AMDGPU_PP_SENSOR_GPU_TEMP: 1779 *((uint32_t *)value) = smu8_thermal_get_temperature(hwmgr); 1780 return 0; 1781 default: 1782 return -EINVAL; 1783 } 1784 } 1785 1786 static int smu8_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, 1787 uint32_t virtual_addr_low, 1788 uint32_t virtual_addr_hi, 1789 uint32_t mc_addr_low, 1790 uint32_t mc_addr_hi, 1791 uint32_t size) 1792 { 1793 smum_send_msg_to_smc_with_parameter(hwmgr, 1794 PPSMC_MSG_DramAddrHiVirtual, 1795 mc_addr_hi); 1796 smum_send_msg_to_smc_with_parameter(hwmgr, 1797 PPSMC_MSG_DramAddrLoVirtual, 1798 mc_addr_low); 1799 smum_send_msg_to_smc_with_parameter(hwmgr, 1800 PPSMC_MSG_DramAddrHiPhysical, 1801 virtual_addr_hi); 1802 smum_send_msg_to_smc_with_parameter(hwmgr, 1803 PPSMC_MSG_DramAddrLoPhysical, 1804 virtual_addr_low); 1805 1806 smum_send_msg_to_smc_with_parameter(hwmgr, 1807 PPSMC_MSG_DramBufferSize, 1808 size); 1809 return 0; 1810 } 1811 1812 static int smu8_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, 1813 struct PP_TemperatureRange *thermal_data) 1814 { 1815 struct smu8_hwmgr *data = hwmgr->backend; 1816 1817 memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange)); 1818 1819 thermal_data->max = (data->thermal_auto_throttling_treshold + 1820 data->sys_info.htc_hyst_lmt) * 1821 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 1822 1823 return 0; 1824 } 1825 1826 static int smu8_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) 1827 { 1828 struct smu8_hwmgr *data = hwmgr->backend; 1829 uint32_t dpm_features = 0; 1830 1831 if (enable && 1832 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1833 PHM_PlatformCaps_UVDDPM)) { 1834 data->dpm_flags |= DPMFlags_UVD_Enabled; 1835 dpm_features |= UVD_DPM_MASK; 1836 smum_send_msg_to_smc_with_parameter(hwmgr, 1837 PPSMC_MSG_EnableAllSmuFeatures, dpm_features); 1838 } else { 1839 dpm_features |= UVD_DPM_MASK; 1840 data->dpm_flags &= ~DPMFlags_UVD_Enabled; 1841 smum_send_msg_to_smc_with_parameter(hwmgr, 1842 PPSMC_MSG_DisableAllSmuFeatures, dpm_features); 1843 } 1844 return 0; 1845 } 1846 1847 int smu8_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) 1848 { 1849 struct smu8_hwmgr *data = hwmgr->backend; 1850 struct phm_uvd_clock_voltage_dependency_table *ptable = 1851 hwmgr->dyn_state.uvd_clock_voltage_dependency_table; 1852 1853 if (!bgate) { 1854 /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */ 1855 if (PP_CAP(PHM_PlatformCaps_StablePState) || 1856 hwmgr->en_umd_pstate) { 1857 data->uvd_dpm.hard_min_clk = 1858 ptable->entries[ptable->count - 1].vclk; 1859 1860 smum_send_msg_to_smc_with_parameter(hwmgr, 1861 PPSMC_MSG_SetUvdHardMin, 1862 smu8_get_uvd_level(hwmgr, 1863 data->uvd_dpm.hard_min_clk, 1864 PPSMC_MSG_SetUvdHardMin)); 1865 1866 smu8_enable_disable_uvd_dpm(hwmgr, true); 1867 } else { 1868 smu8_enable_disable_uvd_dpm(hwmgr, true); 1869 } 1870 } else { 1871 smu8_enable_disable_uvd_dpm(hwmgr, false); 1872 } 1873 1874 return 0; 1875 } 1876 1877 static int smu8_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) 1878 { 1879 struct smu8_hwmgr *data = hwmgr->backend; 1880 uint32_t dpm_features = 0; 1881 1882 if (enable && phm_cap_enabled( 1883 hwmgr->platform_descriptor.platformCaps, 1884 PHM_PlatformCaps_VCEDPM)) { 1885 data->dpm_flags |= DPMFlags_VCE_Enabled; 1886 dpm_features |= VCE_DPM_MASK; 1887 smum_send_msg_to_smc_with_parameter(hwmgr, 1888 PPSMC_MSG_EnableAllSmuFeatures, dpm_features); 1889 } else { 1890 dpm_features |= VCE_DPM_MASK; 1891 data->dpm_flags &= ~DPMFlags_VCE_Enabled; 1892 smum_send_msg_to_smc_with_parameter(hwmgr, 1893 PPSMC_MSG_DisableAllSmuFeatures, dpm_features); 1894 } 1895 1896 return 0; 1897 } 1898 1899 1900 static void smu8_dpm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate) 1901 { 1902 struct smu8_hwmgr *data = hwmgr->backend; 1903 1904 if (data->acp_power_gated == bgate) 1905 return; 1906 1907 if (bgate) 1908 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerOFF); 1909 else 1910 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerON); 1911 } 1912 1913 static void smu8_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) 1914 { 1915 struct smu8_hwmgr *data = hwmgr->backend; 1916 1917 data->uvd_power_gated = bgate; 1918 1919 if (bgate) { 1920 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 1921 AMD_IP_BLOCK_TYPE_UVD, 1922 AMD_PG_STATE_GATE); 1923 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 1924 AMD_IP_BLOCK_TYPE_UVD, 1925 AMD_CG_STATE_GATE); 1926 smu8_dpm_update_uvd_dpm(hwmgr, true); 1927 smu8_dpm_powerdown_uvd(hwmgr); 1928 } else { 1929 smu8_dpm_powerup_uvd(hwmgr); 1930 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 1931 AMD_IP_BLOCK_TYPE_UVD, 1932 AMD_CG_STATE_UNGATE); 1933 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 1934 AMD_IP_BLOCK_TYPE_UVD, 1935 AMD_PG_STATE_UNGATE); 1936 smu8_dpm_update_uvd_dpm(hwmgr, false); 1937 } 1938 1939 } 1940 1941 static void smu8_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) 1942 { 1943 struct smu8_hwmgr *data = hwmgr->backend; 1944 1945 if (bgate) { 1946 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 1947 AMD_IP_BLOCK_TYPE_VCE, 1948 AMD_PG_STATE_GATE); 1949 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 1950 AMD_IP_BLOCK_TYPE_VCE, 1951 AMD_CG_STATE_GATE); 1952 smu8_enable_disable_vce_dpm(hwmgr, false); 1953 smu8_dpm_powerdown_vce(hwmgr); 1954 data->vce_power_gated = true; 1955 } else { 1956 smu8_dpm_powerup_vce(hwmgr); 1957 data->vce_power_gated = false; 1958 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 1959 AMD_IP_BLOCK_TYPE_VCE, 1960 AMD_CG_STATE_UNGATE); 1961 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 1962 AMD_IP_BLOCK_TYPE_VCE, 1963 AMD_PG_STATE_UNGATE); 1964 smu8_dpm_update_vce_dpm(hwmgr); 1965 smu8_enable_disable_vce_dpm(hwmgr, true); 1966 } 1967 } 1968 1969 static const struct pp_hwmgr_func smu8_hwmgr_funcs = { 1970 .backend_init = smu8_hwmgr_backend_init, 1971 .backend_fini = smu8_hwmgr_backend_fini, 1972 .apply_state_adjust_rules = smu8_apply_state_adjust_rules, 1973 .force_dpm_level = smu8_dpm_force_dpm_level, 1974 .get_power_state_size = smu8_get_power_state_size, 1975 .powerdown_uvd = smu8_dpm_powerdown_uvd, 1976 .powergate_uvd = smu8_dpm_powergate_uvd, 1977 .powergate_vce = smu8_dpm_powergate_vce, 1978 .powergate_acp = smu8_dpm_powergate_acp, 1979 .get_mclk = smu8_dpm_get_mclk, 1980 .get_sclk = smu8_dpm_get_sclk, 1981 .patch_boot_state = smu8_dpm_patch_boot_state, 1982 .get_pp_table_entry = smu8_dpm_get_pp_table_entry, 1983 .get_num_of_pp_table_entries = smu8_dpm_get_num_of_pp_table_entries, 1984 .set_cpu_power_state = smu8_set_cpu_power_state, 1985 .store_cc6_data = smu8_store_cc6_data, 1986 .force_clock_level = smu8_force_clock_level, 1987 .print_clock_levels = smu8_print_clock_levels, 1988 .get_dal_power_level = smu8_get_dal_power_level, 1989 .get_performance_level = smu8_get_performance_level, 1990 .get_current_shallow_sleep_clocks = smu8_get_current_shallow_sleep_clocks, 1991 .get_clock_by_type = smu8_get_clock_by_type, 1992 .get_max_high_clocks = smu8_get_max_high_clocks, 1993 .read_sensor = smu8_read_sensor, 1994 .power_off_asic = smu8_power_off_asic, 1995 .asic_setup = smu8_setup_asic_task, 1996 .dynamic_state_management_enable = smu8_enable_dpm_tasks, 1997 .power_state_set = smu8_set_power_state_tasks, 1998 .dynamic_state_management_disable = smu8_disable_dpm_tasks, 1999 .notify_cac_buffer_info = smu8_notify_cac_buffer_info, 2000 .update_nbdpm_pstate = smu8_nbdpm_pstate_enable_disable, 2001 .get_thermal_temperature_range = smu8_get_thermal_temperature_range, 2002 }; 2003 2004 int smu8_init_function_pointers(struct pp_hwmgr *hwmgr) 2005 { 2006 hwmgr->hwmgr_func = &smu8_hwmgr_funcs; 2007 hwmgr->pptable_func = &pptable_funcs; 2008 return 0; 2009 } 2010