diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-07-15 18:14:24 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-08-30 16:30:30 -0400 |
commit | 89536fd600f9997e776eef6c666cc61ea8c55f07 (patch) | |
tree | 994d2484a3cd8be3d8e9d71ebe0574038ff672ae | |
parent | 94b4adc5ae30fb451300bdca901ae9771f6baf5f (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.c | 153 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/ppsmc.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 2 |
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 | ||
3604 | static 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 | |||
3616 | int 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 | |||
3604 | static int ci_set_mc_special_registers(struct radeon_device *rdev, | 3751 | static 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); |
766 | void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, | 766 | void ci_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, |
767 | struct seq_file *m); | 767 | struct seq_file *m); |
768 | int ci_dpm_force_performance_level(struct radeon_device *rdev, | ||
769 | enum radeon_dpm_forced_level level); | ||
768 | 770 | ||
769 | int kv_dpm_init(struct radeon_device *rdev); | 771 | int kv_dpm_init(struct radeon_device *rdev); |
770 | int kv_dpm_enable(struct radeon_device *rdev); | 772 | int kv_dpm_enable(struct radeon_device *rdev); |