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