0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #define SWSMU_CODE_LAYER_L2
0025
0026 #include "amdgpu.h"
0027 #include "amdgpu_smu.h"
0028 #include "smu_v13_0.h"
0029 #include "smu13_driver_if_yellow_carp.h"
0030 #include "yellow_carp_ppt.h"
0031 #include "smu_v13_0_1_ppsmc.h"
0032 #include "smu_v13_0_1_pmfw.h"
0033 #include "smu_cmn.h"
0034
0035
0036
0037
0038
0039
0040 #undef pr_err
0041 #undef pr_warn
0042 #undef pr_info
0043 #undef pr_debug
0044
0045 #define regSMUIO_GFX_MISC_CNTL 0x00c5
0046 #define regSMUIO_GFX_MISC_CNTL_BASE_IDX 0
0047 #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK 0x00000006L
0048 #define SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT 0x1L
0049
0050 #define FEATURE_MASK(feature) (1ULL << feature)
0051 #define SMC_DPM_FEATURE ( \
0052 FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
0053 FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \
0054 FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \
0055 FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) | \
0056 FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) | \
0057 FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \
0058 FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT) | \
0059 FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
0060 FEATURE_MASK(FEATURE_GFX_DPM_BIT))
0061
0062 static struct cmn2asic_msg_mapping yellow_carp_message_map[SMU_MSG_MAX_COUNT] = {
0063 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
0064 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
0065 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
0066 MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 1),
0067 MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 1),
0068 MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 1),
0069 MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1),
0070 MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1),
0071 MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1),
0072 MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1),
0073 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
0074 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
0075 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1),
0076 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 1),
0077 MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1),
0078 MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 1),
0079 MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 1),
0080 MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1),
0081 MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1),
0082 MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 1),
0083 MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1),
0084 MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1),
0085 MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 1),
0086 MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 1),
0087 MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1),
0088 MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 1),
0089 MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1),
0090 MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1),
0091 MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 1),
0092 MSG_MAP(SetSoftMinSocclkByFreq, PPSMC_MSG_SetSoftMinSocclkByFreq, 1),
0093 };
0094
0095 static struct cmn2asic_mapping yellow_carp_feature_mask_map[SMU_FEATURE_COUNT] = {
0096 FEA_MAP(CCLK_DPM),
0097 FEA_MAP(FAN_CONTROLLER),
0098 FEA_MAP(PPT),
0099 FEA_MAP(TDC),
0100 FEA_MAP(THERMAL),
0101 FEA_MAP(ULV),
0102 FEA_MAP(VCN_DPM),
0103 FEA_MAP_REVERSE(FCLK),
0104 FEA_MAP_REVERSE(SOCCLK),
0105 FEA_MAP(LCLK_DPM),
0106 FEA_MAP(SHUBCLK_DPM),
0107 FEA_MAP(DCFCLK_DPM),
0108 FEA_MAP_HALF_REVERSE(GFX),
0109 FEA_MAP(DS_GFXCLK),
0110 FEA_MAP(DS_SOCCLK),
0111 FEA_MAP(DS_LCLK),
0112 FEA_MAP(DS_DCFCLK),
0113 FEA_MAP(DS_FCLK),
0114 FEA_MAP(DS_MP1CLK),
0115 FEA_MAP(DS_MP0CLK),
0116 FEA_MAP(GFX_DEM),
0117 FEA_MAP(PSI),
0118 FEA_MAP(PROCHOT),
0119 FEA_MAP(CPUOFF),
0120 FEA_MAP(STAPM),
0121 FEA_MAP(S0I3),
0122 FEA_MAP(PERF_LIMIT),
0123 FEA_MAP(CORE_DLDO),
0124 FEA_MAP(RSMU_LOW_POWER),
0125 FEA_MAP(SMN_LOW_POWER),
0126 FEA_MAP(THM_LOW_POWER),
0127 FEA_MAP(SMUIO_LOW_POWER),
0128 FEA_MAP(MP1_LOW_POWER),
0129 FEA_MAP(DS_VCN),
0130 FEA_MAP(CPPC),
0131 FEA_MAP(DF_CSTATES),
0132 FEA_MAP(MSMU_LOW_POWER),
0133 FEA_MAP(ATHUB_PG),
0134 };
0135
0136 static struct cmn2asic_mapping yellow_carp_table_map[SMU_TABLE_COUNT] = {
0137 TAB_MAP_VALID(WATERMARKS),
0138 TAB_MAP_VALID(SMU_METRICS),
0139 TAB_MAP_VALID(CUSTOM_DPM),
0140 TAB_MAP_VALID(DPMCLOCKS),
0141 };
0142
0143 static int yellow_carp_init_smc_tables(struct smu_context *smu)
0144 {
0145 struct smu_table_context *smu_table = &smu->smu_table;
0146 struct smu_table *tables = smu_table->tables;
0147
0148 SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
0149 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
0150 SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
0151 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
0152 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
0153 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
0154
0155 smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
0156 if (!smu_table->clocks_table)
0157 goto err0_out;
0158
0159 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
0160 if (!smu_table->metrics_table)
0161 goto err1_out;
0162 smu_table->metrics_time = 0;
0163
0164 smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
0165 if (!smu_table->watermarks_table)
0166 goto err2_out;
0167
0168 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1);
0169 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
0170 if (!smu_table->gpu_metrics_table)
0171 goto err3_out;
0172
0173 return 0;
0174
0175 err3_out:
0176 kfree(smu_table->watermarks_table);
0177 err2_out:
0178 kfree(smu_table->metrics_table);
0179 err1_out:
0180 kfree(smu_table->clocks_table);
0181 err0_out:
0182 return -ENOMEM;
0183 }
0184
0185 static int yellow_carp_fini_smc_tables(struct smu_context *smu)
0186 {
0187 struct smu_table_context *smu_table = &smu->smu_table;
0188
0189 kfree(smu_table->clocks_table);
0190 smu_table->clocks_table = NULL;
0191
0192 kfree(smu_table->metrics_table);
0193 smu_table->metrics_table = NULL;
0194
0195 kfree(smu_table->watermarks_table);
0196 smu_table->watermarks_table = NULL;
0197
0198 kfree(smu_table->gpu_metrics_table);
0199 smu_table->gpu_metrics_table = NULL;
0200
0201 return 0;
0202 }
0203
0204 static int yellow_carp_system_features_control(struct smu_context *smu, bool en)
0205 {
0206 struct amdgpu_device *adev = smu->adev;
0207 int ret = 0;
0208
0209 if (!en && !adev->in_s0ix)
0210 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
0211
0212 return ret;
0213 }
0214
0215 static int yellow_carp_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
0216 {
0217 int ret = 0;
0218
0219
0220 if (enable)
0221 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn,
0222 0, NULL);
0223 else
0224 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn,
0225 0, NULL);
0226
0227 return ret;
0228 }
0229
0230 static int yellow_carp_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
0231 {
0232 int ret = 0;
0233
0234 if (enable)
0235 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg,
0236 0, NULL);
0237 else
0238 ret = smu_cmn_send_smc_msg_with_param(smu,
0239 SMU_MSG_PowerDownJpeg, 0,
0240 NULL);
0241
0242 return ret;
0243 }
0244
0245
0246 static bool yellow_carp_is_dpm_running(struct smu_context *smu)
0247 {
0248 int ret = 0;
0249 uint64_t feature_enabled;
0250
0251 ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
0252
0253 if (ret)
0254 return false;
0255
0256 return !!(feature_enabled & SMC_DPM_FEATURE);
0257 }
0258
0259 static int yellow_carp_post_smu_init(struct smu_context *smu)
0260 {
0261 struct amdgpu_device *adev = smu->adev;
0262 int ret = 0;
0263
0264
0265 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
0266 if (ret)
0267 dev_err(adev->dev, "Failed to Enable GfxOff!\n");
0268 return ret;
0269 }
0270
0271 static int yellow_carp_mode_reset(struct smu_context *smu, int type)
0272 {
0273 int ret = 0;
0274
0275 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, type, NULL);
0276 if (ret)
0277 dev_err(smu->adev->dev, "Failed to mode reset!\n");
0278
0279 return ret;
0280 }
0281
0282 static int yellow_carp_mode2_reset(struct smu_context *smu)
0283 {
0284 return yellow_carp_mode_reset(smu, SMU_RESET_MODE_2);
0285 }
0286
0287
0288 static void yellow_carp_get_ss_power_percent(SmuMetrics_t *metrics,
0289 uint32_t *apu_percent, uint32_t *dgpu_percent)
0290 {
0291 uint32_t apu_boost = 0;
0292 uint32_t dgpu_boost = 0;
0293 uint16_t apu_limit = 0;
0294 uint16_t dgpu_limit = 0;
0295 uint16_t apu_power = 0;
0296 uint16_t dgpu_power = 0;
0297
0298
0299
0300 apu_power = metrics->ApuPower/1000;
0301 apu_limit = metrics->StapmOpnLimit;
0302 if (apu_power > apu_limit && apu_limit != 0)
0303 apu_boost = ((apu_power - apu_limit) * 100) / apu_limit;
0304 apu_boost = (apu_boost > 100) ? 100 : apu_boost;
0305
0306 dgpu_power = metrics->dGpuPower/1000;
0307 if (metrics->StapmCurrentLimit > metrics->StapmOpnLimit)
0308 dgpu_limit = metrics->StapmCurrentLimit - metrics->StapmOpnLimit;
0309 if (dgpu_power > dgpu_limit && dgpu_limit != 0)
0310 dgpu_boost = ((dgpu_power - dgpu_limit) * 100) / dgpu_limit;
0311 dgpu_boost = (dgpu_boost > 100) ? 100 : dgpu_boost;
0312
0313 if (dgpu_boost >= apu_boost)
0314 apu_boost = 0;
0315 else
0316 dgpu_boost = 0;
0317
0318 *apu_percent = apu_boost;
0319 *dgpu_percent = dgpu_boost;
0320
0321 }
0322
0323 static int yellow_carp_get_smu_metrics_data(struct smu_context *smu,
0324 MetricsMember_t member,
0325 uint32_t *value)
0326 {
0327 struct smu_table_context *smu_table = &smu->smu_table;
0328
0329 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
0330 int ret = 0;
0331 uint32_t apu_percent = 0;
0332 uint32_t dgpu_percent = 0;
0333
0334 ret = smu_cmn_get_metrics_table(smu, NULL, false);
0335 if (ret)
0336 return ret;
0337
0338 switch (member) {
0339 case METRICS_AVERAGE_GFXCLK:
0340 *value = metrics->GfxclkFrequency;
0341 break;
0342 case METRICS_AVERAGE_SOCCLK:
0343 *value = metrics->SocclkFrequency;
0344 break;
0345 case METRICS_AVERAGE_VCLK:
0346 *value = metrics->VclkFrequency;
0347 break;
0348 case METRICS_AVERAGE_DCLK:
0349 *value = metrics->DclkFrequency;
0350 break;
0351 case METRICS_AVERAGE_UCLK:
0352 *value = metrics->MemclkFrequency;
0353 break;
0354 case METRICS_AVERAGE_GFXACTIVITY:
0355 *value = metrics->GfxActivity / 100;
0356 break;
0357 case METRICS_AVERAGE_VCNACTIVITY:
0358 *value = metrics->UvdActivity;
0359 break;
0360 case METRICS_AVERAGE_SOCKETPOWER:
0361 *value = (metrics->CurrentSocketPower << 8) / 1000;
0362 break;
0363 case METRICS_TEMPERATURE_EDGE:
0364 *value = metrics->GfxTemperature / 100 *
0365 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
0366 break;
0367 case METRICS_TEMPERATURE_HOTSPOT:
0368 *value = metrics->SocTemperature / 100 *
0369 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
0370 break;
0371 case METRICS_THROTTLER_STATUS:
0372 *value = metrics->ThrottlerStatus;
0373 break;
0374 case METRICS_VOLTAGE_VDDGFX:
0375 *value = metrics->Voltage[0];
0376 break;
0377 case METRICS_VOLTAGE_VDDSOC:
0378 *value = metrics->Voltage[1];
0379 break;
0380 case METRICS_SS_APU_SHARE:
0381
0382
0383
0384 yellow_carp_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
0385 *value = apu_percent;
0386 break;
0387 case METRICS_SS_DGPU_SHARE:
0388
0389
0390
0391 yellow_carp_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
0392 *value = dgpu_percent;
0393 break;
0394 default:
0395 *value = UINT_MAX;
0396 break;
0397 }
0398
0399 return ret;
0400 }
0401
0402 static int yellow_carp_read_sensor(struct smu_context *smu,
0403 enum amd_pp_sensors sensor,
0404 void *data, uint32_t *size)
0405 {
0406 int ret = 0;
0407
0408 if (!data || !size)
0409 return -EINVAL;
0410
0411 switch (sensor) {
0412 case AMDGPU_PP_SENSOR_GPU_LOAD:
0413 ret = yellow_carp_get_smu_metrics_data(smu,
0414 METRICS_AVERAGE_GFXACTIVITY,
0415 (uint32_t *)data);
0416 *size = 4;
0417 break;
0418 case AMDGPU_PP_SENSOR_GPU_POWER:
0419 ret = yellow_carp_get_smu_metrics_data(smu,
0420 METRICS_AVERAGE_SOCKETPOWER,
0421 (uint32_t *)data);
0422 *size = 4;
0423 break;
0424 case AMDGPU_PP_SENSOR_EDGE_TEMP:
0425 ret = yellow_carp_get_smu_metrics_data(smu,
0426 METRICS_TEMPERATURE_EDGE,
0427 (uint32_t *)data);
0428 *size = 4;
0429 break;
0430 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
0431 ret = yellow_carp_get_smu_metrics_data(smu,
0432 METRICS_TEMPERATURE_HOTSPOT,
0433 (uint32_t *)data);
0434 *size = 4;
0435 break;
0436 case AMDGPU_PP_SENSOR_GFX_MCLK:
0437 ret = yellow_carp_get_smu_metrics_data(smu,
0438 METRICS_AVERAGE_UCLK,
0439 (uint32_t *)data);
0440 *(uint32_t *)data *= 100;
0441 *size = 4;
0442 break;
0443 case AMDGPU_PP_SENSOR_GFX_SCLK:
0444 ret = yellow_carp_get_smu_metrics_data(smu,
0445 METRICS_AVERAGE_GFXCLK,
0446 (uint32_t *)data);
0447 *(uint32_t *)data *= 100;
0448 *size = 4;
0449 break;
0450 case AMDGPU_PP_SENSOR_VDDGFX:
0451 ret = yellow_carp_get_smu_metrics_data(smu,
0452 METRICS_VOLTAGE_VDDGFX,
0453 (uint32_t *)data);
0454 *size = 4;
0455 break;
0456 case AMDGPU_PP_SENSOR_VDDNB:
0457 ret = yellow_carp_get_smu_metrics_data(smu,
0458 METRICS_VOLTAGE_VDDSOC,
0459 (uint32_t *)data);
0460 *size = 4;
0461 break;
0462 case AMDGPU_PP_SENSOR_SS_APU_SHARE:
0463 ret = yellow_carp_get_smu_metrics_data(smu,
0464 METRICS_SS_APU_SHARE,
0465 (uint32_t *)data);
0466 *size = 4;
0467 break;
0468 case AMDGPU_PP_SENSOR_SS_DGPU_SHARE:
0469 ret = yellow_carp_get_smu_metrics_data(smu,
0470 METRICS_SS_DGPU_SHARE,
0471 (uint32_t *)data);
0472 *size = 4;
0473 break;
0474 default:
0475 ret = -EOPNOTSUPP;
0476 break;
0477 }
0478
0479 return ret;
0480 }
0481
0482 static int yellow_carp_set_watermarks_table(struct smu_context *smu,
0483 struct pp_smu_wm_range_sets *clock_ranges)
0484 {
0485 int i;
0486 int ret = 0;
0487 Watermarks_t *table = smu->smu_table.watermarks_table;
0488
0489 if (!table || !clock_ranges)
0490 return -EINVAL;
0491
0492 if (clock_ranges) {
0493 if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
0494 clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
0495 return -EINVAL;
0496
0497 for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
0498 table->WatermarkRow[WM_DCFCLK][i].MinClock =
0499 clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
0500 table->WatermarkRow[WM_DCFCLK][i].MaxClock =
0501 clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
0502 table->WatermarkRow[WM_DCFCLK][i].MinMclk =
0503 clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
0504 table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
0505 clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
0506
0507 table->WatermarkRow[WM_DCFCLK][i].WmSetting =
0508 clock_ranges->reader_wm_sets[i].wm_inst;
0509 }
0510
0511 for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
0512 table->WatermarkRow[WM_SOCCLK][i].MinClock =
0513 clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
0514 table->WatermarkRow[WM_SOCCLK][i].MaxClock =
0515 clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
0516 table->WatermarkRow[WM_SOCCLK][i].MinMclk =
0517 clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
0518 table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
0519 clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
0520
0521 table->WatermarkRow[WM_SOCCLK][i].WmSetting =
0522 clock_ranges->writer_wm_sets[i].wm_inst;
0523 }
0524
0525 smu->watermarks_bitmap |= WATERMARKS_EXIST;
0526 }
0527
0528
0529 if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
0530 !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
0531 ret = smu_cmn_write_watermarks_table(smu);
0532 if (ret) {
0533 dev_err(smu->adev->dev, "Failed to update WMTABLE!");
0534 return ret;
0535 }
0536 smu->watermarks_bitmap |= WATERMARKS_LOADED;
0537 }
0538
0539 return 0;
0540 }
0541
0542 static ssize_t yellow_carp_get_gpu_metrics(struct smu_context *smu,
0543 void **table)
0544 {
0545 struct smu_table_context *smu_table = &smu->smu_table;
0546 struct gpu_metrics_v2_1 *gpu_metrics =
0547 (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table;
0548 SmuMetrics_t metrics;
0549 int ret = 0;
0550
0551 ret = smu_cmn_get_metrics_table(smu, &metrics, true);
0552 if (ret)
0553 return ret;
0554
0555 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1);
0556
0557 gpu_metrics->temperature_gfx = metrics.GfxTemperature;
0558 gpu_metrics->temperature_soc = metrics.SocTemperature;
0559 memcpy(&gpu_metrics->temperature_core[0],
0560 &metrics.CoreTemperature[0],
0561 sizeof(uint16_t) * 8);
0562 gpu_metrics->temperature_l3[0] = metrics.L3Temperature;
0563
0564 gpu_metrics->average_gfx_activity = metrics.GfxActivity;
0565 gpu_metrics->average_mm_activity = metrics.UvdActivity;
0566
0567 gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
0568 gpu_metrics->average_gfx_power = metrics.Power[0];
0569 gpu_metrics->average_soc_power = metrics.Power[1];
0570 memcpy(&gpu_metrics->average_core_power[0],
0571 &metrics.CorePower[0],
0572 sizeof(uint16_t) * 8);
0573
0574 gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
0575 gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
0576 gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
0577 gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
0578 gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
0579 gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
0580
0581 memcpy(&gpu_metrics->current_coreclk[0],
0582 &metrics.CoreFrequency[0],
0583 sizeof(uint16_t) * 8);
0584 gpu_metrics->current_l3clk[0] = metrics.L3Frequency;
0585
0586 gpu_metrics->throttle_status = metrics.ThrottlerStatus;
0587
0588 gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
0589
0590 *table = (void *)gpu_metrics;
0591
0592 return sizeof(struct gpu_metrics_v2_1);
0593 }
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607 static uint32_t yellow_carp_get_gfxoff_status(struct smu_context *smu)
0608 {
0609 uint32_t reg;
0610 uint32_t gfxoff_status = 0;
0611 struct amdgpu_device *adev = smu->adev;
0612
0613 reg = RREG32_SOC15(SMUIO, 0, regSMUIO_GFX_MISC_CNTL);
0614 gfxoff_status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK)
0615 >> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT;
0616
0617 return gfxoff_status;
0618 }
0619
0620 static int yellow_carp_set_default_dpm_tables(struct smu_context *smu)
0621 {
0622 struct smu_table_context *smu_table = &smu->smu_table;
0623
0624 return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
0625 }
0626
0627 static int yellow_carp_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
0628 long input[], uint32_t size)
0629 {
0630 struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
0631 int ret = 0;
0632
0633
0634 if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
0635 return -EINVAL;
0636
0637 switch (type) {
0638 case PP_OD_EDIT_SCLK_VDDC_TABLE:
0639 if (size != 2) {
0640 dev_err(smu->adev->dev, "Input parameter number not correct\n");
0641 return -EINVAL;
0642 }
0643
0644 if (input[0] == 0) {
0645 if (input[1] < smu->gfx_default_hard_min_freq) {
0646 dev_warn(smu->adev->dev,
0647 "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
0648 input[1], smu->gfx_default_hard_min_freq);
0649 return -EINVAL;
0650 }
0651 smu->gfx_actual_hard_min_freq = input[1];
0652 } else if (input[0] == 1) {
0653 if (input[1] > smu->gfx_default_soft_max_freq) {
0654 dev_warn(smu->adev->dev,
0655 "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
0656 input[1], smu->gfx_default_soft_max_freq);
0657 return -EINVAL;
0658 }
0659 smu->gfx_actual_soft_max_freq = input[1];
0660 } else {
0661 return -EINVAL;
0662 }
0663 break;
0664 case PP_OD_RESTORE_DEFAULT_TABLE:
0665 if (size != 0) {
0666 dev_err(smu->adev->dev, "Input parameter number not correct\n");
0667 return -EINVAL;
0668 } else {
0669 smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
0670 smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
0671 }
0672 break;
0673 case PP_OD_COMMIT_DPM_TABLE:
0674 if (size != 0) {
0675 dev_err(smu->adev->dev, "Input parameter number not correct\n");
0676 return -EINVAL;
0677 } else {
0678 if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
0679 dev_err(smu->adev->dev,
0680 "The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
0681 smu->gfx_actual_hard_min_freq,
0682 smu->gfx_actual_soft_max_freq);
0683 return -EINVAL;
0684 }
0685
0686 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
0687 smu->gfx_actual_hard_min_freq, NULL);
0688 if (ret) {
0689 dev_err(smu->adev->dev, "Set hard min sclk failed!");
0690 return ret;
0691 }
0692
0693 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
0694 smu->gfx_actual_soft_max_freq, NULL);
0695 if (ret) {
0696 dev_err(smu->adev->dev, "Set soft max sclk failed!");
0697 return ret;
0698 }
0699 }
0700 break;
0701 default:
0702 return -ENOSYS;
0703 }
0704
0705 return ret;
0706 }
0707
0708 static int yellow_carp_get_current_clk_freq(struct smu_context *smu,
0709 enum smu_clk_type clk_type,
0710 uint32_t *value)
0711 {
0712 MetricsMember_t member_type;
0713
0714 switch (clk_type) {
0715 case SMU_SOCCLK:
0716 member_type = METRICS_AVERAGE_SOCCLK;
0717 break;
0718 case SMU_VCLK:
0719 member_type = METRICS_AVERAGE_VCLK;
0720 break;
0721 case SMU_DCLK:
0722 member_type = METRICS_AVERAGE_DCLK;
0723 break;
0724 case SMU_MCLK:
0725 member_type = METRICS_AVERAGE_UCLK;
0726 break;
0727 case SMU_FCLK:
0728 return smu_cmn_send_smc_msg_with_param(smu,
0729 SMU_MSG_GetFclkFrequency, 0, value);
0730 case SMU_GFXCLK:
0731 case SMU_SCLK:
0732 return smu_cmn_send_smc_msg_with_param(smu,
0733 SMU_MSG_GetGfxclkFrequency, 0, value);
0734 break;
0735 default:
0736 return -EINVAL;
0737 }
0738
0739 return yellow_carp_get_smu_metrics_data(smu, member_type, value);
0740 }
0741
0742 static int yellow_carp_get_dpm_level_count(struct smu_context *smu,
0743 enum smu_clk_type clk_type,
0744 uint32_t *count)
0745 {
0746 DpmClocks_t *clk_table = smu->smu_table.clocks_table;
0747
0748 switch (clk_type) {
0749 case SMU_SOCCLK:
0750 *count = clk_table->NumSocClkLevelsEnabled;
0751 break;
0752 case SMU_VCLK:
0753 *count = clk_table->VcnClkLevelsEnabled;
0754 break;
0755 case SMU_DCLK:
0756 *count = clk_table->VcnClkLevelsEnabled;
0757 break;
0758 case SMU_MCLK:
0759 *count = clk_table->NumDfPstatesEnabled;
0760 break;
0761 case SMU_FCLK:
0762 *count = clk_table->NumDfPstatesEnabled;
0763 break;
0764 default:
0765 break;
0766 }
0767
0768 return 0;
0769 }
0770
0771 static int yellow_carp_get_dpm_freq_by_index(struct smu_context *smu,
0772 enum smu_clk_type clk_type,
0773 uint32_t dpm_level,
0774 uint32_t *freq)
0775 {
0776 DpmClocks_t *clk_table = smu->smu_table.clocks_table;
0777
0778 if (!clk_table || clk_type >= SMU_CLK_COUNT)
0779 return -EINVAL;
0780
0781 switch (clk_type) {
0782 case SMU_SOCCLK:
0783 if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
0784 return -EINVAL;
0785 *freq = clk_table->SocClocks[dpm_level];
0786 break;
0787 case SMU_VCLK:
0788 if (dpm_level >= clk_table->VcnClkLevelsEnabled)
0789 return -EINVAL;
0790 *freq = clk_table->VClocks[dpm_level];
0791 break;
0792 case SMU_DCLK:
0793 if (dpm_level >= clk_table->VcnClkLevelsEnabled)
0794 return -EINVAL;
0795 *freq = clk_table->DClocks[dpm_level];
0796 break;
0797 case SMU_UCLK:
0798 case SMU_MCLK:
0799 if (dpm_level >= clk_table->NumDfPstatesEnabled)
0800 return -EINVAL;
0801 *freq = clk_table->DfPstateTable[dpm_level].MemClk;
0802 break;
0803 case SMU_FCLK:
0804 if (dpm_level >= clk_table->NumDfPstatesEnabled)
0805 return -EINVAL;
0806 *freq = clk_table->DfPstateTable[dpm_level].FClk;
0807 break;
0808 default:
0809 return -EINVAL;
0810 }
0811
0812 return 0;
0813 }
0814
0815 static bool yellow_carp_clk_dpm_is_enabled(struct smu_context *smu,
0816 enum smu_clk_type clk_type)
0817 {
0818 enum smu_feature_mask feature_id = 0;
0819
0820 switch (clk_type) {
0821 case SMU_MCLK:
0822 case SMU_UCLK:
0823 case SMU_FCLK:
0824 feature_id = SMU_FEATURE_DPM_FCLK_BIT;
0825 break;
0826 case SMU_GFXCLK:
0827 case SMU_SCLK:
0828 feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
0829 break;
0830 case SMU_SOCCLK:
0831 feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
0832 break;
0833 case SMU_VCLK:
0834 case SMU_DCLK:
0835 feature_id = SMU_FEATURE_VCN_DPM_BIT;
0836 break;
0837 default:
0838 return true;
0839 }
0840
0841 return smu_cmn_feature_is_enabled(smu, feature_id);
0842 }
0843
0844 static int yellow_carp_get_dpm_ultimate_freq(struct smu_context *smu,
0845 enum smu_clk_type clk_type,
0846 uint32_t *min,
0847 uint32_t *max)
0848 {
0849 DpmClocks_t *clk_table = smu->smu_table.clocks_table;
0850 uint32_t clock_limit;
0851 uint32_t max_dpm_level, min_dpm_level;
0852 int ret = 0;
0853
0854 if (!yellow_carp_clk_dpm_is_enabled(smu, clk_type)) {
0855 switch (clk_type) {
0856 case SMU_MCLK:
0857 case SMU_UCLK:
0858 clock_limit = smu->smu_table.boot_values.uclk;
0859 break;
0860 case SMU_FCLK:
0861 clock_limit = smu->smu_table.boot_values.fclk;
0862 break;
0863 case SMU_GFXCLK:
0864 case SMU_SCLK:
0865 clock_limit = smu->smu_table.boot_values.gfxclk;
0866 break;
0867 case SMU_SOCCLK:
0868 clock_limit = smu->smu_table.boot_values.socclk;
0869 break;
0870 case SMU_VCLK:
0871 clock_limit = smu->smu_table.boot_values.vclk;
0872 break;
0873 case SMU_DCLK:
0874 clock_limit = smu->smu_table.boot_values.dclk;
0875 break;
0876 default:
0877 clock_limit = 0;
0878 break;
0879 }
0880
0881
0882 if (min)
0883 *min = clock_limit / 100;
0884 if (max)
0885 *max = clock_limit / 100;
0886
0887 return 0;
0888 }
0889
0890 if (max) {
0891 switch (clk_type) {
0892 case SMU_GFXCLK:
0893 case SMU_SCLK:
0894 *max = clk_table->MaxGfxClk;
0895 break;
0896 case SMU_MCLK:
0897 case SMU_UCLK:
0898 case SMU_FCLK:
0899 max_dpm_level = 0;
0900 break;
0901 case SMU_SOCCLK:
0902 max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1;
0903 break;
0904 case SMU_VCLK:
0905 case SMU_DCLK:
0906 max_dpm_level = clk_table->VcnClkLevelsEnabled - 1;
0907 break;
0908 default:
0909 ret = -EINVAL;
0910 goto failed;
0911 }
0912
0913 if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
0914 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max);
0915 if (ret)
0916 goto failed;
0917 }
0918 }
0919
0920 if (min) {
0921 switch (clk_type) {
0922 case SMU_GFXCLK:
0923 case SMU_SCLK:
0924 *min = clk_table->MinGfxClk;
0925 break;
0926 case SMU_MCLK:
0927 case SMU_UCLK:
0928 case SMU_FCLK:
0929 min_dpm_level = clk_table->NumDfPstatesEnabled - 1;
0930 break;
0931 case SMU_SOCCLK:
0932 min_dpm_level = 0;
0933 break;
0934 case SMU_VCLK:
0935 case SMU_DCLK:
0936 min_dpm_level = 0;
0937 break;
0938 default:
0939 ret = -EINVAL;
0940 goto failed;
0941 }
0942
0943 if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
0944 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min);
0945 if (ret)
0946 goto failed;
0947 }
0948 }
0949
0950 failed:
0951 return ret;
0952 }
0953
0954 static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
0955 enum smu_clk_type clk_type,
0956 uint32_t min,
0957 uint32_t max)
0958 {
0959 enum smu_message_type msg_set_min, msg_set_max;
0960 int ret = 0;
0961
0962 if (!yellow_carp_clk_dpm_is_enabled(smu, clk_type))
0963 return -EINVAL;
0964
0965 switch (clk_type) {
0966 case SMU_GFXCLK:
0967 case SMU_SCLK:
0968 msg_set_min = SMU_MSG_SetHardMinGfxClk;
0969 msg_set_max = SMU_MSG_SetSoftMaxGfxClk;
0970 break;
0971 case SMU_FCLK:
0972 msg_set_min = SMU_MSG_SetHardMinFclkByFreq;
0973 msg_set_max = SMU_MSG_SetSoftMaxFclkByFreq;
0974 break;
0975 case SMU_SOCCLK:
0976 msg_set_min = SMU_MSG_SetHardMinSocclkByFreq;
0977 msg_set_max = SMU_MSG_SetSoftMaxSocclkByFreq;
0978 break;
0979 case SMU_VCLK:
0980 case SMU_DCLK:
0981 msg_set_min = SMU_MSG_SetHardMinVcn;
0982 msg_set_max = SMU_MSG_SetSoftMaxVcn;
0983 break;
0984 default:
0985 return -EINVAL;
0986 }
0987
0988 ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
0989 if (ret)
0990 goto out;
0991
0992 ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_max, max, NULL);
0993 if (ret)
0994 goto out;
0995
0996 out:
0997 return ret;
0998 }
0999
1000 static int yellow_carp_print_clk_levels(struct smu_context *smu,
1001 enum smu_clk_type clk_type, char *buf)
1002 {
1003 int i, size = 0, ret = 0;
1004 uint32_t cur_value = 0, value = 0, count = 0;
1005 uint32_t min, max;
1006
1007 smu_cmn_get_sysfs_buf(&buf, &size);
1008
1009 switch (clk_type) {
1010 case SMU_OD_SCLK:
1011 size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
1012 size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
1013 (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
1014 size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
1015 (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
1016 break;
1017 case SMU_OD_RANGE:
1018 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
1019 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
1020 smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
1021 break;
1022 case SMU_SOCCLK:
1023 case SMU_VCLK:
1024 case SMU_DCLK:
1025 case SMU_MCLK:
1026 case SMU_FCLK:
1027 ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value);
1028 if (ret)
1029 goto print_clk_out;
1030
1031 ret = yellow_carp_get_dpm_level_count(smu, clk_type, &count);
1032 if (ret)
1033 goto print_clk_out;
1034
1035 for (i = 0; i < count; i++) {
1036 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, i, &value);
1037 if (ret)
1038 goto print_clk_out;
1039
1040 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
1041 cur_value == value ? "*" : "");
1042 }
1043 break;
1044 case SMU_GFXCLK:
1045 case SMU_SCLK:
1046 ret = yellow_carp_get_current_clk_freq(smu, clk_type, &cur_value);
1047 if (ret)
1048 goto print_clk_out;
1049 min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
1050 max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
1051 if (cur_value == max)
1052 i = 2;
1053 else if (cur_value == min)
1054 i = 0;
1055 else
1056 i = 1;
1057 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
1058 i == 0 ? "*" : "");
1059 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
1060 i == 1 ? cur_value : YELLOW_CARP_UMD_PSTATE_GFXCLK,
1061 i == 1 ? "*" : "");
1062 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
1063 i == 2 ? "*" : "");
1064 break;
1065 default:
1066 break;
1067 }
1068
1069 print_clk_out:
1070 return size;
1071 }
1072
1073 static int yellow_carp_force_clk_levels(struct smu_context *smu,
1074 enum smu_clk_type clk_type, uint32_t mask)
1075 {
1076 uint32_t soft_min_level = 0, soft_max_level = 0;
1077 uint32_t min_freq = 0, max_freq = 0;
1078 int ret = 0;
1079
1080 soft_min_level = mask ? (ffs(mask) - 1) : 0;
1081 soft_max_level = mask ? (fls(mask) - 1) : 0;
1082
1083 switch (clk_type) {
1084 case SMU_SOCCLK:
1085 case SMU_FCLK:
1086 case SMU_VCLK:
1087 case SMU_DCLK:
1088 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
1089 if (ret)
1090 goto force_level_out;
1091
1092 ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
1093 if (ret)
1094 goto force_level_out;
1095
1096 ret = yellow_carp_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
1097 if (ret)
1098 goto force_level_out;
1099 break;
1100 default:
1101 ret = -EINVAL;
1102 break;
1103 }
1104
1105 force_level_out:
1106 return ret;
1107 }
1108
1109 static int yellow_carp_set_performance_level(struct smu_context *smu,
1110 enum amd_dpm_forced_level level)
1111 {
1112 struct amdgpu_device *adev = smu->adev;
1113 uint32_t sclk_min = 0, sclk_max = 0;
1114 uint32_t fclk_min = 0, fclk_max = 0;
1115 uint32_t socclk_min = 0, socclk_max = 0;
1116 int ret = 0;
1117
1118 switch (level) {
1119 case AMD_DPM_FORCED_LEVEL_HIGH:
1120 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
1121 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
1122 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
1123 sclk_min = sclk_max;
1124 fclk_min = fclk_max;
1125 socclk_min = socclk_max;
1126 break;
1127 case AMD_DPM_FORCED_LEVEL_LOW:
1128 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
1129 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
1130 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
1131 sclk_max = sclk_min;
1132 fclk_max = fclk_min;
1133 socclk_max = socclk_min;
1134 break;
1135 case AMD_DPM_FORCED_LEVEL_AUTO:
1136 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
1137 yellow_carp_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
1138 yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
1139 break;
1140 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1141 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1142 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1143 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1144
1145 break;
1146 case AMD_DPM_FORCED_LEVEL_MANUAL:
1147 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1148 return 0;
1149 default:
1150 dev_err(adev->dev, "Invalid performance level %d\n", level);
1151 return -EINVAL;
1152 }
1153
1154 if (sclk_min && sclk_max) {
1155 ret = yellow_carp_set_soft_freq_limited_range(smu,
1156 SMU_SCLK,
1157 sclk_min,
1158 sclk_max);
1159 if (ret)
1160 return ret;
1161
1162 smu->gfx_actual_hard_min_freq = sclk_min;
1163 smu->gfx_actual_soft_max_freq = sclk_max;
1164 }
1165
1166 if (fclk_min && fclk_max) {
1167 ret = yellow_carp_set_soft_freq_limited_range(smu,
1168 SMU_FCLK,
1169 fclk_min,
1170 fclk_max);
1171 if (ret)
1172 return ret;
1173 }
1174
1175 if (socclk_min && socclk_max) {
1176 ret = yellow_carp_set_soft_freq_limited_range(smu,
1177 SMU_SOCCLK,
1178 socclk_min,
1179 socclk_max);
1180 if (ret)
1181 return ret;
1182 }
1183
1184 return ret;
1185 }
1186
1187 static int yellow_carp_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
1188 {
1189 DpmClocks_t *clk_table = smu->smu_table.clocks_table;
1190
1191 smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
1192 smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
1193 smu->gfx_actual_hard_min_freq = 0;
1194 smu->gfx_actual_soft_max_freq = 0;
1195
1196 return 0;
1197 }
1198
1199 static const struct pptable_funcs yellow_carp_ppt_funcs = {
1200 .check_fw_status = smu_v13_0_check_fw_status,
1201 .check_fw_version = smu_v13_0_check_fw_version,
1202 .init_smc_tables = yellow_carp_init_smc_tables,
1203 .fini_smc_tables = yellow_carp_fini_smc_tables,
1204 .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
1205 .system_features_control = yellow_carp_system_features_control,
1206 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
1207 .send_smc_msg = smu_cmn_send_smc_msg,
1208 .dpm_set_vcn_enable = yellow_carp_dpm_set_vcn_enable,
1209 .dpm_set_jpeg_enable = yellow_carp_dpm_set_jpeg_enable,
1210 .set_default_dpm_table = yellow_carp_set_default_dpm_tables,
1211 .read_sensor = yellow_carp_read_sensor,
1212 .is_dpm_running = yellow_carp_is_dpm_running,
1213 .set_watermarks_table = yellow_carp_set_watermarks_table,
1214 .get_gpu_metrics = yellow_carp_get_gpu_metrics,
1215 .get_enabled_mask = smu_cmn_get_enabled_mask,
1216 .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
1217 .set_driver_table_location = smu_v13_0_set_driver_table_location,
1218 .gfx_off_control = smu_v13_0_gfx_off_control,
1219 .get_gfx_off_status = yellow_carp_get_gfxoff_status,
1220 .post_init = yellow_carp_post_smu_init,
1221 .mode2_reset = yellow_carp_mode2_reset,
1222 .get_dpm_ultimate_freq = yellow_carp_get_dpm_ultimate_freq,
1223 .od_edit_dpm_table = yellow_carp_od_edit_dpm_table,
1224 .print_clk_levels = yellow_carp_print_clk_levels,
1225 .force_clk_levels = yellow_carp_force_clk_levels,
1226 .set_performance_level = yellow_carp_set_performance_level,
1227 .set_fine_grain_gfx_freq_parameters = yellow_carp_set_fine_grain_gfx_freq_parameters,
1228 };
1229
1230 void yellow_carp_set_ppt_funcs(struct smu_context *smu)
1231 {
1232 smu->ppt_funcs = &yellow_carp_ppt_funcs;
1233 smu->message_map = yellow_carp_message_map;
1234 smu->feature_map = yellow_carp_feature_mask_map;
1235 smu->table_map = yellow_carp_table_map;
1236 smu->is_apu = true;
1237 smu_v13_0_set_smu_mailbox_registers(smu);
1238 }