cyan_skillfish_ppt.c (17379B)
1/* 2 * Copyright 2021 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_v11_0.h" 29#include "smu11_driver_if_cyan_skillfish.h" 30#include "cyan_skillfish_ppt.h" 31#include "smu_v11_8_ppsmc.h" 32#include "smu_v11_8_pmfw.h" 33#include "smu_cmn.h" 34#include "soc15_common.h" 35 36/* 37 * DO NOT use these for err/warn/info/debug messages. 38 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 39 * They are more MGPU friendly. 40 */ 41 42#undef pr_err 43#undef pr_warn 44#undef pr_info 45#undef pr_debug 46 47/* unit: MHz */ 48#define CYAN_SKILLFISH_SCLK_MIN 1000 49#define CYAN_SKILLFISH_SCLK_MAX 2000 50 51/* unit: mV */ 52#define CYAN_SKILLFISH_VDDC_MIN 700 53#define CYAN_SKILLFISH_VDDC_MAX 1129 54#define CYAN_SKILLFISH_VDDC_MAGIC 5118 // 0x13fe 55 56static struct gfx_user_settings { 57 uint32_t sclk; 58 uint32_t vddc; 59} cyan_skillfish_user_settings; 60 61static uint32_t cyan_skillfish_sclk_default; 62 63#define FEATURE_MASK(feature) (1ULL << feature) 64#define SMC_DPM_FEATURE ( \ 65 FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ 66 FEATURE_MASK(FEATURE_SOC_DPM_BIT) | \ 67 FEATURE_MASK(FEATURE_GFX_DPM_BIT)) 68 69static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = { 70 MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), 71 MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), 72 MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 0), 73 MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverTableDramAddrHigh, 0), 74 MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0), 75 MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), 76 MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), 77 MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0), 78 MSG_MAP(RequestGfxclk, PPSMC_MSG_RequestGfxclk, 0), 79 MSG_MAP(ForceGfxVid, PPSMC_MSG_ForceGfxVid, 0), 80 MSG_MAP(UnforceGfxVid, PPSMC_MSG_UnforceGfxVid, 0), 81}; 82 83static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = { 84 TAB_MAP_VALID(SMU_METRICS), 85}; 86 87static int cyan_skillfish_tables_init(struct smu_context *smu) 88{ 89 struct smu_table_context *smu_table = &smu->smu_table; 90 struct smu_table *tables = smu_table->tables; 91 92 SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, 93 sizeof(SmuMetrics_t), 94 PAGE_SIZE, 95 AMDGPU_GEM_DOMAIN_VRAM); 96 97 smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); 98 if (!smu_table->metrics_table) 99 goto err0_out; 100 101 smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); 102 smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); 103 if (!smu_table->gpu_metrics_table) 104 goto err1_out; 105 106 smu_table->metrics_time = 0; 107 108 return 0; 109 110err1_out: 111 smu_table->gpu_metrics_table_size = 0; 112 kfree(smu_table->metrics_table); 113err0_out: 114 return -ENOMEM; 115} 116 117static int cyan_skillfish_init_smc_tables(struct smu_context *smu) 118{ 119 int ret = 0; 120 121 ret = cyan_skillfish_tables_init(smu); 122 if (ret) 123 return ret; 124 125 return smu_v11_0_init_smc_tables(smu); 126} 127 128static int 129cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, 130 MetricsMember_t member, 131 uint32_t *value) 132{ 133 struct smu_table_context *smu_table = &smu->smu_table; 134 SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; 135 int ret = 0; 136 137 ret = smu_cmn_get_metrics_table(smu, NULL, false); 138 if (ret) 139 return ret; 140 141 switch (member) { 142 case METRICS_CURR_GFXCLK: 143 *value = metrics->Current.GfxclkFrequency; 144 break; 145 case METRICS_CURR_SOCCLK: 146 *value = metrics->Current.SocclkFrequency; 147 break; 148 case METRICS_CURR_VCLK: 149 *value = metrics->Current.VclkFrequency; 150 break; 151 case METRICS_CURR_DCLK: 152 *value = metrics->Current.DclkFrequency; 153 break; 154 case METRICS_CURR_UCLK: 155 *value = metrics->Current.MemclkFrequency; 156 break; 157 case METRICS_AVERAGE_SOCKETPOWER: 158 *value = (metrics->Current.CurrentSocketPower << 8) / 159 1000; 160 break; 161 case METRICS_TEMPERATURE_EDGE: 162 *value = metrics->Current.GfxTemperature / 100 * 163 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 164 break; 165 case METRICS_TEMPERATURE_HOTSPOT: 166 *value = metrics->Current.SocTemperature / 100 * 167 SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; 168 break; 169 case METRICS_VOLTAGE_VDDSOC: 170 *value = metrics->Current.Voltage[0]; 171 break; 172 case METRICS_VOLTAGE_VDDGFX: 173 *value = metrics->Current.Voltage[1]; 174 break; 175 case METRICS_THROTTLER_STATUS: 176 *value = metrics->Current.ThrottlerStatus; 177 break; 178 default: 179 *value = UINT_MAX; 180 break; 181 } 182 183 return ret; 184} 185 186static int cyan_skillfish_read_sensor(struct smu_context *smu, 187 enum amd_pp_sensors sensor, 188 void *data, 189 uint32_t *size) 190{ 191 int ret = 0; 192 193 if (!data || !size) 194 return -EINVAL; 195 196 switch (sensor) { 197 case AMDGPU_PP_SENSOR_GFX_SCLK: 198 ret = cyan_skillfish_get_smu_metrics_data(smu, 199 METRICS_CURR_GFXCLK, 200 (uint32_t *)data); 201 *(uint32_t *)data *= 100; 202 *size = 4; 203 break; 204 case AMDGPU_PP_SENSOR_GFX_MCLK: 205 ret = cyan_skillfish_get_smu_metrics_data(smu, 206 METRICS_CURR_UCLK, 207 (uint32_t *)data); 208 *(uint32_t *)data *= 100; 209 *size = 4; 210 break; 211 case AMDGPU_PP_SENSOR_GPU_POWER: 212 ret = cyan_skillfish_get_smu_metrics_data(smu, 213 METRICS_AVERAGE_SOCKETPOWER, 214 (uint32_t *)data); 215 *size = 4; 216 break; 217 case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: 218 ret = cyan_skillfish_get_smu_metrics_data(smu, 219 METRICS_TEMPERATURE_HOTSPOT, 220 (uint32_t *)data); 221 *size = 4; 222 break; 223 case AMDGPU_PP_SENSOR_EDGE_TEMP: 224 ret = cyan_skillfish_get_smu_metrics_data(smu, 225 METRICS_TEMPERATURE_EDGE, 226 (uint32_t *)data); 227 *size = 4; 228 break; 229 case AMDGPU_PP_SENSOR_VDDNB: 230 ret = cyan_skillfish_get_smu_metrics_data(smu, 231 METRICS_VOLTAGE_VDDSOC, 232 (uint32_t *)data); 233 *size = 4; 234 break; 235 case AMDGPU_PP_SENSOR_VDDGFX: 236 ret = cyan_skillfish_get_smu_metrics_data(smu, 237 METRICS_VOLTAGE_VDDGFX, 238 (uint32_t *)data); 239 *size = 4; 240 break; 241 default: 242 ret = -EOPNOTSUPP; 243 break; 244 } 245 246 return ret; 247} 248 249static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu, 250 enum smu_clk_type clk_type, 251 uint32_t *value) 252{ 253 MetricsMember_t member_type; 254 255 switch (clk_type) { 256 case SMU_GFXCLK: 257 case SMU_SCLK: 258 member_type = METRICS_CURR_GFXCLK; 259 break; 260 case SMU_FCLK: 261 case SMU_MCLK: 262 member_type = METRICS_CURR_UCLK; 263 break; 264 case SMU_SOCCLK: 265 member_type = METRICS_CURR_SOCCLK; 266 break; 267 case SMU_VCLK: 268 member_type = METRICS_CURR_VCLK; 269 break; 270 case SMU_DCLK: 271 member_type = METRICS_CURR_DCLK; 272 break; 273 default: 274 return -EINVAL; 275 } 276 277 return cyan_skillfish_get_smu_metrics_data(smu, member_type, value); 278} 279 280static int cyan_skillfish_print_clk_levels(struct smu_context *smu, 281 enum smu_clk_type clk_type, 282 char *buf) 283{ 284 int ret = 0, size = 0; 285 uint32_t cur_value = 0; 286 int i; 287 288 smu_cmn_get_sysfs_buf(&buf, &size); 289 290 switch (clk_type) { 291 case SMU_OD_SCLK: 292 ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value); 293 if (ret) 294 return ret; 295 size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK"); 296 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); 297 break; 298 case SMU_OD_VDDC_CURVE: 299 ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value); 300 if (ret) 301 return ret; 302 size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC"); 303 size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value); 304 break; 305 case SMU_OD_RANGE: 306 size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); 307 size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", 308 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 309 size += sysfs_emit_at(buf, size, "VDDC: %7umV %10umV\n", 310 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 311 break; 312 case SMU_FCLK: 313 case SMU_MCLK: 314 case SMU_SOCCLK: 315 case SMU_VCLK: 316 case SMU_DCLK: 317 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); 318 if (ret) 319 return ret; 320 size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); 321 break; 322 case SMU_SCLK: 323 case SMU_GFXCLK: 324 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); 325 if (ret) 326 return ret; 327 if (cur_value == CYAN_SKILLFISH_SCLK_MAX) 328 i = 2; 329 else if (cur_value == CYAN_SKILLFISH_SCLK_MIN) 330 i = 0; 331 else 332 i = 1; 333 size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MIN, 334 i == 0 ? "*" : ""); 335 size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", 336 i == 1 ? cur_value : cyan_skillfish_sclk_default, 337 i == 1 ? "*" : ""); 338 size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", CYAN_SKILLFISH_SCLK_MAX, 339 i == 2 ? "*" : ""); 340 break; 341 default: 342 dev_warn(smu->adev->dev, "Unsupported clock type\n"); 343 return ret; 344 } 345 346 return size; 347} 348 349static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) 350{ 351 struct amdgpu_device *adev = smu->adev; 352 int ret = 0; 353 uint64_t feature_enabled; 354 355 /* we need to re-init after suspend so return false */ 356 if (adev->in_suspend) 357 return false; 358 359 ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); 360 if (ret) 361 return false; 362 363 /* 364 * cyan_skillfish specific, query default sclk inseted of hard code. 365 */ 366 if (!cyan_skillfish_sclk_default) 367 cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, 368 &cyan_skillfish_sclk_default); 369 370 return !!(feature_enabled & SMC_DPM_FEATURE); 371} 372 373static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, 374 void **table) 375{ 376 struct smu_table_context *smu_table = &smu->smu_table; 377 struct gpu_metrics_v2_2 *gpu_metrics = 378 (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; 379 SmuMetrics_t metrics; 380 int i, ret = 0; 381 382 ret = smu_cmn_get_metrics_table(smu, &metrics, true); 383 if (ret) 384 return ret; 385 386 smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); 387 388 gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; 389 gpu_metrics->temperature_soc = metrics.Current.SocTemperature; 390 391 gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower; 392 gpu_metrics->average_soc_power = metrics.Current.Power[0]; 393 gpu_metrics->average_gfx_power = metrics.Current.Power[1]; 394 395 gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency; 396 gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency; 397 gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency; 398 gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency; 399 gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency; 400 gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency; 401 402 gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency; 403 gpu_metrics->current_socclk = metrics.Current.SocclkFrequency; 404 gpu_metrics->current_uclk = metrics.Current.MemclkFrequency; 405 gpu_metrics->current_fclk = metrics.Current.MemclkFrequency; 406 gpu_metrics->current_vclk = metrics.Current.VclkFrequency; 407 gpu_metrics->current_dclk = metrics.Current.DclkFrequency; 408 409 for (i = 0; i < 6; i++) { 410 gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i]; 411 gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i]; 412 gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i]; 413 } 414 415 for (i = 0; i < 2; i++) { 416 gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i]; 417 gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i]; 418 } 419 420 gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; 421 gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); 422 423 *table = (void *)gpu_metrics; 424 425 return sizeof(struct gpu_metrics_v2_2); 426} 427 428static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, 429 enum PP_OD_DPM_TABLE_COMMAND type, 430 long input[], uint32_t size) 431{ 432 int ret = 0; 433 uint32_t vid; 434 435 switch (type) { 436 case PP_OD_EDIT_VDDC_CURVE: 437 if (size != 3 || input[0] != 0) { 438 dev_err(smu->adev->dev, "Invalid parameter!\n"); 439 return -EINVAL; 440 } 441 442 if (input[1] < CYAN_SKILLFISH_SCLK_MIN || 443 input[1] > CYAN_SKILLFISH_SCLK_MAX) { 444 dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", 445 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 446 return -EINVAL; 447 } 448 449 if (input[2] < CYAN_SKILLFISH_VDDC_MIN || 450 input[2] > CYAN_SKILLFISH_VDDC_MAX) { 451 dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", 452 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 453 return -EINVAL; 454 } 455 456 cyan_skillfish_user_settings.sclk = input[1]; 457 cyan_skillfish_user_settings.vddc = input[2]; 458 459 break; 460 case PP_OD_RESTORE_DEFAULT_TABLE: 461 if (size != 0) { 462 dev_err(smu->adev->dev, "Invalid parameter!\n"); 463 return -EINVAL; 464 } 465 466 cyan_skillfish_user_settings.sclk = cyan_skillfish_sclk_default; 467 cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC; 468 469 break; 470 case PP_OD_COMMIT_DPM_TABLE: 471 if (size != 0) { 472 dev_err(smu->adev->dev, "Invalid parameter!\n"); 473 return -EINVAL; 474 } 475 476 if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN || 477 cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) { 478 dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", 479 CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); 480 return -EINVAL; 481 } 482 483 if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) && 484 (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN || 485 cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) { 486 dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", 487 CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); 488 return -EINVAL; 489 } 490 491 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk, 492 cyan_skillfish_user_settings.sclk, NULL); 493 if (ret) { 494 dev_err(smu->adev->dev, "Set sclk failed!\n"); 495 return ret; 496 } 497 498 if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) { 499 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL); 500 if (ret) { 501 dev_err(smu->adev->dev, "Unforce vddc failed!\n"); 502 return ret; 503 } 504 } else { 505 /* 506 * PMFW accepts SVI2 VID code, convert voltage to VID: 507 * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001) 508 */ 509 vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000; 510 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL); 511 if (ret) { 512 dev_err(smu->adev->dev, "Force vddc failed!\n"); 513 return ret; 514 } 515 } 516 517 break; 518 default: 519 return -EOPNOTSUPP; 520 } 521 522 return ret; 523} 524 525static int cyan_skillfish_get_dpm_ultimate_freq(struct smu_context *smu, 526 enum smu_clk_type clk_type, 527 uint32_t *min, 528 uint32_t *max) 529{ 530 int ret = 0; 531 uint32_t low, high; 532 533 switch (clk_type) { 534 case SMU_GFXCLK: 535 case SMU_SCLK: 536 low = CYAN_SKILLFISH_SCLK_MIN; 537 high = CYAN_SKILLFISH_SCLK_MAX; 538 break; 539 default: 540 ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &low); 541 if (ret) 542 return ret; 543 high = low; 544 break; 545 } 546 547 if (min) 548 *min = low; 549 if (max) 550 *max = high; 551 552 return 0; 553} 554 555static int cyan_skillfish_get_enabled_mask(struct smu_context *smu, 556 uint64_t *feature_mask) 557{ 558 if (!feature_mask) 559 return -EINVAL; 560 memset(feature_mask, 0xff, sizeof(*feature_mask)); 561 562 return 0; 563} 564 565static const struct pptable_funcs cyan_skillfish_ppt_funcs = { 566 567 .check_fw_status = smu_v11_0_check_fw_status, 568 .check_fw_version = smu_v11_0_check_fw_version, 569 .init_power = smu_v11_0_init_power, 570 .fini_power = smu_v11_0_fini_power, 571 .init_smc_tables = cyan_skillfish_init_smc_tables, 572 .fini_smc_tables = smu_v11_0_fini_smc_tables, 573 .read_sensor = cyan_skillfish_read_sensor, 574 .print_clk_levels = cyan_skillfish_print_clk_levels, 575 .get_enabled_mask = cyan_skillfish_get_enabled_mask, 576 .is_dpm_running = cyan_skillfish_is_dpm_running, 577 .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, 578 .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, 579 .get_dpm_ultimate_freq = cyan_skillfish_get_dpm_ultimate_freq, 580 .register_irq_handler = smu_v11_0_register_irq_handler, 581 .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, 582 .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, 583 .send_smc_msg = smu_cmn_send_smc_msg, 584 .set_driver_table_location = smu_v11_0_set_driver_table_location, 585 .interrupt_work = smu_v11_0_interrupt_work, 586}; 587 588void cyan_skillfish_set_ppt_funcs(struct smu_context *smu) 589{ 590 smu->ppt_funcs = &cyan_skillfish_ppt_funcs; 591 smu->message_map = cyan_skillfish_message_map; 592 smu->table_map = cyan_skillfish_table_map; 593 smu->is_apu = true; 594}