aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c252
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.h7
2 files changed, 259 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index f97ecb49972e..578878d1d4c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -3681,6 +3681,40 @@ static int ci_find_boot_level(struct ci_single_dpm_table *table,
3681 return ret; 3681 return ret;
3682} 3682}
3683 3683
3684static void ci_save_default_power_profile(struct amdgpu_device *adev)
3685{
3686 struct ci_power_info *pi = ci_get_pi(adev);
3687 struct SMU7_Discrete_GraphicsLevel *levels =
3688 pi->smc_state_table.GraphicsLevel;
3689 uint32_t min_level = 0;
3690
3691 pi->default_gfx_power_profile.activity_threshold =
3692 be16_to_cpu(levels[0].ActivityLevel);
3693 pi->default_gfx_power_profile.up_hyst = levels[0].UpH;
3694 pi->default_gfx_power_profile.down_hyst = levels[0].DownH;
3695 pi->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
3696
3697 pi->default_compute_power_profile = pi->default_gfx_power_profile;
3698 pi->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
3699
3700 /* Optimize compute power profile: Use only highest
3701 * 2 power levels (if more than 2 are available), Hysteresis:
3702 * 0ms up, 5ms down
3703 */
3704 if (pi->smc_state_table.GraphicsDpmLevelCount > 2)
3705 min_level = pi->smc_state_table.GraphicsDpmLevelCount - 2;
3706 else if (pi->smc_state_table.GraphicsDpmLevelCount == 2)
3707 min_level = 1;
3708 pi->default_compute_power_profile.min_sclk =
3709 be32_to_cpu(levels[min_level].SclkFrequency);
3710
3711 pi->default_compute_power_profile.up_hyst = 0;
3712 pi->default_compute_power_profile.down_hyst = 5;
3713
3714 pi->gfx_power_profile = pi->default_gfx_power_profile;
3715 pi->compute_power_profile = pi->default_compute_power_profile;
3716}
3717
3684static int ci_init_smc_table(struct amdgpu_device *adev) 3718static int ci_init_smc_table(struct amdgpu_device *adev)
3685{ 3719{
3686 struct ci_power_info *pi = ci_get_pi(adev); 3720 struct ci_power_info *pi = ci_get_pi(adev);
@@ -3826,6 +3860,8 @@ static int ci_init_smc_table(struct amdgpu_device *adev)
3826 if (ret) 3860 if (ret)
3827 return ret; 3861 return ret;
3828 3862
3863 ci_save_default_power_profile(adev);
3864
3829 return 0; 3865 return 0;
3830} 3866}
3831 3867
@@ -6688,6 +6724,218 @@ static int ci_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value)
6688 return 0; 6724 return 0;
6689} 6725}
6690 6726
6727static int ci_dpm_get_power_profile_state(struct amdgpu_device *adev,
6728 struct amd_pp_profile *query)
6729{
6730 struct ci_power_info *pi = ci_get_pi(adev);
6731
6732 if (!pi || !query)
6733 return -EINVAL;
6734
6735 if (query->type == AMD_PP_GFX_PROFILE)
6736 memcpy(query, &pi->gfx_power_profile,
6737 sizeof(struct amd_pp_profile));
6738 else if (query->type == AMD_PP_COMPUTE_PROFILE)
6739 memcpy(query, &pi->compute_power_profile,
6740 sizeof(struct amd_pp_profile));
6741 else
6742 return -EINVAL;
6743
6744 return 0;
6745}
6746
6747static int ci_populate_requested_graphic_levels(struct amdgpu_device *adev,
6748 struct amd_pp_profile *request)
6749{
6750 struct ci_power_info *pi = ci_get_pi(adev);
6751 struct ci_dpm_table *dpm_table = &(pi->dpm_table);
6752 struct SMU7_Discrete_GraphicsLevel *levels =
6753 pi->smc_state_table.GraphicsLevel;
6754 uint32_t array = pi->dpm_table_start +
6755 offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
6756 uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) *
6757 SMU7_MAX_LEVELS_GRAPHICS;
6758 uint32_t i;
6759
6760 for (i = 0; i < dpm_table->sclk_table.count; i++) {
6761 levels[i].ActivityLevel =
6762 cpu_to_be16(request->activity_threshold);
6763 levels[i].EnabledForActivity = 1;
6764 levels[i].UpH = request->up_hyst;
6765 levels[i].DownH = request->down_hyst;
6766 }
6767
6768 return amdgpu_ci_copy_bytes_to_smc(adev, array, (uint8_t *)levels,
6769 array_size, pi->sram_end);
6770}
6771
6772static void ci_find_min_clock_masks(struct amdgpu_device *adev,
6773 uint32_t *sclk_mask, uint32_t *mclk_mask,
6774 uint32_t min_sclk, uint32_t min_mclk)
6775{
6776 struct ci_power_info *pi = ci_get_pi(adev);
6777 struct ci_dpm_table *dpm_table = &(pi->dpm_table);
6778 uint32_t i;
6779
6780 for (i = 0; i < dpm_table->sclk_table.count; i++) {
6781 if (dpm_table->sclk_table.dpm_levels[i].enabled &&
6782 dpm_table->sclk_table.dpm_levels[i].value >= min_sclk)
6783 *sclk_mask |= 1 << i;
6784 }
6785
6786 for (i = 0; i < dpm_table->mclk_table.count; i++) {
6787 if (dpm_table->mclk_table.dpm_levels[i].enabled &&
6788 dpm_table->mclk_table.dpm_levels[i].value >= min_mclk)
6789 *mclk_mask |= 1 << i;
6790 }
6791}
6792
6793static int ci_set_power_profile_state(struct amdgpu_device *adev,
6794 struct amd_pp_profile *request)
6795{
6796 struct ci_power_info *pi = ci_get_pi(adev);
6797 int tmp_result, result = 0;
6798 uint32_t sclk_mask = 0, mclk_mask = 0;
6799
6800 tmp_result = ci_freeze_sclk_mclk_dpm(adev);
6801 if (tmp_result) {
6802 DRM_ERROR("Failed to freeze SCLK MCLK DPM!");
6803 result = tmp_result;
6804 }
6805
6806 tmp_result = ci_populate_requested_graphic_levels(adev,
6807 request);
6808 if (tmp_result) {
6809 DRM_ERROR("Failed to populate requested graphic levels!");
6810 result = tmp_result;
6811 }
6812
6813 tmp_result = ci_unfreeze_sclk_mclk_dpm(adev);
6814 if (tmp_result) {
6815 DRM_ERROR("Failed to unfreeze SCLK MCLK DPM!");
6816 result = tmp_result;
6817 }
6818
6819 ci_find_min_clock_masks(adev, &sclk_mask, &mclk_mask,
6820 request->min_sclk, request->min_mclk);
6821
6822 if (sclk_mask) {
6823 if (!pi->sclk_dpm_key_disabled)
6824 amdgpu_ci_send_msg_to_smc_with_parameter(
6825 adev,
6826 PPSMC_MSG_SCLKDPM_SetEnabledMask,
6827 pi->dpm_level_enable_mask.
6828 sclk_dpm_enable_mask &
6829 sclk_mask);
6830 }
6831
6832 if (mclk_mask) {
6833 if (!pi->mclk_dpm_key_disabled)
6834 amdgpu_ci_send_msg_to_smc_with_parameter(
6835 adev,
6836 PPSMC_MSG_MCLKDPM_SetEnabledMask,
6837 pi->dpm_level_enable_mask.
6838 mclk_dpm_enable_mask &
6839 mclk_mask);
6840 }
6841
6842
6843 return result;
6844}
6845
6846static int ci_dpm_set_power_profile_state(struct amdgpu_device *adev,
6847 struct amd_pp_profile *request)
6848{
6849 struct ci_power_info *pi = ci_get_pi(adev);
6850 int ret = -1;
6851
6852 if (!pi || !request)
6853 return -EINVAL;
6854
6855 if (adev->pm.dpm.forced_level !=
6856 AMD_DPM_FORCED_LEVEL_AUTO)
6857 return -EINVAL;
6858
6859 if (request->min_sclk ||
6860 request->min_mclk ||
6861 request->activity_threshold ||
6862 request->up_hyst ||
6863 request->down_hyst) {
6864 if (request->type == AMD_PP_GFX_PROFILE)
6865 memcpy(&pi->gfx_power_profile, request,
6866 sizeof(struct amd_pp_profile));
6867 else if (request->type == AMD_PP_COMPUTE_PROFILE)
6868 memcpy(&pi->compute_power_profile, request,
6869 sizeof(struct amd_pp_profile));
6870 else
6871 return -EINVAL;
6872
6873 if (request->type == pi->current_power_profile)
6874 ret = ci_set_power_profile_state(
6875 adev,
6876 request);
6877 } else {
6878 /* set power profile if it exists */
6879 switch (request->type) {
6880 case AMD_PP_GFX_PROFILE:
6881 ret = ci_set_power_profile_state(
6882 adev,
6883 &pi->gfx_power_profile);
6884 break;
6885 case AMD_PP_COMPUTE_PROFILE:
6886 ret = ci_set_power_profile_state(
6887 adev,
6888 &pi->compute_power_profile);
6889 break;
6890 default:
6891 return -EINVAL;
6892 }
6893 }
6894
6895 if (!ret)
6896 pi->current_power_profile = request->type;
6897
6898 return 0;
6899}
6900
6901static int ci_dpm_reset_power_profile_state(struct amdgpu_device *adev,
6902 struct amd_pp_profile *request)
6903{
6904 struct ci_power_info *pi = ci_get_pi(adev);
6905
6906 if (!pi || !request)
6907 return -EINVAL;
6908
6909 if (request->type == AMD_PP_GFX_PROFILE) {
6910 pi->gfx_power_profile = pi->default_gfx_power_profile;
6911 return ci_dpm_set_power_profile_state(adev,
6912 &pi->gfx_power_profile);
6913 } else if (request->type == AMD_PP_COMPUTE_PROFILE) {
6914 pi->compute_power_profile =
6915 pi->default_compute_power_profile;
6916 return ci_dpm_set_power_profile_state(adev,
6917 &pi->compute_power_profile);
6918 } else
6919 return -EINVAL;
6920}
6921
6922static int ci_dpm_switch_power_profile(struct amdgpu_device *adev,
6923 enum amd_pp_profile_type type)
6924{
6925 struct ci_power_info *pi = ci_get_pi(adev);
6926 struct amd_pp_profile request = {0};
6927
6928 if (!pi)
6929 return -EINVAL;
6930
6931 if (pi->current_power_profile != type) {
6932 request.type = type;
6933 return ci_dpm_set_power_profile_state(adev, &request);
6934 }
6935
6936 return 0;
6937}
6938
6691const struct amd_ip_funcs ci_dpm_ip_funcs = { 6939const struct amd_ip_funcs ci_dpm_ip_funcs = {
6692 .name = "ci_dpm", 6940 .name = "ci_dpm",
6693 .early_init = ci_dpm_early_init, 6941 .early_init = ci_dpm_early_init,
@@ -6730,6 +6978,10 @@ static const struct amdgpu_dpm_funcs ci_dpm_funcs = {
6730 .set_mclk_od = ci_dpm_set_mclk_od, 6978 .set_mclk_od = ci_dpm_set_mclk_od,
6731 .check_state_equal = ci_check_state_equal, 6979 .check_state_equal = ci_check_state_equal,
6732 .get_vce_clock_state = amdgpu_get_vce_clock_state, 6980 .get_vce_clock_state = amdgpu_get_vce_clock_state,
6981 .get_power_profile_state = ci_dpm_get_power_profile_state,
6982 .set_power_profile_state = ci_dpm_set_power_profile_state,
6983 .reset_power_profile_state = ci_dpm_reset_power_profile_state,
6984 .switch_power_profile = ci_dpm_switch_power_profile,
6733}; 6985};
6734 6986
6735static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev) 6987static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.h b/drivers/gpu/drm/amd/amdgpu/ci_dpm.h
index 91be2996ae7c..84cbc9c45f4d 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.h
@@ -295,6 +295,13 @@ struct ci_power_info {
295 bool fan_is_controlled_by_smc; 295 bool fan_is_controlled_by_smc;
296 u32 t_min; 296 u32 t_min;
297 u32 fan_ctrl_default_mode; 297 u32 fan_ctrl_default_mode;
298
299 /* power profile */
300 struct amd_pp_profile gfx_power_profile;
301 struct amd_pp_profile compute_power_profile;
302 struct amd_pp_profile default_gfx_power_profile;
303 struct amd_pp_profile default_compute_power_profile;
304 enum amd_pp_profile_type current_power_profile;
298}; 305};
299 306
300#define CISLANDS_VOLTAGE_CONTROL_NONE 0x0 307#define CISLANDS_VOLTAGE_CONTROL_NONE 0x0