FILE
yellow_carp_ppt.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
1/* 2 * Copyright 2020 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24#define SWSMU_CODE_LAYER_L2 25 26#include "amdgpu.h" 27#include "amdgpu_smu.h" 28#include "smu_v13_0.h" 29#include "smu13_driver_if_yellow_carp.h" 30#include "yellow_carp_ppt.h" 31#include "smu_v13_0_1_ppsmc.h" 32#include "smu_v13_0_1_pmfw.h" 33#include "smu_cmn.h" 34 35/* 36 * DO NOT use these for err/warn/info/debug messages. 37 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 38 * They are more MGPU friendly. 39 */ 40#undef pr_err 41#undef pr_warn 42#undef pr_info 43#undef pr_debug 44 45#define regSMUIO_GFX_MISC_CNTL 0x00c5 46#define regSMUIO_GFX_MISC_CNTL_BASE_IDX 0 47#define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK 0x00000006L 48#define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT 0x1L 49 50#define SMU_13_0_8_UMD_PSTATE_GFXCLK 533 51#define SMU_13_0_8_UMD_PSTATE_SOCCLK 533 52#define SMU_13_0_8_UMD_PSTATE_FCLK 800 53 54#define SMU_13_0_1_UMD_PSTATE_GFXCLK 700 55#define SMU_13_0_1_UMD_PSTATE_SOCCLK 678 56#define SMU_13_0_1_UMD_PSTATE_FCLK 1800 57 58#define FEATURE_MASK(feature) (1ULL << feature) 59#define SMC_DPM_FEATURE ( \ 60 FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \ 61 FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \ 62 FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ 63 FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) | \ 64 FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) | \ 65 FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \ 66 FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT) | \ 67 FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \ 68 FEATURE_MASK(FEATURE_GFX_DPM_BIT)) 69 70static struct cmn2asic_msg_mapping yellow_carp_message_map[SMU_MSG_MAX_COUNT] = { 71 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), 72 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), 73 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), 74 MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 1), 75 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 1), 76 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 1), 77 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), 78 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1), 79 MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1), 80 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), 81 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), 82 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), 83 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), 84 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 1), 85 MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1), 86 MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 1), 87 MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 1), 88 MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1), 89 MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1), 90 MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 1), 91 MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), 92 MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1), 93 MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 1), 94 MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 1), 95 MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1), 96 MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 1), 97 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), 98 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1), 99 MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 1), 100 MSG_MAP(SetSoftMinSocclkByFreq, PPSMC_MSG_SetSoftMinSocclkByFreq, 1), 101}; 102 103static struct cmn2asic_mapping yellow_carp_feature_mask_map[SMU_FEATURE_COUNT] = { 104 FEA_MAP(CCLK_DPM), 105 FEA_MAP(FAN_CONTROLLER), 106 FEA_MAP(PPT), 107 FEA_MAP(TDC), 108 FEA_MAP(THERMAL), 109 FEA_MAP(ULV), 110 FEA_MAP(VCN_DPM), 111 FEA_MAP_REVERSE(FCLK), 112 FEA_MAP_REVERSE(SOCCLK), 113 FEA_MAP(LCLK_DPM), 114 FEA_MAP(SHUBCLK_DPM), 115 FEA_MAP(DCFCLK_DPM), 116 FEA_MAP_HALF_REVERSE(GFX), 117 FEA_MAP(DS_GFXCLK), 118 FEA_MAP(DS_SOCCLK), 119 FEA_MAP(DS_LCLK), 120 FEA_MAP(DS_DCFCLK), 121 FEA_MAP(DS_FCLK), 122 FEA_MAP(DS_MP1CLK), 123 FEA_MAP(DS_MP0CLK), 124 FEA_MAP(GFX_DEM), 125 FEA_MAP(PSI), 126 FEA_MAP(PROCHOT), 127 FEA_MAP(CPUOFF), 128 FEA_MAP(STAPM), 129 FEA_MAP(S0I3), 130 FEA_MAP(PERF_LIMIT), 131 FEA_MAP(CORE_DLDO), 132 FEA_MAP(RSMU_LOW_POWER), 133 FEA_MAP(SMN_LOW_POWER), 134 FEA_MAP(THM_LOW_POWER), 135 FEA_MAP(SMUIO_LOW_POWER), 136 FEA_MAP(MP1_LOW_POWER), 137 FEA_MAP(DS_VCN), 138 FEA_MAP(CPPC), 139 FEA_MAP(DF_CSTATES), 140 FEA_MAP(MSMU_LOW_POWER), 141 FEA_MAP(ATHUB_PG), 142}; 143 144static struct cmn2asic_mapping yellow_carp_table_map[SMU_TABLE_COUNT] = { 145 TAB_MAP_VALID(WATERMARKS), 146 TAB_MAP_VALID(SMU_METRICS), 147 TAB_MAP_VALID(CUSTOM_DPM), 148 TAB_MAP_VALID(DPMCLOCKS), 149}; 150 151static int yellow_carp_init_smc_tables(struct smu_context *smu) 152{ 153 struct smu_table_context *smu_table = &smu->smu_table; 154 struct smu_table *tables = smu_table->tables; 155 156 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), 157 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 158 SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), 159 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 160 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), 161 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); 162 163 smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); 164 if (!smu_table->clocks_table) 165 goto err0_out; 166 167 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 168 if (!smu_table->metrics_table) 169 goto err1_out; 170 smu_table->metrics_time = 0; 171 172 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); 173 if (!smu_table->watermarks_table) 174 goto err2_out; 175 176 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1); 177 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 178 if (!smu_table->gpu_metrics_table) 179 goto err3_out; 180 181 return 0; 182 183err3_out: 184 kfree(smu_table->watermarks_table); 185err2_out: 186 kfree(smu_table->metrics_table); 187err1_out: 188 kfree(smu_table->clocks_table); 189err0_out: 190 return -ENOMEM; 191} 192 193static int yellow_carp_fini_smc_tables(struct smu_context *smu) 194{ 195 struct smu_table_context *smu_table = &smu->smu_table; 196 197 kfree(smu_table->clocks_table); 198 smu_table->clocks_table = NULL; 199 200 kfree(smu_table->metrics_table); 201 smu_table->metrics_table = NULL; 202 203 kfree(smu_table->watermarks_table); 204 smu_table->watermarks_table = NULL; 205 206 kfree(smu_table->gpu_metrics_table); 207 smu_table->gpu_metrics_table = NULL; 208 209 return 0; 210} 211 212static int yellow_carp_system_features_control(struct smu_context *smu, bool en) 213{ 214 struct amdgpu_device *adev = smu->adev; 215 int ret = 0; 216 217 if (!en && !adev->in_s0ix) 218 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); 219 220 return ret; 221} 222 223static int yellow_carp_dpm_set_vcn_enable(struct smu_context *smu, 224 bool enable, 225 int inst) 226{ 227 int ret = 0; 228 229 /* vcn dpm on is a prerequisite for vcn power gate messages */ 230 if (enable) 231 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 232 0, NULL); 233 else 234 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 235 0, NULL); 236 237 return ret; 238} 239 240static int yellow_carp_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) 241{ 242 int ret = 0; 243 244 if (enable) 245 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 246 0, NULL); 247 else 248 ret = smu_cmn_send_smc_msg_with_param(smu, 249 SMU_MSG_PowerDownJpeg, 0, 250 NULL); 251 252 return ret; 253} 254 255 256static bool yellow_carp_is_dpm_running(struct smu_context *smu) 257{ 258 int ret = 0; 259 uint64_t feature_enabled; 260 261 ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); 262 263 if (ret) 264 return false; 265 266 return !!(feature_enabled & SMC_DPM_FEATURE); 267} 268 269static int yellow_carp_post_smu_init(struct smu_context *smu) 270{ 271 struct amdgpu_device *adev = smu->adev; 272 int ret = 0; 273 274 /* allow message will be sent after enable message on Yellow Carp*/ 275 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL); 276 if (ret) 277 dev_err(adev->dev, "Failed to Enable GfxOff!\n"); 278 return ret; 279} 280 281static int yellow_carp_mode_reset(struct smu_context *smu, int type) 282{ 283 int ret = 0; 284 285 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, type, NULL); 286 if (ret) 287 dev_err(smu->adev->dev, "Failed to mode reset!\n"); 288 289 return ret; 290} 291 292static int yellow_carp_mode2_reset(struct smu_context *smu) 293{ 294 return yellow_carp_mode_reset(smu, SMU_RESET_MODE_2); 295} 296 297 298static void yellow_carp_get_ss_power_percent(SmuMetrics_t *metrics, 299 uint32_t *apu_percent, uint32_t *dgpu_percent) 300{ 301 uint32_t apu_boost = 0; 302 uint32_t dgpu_boost = 0; 303 uint16_t apu_limit = 0; 304 uint16_t dgpu_limit = 0; 305 uint16_t apu_power = 0; 306 uint16_t dgpu_power = 0; 307 308 /* APU and dGPU power values are reported in milli Watts 309 * and STAPM power limits are in Watts */ 310 apu_power = metrics->ApuPower/1000; 311 apu_limit = metrics->StapmOpnLimit; 312 if (apu_power > apu_limit && apu_limit != 0) 313 apu_boost = ((apu_power - apu_limit) * 100) / apu_limit; 314 apu_boost = (apu_boost > 100) ? 100 : apu_boost; 315 316 dgpu_power = metrics->dGpuPower/1000; 317 if (metrics->StapmCurrentLimit > metrics->StapmOpnLimit) 318 dgpu_limit = metrics->StapmCurrentLimit - metrics->StapmOpnLimit; 319 if (dgpu_power > dgpu_limit && dgpu_limit != 0) 320 dgpu_boost = ((dgpu_power - dgpu_limit) * 100) / dgpu_limit; 321 dgpu_boost = (dgpu_boost > 100) ? 100 : dgpu_boost; 322 323 if (dgpu_boost >= apu_boost) 324 apu_boost = 0; 325 else 326 dgpu_boost = 0; 327 328 *apu_percent = apu_boost; 329 *dgpu_percent = dgpu_boost; 330 331} 332 333static int yellow_carp_get_smu_metrics_data(struct smu_context *smu, 334 MetricsMember_t member, 335 uint32_t *value) 336{ 337 struct smu_table_context *smu_table = &smu->smu_table; 338 339 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 340 int ret = 0; 341 uint32_t apu_percent = 0; 342 uint32_t dgpu_percent = 0; 343 344 ret = smu_cmn_get_metrics_table(smu, NULL, false); 345 if (ret) 346 return ret; 347 348 switch (member) { 349 case METRICS_AVERAGE_GFXCLK: 350 *value = metrics->GfxclkFrequency; 351 break; 352 case METRICS_AVERAGE_SOCCLK: 353 *value = metrics->SocclkFrequency; 354 break; 355 case METRICS_AVERAGE_VCLK: 356 *value = metrics->VclkFrequency; 357 break; 358 case METRICS_AVERAGE_DCLK: 359 *value = metrics->DclkFrequency; 360 break; 361 case METRICS_AVERAGE_UCLK: 362 *value = metrics->MemclkFrequency; 363 break; 364 case METRICS_AVERAGE_GFXACTIVITY: 365 *value = metrics->GfxActivity / 100; 366 break; 367 case METRICS_AVERAGE_VCNACTIVITY: 368 *value = metrics->UvdActivity / 100; 369 break; 370 case METRICS_CURR_SOCKETPOWER: 371 *value = (metrics->CurrentSocketPower << 8) / 1000; 372 break; 373 case METRICS_TEMPERATURE_EDGE: 374 *value = metrics->GfxTemperature / 100 * 375 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 376 break; 377 case METRICS_TEMPERATURE_HOTSPOT: 378 *value = metrics->SocTemperature / 100 * 379 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 380 break; 381 case METRICS_THROTTLER_STATUS: 382 *value = metrics->ThrottlerStatus; 383 break; 384 case METRICS_VOLTAGE_VDDGFX: 385 *value = metrics->Voltage[0]; 386 break; 387 case METRICS_VOLTAGE_VDDSOC: 388 *value = metrics->Voltage[1]; 389 break; 390 case METRICS_SS_APU_SHARE: 391 /* return the percentage of APU power boost 392 * with respect to APU's power limit. 393 */ 394 yellow_carp_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent); 395 *value = apu_percent; 396 break; 397 case METRICS_SS_DGPU_SHARE: 398 /* return the percentage of dGPU power boost 399 * with respect to dGPU's power limit. 400 */ 401 yellow_carp_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent); 402 *value = dgpu_percent; 403 break; 404 default: 405 *value = UINT_MAX; 406 break; 407 } 408 409 return ret; 410} 411 412static int yellow_carp_read_sensor(struct smu_context *smu, 413 enum amd_pp_sensors sensor, 414 void *data, uint32_t *size) 415{ 416 int ret = 0; 417 418 if (!data || !size) 419 return -EINVAL; 420 421 switch (sensor) { 422 case AMDGPU_PP_SENSOR_GPU_LOAD: 423 ret = yellow_carp_get_smu_metrics_data(smu, 424 METRICS_AVERAGE_GFXACTIVITY, 425 (uint32_t *)data); 426 *size = 4; 427 break; 428 case AMDGPU_PP_SENSOR_VCN_LOAD: 429 ret = yellow_carp_get_smu_metrics_data(smu, 430 METRICS_AVERAGE_VCNACTIVITY, 431 (uint32_t *)data); 432 *size = 4; 433 break; 434 case AMDGPU_PP_SENSOR_GPU_INPUT_POWER: 435 ret = yellow_carp_get_smu_metrics_data(smu, 436 METRICS_CURR_SOCKETPOWER, 437 (uint32_t *)data); 438 *size = 4; 439 break; 440 case AMDGPU_PP_SENSOR_EDGE_TEMP: 441 ret = yellow_carp_get_smu_metrics_data(smu, 442 METRICS_TEMPERATURE_EDGE, 443 (uint32_t *)data); 444 *size = 4; 445 break; 446 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 447 ret = yellow_carp_get_smu_metrics_data(smu, 448 METRICS_TEMPERATURE_HOTSPOT, 449 (uint32_t *)data); 450 *size = 4; 451 break; 452 case AMDGPU_PP_SENSOR_GFX_MCLK: 453 ret = yellow_carp_get_smu_metrics_data(smu, 454 METRICS_AVERAGE_UCLK, 455 (uint32_t *)data); 456 *(uint32_t *)data *= 100; 457 *size = 4; 458 break; 459 case AMDGPU_PP_SENSOR_GFX_SCLK: 460 ret = yellow_carp_get_smu_metrics_data(smu, 461 METRICS_AVERAGE_GFXCLK, 462 (uint32_t *)data); 463 *(uint32_t *)data *= 100; 464 *size = 4; 465 break; 466 case AMDGPU_PP_SENSOR_VDDGFX: 467 ret = yellow_carp_get_smu_metrics_data(smu, 468 METRICS_VOLTAGE_VDDGFX, 469 (uint32_t *)data); 470 *size = 4; 471 break; 472 case AMDGPU_PP_SENSOR_VDDNB: 473 ret = yellow_carp_get_smu_metrics_data(smu, 474 METRICS_VOLTAGE_VDDSOC, 475 (uint32_t *)data); 476 *size = 4; 477 break; 478 case AMDGPU_PP_SENSOR_SS_APU_SHARE: 479 ret = yellow_carp_get_smu_metrics_data(smu, 480 METRICS_SS_APU_SHARE, 481 (uint32_t *)data); 482 *size = 4; 483 break; 484 case AMDGPU_PP_SENSOR_SS_DGPU_SHARE: 485 ret = yellow_carp_get_smu_metrics_data(smu, 486 METRICS_SS_DGPU_SHARE, 487 (uint32_t *)data); 488 *size = 4; 489 break; 490 case AMDGPU_PP_SENSOR_GPU_AVG_POWER: 491 default: 492 ret = -EOPNOTSUPP; 493 break; 494 } 495 496 return ret; 497} 498 499static int yellow_carp_set_watermarks_table(struct smu_context *smu, 500 struct pp_smu_wm_range_sets *clock_ranges) 501{ 502 int i; 503 int ret = 0; 504 Watermarks_t *table = smu->smu_table.watermarks_table; 505 506 if (!table || !clock_ranges) 507 return -EINVAL; 508 509 if (clock_ranges) { 510 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || 511 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) 512 return -EINVAL; 513 514 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { 515 table->WatermarkRow[WM_DCFCLK][i].MinClock = 516 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; 517 table->WatermarkRow[WM_DCFCLK][i].MaxClock = 518 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; 519 table->WatermarkRow[WM_DCFCLK][i].MinMclk = 520 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; 521 table->WatermarkRow[WM_DCFCLK][i].MaxMclk = 522 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; 523 524 table->WatermarkRow[WM_DCFCLK][i].WmSetting = 525 clock_ranges->reader_wm_sets[i].wm_inst; 526 } 527 528 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { 529 table->WatermarkRow[WM_SOCCLK][i].MinClock = 530 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; 531 table->WatermarkRow[WM_SOCCLK][i].MaxClock = 532 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; 533 table->WatermarkRow[WM_SOCCLK][i].MinMclk = 534 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; 535 table->WatermarkRow[WM_SOCCLK][i].MaxMclk = 536 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; 537 538 table->WatermarkRow[WM_SOCCLK][i].WmSetting = 539 clock_ranges->writer_wm_sets[i].wm_inst; 540 } 541 542 smu->watermarks_bitmap |= WATERMARKS_EXIST; 543 } 544 545 /* pass data to smu controller */ 546 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && 547 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { 548 ret = smu_cmn_write_watermarks_table(smu); 549 if (ret) { 550 dev_err(smu->adev->dev, "Failed to update WMTABLE!"); 551 return ret; 552 } 553 smu->watermarks_bitmap |= WATERMARKS_LOADED; 554 } 555 556 return 0; 557} 558 559static ssize_t yellow_carp_get_gpu_metrics(struct smu_context *smu, 560 void **table) 561{ 562 struct smu_table_context *smu_table = &smu->smu_table; 563 struct gpu_metrics_v2_1 *gpu_metrics = 564 (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table; 565 SmuMetrics_t metrics; 566 int ret = 0; 567 568 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 569 if (ret) 570 return ret; 571 572 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1); 573 574 gpu_metrics->temperature_gfx = metrics.GfxTemperature; 575 gpu_metrics->temperature_soc = metrics.SocTemperature; 576 memcpy(&gpu_metrics->temperature_core[0], 577 &metrics.CoreTemperature[0], 578 sizeof(uint16_t) * 8); 579 gpu_metrics->temperature_l3[0] = metrics.L3Temperature; 580 581 gpu_metrics->average_gfx_activity = metrics.GfxActivity; 582 gpu_metrics->average_mm_activity = metrics.UvdActivity; 583 584 gpu_metrics->average_socket_power = metrics.CurrentSocketPower; 585 gpu_metrics->average_gfx_power = metrics.Power[0]; 586 gpu_metrics->average_soc_power = metrics.Power[1]; 587 memcpy(&gpu_metrics->average_core_power[0], 588 &metrics.CorePower[0], 589 sizeof(uint16_t) * 8); 590 591 gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; 592 gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; 593 gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency; 594 gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; 595 gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; 596 gpu_metrics->average_dclk_frequency = metrics.DclkFrequency; 597 598 memcpy(&gpu_metrics->current_coreclk[0], 599 &metrics.CoreFrequency[0], 600 sizeof(uint16_t) * 8); 601 gpu_metrics->current_l3clk[0] = metrics.L3Frequency; 602 603 gpu_metrics->throttle_status = metrics.ThrottlerStatus; 604 605 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 606 607 *table = (void *)gpu_metrics; 608 609 return sizeof(struct gpu_metrics_v2_1); 610} 611 612/** 613 * yellow_carp_get_gfxoff_status - get gfxoff status 614 * 615 * @smu: smu_context pointer 616 * 617 * This function will be used to get gfxoff status 618 * 619 * Returns 0=GFXOFF(default). 620 * Returns 1=Transition out of GFX State. 621 * Returns 2=Not in GFXOFF. 622 * Returns 3=Transition into GFXOFF. 623 */ 624static uint32_t yellow_carp_get_gfxoff_status(struct smu_context *smu) 625{ 626 uint32_t reg; 627 uint32_t gfxoff_status = 0; 628 struct amdgpu_device *adev = smu->adev; 629 630 reg = RREG32_SOC15(SMUIO, 0, regSMUIO_GFX_MISC_CNTL); 631 gfxoff_status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK) 632 >> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT; 633 634 return gfxoff_status; 635} 636 637static int yellow_carp_set_default_dpm_tables(struct smu_context *smu) 638{ 639 struct smu_table_context *smu_table = &smu->smu_table; 640 641 return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 642} 643 644static int yellow_carp_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 645 long input[], uint32_t size) 646{ 647 struct smu_dpm_context *smu_dpm = &(smu->smu_dpm); 648 int ret = 0; 649 650 /* Only allowed in manual mode */ 651 if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) 652 return -EINVAL; 653 654 switch (type) { 655 case PP_OD_EDIT_SCLK_VDDC_TABLE: 656 if (size != 2) { 657 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 658 return -EINVAL; 659 } 660 661 if (input[0] == 0) { 662 if (input[1] < smu->gfx_default_hard_min_freq) { 663 dev_warn(smu->adev->dev, 664 "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 665 input[1], smu->gfx_default_hard_min_freq); 666 return -EINVAL; 667 } 668 smu->gfx_actual_hard_min_freq = input[1]; 669 } else if (input[0] == 1) { 670 if (input[1] > smu->gfx_default_soft_max_freq) { 671 dev_warn(smu->adev->dev, 672 "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 673 input[1], smu->gfx_default_soft_max_freq); 674 return -EINVAL; 675 } 676 smu->gfx_actual_soft_max_freq = input[1]; 677 } else { 678 return -EINVAL; 679 } 680 break; 681 case PP_OD_RESTORE_DEFAULT_TABLE: 682 if (size != 0) { 683 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 684 return -EINVAL; 685 } else { 686 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 687 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 688 } 689 break; 690 case PP_OD_COMMIT_DPM_TABLE: 691 if (size != 0) { 692 dev_err(smu->adev->dev, "Input parameter number not correct\n"); 693 return -EINVAL; 694 } else { 695 if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 696 dev_err(smu->adev->dev, 697 "The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 698 smu->gfx_actual_hard_min_freq, 699 smu->gfx_actual_soft_max_freq); 700 return -EINVAL; 701 } 702 703 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 704 smu->gfx_actual_hard_min_freq, NULL); 705 if (ret) { 706 dev_err(smu->adev->dev, "Set hard min sclk failed!"); 707 return ret; 708 } 709 710 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 711 smu->gfx_actual_soft_max_freq, NULL); 712 if (ret) { 713 dev_err(smu->adev->dev, "Set soft max sclk failed!"); 714 return ret; 715 } 716 } 717 break; 718 default: 719 return -ENOSYS; 720 } 721 722 return ret; 723} 724 725static int yellow_carp_get_current_clk_freq(struct smu_context *smu, 726 enum smu_clk_type clk_type, 727 uint32_t *value) 728{ 729 MetricsMember_t member_type; 730 731 switch (clk_type) { 732 case SMU_SOCCLK: 733 member_type = METRICS_AVERAGE_SOCCLK; 734 break; 735 case SMU_VCLK: 736 member_type = METRICS_AVERAGE_VCLK; 737 break; 738 case SMU_DCLK: 739 member_type = METRICS_AVERAGE_DCLK; 740 break; 741 case SMU_MCLK: 742 member_type = METRICS_AVERAGE_UCLK; 743 break; 744 case SMU_FCLK: 745 return smu_cmn_send_smc_msg_with_param(smu, 746 SMU_MSG_GetFclkFrequency, 0, value); 747 case SMU_GFXCLK: 748 case SMU_SCLK: 749 return smu_cmn_send_smc_msg_with_param(smu, 750 SMU_MSG_GetGfxclkFrequency, 0, value); 751 break; 752 default: 753 return -EINVAL; 754 } 755 756 return yellow_carp_get_smu_metrics_data(smu, member_type, value); 757} 758 759static int yellow_carp_get_dpm_level_count(struct smu_context *smu, 760 enum smu_clk_type clk_type, 761 uint32_t *count) 762{ 763 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 764 765 switch (clk_type) { 766 case SMU_SOCCLK: 767 *count = clk_table->NumSocClkLevelsEnabled; 768 break; 769 case SMU_VCLK: 770 *count = clk_table->VcnClkLevelsEnabled; 771 break; 772 case SMU_DCLK: 773 *count = clk_table->VcnClkLevelsEnabled; 774 break; 775 case SMU_MCLK: 776 *count = clk_table->NumDfPstatesEnabled; 777 break; 778 case SMU_FCLK: 779 *count = clk_table->NumDfPstatesEnabled; 780 break; 781 default: 782 return -EINVAL; 783 } 784 785 return 0; 786} 787 788static int yellow_carp_get_dpm_freq_by_index(struct smu_context *smu, 789 enum smu_clk_type clk_type, 790 uint32_t dpm_level, 791 uint32_t *freq) 792{ 793 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 794 795 if (!clk_table || clk_type >= SMU_CLK_COUNT) 796 return -EINVAL; 797 798 switch (clk_type) { 799 case SMU_SOCCLK: 800 if (dpm_level >= clk_table->NumSocClkLevelsEnabled) 801 return -EINVAL; 802 *freq = clk_table->SocClocks[dpm_level]; 803 break; 804 case SMU_VCLK: 805 if (dpm_level >= clk_table->VcnClkLevelsEnabled) 806 return -EINVAL; 807 *freq = clk_table->VClocks[dpm_level]; 808 break; 809 case SMU_DCLK: 810 if (dpm_level >= clk_table->VcnClkLevelsEnabled) 811 return -EINVAL; 812 *freq = clk_table->DClocks[dpm_level]; 813 break; 814 case SMU_UCLK: 815 case SMU_MCLK: 816 if (dpm_level >= clk_table->NumDfPstatesEnabled) 817 return -EINVAL; 818 *freq = clk_table->DfPstateTable[dpm_level].MemClk; 819 break; 820 case SMU_FCLK: 821 if (dpm_level >= clk_table->NumDfPstatesEnabled) 822 return -EINVAL; 823 *freq = clk_table->DfPstateTable[dpm_level].FClk; 824 break; 825 default: 826 return -EINVAL; 827 } 828 829 return 0; 830} 831 832static bool yellow_carp_clk_dpm_is_enabled(struct smu_context *smu, 833 enum smu_clk_type clk_type) 834{ 835 enum smu_feature_mask feature_id = 0; 836 837 switch (clk_type) { 838 case SMU_MCLK: 839 case SMU_UCLK: 840 case SMU_FCLK: 841 feature_id = SMU_FEATURE_DPM_FCLK_BIT; 842 break; 843 case SMU_GFXCLK: 844 case SMU_SCLK: 845 feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; 846 break; 847 case SMU_SOCCLK: 848 feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; 849 break; 850 case SMU_VCLK: 851 case SMU_DCLK: 852 feature_id = SMU_FEATURE_VCN_DPM_BIT; 853 break; 854 default: 855 return true; 856 } 857 858 return smu_cmn_feature_is_enabled(smu, feature_id); 859} 860 861static int yellow_carp_get_dpm_ultimate_freq(struct smu_context *smu, 862 enum smu_clk_type clk_type, 863 uint32_t *min, 864 uint32_t *max) 865{ 866 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 867 uint32_t clock_limit; 868 uint32_t max_dpm_level, min_dpm_level; 869 int ret = 0; 870 871 if (!yellow_carp_clk_dpm_is_enabled(smu, clk_type)) { 872 ret = smu_v13_0_get_boot_freq_by_index(smu, clk_type, &clock_limit); 873 if (ret) 874 return ret; 875 876 /* clock in Mhz unit */ 877 if (min) 878 *min = clock_limit / 100; 879 if (max) 880 *max = clock_limit / 100; 881 882 return 0; 883 } 884 885 if (max) { 886 switch (clk_type) { 887 case SMU_GFXCLK: 888 case SMU_SCLK: 889 *max = clk_table->MaxGfxClk; 890 break; 891 case SMU_MCLK: 892 case SMU_UCLK: 893 case SMU_FCLK: 894 max_dpm_level = 0; 895 break; 896 case SMU_SOCCLK: 897 max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1; 898 break; 899 case SMU_VCLK: 900 case SMU_DCLK: 901 max_dpm_level = clk_table->VcnClkLevelsEnabled - 1; 902 break; 903 default: 904 ret = -EINVAL; 905 goto failed; 906 } 907 908 if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { 909 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); 910 if (ret) 911 goto failed; 912 } 913 } 914 915 if (min) { 916 switch (clk_type) { 917 case SMU_GFXCLK: 918 case SMU_SCLK: 919 *min = clk_table->MinGfxClk; 920 break; 921 case SMU_MCLK: 922 case SMU_UCLK: 923 case SMU_FCLK: 924 min_dpm_level = clk_table->NumDfPstatesEnabled - 1; 925 break; 926 case SMU_SOCCLK: 927 min_dpm_level = 0; 928 break; 929 case SMU_VCLK: 930 case SMU_DCLK: 931 min_dpm_level = 0; 932 break; 933 default: 934 ret = -EINVAL; 935 goto failed; 936 } 937 938 if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { 939 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); 940 if (ret) 941 goto failed; 942 } 943 } 944 945failed: 946 return ret; 947} 948 949static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu, 950 enum smu_clk_type clk_type, 951 uint32_t min, 952 uint32_t max, 953 bool automatic) 954{ 955 enum smu_message_type msg_set_min, msg_set_max; 956 uint32_t min_clk = min; 957 uint32_t max_clk = max; 958 959 int ret = 0; 960 961 if (!yellow_carp_clk_dpm_is_enabled(smu, clk_type)) 962 return -EINVAL; 963 964 switch (clk_type) { 965 case SMU_GFXCLK: 966 case SMU_SCLK: 967 msg_set_min = SMU_MSG_SetHardMinGfxClk; 968 msg_set_max = SMU_MSG_SetSoftMaxGfxClk; 969 break; 970 case SMU_FCLK: 971 msg_set_min = SMU_MSG_SetHardMinFclkByFreq; 972 msg_set_max = SMU_MSG_SetSoftMaxFclkByFreq; 973 break; 974 case SMU_SOCCLK: 975 msg_set_min = SMU_MSG_SetHardMinSocclkByFreq; 976 msg_set_max = SMU_MSG_SetSoftMaxSocclkByFreq; 977 break; 978 case SMU_VCLK: 979 case SMU_DCLK: 980 msg_set_min = SMU_MSG_SetHardMinVcn; 981 msg_set_max = SMU_MSG_SetSoftMaxVcn; 982 break; 983 default: 984 return -EINVAL; 985 } 986 987 if (clk_type == SMU_VCLK) { 988 min_clk = min << SMU_13_VCLK_SHIFT; 989 max_clk = max << SMU_13_VCLK_SHIFT; 990 } 991 992 ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min_clk, NULL); 993 994 if (ret) 995 goto out; 996 997 ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max_clk, NULL); 998 if (ret) 999 goto out; 1000 1001out: 1002 return ret; 1003} 1004 1005static uint32_t yellow_carp_get_umd_pstate_clk_default(struct smu_context *smu, 1006 enum smu_clk_type clk_type) 1007{ 1008 uint32_t clk_limit = 0; 1009 struct amdgpu_device *adev = smu->adev; 1010 1011 switch (clk_type) { 1012 case SMU_GFXCLK: 1013 case SMU_SCLK: 1014 if ((amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 8)) 1015 clk_limit = SMU_13_0_8_UMD_PSTATE_GFXCLK; 1016 if ((amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 1) || 1017 (amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 3)) 1018 clk_limit = SMU_13_0_1_UMD_PSTATE_GFXCLK; 1019 break; 1020 case SMU_SOCCLK: 1021 if ((amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 8)) 1022 clk_limit = SMU_13_0_8_UMD_PSTATE_SOCCLK; 1023 if ((amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 1) || 1024 (amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 3)) 1025 clk_limit = SMU_13_0_1_UMD_PSTATE_SOCCLK; 1026 break; 1027 case SMU_FCLK: 1028 if ((amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 8)) 1029 clk_limit = SMU_13_0_8_UMD_PSTATE_FCLK; 1030 if ((amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 1) || 1031 (amdgpu_ip_version(adev, MP1_HWIP, 0)) == IP_VERSION(13, 0, 3)) 1032 clk_limit = SMU_13_0_1_UMD_PSTATE_FCLK; 1033 break; 1034 default: 1035 break; 1036 } 1037 1038 return clk_limit; 1039} 1040 1041static int yellow_carp_print_clk_levels(struct smu_context *smu, 1042 enum smu_clk_type clk_type, char *buf) 1043{ 1044 int i, idx, size = 0, ret = 0, start_offset = 0; 1045 uint32_t cur_value = 0, value = 0, count = 0; 1046 uint32_t min, max; 1047 uint32_t clk_limit = 0; 1048 1049 smu_cmn_get_sysfs_buf(&buf, &size); 1050 start_offset = size; 1051 1052 switch (clk_type) { 1053 case SMU_OD_SCLK: 1054 size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); 1055 size += sysfs_emit_at(buf, size, "0: %10uMhz\n", 1056 (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); 1057 size += sysfs_emit_at(buf, size, "1: %10uMhz\n", 1058 (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); 1059 break; 1060 case SMU_OD_RANGE: 1061 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 1062 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", 1063 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); 1064 break; 1065 case SMU_SOCCLK: 1066 case SMU_VCLK: 1067 case SMU_DCLK: 1068 case SMU_MCLK: 1069 case SMU_FCLK: 1070 ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value); 1071 if (ret) 1072 goto print_clk_out; 1073 1074 ret = yellow_carp_get_dpm_level_count(smu, clk_type, &count); 1075 if (ret) 1076 goto print_clk_out; 1077 1078 for (i = 0; i < count; i++) { 1079 idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i; 1080 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, idx, &value); 1081 if (ret) 1082 goto print_clk_out; 1083 1084 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value, 1085 cur_value == value ? "*" : ""); 1086 } 1087 break; 1088 case SMU_GFXCLK: 1089 case SMU_SCLK: 1090 clk_limit = yellow_carp_get_umd_pstate_clk_default(smu, clk_type); 1091 ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value); 1092 if (ret) 1093 goto print_clk_out; 1094 min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq; 1095 max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq; 1096 if (cur_value == max) 1097 i = 2; 1098 else if (cur_value == min) 1099 i = 0; 1100 else 1101 i = 1; 1102 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min, 1103 i == 0 ? "*" : ""); 1104 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 1105 i == 1 ? cur_value : clk_limit, 1106 i == 1 ? "*" : ""); 1107 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max, 1108 i == 2 ? "*" : ""); 1109 break; 1110 default: 1111 break; 1112 } 1113 1114print_clk_out: 1115 return size - start_offset; 1116} 1117 1118static int yellow_carp_force_clk_levels(struct smu_context *smu, 1119 enum smu_clk_type clk_type, uint32_t mask) 1120{ 1121 uint32_t soft_min_level = 0, soft_max_level = 0; 1122 uint32_t min_freq = 0, max_freq = 0; 1123 int ret = 0; 1124 1125 soft_min_level = mask ? (ffs(mask) - 1) : 0; 1126 soft_max_level = mask ? (fls(mask) - 1) : 0; 1127 1128 switch (clk_type) { 1129 case SMU_SOCCLK: 1130 case SMU_FCLK: 1131 case SMU_VCLK: 1132 case SMU_DCLK: 1133 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); 1134 if (ret) 1135 goto force_level_out; 1136 1137 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); 1138 if (ret) 1139 goto force_level_out; 1140 1141 ret = yellow_carp_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false); 1142 if (ret) 1143 goto force_level_out; 1144 break; 1145 default: 1146 ret = -EINVAL; 1147 break; 1148 } 1149 1150force_level_out: 1151 return ret; 1152} 1153 1154static int yellow_carp_get_dpm_profile_freq(struct smu_context *smu, 1155 enum amd_dpm_forced_level level, 1156 enum smu_clk_type clk_type, 1157 uint32_t *min_clk, 1158 uint32_t *max_clk) 1159{ 1160 int ret = 0; 1161 uint32_t clk_limit = 0; 1162 1163 clk_limit = yellow_carp_get_umd_pstate_clk_default(smu, clk_type); 1164 1165 switch (clk_type) { 1166 case SMU_GFXCLK: 1167 case SMU_SCLK: 1168 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 1169 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &clk_limit); 1170 else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) 1171 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &clk_limit, NULL); 1172 break; 1173 case SMU_SOCCLK: 1174 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 1175 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit); 1176 break; 1177 case SMU_FCLK: 1178 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 1179 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit); 1180 else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) 1181 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &clk_limit, NULL); 1182 break; 1183 case SMU_VCLK: 1184 yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &clk_limit); 1185 break; 1186 case SMU_DCLK: 1187 yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &clk_limit); 1188 break; 1189 default: 1190 ret = -EINVAL; 1191 break; 1192 } 1193 *min_clk = *max_clk = clk_limit; 1194 return ret; 1195} 1196 1197static int yellow_carp_set_performance_level(struct smu_context *smu, 1198 enum amd_dpm_forced_level level) 1199{ 1200 struct amdgpu_device *adev = smu->adev; 1201 uint32_t sclk_min = 0, sclk_max = 0; 1202 uint32_t fclk_min = 0, fclk_max = 0; 1203 uint32_t socclk_min = 0, socclk_max = 0; 1204 uint32_t vclk_min = 0, vclk_max = 0; 1205 uint32_t dclk_min = 0, dclk_max = 0; 1206 1207 int ret = 0; 1208 1209 switch (level) { 1210 case AMD_DPM_FORCED_LEVEL_HIGH: 1211 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max); 1212 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max); 1213 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max); 1214 yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, NULL, &vclk_max); 1215 yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, NULL, &dclk_max); 1216 sclk_min = sclk_max; 1217 fclk_min = fclk_max; 1218 socclk_min = socclk_max; 1219 vclk_min = vclk_max; 1220 dclk_min = dclk_max; 1221 break; 1222 case AMD_DPM_FORCED_LEVEL_LOW: 1223 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL); 1224 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL); 1225 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL); 1226 yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, NULL); 1227 yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, NULL); 1228 sclk_max = sclk_min; 1229 fclk_max = fclk_min; 1230 socclk_max = socclk_min; 1231 vclk_max = vclk_min; 1232 dclk_max = dclk_min; 1233 break; 1234 case AMD_DPM_FORCED_LEVEL_AUTO: 1235 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max); 1236 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max); 1237 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max); 1238 yellow_carp_get_dpm_ultimate_freq(smu, SMU_VCLK, &vclk_min, &vclk_max); 1239 yellow_carp_get_dpm_ultimate_freq(smu, SMU_DCLK, &dclk_min, &dclk_max); 1240 break; 1241 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 1242 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 1243 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 1244 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 1245 yellow_carp_get_dpm_profile_freq(smu, level, SMU_SCLK, &sclk_min, &sclk_max); 1246 yellow_carp_get_dpm_profile_freq(smu, level, SMU_FCLK, &fclk_min, &fclk_max); 1247 yellow_carp_get_dpm_profile_freq(smu, level, SMU_SOCCLK, &socclk_min, &socclk_max); 1248 yellow_carp_get_dpm_profile_freq(smu, level, SMU_VCLK, &vclk_min, &vclk_max); 1249 yellow_carp_get_dpm_profile_freq(smu, level, SMU_DCLK, &dclk_min, &dclk_max); 1250 break; 1251 case AMD_DPM_FORCED_LEVEL_MANUAL: 1252 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 1253 return 0; 1254 default: 1255 dev_err(adev->dev, "Invalid performance level %d\n", level); 1256 return -EINVAL; 1257 } 1258 1259 if (sclk_min && sclk_max) { 1260 ret = yellow_carp_set_soft_freq_limited_range(smu, 1261 SMU_SCLK, 1262 sclk_min, 1263 sclk_max, 1264 false); 1265 if (ret) 1266 return ret; 1267 1268 smu->gfx_actual_hard_min_freq = sclk_min; 1269 smu->gfx_actual_soft_max_freq = sclk_max; 1270 } 1271 1272 if (fclk_min && fclk_max) { 1273 ret = yellow_carp_set_soft_freq_limited_range(smu, 1274 SMU_FCLK, 1275 fclk_min, 1276 fclk_max, 1277 false); 1278 if (ret) 1279 return ret; 1280 } 1281 1282 if (socclk_min && socclk_max) { 1283 ret = yellow_carp_set_soft_freq_limited_range(smu, 1284 SMU_SOCCLK, 1285 socclk_min, 1286 socclk_max, 1287 false); 1288 if (ret) 1289 return ret; 1290 } 1291 1292 if (vclk_min && vclk_max) { 1293 ret = yellow_carp_set_soft_freq_limited_range(smu, 1294 SMU_VCLK, 1295 vclk_min, 1296 vclk_max, 1297 false); 1298 if (ret) 1299 return ret; 1300 } 1301 1302 if (dclk_min && dclk_max) { 1303 ret = yellow_carp_set_soft_freq_limited_range(smu, 1304 SMU_DCLK, 1305 dclk_min, 1306 dclk_max, 1307 false); 1308 if (ret) 1309 return ret; 1310 } 1311 1312 return ret; 1313} 1314 1315static int yellow_carp_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 1316{ 1317 DpmClocks_t *clk_table = smu->smu_table.clocks_table; 1318 1319 smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 1320 smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 1321 smu->gfx_actual_hard_min_freq = 0; 1322 smu->gfx_actual_soft_max_freq = 0; 1323 1324 return 0; 1325} 1326 1327static const struct pptable_funcs yellow_carp_ppt_funcs = { 1328 .check_fw_status = smu_v13_0_check_fw_status, 1329 .check_fw_version = smu_v13_0_check_fw_version, 1330 .init_smc_tables = yellow_carp_init_smc_tables, 1331 .fini_smc_tables = yellow_carp_fini_smc_tables, 1332 .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values, 1333 .system_features_control = yellow_carp_system_features_control, 1334 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 1335 .send_smc_msg = smu_cmn_send_smc_msg, 1336 .dpm_set_vcn_enable = yellow_carp_dpm_set_vcn_enable, 1337 .dpm_set_jpeg_enable = yellow_carp_dpm_set_jpeg_enable, 1338 .set_default_dpm_table = yellow_carp_set_default_dpm_tables, 1339 .read_sensor = yellow_carp_read_sensor, 1340 .is_dpm_running = yellow_carp_is_dpm_running, 1341 .set_watermarks_table = yellow_carp_set_watermarks_table, 1342 .get_gpu_metrics = yellow_carp_get_gpu_metrics, 1343 .get_enabled_mask = smu_cmn_get_enabled_mask, 1344 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, 1345 .set_driver_table_location = smu_v13_0_set_driver_table_location, 1346 .gfx_off_control = smu_v13_0_gfx_off_control, 1347 .get_gfx_off_status = yellow_carp_get_gfxoff_status, 1348 .post_init = yellow_carp_post_smu_init, 1349 .mode2_reset = yellow_carp_mode2_reset, 1350 .get_dpm_ultimate_freq = yellow_carp_get_dpm_ultimate_freq, 1351 .od_edit_dpm_table = yellow_carp_od_edit_dpm_table, 1352 .print_clk_levels = yellow_carp_print_clk_levels, 1353 .force_clk_levels = yellow_carp_force_clk_levels, 1354 .set_performance_level = yellow_carp_set_performance_level, 1355 .set_fine_grain_gfx_freq_parameters = yellow_carp_set_fine_grain_gfx_freq_parameters, 1356}; 1357 1358void yellow_carp_set_ppt_funcs(struct smu_context *smu) 1359{ 1360 smu->ppt_funcs = &yellow_carp_ppt_funcs; 1361 smu->message_map = yellow_carp_message_map; 1362 smu->feature_map = yellow_carp_feature_mask_map; 1363 smu->table_map = yellow_carp_table_map; 1364 smu->is_apu = true; 1365 smu->smc_driver_if_version = SMU13_YELLOW_CARP_DRIVER_IF_VERSION; 1366 smu_v13_0_set_smu_mailbox_registers(smu); 1367}
~/
Read-only file preview.