diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-07-02 18:52:10 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-07-05 18:10:06 -0400 |
commit | 9b5de59629d2e58eab41e2f0e5cc60b3c395f1c3 (patch) | |
tree | 58c2805c7a3e4e0bb1d7480bcd359719ebf5eca5 /drivers/gpu | |
parent | 5d5e559193afd516daae9816e892bf2d97be0988 (diff) |
drm/radeon/dpm: implement force performance level for TN
Allows you to force the selected performance level via sysfs.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-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 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/trinity_dpm.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/trinity_dpm.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/trinity_smc.c | 7 |
6 files changed, 44 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h index fc71ca6b04c..b5564a3645d 100644 --- a/drivers/gpu/drm/radeon/ppsmc.h +++ b/drivers/gpu/drm/radeon/ppsmc.h @@ -103,6 +103,7 @@ typedef uint8_t PPSMC_Result; #define PPSMC_MSG_DPM_Config ((uint32_t) 0x102) #define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104) #define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112) #define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d) #define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e) #define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 5d592aed1ee..a6906d4ca73 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2115,6 +2115,7 @@ static struct radeon_asic trinity_asic = { .get_mclk = &trinity_dpm_get_mclk, .print_power_state = &trinity_dpm_print_power_state, .debugfs_print_current_performance_level = &trinity_dpm_debugfs_print_current_performance_level, + .force_performance_level = &trinity_dpm_force_performance_level, }, .pflip = { .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 1a89b3af04f..4456f85a932 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -636,6 +636,8 @@ void trinity_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m); +int trinity_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level); /* DCE6 - SI */ void dce6_bandwidth_update(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index 8a32bcc6bbb..a1eb5f59939 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c @@ -1158,6 +1158,37 @@ static void trinity_setup_nbp_sim(struct radeon_device *rdev, } } +int trinity_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level) +{ + struct trinity_power_info *pi = trinity_get_pi(rdev); + struct radeon_ps *rps = &pi->current_rps; + struct trinity_ps *ps = trinity_get_ps(rps); + int i, ret; + + if (ps->num_levels <= 1) + return 0; + + if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { + /* not supported by the hw */ + return -EINVAL; + } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { + ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1); + if (ret) + return ret; + } else { + for (i = 0; i < ps->num_levels; i++) { + ret = trinity_dpm_n_levels_disabled(rdev, 0); + if (ret) + return ret; + } + } + + rdev->pm.dpm.forced_level = level; + + return 0; +} + int trinity_dpm_pre_set_power_state(struct radeon_device *rdev) { struct trinity_power_info *pi = trinity_get_pi(rdev); @@ -1190,6 +1221,7 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev) trinity_force_level_0(rdev); trinity_unforce_levels(rdev); trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); + rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; } trinity_release_mutex(rdev); diff --git a/drivers/gpu/drm/radeon/trinity_dpm.h b/drivers/gpu/drm/radeon/trinity_dpm.h index c621b843aab..e82df071f8b 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.h +++ b/drivers/gpu/drm/radeon/trinity_dpm.h @@ -121,6 +121,7 @@ struct trinity_power_info { int trinity_dpm_config(struct radeon_device *rdev, bool enable); int trinity_uvd_dpm_config(struct radeon_device *rdev); int trinity_dpm_force_state(struct radeon_device *rdev, u32 n); +int trinity_dpm_n_levels_disabled(struct radeon_device *rdev, u32 n); int trinity_dpm_no_forced_level(struct radeon_device *rdev); int trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev, bool enable); diff --git a/drivers/gpu/drm/radeon/trinity_smc.c b/drivers/gpu/drm/radeon/trinity_smc.c index 85f86a29513..a42d89f1830 100644 --- a/drivers/gpu/drm/radeon/trinity_smc.c +++ b/drivers/gpu/drm/radeon/trinity_smc.c @@ -73,6 +73,13 @@ int trinity_dpm_force_state(struct radeon_device *rdev, u32 n) return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState); } +int trinity_dpm_n_levels_disabled(struct radeon_device *rdev, u32 n) +{ + WREG32_SMC(SMU_SCRATCH0, n); + + return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_N_LevelsDisabled); +} + int trinity_uvd_dpm_config(struct radeon_device *rdev) { return trinity_notify_message_to_smu(rdev, PPSMC_MSG_UVD_DPM_Config); |