summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon/si_dpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/si_dpm.c')
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c65
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 6918f07..73aaa2e 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -28,6 +28,7 @@
#include "si_dpm.h"
#include "atom.h"
#include <linux/math64.h>
+#include <linux/seq_file.h>
#define MC_CG_ARB_FREQ_F0 0x0a
#define MC_CG_ARB_FREQ_F1 0x0b
@@ -2905,7 +2906,8 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
u16 vddc, vddci;
int i;
- if (rdev->pm.dpm.new_active_crtc_count > 1)
+ if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
+ ni_dpm_vblank_too_short(rdev))
disable_mclk_switching = true;
else
disable_mclk_switching = false;
@@ -3230,16 +3232,38 @@ static int si_restrict_performance_levels_before_switch(struct radeon_device *rd
0 : -EINVAL;
}
-#if 0
-static int si_unrestrict_performance_levels_after_switch(struct radeon_device *rdev)
+int si_dpm_force_performance_level(struct radeon_device *rdev,
+ enum radeon_dpm_forced_level level)
{
- if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
- return -EINVAL;
+ struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+ struct ni_ps *ps = ni_get_ps(rps);
+ u32 levels;
- return (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) == PPSMC_Result_OK) ?
- 0 : -EINVAL;
+ if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
+ if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
+ return -EINVAL;
+
+ if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
+ return -EINVAL;
+ } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
+ if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
+ return -EINVAL;
+
+ levels = ps->performance_level_count - 1;
+ if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
+ return -EINVAL;
+ } else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
+ if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
+ return -EINVAL;
+
+ if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
+ return -EINVAL;
+ }
+
+ rdev->pm.dpm.forced_level = level;
+
+ return 0;
}
-#endif
static int si_set_boot_state(struct radeon_device *rdev)
{
@@ -5991,11 +6015,13 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
#if 0
/* XXX */
- ret = si_unrestrict_performance_levels_after_switch(rdev);
+ ret = si_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
if (ret) {
- DRM_ERROR("si_unrestrict_performance_levels_after_switch failed\n");
+ DRM_ERROR("si_dpm_force_performance_level failed\n");
return ret;
}
+#else
+ rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
#endif
return 0;
@@ -6385,3 +6411,22 @@ void si_dpm_fini(struct radeon_device *rdev)
r600_free_extended_power_table(rdev);
}
+void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
+ struct seq_file *m)
+{
+ struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+ struct ni_ps *ps = ni_get_ps(rps);
+ struct rv7xx_pl *pl;
+ u32 current_index =
+ (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
+ CURRENT_STATE_INDEX_SHIFT;
+
+ if (current_index >= ps->performance_level_count) {
+ seq_printf(m, "invalid dpm profile %d\n", current_index);
+ } else {
+ pl = &ps->performance_levels[current_index];
+ seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
+ seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",
+ current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
+ }
+}