drm/radeon/kms/pm: rework power management

Add two new sysfs attributes:
- dynpm
- power_state

Echoing 0/1 to dynpm disables/enables dynamic power management.
The driver scales the sclk dynamically based on the number of
queued fences.  dynpm only scales sclk dynamically in single head
mode.

Echoing x.y to power_state selects a static power state (x) and clock
mode (y).  This allows you to statically select a power state and clock
mode.  Selecting a static clock mode will disable dynpm.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Alex Deucher
2010-04-24 14:50:23 -04:00
committed by Dave Airlie
parent 49e02b7306
commit a424816fb3
5 changed files with 229 additions and 56 deletions

View File

@@ -247,7 +247,7 @@ void r600_get_power_state(struct radeon_device *rdev,
pcie_lanes);
}
void r600_set_power_state(struct radeon_device *rdev)
void r600_set_power_state(struct radeon_device *rdev, bool static_switch)
{
u32 sclk, mclk;
@@ -266,37 +266,52 @@ void r600_set_power_state(struct radeon_device *rdev)
clock_info[rdev->pm.requested_clock_mode_index].mclk;
if (mclk > rdev->clock.default_mclk)
mclk = rdev->clock.default_mclk;
/* don't change the mclk with multiple crtcs */
if (rdev->pm.active_crtc_count > 1)
mclk = rdev->clock.default_mclk;
/* set pcie lanes */
/* TODO */
/* voltage, pcie lanes, etc.*/
radeon_pm_misc(rdev);
/* set voltage */
/* TODO */
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_sync_with_vblank(rdev);
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_engine_clock(rdev, sclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_sclk = sclk;
DRM_INFO("Setting: e: %d\n", sclk);
}
if (static_switch) {
radeon_pm_prepare(rdev);
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_set_engine_clock(rdev, sclk);
rdev->pm.current_sclk = sclk;
DRM_INFO("Setting: e: %d\n", sclk);
}
#if 0
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_set_memory_clock(rdev, mclk);
rdev->pm.current_mclk = mclk;
DRM_INFO("Setting: m: %d\n", mclk);
}
#endif
radeon_pm_finish(rdev);
} else {
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_sync_with_vblank(rdev);
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_engine_clock(rdev, sclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_sclk = sclk;
DRM_INFO("Setting: e: %d\n", sclk);
}
#if 0
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_sync_with_vblank(rdev);
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_set_memory_clock(rdev, mclk);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_mclk = mclk;
DRM_INFO("Setting: m: %d\n", mclk);
}
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_sync_with_vblank(rdev);
radeon_pm_debug_check_in_vbl(rdev, false);
radeon_pm_prepare(rdev);
radeon_set_memory_clock(rdev, mclk);
radeon_pm_finish(rdev);
radeon_pm_debug_check_in_vbl(rdev, true);
rdev->pm.current_mclk = mclk;
DRM_INFO("Setting: m: %d\n", mclk);
}
#endif
}
rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;