aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-07-25 20:07:25 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-07-25 20:07:25 -0400
commitf4f85a8c94752300ad2c4f7a3475a3d3b8ef72ca (patch)
tree0f7e496a1587541cc27654627b7d2b85822ab669
parent2333a003a83ae8b257ac4bc1bb297c897c1ebb90 (diff)
drm/radeon/dpm: implement force performance levels for rv6xx
Allows you to limit the selected power levels via sysfs. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h2
-rw-r--r--drivers/gpu/drm/radeon/rv6xx_dpm.c35
3 files changed, 38 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 78bec1a58ed1..f8f8b3113ddd 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -1161,6 +1161,7 @@ static struct radeon_asic rv6xx_asic = {
1161 .get_mclk = &rv6xx_dpm_get_mclk, 1161 .get_mclk = &rv6xx_dpm_get_mclk,
1162 .print_power_state = &rv6xx_dpm_print_power_state, 1162 .print_power_state = &rv6xx_dpm_print_power_state,
1163 .debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level, 1163 .debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level,
1164 .force_performance_level = &rv6xx_dpm_force_performance_level,
1164 }, 1165 },
1165 .pflip = { 1166 .pflip = {
1166 .pre_page_flip = &rs600_pre_page_flip, 1167 .pre_page_flip = &rs600_pre_page_flip,
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index ca1895709908..902479fa737f 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -421,6 +421,8 @@ void rv6xx_dpm_print_power_state(struct radeon_device *rdev,
421 struct radeon_ps *ps); 421 struct radeon_ps *ps);
422void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 422void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
423 struct seq_file *m); 423 struct seq_file *m);
424int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
425 enum radeon_dpm_forced_level level);
424/* rs780 dpm */ 426/* rs780 dpm */
425int rs780_dpm_init(struct radeon_device *rdev); 427int rs780_dpm_init(struct radeon_device *rdev);
426int rs780_dpm_enable(struct radeon_device *rdev); 428int rs780_dpm_enable(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c
index dde402340f22..363018c60412 100644
--- a/drivers/gpu/drm/radeon/rv6xx_dpm.c
+++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c
@@ -1670,6 +1670,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
1670 struct radeon_ps *old_ps = rdev->pm.dpm.current_ps; 1670 struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
1671 int ret; 1671 int ret;
1672 1672
1673 pi->restricted_levels = 0;
1674
1673 rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); 1675 rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
1674 1676
1675 rv6xx_clear_vc(rdev); 1677 rv6xx_clear_vc(rdev);
@@ -1756,6 +1758,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
1756 1758
1757 rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 1759 rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1758 1760
1761 rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
1762
1759 return 0; 1763 return 0;
1760} 1764}
1761 1765
@@ -2085,3 +2089,34 @@ u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low)
2085 else 2089 else
2086 return requested_state->high.mclk; 2090 return requested_state->high.mclk;
2087} 2091}
2092
2093int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
2094 enum radeon_dpm_forced_level level)
2095{
2096 struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
2097
2098 if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
2099 pi->restricted_levels = 3;
2100 } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
2101 pi->restricted_levels = 2;
2102 } else {
2103 pi->restricted_levels = 0;
2104 }
2105
2106 rv6xx_clear_vc(rdev);
2107 r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true);
2108 r600_set_at(rdev, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
2109 r600_wait_for_power_level(rdev, R600_POWER_LEVEL_LOW);
2110 r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false);
2111 r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false);
2112 rv6xx_enable_medium(rdev);
2113 rv6xx_enable_high(rdev);
2114 if (pi->restricted_levels == 3)
2115 r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, false);
2116 rv6xx_program_vc(rdev);
2117 rv6xx_program_at(rdev);
2118
2119 rdev->pm.dpm.forced_level = level;
2120
2121 return 0;
2122}