Commit f4f85a8c authored by Alex Deucher's avatar Alex Deucher

drm/radeon/dpm: implement force performance levels for rv6xx

Allows you to limit the selected power levels via sysfs.
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 2333a003
...@@ -1161,6 +1161,7 @@ static struct radeon_asic rv6xx_asic = { ...@@ -1161,6 +1161,7 @@ static struct radeon_asic rv6xx_asic = {
.get_mclk = &rv6xx_dpm_get_mclk, .get_mclk = &rv6xx_dpm_get_mclk,
.print_power_state = &rv6xx_dpm_print_power_state, .print_power_state = &rv6xx_dpm_print_power_state,
.debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level, .debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level,
.force_performance_level = &rv6xx_dpm_force_performance_level,
}, },
.pflip = { .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .pre_page_flip = &rs600_pre_page_flip,
......
...@@ -421,6 +421,8 @@ void rv6xx_dpm_print_power_state(struct radeon_device *rdev, ...@@ -421,6 +421,8 @@ void rv6xx_dpm_print_power_state(struct radeon_device *rdev,
struct radeon_ps *ps); struct radeon_ps *ps);
void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
struct seq_file *m); struct seq_file *m);
int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
enum radeon_dpm_forced_level level);
/* rs780 dpm */ /* rs780 dpm */
int rs780_dpm_init(struct radeon_device *rdev); int rs780_dpm_init(struct radeon_device *rdev);
int rs780_dpm_enable(struct radeon_device *rdev); int rs780_dpm_enable(struct radeon_device *rdev);
......
...@@ -1670,6 +1670,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev) ...@@ -1670,6 +1670,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
struct radeon_ps *old_ps = rdev->pm.dpm.current_ps; struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
int ret; int ret;
pi->restricted_levels = 0;
rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); rv6xx_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
rv6xx_clear_vc(rdev); rv6xx_clear_vc(rdev);
...@@ -1756,6 +1758,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev) ...@@ -1756,6 +1758,8 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
return 0; return 0;
} }
...@@ -2085,3 +2089,34 @@ u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low) ...@@ -2085,3 +2089,34 @@ u32 rv6xx_dpm_get_mclk(struct radeon_device *rdev, bool low)
else else
return requested_state->high.mclk; return requested_state->high.mclk;
} }
int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
enum radeon_dpm_forced_level level)
{
struct rv6xx_power_info *pi = rv6xx_get_pi(rdev);
if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
pi->restricted_levels = 3;
} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
pi->restricted_levels = 2;
} else {
pi->restricted_levels = 0;
}
rv6xx_clear_vc(rdev);
r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, true);
r600_set_at(rdev, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF);
r600_wait_for_power_level(rdev, R600_POWER_LEVEL_LOW);
r600_power_level_enable(rdev, R600_POWER_LEVEL_HIGH, false);
r600_power_level_enable(rdev, R600_POWER_LEVEL_MEDIUM, false);
rv6xx_enable_medium(rdev);
rv6xx_enable_high(rdev);
if (pi->restricted_levels == 3)
r600_power_level_enable(rdev, R600_POWER_LEVEL_LOW, false);
rv6xx_program_vc(rdev);
rv6xx_program_at(rdev);
rdev->pm.dpm.forced_level = level;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment