1/* $NetBSD: amdgpu_smu10_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_smu10_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 "smumgr.h" 37#include "hwmgr.h" 38#include "hardwaremanager.h" 39#include "rv_ppsmc.h" 40#include "smu10_hwmgr.h" 41#include "power_state.h" 42#include "soc15_common.h" 43#include "smu10.h" 44 45#include <linux/nbsd-namespace.h> 46 47#define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5 48#define SMU10_MINIMUM_ENGINE_CLOCK 800 /* 8Mhz, the low boundary of engine clock allowed on this chip */ 49#define SCLK_MIN_DIV_INTV_SHIFT 12 50#define SMU10_DISPCLK_BYPASS_THRESHOLD 10000 /* 100Mhz */ 51#define SMC_RAM_END 0x40000 52 53#define mmPWR_MISC_CNTL_STATUS 0x0183 54#define mmPWR_MISC_CNTL_STATUS_BASE_IDX 0 55#define PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN__SHIFT 0x0 56#define PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT 0x1 57#define PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN_MASK 0x00000001L 58#define PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK 0x00000006L 59 60static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic; 61 62 63static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, 64 struct pp_display_clock_request *clock_req) 65{ 66 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 67 enum amd_pp_clock_type clk_type = clock_req->clock_type; 68 uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; 69 PPSMC_Msg msg; 70 71 switch (clk_type) { 72 case amd_pp_dcf_clock: 73 if (clk_freq == smu10_data->dcf_actual_hard_min_freq) 74 return 0; 75 msg = PPSMC_MSG_SetHardMinDcefclkByFreq; 76 smu10_data->dcf_actual_hard_min_freq = clk_freq; 77 break; 78 case amd_pp_soc_clock: 79 msg = PPSMC_MSG_SetHardMinSocclkByFreq; 80 break; 81 case amd_pp_f_clock: 82 if (clk_freq == smu10_data->f_actual_hard_min_freq) 83 return 0; 84 smu10_data->f_actual_hard_min_freq = clk_freq; 85 msg = PPSMC_MSG_SetHardMinFclkByFreq; 86 break; 87 default: 88 pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); 89 return -EINVAL; 90 } 91 smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq); 92 93 return 0; 94} 95 96static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps) 97{ 98 if (SMU10_Magic != hw_ps->magic) 99 return NULL; 100 101 return (struct smu10_power_state *)hw_ps; 102} 103 104static const struct smu10_power_state *cast_const_smu10_ps( 105 const struct pp_hw_power_state *hw_ps) 106{ 107 if (SMU10_Magic != hw_ps->magic) 108 return NULL; 109 110 return (const struct smu10_power_state *)hw_ps; 111} 112 113static int smu10_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) 114{ 115 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 116 117 smu10_data->dce_slow_sclk_threshold = 30000; 118 smu10_data->thermal_auto_throttling_treshold = 0; 119 smu10_data->is_nb_dpm_enabled = 1; 120 smu10_data->dpm_flags = 1; 121 smu10_data->need_min_deep_sleep_dcefclk = true; 122 smu10_data->num_active_display = 0; 123 smu10_data->deep_sleep_dcefclk = 0; 124 125 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 126 PHM_PlatformCaps_SclkDeepSleep); 127 128 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 129 PHM_PlatformCaps_SclkThrottleLowNotification); 130 131 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 132 PHM_PlatformCaps_PowerPlaySupport); 133 return 0; 134} 135 136static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, 137 struct phm_clock_and_voltage_limits *table) 138{ 139 return 0; 140} 141 142static int smu10_init_dynamic_state_adjustment_rule_settings( 143 struct pp_hwmgr *hwmgr) 144{ 145 struct phm_clock_voltage_dependency_table *table_clk_vlt; 146 147 table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), 148 GFP_KERNEL); 149 150 if (NULL == table_clk_vlt) { 151 pr_err("Can not allocate memory!\n"); 152 return -ENOMEM; 153 } 154 155 table_clk_vlt->count = 8; 156 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; 157 table_clk_vlt->entries[0].v = 0; 158 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; 159 table_clk_vlt->entries[1].v = 1; 160 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; 161 table_clk_vlt->entries[2].v = 2; 162 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; 163 table_clk_vlt->entries[3].v = 3; 164 table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; 165 table_clk_vlt->entries[4].v = 4; 166 table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; 167 table_clk_vlt->entries[5].v = 5; 168 table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; 169 table_clk_vlt->entries[6].v = 6; 170 table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; 171 table_clk_vlt->entries[7].v = 7; 172 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; 173 174 return 0; 175} 176 177static int smu10_get_system_info_data(struct pp_hwmgr *hwmgr) 178{ 179 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)hwmgr->backend; 180 181 smu10_data->sys_info.htc_hyst_lmt = 5; 182 smu10_data->sys_info.htc_tmp_lmt = 203; 183 184 if (smu10_data->thermal_auto_throttling_treshold == 0) 185 smu10_data->thermal_auto_throttling_treshold = 203; 186 187 smu10_construct_max_power_limits_table (hwmgr, 188 &hwmgr->dyn_state.max_clock_voltage_on_ac); 189 190 smu10_init_dynamic_state_adjustment_rule_settings(hwmgr); 191 192 return 0; 193} 194 195static int smu10_construct_boot_state(struct pp_hwmgr *hwmgr) 196{ 197 return 0; 198} 199 200static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input) 201{ 202 struct PP_Clocks clocks = {0}; 203 struct pp_display_clock_request clock_req; 204 205 clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; 206 clock_req.clock_type = amd_pp_dcf_clock; 207 clock_req.clock_freq_in_khz = clocks.dcefClock * 10; 208 209 PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, &clock_req), 210 "Attempt to set DCF Clock Failed!", return -EINVAL); 211 212 return 0; 213} 214 215static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) 216{ 217 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 218 219 if (smu10_data->need_min_deep_sleep_dcefclk && 220 smu10_data->deep_sleep_dcefclk != clock) { 221 smu10_data->deep_sleep_dcefclk = clock; 222 smum_send_msg_to_smc_with_parameter(hwmgr, 223 PPSMC_MSG_SetMinDeepSleepDcefclk, 224 smu10_data->deep_sleep_dcefclk); 225 } 226 return 0; 227} 228 229static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) 230{ 231 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 232 233 if (smu10_data->dcf_actual_hard_min_freq && 234 smu10_data->dcf_actual_hard_min_freq != clock) { 235 smu10_data->dcf_actual_hard_min_freq = clock; 236 smum_send_msg_to_smc_with_parameter(hwmgr, 237 PPSMC_MSG_SetHardMinDcefclkByFreq, 238 smu10_data->dcf_actual_hard_min_freq); 239 } 240 return 0; 241} 242 243static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) 244{ 245 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 246 247 if (smu10_data->f_actual_hard_min_freq && 248 smu10_data->f_actual_hard_min_freq != clock) { 249 smu10_data->f_actual_hard_min_freq = clock; 250 smum_send_msg_to_smc_with_parameter(hwmgr, 251 PPSMC_MSG_SetHardMinFclkByFreq, 252 smu10_data->f_actual_hard_min_freq); 253 } 254 return 0; 255} 256 257static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) 258{ 259 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 260 261 if (smu10_data->num_active_display != count) { 262 smu10_data->num_active_display = count; 263 smum_send_msg_to_smc_with_parameter(hwmgr, 264 PPSMC_MSG_SetDisplayCount, 265 smu10_data->num_active_display); 266 } 267 268 return 0; 269} 270 271static int smu10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) 272{ 273 return smu10_set_clock_limit(hwmgr, input); 274} 275 276static int smu10_init_power_gate_state(struct pp_hwmgr *hwmgr) 277{ 278 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 279 struct amdgpu_device *adev = hwmgr->adev; 280 281 smu10_data->vcn_power_gated = true; 282 smu10_data->isp_tileA_power_gated = true; 283 smu10_data->isp_tileB_power_gated = true; 284 285 if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) 286 return smum_send_msg_to_smc_with_parameter(hwmgr, 287 PPSMC_MSG_SetGfxCGPG, 288 true); 289 else 290 return 0; 291} 292 293 294static int smu10_setup_asic_task(struct pp_hwmgr *hwmgr) 295{ 296 return smu10_init_power_gate_state(hwmgr); 297} 298 299static int smu10_reset_cc6_data(struct pp_hwmgr *hwmgr) 300{ 301 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 302 303 smu10_data->separation_time = 0; 304 smu10_data->cc6_disable = false; 305 smu10_data->pstate_disable = false; 306 smu10_data->cc6_setting_changed = false; 307 308 return 0; 309} 310 311static int smu10_power_off_asic(struct pp_hwmgr *hwmgr) 312{ 313 return smu10_reset_cc6_data(hwmgr); 314} 315 316static bool smu10_is_gfx_on(struct pp_hwmgr *hwmgr) 317{ 318 uint32_t reg; 319 struct amdgpu_device *adev = hwmgr->adev; 320 321 reg = RREG32_SOC15(PWR, 0, mmPWR_MISC_CNTL_STATUS); 322 if ((reg & PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK) == 323 (0x2 << PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT)) 324 return true; 325 326 return false; 327} 328 329static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr) 330{ 331 struct amdgpu_device *adev = hwmgr->adev; 332 333 if (adev->pm.pp_feature & PP_GFXOFF_MASK) { 334 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff); 335 336 /* confirm gfx is back to "on" state */ 337 while (!smu10_is_gfx_on(hwmgr)) 338 msleep(1); 339 } 340 341 return 0; 342} 343 344static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 345{ 346 return 0; 347} 348 349static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr) 350{ 351 struct amdgpu_device *adev = hwmgr->adev; 352 353 if (adev->pm.pp_feature & PP_GFXOFF_MASK) 354 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff); 355 356 return 0; 357} 358 359static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) 360{ 361 return 0; 362} 363 364static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) 365{ 366 if (enable) 367 return smu10_enable_gfx_off(hwmgr); 368 else 369 return smu10_disable_gfx_off(hwmgr); 370} 371 372static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, 373 struct pp_power_state *prequest_ps, 374 const struct pp_power_state *pcurrent_ps) 375{ 376 return 0; 377} 378 379/* temporary hardcoded clock voltage breakdown tables */ 380static const DpmClock_t VddDcfClk[]= { 381 { 300, 2600}, 382 { 600, 3200}, 383 { 600, 3600}, 384}; 385 386static const DpmClock_t VddSocClk[]= { 387 { 478, 2600}, 388 { 722, 3200}, 389 { 722, 3600}, 390}; 391 392static const DpmClock_t VddFClk[]= { 393 { 400, 2600}, 394 {1200, 3200}, 395 {1200, 3600}, 396}; 397 398static const DpmClock_t VddDispClk[]= { 399 { 435, 2600}, 400 { 661, 3200}, 401 {1086, 3600}, 402}; 403 404static const DpmClock_t VddDppClk[]= { 405 { 435, 2600}, 406 { 661, 3200}, 407 { 661, 3600}, 408}; 409 410static const DpmClock_t VddPhyClk[]= { 411 { 540, 2600}, 412 { 810, 3200}, 413 { 810, 3600}, 414}; 415 416static int smu10_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, 417 struct smu10_voltage_dependency_table **pptable, 418 uint32_t num_entry, const DpmClock_t *pclk_dependency_table) 419{ 420 uint32_t table_size, i; 421 struct smu10_voltage_dependency_table *ptable; 422 423 table_size = sizeof(uint32_t) + sizeof(struct smu10_voltage_dependency_table) * num_entry; 424 ptable = kzalloc(table_size, GFP_KERNEL); 425 426 if (NULL == ptable) 427 return -ENOMEM; 428 429 ptable->count = num_entry; 430 431 for (i = 0; i < ptable->count; i++) { 432 ptable->entries[i].clk = pclk_dependency_table->Freq * 100; 433 ptable->entries[i].vol = pclk_dependency_table->Vol; 434 pclk_dependency_table++; 435 } 436 437 *pptable = ptable; 438 439 return 0; 440} 441 442 443static int smu10_populate_clock_table(struct pp_hwmgr *hwmgr) 444{ 445 uint32_t result; 446 447 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 448 DpmClocks_t *table = &(smu10_data->clock_table); 449 struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); 450 451 result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true); 452 453 PP_ASSERT_WITH_CODE((0 == result), 454 "Attempt to copy clock table from smc failed", 455 return result); 456 457 if (0 == result && table->DcefClocks[0].Freq != 0) { 458 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk, 459 NUM_DCEFCLK_DPM_LEVELS, 460 &smu10_data->clock_table.DcefClocks[0]); 461 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk, 462 NUM_SOCCLK_DPM_LEVELS, 463 &smu10_data->clock_table.SocClocks[0]); 464 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk, 465 NUM_FCLK_DPM_LEVELS, 466 &smu10_data->clock_table.FClocks[0]); 467 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk, 468 NUM_MEMCLK_DPM_LEVELS, 469 &smu10_data->clock_table.MemClocks[0]); 470 } else { 471 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk, 472 ARRAY_SIZE(VddDcfClk), 473 &VddDcfClk[0]); 474 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk, 475 ARRAY_SIZE(VddSocClk), 476 &VddSocClk[0]); 477 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk, 478 ARRAY_SIZE(VddFClk), 479 &VddFClk[0]); 480 } 481 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk, 482 ARRAY_SIZE(VddDispClk), 483 &VddDispClk[0]); 484 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk, 485 ARRAY_SIZE(VddDppClk), &VddDppClk[0]); 486 smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk, 487 ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]); 488 489 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency); 490 result = smum_get_argument(hwmgr); 491 smu10_data->gfx_min_freq_limit = result / 10 * 1000; 492 493 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency); 494 result = smum_get_argument(hwmgr); 495 smu10_data->gfx_max_freq_limit = result / 10 * 1000; 496 497 return 0; 498} 499 500static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) 501{ 502 int result = 0; 503 struct smu10_hwmgr *data; 504 505 data = kzalloc(sizeof(struct smu10_hwmgr), GFP_KERNEL); 506 if (data == NULL) 507 return -ENOMEM; 508 509 hwmgr->backend = data; 510 511 result = smu10_initialize_dpm_defaults(hwmgr); 512 if (result != 0) { 513 pr_err("smu10_initialize_dpm_defaults failed\n"); 514 return result; 515 } 516 517 smu10_populate_clock_table(hwmgr); 518 519 result = smu10_get_system_info_data(hwmgr); 520 if (result != 0) { 521 pr_err("smu10_get_system_info_data failed\n"); 522 return result; 523 } 524 525 smu10_construct_boot_state(hwmgr); 526 527 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = 528 SMU10_MAX_HARDWARE_POWERLEVELS; 529 530 hwmgr->platform_descriptor.hardwarePerformanceLevels = 531 SMU10_MAX_HARDWARE_POWERLEVELS; 532 533 hwmgr->platform_descriptor.vbiosInterruptId = 0; 534 535 hwmgr->platform_descriptor.clockStep.engineClock = 500; 536 537 hwmgr->platform_descriptor.clockStep.memoryClock = 500; 538 539 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; 540 541 hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK * 100; 542 hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK * 100; 543 544 return result; 545} 546 547static int smu10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) 548{ 549 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 550 struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); 551 552 kfree(pinfo->vdd_dep_on_dcefclk); 553 pinfo->vdd_dep_on_dcefclk = NULL; 554 kfree(pinfo->vdd_dep_on_socclk); 555 pinfo->vdd_dep_on_socclk = NULL; 556 kfree(pinfo->vdd_dep_on_fclk); 557 pinfo->vdd_dep_on_fclk = NULL; 558 kfree(pinfo->vdd_dep_on_dispclk); 559 pinfo->vdd_dep_on_dispclk = NULL; 560 kfree(pinfo->vdd_dep_on_dppclk); 561 pinfo->vdd_dep_on_dppclk = NULL; 562 kfree(pinfo->vdd_dep_on_phyclk); 563 pinfo->vdd_dep_on_phyclk = NULL; 564 565 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); 566 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; 567 568 kfree(hwmgr->backend); 569 hwmgr->backend = NULL; 570 571 return 0; 572} 573 574static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, 575 enum amd_dpm_forced_level level) 576{ 577 struct smu10_hwmgr *data = hwmgr->backend; 578 uint32_t min_sclk = hwmgr->display_config->min_core_set_clock; 579 uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100; 580 581 if (hwmgr->smu_version < 0x1E3700) { 582 pr_info("smu firmware version too old, can not set dpm level\n"); 583 return 0; 584 } 585 586 if (min_sclk < data->gfx_min_freq_limit) 587 min_sclk = data->gfx_min_freq_limit; 588 589 min_sclk /= 100; /* transfer 10KHz to MHz */ 590 if (min_mclk < data->clock_table.FClocks[0].Freq) 591 min_mclk = data->clock_table.FClocks[0].Freq; 592 593 switch (level) { 594 case AMD_DPM_FORCED_LEVEL_HIGH: 595 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 596 smum_send_msg_to_smc_with_parameter(hwmgr, 597 PPSMC_MSG_SetHardMinGfxClk, 598 data->gfx_max_freq_limit/100); 599 smum_send_msg_to_smc_with_parameter(hwmgr, 600 PPSMC_MSG_SetHardMinFclkByFreq, 601 SMU10_UMD_PSTATE_PEAK_FCLK); 602 smum_send_msg_to_smc_with_parameter(hwmgr, 603 PPSMC_MSG_SetHardMinSocclkByFreq, 604 SMU10_UMD_PSTATE_PEAK_SOCCLK); 605 smum_send_msg_to_smc_with_parameter(hwmgr, 606 PPSMC_MSG_SetHardMinVcn, 607 SMU10_UMD_PSTATE_VCE); 608 609 smum_send_msg_to_smc_with_parameter(hwmgr, 610 PPSMC_MSG_SetSoftMaxGfxClk, 611 data->gfx_max_freq_limit/100); 612 smum_send_msg_to_smc_with_parameter(hwmgr, 613 PPSMC_MSG_SetSoftMaxFclkByFreq, 614 SMU10_UMD_PSTATE_PEAK_FCLK); 615 smum_send_msg_to_smc_with_parameter(hwmgr, 616 PPSMC_MSG_SetSoftMaxSocclkByFreq, 617 SMU10_UMD_PSTATE_PEAK_SOCCLK); 618 smum_send_msg_to_smc_with_parameter(hwmgr, 619 PPSMC_MSG_SetSoftMaxVcn, 620 SMU10_UMD_PSTATE_VCE); 621 break; 622 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 623 smum_send_msg_to_smc_with_parameter(hwmgr, 624 PPSMC_MSG_SetHardMinGfxClk, 625 min_sclk); 626 smum_send_msg_to_smc_with_parameter(hwmgr, 627 PPSMC_MSG_SetSoftMaxGfxClk, 628 min_sclk); 629 break; 630 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 631 smum_send_msg_to_smc_with_parameter(hwmgr, 632 PPSMC_MSG_SetHardMinFclkByFreq, 633 min_mclk); 634 smum_send_msg_to_smc_with_parameter(hwmgr, 635 PPSMC_MSG_SetSoftMaxFclkByFreq, 636 min_mclk); 637 break; 638 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 639 smum_send_msg_to_smc_with_parameter(hwmgr, 640 PPSMC_MSG_SetHardMinGfxClk, 641 SMU10_UMD_PSTATE_GFXCLK); 642 smum_send_msg_to_smc_with_parameter(hwmgr, 643 PPSMC_MSG_SetHardMinFclkByFreq, 644 SMU10_UMD_PSTATE_FCLK); 645 smum_send_msg_to_smc_with_parameter(hwmgr, 646 PPSMC_MSG_SetHardMinSocclkByFreq, 647 SMU10_UMD_PSTATE_SOCCLK); 648 smum_send_msg_to_smc_with_parameter(hwmgr, 649 PPSMC_MSG_SetHardMinVcn, 650 SMU10_UMD_PSTATE_VCE); 651 652 smum_send_msg_to_smc_with_parameter(hwmgr, 653 PPSMC_MSG_SetSoftMaxGfxClk, 654 SMU10_UMD_PSTATE_GFXCLK); 655 smum_send_msg_to_smc_with_parameter(hwmgr, 656 PPSMC_MSG_SetSoftMaxFclkByFreq, 657 SMU10_UMD_PSTATE_FCLK); 658 smum_send_msg_to_smc_with_parameter(hwmgr, 659 PPSMC_MSG_SetSoftMaxSocclkByFreq, 660 SMU10_UMD_PSTATE_SOCCLK); 661 smum_send_msg_to_smc_with_parameter(hwmgr, 662 PPSMC_MSG_SetSoftMaxVcn, 663 SMU10_UMD_PSTATE_VCE); 664 break; 665 case AMD_DPM_FORCED_LEVEL_AUTO: 666 smum_send_msg_to_smc_with_parameter(hwmgr, 667 PPSMC_MSG_SetHardMinGfxClk, 668 min_sclk); 669 smum_send_msg_to_smc_with_parameter(hwmgr, 670 PPSMC_MSG_SetHardMinFclkByFreq, 671 hwmgr->display_config->num_display > 3 ? 672 SMU10_UMD_PSTATE_PEAK_FCLK : 673 min_mclk); 674 675 smum_send_msg_to_smc_with_parameter(hwmgr, 676 PPSMC_MSG_SetHardMinSocclkByFreq, 677 SMU10_UMD_PSTATE_MIN_SOCCLK); 678 smum_send_msg_to_smc_with_parameter(hwmgr, 679 PPSMC_MSG_SetHardMinVcn, 680 SMU10_UMD_PSTATE_MIN_VCE); 681 682 smum_send_msg_to_smc_with_parameter(hwmgr, 683 PPSMC_MSG_SetSoftMaxGfxClk, 684 data->gfx_max_freq_limit/100); 685 smum_send_msg_to_smc_with_parameter(hwmgr, 686 PPSMC_MSG_SetSoftMaxFclkByFreq, 687 SMU10_UMD_PSTATE_PEAK_FCLK); 688 smum_send_msg_to_smc_with_parameter(hwmgr, 689 PPSMC_MSG_SetSoftMaxSocclkByFreq, 690 SMU10_UMD_PSTATE_PEAK_SOCCLK); 691 smum_send_msg_to_smc_with_parameter(hwmgr, 692 PPSMC_MSG_SetSoftMaxVcn, 693 SMU10_UMD_PSTATE_VCE); 694 break; 695 case AMD_DPM_FORCED_LEVEL_LOW: 696 smum_send_msg_to_smc_with_parameter(hwmgr, 697 PPSMC_MSG_SetHardMinGfxClk, 698 data->gfx_min_freq_limit/100); 699 smum_send_msg_to_smc_with_parameter(hwmgr, 700 PPSMC_MSG_SetSoftMaxGfxClk, 701 data->gfx_min_freq_limit/100); 702 smum_send_msg_to_smc_with_parameter(hwmgr, 703 PPSMC_MSG_SetHardMinFclkByFreq, 704 min_mclk); 705 smum_send_msg_to_smc_with_parameter(hwmgr, 706 PPSMC_MSG_SetSoftMaxFclkByFreq, 707 min_mclk); 708 break; 709 case AMD_DPM_FORCED_LEVEL_MANUAL: 710 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 711 default: 712 break; 713 } 714 return 0; 715} 716 717static uint32_t smu10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 718{ 719 struct smu10_hwmgr *data; 720 721 if (hwmgr == NULL) 722 return -EINVAL; 723 724 data = (struct smu10_hwmgr *)(hwmgr->backend); 725 726 if (low) 727 return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; 728 else 729 return data->clock_vol_info.vdd_dep_on_fclk->entries[ 730 data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; 731} 732 733static uint32_t smu10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 734{ 735 struct smu10_hwmgr *data; 736 737 if (hwmgr == NULL) 738 return -EINVAL; 739 740 data = (struct smu10_hwmgr *)(hwmgr->backend); 741 742 if (low) 743 return data->gfx_min_freq_limit; 744 else 745 return data->gfx_max_freq_limit; 746} 747 748static int smu10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, 749 struct pp_hw_power_state *hw_ps) 750{ 751 return 0; 752} 753 754static int smu10_dpm_get_pp_table_entry_callback( 755 struct pp_hwmgr *hwmgr, 756 struct pp_hw_power_state *hw_ps, 757 unsigned int index, 758 const void *clock_info) 759{ 760 struct smu10_power_state *smu10_ps = cast_smu10_ps(hw_ps); 761 762 smu10_ps->levels[index].engine_clock = 0; 763 764 smu10_ps->levels[index].vddc_index = 0; 765 smu10_ps->level = index + 1; 766 767 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { 768 smu10_ps->levels[index].ds_divider_index = 5; 769 smu10_ps->levels[index].ss_divider_index = 5; 770 } 771 772 return 0; 773} 774 775static int smu10_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) 776{ 777 int result; 778 unsigned long ret = 0; 779 780 result = pp_tables_get_num_of_entries(hwmgr, &ret); 781 782 return result ? 0 : ret; 783} 784 785static int smu10_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, 786 unsigned long entry, struct pp_power_state *ps) 787{ 788 int result; 789 struct smu10_power_state *smu10_ps; 790 791 ps->hardware.magic = SMU10_Magic; 792 793 smu10_ps = cast_smu10_ps(&(ps->hardware)); 794 795 result = pp_tables_get_entry(hwmgr, entry, ps, 796 smu10_dpm_get_pp_table_entry_callback); 797 798 smu10_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; 799 smu10_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; 800 801 return result; 802} 803 804static int smu10_get_power_state_size(struct pp_hwmgr *hwmgr) 805{ 806 return sizeof(struct smu10_power_state); 807} 808 809static int smu10_set_cpu_power_state(struct pp_hwmgr *hwmgr) 810{ 811 return 0; 812} 813 814 815static int smu10_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, 816 bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) 817{ 818 struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend); 819 820 if (separation_time != data->separation_time || 821 cc6_disable != data->cc6_disable || 822 pstate_disable != data->pstate_disable) { 823 data->separation_time = separation_time; 824 data->cc6_disable = cc6_disable; 825 data->pstate_disable = pstate_disable; 826 data->cc6_setting_changed = true; 827 } 828 return 0; 829} 830 831static int smu10_get_dal_power_level(struct pp_hwmgr *hwmgr, 832 struct amd_pp_simple_clock_info *info) 833{ 834 return -EINVAL; 835} 836 837static int smu10_force_clock_level(struct pp_hwmgr *hwmgr, 838 enum pp_clock_type type, uint32_t mask) 839{ 840 struct smu10_hwmgr *data = hwmgr->backend; 841 struct smu10_voltage_dependency_table *mclk_table = 842 data->clock_vol_info.vdd_dep_on_fclk; 843 uint32_t low, high; 844 845 low = mask ? (ffs(mask) - 1) : 0; 846 high = mask ? (fls(mask) - 1) : 0; 847 848 switch (type) { 849 case PP_SCLK: 850 if (low > 2 || high > 2) { 851 pr_info("Currently sclk only support 3 levels on RV\n"); 852 return -EINVAL; 853 } 854 855 smum_send_msg_to_smc_with_parameter(hwmgr, 856 PPSMC_MSG_SetHardMinGfxClk, 857 low == 2 ? data->gfx_max_freq_limit/100 : 858 low == 1 ? SMU10_UMD_PSTATE_GFXCLK : 859 data->gfx_min_freq_limit/100); 860 861 smum_send_msg_to_smc_with_parameter(hwmgr, 862 PPSMC_MSG_SetSoftMaxGfxClk, 863 high == 0 ? data->gfx_min_freq_limit/100 : 864 high == 1 ? SMU10_UMD_PSTATE_GFXCLK : 865 data->gfx_max_freq_limit/100); 866 break; 867 868 case PP_MCLK: 869 if (low > mclk_table->count - 1 || high > mclk_table->count - 1) 870 return -EINVAL; 871 872 smum_send_msg_to_smc_with_parameter(hwmgr, 873 PPSMC_MSG_SetHardMinFclkByFreq, 874 mclk_table->entries[low].clk/100); 875 876 smum_send_msg_to_smc_with_parameter(hwmgr, 877 PPSMC_MSG_SetSoftMaxFclkByFreq, 878 mclk_table->entries[high].clk/100); 879 break; 880 881 case PP_PCIE: 882 default: 883 break; 884 } 885 return 0; 886} 887 888static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, 889 enum pp_clock_type type, char *buf) 890{ 891 struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend); 892 struct smu10_voltage_dependency_table *mclk_table = 893 data->clock_vol_info.vdd_dep_on_fclk; 894 uint32_t i, now, size = 0; 895 896 switch (type) { 897 case PP_SCLK: 898 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency); 899 now = smum_get_argument(hwmgr); 900 901 /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ 902 if (now == data->gfx_max_freq_limit/100) 903 i = 2; 904 else if (now == data->gfx_min_freq_limit/100) 905 i = 0; 906 else 907 i = 1; 908 909 size += sprintf(buf + size, "0: %uMhz %s\n", 910 data->gfx_min_freq_limit/100, 911 i == 0 ? "*" : ""); 912 size += sprintf(buf + size, "1: %uMhz %s\n", 913 i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK, 914 i == 1 ? "*" : ""); 915 size += sprintf(buf + size, "2: %uMhz %s\n", 916 data->gfx_max_freq_limit/100, 917 i == 2 ? "*" : ""); 918 break; 919 case PP_MCLK: 920 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency); 921 now = smum_get_argument(hwmgr); 922 923 for (i = 0; i < mclk_table->count; i++) 924 size += sprintf(buf + size, "%d: %uMhz %s\n", 925 i, 926 mclk_table->entries[i].clk / 100, 927 ((mclk_table->entries[i].clk / 100) 928 == now) ? "*" : ""); 929 break; 930 default: 931 break; 932 } 933 934 return size; 935} 936 937static int smu10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 938 PHM_PerformanceLevelDesignation designation, uint32_t index, 939 PHM_PerformanceLevel *level) 940{ 941 struct smu10_hwmgr *data; 942 943 if (level == NULL || hwmgr == NULL || state == NULL) 944 return -EINVAL; 945 946 data = (struct smu10_hwmgr *)(hwmgr->backend); 947 948 if (index == 0) { 949 level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; 950 level->coreClock = data->gfx_min_freq_limit; 951 } else { 952 level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[ 953 data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; 954 level->coreClock = data->gfx_max_freq_limit; 955 } 956 957 level->nonLocalMemoryFreq = 0; 958 level->nonLocalMemoryWidth = 0; 959 960 return 0; 961} 962 963static int smu10_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, 964 const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) 965{ 966 const struct smu10_power_state *ps = cast_const_smu10_ps(state); 967 968 clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index)); 969 clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index)); 970 971 return 0; 972} 973 974#define MEM_FREQ_LOW_LATENCY 25000 975#define MEM_FREQ_HIGH_LATENCY 80000 976#define MEM_LATENCY_HIGH 245 977#define MEM_LATENCY_LOW 35 978#define MEM_LATENCY_ERR 0xFFFF 979 980 981static uint32_t smu10_get_mem_latency(struct pp_hwmgr *hwmgr, 982 uint32_t clock) 983{ 984 if (clock >= MEM_FREQ_LOW_LATENCY && 985 clock < MEM_FREQ_HIGH_LATENCY) 986 return MEM_LATENCY_HIGH; 987 else if (clock >= MEM_FREQ_HIGH_LATENCY) 988 return MEM_LATENCY_LOW; 989 else 990 return MEM_LATENCY_ERR; 991} 992 993static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, 994 enum amd_pp_clock_type type, 995 struct pp_clock_levels_with_latency *clocks) 996{ 997 uint32_t i; 998 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 999 struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); 1000 struct smu10_voltage_dependency_table *pclk_vol_table; 1001 bool latency_required = false; 1002 1003 if (pinfo == NULL) 1004 return -EINVAL; 1005 1006 switch (type) { 1007 case amd_pp_mem_clock: 1008 pclk_vol_table = pinfo->vdd_dep_on_mclk; 1009 latency_required = true; 1010 break; 1011 case amd_pp_f_clock: 1012 pclk_vol_table = pinfo->vdd_dep_on_fclk; 1013 latency_required = true; 1014 break; 1015 case amd_pp_dcf_clock: 1016 pclk_vol_table = pinfo->vdd_dep_on_dcefclk; 1017 break; 1018 case amd_pp_disp_clock: 1019 pclk_vol_table = pinfo->vdd_dep_on_dispclk; 1020 break; 1021 case amd_pp_phy_clock: 1022 pclk_vol_table = pinfo->vdd_dep_on_phyclk; 1023 break; 1024 case amd_pp_dpp_clock: 1025 pclk_vol_table = pinfo->vdd_dep_on_dppclk; 1026 break; 1027 default: 1028 return -EINVAL; 1029 } 1030 1031 if (pclk_vol_table == NULL || pclk_vol_table->count == 0) 1032 return -EINVAL; 1033 1034 clocks->num_levels = 0; 1035 for (i = 0; i < pclk_vol_table->count; i++) { 1036 if (pclk_vol_table->entries[i].clk) { 1037 clocks->data[clocks->num_levels].clocks_in_khz = 1038 pclk_vol_table->entries[i].clk * 10; 1039 clocks->data[clocks->num_levels].latency_in_us = latency_required ? 1040 smu10_get_mem_latency(hwmgr, 1041 pclk_vol_table->entries[i].clk) : 1042 0; 1043 clocks->num_levels++; 1044 } 1045 } 1046 1047 return 0; 1048} 1049 1050static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, 1051 enum amd_pp_clock_type type, 1052 struct pp_clock_levels_with_voltage *clocks) 1053{ 1054 uint32_t i; 1055 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 1056 struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); 1057 struct smu10_voltage_dependency_table *pclk_vol_table = NULL; 1058 1059 if (pinfo == NULL) 1060 return -EINVAL; 1061 1062 switch (type) { 1063 case amd_pp_mem_clock: 1064 pclk_vol_table = pinfo->vdd_dep_on_mclk; 1065 break; 1066 case amd_pp_f_clock: 1067 pclk_vol_table = pinfo->vdd_dep_on_fclk; 1068 break; 1069 case amd_pp_dcf_clock: 1070 pclk_vol_table = pinfo->vdd_dep_on_dcefclk; 1071 break; 1072 case amd_pp_soc_clock: 1073 pclk_vol_table = pinfo->vdd_dep_on_socclk; 1074 break; 1075 case amd_pp_disp_clock: 1076 pclk_vol_table = pinfo->vdd_dep_on_dispclk; 1077 break; 1078 case amd_pp_phy_clock: 1079 pclk_vol_table = pinfo->vdd_dep_on_phyclk; 1080 break; 1081 default: 1082 return -EINVAL; 1083 } 1084 1085 if (pclk_vol_table == NULL || pclk_vol_table->count == 0) 1086 return -EINVAL; 1087 1088 clocks->num_levels = 0; 1089 for (i = 0; i < pclk_vol_table->count; i++) { 1090 if (pclk_vol_table->entries[i].clk) { 1091 clocks->data[clocks->num_levels].clocks_in_khz = pclk_vol_table->entries[i].clk * 10; 1092 clocks->data[clocks->num_levels].voltage_in_mv = pclk_vol_table->entries[i].vol; 1093 clocks->num_levels++; 1094 } 1095 } 1096 1097 return 0; 1098} 1099 1100 1101 1102static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) 1103{ 1104 clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */ 1105 return 0; 1106} 1107 1108static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr) 1109{ 1110 struct amdgpu_device *adev = hwmgr->adev; 1111 uint32_t reg_value = RREG32_SOC15(THM, 0, mmTHM_TCON_CUR_TMP); 1112 int cur_temp = 1113 (reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT; 1114 1115 if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK) 1116 cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 1117 else 1118 cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 1119 1120 return cur_temp; 1121} 1122 1123static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx, 1124 void *value, int *size) 1125{ 1126 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 1127 uint32_t sclk, mclk; 1128 int ret = 0; 1129 1130 switch (idx) { 1131 case AMDGPU_PP_SENSOR_GFX_SCLK: 1132 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency); 1133 sclk = smum_get_argument(hwmgr); 1134 /* in units of 10KHZ */ 1135 *((uint32_t *)value) = sclk * 100; 1136 *size = 4; 1137 break; 1138 case AMDGPU_PP_SENSOR_GFX_MCLK: 1139 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency); 1140 mclk = smum_get_argument(hwmgr); 1141 /* in units of 10KHZ */ 1142 *((uint32_t *)value) = mclk * 100; 1143 *size = 4; 1144 break; 1145 case AMDGPU_PP_SENSOR_GPU_TEMP: 1146 *((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr); 1147 break; 1148 case AMDGPU_PP_SENSOR_VCN_POWER_STATE: 1149 *(uint32_t *)value = smu10_data->vcn_power_gated ? 0 : 1; 1150 *size = 4; 1151 break; 1152 default: 1153 ret = -EINVAL; 1154 break; 1155 } 1156 1157 return ret; 1158} 1159 1160static int smu10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, 1161 void *clock_ranges) 1162{ 1163 struct smu10_hwmgr *data = hwmgr->backend; 1164 struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; 1165 Watermarks_t *table = &(data->water_marks_table); 1166 1167 smu_set_watermarks_for_clocks_ranges(table,wm_with_clock_ranges); 1168 smum_smc_table_manager(hwmgr, (uint8_t *)table, (uint16_t)SMU10_WMTABLE, false); 1169 data->water_marks_exist = true; 1170 return 0; 1171} 1172 1173static int smu10_smus_notify_pwe(struct pp_hwmgr *hwmgr) 1174{ 1175 1176 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SetRccPfcPmeRestoreRegister); 1177} 1178 1179static int smu10_powergate_mmhub(struct pp_hwmgr *hwmgr) 1180{ 1181 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub); 1182} 1183 1184static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate) 1185{ 1186 if (gate) 1187 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma); 1188 else 1189 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma); 1190} 1191 1192static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate) 1193{ 1194 struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); 1195 1196 if (bgate) { 1197 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 1198 AMD_IP_BLOCK_TYPE_VCN, 1199 AMD_PG_STATE_GATE); 1200 smum_send_msg_to_smc_with_parameter(hwmgr, 1201 PPSMC_MSG_PowerDownVcn, 0); 1202 smu10_data->vcn_power_gated = true; 1203 } else { 1204 smum_send_msg_to_smc_with_parameter(hwmgr, 1205 PPSMC_MSG_PowerUpVcn, 0); 1206 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 1207 AMD_IP_BLOCK_TYPE_VCN, 1208 AMD_PG_STATE_UNGATE); 1209 smu10_data->vcn_power_gated = false; 1210 } 1211} 1212 1213static int conv_power_profile_to_pplib_workload(int power_profile) 1214{ 1215 int pplib_workload = 0; 1216 1217 switch (power_profile) { 1218 case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: 1219 pplib_workload = WORKLOAD_DEFAULT_BIT; 1220 break; 1221 case PP_SMC_POWER_PROFILE_FULLSCREEN3D: 1222 pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; 1223 break; 1224 case PP_SMC_POWER_PROFILE_POWERSAVING: 1225 pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; 1226 break; 1227 case PP_SMC_POWER_PROFILE_VIDEO: 1228 pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; 1229 break; 1230 case PP_SMC_POWER_PROFILE_VR: 1231 pplib_workload = WORKLOAD_PPLIB_VR_BIT; 1232 break; 1233 case PP_SMC_POWER_PROFILE_COMPUTE: 1234 pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; 1235 break; 1236 } 1237 1238 return pplib_workload; 1239} 1240 1241static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) 1242{ 1243 uint32_t i, size = 0; 1244 static const uint8_t 1245 profile_mode_setting[6][4] = {{70, 60, 0, 0,}, 1246 {70, 60, 1, 3,}, 1247 {90, 60, 0, 0,}, 1248 {70, 60, 0, 0,}, 1249 {70, 90, 0, 0,}, 1250 {30, 60, 0, 6,}, 1251 }; 1252 static const char *profile_name[6] = { 1253 "BOOTUP_DEFAULT", 1254 "3D_FULL_SCREEN", 1255 "POWER_SAVING", 1256 "VIDEO", 1257 "VR", 1258 "COMPUTE"}; 1259 static const char *title[6] = {"NUM", 1260 "MODE_NAME", 1261 "BUSY_SET_POINT", 1262 "FPS", 1263 "USE_RLC_BUSY", 1264 "MIN_ACTIVE_LEVEL"}; 1265 1266 if (!buf) 1267 return -EINVAL; 1268 1269 size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], 1270 title[1], title[2], title[3], title[4], title[5]); 1271 1272 for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++) 1273 size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", 1274 i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", 1275 profile_mode_setting[i][0], profile_mode_setting[i][1], 1276 profile_mode_setting[i][2], profile_mode_setting[i][3]); 1277 1278 return size; 1279} 1280 1281static bool smu10_is_raven1_refresh(struct pp_hwmgr *hwmgr) 1282{ 1283 struct amdgpu_device *adev = hwmgr->adev; 1284 if ((adev->asic_type == CHIP_RAVEN) && 1285 (adev->rev_id != 0x15d8) && 1286 (hwmgr->smu_version >= 0x41e2b)) 1287 return true; 1288 else 1289 return false; 1290} 1291 1292static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) 1293{ 1294 int workload_type = 0; 1295 int result = 0; 1296 1297 if (input[size] > PP_SMC_POWER_PROFILE_COMPUTE) { 1298 pr_err("Invalid power profile mode %ld\n", input[size]); 1299 return -EINVAL; 1300 } 1301 if (hwmgr->power_profile_mode == input[size]) 1302 return 0; 1303 1304 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 1305 workload_type = 1306 conv_power_profile_to_pplib_workload(input[size]); 1307 if (workload_type && 1308 smu10_is_raven1_refresh(hwmgr) && 1309 !hwmgr->gfxoff_state_changed_by_workload) { 1310 smu10_gfx_off_control(hwmgr, false); 1311 hwmgr->gfxoff_state_changed_by_workload = true; 1312 } 1313 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify, 1314 1 << workload_type); 1315 if (!result) 1316 hwmgr->power_profile_mode = input[size]; 1317 if (workload_type && hwmgr->gfxoff_state_changed_by_workload) { 1318 smu10_gfx_off_control(hwmgr, true); 1319 hwmgr->gfxoff_state_changed_by_workload = false; 1320 } 1321 1322 return 0; 1323} 1324 1325static int smu10_asic_reset(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode) 1326{ 1327 return smum_send_msg_to_smc_with_parameter(hwmgr, 1328 PPSMC_MSG_DeviceDriverReset, 1329 mode); 1330} 1331 1332static const struct pp_hwmgr_func smu10_hwmgr_funcs = { 1333 .backend_init = smu10_hwmgr_backend_init, 1334 .backend_fini = smu10_hwmgr_backend_fini, 1335 .asic_setup = NULL, 1336 .apply_state_adjust_rules = smu10_apply_state_adjust_rules, 1337 .force_dpm_level = smu10_dpm_force_dpm_level, 1338 .get_power_state_size = smu10_get_power_state_size, 1339 .powerdown_uvd = NULL, 1340 .powergate_uvd = smu10_powergate_vcn, 1341 .powergate_vce = NULL, 1342 .get_mclk = smu10_dpm_get_mclk, 1343 .get_sclk = smu10_dpm_get_sclk, 1344 .patch_boot_state = smu10_dpm_patch_boot_state, 1345 .get_pp_table_entry = smu10_dpm_get_pp_table_entry, 1346 .get_num_of_pp_table_entries = smu10_dpm_get_num_of_pp_table_entries, 1347 .set_cpu_power_state = smu10_set_cpu_power_state, 1348 .store_cc6_data = smu10_store_cc6_data, 1349 .force_clock_level = smu10_force_clock_level, 1350 .print_clock_levels = smu10_print_clock_levels, 1351 .get_dal_power_level = smu10_get_dal_power_level, 1352 .get_performance_level = smu10_get_performance_level, 1353 .get_current_shallow_sleep_clocks = smu10_get_current_shallow_sleep_clocks, 1354 .get_clock_by_type_with_latency = smu10_get_clock_by_type_with_latency, 1355 .get_clock_by_type_with_voltage = smu10_get_clock_by_type_with_voltage, 1356 .set_watermarks_for_clocks_ranges = smu10_set_watermarks_for_clocks_ranges, 1357 .get_max_high_clocks = smu10_get_max_high_clocks, 1358 .read_sensor = smu10_read_sensor, 1359 .set_active_display_count = smu10_set_active_display_count, 1360 .set_min_deep_sleep_dcefclk = smu10_set_min_deep_sleep_dcefclk, 1361 .dynamic_state_management_enable = smu10_enable_dpm_tasks, 1362 .power_off_asic = smu10_power_off_asic, 1363 .asic_setup = smu10_setup_asic_task, 1364 .power_state_set = smu10_set_power_state_tasks, 1365 .dynamic_state_management_disable = smu10_disable_dpm_tasks, 1366 .powergate_mmhub = smu10_powergate_mmhub, 1367 .smus_notify_pwe = smu10_smus_notify_pwe, 1368 .display_clock_voltage_request = smu10_display_clock_voltage_request, 1369 .powergate_gfx = smu10_gfx_off_control, 1370 .powergate_sdma = smu10_powergate_sdma, 1371 .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq, 1372 .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq, 1373 .get_power_profile_mode = smu10_get_power_profile_mode, 1374 .set_power_profile_mode = smu10_set_power_profile_mode, 1375 .asic_reset = smu10_asic_reset, 1376}; 1377 1378int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) 1379{ 1380 hwmgr->hwmgr_func = &smu10_hwmgr_funcs; 1381 hwmgr->pptable_func = &pptable_funcs; 1382 return 0; 1383} 1384