Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/pm: add the fine grain tuning function for vangogh

This patch is to add the fine grain tuning function for vangogh.
This function uses the pp_od_clk_voltage sysfs file to configure the min
and max value of gfx clock frequency or restore the default value.

Command guide:
echo "s level value" > pp_od_clk_voltage
"s" - set the sclk frequency
"level" - 0 or 1, "0" represents the min value, "1" represents
the max value
"value" - the target value of sclk frequency, it should be
limited in the safe range
echo "r" > pp_od_clk_voltage
"r" - reset the sclk frequency, restore the default value
instantly
echo "c" > pp_od_clk_voltage
"c" - commit the min and max value of sclk frequency to the system
only after the commit command, the setting target values by "s" command
will take effect.
Example:
1)check the default sclk frequency
$ cat pp_od_clk_voltage
OD_SCLK:
0: 200Mhz
1: 1400Mhz
OD_RANGE:
SCLK: 200MHz 1400MHz
2)use "s" -- set command to configure the min or max sclk frequency
$ echo "s 0 600" > pp_od_clk_voltage
$ echo "s 1 1000" > pp_od_clk_voltage
$ echo "c" > pp_od_clk_voltage
$ cat pp_od_clk_voltage
OD_SCLK:
0: 600Mhz
1: 1000Mhz
OD_RANGE:
SCLK: 200MHz 1400MHz
3)use "r" -- reset command to restore the min and max sclk frequency
$ echo "r" > pp_od_clk_voltage
$ cat pp_od_clk_voltage
OD_SCLK:
0: 200Mhz
1: 1400Mhz
OD_RANGE:
SCLK: 200MHz 1400MHz

Signed-off-by: Xiaojian Du <Xiaojian.Du@amd.com>
Reviewed-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Xiaojian Du and committed by
Alex Deucher
c98ee897 5fe6b98a

