From: Alex Deucher Date: Tue, 2 Jul 2013 22:52:10 +0000 (-0400) Subject: drm/radeon/dpm: implement force performance level for TN X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=9b5de59629d2e58eab41e2f0e5cc60b3c395f1c3;p=linux-beck.git drm/radeon/dpm: implement force performance level for TN Allows you to force the selected performance level via sysfs. Signed-off-by: Alex Deucher --- 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);