diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-07-25 20:07:25 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-07-25 20:07:25 -0400 |
commit | f4f85a8c94752300ad2c4f7a3475a3d3b8ef72ca (patch) | |
tree | 0f7e496a1587541cc27654627b7d2b85822ab669 | |
parent | 2333a003a83ae8b257ac4bc1bb297c897c1ebb90 (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.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rv6xx_dpm.c | 35 |
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); |
422 | void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, | 422 | void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, |
423 | struct seq_file *m); | 423 | struct seq_file *m); |
424 | int rv6xx_dpm_force_performance_level(struct radeon_device *rdev, | ||
425 | enum radeon_dpm_forced_level level); | ||
424 | /* rs780 dpm */ | 426 | /* rs780 dpm */ |
425 | int rs780_dpm_init(struct radeon_device *rdev); | 427 | int rs780_dpm_init(struct radeon_device *rdev); |
426 | int rs780_dpm_enable(struct radeon_device *rdev); | 428 | int 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 | |||
2093 | int 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 | } | ||