+158
+6
drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
··· 459 459 460 460 unsigned fan_max_rpm; 461 461 unsigned manual_fan_speed_rpm; 462 + 463 + uint32_t gfx_default_hard_min_freq; 464 + uint32_t gfx_default_soft_max_freq; 465 + uint32_t gfx_actual_hard_min_freq; 466 + uint32_t gfx_actual_soft_max_freq; 462 467 }; 463 468 464 469 struct i2c_adapter; ··· 582 577 void (*interrupt_work)(struct smu_context *smu); 583 578 int (*gpo_control)(struct smu_context *smu, bool enablement); 584 579 int (*gfx_state_change_set)(struct smu_context *smu, uint32_t state); 580 + int (*set_fine_grain_gfx_freq_parameters)(struct smu_context *smu); 585 581 }; 586 582 587 583 typedef enum {
+2
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
··· 438 438 kfree(smu_table->overdrive_table); 439 439 kfree(smu_table->max_sustainable_clocks); 440 440 kfree(smu_table->driver_pptable); 441 + kfree(smu_table->clocks_table); 441 442 smu_table->gpu_metrics_table = NULL; 442 443 smu_table->boot_overdrive_table = NULL; 443 444 smu_table->overdrive_table = NULL; 444 445 smu_table->max_sustainable_clocks = NULL; 445 446 smu_table->driver_pptable = NULL; 447 + smu_table->clocks_table = NULL; 446 448 kfree(smu_table->hardcode_pptable); 447 449 smu_table->hardcode_pptable = NULL; 448 450
+149
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
··· 200 200 if (!smu_table->watermarks_table) 201 201 goto err2_out; 202 202 203 + smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); 204 + if (!smu_table->clocks_table) 205 + goto err3_out; 206 + 203 207 return 0; 204 208 209 + err3_out: 210 + kfree(smu_table->clocks_table); 205 211 err2_out: 206 212 kfree(smu_table->gpu_metrics_table); 207 213 err1_out: ··· 483 477 value); 484 478 } 485 479 480 + static int vangogh_print_fine_grain_clk(struct smu_context *smu, 481 + enum smu_clk_type clk_type, char *buf) 482 + { 483 + int size = 0; 484 + 485 + switch (clk_type) { 486 + case SMU_OD_SCLK: 487 + if (smu->od_enabled) { 488 + size = sprintf(buf, "%s:\n", "OD_SCLK"); 489 + size += sprintf(buf + size, "0: %10uMhz\n", 490 + (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); 491 + size += sprintf(buf + size, "1: %10uMhz\n", 492 + (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); 493 + } 494 + break; 495 + case SMU_OD_RANGE: 496 + if (smu->od_enabled) { 497 + size = sprintf(buf, "%s:\n", "OD_RANGE"); 498 + size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", 499 + smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); 500 + } 501 + break; 502 + default: 503 + break; 504 + } 505 + 506 + return size; 507 + } 508 + 486 509 static int vangogh_read_sensor(struct smu_context *smu, 487 510 enum amd_pp_sensors sensor, 488 511 void *data, uint32_t *size) ··· 670 635 return sizeof(struct gpu_metrics_v2_0); 671 636 } 672 637 638 + static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, 639 + long input[], uint32_t size) 640 + { 641 + int ret = 0; 642 + 643 + if (!smu->od_enabled) { 644 + dev_warn(smu->adev->dev, "Fine grain is not enabled!\n"); 645 + return -EINVAL; 646 + } 647 + 648 + switch (type) { 649 + case PP_OD_EDIT_SCLK_VDDC_TABLE: 650 + if (size != 2) { 651 + dev_err(smu->adev->dev, "Input parameter number not correct\n"); 652 + return -EINVAL; 653 + } 654 + 655 + if (input[0] == 0) { 656 + if (input[1] < smu->gfx_default_hard_min_freq) { 657 + dev_warn(smu->adev->dev, "Fine grain setting minimun sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", 658 + input[1], smu->gfx_default_hard_min_freq); 659 + return -EINVAL; 660 + } 661 + smu->gfx_actual_hard_min_freq = input[1]; 662 + } else if (input[0] == 1) { 663 + if (input[1] > smu->gfx_default_soft_max_freq) { 664 + dev_warn(smu->adev->dev, "Fine grain setting maximun sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", 665 + input[1], smu->gfx_default_soft_max_freq); 666 + return -EINVAL; 667 + } 668 + smu->gfx_actual_soft_max_freq = input[1]; 669 + } else { 670 + return -EINVAL; 671 + } 672 + break; 673 + case PP_OD_RESTORE_DEFAULT_TABLE: 674 + if (size != 0) { 675 + dev_err(smu->adev->dev, "Input parameter number not correct\n"); 676 + return -EINVAL; 677 + } else { 678 + smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; 679 + smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; 680 + 681 + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 682 + smu->gfx_actual_hard_min_freq, NULL); 683 + if (ret) { 684 + dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); 685 + return ret; 686 + } 687 + 688 + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 689 + smu->gfx_actual_soft_max_freq, NULL); 690 + if (ret) { 691 + dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); 692 + return ret; 693 + } 694 + } 695 + break; 696 + case PP_OD_COMMIT_DPM_TABLE: 697 + if (size != 0) { 698 + dev_err(smu->adev->dev, "Input parameter number not correct\n"); 699 + return -EINVAL; 700 + } else { 701 + if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { 702 + dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", 703 + smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq); 704 + return -EINVAL; 705 + } 706 + 707 + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, 708 + smu->gfx_actual_hard_min_freq, NULL); 709 + if (ret) { 710 + dev_err(smu->adev->dev, "Set hard min sclk failed!"); 711 + return ret; 712 + } 713 + 714 + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, 715 + smu->gfx_actual_soft_max_freq, NULL); 716 + if (ret) { 717 + dev_err(smu->adev->dev, "Set soft max sclk failed!"); 718 + return ret; 719 + } 720 + } 721 + break; 722 + default: 723 + return -ENOSYS; 724 + } 725 + 726 + return ret; 727 + } 728 + 729 + int vangogh_set_default_dpm_tables(struct smu_context *smu) 730 + { 731 + struct smu_table_context *smu_table = &smu->smu_table; 732 + 733 + return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); 734 + } 735 + 736 + static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) 737 + { 738 + DpmClocks_t *clk_table = smu->smu_table.clocks_table; 739 + 740 + smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; 741 + smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; 742 + smu->gfx_actual_hard_min_freq = 0; 743 + smu->gfx_actual_soft_max_freq = 0; 744 + 745 + return 0; 746 + } 747 + 673 748 static const struct pptable_funcs vangogh_ppt_funcs = { 674 749 675 750 .check_fw_status = smu_v11_0_check_fw_status, ··· 804 659 .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, 805 660 .interrupt_work = smu_v11_0_interrupt_work, 806 661 .get_gpu_metrics = vangogh_get_gpu_metrics, 662 + .od_edit_dpm_table = vangogh_od_edit_dpm_table, 663 + .print_clk_levels = vangogh_print_fine_grain_clk, 664 + .set_default_dpm_table = vangogh_set_default_dpm_tables, 665 + .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, 807 666 }; 808 667 809 668 void vangogh_set_ppt_funcs(struct smu_context *smu)
+1
drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
··· 90 90 #define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu) 91 91 #define smu_post_init(smu) smu_ppt_funcs(post_init, 0, smu) 92 92 #define smu_gpo_control(smu, enablement) smu_ppt_funcs(gpo_control, 0, smu, enablement) 93 + #define smu_set_fine_grain_gfx_freq_parameters(smu) smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu) 93 94 94 95 #endif 95 96 #endif