summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-07-03 02:52:10 +0400
committerAlex Deucher <alexander.deucher@amd.com>2013-07-06 02:10:06 +0400
commit9b5de59629d2e58eab41e2f0e5cc60b3c395f1c3 (patch)
tree58c2805c7a3e4e0bb1d7480bcd359719ebf5eca5 /drivers/gpu
parent5d5e559193afd516daae9816e892bf2d97be0988 (diff)
downloadlinux-9b5de59629d2e58eab41e2f0e5cc60b3c395f1c3.tar.xz
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.h1
-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/trinity_dpm.c32
-rw-r--r--drivers/gpu/drm/radeon/trinity_dpm.h1
-rw-r--r--drivers/gpu/drm/radeon/trinity_smc.c7
6 files changed, 44 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h
index fc71ca6b04ca..b5564a3645d2 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 5d592aed1ee9..a6906d4ca734 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 1a89b3af04f3..4456f85a932e 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 8a32bcc6bbb5..a1eb5f59939f 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 c621b843aab5..e82df071f8b3 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 85f86a29513c..a42d89f1830c 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);