1 /* $NetBSD: amdgpu_vega20_ppt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $ */ 2 3 /* 4 * Copyright 2019 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 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vega20_ppt.c,v 1.3 2021/12/19 12:21:29 riastradh Exp $"); 28 29 #include "pp_debug.h" 30 #include <linux/firmware.h> 31 #include "amdgpu.h" 32 #include "amdgpu_smu.h" 33 #include "smu_internal.h" 34 #include "atomfirmware.h" 35 #include "amdgpu_atomfirmware.h" 36 #include "smu_v11_0.h" 37 #include "smu11_driver_if.h" 38 #include "soc15_common.h" 39 #include "atom.h" 40 #include "power_state.h" 41 #include "vega20_ppt.h" 42 #include "vega20_pptable.h" 43 #include "vega20_ppsmc.h" 44 #include "nbio/nbio_7_4_sh_mask.h" 45 #include "asic_reg/thm/thm_11_0_2_offset.h" 46 #include "asic_reg/thm/thm_11_0_2_sh_mask.h" 47 48 #include <linux/nbsd-namespace.h> 49 50 #define smnPCIE_LC_SPEED_CNTL 0x11140290 51 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 52 53 #define CTF_OFFSET_EDGE 5 54 #define CTF_OFFSET_HOTSPOT 5 55 #define CTF_OFFSET_HBM 5 56 57 #define MSG_MAP(msg) \ 58 [SMU_MSG_##msg] = {1, PPSMC_MSG_##msg} 59 60 #define SMC_DPM_FEATURE (FEATURE_DPM_PREFETCHER_MASK | \ 61 FEATURE_DPM_GFXCLK_MASK | \ 62 FEATURE_DPM_UCLK_MASK | \ 63 FEATURE_DPM_SOCCLK_MASK | \ 64 FEATURE_DPM_UVD_MASK | \ 65 FEATURE_DPM_VCE_MASK | \ 66 FEATURE_DPM_MP0CLK_MASK | \ 67 FEATURE_DPM_LINK_MASK | \ 68 FEATURE_DPM_DCEFCLK_MASK) 69 70 static struct smu_11_0_cmn2aisc_mapping vega20_message_map[SMU_MSG_MAX_COUNT] = { 71 MSG_MAP(TestMessage), 72 MSG_MAP(GetSmuVersion), 73 MSG_MAP(GetDriverIfVersion), 74 MSG_MAP(SetAllowedFeaturesMaskLow), 75 MSG_MAP(SetAllowedFeaturesMaskHigh), 76 MSG_MAP(EnableAllSmuFeatures), 77 MSG_MAP(DisableAllSmuFeatures), 78 MSG_MAP(EnableSmuFeaturesLow), 79 MSG_MAP(EnableSmuFeaturesHigh), 80 MSG_MAP(DisableSmuFeaturesLow), 81 MSG_MAP(DisableSmuFeaturesHigh), 82 MSG_MAP(GetEnabledSmuFeaturesLow), 83 MSG_MAP(GetEnabledSmuFeaturesHigh), 84 MSG_MAP(SetWorkloadMask), 85 MSG_MAP(SetPptLimit), 86 MSG_MAP(SetDriverDramAddrHigh), 87 MSG_MAP(SetDriverDramAddrLow), 88 MSG_MAP(SetToolsDramAddrHigh), 89 MSG_MAP(SetToolsDramAddrLow), 90 MSG_MAP(TransferTableSmu2Dram), 91 MSG_MAP(TransferTableDram2Smu), 92 MSG_MAP(UseDefaultPPTable), 93 MSG_MAP(UseBackupPPTable), 94 MSG_MAP(RunBtc), 95 MSG_MAP(RequestI2CBus), 96 MSG_MAP(ReleaseI2CBus), 97 MSG_MAP(SetFloorSocVoltage), 98 MSG_MAP(SoftReset), 99 MSG_MAP(StartBacoMonitor), 100 MSG_MAP(CancelBacoMonitor), 101 MSG_MAP(EnterBaco), 102 MSG_MAP(SetSoftMinByFreq), 103 MSG_MAP(SetSoftMaxByFreq), 104 MSG_MAP(SetHardMinByFreq), 105 MSG_MAP(SetHardMaxByFreq), 106 MSG_MAP(GetMinDpmFreq), 107 MSG_MAP(GetMaxDpmFreq), 108 MSG_MAP(GetDpmFreqByIndex), 109 MSG_MAP(GetDpmClockFreq), 110 MSG_MAP(GetSsVoltageByDpm), 111 MSG_MAP(SetMemoryChannelConfig), 112 MSG_MAP(SetGeminiMode), 113 MSG_MAP(SetGeminiApertureHigh), 114 MSG_MAP(SetGeminiApertureLow), 115 MSG_MAP(SetMinLinkDpmByIndex), 116 MSG_MAP(OverridePcieParameters), 117 MSG_MAP(OverDriveSetPercentage), 118 MSG_MAP(SetMinDeepSleepDcefclk), 119 MSG_MAP(ReenableAcDcInterrupt), 120 MSG_MAP(NotifyPowerSource), 121 MSG_MAP(SetUclkFastSwitch), 122 MSG_MAP(SetUclkDownHyst), 123 MSG_MAP(GetCurrentRpm), 124 MSG_MAP(SetVideoFps), 125 MSG_MAP(SetTjMax), 126 MSG_MAP(SetFanTemperatureTarget), 127 MSG_MAP(PrepareMp1ForUnload), 128 MSG_MAP(DramLogSetDramAddrHigh), 129 MSG_MAP(DramLogSetDramAddrLow), 130 MSG_MAP(DramLogSetDramSize), 131 MSG_MAP(SetFanMaxRpm), 132 MSG_MAP(SetFanMinPwm), 133 MSG_MAP(ConfigureGfxDidt), 134 MSG_MAP(NumOfDisplays), 135 MSG_MAP(RemoveMargins), 136 MSG_MAP(ReadSerialNumTop32), 137 MSG_MAP(ReadSerialNumBottom32), 138 MSG_MAP(SetSystemVirtualDramAddrHigh), 139 MSG_MAP(SetSystemVirtualDramAddrLow), 140 MSG_MAP(WaflTest), 141 MSG_MAP(SetFclkGfxClkRatio), 142 MSG_MAP(AllowGfxOff), 143 MSG_MAP(DisallowGfxOff), 144 MSG_MAP(GetPptLimit), 145 MSG_MAP(GetDcModeMaxDpmFreq), 146 MSG_MAP(GetDebugData), 147 MSG_MAP(SetXgmiMode), 148 MSG_MAP(RunAfllBtc), 149 MSG_MAP(ExitBaco), 150 MSG_MAP(PrepareMp1ForReset), 151 MSG_MAP(PrepareMp1ForShutdown), 152 MSG_MAP(SetMGpuFanBoostLimitRpm), 153 MSG_MAP(GetAVFSVoltageByDpm), 154 MSG_MAP(DFCstateControl), 155 }; 156 157 static struct smu_11_0_cmn2aisc_mapping vega20_clk_map[SMU_CLK_COUNT] = { 158 CLK_MAP(GFXCLK, PPCLK_GFXCLK), 159 CLK_MAP(VCLK, PPCLK_VCLK), 160 CLK_MAP(DCLK, PPCLK_DCLK), 161 CLK_MAP(ECLK, PPCLK_ECLK), 162 CLK_MAP(SOCCLK, PPCLK_SOCCLK), 163 CLK_MAP(UCLK, PPCLK_UCLK), 164 CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), 165 CLK_MAP(DISPCLK, PPCLK_DISPCLK), 166 CLK_MAP(PIXCLK, PPCLK_PIXCLK), 167 CLK_MAP(PHYCLK, PPCLK_PHYCLK), 168 CLK_MAP(FCLK, PPCLK_FCLK), 169 }; 170 171 static struct smu_11_0_cmn2aisc_mapping vega20_feature_mask_map[SMU_FEATURE_COUNT] = { 172 FEA_MAP(DPM_PREFETCHER), 173 FEA_MAP(DPM_GFXCLK), 174 FEA_MAP(DPM_UCLK), 175 FEA_MAP(DPM_SOCCLK), 176 FEA_MAP(DPM_UVD), 177 FEA_MAP(DPM_VCE), 178 FEA_MAP(ULV), 179 FEA_MAP(DPM_MP0CLK), 180 FEA_MAP(DPM_LINK), 181 FEA_MAP(DPM_DCEFCLK), 182 FEA_MAP(DS_GFXCLK), 183 FEA_MAP(DS_SOCCLK), 184 FEA_MAP(DS_LCLK), 185 FEA_MAP(PPT), 186 FEA_MAP(TDC), 187 FEA_MAP(THERMAL), 188 FEA_MAP(GFX_PER_CU_CG), 189 FEA_MAP(RM), 190 FEA_MAP(DS_DCEFCLK), 191 FEA_MAP(ACDC), 192 FEA_MAP(VR0HOT), 193 FEA_MAP(VR1HOT), 194 FEA_MAP(FW_CTF), 195 FEA_MAP(LED_DISPLAY), 196 FEA_MAP(FAN_CONTROL), 197 FEA_MAP(GFX_EDC), 198 FEA_MAP(GFXOFF), 199 FEA_MAP(CG), 200 FEA_MAP(DPM_FCLK), 201 FEA_MAP(DS_FCLK), 202 FEA_MAP(DS_MP1CLK), 203 FEA_MAP(DS_MP0CLK), 204 FEA_MAP(XGMI), 205 }; 206 207 static struct smu_11_0_cmn2aisc_mapping vega20_table_map[SMU_TABLE_COUNT] = { 208 TAB_MAP(PPTABLE), 209 TAB_MAP(WATERMARKS), 210 TAB_MAP(AVFS), 211 TAB_MAP(AVFS_PSM_DEBUG), 212 TAB_MAP(AVFS_FUSE_OVERRIDE), 213 TAB_MAP(PMSTATUSLOG), 214 TAB_MAP(SMU_METRICS), 215 TAB_MAP(DRIVER_SMU_CONFIG), 216 TAB_MAP(ACTIVITY_MONITOR_COEFF), 217 TAB_MAP(OVERDRIVE), 218 }; 219 220 static struct smu_11_0_cmn2aisc_mapping vega20_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { 221 PWR_MAP(AC), 222 PWR_MAP(DC), 223 }; 224 225 static struct smu_11_0_cmn2aisc_mapping vega20_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { 226 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_DEFAULT_BIT), 227 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), 228 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), 229 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), 230 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), 231 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), 232 WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), 233 }; 234 235 static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index) 236 { 237 struct smu_11_0_cmn2aisc_mapping mapping; 238 239 if (index >= SMU_TABLE_COUNT) 240 return -EINVAL; 241 242 mapping = vega20_table_map[index]; 243 if (!(mapping.valid_mapping)) { 244 return -EINVAL; 245 } 246 247 return mapping.map_to; 248 } 249 250 static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index) 251 { 252 struct smu_11_0_cmn2aisc_mapping mapping; 253 254 if (index >= SMU_POWER_SOURCE_COUNT) 255 return -EINVAL; 256 257 mapping = vega20_pwr_src_map[index]; 258 if (!(mapping.valid_mapping)) { 259 return -EINVAL; 260 } 261 262 return mapping.map_to; 263 } 264 265 static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index) 266 { 267 struct smu_11_0_cmn2aisc_mapping mapping; 268 269 if (index >= SMU_FEATURE_COUNT) 270 return -EINVAL; 271 272 mapping = vega20_feature_mask_map[index]; 273 if (!(mapping.valid_mapping)) { 274 return -EINVAL; 275 } 276 277 return mapping.map_to; 278 } 279 280 static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index) 281 { 282 struct smu_11_0_cmn2aisc_mapping mapping; 283 284 if (index >= SMU_CLK_COUNT) 285 return -EINVAL; 286 287 mapping = vega20_clk_map[index]; 288 if (!(mapping.valid_mapping)) { 289 return -EINVAL; 290 } 291 292 return mapping.map_to; 293 } 294 295 static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index) 296 { 297 struct smu_11_0_cmn2aisc_mapping mapping; 298 299 if (index >= SMU_MSG_MAX_COUNT) 300 return -EINVAL; 301 302 mapping = vega20_message_map[index]; 303 if (!(mapping.valid_mapping)) { 304 return -EINVAL; 305 } 306 307 return mapping.map_to; 308 } 309 310 static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_PROFILE profile) 311 { 312 struct smu_11_0_cmn2aisc_mapping mapping; 313 314 if (profile > PP_SMC_POWER_PROFILE_CUSTOM) 315 return -EINVAL; 316 317 mapping = vega20_workload_map[profile]; 318 if (!(mapping.valid_mapping)) { 319 return -EINVAL; 320 } 321 322 return mapping.map_to; 323 } 324 325 static int vega20_tables_init(struct smu_context *smu, struct smu_table *tables) 326 { 327 struct smu_table_context *smu_table = &smu->smu_table; 328 329 SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), 330 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 331 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 332 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 333 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), 334 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 335 SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), 336 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 337 SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, 338 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 339 SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, 340 sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, 341 AMDGPU_GEM_DOMAIN_VRAM); 342 343 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 344 if (!smu_table->metrics_table) 345 return -ENOMEM; 346 smu_table->metrics_time = 0; 347 348 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 349 if (!smu_table->watermarks_table) 350 return -ENOMEM; 351 352 return 0; 353 } 354 355 static int vega20_allocate_dpm_context(struct smu_context *smu) 356 { 357 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 358 359 if (smu_dpm->dpm_context) 360 return -EINVAL; 361 362 smu_dpm->dpm_context = kzalloc(sizeof(struct vega20_dpm_table), 363 GFP_KERNEL); 364 if (!smu_dpm->dpm_context) 365 return -ENOMEM; 366 367 if (smu_dpm->golden_dpm_context) 368 return -EINVAL; 369 370 smu_dpm->golden_dpm_context = kzalloc(sizeof(struct vega20_dpm_table), 371 GFP_KERNEL); 372 if (!smu_dpm->golden_dpm_context) 373 return -ENOMEM; 374 375 smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table); 376 377 smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state), 378 GFP_KERNEL); 379 if (!smu_dpm->dpm_current_power_state) 380 return -ENOMEM; 381 382 smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state), 383 GFP_KERNEL); 384 if (!smu_dpm->dpm_request_power_state) 385 return -ENOMEM; 386 387 return 0; 388 } 389 390 static int vega20_setup_od8_information(struct smu_context *smu) 391 { 392 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; 393 struct smu_table_context *table_context = &smu->smu_table; 394 struct vega20_od8_settings *od8_settings = (struct vega20_od8_settings *)smu->od_settings; 395 396 uint32_t od_feature_count, od_feature_array_size, 397 od_setting_count, od_setting_array_size; 398 399 if (!table_context->power_play_table) 400 return -EINVAL; 401 402 powerplay_table = table_context->power_play_table; 403 404 if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) { 405 /* Setup correct ODFeatureCount, and store ODFeatureArray from 406 * powerplay table to od_feature_capabilities */ 407 od_feature_count = 408 (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) > 409 ATOM_VEGA20_ODFEATURE_COUNT) ? 410 ATOM_VEGA20_ODFEATURE_COUNT : 411 le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount); 412 413 od_feature_array_size = sizeof(uint8_t) * od_feature_count; 414 415 if (od8_settings->od_feature_capabilities) 416 return -EINVAL; 417 418 od8_settings->od_feature_capabilities = kmemdup(&powerplay_table->OverDrive8Table.ODFeatureCapabilities, 419 od_feature_array_size, 420 GFP_KERNEL); 421 if (!od8_settings->od_feature_capabilities) 422 return -ENOMEM; 423 424 /* Setup correct ODSettingCount, and store ODSettingArray from 425 * powerplay table to od_settings_max and od_setting_min */ 426 od_setting_count = 427 (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) > 428 ATOM_VEGA20_ODSETTING_COUNT) ? 429 ATOM_VEGA20_ODSETTING_COUNT : 430 le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount); 431 432 od_setting_array_size = sizeof(uint32_t) * od_setting_count; 433 434 if (od8_settings->od_settings_max) 435 return -EINVAL; 436 437 od8_settings->od_settings_max = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMax, 438 od_setting_array_size, 439 GFP_KERNEL); 440 441 if (!od8_settings->od_settings_max) { 442 kfree(od8_settings->od_feature_capabilities); 443 od8_settings->od_feature_capabilities = NULL; 444 return -ENOMEM; 445 } 446 447 if (od8_settings->od_settings_min) 448 return -EINVAL; 449 450 od8_settings->od_settings_min = kmemdup(&powerplay_table->OverDrive8Table.ODSettingsMin, 451 od_setting_array_size, 452 GFP_KERNEL); 453 454 if (!od8_settings->od_settings_min) { 455 kfree(od8_settings->od_feature_capabilities); 456 od8_settings->od_feature_capabilities = NULL; 457 kfree(od8_settings->od_settings_max); 458 od8_settings->od_settings_max = NULL; 459 return -ENOMEM; 460 } 461 } 462 463 return 0; 464 } 465 466 static int vega20_store_powerplay_table(struct smu_context *smu) 467 { 468 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; 469 struct smu_table_context *table_context = &smu->smu_table; 470 471 if (!table_context->power_play_table) 472 return -EINVAL; 473 474 powerplay_table = table_context->power_play_table; 475 476 memcpy(table_context->driver_pptable, &powerplay_table->smcPPTable, 477 sizeof(PPTable_t)); 478 479 table_context->thermal_controller_type = powerplay_table->ucThermalControllerType; 480 481 return 0; 482 } 483 484 static int vega20_append_powerplay_table(struct smu_context *smu) 485 { 486 struct smu_table_context *table_context = &smu->smu_table; 487 PPTable_t *smc_pptable = table_context->driver_pptable; 488 struct atom_smc_dpm_info_v4_4 *smc_dpm_table; 489 int index, i, ret; 490 491 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, 492 smc_dpm_info); 493 494 ret = smu_get_atom_data_table(smu, index, NULL, NULL, NULL, 495 (uint8_t **)&smc_dpm_table); 496 if (ret) 497 return ret; 498 499 smc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; 500 smc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; 501 502 smc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping; 503 smc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping; 504 smc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping; 505 smc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping; 506 507 smc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask; 508 smc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask; 509 smc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent; 510 511 smc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent; 512 smc_pptable->GfxOffset = smc_dpm_table->gfxoffset; 513 smc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx; 514 515 smc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent; 516 smc_pptable->SocOffset = smc_dpm_table->socoffset; 517 smc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc; 518 519 smc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent; 520 smc_pptable->Mem0Offset = smc_dpm_table->mem0offset; 521 smc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0; 522 523 smc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent; 524 smc_pptable->Mem1Offset = smc_dpm_table->mem1offset; 525 smc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1; 526 527 smc_pptable->AcDcGpio = smc_dpm_table->acdcgpio; 528 smc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity; 529 smc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio; 530 smc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity; 531 532 smc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio; 533 smc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity; 534 smc_pptable->Padding1 = smc_dpm_table->padding1; 535 smc_pptable->Padding2 = smc_dpm_table->padding2; 536 537 smc_pptable->LedPin0 = smc_dpm_table->ledpin0; 538 smc_pptable->LedPin1 = smc_dpm_table->ledpin1; 539 smc_pptable->LedPin2 = smc_dpm_table->ledpin2; 540 541 smc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled; 542 smc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent; 543 smc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq; 544 545 smc_pptable->UclkSpreadEnabled = 0; 546 smc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent; 547 smc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq; 548 549 smc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled; 550 smc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent; 551 smc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq; 552 553 smc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled; 554 smc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; 555 smc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; 556 557 for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { 558 smc_pptable->I2cControllers[i].Enabled = 559 smc_dpm_table->i2ccontrollers[i].enabled; 560 smc_pptable->I2cControllers[i].SlaveAddress = 561 smc_dpm_table->i2ccontrollers[i].slaveaddress; 562 smc_pptable->I2cControllers[i].ControllerPort = 563 smc_dpm_table->i2ccontrollers[i].controllerport; 564 smc_pptable->I2cControllers[i].ThermalThrottler = 565 smc_dpm_table->i2ccontrollers[i].thermalthrottler; 566 smc_pptable->I2cControllers[i].I2cProtocol = 567 smc_dpm_table->i2ccontrollers[i].i2cprotocol; 568 smc_pptable->I2cControllers[i].I2cSpeed = 569 smc_dpm_table->i2ccontrollers[i].i2cspeed; 570 } 571 572 return 0; 573 } 574 575 static int vega20_check_powerplay_table(struct smu_context *smu) 576 { 577 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = NULL; 578 struct smu_table_context *table_context = &smu->smu_table; 579 580 powerplay_table = table_context->power_play_table; 581 582 if (powerplay_table->sHeader.format_revision < ATOM_VEGA20_TABLE_REVISION_VEGA20) { 583 pr_err("Unsupported PPTable format!"); 584 return -EINVAL; 585 } 586 587 if (!powerplay_table->sHeader.structuresize) { 588 pr_err("Invalid PowerPlay Table!"); 589 return -EINVAL; 590 } 591 592 return 0; 593 } 594 595 static int vega20_run_btc_afll(struct smu_context *smu) 596 { 597 return smu_send_smc_msg(smu, SMU_MSG_RunAfllBtc); 598 } 599 600 #define FEATURE_MASK(feature) (1ULL << feature) 601 static int 602 vega20_get_allowed_feature_mask(struct smu_context *smu, 603 uint32_t *feature_mask, uint32_t num) 604 { 605 if (num > 2) 606 return -EINVAL; 607 608 memset(feature_mask, 0, sizeof(uint32_t) * num); 609 610 *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) 611 | FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) 612 | FEATURE_MASK(FEATURE_DPM_UCLK_BIT) 613 | FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) 614 | FEATURE_MASK(FEATURE_DPM_UVD_BIT) 615 | FEATURE_MASK(FEATURE_DPM_VCE_BIT) 616 | FEATURE_MASK(FEATURE_ULV_BIT) 617 | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) 618 | FEATURE_MASK(FEATURE_DPM_LINK_BIT) 619 | FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) 620 | FEATURE_MASK(FEATURE_PPT_BIT) 621 | FEATURE_MASK(FEATURE_TDC_BIT) 622 | FEATURE_MASK(FEATURE_THERMAL_BIT) 623 | FEATURE_MASK(FEATURE_GFX_PER_CU_CG_BIT) 624 | FEATURE_MASK(FEATURE_RM_BIT) 625 | FEATURE_MASK(FEATURE_ACDC_BIT) 626 | FEATURE_MASK(FEATURE_VR0HOT_BIT) 627 | FEATURE_MASK(FEATURE_VR1HOT_BIT) 628 | FEATURE_MASK(FEATURE_FW_CTF_BIT) 629 | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) 630 | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) 631 | FEATURE_MASK(FEATURE_GFX_EDC_BIT) 632 | FEATURE_MASK(FEATURE_GFXOFF_BIT) 633 | FEATURE_MASK(FEATURE_CG_BIT) 634 | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) 635 | FEATURE_MASK(FEATURE_XGMI_BIT); 636 return 0; 637 } 638 639 static enum 640 amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu) 641 { 642 enum amd_pm_state_type pm_type; 643 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); 644 645 if (!smu_dpm_ctx->dpm_context || 646 !smu_dpm_ctx->dpm_current_power_state) 647 return -EINVAL; 648 649 switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) { 650 case SMU_STATE_UI_LABEL_BATTERY: 651 pm_type = POWER_STATE_TYPE_BATTERY; 652 break; 653 case SMU_STATE_UI_LABEL_BALLANCED: 654 pm_type = POWER_STATE_TYPE_BALANCED; 655 break; 656 case SMU_STATE_UI_LABEL_PERFORMANCE: 657 pm_type = POWER_STATE_TYPE_PERFORMANCE; 658 break; 659 default: 660 if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT) 661 pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; 662 else 663 pm_type = POWER_STATE_TYPE_DEFAULT; 664 break; 665 } 666 667 return pm_type; 668 } 669 670 static int 671 vega20_set_single_dpm_table(struct smu_context *smu, 672 struct vega20_single_dpm_table *single_dpm_table, 673 PPCLK_e clk_id) 674 { 675 int ret = 0; 676 uint32_t i, num_of_levels = 0, clk; 677 678 ret = smu_send_smc_msg_with_param(smu, 679 SMU_MSG_GetDpmFreqByIndex, 680 (clk_id << 16 | 0xFF)); 681 if (ret) { 682 pr_err("[GetNumOfDpmLevel] failed to get dpm levels!"); 683 return ret; 684 } 685 686 smu_read_smc_arg(smu, &num_of_levels); 687 if (!num_of_levels) { 688 pr_err("[GetNumOfDpmLevel] number of clk levels is invalid!"); 689 return -EINVAL; 690 } 691 692 single_dpm_table->count = num_of_levels; 693 694 for (i = 0; i < num_of_levels; i++) { 695 ret = smu_send_smc_msg_with_param(smu, 696 SMU_MSG_GetDpmFreqByIndex, 697 (clk_id << 16 | i)); 698 if (ret) { 699 pr_err("[GetDpmFreqByIndex] failed to get dpm freq by index!"); 700 return ret; 701 } 702 smu_read_smc_arg(smu, &clk); 703 if (!clk) { 704 pr_err("[GetDpmFreqByIndex] clk value is invalid!"); 705 return -EINVAL; 706 } 707 single_dpm_table->dpm_levels[i].value = clk; 708 single_dpm_table->dpm_levels[i].enabled = true; 709 } 710 return 0; 711 } 712 713 static void vega20_init_single_dpm_state(struct vega20_dpm_state *dpm_state) 714 { 715 dpm_state->soft_min_level = 0x0; 716 dpm_state->soft_max_level = 0xffff; 717 dpm_state->hard_min_level = 0x0; 718 dpm_state->hard_max_level = 0xffff; 719 } 720 721 static int vega20_set_default_dpm_table(struct smu_context *smu) 722 { 723 int ret; 724 725 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 726 struct vega20_dpm_table *dpm_table = NULL; 727 struct vega20_single_dpm_table *single_dpm_table; 728 729 dpm_table = smu_dpm->dpm_context; 730 731 /* socclk */ 732 single_dpm_table = &(dpm_table->soc_table); 733 734 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { 735 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 736 PPCLK_SOCCLK); 737 if (ret) { 738 pr_err("[SetupDefaultDpmTable] failed to get socclk dpm levels!"); 739 return ret; 740 } 741 } else { 742 single_dpm_table->count = 1; 743 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; 744 } 745 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 746 747 /* gfxclk */ 748 single_dpm_table = &(dpm_table->gfx_table); 749 750 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { 751 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 752 PPCLK_GFXCLK); 753 if (ret) { 754 pr_err("[SetupDefaultDpmTable] failed to get gfxclk dpm levels!"); 755 return ret; 756 } 757 } else { 758 single_dpm_table->count = 1; 759 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; 760 } 761 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 762 763 /* memclk */ 764 single_dpm_table = &(dpm_table->mem_table); 765 766 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { 767 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 768 PPCLK_UCLK); 769 if (ret) { 770 pr_err("[SetupDefaultDpmTable] failed to get memclk dpm levels!"); 771 return ret; 772 } 773 } else { 774 single_dpm_table->count = 1; 775 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; 776 } 777 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 778 779 /* eclk */ 780 single_dpm_table = &(dpm_table->eclk_table); 781 782 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) { 783 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_ECLK); 784 if (ret) { 785 pr_err("[SetupDefaultDpmTable] failed to get eclk dpm levels!"); 786 return ret; 787 } 788 } else { 789 single_dpm_table->count = 1; 790 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.eclk / 100; 791 } 792 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 793 794 /* vclk */ 795 single_dpm_table = &(dpm_table->vclk_table); 796 797 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) { 798 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_VCLK); 799 if (ret) { 800 pr_err("[SetupDefaultDpmTable] failed to get vclk dpm levels!"); 801 return ret; 802 } 803 } else { 804 single_dpm_table->count = 1; 805 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; 806 } 807 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 808 809 /* dclk */ 810 single_dpm_table = &(dpm_table->dclk_table); 811 812 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) { 813 ret = vega20_set_single_dpm_table(smu, single_dpm_table, PPCLK_DCLK); 814 if (ret) { 815 pr_err("[SetupDefaultDpmTable] failed to get dclk dpm levels!"); 816 return ret; 817 } 818 } else { 819 single_dpm_table->count = 1; 820 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; 821 } 822 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 823 824 /* dcefclk */ 825 single_dpm_table = &(dpm_table->dcef_table); 826 827 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { 828 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 829 PPCLK_DCEFCLK); 830 if (ret) { 831 pr_err("[SetupDefaultDpmTable] failed to get dcefclk dpm levels!"); 832 return ret; 833 } 834 } else { 835 single_dpm_table->count = 1; 836 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; 837 } 838 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 839 840 /* pixclk */ 841 single_dpm_table = &(dpm_table->pixel_table); 842 843 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { 844 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 845 PPCLK_PIXCLK); 846 if (ret) { 847 pr_err("[SetupDefaultDpmTable] failed to get pixclk dpm levels!"); 848 return ret; 849 } 850 } else { 851 single_dpm_table->count = 0; 852 } 853 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 854 855 /* dispclk */ 856 single_dpm_table = &(dpm_table->display_table); 857 858 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { 859 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 860 PPCLK_DISPCLK); 861 if (ret) { 862 pr_err("[SetupDefaultDpmTable] failed to get dispclk dpm levels!"); 863 return ret; 864 } 865 } else { 866 single_dpm_table->count = 0; 867 } 868 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 869 870 /* phyclk */ 871 single_dpm_table = &(dpm_table->phy_table); 872 873 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { 874 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 875 PPCLK_PHYCLK); 876 if (ret) { 877 pr_err("[SetupDefaultDpmTable] failed to get phyclk dpm levels!"); 878 return ret; 879 } 880 } else { 881 single_dpm_table->count = 0; 882 } 883 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 884 885 /* fclk */ 886 single_dpm_table = &(dpm_table->fclk_table); 887 888 if (smu_feature_is_enabled(smu,FEATURE_DPM_FCLK_BIT)) { 889 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 890 PPCLK_FCLK); 891 if (ret) { 892 pr_err("[SetupDefaultDpmTable] failed to get fclk dpm levels!"); 893 return ret; 894 } 895 } else { 896 single_dpm_table->count = 0; 897 } 898 vega20_init_single_dpm_state(&(single_dpm_table->dpm_state)); 899 900 memcpy(smu_dpm->golden_dpm_context, dpm_table, 901 sizeof(struct vega20_dpm_table)); 902 903 return 0; 904 } 905 906 static int vega20_populate_umd_state_clk(struct smu_context *smu) 907 { 908 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 909 struct vega20_dpm_table *dpm_table = NULL; 910 struct vega20_single_dpm_table *gfx_table = NULL; 911 struct vega20_single_dpm_table *mem_table = NULL; 912 913 dpm_table = smu_dpm->dpm_context; 914 gfx_table = &(dpm_table->gfx_table); 915 mem_table = &(dpm_table->mem_table); 916 917 smu->pstate_sclk = gfx_table->dpm_levels[0].value; 918 smu->pstate_mclk = mem_table->dpm_levels[0].value; 919 920 if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && 921 mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { 922 smu->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 923 smu->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 924 } 925 926 smu->pstate_sclk = smu->pstate_sclk * 100; 927 smu->pstate_mclk = smu->pstate_mclk * 100; 928 929 return 0; 930 } 931 932 static int vega20_get_clk_table(struct smu_context *smu, 933 struct pp_clock_levels_with_latency *clocks, 934 struct vega20_single_dpm_table *dpm_table) 935 { 936 int i, count; 937 938 count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; 939 clocks->num_levels = count; 940 941 for (i = 0; i < count; i++) { 942 clocks->data[i].clocks_in_khz = 943 dpm_table->dpm_levels[i].value * 1000; 944 clocks->data[i].latency_in_us = 0; 945 } 946 947 return 0; 948 } 949 950 static int vega20_print_clk_levels(struct smu_context *smu, 951 enum smu_clk_type type, char *buf) 952 { 953 int i, now, size = 0; 954 int ret = 0; 955 uint32_t gen_speed, lane_width; 956 struct amdgpu_device *adev = smu->adev; 957 struct pp_clock_levels_with_latency clocks; 958 struct vega20_single_dpm_table *single_dpm_table; 959 struct smu_table_context *table_context = &smu->smu_table; 960 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 961 struct vega20_dpm_table *dpm_table = NULL; 962 struct vega20_od8_settings *od8_settings = 963 (struct vega20_od8_settings *)smu->od_settings; 964 OverDriveTable_t *od_table = 965 (OverDriveTable_t *)(table_context->overdrive_table); 966 PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; 967 968 dpm_table = smu_dpm->dpm_context; 969 970 switch (type) { 971 case SMU_SCLK: 972 ret = smu_get_current_clk_freq(smu, SMU_GFXCLK, &now); 973 if (ret) { 974 pr_err("Attempt to get current gfx clk Failed!"); 975 return ret; 976 } 977 978 single_dpm_table = &(dpm_table->gfx_table); 979 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); 980 if (ret) { 981 pr_err("Attempt to get gfx clk levels Failed!"); 982 return ret; 983 } 984 985 for (i = 0; i < clocks.num_levels; i++) 986 size += sprintf(buf + size, "%d: %uMhz %s\n", i, 987 clocks.data[i].clocks_in_khz / 1000, 988 (clocks.data[i].clocks_in_khz == now * 10) 989 ? "*" : ""); 990 break; 991 992 case SMU_MCLK: 993 ret = smu_get_current_clk_freq(smu, SMU_UCLK, &now); 994 if (ret) { 995 pr_err("Attempt to get current mclk Failed!"); 996 return ret; 997 } 998 999 single_dpm_table = &(dpm_table->mem_table); 1000 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); 1001 if (ret) { 1002 pr_err("Attempt to get memory clk levels Failed!"); 1003 return ret; 1004 } 1005 1006 for (i = 0; i < clocks.num_levels; i++) 1007 size += sprintf(buf + size, "%d: %uMhz %s\n", 1008 i, clocks.data[i].clocks_in_khz / 1000, 1009 (clocks.data[i].clocks_in_khz == now * 10) 1010 ? "*" : ""); 1011 break; 1012 1013 case SMU_SOCCLK: 1014 ret = smu_get_current_clk_freq(smu, SMU_SOCCLK, &now); 1015 if (ret) { 1016 pr_err("Attempt to get current socclk Failed!"); 1017 return ret; 1018 } 1019 1020 single_dpm_table = &(dpm_table->soc_table); 1021 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); 1022 if (ret) { 1023 pr_err("Attempt to get socclk levels Failed!"); 1024 return ret; 1025 } 1026 1027 for (i = 0; i < clocks.num_levels; i++) 1028 size += sprintf(buf + size, "%d: %uMhz %s\n", 1029 i, clocks.data[i].clocks_in_khz / 1000, 1030 (clocks.data[i].clocks_in_khz == now * 10) 1031 ? "*" : ""); 1032 break; 1033 1034 case SMU_FCLK: 1035 ret = smu_get_current_clk_freq(smu, SMU_FCLK, &now); 1036 if (ret) { 1037 pr_err("Attempt to get current fclk Failed!"); 1038 return ret; 1039 } 1040 1041 single_dpm_table = &(dpm_table->fclk_table); 1042 for (i = 0; i < single_dpm_table->count; i++) 1043 size += sprintf(buf + size, "%d: %uMhz %s\n", 1044 i, single_dpm_table->dpm_levels[i].value, 1045 (single_dpm_table->dpm_levels[i].value == now / 100) 1046 ? "*" : ""); 1047 break; 1048 1049 case SMU_DCEFCLK: 1050 ret = smu_get_current_clk_freq(smu, SMU_DCEFCLK, &now); 1051 if (ret) { 1052 pr_err("Attempt to get current dcefclk Failed!"); 1053 return ret; 1054 } 1055 1056 single_dpm_table = &(dpm_table->dcef_table); 1057 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); 1058 if (ret) { 1059 pr_err("Attempt to get dcefclk levels Failed!"); 1060 return ret; 1061 } 1062 1063 for (i = 0; i < clocks.num_levels; i++) 1064 size += sprintf(buf + size, "%d: %uMhz %s\n", 1065 i, clocks.data[i].clocks_in_khz / 1000, 1066 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 1067 break; 1068 1069 case SMU_PCIE: 1070 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & 1071 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) 1072 >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; 1073 lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & 1074 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) 1075 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; 1076 for (i = 0; i < NUM_LINK_LEVELS; i++) 1077 size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, 1078 (pptable->PcieGenSpeed[i] == 0) ? "2.5GT/s," : 1079 (pptable->PcieGenSpeed[i] == 1) ? "5.0GT/s," : 1080 (pptable->PcieGenSpeed[i] == 2) ? "8.0GT/s," : 1081 (pptable->PcieGenSpeed[i] == 3) ? "16.0GT/s," : "", 1082 (pptable->PcieLaneCount[i] == 1) ? "x1" : 1083 (pptable->PcieLaneCount[i] == 2) ? "x2" : 1084 (pptable->PcieLaneCount[i] == 3) ? "x4" : 1085 (pptable->PcieLaneCount[i] == 4) ? "x8" : 1086 (pptable->PcieLaneCount[i] == 5) ? "x12" : 1087 (pptable->PcieLaneCount[i] == 6) ? "x16" : "", 1088 pptable->LclkFreq[i], 1089 (gen_speed == pptable->PcieGenSpeed[i]) && 1090 (lane_width == pptable->PcieLaneCount[i]) ? 1091 "*" : ""); 1092 break; 1093 1094 case SMU_OD_SCLK: 1095 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && 1096 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) { 1097 size = sprintf(buf, "%s:\n", "OD_SCLK"); 1098 size += sprintf(buf + size, "0: %10uMhz\n", 1099 od_table->GfxclkFmin); 1100 size += sprintf(buf + size, "1: %10uMhz\n", 1101 od_table->GfxclkFmax); 1102 } 1103 1104 break; 1105 1106 case SMU_OD_MCLK: 1107 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { 1108 size = sprintf(buf, "%s:\n", "OD_MCLK"); 1109 size += sprintf(buf + size, "1: %10uMhz\n", 1110 od_table->UclkFmax); 1111 } 1112 1113 break; 1114 1115 case SMU_OD_VDDC_CURVE: 1116 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && 1117 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && 1118 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && 1119 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 1120 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 1121 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { 1122 size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE"); 1123 size += sprintf(buf + size, "0: %10uMhz %10dmV\n", 1124 od_table->GfxclkFreq1, 1125 od_table->GfxclkVolt1 / VOLTAGE_SCALE); 1126 size += sprintf(buf + size, "1: %10uMhz %10dmV\n", 1127 od_table->GfxclkFreq2, 1128 od_table->GfxclkVolt2 / VOLTAGE_SCALE); 1129 size += sprintf(buf + size, "2: %10uMhz %10dmV\n", 1130 od_table->GfxclkFreq3, 1131 od_table->GfxclkVolt3 / VOLTAGE_SCALE); 1132 } 1133 1134 break; 1135 1136 case SMU_OD_RANGE: 1137 size = sprintf(buf, "%s:\n", "OD_RANGE"); 1138 1139 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && 1140 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id) { 1141 size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 1142 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, 1143 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); 1144 } 1145 1146 if (od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { 1147 single_dpm_table = &(dpm_table->mem_table); 1148 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); 1149 if (ret) { 1150 pr_err("Attempt to get memory clk levels Failed!"); 1151 return ret; 1152 } 1153 1154 size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", 1155 clocks.data[0].clocks_in_khz / 1000, 1156 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); 1157 } 1158 1159 if (od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && 1160 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && 1161 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && 1162 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 1163 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 1164 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { 1165 size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", 1166 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].min_value, 1167 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].max_value); 1168 size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", 1169 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, 1170 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); 1171 size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", 1172 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].min_value, 1173 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].max_value); 1174 size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", 1175 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, 1176 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); 1177 size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", 1178 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].min_value, 1179 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].max_value); 1180 size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", 1181 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, 1182 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); 1183 } 1184 1185 break; 1186 1187 default: 1188 break; 1189 } 1190 return size; 1191 } 1192 1193 static int vega20_upload_dpm_level(struct smu_context *smu, bool max, 1194 uint32_t feature_mask) 1195 { 1196 struct vega20_dpm_table *dpm_table; 1197 struct vega20_single_dpm_table *single_dpm_table; 1198 uint32_t freq; 1199 int ret = 0; 1200 1201 dpm_table = smu->smu_dpm.dpm_context; 1202 1203 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) && 1204 (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { 1205 single_dpm_table = &(dpm_table->gfx_table); 1206 freq = max ? single_dpm_table->dpm_state.soft_max_level : 1207 single_dpm_table->dpm_state.soft_min_level; 1208 ret = smu_send_smc_msg_with_param(smu, 1209 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), 1210 (PPCLK_GFXCLK << 16) | (freq & 0xffff)); 1211 if (ret) { 1212 pr_err("Failed to set soft %s gfxclk !\n", 1213 max ? "max" : "min"); 1214 return ret; 1215 } 1216 } 1217 1218 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && 1219 (feature_mask & FEATURE_DPM_UCLK_MASK)) { 1220 single_dpm_table = &(dpm_table->mem_table); 1221 freq = max ? single_dpm_table->dpm_state.soft_max_level : 1222 single_dpm_table->dpm_state.soft_min_level; 1223 ret = smu_send_smc_msg_with_param(smu, 1224 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), 1225 (PPCLK_UCLK << 16) | (freq & 0xffff)); 1226 if (ret) { 1227 pr_err("Failed to set soft %s memclk !\n", 1228 max ? "max" : "min"); 1229 return ret; 1230 } 1231 } 1232 1233 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) && 1234 (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { 1235 single_dpm_table = &(dpm_table->soc_table); 1236 freq = max ? single_dpm_table->dpm_state.soft_max_level : 1237 single_dpm_table->dpm_state.soft_min_level; 1238 ret = smu_send_smc_msg_with_param(smu, 1239 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), 1240 (PPCLK_SOCCLK << 16) | (freq & 0xffff)); 1241 if (ret) { 1242 pr_err("Failed to set soft %s socclk !\n", 1243 max ? "max" : "min"); 1244 return ret; 1245 } 1246 } 1247 1248 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT) && 1249 (feature_mask & FEATURE_DPM_FCLK_MASK)) { 1250 single_dpm_table = &(dpm_table->fclk_table); 1251 freq = max ? single_dpm_table->dpm_state.soft_max_level : 1252 single_dpm_table->dpm_state.soft_min_level; 1253 ret = smu_send_smc_msg_with_param(smu, 1254 (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), 1255 (PPCLK_FCLK << 16) | (freq & 0xffff)); 1256 if (ret) { 1257 pr_err("Failed to set soft %s fclk !\n", 1258 max ? "max" : "min"); 1259 return ret; 1260 } 1261 } 1262 1263 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && 1264 (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { 1265 single_dpm_table = &(dpm_table->dcef_table); 1266 freq = single_dpm_table->dpm_state.hard_min_level; 1267 if (!max) { 1268 ret = smu_send_smc_msg_with_param(smu, 1269 SMU_MSG_SetHardMinByFreq, 1270 (PPCLK_DCEFCLK << 16) | (freq & 0xffff)); 1271 if (ret) { 1272 pr_err("Failed to set hard min dcefclk !\n"); 1273 return ret; 1274 } 1275 } 1276 } 1277 1278 return ret; 1279 } 1280 1281 static int vega20_force_clk_levels(struct smu_context *smu, 1282 enum smu_clk_type clk_type, uint32_t mask) 1283 { 1284 struct vega20_dpm_table *dpm_table; 1285 struct vega20_single_dpm_table *single_dpm_table; 1286 uint32_t soft_min_level, soft_max_level, hard_min_level; 1287 int ret = 0; 1288 1289 soft_min_level = mask ? (ffs(mask) - 1) : 0; 1290 soft_max_level = mask ? (fls(mask) - 1) : 0; 1291 1292 dpm_table = smu->smu_dpm.dpm_context; 1293 1294 switch (clk_type) { 1295 case SMU_SCLK: 1296 single_dpm_table = &(dpm_table->gfx_table); 1297 1298 if (soft_max_level >= single_dpm_table->count) { 1299 pr_err("Clock level specified %d is over max allowed %d\n", 1300 soft_max_level, single_dpm_table->count - 1); 1301 ret = -EINVAL; 1302 break; 1303 } 1304 1305 single_dpm_table->dpm_state.soft_min_level = 1306 single_dpm_table->dpm_levels[soft_min_level].value; 1307 single_dpm_table->dpm_state.soft_max_level = 1308 single_dpm_table->dpm_levels[soft_max_level].value; 1309 1310 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_GFXCLK_MASK); 1311 if (ret) { 1312 pr_err("Failed to upload boot level to lowest!\n"); 1313 break; 1314 } 1315 1316 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_GFXCLK_MASK); 1317 if (ret) 1318 pr_err("Failed to upload dpm max level to highest!\n"); 1319 1320 break; 1321 1322 case SMU_MCLK: 1323 single_dpm_table = &(dpm_table->mem_table); 1324 1325 if (soft_max_level >= single_dpm_table->count) { 1326 pr_err("Clock level specified %d is over max allowed %d\n", 1327 soft_max_level, single_dpm_table->count - 1); 1328 ret = -EINVAL; 1329 break; 1330 } 1331 1332 single_dpm_table->dpm_state.soft_min_level = 1333 single_dpm_table->dpm_levels[soft_min_level].value; 1334 single_dpm_table->dpm_state.soft_max_level = 1335 single_dpm_table->dpm_levels[soft_max_level].value; 1336 1337 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_UCLK_MASK); 1338 if (ret) { 1339 pr_err("Failed to upload boot level to lowest!\n"); 1340 break; 1341 } 1342 1343 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_UCLK_MASK); 1344 if (ret) 1345 pr_err("Failed to upload dpm max level to highest!\n"); 1346 1347 break; 1348 1349 case SMU_SOCCLK: 1350 single_dpm_table = &(dpm_table->soc_table); 1351 1352 if (soft_max_level >= single_dpm_table->count) { 1353 pr_err("Clock level specified %d is over max allowed %d\n", 1354 soft_max_level, single_dpm_table->count - 1); 1355 ret = -EINVAL; 1356 break; 1357 } 1358 1359 single_dpm_table->dpm_state.soft_min_level = 1360 single_dpm_table->dpm_levels[soft_min_level].value; 1361 single_dpm_table->dpm_state.soft_max_level = 1362 single_dpm_table->dpm_levels[soft_max_level].value; 1363 1364 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_SOCCLK_MASK); 1365 if (ret) { 1366 pr_err("Failed to upload boot level to lowest!\n"); 1367 break; 1368 } 1369 1370 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_SOCCLK_MASK); 1371 if (ret) 1372 pr_err("Failed to upload dpm max level to highest!\n"); 1373 1374 break; 1375 1376 case SMU_FCLK: 1377 single_dpm_table = &(dpm_table->fclk_table); 1378 1379 if (soft_max_level >= single_dpm_table->count) { 1380 pr_err("Clock level specified %d is over max allowed %d\n", 1381 soft_max_level, single_dpm_table->count - 1); 1382 ret = -EINVAL; 1383 break; 1384 } 1385 1386 single_dpm_table->dpm_state.soft_min_level = 1387 single_dpm_table->dpm_levels[soft_min_level].value; 1388 single_dpm_table->dpm_state.soft_max_level = 1389 single_dpm_table->dpm_levels[soft_max_level].value; 1390 1391 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_FCLK_MASK); 1392 if (ret) { 1393 pr_err("Failed to upload boot level to lowest!\n"); 1394 break; 1395 } 1396 1397 ret = vega20_upload_dpm_level(smu, true, FEATURE_DPM_FCLK_MASK); 1398 if (ret) 1399 pr_err("Failed to upload dpm max level to highest!\n"); 1400 1401 break; 1402 1403 case SMU_DCEFCLK: 1404 hard_min_level = soft_min_level; 1405 single_dpm_table = &(dpm_table->dcef_table); 1406 1407 if (hard_min_level >= single_dpm_table->count) { 1408 pr_err("Clock level specified %d is over max allowed %d\n", 1409 hard_min_level, single_dpm_table->count - 1); 1410 ret = -EINVAL; 1411 break; 1412 } 1413 1414 single_dpm_table->dpm_state.hard_min_level = 1415 single_dpm_table->dpm_levels[hard_min_level].value; 1416 1417 ret = vega20_upload_dpm_level(smu, false, FEATURE_DPM_DCEFCLK_MASK); 1418 if (ret) 1419 pr_err("Failed to upload boot level to lowest!\n"); 1420 1421 break; 1422 1423 case SMU_PCIE: 1424 if (soft_min_level >= NUM_LINK_LEVELS || 1425 soft_max_level >= NUM_LINK_LEVELS) { 1426 ret = -EINVAL; 1427 break; 1428 } 1429 1430 ret = smu_send_smc_msg_with_param(smu, 1431 SMU_MSG_SetMinLinkDpmByIndex, soft_min_level); 1432 if (ret) 1433 pr_err("Failed to set min link dpm level!\n"); 1434 1435 break; 1436 1437 default: 1438 break; 1439 } 1440 1441 return ret; 1442 } 1443 1444 static int vega20_get_clock_by_type_with_latency(struct smu_context *smu, 1445 enum smu_clk_type clk_type, 1446 struct pp_clock_levels_with_latency *clocks) 1447 { 1448 int ret; 1449 struct vega20_single_dpm_table *single_dpm_table; 1450 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 1451 struct vega20_dpm_table *dpm_table = NULL; 1452 1453 dpm_table = smu_dpm->dpm_context; 1454 1455 switch (clk_type) { 1456 case SMU_GFXCLK: 1457 single_dpm_table = &(dpm_table->gfx_table); 1458 ret = vega20_get_clk_table(smu, clocks, single_dpm_table); 1459 break; 1460 case SMU_MCLK: 1461 single_dpm_table = &(dpm_table->mem_table); 1462 ret = vega20_get_clk_table(smu, clocks, single_dpm_table); 1463 break; 1464 case SMU_DCEFCLK: 1465 single_dpm_table = &(dpm_table->dcef_table); 1466 ret = vega20_get_clk_table(smu, clocks, single_dpm_table); 1467 break; 1468 case SMU_SOCCLK: 1469 single_dpm_table = &(dpm_table->soc_table); 1470 ret = vega20_get_clk_table(smu, clocks, single_dpm_table); 1471 break; 1472 default: 1473 ret = -EINVAL; 1474 } 1475 1476 return ret; 1477 } 1478 1479 static int vega20_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, 1480 uint32_t *voltage, 1481 uint32_t freq) 1482 { 1483 int ret; 1484 1485 ret = smu_send_smc_msg_with_param(smu, 1486 SMU_MSG_GetAVFSVoltageByDpm, 1487 ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq)); 1488 if (ret) { 1489 pr_err("[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); 1490 return ret; 1491 } 1492 1493 smu_read_smc_arg(smu, voltage); 1494 *voltage = *voltage / VOLTAGE_SCALE; 1495 1496 return 0; 1497 } 1498 1499 static int vega20_set_default_od8_setttings(struct smu_context *smu) 1500 { 1501 struct smu_table_context *table_context = &smu->smu_table; 1502 OverDriveTable_t *od_table = (OverDriveTable_t *)(table_context->overdrive_table); 1503 struct vega20_od8_settings *od8_settings = NULL; 1504 PPTable_t *smc_pptable = table_context->driver_pptable; 1505 int i, ret; 1506 1507 if (smu->od_settings) 1508 return -EINVAL; 1509 1510 od8_settings = kzalloc(sizeof(struct vega20_od8_settings), GFP_KERNEL); 1511 1512 if (!od8_settings) 1513 return -ENOMEM; 1514 1515 smu->od_settings = (void *)od8_settings; 1516 1517 ret = vega20_setup_od8_information(smu); 1518 if (ret) { 1519 pr_err("Retrieve board OD limits failed!\n"); 1520 return ret; 1521 } 1522 1523 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { 1524 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] && 1525 od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 && 1526 od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 && 1527 (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >= 1528 od8_settings->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) { 1529 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = 1530 OD8_GFXCLK_LIMITS; 1531 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = 1532 OD8_GFXCLK_LIMITS; 1533 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = 1534 od_table->GfxclkFmin; 1535 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = 1536 od_table->GfxclkFmax; 1537 } 1538 1539 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] && 1540 (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >= 1541 smc_pptable->MinVoltageGfx / VOLTAGE_SCALE) && 1542 (od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <= 1543 smc_pptable->MaxVoltageGfx / VOLTAGE_SCALE) && 1544 (od8_settings->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] <= 1545 od8_settings->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3])) { 1546 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = 1547 OD8_GFXCLK_CURVE; 1548 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = 1549 OD8_GFXCLK_CURVE; 1550 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = 1551 OD8_GFXCLK_CURVE; 1552 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = 1553 OD8_GFXCLK_CURVE; 1554 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = 1555 OD8_GFXCLK_CURVE; 1556 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = 1557 OD8_GFXCLK_CURVE; 1558 1559 od_table->GfxclkFreq1 = od_table->GfxclkFmin; 1560 od_table->GfxclkFreq2 = (od_table->GfxclkFmin + od_table->GfxclkFmax) / 2; 1561 od_table->GfxclkFreq3 = od_table->GfxclkFmax; 1562 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = 1563 od_table->GfxclkFreq1; 1564 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = 1565 od_table->GfxclkFreq2; 1566 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = 1567 od_table->GfxclkFreq3; 1568 1569 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu, 1570 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value, 1571 od_table->GfxclkFreq1); 1572 if (ret) 1573 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0; 1574 od_table->GfxclkVolt1 = 1575 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value 1576 * VOLTAGE_SCALE; 1577 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu, 1578 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value, 1579 od_table->GfxclkFreq2); 1580 if (ret) 1581 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0; 1582 od_table->GfxclkVolt2 = 1583 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value 1584 * VOLTAGE_SCALE; 1585 ret = vega20_overdrive_get_gfx_clk_base_voltage(smu, 1586 &od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value, 1587 od_table->GfxclkFreq3); 1588 if (ret) 1589 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0; 1590 od_table->GfxclkVolt3 = 1591 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value 1592 * VOLTAGE_SCALE; 1593 } 1594 } 1595 1596 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { 1597 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] && 1598 od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 && 1599 od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 && 1600 (od8_settings->od_settings_max[OD8_SETTING_UCLK_FMAX] >= 1601 od8_settings->od_settings_min[OD8_SETTING_UCLK_FMAX])) { 1602 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 1603 OD8_UCLK_MAX; 1604 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = 1605 od_table->UclkFmax; 1606 } 1607 } 1608 1609 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] && 1610 od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 && 1611 od8_settings->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100 && 1612 od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 && 1613 od8_settings->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100) { 1614 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 1615 OD8_POWER_LIMIT; 1616 od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = 1617 od_table->OverDrivePct; 1618 } 1619 1620 if (smu_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) { 1621 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] && 1622 od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && 1623 od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && 1624 (od8_settings->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >= 1625 od8_settings->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) { 1626 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = 1627 OD8_ACOUSTIC_LIMIT_SCLK; 1628 od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = 1629 od_table->FanMaximumRpm; 1630 } 1631 1632 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] && 1633 od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] > 0 && 1634 od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 && 1635 (od8_settings->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >= 1636 od8_settings->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) { 1637 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = 1638 OD8_FAN_SPEED_MIN; 1639 od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = 1640 od_table->FanMinimumPwm * smc_pptable->FanMaximumRpm / 100; 1641 } 1642 } 1643 1644 if (smu_feature_is_enabled(smu, SMU_FEATURE_THERMAL_BIT)) { 1645 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] && 1646 od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 && 1647 od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 && 1648 (od8_settings->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >= 1649 od8_settings->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) { 1650 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = 1651 OD8_TEMPERATURE_FAN; 1652 od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = 1653 od_table->FanTargetTemperature; 1654 } 1655 1656 if (od8_settings->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] && 1657 od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && 1658 od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && 1659 (od8_settings->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >= 1660 od8_settings->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) { 1661 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = 1662 OD8_TEMPERATURE_SYSTEM; 1663 od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = 1664 od_table->MaxOpTemp; 1665 } 1666 } 1667 1668 for (i = 0; i < OD8_SETTING_COUNT; i++) { 1669 if (od8_settings->od8_settings_array[i].feature_id) { 1670 od8_settings->od8_settings_array[i].min_value = 1671 od8_settings->od_settings_min[i]; 1672 od8_settings->od8_settings_array[i].max_value = 1673 od8_settings->od_settings_max[i]; 1674 od8_settings->od8_settings_array[i].current_value = 1675 od8_settings->od8_settings_array[i].default_value; 1676 } else { 1677 od8_settings->od8_settings_array[i].min_value = 0; 1678 od8_settings->od8_settings_array[i].max_value = 0; 1679 od8_settings->od8_settings_array[i].current_value = 0; 1680 } 1681 } 1682 1683 return 0; 1684 } 1685 1686 static int vega20_get_metrics_table(struct smu_context *smu, 1687 SmuMetrics_t *metrics_table) 1688 { 1689 struct smu_table_context *smu_table= &smu->smu_table; 1690 int ret = 0; 1691 1692 mutex_lock(&smu->metrics_lock); 1693 if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) { 1694 ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0, 1695 (void *)smu_table->metrics_table, false); 1696 if (ret) { 1697 pr_info("Failed to export SMU metrics table!\n"); 1698 mutex_unlock(&smu->metrics_lock); 1699 return ret; 1700 } 1701 smu_table->metrics_time = jiffies; 1702 } 1703 1704 memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); 1705 mutex_unlock(&smu->metrics_lock); 1706 1707 return ret; 1708 } 1709 1710 static int vega20_set_default_od_settings(struct smu_context *smu, 1711 bool initialize) 1712 { 1713 struct smu_table_context *table_context = &smu->smu_table; 1714 int ret; 1715 1716 ret = smu_v11_0_set_default_od_settings(smu, initialize, sizeof(OverDriveTable_t)); 1717 if (ret) 1718 return ret; 1719 1720 if (initialize) { 1721 ret = vega20_set_default_od8_setttings(smu); 1722 if (ret) 1723 return ret; 1724 } 1725 1726 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, 1727 table_context->overdrive_table, true); 1728 if (ret) { 1729 pr_err("Failed to import over drive table!\n"); 1730 return ret; 1731 } 1732 1733 return 0; 1734 } 1735 1736 static int vega20_get_od_percentage(struct smu_context *smu, 1737 enum smu_clk_type clk_type) 1738 { 1739 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 1740 struct vega20_dpm_table *dpm_table = NULL; 1741 struct vega20_dpm_table *golden_table = NULL; 1742 struct vega20_single_dpm_table *single_dpm_table; 1743 struct vega20_single_dpm_table *golden_dpm_table; 1744 int value, golden_value; 1745 1746 dpm_table = smu_dpm->dpm_context; 1747 golden_table = smu_dpm->golden_dpm_context; 1748 1749 switch (clk_type) { 1750 case SMU_OD_SCLK: 1751 single_dpm_table = &(dpm_table->gfx_table); 1752 golden_dpm_table = &(golden_table->gfx_table); 1753 break; 1754 case SMU_OD_MCLK: 1755 single_dpm_table = &(dpm_table->mem_table); 1756 golden_dpm_table = &(golden_table->mem_table); 1757 break; 1758 default: 1759 return -EINVAL; 1760 break; 1761 } 1762 1763 value = single_dpm_table->dpm_levels[single_dpm_table->count - 1].value; 1764 golden_value = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value; 1765 1766 value -= golden_value; 1767 value = DIV_ROUND_UP(value * 100, golden_value); 1768 1769 return value; 1770 } 1771 1772 static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf) 1773 { 1774 DpmActivityMonitorCoeffInt_t activity_monitor; 1775 uint32_t i, size = 0; 1776 int16_t workload_type = 0; 1777 static const char *profile_name[] = { 1778 "BOOTUP_DEFAULT", 1779 "3D_FULL_SCREEN", 1780 "POWER_SAVING", 1781 "VIDEO", 1782 "VR", 1783 "COMPUTE", 1784 "CUSTOM"}; 1785 static const char *title[] = { 1786 "PROFILE_INDEX(NAME)", 1787 "CLOCK_TYPE(NAME)", 1788 "FPS", 1789 "UseRlcBusy", 1790 "MinActiveFreqType", 1791 "MinActiveFreq", 1792 "BoosterFreqType", 1793 "BoosterFreq", 1794 "PD_Data_limit_c", 1795 "PD_Data_error_coeff", 1796 "PD_Data_error_rate_coeff"}; 1797 int result = 0; 1798 1799 if (!smu->pm_enabled || !buf) 1800 return -EINVAL; 1801 1802 size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", 1803 title[0], title[1], title[2], title[3], title[4], title[5], 1804 title[6], title[7], title[8], title[9], title[10]); 1805 1806 for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { 1807 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 1808 workload_type = smu_workload_get_type(smu, i); 1809 if (workload_type < 0) 1810 return -EINVAL; 1811 1812 result = smu_update_table(smu, 1813 SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, 1814 (void *)(&activity_monitor), false); 1815 if (result) { 1816 pr_err("[%s] Failed to get activity monitor!", __func__); 1817 return result; 1818 } 1819 1820 size += sprintf(buf + size, "%2d %14s%s:\n", 1821 i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); 1822 1823 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 1824 " ", 1825 0, 1826 "GFXCLK", 1827 activity_monitor.Gfx_FPS, 1828 activity_monitor.Gfx_UseRlcBusy, 1829 activity_monitor.Gfx_MinActiveFreqType, 1830 activity_monitor.Gfx_MinActiveFreq, 1831 activity_monitor.Gfx_BoosterFreqType, 1832 activity_monitor.Gfx_BoosterFreq, 1833 activity_monitor.Gfx_PD_Data_limit_c, 1834 activity_monitor.Gfx_PD_Data_error_coeff, 1835 activity_monitor.Gfx_PD_Data_error_rate_coeff); 1836 1837 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 1838 " ", 1839 1, 1840 "SOCCLK", 1841 activity_monitor.Soc_FPS, 1842 activity_monitor.Soc_UseRlcBusy, 1843 activity_monitor.Soc_MinActiveFreqType, 1844 activity_monitor.Soc_MinActiveFreq, 1845 activity_monitor.Soc_BoosterFreqType, 1846 activity_monitor.Soc_BoosterFreq, 1847 activity_monitor.Soc_PD_Data_limit_c, 1848 activity_monitor.Soc_PD_Data_error_coeff, 1849 activity_monitor.Soc_PD_Data_error_rate_coeff); 1850 1851 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 1852 " ", 1853 2, 1854 "UCLK", 1855 activity_monitor.Mem_FPS, 1856 activity_monitor.Mem_UseRlcBusy, 1857 activity_monitor.Mem_MinActiveFreqType, 1858 activity_monitor.Mem_MinActiveFreq, 1859 activity_monitor.Mem_BoosterFreqType, 1860 activity_monitor.Mem_BoosterFreq, 1861 activity_monitor.Mem_PD_Data_limit_c, 1862 activity_monitor.Mem_PD_Data_error_coeff, 1863 activity_monitor.Mem_PD_Data_error_rate_coeff); 1864 1865 size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", 1866 " ", 1867 3, 1868 "FCLK", 1869 activity_monitor.Fclk_FPS, 1870 activity_monitor.Fclk_UseRlcBusy, 1871 activity_monitor.Fclk_MinActiveFreqType, 1872 activity_monitor.Fclk_MinActiveFreq, 1873 activity_monitor.Fclk_BoosterFreqType, 1874 activity_monitor.Fclk_BoosterFreq, 1875 activity_monitor.Fclk_PD_Data_limit_c, 1876 activity_monitor.Fclk_PD_Data_error_coeff, 1877 activity_monitor.Fclk_PD_Data_error_rate_coeff); 1878 } 1879 1880 return size; 1881 } 1882 1883 static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) 1884 { 1885 DpmActivityMonitorCoeffInt_t activity_monitor; 1886 int workload_type = 0, ret = 0; 1887 1888 smu->power_profile_mode = input[size]; 1889 1890 if (!smu->pm_enabled) 1891 return ret; 1892 if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { 1893 pr_err("Invalid power profile mode %d\n", smu->power_profile_mode); 1894 return -EINVAL; 1895 } 1896 1897 if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { 1898 ret = smu_update_table(smu, 1899 SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, 1900 (void *)(&activity_monitor), false); 1901 if (ret) { 1902 pr_err("[%s] Failed to get activity monitor!", __func__); 1903 return ret; 1904 } 1905 1906 switch (input[0]) { 1907 case 0: /* Gfxclk */ 1908 activity_monitor.Gfx_FPS = input[1]; 1909 activity_monitor.Gfx_UseRlcBusy = input[2]; 1910 activity_monitor.Gfx_MinActiveFreqType = input[3]; 1911 activity_monitor.Gfx_MinActiveFreq = input[4]; 1912 activity_monitor.Gfx_BoosterFreqType = input[5]; 1913 activity_monitor.Gfx_BoosterFreq = input[6]; 1914 activity_monitor.Gfx_PD_Data_limit_c = input[7]; 1915 activity_monitor.Gfx_PD_Data_error_coeff = input[8]; 1916 activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; 1917 break; 1918 case 1: /* Socclk */ 1919 activity_monitor.Soc_FPS = input[1]; 1920 activity_monitor.Soc_UseRlcBusy = input[2]; 1921 activity_monitor.Soc_MinActiveFreqType = input[3]; 1922 activity_monitor.Soc_MinActiveFreq = input[4]; 1923 activity_monitor.Soc_BoosterFreqType = input[5]; 1924 activity_monitor.Soc_BoosterFreq = input[6]; 1925 activity_monitor.Soc_PD_Data_limit_c = input[7]; 1926 activity_monitor.Soc_PD_Data_error_coeff = input[8]; 1927 activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; 1928 break; 1929 case 2: /* Uclk */ 1930 activity_monitor.Mem_FPS = input[1]; 1931 activity_monitor.Mem_UseRlcBusy = input[2]; 1932 activity_monitor.Mem_MinActiveFreqType = input[3]; 1933 activity_monitor.Mem_MinActiveFreq = input[4]; 1934 activity_monitor.Mem_BoosterFreqType = input[5]; 1935 activity_monitor.Mem_BoosterFreq = input[6]; 1936 activity_monitor.Mem_PD_Data_limit_c = input[7]; 1937 activity_monitor.Mem_PD_Data_error_coeff = input[8]; 1938 activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; 1939 break; 1940 case 3: /* Fclk */ 1941 activity_monitor.Fclk_FPS = input[1]; 1942 activity_monitor.Fclk_UseRlcBusy = input[2]; 1943 activity_monitor.Fclk_MinActiveFreqType = input[3]; 1944 activity_monitor.Fclk_MinActiveFreq = input[4]; 1945 activity_monitor.Fclk_BoosterFreqType = input[5]; 1946 activity_monitor.Fclk_BoosterFreq = input[6]; 1947 activity_monitor.Fclk_PD_Data_limit_c = input[7]; 1948 activity_monitor.Fclk_PD_Data_error_coeff = input[8]; 1949 activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; 1950 break; 1951 } 1952 1953 ret = smu_update_table(smu, 1954 SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, 1955 (void *)(&activity_monitor), true); 1956 if (ret) { 1957 pr_err("[%s] Failed to set activity monitor!", __func__); 1958 return ret; 1959 } 1960 } 1961 1962 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 1963 workload_type = smu_workload_get_type(smu, smu->power_profile_mode); 1964 if (workload_type < 0) 1965 return -EINVAL; 1966 smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, 1967 1 << workload_type); 1968 1969 return ret; 1970 } 1971 1972 static int 1973 vega20_get_profiling_clk_mask(struct smu_context *smu, 1974 enum amd_dpm_forced_level level, 1975 uint32_t *sclk_mask, 1976 uint32_t *mclk_mask, 1977 uint32_t *soc_mask) 1978 { 1979 struct vega20_dpm_table *dpm_table = (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; 1980 struct vega20_single_dpm_table *gfx_dpm_table; 1981 struct vega20_single_dpm_table *mem_dpm_table; 1982 struct vega20_single_dpm_table *soc_dpm_table; 1983 1984 if (!smu->smu_dpm.dpm_context) 1985 return -EINVAL; 1986 1987 gfx_dpm_table = &dpm_table->gfx_table; 1988 mem_dpm_table = &dpm_table->mem_table; 1989 soc_dpm_table = &dpm_table->soc_table; 1990 1991 *sclk_mask = 0; 1992 *mclk_mask = 0; 1993 *soc_mask = 0; 1994 1995 if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && 1996 mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL && 1997 soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { 1998 *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; 1999 *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; 2000 *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; 2001 } 2002 2003 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 2004 *sclk_mask = 0; 2005 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 2006 *mclk_mask = 0; 2007 } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2008 *sclk_mask = gfx_dpm_table->count - 1; 2009 *mclk_mask = mem_dpm_table->count - 1; 2010 *soc_mask = soc_dpm_table->count - 1; 2011 } 2012 2013 return 0; 2014 } 2015 2016 static int 2017 vega20_set_uclk_to_highest_dpm_level(struct smu_context *smu, 2018 struct vega20_single_dpm_table *dpm_table) 2019 { 2020 int ret = 0; 2021 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); 2022 if (!smu_dpm_ctx->dpm_context) 2023 return -EINVAL; 2024 2025 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { 2026 if (dpm_table->count <= 0) { 2027 pr_err("[%s] Dpm table has no entry!", __func__); 2028 return -EINVAL; 2029 } 2030 2031 if (dpm_table->count > NUM_UCLK_DPM_LEVELS) { 2032 pr_err("[%s] Dpm table has too many entries!", __func__); 2033 return -EINVAL; 2034 } 2035 2036 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2037 ret = smu_send_smc_msg_with_param(smu, 2038 SMU_MSG_SetHardMinByFreq, 2039 (PPCLK_UCLK << 16) | dpm_table->dpm_state.hard_min_level); 2040 if (ret) { 2041 pr_err("[%s] Set hard min uclk failed!", __func__); 2042 return ret; 2043 } 2044 } 2045 2046 return ret; 2047 } 2048 2049 static int vega20_pre_display_config_changed(struct smu_context *smu) 2050 { 2051 int ret = 0; 2052 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context; 2053 2054 if (!smu->smu_dpm.dpm_context) 2055 return -EINVAL; 2056 2057 smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0); 2058 ret = vega20_set_uclk_to_highest_dpm_level(smu, 2059 &dpm_table->mem_table); 2060 if (ret) 2061 pr_err("Failed to set uclk to highest dpm level"); 2062 return ret; 2063 } 2064 2065 static int vega20_display_config_changed(struct smu_context *smu) 2066 { 2067 int ret = 0; 2068 2069 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 2070 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 2071 ret = smu_write_watermarks_table(smu); 2072 if (ret) { 2073 pr_err("Failed to update WMTABLE!"); 2074 return ret; 2075 } 2076 smu->watermarks_bitmap |= WATERMARKS_LOADED; 2077 } 2078 2079 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 2080 smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && 2081 smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { 2082 smu_send_smc_msg_with_param(smu, 2083 SMU_MSG_NumOfDisplays, 2084 smu->display_config->num_display); 2085 } 2086 2087 return ret; 2088 } 2089 2090 static int vega20_apply_clocks_adjust_rules(struct smu_context *smu) 2091 { 2092 struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); 2093 struct vega20_dpm_table *dpm_ctx = (struct vega20_dpm_table *)(smu_dpm_ctx->dpm_context); 2094 struct vega20_single_dpm_table *dpm_table; 2095 bool vblank_too_short = false; 2096 bool disable_mclk_switching; 2097 uint32_t i, latency; 2098 2099 disable_mclk_switching = ((1 < smu->display_config->num_display) && 2100 !smu->display_config->multi_monitor_in_sync) || vblank_too_short; 2101 latency = smu->display_config->dce_tolerable_mclk_in_active_latency; 2102 2103 /* gfxclk */ 2104 dpm_table = &(dpm_ctx->gfx_table); 2105 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2106 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2107 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 2108 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2109 2110 if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { 2111 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 2112 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; 2113 } 2114 2115 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 2116 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2117 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; 2118 } 2119 2120 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2121 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2122 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2123 } 2124 2125 /* memclk */ 2126 dpm_table = &(dpm_ctx->mem_table); 2127 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2128 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2129 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 2130 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2131 2132 if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { 2133 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 2134 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; 2135 } 2136 2137 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { 2138 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2139 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; 2140 } 2141 2142 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2143 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2144 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2145 } 2146 2147 /* honour DAL's UCLK Hardmin */ 2148 if (dpm_table->dpm_state.hard_min_level < (smu->display_config->min_mem_set_clock / 100)) 2149 dpm_table->dpm_state.hard_min_level = smu->display_config->min_mem_set_clock / 100; 2150 2151 /* Hardmin is dependent on displayconfig */ 2152 if (disable_mclk_switching) { 2153 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2154 for (i = 0; i < smu_dpm_ctx->mclk_latency_table->count - 1; i++) { 2155 if (smu_dpm_ctx->mclk_latency_table->entries[i].latency <= latency) { 2156 if (dpm_table->dpm_levels[i].value >= (smu->display_config->min_mem_set_clock / 100)) { 2157 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; 2158 break; 2159 } 2160 } 2161 } 2162 } 2163 2164 if (smu->display_config->nb_pstate_switch_disable) 2165 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2166 2167 /* vclk */ 2168 dpm_table = &(dpm_ctx->vclk_table); 2169 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2170 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2171 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 2172 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2173 2174 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { 2175 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 2176 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 2177 } 2178 2179 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2180 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2181 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2182 } 2183 2184 /* dclk */ 2185 dpm_table = &(dpm_ctx->dclk_table); 2186 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2187 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2188 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 2189 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2190 2191 if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { 2192 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 2193 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; 2194 } 2195 2196 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2197 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2198 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2199 } 2200 2201 /* socclk */ 2202 dpm_table = &(dpm_ctx->soc_table); 2203 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2204 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2205 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 2206 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2207 2208 if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { 2209 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; 2210 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; 2211 } 2212 2213 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2214 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2215 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2216 } 2217 2218 /* eclk */ 2219 dpm_table = &(dpm_ctx->eclk_table); 2220 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; 2221 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2222 dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; 2223 dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2224 2225 if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { 2226 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; 2227 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; 2228 } 2229 2230 if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { 2231 dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2232 dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; 2233 } 2234 return 0; 2235 } 2236 2237 static int 2238 vega20_notify_smc_display_config(struct smu_context *smu) 2239 { 2240 struct vega20_dpm_table *dpm_table = smu->smu_dpm.dpm_context; 2241 struct vega20_single_dpm_table *memtable = &dpm_table->mem_table; 2242 struct smu_clocks min_clocks = {0}; 2243 struct pp_display_clock_request clock_req; 2244 int ret = 0; 2245 2246 min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; 2247 min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; 2248 min_clocks.memory_clock = smu->display_config->min_mem_set_clock; 2249 2250 if (smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { 2251 clock_req.clock_type = amd_pp_dcef_clock; 2252 clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; 2253 if (!smu_v11_0_display_clock_voltage_request(smu, &clock_req)) { 2254 if (smu_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { 2255 ret = smu_send_smc_msg_with_param(smu, 2256 SMU_MSG_SetMinDeepSleepDcefclk, 2257 min_clocks.dcef_clock_in_sr/100); 2258 if (ret) { 2259 pr_err("Attempt to set divider for DCEFCLK Failed!"); 2260 return ret; 2261 } 2262 } 2263 } else { 2264 pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); 2265 } 2266 } 2267 2268 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { 2269 memtable->dpm_state.hard_min_level = min_clocks.memory_clock/100; 2270 ret = smu_send_smc_msg_with_param(smu, 2271 SMU_MSG_SetHardMinByFreq, 2272 (PPCLK_UCLK << 16) | memtable->dpm_state.hard_min_level); 2273 if (ret) { 2274 pr_err("[%s] Set hard min uclk failed!", __func__); 2275 return ret; 2276 } 2277 } 2278 2279 return 0; 2280 } 2281 2282 static uint32_t vega20_find_lowest_dpm_level(struct vega20_single_dpm_table *table) 2283 { 2284 uint32_t i; 2285 2286 for (i = 0; i < table->count; i++) { 2287 if (table->dpm_levels[i].enabled) 2288 break; 2289 } 2290 if (i >= table->count) { 2291 i = 0; 2292 table->dpm_levels[i].enabled = true; 2293 } 2294 2295 return i; 2296 } 2297 2298 static uint32_t vega20_find_highest_dpm_level(struct vega20_single_dpm_table *table) 2299 { 2300 int i = 0; 2301 2302 if (!table) { 2303 pr_err("[%s] DPM Table does not exist!", __func__); 2304 return 0; 2305 } 2306 if (table->count <= 0) { 2307 pr_err("[%s] DPM Table has no entry!", __func__); 2308 return 0; 2309 } 2310 if (table->count > MAX_REGULAR_DPM_NUMBER) { 2311 pr_err("[%s] DPM Table has too many entries!", __func__); 2312 return MAX_REGULAR_DPM_NUMBER - 1; 2313 } 2314 2315 for (i = table->count - 1; i >= 0; i--) { 2316 if (table->dpm_levels[i].enabled) 2317 break; 2318 } 2319 if (i < 0) { 2320 i = 0; 2321 table->dpm_levels[i].enabled = true; 2322 } 2323 2324 return i; 2325 } 2326 2327 static int vega20_force_dpm_limit_value(struct smu_context *smu, bool highest) 2328 { 2329 uint32_t soft_level; 2330 int ret = 0; 2331 struct vega20_dpm_table *dpm_table = 2332 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; 2333 2334 if (highest) 2335 soft_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table)); 2336 else 2337 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table)); 2338 2339 dpm_table->gfx_table.dpm_state.soft_min_level = 2340 dpm_table->gfx_table.dpm_state.soft_max_level = 2341 dpm_table->gfx_table.dpm_levels[soft_level].value; 2342 2343 if (highest) 2344 soft_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table)); 2345 else 2346 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table)); 2347 2348 dpm_table->mem_table.dpm_state.soft_min_level = 2349 dpm_table->mem_table.dpm_state.soft_max_level = 2350 dpm_table->mem_table.dpm_levels[soft_level].value; 2351 2352 if (highest) 2353 soft_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table)); 2354 else 2355 soft_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table)); 2356 2357 dpm_table->soc_table.dpm_state.soft_min_level = 2358 dpm_table->soc_table.dpm_state.soft_max_level = 2359 dpm_table->soc_table.dpm_levels[soft_level].value; 2360 2361 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF); 2362 if (ret) { 2363 pr_err("Failed to upload boot level to %s!\n", 2364 highest ? "highest" : "lowest"); 2365 return ret; 2366 } 2367 2368 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF); 2369 if (ret) { 2370 pr_err("Failed to upload dpm max level to %s!\n!", 2371 highest ? "highest" : "lowest"); 2372 return ret; 2373 } 2374 2375 return ret; 2376 } 2377 2378 static int vega20_unforce_dpm_levels(struct smu_context *smu) 2379 { 2380 uint32_t soft_min_level, soft_max_level; 2381 int ret = 0; 2382 struct vega20_dpm_table *dpm_table = 2383 (struct vega20_dpm_table *)smu->smu_dpm.dpm_context; 2384 2385 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->gfx_table)); 2386 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->gfx_table)); 2387 dpm_table->gfx_table.dpm_state.soft_min_level = 2388 dpm_table->gfx_table.dpm_levels[soft_min_level].value; 2389 dpm_table->gfx_table.dpm_state.soft_max_level = 2390 dpm_table->gfx_table.dpm_levels[soft_max_level].value; 2391 2392 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->mem_table)); 2393 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->mem_table)); 2394 dpm_table->mem_table.dpm_state.soft_min_level = 2395 dpm_table->gfx_table.dpm_levels[soft_min_level].value; 2396 dpm_table->mem_table.dpm_state.soft_max_level = 2397 dpm_table->gfx_table.dpm_levels[soft_max_level].value; 2398 2399 soft_min_level = vega20_find_lowest_dpm_level(&(dpm_table->soc_table)); 2400 soft_max_level = vega20_find_highest_dpm_level(&(dpm_table->soc_table)); 2401 dpm_table->soc_table.dpm_state.soft_min_level = 2402 dpm_table->soc_table.dpm_levels[soft_min_level].value; 2403 dpm_table->soc_table.dpm_state.soft_max_level = 2404 dpm_table->soc_table.dpm_levels[soft_max_level].value; 2405 2406 ret = vega20_upload_dpm_level(smu, false, 0xFFFFFFFF); 2407 if (ret) { 2408 pr_err("Failed to upload DPM Bootup Levels!"); 2409 return ret; 2410 } 2411 2412 ret = vega20_upload_dpm_level(smu, true, 0xFFFFFFFF); 2413 if (ret) { 2414 pr_err("Failed to upload DPM Max Levels!"); 2415 return ret; 2416 } 2417 2418 return ret; 2419 } 2420 2421 static int vega20_update_specified_od8_value(struct smu_context *smu, 2422 uint32_t index, 2423 uint32_t value) 2424 { 2425 struct smu_table_context *table_context = &smu->smu_table; 2426 OverDriveTable_t *od_table = 2427 (OverDriveTable_t *)(table_context->overdrive_table); 2428 struct vega20_od8_settings *od8_settings = 2429 (struct vega20_od8_settings *)smu->od_settings; 2430 2431 switch (index) { 2432 case OD8_SETTING_GFXCLK_FMIN: 2433 od_table->GfxclkFmin = (uint16_t)value; 2434 break; 2435 2436 case OD8_SETTING_GFXCLK_FMAX: 2437 if (value < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].min_value || 2438 value > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) 2439 return -EINVAL; 2440 od_table->GfxclkFmax = (uint16_t)value; 2441 break; 2442 2443 case OD8_SETTING_GFXCLK_FREQ1: 2444 od_table->GfxclkFreq1 = (uint16_t)value; 2445 break; 2446 2447 case OD8_SETTING_GFXCLK_VOLTAGE1: 2448 od_table->GfxclkVolt1 = (uint16_t)value; 2449 break; 2450 2451 case OD8_SETTING_GFXCLK_FREQ2: 2452 od_table->GfxclkFreq2 = (uint16_t)value; 2453 break; 2454 2455 case OD8_SETTING_GFXCLK_VOLTAGE2: 2456 od_table->GfxclkVolt2 = (uint16_t)value; 2457 break; 2458 2459 case OD8_SETTING_GFXCLK_FREQ3: 2460 od_table->GfxclkFreq3 = (uint16_t)value; 2461 break; 2462 2463 case OD8_SETTING_GFXCLK_VOLTAGE3: 2464 od_table->GfxclkVolt3 = (uint16_t)value; 2465 break; 2466 2467 case OD8_SETTING_UCLK_FMAX: 2468 if (value < od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].min_value || 2469 value > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) 2470 return -EINVAL; 2471 od_table->UclkFmax = (uint16_t)value; 2472 break; 2473 2474 case OD8_SETTING_POWER_PERCENTAGE: 2475 od_table->OverDrivePct = (int16_t)value; 2476 break; 2477 2478 case OD8_SETTING_FAN_ACOUSTIC_LIMIT: 2479 od_table->FanMaximumRpm = (uint16_t)value; 2480 break; 2481 2482 case OD8_SETTING_FAN_MIN_SPEED: 2483 od_table->FanMinimumPwm = (uint16_t)value; 2484 break; 2485 2486 case OD8_SETTING_FAN_TARGET_TEMP: 2487 od_table->FanTargetTemperature = (uint16_t)value; 2488 break; 2489 2490 case OD8_SETTING_OPERATING_TEMP_MAX: 2491 od_table->MaxOpTemp = (uint16_t)value; 2492 break; 2493 } 2494 2495 return 0; 2496 } 2497 2498 static int vega20_update_od8_settings(struct smu_context *smu, 2499 uint32_t index, 2500 uint32_t value) 2501 { 2502 struct smu_table_context *table_context = &smu->smu_table; 2503 int ret; 2504 2505 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, 2506 table_context->overdrive_table, false); 2507 if (ret) { 2508 pr_err("Failed to export over drive table!\n"); 2509 return ret; 2510 } 2511 2512 ret = vega20_update_specified_od8_value(smu, index, value); 2513 if (ret) 2514 return ret; 2515 2516 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, 2517 table_context->overdrive_table, true); 2518 if (ret) { 2519 pr_err("Failed to import over drive table!\n"); 2520 return ret; 2521 } 2522 2523 return 0; 2524 } 2525 2526 static int vega20_set_od_percentage(struct smu_context *smu, 2527 enum smu_clk_type clk_type, 2528 uint32_t value) 2529 { 2530 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 2531 struct vega20_dpm_table *dpm_table = NULL; 2532 struct vega20_dpm_table *golden_table = NULL; 2533 struct vega20_single_dpm_table *single_dpm_table; 2534 struct vega20_single_dpm_table *golden_dpm_table; 2535 uint32_t od_clk, index; 2536 int ret = 0; 2537 int feature_enabled; 2538 PPCLK_e clk_id; 2539 2540 dpm_table = smu_dpm->dpm_context; 2541 golden_table = smu_dpm->golden_dpm_context; 2542 2543 switch (clk_type) { 2544 case SMU_OD_SCLK: 2545 single_dpm_table = &(dpm_table->gfx_table); 2546 golden_dpm_table = &(golden_table->gfx_table); 2547 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT); 2548 clk_id = PPCLK_GFXCLK; 2549 index = OD8_SETTING_GFXCLK_FMAX; 2550 break; 2551 case SMU_OD_MCLK: 2552 single_dpm_table = &(dpm_table->mem_table); 2553 golden_dpm_table = &(golden_table->mem_table); 2554 feature_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT); 2555 clk_id = PPCLK_UCLK; 2556 index = OD8_SETTING_UCLK_FMAX; 2557 break; 2558 default: 2559 ret = -EINVAL; 2560 break; 2561 } 2562 2563 if (ret) 2564 goto set_od_failed; 2565 2566 od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value; 2567 od_clk /= 100; 2568 od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value; 2569 2570 ret = vega20_update_od8_settings(smu, index, od_clk); 2571 if (ret) { 2572 pr_err("[Setoverdrive] failed to set od clk!\n"); 2573 goto set_od_failed; 2574 } 2575 2576 if (feature_enabled) { 2577 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 2578 clk_id); 2579 if (ret) { 2580 pr_err("[Setoverdrive] failed to refresh dpm table!\n"); 2581 goto set_od_failed; 2582 } 2583 } else { 2584 single_dpm_table->count = 1; 2585 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; 2586 } 2587 2588 ret = smu_handle_task(smu, smu_dpm->dpm_level, 2589 AMD_PP_TASK_READJUST_POWER_STATE, 2590 false); 2591 2592 set_od_failed: 2593 return ret; 2594 } 2595 2596 static int vega20_odn_edit_dpm_table(struct smu_context *smu, 2597 enum PP_OD_DPM_TABLE_COMMAND type, 2598 long *input, uint32_t size) 2599 { 2600 struct smu_table_context *table_context = &smu->smu_table; 2601 OverDriveTable_t *od_table = 2602 (OverDriveTable_t *)(table_context->overdrive_table); 2603 struct smu_dpm_context *smu_dpm = &smu->smu_dpm; 2604 struct vega20_dpm_table *dpm_table = NULL; 2605 struct vega20_single_dpm_table *single_dpm_table; 2606 struct vega20_od8_settings *od8_settings = 2607 (struct vega20_od8_settings *)smu->od_settings; 2608 struct pp_clock_levels_with_latency clocks; 2609 int32_t input_index, input_clk, input_vol, i; 2610 int od8_id; 2611 int ret = 0; 2612 2613 dpm_table = smu_dpm->dpm_context; 2614 2615 if (!input) { 2616 pr_warn("NULL user input for clock and voltage\n"); 2617 return -EINVAL; 2618 } 2619 2620 switch (type) { 2621 case PP_OD_EDIT_SCLK_VDDC_TABLE: 2622 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && 2623 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) { 2624 pr_info("Sclk min/max frequency overdrive not supported\n"); 2625 return -EOPNOTSUPP; 2626 } 2627 2628 for (i = 0; i < size; i += 2) { 2629 if (i + 2 > size) { 2630 pr_info("invalid number of input parameters %d\n", size); 2631 return -EINVAL; 2632 } 2633 2634 input_index = input[i]; 2635 input_clk = input[i + 1]; 2636 2637 if (input_index != 0 && input_index != 1) { 2638 pr_info("Invalid index %d\n", input_index); 2639 pr_info("Support min/max sclk frequency settingonly which index by 0/1\n"); 2640 return -EINVAL; 2641 } 2642 2643 if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value || 2644 input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) { 2645 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 2646 input_clk, 2647 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, 2648 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); 2649 return -EINVAL; 2650 } 2651 2652 if (input_index == 0 && od_table->GfxclkFmin != input_clk) { 2653 od_table->GfxclkFmin = input_clk; 2654 od8_settings->od_gfxclk_update = true; 2655 } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) { 2656 od_table->GfxclkFmax = input_clk; 2657 od8_settings->od_gfxclk_update = true; 2658 } 2659 } 2660 2661 break; 2662 2663 case PP_OD_EDIT_MCLK_VDDC_TABLE: 2664 if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { 2665 pr_info("Mclk max frequency overdrive not supported\n"); 2666 return -EOPNOTSUPP; 2667 } 2668 2669 single_dpm_table = &(dpm_table->mem_table); 2670 ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); 2671 if (ret) { 2672 pr_err("Attempt to get memory clk levels Failed!"); 2673 return ret; 2674 } 2675 2676 for (i = 0; i < size; i += 2) { 2677 if (i + 2 > size) { 2678 pr_info("invalid number of input parameters %d\n", 2679 size); 2680 return -EINVAL; 2681 } 2682 2683 input_index = input[i]; 2684 input_clk = input[i + 1]; 2685 2686 if (input_index != 1) { 2687 pr_info("Invalid index %d\n", input_index); 2688 pr_info("Support max Mclk frequency setting only which index by 1\n"); 2689 return -EINVAL; 2690 } 2691 2692 if (input_clk < clocks.data[0].clocks_in_khz / 1000 || 2693 input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) { 2694 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 2695 input_clk, 2696 clocks.data[0].clocks_in_khz / 1000, 2697 od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); 2698 return -EINVAL; 2699 } 2700 2701 if (input_index == 1 && od_table->UclkFmax != input_clk) { 2702 od8_settings->od_gfxclk_update = true; 2703 od_table->UclkFmax = input_clk; 2704 } 2705 } 2706 2707 break; 2708 2709 case PP_OD_EDIT_VDDC_CURVE: 2710 if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && 2711 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && 2712 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && 2713 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && 2714 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && 2715 od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { 2716 pr_info("Voltage curve calibrate not supported\n"); 2717 return -EOPNOTSUPP; 2718 } 2719 2720 for (i = 0; i < size; i += 3) { 2721 if (i + 3 > size) { 2722 pr_info("invalid number of input parameters %d\n", 2723 size); 2724 return -EINVAL; 2725 } 2726 2727 input_index = input[i]; 2728 input_clk = input[i + 1]; 2729 input_vol = input[i + 2]; 2730 2731 if (input_index > 2) { 2732 pr_info("Setting for point %d is not supported\n", 2733 input_index + 1); 2734 pr_info("Three supported points index by 0, 1, 2\n"); 2735 return -EINVAL; 2736 } 2737 2738 od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index; 2739 if (input_clk < od8_settings->od8_settings_array[od8_id].min_value || 2740 input_clk > od8_settings->od8_settings_array[od8_id].max_value) { 2741 pr_info("clock freq %d is not within allowed range [%d - %d]\n", 2742 input_clk, 2743 od8_settings->od8_settings_array[od8_id].min_value, 2744 od8_settings->od8_settings_array[od8_id].max_value); 2745 return -EINVAL; 2746 } 2747 2748 od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index; 2749 if (input_vol < od8_settings->od8_settings_array[od8_id].min_value || 2750 input_vol > od8_settings->od8_settings_array[od8_id].max_value) { 2751 pr_info("clock voltage %d is not within allowed range [%d- %d]\n", 2752 input_vol, 2753 od8_settings->od8_settings_array[od8_id].min_value, 2754 od8_settings->od8_settings_array[od8_id].max_value); 2755 return -EINVAL; 2756 } 2757 2758 switch (input_index) { 2759 case 0: 2760 od_table->GfxclkFreq1 = input_clk; 2761 od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE; 2762 break; 2763 case 1: 2764 od_table->GfxclkFreq2 = input_clk; 2765 od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE; 2766 break; 2767 case 2: 2768 od_table->GfxclkFreq3 = input_clk; 2769 od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE; 2770 break; 2771 } 2772 } 2773 2774 break; 2775 2776 case PP_OD_RESTORE_DEFAULT_TABLE: 2777 if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) { 2778 pr_err("Overdrive table was not initialized!\n"); 2779 return -EINVAL; 2780 } 2781 memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t)); 2782 break; 2783 2784 case PP_OD_COMMIT_DPM_TABLE: 2785 ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true); 2786 if (ret) { 2787 pr_err("Failed to import over drive table!\n"); 2788 return ret; 2789 } 2790 2791 /* retrieve updated gfxclk table */ 2792 if (od8_settings->od_gfxclk_update) { 2793 od8_settings->od_gfxclk_update = false; 2794 single_dpm_table = &(dpm_table->gfx_table); 2795 2796 if (smu_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { 2797 ret = vega20_set_single_dpm_table(smu, single_dpm_table, 2798 PPCLK_GFXCLK); 2799 if (ret) { 2800 pr_err("[Setoverdrive] failed to refresh dpm table!\n"); 2801 return ret; 2802 } 2803 } else { 2804 single_dpm_table->count = 1; 2805 single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; 2806 } 2807 } 2808 2809 break; 2810 2811 default: 2812 return -EINVAL; 2813 } 2814 2815 if (type == PP_OD_COMMIT_DPM_TABLE) { 2816 ret = smu_handle_task(smu, smu_dpm->dpm_level, 2817 AMD_PP_TASK_READJUST_POWER_STATE, 2818 false); 2819 } 2820 2821 return ret; 2822 } 2823 2824 static int vega20_dpm_set_uvd_enable(struct smu_context *smu, bool enable) 2825 { 2826 if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_UVD_BIT)) 2827 return 0; 2828 2829 if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT)) 2830 return 0; 2831 2832 return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_UVD_BIT, enable); 2833 } 2834 2835 static int vega20_dpm_set_vce_enable(struct smu_context *smu, bool enable) 2836 { 2837 if (!smu_feature_is_supported(smu, SMU_FEATURE_DPM_VCE_BIT)) 2838 return 0; 2839 2840 if (enable == smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT)) 2841 return 0; 2842 2843 return smu_feature_set_enabled(smu, SMU_FEATURE_DPM_VCE_BIT, enable); 2844 } 2845 2846 static bool vega20_is_dpm_running(struct smu_context *smu) 2847 { 2848 int ret __unused = 0; 2849 uint32_t feature_mask[2]; 2850 unsigned long feature_enabled; 2851 ret = smu_feature_get_enabled_mask(smu, feature_mask, 2); 2852 feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | 2853 ((uint64_t)feature_mask[1] << 32)); 2854 return !!(feature_enabled & SMC_DPM_FEATURE); 2855 } 2856 2857 static int vega20_set_thermal_fan_table(struct smu_context *smu) 2858 { 2859 int ret; 2860 struct smu_table_context *table_context = &smu->smu_table; 2861 PPTable_t *pptable = table_context->driver_pptable; 2862 2863 ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetFanTemperatureTarget, 2864 (uint32_t)pptable->FanTargetTemperature); 2865 2866 return ret; 2867 } 2868 2869 static int vega20_get_fan_speed_rpm(struct smu_context *smu, 2870 uint32_t *speed) 2871 { 2872 int ret; 2873 2874 ret = smu_send_smc_msg(smu, SMU_MSG_GetCurrentRpm); 2875 2876 if (ret) { 2877 pr_err("Attempt to get current RPM from SMC Failed!\n"); 2878 return ret; 2879 } 2880 2881 smu_read_smc_arg(smu, speed); 2882 2883 return 0; 2884 } 2885 2886 static int vega20_get_fan_speed_percent(struct smu_context *smu, 2887 uint32_t *speed) 2888 { 2889 int ret = 0; 2890 uint32_t current_rpm = 0, percent = 0; 2891 PPTable_t *pptable = smu->smu_table.driver_pptable; 2892 2893 ret = vega20_get_fan_speed_rpm(smu, ¤t_rpm); 2894 if (ret) 2895 return ret; 2896 2897 percent = current_rpm * 100 / pptable->FanMaximumRpm; 2898 *speed = percent > 100 ? 100 : percent; 2899 2900 return 0; 2901 } 2902 2903 static int vega20_get_gpu_power(struct smu_context *smu, uint32_t *value) 2904 { 2905 uint32_t smu_version; 2906 int ret = 0; 2907 SmuMetrics_t metrics; 2908 2909 if (!value) 2910 return -EINVAL; 2911 2912 ret = vega20_get_metrics_table(smu, &metrics); 2913 if (ret) 2914 return ret; 2915 2916 ret = smu_get_smc_version(smu, NULL, &smu_version); 2917 if (ret) 2918 return ret; 2919 2920 /* For the 40.46 release, they changed the value name */ 2921 if (smu_version == 0x282e00) 2922 *value = metrics.AverageSocketPower << 8; 2923 else 2924 *value = metrics.CurrSocketPower << 8; 2925 2926 return 0; 2927 } 2928 2929 static int vega20_get_current_activity_percent(struct smu_context *smu, 2930 enum amd_pp_sensors sensor, 2931 uint32_t *value) 2932 { 2933 int ret = 0; 2934 SmuMetrics_t metrics; 2935 2936 if (!value) 2937 return -EINVAL; 2938 2939 ret = vega20_get_metrics_table(smu, &metrics); 2940 if (ret) 2941 return ret; 2942 2943 switch (sensor) { 2944 case AMDGPU_PP_SENSOR_GPU_LOAD: 2945 *value = metrics.AverageGfxActivity; 2946 break; 2947 case AMDGPU_PP_SENSOR_MEM_LOAD: 2948 *value = metrics.AverageUclkActivity; 2949 break; 2950 default: 2951 pr_err("Invalid sensor for retrieving clock activity\n"); 2952 return -EINVAL; 2953 } 2954 2955 return 0; 2956 } 2957 2958 static int vega20_thermal_get_temperature(struct smu_context *smu, 2959 enum amd_pp_sensors sensor, 2960 uint32_t *value) 2961 { 2962 struct amdgpu_device *adev = smu->adev; 2963 SmuMetrics_t metrics; 2964 uint32_t temp = 0; 2965 int ret = 0; 2966 2967 if (!value) 2968 return -EINVAL; 2969 2970 ret = vega20_get_metrics_table(smu, &metrics); 2971 if (ret) 2972 return ret; 2973 2974 switch (sensor) { 2975 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 2976 temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); 2977 temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> 2978 CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; 2979 2980 temp = temp & 0x1ff; 2981 temp *= SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 2982 2983 *value = temp; 2984 break; 2985 case AMDGPU_PP_SENSOR_EDGE_TEMP: 2986 *value = metrics.TemperatureEdge * 2987 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 2988 break; 2989 case AMDGPU_PP_SENSOR_MEM_TEMP: 2990 *value = metrics.TemperatureHBM * 2991 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 2992 break; 2993 default: 2994 pr_err("Invalid sensor for retrieving temp\n"); 2995 return -EINVAL; 2996 } 2997 2998 return 0; 2999 } 3000 static int vega20_read_sensor(struct smu_context *smu, 3001 enum amd_pp_sensors sensor, 3002 void *data, uint32_t *size) 3003 { 3004 int ret = 0; 3005 struct smu_table_context *table_context = &smu->smu_table; 3006 PPTable_t *pptable = table_context->driver_pptable; 3007 3008 if(!data || !size) 3009 return -EINVAL; 3010 3011 mutex_lock(&smu->sensor_lock); 3012 switch (sensor) { 3013 case AMDGPU_PP_SENSOR_MAX_FAN_RPM: 3014 *(uint32_t *)data = pptable->FanMaximumRpm; 3015 *size = 4; 3016 break; 3017 case AMDGPU_PP_SENSOR_MEM_LOAD: 3018 case AMDGPU_PP_SENSOR_GPU_LOAD: 3019 ret = vega20_get_current_activity_percent(smu, 3020 sensor, 3021 (uint32_t *)data); 3022 *size = 4; 3023 break; 3024 case AMDGPU_PP_SENSOR_GPU_POWER: 3025 ret = vega20_get_gpu_power(smu, (uint32_t *)data); 3026 *size = 4; 3027 break; 3028 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 3029 case AMDGPU_PP_SENSOR_EDGE_TEMP: 3030 case AMDGPU_PP_SENSOR_MEM_TEMP: 3031 ret = vega20_thermal_get_temperature(smu, sensor, (uint32_t *)data); 3032 *size = 4; 3033 break; 3034 default: 3035 ret = smu_v11_0_read_sensor(smu, sensor, data, size); 3036 } 3037 mutex_unlock(&smu->sensor_lock); 3038 3039 return ret; 3040 } 3041 3042 static int vega20_set_watermarks_table(struct smu_context *smu, 3043 void *watermarks, struct 3044 dm_pp_wm_sets_with_clock_ranges_soc15 3045 *clock_ranges) 3046 { 3047 int i; 3048 Watermarks_t *table = watermarks; 3049 3050 if (!table || !clock_ranges) 3051 return -EINVAL; 3052 3053 if (clock_ranges->num_wm_dmif_sets > 4 || 3054 clock_ranges->num_wm_mcif_sets > 4) 3055 return -EINVAL; 3056 3057 for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { 3058 table->WatermarkRow[1][i].MinClock = 3059 cpu_to_le16((uint16_t) 3060 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / 3061 1000)); 3062 table->WatermarkRow[1][i].MaxClock = 3063 cpu_to_le16((uint16_t) 3064 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / 3065 1000)); 3066 table->WatermarkRow[1][i].MinUclk = 3067 cpu_to_le16((uint16_t) 3068 (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / 3069 1000)); 3070 table->WatermarkRow[1][i].MaxUclk = 3071 cpu_to_le16((uint16_t) 3072 (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / 3073 1000)); 3074 table->WatermarkRow[1][i].WmSetting = (uint8_t) 3075 clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; 3076 } 3077 3078 for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { 3079 table->WatermarkRow[0][i].MinClock = 3080 cpu_to_le16((uint16_t) 3081 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / 3082 1000)); 3083 table->WatermarkRow[0][i].MaxClock = 3084 cpu_to_le16((uint16_t) 3085 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / 3086 1000)); 3087 table->WatermarkRow[0][i].MinUclk = 3088 cpu_to_le16((uint16_t) 3089 (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / 3090 1000)); 3091 table->WatermarkRow[0][i].MaxUclk = 3092 cpu_to_le16((uint16_t) 3093 (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / 3094 1000)); 3095 table->WatermarkRow[0][i].WmSetting = (uint8_t) 3096 clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; 3097 } 3098 3099 return 0; 3100 } 3101 3102 static int vega20_get_thermal_temperature_range(struct smu_context *smu, 3103 struct smu_temperature_range *range) 3104 { 3105 struct smu_table_context *table_context = &smu->smu_table; 3106 const ATOM_Vega20_POWERPLAYTABLE *powerplay_table = table_context->power_play_table; 3107 PPTable_t *pptable = smu->smu_table.driver_pptable; 3108 3109 if (!range || !powerplay_table) 3110 return -EINVAL; 3111 3112 range->max = powerplay_table->usSoftwareShutdownTemp * 3113 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 3114 range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * 3115 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 3116 range->hotspot_crit_max = pptable->ThotspotLimit * 3117 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 3118 range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) * 3119 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 3120 range->mem_crit_max = pptable->ThbmLimit * 3121 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 3122 range->mem_emergency_max = (pptable->ThbmLimit + CTF_OFFSET_HBM) * 3123 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 3124 3125 3126 return 0; 3127 } 3128 3129 static int vega20_set_df_cstate(struct smu_context *smu, 3130 enum pp_df_cstate state) 3131 { 3132 uint32_t smu_version; 3133 int ret; 3134 3135 ret = smu_get_smc_version(smu, NULL, &smu_version); 3136 if (ret) { 3137 pr_err("Failed to get smu version!\n"); 3138 return ret; 3139 } 3140 3141 /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */ 3142 if (smu_version < 0x283200) { 3143 pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n"); 3144 return -EINVAL; 3145 } 3146 3147 return smu_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state); 3148 } 3149 3150 static int vega20_update_pcie_parameters(struct smu_context *smu, 3151 uint32_t pcie_gen_cap, 3152 uint32_t pcie_width_cap) 3153 { 3154 PPTable_t *pptable = smu->smu_table.driver_pptable; 3155 int ret, i; 3156 uint32_t smu_pcie_arg; 3157 3158 for (i = 0; i < NUM_LINK_LEVELS; i++) { 3159 smu_pcie_arg = (i << 16) | 3160 ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) : 3161 (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? 3162 pptable->PcieLaneCount[i] : pcie_width_cap); 3163 ret = smu_send_smc_msg_with_param(smu, 3164 SMU_MSG_OverridePcieParameters, 3165 smu_pcie_arg); 3166 } 3167 3168 return ret; 3169 } 3170 3171 3172 static const struct pptable_funcs vega20_ppt_funcs = { 3173 .tables_init = vega20_tables_init, 3174 .alloc_dpm_context = vega20_allocate_dpm_context, 3175 .store_powerplay_table = vega20_store_powerplay_table, 3176 .check_powerplay_table = vega20_check_powerplay_table, 3177 .append_powerplay_table = vega20_append_powerplay_table, 3178 .get_smu_msg_index = vega20_get_smu_msg_index, 3179 .get_smu_clk_index = vega20_get_smu_clk_index, 3180 .get_smu_feature_index = vega20_get_smu_feature_index, 3181 .get_smu_table_index = vega20_get_smu_table_index, 3182 .get_smu_power_index = vega20_get_pwr_src_index, 3183 .get_workload_type = vega20_get_workload_type, 3184 .run_btc = vega20_run_btc_afll, 3185 .get_allowed_feature_mask = vega20_get_allowed_feature_mask, 3186 .get_current_power_state = vega20_get_current_power_state, 3187 .set_default_dpm_table = vega20_set_default_dpm_table, 3188 .set_power_state = NULL, 3189 .populate_umd_state_clk = vega20_populate_umd_state_clk, 3190 .print_clk_levels = vega20_print_clk_levels, 3191 .force_clk_levels = vega20_force_clk_levels, 3192 .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency, 3193 .get_od_percentage = vega20_get_od_percentage, 3194 .get_power_profile_mode = vega20_get_power_profile_mode, 3195 .set_power_profile_mode = vega20_set_power_profile_mode, 3196 .set_performance_level = smu_v11_0_set_performance_level, 3197 .set_od_percentage = vega20_set_od_percentage, 3198 .set_default_od_settings = vega20_set_default_od_settings, 3199 .od_edit_dpm_table = vega20_odn_edit_dpm_table, 3200 .dpm_set_uvd_enable = vega20_dpm_set_uvd_enable, 3201 .dpm_set_vce_enable = vega20_dpm_set_vce_enable, 3202 .read_sensor = vega20_read_sensor, 3203 .pre_display_config_changed = vega20_pre_display_config_changed, 3204 .display_config_changed = vega20_display_config_changed, 3205 .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, 3206 .notify_smc_display_config = vega20_notify_smc_display_config, 3207 .force_dpm_limit_value = vega20_force_dpm_limit_value, 3208 .unforce_dpm_levels = vega20_unforce_dpm_levels, 3209 .get_profiling_clk_mask = vega20_get_profiling_clk_mask, 3210 .is_dpm_running = vega20_is_dpm_running, 3211 .set_thermal_fan_table = vega20_set_thermal_fan_table, 3212 .get_fan_speed_percent = vega20_get_fan_speed_percent, 3213 .get_fan_speed_rpm = vega20_get_fan_speed_rpm, 3214 .set_watermarks_table = vega20_set_watermarks_table, 3215 .get_thermal_temperature_range = vega20_get_thermal_temperature_range, 3216 .set_df_cstate = vega20_set_df_cstate, 3217 .update_pcie_parameters = vega20_update_pcie_parameters, 3218 .init_microcode = smu_v11_0_init_microcode, 3219 .load_microcode = smu_v11_0_load_microcode, 3220 .init_smc_tables = smu_v11_0_init_smc_tables, 3221 .fini_smc_tables = smu_v11_0_fini_smc_tables, 3222 .init_power = smu_v11_0_init_power, 3223 .fini_power = smu_v11_0_fini_power, 3224 .check_fw_status = smu_v11_0_check_fw_status, 3225 .setup_pptable = smu_v11_0_setup_pptable, 3226 .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, 3227 .get_clk_info_from_vbios = smu_v11_0_get_clk_info_from_vbios, 3228 .check_pptable = smu_v11_0_check_pptable, 3229 .parse_pptable = smu_v11_0_parse_pptable, 3230 .populate_smc_tables = smu_v11_0_populate_smc_pptable, 3231 .check_fw_version = smu_v11_0_check_fw_version, 3232 .write_pptable = smu_v11_0_write_pptable, 3233 .set_min_dcef_deep_sleep = smu_v11_0_set_min_dcef_deep_sleep, 3234 .set_driver_table_location = smu_v11_0_set_driver_table_location, 3235 .set_tool_table_location = smu_v11_0_set_tool_table_location, 3236 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 3237 .system_features_control = smu_v11_0_system_features_control, 3238 .send_smc_msg_with_param = smu_v11_0_send_msg_with_param, 3239 .read_smc_arg = smu_v11_0_read_arg, 3240 .init_display_count = smu_v11_0_init_display_count, 3241 .set_allowed_mask = smu_v11_0_set_allowed_mask, 3242 .get_enabled_mask = smu_v11_0_get_enabled_mask, 3243 .notify_display_change = smu_v11_0_notify_display_change, 3244 .set_power_limit = smu_v11_0_set_power_limit, 3245 .get_current_clk_freq = smu_v11_0_get_current_clk_freq, 3246 .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, 3247 .start_thermal_control = smu_v11_0_start_thermal_control, 3248 .stop_thermal_control = smu_v11_0_stop_thermal_control, 3249 .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk, 3250 .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, 3251 .get_fan_control_mode = smu_v11_0_get_fan_control_mode, 3252 .set_fan_control_mode = smu_v11_0_set_fan_control_mode, 3253 .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, 3254 .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, 3255 .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, 3256 .gfx_off_control = smu_v11_0_gfx_off_control, 3257 .register_irq_handler = smu_v11_0_register_irq_handler, 3258 .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, 3259 .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, 3260 .baco_is_support= smu_v11_0_baco_is_support, 3261 .baco_get_state = smu_v11_0_baco_get_state, 3262 .baco_set_state = smu_v11_0_baco_set_state, 3263 .baco_enter = smu_v11_0_baco_enter, 3264 .baco_exit = smu_v11_0_baco_exit, 3265 .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, 3266 .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, 3267 .override_pcie_parameters = smu_v11_0_override_pcie_parameters, 3268 }; 3269 3270 void vega20_set_ppt_funcs(struct smu_context *smu) 3271 { 3272 smu->ppt_funcs = &vega20_ppt_funcs; 3273 } 3274