aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-07-15 18:14:24 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-08-30 16:30:30 -0400
commit89536fd600f9997e776eef6c666cc61ea8c55f07 (patch)
tree994d2484a3cd8be3d8e9d71ebe0574038ff672ae
parent94b4adc5ae30fb451300bdca901ae9771f6baf5f (diff)
drm/radeon/dpm: implement force performance level for CI
Allows you to force the selected performance level via sysfs. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c153
-rw-r--r--drivers/gpu/drm/radeon/ppsmc.h1
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h2
4 files changed, 157 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 28b2b36f699d..9eebf1f7e223 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -3601,6 +3601,153 @@ static int ci_generate_dpm_level_enable_mask(struct radeon_device *rdev,
3601 return 0; 3601 return 0;
3602} 3602}
3603 3603
3604static u32 ci_get_lowest_enabled_level(struct radeon_device *rdev,
3605 u32 level_mask)
3606{
3607 u32 level = 0;
3608
3609 while ((level_mask & (1 << level)) == 0)
3610 level++;
3611
3612 return level;
3613}
3614
3615
3616int ci_dpm_force_performance_level(struct radeon_device *rdev,
3617 enum radeon_dpm_forced_level level)
3618{
3619 struct ci_power_info *pi = ci_get_pi(rdev);
3620 PPSMC_Result smc_result;
3621 u32 tmp, levels, i;
3622 int ret;
3623
3624 if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
3625 if ((!pi->sclk_dpm_key_disabled) &&
3626 pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3627 levels = 0;
3628 tmp = pi->dpm_level_enable_mask.sclk_dpm_enable_mask;
3629 while (tmp >>= 1)
3630 levels++;
3631 if (levels) {
3632 ret = ci_dpm_force_state_sclk(rdev, levels);
3633 if (ret)
3634 return ret;
3635 for (i = 0; i < rdev->usec_timeout; i++) {
3636 tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
3637 CURR_SCLK_INDEX_MASK) >> CURR_SCLK_INDEX_SHIFT;
3638 if (tmp == levels)
3639 break;
3640 udelay(1);
3641 }
3642 }
3643 }
3644 if ((!pi->mclk_dpm_key_disabled) &&
3645 pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3646 levels = 0;
3647 tmp = pi->dpm_level_enable_mask.mclk_dpm_enable_mask;
3648 while (tmp >>= 1)
3649 levels++;
3650 if (levels) {
3651 ret = ci_dpm_force_state_mclk(rdev, levels);
3652 if (ret)
3653 return ret;
3654 for (i = 0; i < rdev->usec_timeout; i++) {
3655 tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
3656 CURR_MCLK_INDEX_MASK) >> CURR_MCLK_INDEX_SHIFT;
3657 if (tmp == levels)
3658 break;
3659 udelay(1);
3660 }
3661 }
3662 }
3663 if ((!pi->pcie_dpm_key_disabled) &&
3664 pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3665 levels = 0;
3666 tmp = pi->dpm_level_enable_mask.pcie_dpm_enable_mask;
3667 while (tmp >>= 1)
3668 levels++;
3669 if (levels) {
3670 ret = ci_dpm_force_state_pcie(rdev, level);
3671 if (ret)
3672 return ret;
3673 for (i = 0; i < rdev->usec_timeout; i++) {
3674 tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX_1) &
3675 CURR_PCIE_INDEX_MASK) >> CURR_PCIE_INDEX_SHIFT;
3676 if (tmp == levels)
3677 break;
3678 udelay(1);
3679 }
3680 }
3681 }
3682 } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
3683 if ((!pi->sclk_dpm_key_disabled) &&
3684 pi->dpm_level_enable_mask.sclk_dpm_enable_mask) {
3685 levels = ci_get_lowest_enabled_level(rdev,
3686 pi->dpm_level_enable_mask.sclk_dpm_enable_mask);
3687 ret = ci_dpm_force_state_sclk(rdev, levels);
3688 if (ret)
3689 return ret;
3690 for (i = 0; i < rdev->usec_timeout; i++) {
3691 tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
3692 CURR_SCLK_INDEX_MASK) >> CURR_SCLK_INDEX_SHIFT;
3693 if (tmp == levels)
3694 break;
3695 udelay(1);
3696 }
3697 }
3698 if ((!pi->mclk_dpm_key_disabled) &&
3699 pi->dpm_level_enable_mask.mclk_dpm_enable_mask) {
3700 levels = ci_get_lowest_enabled_level(rdev,
3701 pi->dpm_level_enable_mask.mclk_dpm_enable_mask);
3702 ret = ci_dpm_force_state_mclk(rdev, levels);
3703 if (ret)
3704 return ret;
3705 for (i = 0; i < rdev->usec_timeout; i++) {
3706 tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) &
3707 CURR_MCLK_INDEX_MASK) >> CURR_MCLK_INDEX_SHIFT;
3708 if (tmp == levels)
3709 break;
3710 udelay(1);
3711 }
3712 }
3713 if ((!pi->pcie_dpm_key_disabled) &&
3714 pi->dpm_level_enable_mask.pcie_dpm_enable_mask) {
3715 levels = ci_get_lowest_enabled_level(rdev,
3716 pi->dpm_level_enable_mask.pcie_dpm_enable_mask);
3717 ret = ci_dpm_force_state_pcie(rdev, levels);
3718 if (ret)
3719 return ret;
3720 for (i = 0; i < rdev->usec_timeout; i++) {
3721 tmp = (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX_1) &
3722 CURR_PCIE_INDEX_MASK) >> CURR_PCIE_INDEX_SHIFT;
3723 if (tmp == levels)
3724 break;
3725 udelay(1);
3726 }
3727 }
3728 } else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
3729 if (!pi->sclk_dpm_key_disabled) {
3730 smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel);
3731 if (smc_result != PPSMC_Result_OK)
3732 return -EINVAL;
3733 }
3734 if (!pi->mclk_dpm_key_disabled) {
3735 smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_MCLKDPM_NoForcedLevel);
3736 if (smc_result != PPSMC_Result_OK)
3737 return -EINVAL;
3738 }
3739 if (!pi->pcie_dpm_key_disabled) {
3740 smc_result = ci_send_msg_to_smc(rdev, PPSMC_MSG_PCIeDPM_UnForceLevel);
3741 if (smc_result != PPSMC_Result_OK)
3742 return -EINVAL;
3743 }
3744 }
3745
3746 rdev->pm.dpm.forced_level = level;
3747
3748 return 0;
3749}
3750
3604static int ci_set_mc_special_registers(struct radeon_device *rdev, 3751static int ci_set_mc_special_registers(struct radeon_device *rdev,
3605 struct ci_mc_reg_table *table) 3752 struct ci_mc_reg_table *table)
3606{ 3753{
@@ -4548,6 +4695,12 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
4548 if (pi->pcie_performance_request) 4695 if (pi->pcie_performance_request)
4549 ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps); 4696 ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
4550 4697
4698 ret = ci_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
4699 if (ret) {
4700 DRM_ERROR("ci_dpm_force_performance_level failed\n");
4701 return ret;
4702 }
4703
4551 return 0; 4704 return 0;
4552} 4705}
4553 4706
diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h
index 4c1ee6df09a0..682842804bce 100644
--- a/drivers/gpu/drm/radeon/ppsmc.h
+++ b/drivers/gpu/drm/radeon/ppsmc.h
@@ -119,6 +119,7 @@ typedef uint8_t PPSMC_Result;
119#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) 119#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145)
120#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) 120#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146)
121#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) 121#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147)
122#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148)
122#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) 123#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a)
123#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e) 124#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e)
124#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f) 125#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f)
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index e28f08bbd4c0..705bc7498ff2 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -2468,6 +2468,7 @@ static struct radeon_asic ci_asic = {
2468 .get_mclk = &ci_dpm_get_mclk, 2468 .get_mclk = &ci_dpm_get_mclk,
2469 .print_power_state = &ci_dpm_print_power_state, 2469 .print_power_state = &ci_dpm_print_power_state,
2470 .debugfs_print_current_performance_level = &ci_dpm_debugfs_print_current_performance_level, 2470 .debugfs_print_current_performance_level = &ci_dpm_debugfs_print_current_performance_level,
2471 .force_performance_level = &ci_dpm_force_performance_level,
2471 }, 2472 },
2472 .pflip = { 2473 .pflip = {
2473 .pre_page_flip = &evergreen_pre_page_flip, 2474 .pre_page_flip = &evergreen_pre_page_flip,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 371a6f2c60ee..a88792865fa4 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -765,6 +765,8 @@ void ci_dpm_print_power_state(struct radeon_device *rdev,
765 struct radeon_ps *ps); 765 struct radeon_ps *ps);
766void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 766void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
767 struct seq_file *m); 767 struct seq_file *m);
768int ci_dpm_force_performance_level(struct radeon_device *rdev,
769 enum radeon_dpm_forced_level level);
768 770
769int kv_dpm_init(struct radeon_device *rdev); 771int kv_dpm_init(struct radeon_device *rdev);
770int kv_dpm_enable(struct radeon_device *rdev); 772int kv_dpm_enable(struct radeon_device *rdev);