Commit ce8f5370 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms/pm: rework power management

- Separate dynpm and profile based power management methods.  You can select the pm method
  by echoing the selected method ("dynpm" or "profile") to power_method in sysfs.
- Expose basic 4 profile in profile method
  "default" - default clocks
  "auto" - select between low and high based on ac/dc state
  "low" - DC, low power mode
  "high" - AC, performance mode
  The current base profile is "default", but it should switched to "auto" once we've tested
  on more systems.  Switching the state is a matter of echoing the requested profile to
  power_profile in sysfs.  The lowest power states are selected automatically when dpms turns
  the monitors off in all states but default.
- Remove dynamic fence-based reclocking for the moment.  We can revisit this later once we
  have basic pm in.
- Move pm init/fini to modesetting path.  pm is tightly coupled with display state.  Make sure
  display side is initialized before pm.
- Add pm suspend/resume functions to make sure pm state is properly reinitialized on resume.
- Remove dynpm module option.  It's now selectable via sysfs.
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent d7311171
config DRM_RADEON_KMS config DRM_RADEON_KMS
bool "Enable modesetting on radeon by default - NEW DRIVER" bool "Enable modesetting on radeon by default - NEW DRIVER"
depends on DRM_RADEON depends on DRM_RADEON
depends on POWER_SUPPLY
help help
Choose this option if you want kernel modesetting enabled by default. Choose this option if you want kernel modesetting enabled by default.
......
...@@ -2115,8 +2115,6 @@ int evergreen_init(struct radeon_device *rdev) ...@@ -2115,8 +2115,6 @@ int evergreen_init(struct radeon_device *rdev)
r = radeon_clocks_init(rdev); r = radeon_clocks_init(rdev);
if (r) if (r)
return r; return r;
/* Initialize power management */
radeon_pm_init(rdev);
/* Fence driver */ /* Fence driver */
r = radeon_fence_driver_init(rdev); r = radeon_fence_driver_init(rdev);
if (r) if (r)
...@@ -2178,7 +2176,6 @@ int evergreen_init(struct radeon_device *rdev) ...@@ -2178,7 +2176,6 @@ int evergreen_init(struct radeon_device *rdev)
void evergreen_fini(struct radeon_device *rdev) void evergreen_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
/*r600_blit_fini(rdev);*/ /*r600_blit_fini(rdev);*/
r700_cp_fini(rdev); r700_cp_fini(rdev);
r600_wb_fini(rdev); r600_wb_fini(rdev);
......
...@@ -68,22 +68,21 @@ MODULE_FIRMWARE(FIRMWARE_R520); ...@@ -68,22 +68,21 @@ MODULE_FIRMWARE(FIRMWARE_R520);
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
*/ */
void r100_get_power_state(struct radeon_device *rdev, void r100_pm_get_dynpm_state(struct radeon_device *rdev)
enum radeon_pm_action action)
{ {
int i; int i;
rdev->pm.can_upclock = true; rdev->pm.dynpm_can_upclock = true;
rdev->pm.can_downclock = true; rdev->pm.dynpm_can_downclock = true;
switch (action) { switch (rdev->pm.dynpm_planned_action) {
case PM_ACTION_MINIMUM: case DYNPM_ACTION_MINIMUM:
rdev->pm.requested_power_state_index = 0; rdev->pm.requested_power_state_index = 0;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
break; break;
case PM_ACTION_DOWNCLOCK: case DYNPM_ACTION_DOWNCLOCK:
if (rdev->pm.current_power_state_index == 0) { if (rdev->pm.current_power_state_index == 0) {
rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
} else { } else {
if (rdev->pm.active_crtc_count > 1) { if (rdev->pm.active_crtc_count > 1) {
for (i = 0; i < rdev->pm.num_power_states; i++) { for (i = 0; i < rdev->pm.num_power_states; i++) {
...@@ -108,10 +107,10 @@ void r100_get_power_state(struct radeon_device *rdev, ...@@ -108,10 +107,10 @@ void r100_get_power_state(struct radeon_device *rdev,
rdev->pm.requested_power_state_index++; rdev->pm.requested_power_state_index++;
} }
break; break;
case PM_ACTION_UPCLOCK: case DYNPM_ACTION_UPCLOCK:
if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
} else { } else {
if (rdev->pm.active_crtc_count > 1) { if (rdev->pm.active_crtc_count > 1) {
for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
...@@ -130,11 +129,11 @@ void r100_get_power_state(struct radeon_device *rdev, ...@@ -130,11 +129,11 @@ void r100_get_power_state(struct radeon_device *rdev,
rdev->pm.current_power_state_index + 1; rdev->pm.current_power_state_index + 1;
} }
break; break;
case PM_ACTION_DEFAULT: case DYNPM_ACTION_DEFAULT:
rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
break; break;
case PM_ACTION_NONE: case DYNPM_ACTION_NONE:
default: default:
DRM_ERROR("Requested mode for not defined action\n"); DRM_ERROR("Requested mode for not defined action\n");
return; return;
...@@ -151,77 +150,33 @@ void r100_get_power_state(struct radeon_device *rdev, ...@@ -151,77 +150,33 @@ void r100_get_power_state(struct radeon_device *rdev,
pcie_lanes); pcie_lanes);
} }
void r100_set_power_state(struct radeon_device *rdev, bool static_switch) void r100_pm_init_profile(struct radeon_device *rdev)
{ {
u32 sclk, mclk; /* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
if (rdev->pm.current_power_state_index == rdev->pm.requested_power_state_index) rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
return; rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
if (radeon_gui_idle(rdev)) { /* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
clock_info[rdev->pm.requested_clock_mode_index].sclk; rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
if (sclk > rdev->clock.default_sclk) rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
sclk = rdev->clock.default_sclk; /* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
clock_info[rdev->pm.requested_clock_mode_index].mclk; rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
if (mclk > rdev->clock.default_mclk) rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
mclk = rdev->clock.default_mclk; /* low mh */
/* don't change the mclk with multiple crtcs */ rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
if (rdev->pm.active_crtc_count > 1) rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
mclk = rdev->clock.default_mclk; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
/* voltage, pcie lanes, etc.*/ /* high mh */
radeon_pm_misc(rdev); rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
if (static_switch) { rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
radeon_pm_prepare(rdev); rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
/* 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);
}
/* 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);
}
radeon_pm_finish(rdev);
} else {
radeon_sync_with_vblank(rdev);
if (!radeon_pm_in_vbl(rdev))
return;
radeon_pm_prepare(rdev);
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
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);
}
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
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);
}
radeon_pm_finish(rdev);
}
rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
} else
DRM_INFO("pm: GUI not idle!!!\n");
} }
void r100_pm_misc(struct radeon_device *rdev) void r100_pm_misc(struct radeon_device *rdev)
...@@ -3815,7 +3770,6 @@ int r100_suspend(struct radeon_device *rdev) ...@@ -3815,7 +3770,6 @@ int r100_suspend(struct radeon_device *rdev)
void r100_fini(struct radeon_device *rdev) void r100_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -3871,8 +3825,6 @@ int r100_init(struct radeon_device *rdev) ...@@ -3871,8 +3825,6 @@ int r100_init(struct radeon_device *rdev)
r100_errata(rdev); r100_errata(rdev);
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize AGP */ /* initialize AGP */
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
......
...@@ -1345,7 +1345,6 @@ int r300_suspend(struct radeon_device *rdev) ...@@ -1345,7 +1345,6 @@ int r300_suspend(struct radeon_device *rdev)
void r300_fini(struct radeon_device *rdev) void r300_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -1401,8 +1400,6 @@ int r300_init(struct radeon_device *rdev) ...@@ -1401,8 +1400,6 @@ int r300_init(struct radeon_device *rdev)
r300_errata(rdev); r300_errata(rdev);
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize AGP */ /* initialize AGP */
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
......
...@@ -36,6 +36,35 @@ ...@@ -36,6 +36,35 @@
#include "r420d.h" #include "r420d.h"
#include "r420_reg_safe.h" #include "r420_reg_safe.h"
void r420_pm_init_profile(struct radeon_device *rdev)
{
/* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
}
static void r420_set_reg_safe(struct radeon_device *rdev) static void r420_set_reg_safe(struct radeon_device *rdev)
{ {
rdev->config.r300.reg_safe_bm = r420_reg_safe_bm; rdev->config.r300.reg_safe_bm = r420_reg_safe_bm;
...@@ -268,7 +297,6 @@ int r420_suspend(struct radeon_device *rdev) ...@@ -268,7 +297,6 @@ int r420_suspend(struct radeon_device *rdev)
void r420_fini(struct radeon_device *rdev) void r420_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -328,8 +356,6 @@ int r420_init(struct radeon_device *rdev) ...@@ -328,8 +356,6 @@ int r420_init(struct radeon_device *rdev)
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize AGP */ /* initialize AGP */
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
......
...@@ -261,8 +261,6 @@ int r520_init(struct radeon_device *rdev) ...@@ -261,8 +261,6 @@ int r520_init(struct radeon_device *rdev)
} }
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize AGP */ /* initialize AGP */
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
......
...@@ -92,13 +92,12 @@ void r600_gpu_init(struct radeon_device *rdev); ...@@ -92,13 +92,12 @@ void r600_gpu_init(struct radeon_device *rdev);
void r600_fini(struct radeon_device *rdev); void r600_fini(struct radeon_device *rdev);
void r600_irq_disable(struct radeon_device *rdev); void r600_irq_disable(struct radeon_device *rdev);
void r600_get_power_state(struct radeon_device *rdev, void r600_pm_get_dynpm_state(struct radeon_device *rdev)
enum radeon_pm_action action)
{ {
int i; int i;
rdev->pm.can_upclock = true; rdev->pm.dynpm_can_upclock = true;
rdev->pm.can_downclock = true; rdev->pm.dynpm_can_downclock = true;
/* power state array is low to high, default is first */ /* power state array is low to high, default is first */
if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) { if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) {
...@@ -107,16 +106,16 @@ void r600_get_power_state(struct radeon_device *rdev, ...@@ -107,16 +106,16 @@ void r600_get_power_state(struct radeon_device *rdev,
if (rdev->pm.num_power_states > 2) if (rdev->pm.num_power_states > 2)
min_power_state_index = 1; min_power_state_index = 1;
switch (action) { switch (rdev->pm.dynpm_planned_action) {
case PM_ACTION_MINIMUM: case DYNPM_ACTION_MINIMUM:
rdev->pm.requested_power_state_index = min_power_state_index; rdev->pm.requested_power_state_index = min_power_state_index;
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
break; break;
case PM_ACTION_DOWNCLOCK: case DYNPM_ACTION_DOWNCLOCK:
if (rdev->pm.current_power_state_index == min_power_state_index) { if (rdev->pm.current_power_state_index == min_power_state_index) {
rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
} else { } else {
if (rdev->pm.active_crtc_count > 1) { if (rdev->pm.active_crtc_count > 1) {
for (i = 0; i < rdev->pm.num_power_states; i++) { for (i = 0; i < rdev->pm.num_power_states; i++) {
...@@ -144,10 +143,10 @@ void r600_get_power_state(struct radeon_device *rdev, ...@@ -144,10 +143,10 @@ void r600_get_power_state(struct radeon_device *rdev,
rdev->pm.requested_power_state_index++; rdev->pm.requested_power_state_index++;
} }
break; break;
case PM_ACTION_UPCLOCK: case DYNPM_ACTION_UPCLOCK:
if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
} else { } else {
if (rdev->pm.active_crtc_count > 1) { if (rdev->pm.active_crtc_count > 1) {
for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
...@@ -168,12 +167,12 @@ void r600_get_power_state(struct radeon_device *rdev, ...@@ -168,12 +167,12 @@ void r600_get_power_state(struct radeon_device *rdev,
} }
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
break; break;
case PM_ACTION_DEFAULT: case DYNPM_ACTION_DEFAULT:
rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
break; break;
case PM_ACTION_NONE: case DYNPM_ACTION_NONE:
default: default:
DRM_ERROR("Requested mode for not defined action\n"); DRM_ERROR("Requested mode for not defined action\n");
return; return;
...@@ -200,22 +199,22 @@ void r600_get_power_state(struct radeon_device *rdev, ...@@ -200,22 +199,22 @@ void r600_get_power_state(struct radeon_device *rdev,
} else } else
rdev->pm.requested_power_state_index = 1; rdev->pm.requested_power_state_index = 1;
switch (action) { switch (rdev->pm.dynpm_planned_action) {
case PM_ACTION_MINIMUM: case DYNPM_ACTION_MINIMUM:
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
break; break;
case PM_ACTION_DOWNCLOCK: case DYNPM_ACTION_DOWNCLOCK:
if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
if (rdev->pm.current_clock_mode_index == 0) { if (rdev->pm.current_clock_mode_index == 0) {
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
} else } else
rdev->pm.requested_clock_mode_index = rdev->pm.requested_clock_mode_index =
rdev->pm.current_clock_mode_index - 1; rdev->pm.current_clock_mode_index - 1;
} else { } else {
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
rdev->pm.can_downclock = false; rdev->pm.dynpm_can_downclock = false;
} }
/* don't use the power state if crtcs are active and no display flag is set */ /* don't use the power state if crtcs are active and no display flag is set */
if ((rdev->pm.active_crtc_count > 0) && if ((rdev->pm.active_crtc_count > 0) &&
...@@ -225,27 +224,27 @@ void r600_get_power_state(struct radeon_device *rdev, ...@@ -225,27 +224,27 @@ void r600_get_power_state(struct radeon_device *rdev,
rdev->pm.requested_clock_mode_index++; rdev->pm.requested_clock_mode_index++;
} }
break; break;
case PM_ACTION_UPCLOCK: case DYNPM_ACTION_UPCLOCK:
if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
if (rdev->pm.current_clock_mode_index == if (rdev->pm.current_clock_mode_index ==
(rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) { (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) {
rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index; rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
} else } else
rdev->pm.requested_clock_mode_index = rdev->pm.requested_clock_mode_index =
rdev->pm.current_clock_mode_index + 1; rdev->pm.current_clock_mode_index + 1;
} else { } else {
rdev->pm.requested_clock_mode_index = rdev->pm.requested_clock_mode_index =
rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1; rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
} }
break; break;
case PM_ACTION_DEFAULT: case DYNPM_ACTION_DEFAULT:
rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.requested_clock_mode_index = 0; rdev->pm.requested_clock_mode_index = 0;
rdev->pm.can_upclock = false; rdev->pm.dynpm_can_upclock = false;
break; break;
case PM_ACTION_NONE: case DYNPM_ACTION_NONE:
default: default:
DRM_ERROR("Requested mode for not defined action\n"); DRM_ERROR("Requested mode for not defined action\n");
return; return;
...@@ -261,73 +260,225 @@ void r600_get_power_state(struct radeon_device *rdev, ...@@ -261,73 +260,225 @@ void r600_get_power_state(struct radeon_device *rdev,
pcie_lanes); pcie_lanes);
} }
void r600_set_power_state(struct radeon_device *rdev, bool static_switch) static int r600_pm_get_type_index(struct radeon_device *rdev,
enum radeon_pm_state_type ps_type,
int instance)
{ {
u32 sclk, mclk; int i;
int found_instance = -1;
if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
return;
if (radeon_gui_idle(rdev)) {
sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
clock_info[rdev->pm.requested_clock_mode_index].sclk;
if (sclk > rdev->clock.default_sclk)
sclk = rdev->clock.default_sclk;
mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
clock_info[rdev->pm.requested_clock_mode_index].mclk;
if (mclk > rdev->clock.default_mclk)
mclk = rdev->clock.default_mclk;
/* voltage, pcie lanes, etc.*/
radeon_pm_misc(rdev);
if (static_switch) { for (i = 0; i < rdev->pm.num_power_states; i++) {
radeon_pm_prepare(rdev); if (rdev->pm.power_state[i].type == ps_type) {
/* set engine clock */ found_instance++;
if (sclk != rdev->pm.current_sclk) { if (found_instance == instance)
radeon_set_engine_clock(rdev, sclk); return i;
rdev->pm.current_sclk = sclk; }
DRM_INFO("Setting: e: %d\n", sclk); }
} /* return default if no match */
/* set memory clock */ return rdev->pm.default_power_state_index;
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { }
radeon_set_memory_clock(rdev, mclk);
rdev->pm.current_mclk = mclk; void rs780_pm_init_profile(struct radeon_device *rdev)
DRM_INFO("Setting: m: %d\n", mclk); {
} if (rdev->pm.num_power_states == 2) {
radeon_pm_finish(rdev); /* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
} else if (rdev->pm.num_power_states == 3) {
/* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
} else {
/* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
}
}
void r600_pm_init_profile(struct radeon_device *rdev)
{
if (rdev->family == CHIP_R600) {
/* XXX */
/* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 2;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
} else if (rdev->flags & RADEON_IS_MOBILITY) {
/* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 2;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx =
r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
} else {
if (rdev->pm.num_power_states < 4) {
/* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
/* low sh */
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 2;
/* high sh */
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
/* low mh */
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2;
/* high mh */
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
} else { } else {
radeon_sync_with_vblank(rdev); /* default */
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
if (!radeon_pm_in_vbl(rdev)) rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
return; rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
radeon_pm_prepare(rdev); /* low sh */
if (sclk != rdev->pm.current_sclk) { rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1;
radeon_pm_debug_check_in_vbl(rdev, false); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1;
radeon_set_engine_clock(rdev, sclk); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
radeon_pm_debug_check_in_vbl(rdev, true); rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 2;
rdev->pm.current_sclk = sclk; /* high sh */
DRM_INFO("Setting: e: %d\n", sclk); rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1;
} rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1;
rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
/* set memory clock */ rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) { /* low mh */
radeon_pm_debug_check_in_vbl(rdev, false); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 3;
radeon_set_memory_clock(rdev, mclk); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 3;
radeon_pm_debug_check_in_vbl(rdev, true); rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.current_mclk = mclk; rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 2;
DRM_INFO("Setting: m: %d\n", mclk); /* high mh */
} rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 3;
radeon_pm_finish(rdev); rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
} }
}
rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
} else
DRM_INFO("GUI not idle!!!\n");
} }
void r600_pm_misc(struct radeon_device *rdev) void r600_pm_misc(struct radeon_device *rdev)
...@@ -2320,8 +2471,6 @@ int r600_init(struct radeon_device *rdev) ...@@ -2320,8 +2471,6 @@ int r600_init(struct radeon_device *rdev)
r = radeon_clocks_init(rdev); r = radeon_clocks_init(rdev);
if (r) if (r)
return r; return r;
/* Initialize power management */
radeon_pm_init(rdev);
/* Fence driver */ /* Fence driver */
r = radeon_fence_driver_init(rdev); r = radeon_fence_driver_init(rdev);
if (r) if (r)
...@@ -2386,7 +2535,6 @@ int r600_init(struct radeon_device *rdev) ...@@ -2386,7 +2535,6 @@ int r600_init(struct radeon_device *rdev)
void r600_fini(struct radeon_device *rdev) void r600_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r600_audio_fini(rdev); r600_audio_fini(rdev);
r600_blit_fini(rdev); r600_blit_fini(rdev);
r600_cp_fini(rdev); r600_cp_fini(rdev);
......
...@@ -89,7 +89,6 @@ extern int radeon_testing; ...@@ -89,7 +89,6 @@ extern int radeon_testing;
extern int radeon_connector_table; extern int radeon_connector_table;
extern int radeon_tv; extern int radeon_tv;
extern int radeon_new_pll; extern int radeon_new_pll;
extern int radeon_dynpm;
extern int radeon_audio; extern int radeon_audio;
extern int radeon_disp_priority; extern int radeon_disp_priority;
extern int radeon_hw_i2c; extern int radeon_hw_i2c;
...@@ -173,11 +172,10 @@ struct radeon_clock { ...@@ -173,11 +172,10 @@ struct radeon_clock {
int radeon_pm_init(struct radeon_device *rdev); int radeon_pm_init(struct radeon_device *rdev);
void radeon_pm_fini(struct radeon_device *rdev); void radeon_pm_fini(struct radeon_device *rdev);
void radeon_pm_compute_clocks(struct radeon_device *rdev); void radeon_pm_compute_clocks(struct radeon_device *rdev);
void radeon_pm_suspend(struct radeon_device *rdev);
void radeon_pm_resume(struct radeon_device *rdev);
void radeon_combios_get_power_modes(struct radeon_device *rdev); void radeon_combios_get_power_modes(struct radeon_device *rdev);
void radeon_atombios_get_power_modes(struct radeon_device *rdev); void radeon_atombios_get_power_modes(struct radeon_device *rdev);
bool radeon_pm_in_vbl(struct radeon_device *rdev);
bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
void radeon_sync_with_vblank(struct radeon_device *rdev);
/* /*
* Fences. * Fences.
...@@ -608,18 +606,24 @@ struct radeon_wb { ...@@ -608,18 +606,24 @@ struct radeon_wb {
* Equation between gpu/memory clock and available bandwidth is hw dependent * Equation between gpu/memory clock and available bandwidth is hw dependent
* (type of memory, bus size, efficiency, ...) * (type of memory, bus size, efficiency, ...)
*/ */
enum radeon_pm_state {
PM_STATE_DISABLED, enum radeon_pm_method {
PM_STATE_MINIMUM, PM_METHOD_PROFILE,
PM_STATE_PAUSED, PM_METHOD_DYNPM,
PM_STATE_ACTIVE };
enum radeon_dynpm_state {
DYNPM_STATE_DISABLED,
DYNPM_STATE_MINIMUM,
DYNPM_STATE_PAUSED,
DYNPM_STATE_ACTIVE
}; };
enum radeon_pm_action { enum radeon_dynpm_action {
PM_ACTION_NONE, DYNPM_ACTION_NONE,
PM_ACTION_MINIMUM, DYNPM_ACTION_MINIMUM,
PM_ACTION_DOWNCLOCK, DYNPM_ACTION_DOWNCLOCK,
PM_ACTION_UPCLOCK, DYNPM_ACTION_UPCLOCK,
PM_ACTION_DEFAULT DYNPM_ACTION_DEFAULT
}; };
enum radeon_voltage_type { enum radeon_voltage_type {
...@@ -637,11 +641,25 @@ enum radeon_pm_state_type { ...@@ -637,11 +641,25 @@ enum radeon_pm_state_type {
POWER_STATE_TYPE_PERFORMANCE, POWER_STATE_TYPE_PERFORMANCE,
}; };
enum radeon_pm_clock_mode_type { enum radeon_pm_profile_type {
POWER_MODE_TYPE_DEFAULT, PM_PROFILE_DEFAULT,
POWER_MODE_TYPE_LOW, PM_PROFILE_AUTO,
POWER_MODE_TYPE_MID, PM_PROFILE_LOW,
POWER_MODE_TYPE_HIGH, PM_PROFILE_HIGH,
};
#define PM_PROFILE_DEFAULT_IDX 0
#define PM_PROFILE_LOW_SH_IDX 1
#define PM_PROFILE_HIGH_SH_IDX 2
#define PM_PROFILE_LOW_MH_IDX 3
#define PM_PROFILE_HIGH_MH_IDX 4
#define PM_PROFILE_MAX 5
struct radeon_pm_profile {
int dpms_off_ps_idx;
int dpms_on_ps_idx;
int dpms_off_cm_idx;
int dpms_on_cm_idx;
}; };
struct radeon_voltage { struct radeon_voltage {
...@@ -696,12 +714,6 @@ struct radeon_power_state { ...@@ -696,12 +714,6 @@ struct radeon_power_state {
struct radeon_pm { struct radeon_pm {
struct mutex mutex; struct mutex mutex;
struct delayed_work idle_work;
enum radeon_pm_state state;
enum radeon_pm_action planned_action;
unsigned long action_timeout;
bool can_upclock;
bool can_downclock;
u32 active_crtcs; u32 active_crtcs;
int active_crtc_count; int active_crtc_count;
int req_vblank; int req_vblank;
...@@ -731,6 +743,19 @@ struct radeon_pm { ...@@ -731,6 +743,19 @@ struct radeon_pm {
u32 current_sclk; u32 current_sclk;
u32 current_mclk; u32 current_mclk;
struct radeon_i2c_chan *i2c_bus; struct radeon_i2c_chan *i2c_bus;
/* selected pm method */
enum radeon_pm_method pm_method;
/* dynpm power management */
struct delayed_work dynpm_idle_work;
enum radeon_dynpm_state dynpm_state;
enum radeon_dynpm_action dynpm_planned_action;
unsigned long dynpm_action_timeout;
bool dynpm_can_upclock;
bool dynpm_can_downclock;
/* profile-based power management */
enum radeon_pm_profile_type profile;
int profile_index;
struct radeon_pm_profile profiles[PM_PROFILE_MAX];
}; };
...@@ -819,11 +844,12 @@ struct radeon_asic { ...@@ -819,11 +844,12 @@ struct radeon_asic {
*/ */
void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo); void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
bool (*gui_idle)(struct radeon_device *rdev); bool (*gui_idle)(struct radeon_device *rdev);
void (*get_power_state)(struct radeon_device *rdev, enum radeon_pm_action action); /* power management */
void (*set_power_state)(struct radeon_device *rdev, bool static_switch);
void (*pm_misc)(struct radeon_device *rdev); void (*pm_misc)(struct radeon_device *rdev);
void (*pm_prepare)(struct radeon_device *rdev); void (*pm_prepare)(struct radeon_device *rdev);
void (*pm_finish)(struct radeon_device *rdev); void (*pm_finish)(struct radeon_device *rdev);
void (*pm_init_profile)(struct radeon_device *rdev);
void (*pm_get_dynpm_state)(struct radeon_device *rdev);
}; };
/* /*
...@@ -1041,6 +1067,7 @@ struct radeon_device { ...@@ -1041,6 +1067,7 @@ struct radeon_device {
uint8_t audio_category_code; uint8_t audio_category_code;
bool powered_down; bool powered_down;
struct notifier_block acpi_nb;
}; };
int radeon_device_init(struct radeon_device *rdev, int radeon_device_init(struct radeon_device *rdev,
...@@ -1232,11 +1259,11 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) ...@@ -1232,11 +1259,11 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
#define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd)) #define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd))
#define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
#define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev)) #define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev))
#define radeon_get_power_state(rdev, a) (rdev)->asic->get_power_state((rdev), (a))
#define radeon_set_power_state(rdev, s) (rdev)->asic->set_power_state((rdev), (s))
#define radeon_pm_misc(rdev) (rdev)->asic->pm_misc((rdev)) #define radeon_pm_misc(rdev) (rdev)->asic->pm_misc((rdev))
#define radeon_pm_prepare(rdev) (rdev)->asic->pm_prepare((rdev)) #define radeon_pm_prepare(rdev) (rdev)->asic->pm_prepare((rdev))
#define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev)) #define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev))
#define radeon_pm_init_profile(rdev) (rdev)->asic->pm_init_profile((rdev))
#define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm_get_dynpm_state((rdev))
/* Common functions */ /* Common functions */
/* AGP */ /* AGP */
......
...@@ -166,11 +166,11 @@ static struct radeon_asic r100_asic = { ...@@ -166,11 +166,11 @@ static struct radeon_asic r100_asic = {
.hpd_set_polarity = &r100_hpd_set_polarity, .hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &r100_pm_misc, .pm_misc = &r100_pm_misc,
.pm_prepare = &r100_pm_prepare, .pm_prepare = &r100_pm_prepare,
.pm_finish = &r100_pm_finish, .pm_finish = &r100_pm_finish,
.pm_init_profile = &r100_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic r200_asic = { static struct radeon_asic r200_asic = {
...@@ -210,11 +210,11 @@ static struct radeon_asic r200_asic = { ...@@ -210,11 +210,11 @@ static struct radeon_asic r200_asic = {
.hpd_set_polarity = &r100_hpd_set_polarity, .hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &r100_pm_misc, .pm_misc = &r100_pm_misc,
.pm_prepare = &r100_pm_prepare, .pm_prepare = &r100_pm_prepare,
.pm_finish = &r100_pm_finish, .pm_finish = &r100_pm_finish,
.pm_init_profile = &r100_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic r300_asic = { static struct radeon_asic r300_asic = {
...@@ -255,11 +255,11 @@ static struct radeon_asic r300_asic = { ...@@ -255,11 +255,11 @@ static struct radeon_asic r300_asic = {
.hpd_set_polarity = &r100_hpd_set_polarity, .hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &r100_pm_misc, .pm_misc = &r100_pm_misc,
.pm_prepare = &r100_pm_prepare, .pm_prepare = &r100_pm_prepare,
.pm_finish = &r100_pm_finish, .pm_finish = &r100_pm_finish,
.pm_init_profile = &r100_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic r300_asic_pcie = { static struct radeon_asic r300_asic_pcie = {
...@@ -299,11 +299,11 @@ static struct radeon_asic r300_asic_pcie = { ...@@ -299,11 +299,11 @@ static struct radeon_asic r300_asic_pcie = {
.hpd_set_polarity = &r100_hpd_set_polarity, .hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &r100_pm_misc, .pm_misc = &r100_pm_misc,
.pm_prepare = &r100_pm_prepare, .pm_prepare = &r100_pm_prepare,
.pm_finish = &r100_pm_finish, .pm_finish = &r100_pm_finish,
.pm_init_profile = &r100_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic r420_asic = { static struct radeon_asic r420_asic = {
...@@ -344,11 +344,11 @@ static struct radeon_asic r420_asic = { ...@@ -344,11 +344,11 @@ static struct radeon_asic r420_asic = {
.hpd_set_polarity = &r100_hpd_set_polarity, .hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &r100_pm_misc, .pm_misc = &r100_pm_misc,
.pm_prepare = &r100_pm_prepare, .pm_prepare = &r100_pm_prepare,
.pm_finish = &r100_pm_finish, .pm_finish = &r100_pm_finish,
.pm_init_profile = &r420_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic rs400_asic = { static struct radeon_asic rs400_asic = {
...@@ -389,11 +389,11 @@ static struct radeon_asic rs400_asic = { ...@@ -389,11 +389,11 @@ static struct radeon_asic rs400_asic = {
.hpd_set_polarity = &r100_hpd_set_polarity, .hpd_set_polarity = &r100_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &r100_pm_misc, .pm_misc = &r100_pm_misc,
.pm_prepare = &r100_pm_prepare, .pm_prepare = &r100_pm_prepare,
.pm_finish = &r100_pm_finish, .pm_finish = &r100_pm_finish,
.pm_init_profile = &r100_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic rs600_asic = { static struct radeon_asic rs600_asic = {
...@@ -434,11 +434,11 @@ static struct radeon_asic rs600_asic = { ...@@ -434,11 +434,11 @@ static struct radeon_asic rs600_asic = {
.hpd_set_polarity = &rs600_hpd_set_polarity, .hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &rs600_pm_misc, .pm_misc = &rs600_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &r420_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic rs690_asic = { static struct radeon_asic rs690_asic = {
...@@ -479,11 +479,11 @@ static struct radeon_asic rs690_asic = { ...@@ -479,11 +479,11 @@ static struct radeon_asic rs690_asic = {
.hpd_set_polarity = &rs600_hpd_set_polarity, .hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &rs600_pm_misc, .pm_misc = &rs600_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &r420_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic rv515_asic = { static struct radeon_asic rv515_asic = {
...@@ -524,11 +524,11 @@ static struct radeon_asic rv515_asic = { ...@@ -524,11 +524,11 @@ static struct radeon_asic rv515_asic = {
.hpd_set_polarity = &rs600_hpd_set_polarity, .hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &rs600_pm_misc, .pm_misc = &rs600_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &r420_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic r520_asic = { static struct radeon_asic r520_asic = {
...@@ -569,11 +569,11 @@ static struct radeon_asic r520_asic = { ...@@ -569,11 +569,11 @@ static struct radeon_asic r520_asic = {
.hpd_set_polarity = &rs600_hpd_set_polarity, .hpd_set_polarity = &rs600_hpd_set_polarity,
.ioctl_wait_idle = NULL, .ioctl_wait_idle = NULL,
.gui_idle = &r100_gui_idle, .gui_idle = &r100_gui_idle,
.get_power_state = &r100_get_power_state,
.set_power_state = &r100_set_power_state,
.pm_misc = &rs600_pm_misc, .pm_misc = &rs600_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &r420_pm_init_profile,
.pm_get_dynpm_state = &r100_pm_get_dynpm_state,
}; };
static struct radeon_asic r600_asic = { static struct radeon_asic r600_asic = {
...@@ -613,11 +613,11 @@ static struct radeon_asic r600_asic = { ...@@ -613,11 +613,11 @@ static struct radeon_asic r600_asic = {
.hpd_set_polarity = &r600_hpd_set_polarity, .hpd_set_polarity = &r600_hpd_set_polarity,
.ioctl_wait_idle = r600_ioctl_wait_idle, .ioctl_wait_idle = r600_ioctl_wait_idle,
.gui_idle = &r600_gui_idle, .gui_idle = &r600_gui_idle,
.get_power_state = &r600_get_power_state,
.set_power_state = &r600_set_power_state,
.pm_misc = &r600_pm_misc, .pm_misc = &r600_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &r600_pm_init_profile,
.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
}; };
static struct radeon_asic rs780_asic = { static struct radeon_asic rs780_asic = {
...@@ -657,11 +657,11 @@ static struct radeon_asic rs780_asic = { ...@@ -657,11 +657,11 @@ static struct radeon_asic rs780_asic = {
.hpd_set_polarity = &r600_hpd_set_polarity, .hpd_set_polarity = &r600_hpd_set_polarity,
.ioctl_wait_idle = r600_ioctl_wait_idle, .ioctl_wait_idle = r600_ioctl_wait_idle,
.gui_idle = &r600_gui_idle, .gui_idle = &r600_gui_idle,
.get_power_state = &r600_get_power_state,
.set_power_state = &r600_set_power_state,
.pm_misc = &r600_pm_misc, .pm_misc = &r600_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &rs780_pm_init_profile,
.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
}; };
static struct radeon_asic rv770_asic = { static struct radeon_asic rv770_asic = {
...@@ -701,11 +701,11 @@ static struct radeon_asic rv770_asic = { ...@@ -701,11 +701,11 @@ static struct radeon_asic rv770_asic = {
.hpd_set_polarity = &r600_hpd_set_polarity, .hpd_set_polarity = &r600_hpd_set_polarity,
.ioctl_wait_idle = r600_ioctl_wait_idle, .ioctl_wait_idle = r600_ioctl_wait_idle,
.gui_idle = &r600_gui_idle, .gui_idle = &r600_gui_idle,
.get_power_state = &r600_get_power_state,
.set_power_state = &r600_set_power_state,
.pm_misc = &rv770_pm_misc, .pm_misc = &rv770_pm_misc,
.pm_prepare = &rs600_pm_prepare, .pm_prepare = &rs600_pm_prepare,
.pm_finish = &rs600_pm_finish, .pm_finish = &rs600_pm_finish,
.pm_init_profile = &r600_pm_init_profile,
.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
}; };
static struct radeon_asic evergreen_asic = { static struct radeon_asic evergreen_asic = {
...@@ -743,11 +743,11 @@ static struct radeon_asic evergreen_asic = { ...@@ -743,11 +743,11 @@ static struct radeon_asic evergreen_asic = {
.hpd_sense = &evergreen_hpd_sense, .hpd_sense = &evergreen_hpd_sense,
.hpd_set_polarity = &evergreen_hpd_set_polarity, .hpd_set_polarity = &evergreen_hpd_set_polarity,
.gui_idle = &r600_gui_idle, .gui_idle = &r600_gui_idle,
.get_power_state = &r600_get_power_state,
.set_power_state = &r600_set_power_state,
.pm_misc = &evergreen_pm_misc, .pm_misc = &evergreen_pm_misc,
.pm_prepare = &evergreen_pm_prepare, .pm_prepare = &evergreen_pm_prepare,
.pm_finish = &evergreen_pm_finish, .pm_finish = &evergreen_pm_finish,
.pm_init_profile = &r600_pm_init_profile,
.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
}; };
int radeon_asic_init(struct radeon_device *rdev) int radeon_asic_init(struct radeon_device *rdev)
......
...@@ -127,12 +127,11 @@ void r100_enable_bm(struct radeon_device *rdev); ...@@ -127,12 +127,11 @@ void r100_enable_bm(struct radeon_device *rdev);
void r100_set_common_regs(struct radeon_device *rdev); void r100_set_common_regs(struct radeon_device *rdev);
void r100_bm_disable(struct radeon_device *rdev); void r100_bm_disable(struct radeon_device *rdev);
extern bool r100_gui_idle(struct radeon_device *rdev); extern bool r100_gui_idle(struct radeon_device *rdev);
extern void r100_set_power_state(struct radeon_device *rdev, bool static_switch);
extern void r100_get_power_state(struct radeon_device *rdev,
enum radeon_pm_action action);
extern void r100_pm_misc(struct radeon_device *rdev); extern void r100_pm_misc(struct radeon_device *rdev);
extern void r100_pm_prepare(struct radeon_device *rdev); extern void r100_pm_prepare(struct radeon_device *rdev);
extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_finish(struct radeon_device *rdev);
extern void r100_pm_init_profile(struct radeon_device *rdev);
extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
/* /*
* r200,rv250,rs300,rv280 * r200,rv250,rs300,rv280
...@@ -170,6 +169,7 @@ extern int r420_init(struct radeon_device *rdev); ...@@ -170,6 +169,7 @@ extern int r420_init(struct radeon_device *rdev);
extern void r420_fini(struct radeon_device *rdev); extern void r420_fini(struct radeon_device *rdev);
extern int r420_suspend(struct radeon_device *rdev); extern int r420_suspend(struct radeon_device *rdev);
extern int r420_resume(struct radeon_device *rdev); extern int r420_resume(struct radeon_device *rdev);
extern void r420_pm_init_profile(struct radeon_device *rdev);
/* /*
* rs400,rs480 * rs400,rs480
...@@ -281,10 +281,10 @@ void r600_hpd_set_polarity(struct radeon_device *rdev, ...@@ -281,10 +281,10 @@ void r600_hpd_set_polarity(struct radeon_device *rdev,
enum radeon_hpd_id hpd); enum radeon_hpd_id hpd);
extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo); extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
extern bool r600_gui_idle(struct radeon_device *rdev); extern bool r600_gui_idle(struct radeon_device *rdev);
extern void r600_set_power_state(struct radeon_device *rdev, bool static_switch);
extern void r600_get_power_state(struct radeon_device *rdev,
enum radeon_pm_action action);
extern void r600_pm_misc(struct radeon_device *rdev); extern void r600_pm_misc(struct radeon_device *rdev);
extern void r600_pm_init_profile(struct radeon_device *rdev);
extern void rs780_pm_init_profile(struct radeon_device *rdev);
extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
/* /*
* rv770,rv730,rv710,rv740 * rv770,rv730,rv710,rv740
......
...@@ -748,6 +748,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) ...@@ -748,6 +748,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
radeon_save_bios_scratch_regs(rdev); radeon_save_bios_scratch_regs(rdev);
radeon_pm_suspend(rdev);
radeon_suspend(rdev); radeon_suspend(rdev);
radeon_hpd_fini(rdev); radeon_hpd_fini(rdev);
/* evict remaining vram memory */ /* evict remaining vram memory */
...@@ -783,6 +784,7 @@ int radeon_resume_kms(struct drm_device *dev) ...@@ -783,6 +784,7 @@ int radeon_resume_kms(struct drm_device *dev)
/* resume AGP if in use */ /* resume AGP if in use */
radeon_agp_resume(rdev); radeon_agp_resume(rdev);
radeon_resume(rdev); radeon_resume(rdev);
radeon_pm_resume(rdev);
radeon_restore_bios_scratch_regs(rdev); radeon_restore_bios_scratch_regs(rdev);
radeon_fbdev_set_suspend(rdev, 0); radeon_fbdev_set_suspend(rdev, 0);
release_console_sem(); release_console_sem();
......
...@@ -1037,6 +1037,9 @@ int radeon_modeset_init(struct radeon_device *rdev) ...@@ -1037,6 +1037,9 @@ int radeon_modeset_init(struct radeon_device *rdev)
/* initialize hpd */ /* initialize hpd */
radeon_hpd_init(rdev); radeon_hpd_init(rdev);
/* Initialize power management */
radeon_pm_init(rdev);
radeon_fbdev_init(rdev); radeon_fbdev_init(rdev);
drm_kms_helper_poll_init(rdev->ddev); drm_kms_helper_poll_init(rdev->ddev);
...@@ -1047,6 +1050,7 @@ void radeon_modeset_fini(struct radeon_device *rdev) ...@@ -1047,6 +1050,7 @@ void radeon_modeset_fini(struct radeon_device *rdev)
{ {
radeon_fbdev_fini(rdev); radeon_fbdev_fini(rdev);
kfree(rdev->mode_info.bios_hardcoded_edid); kfree(rdev->mode_info.bios_hardcoded_edid);
radeon_pm_fini(rdev);
if (rdev->mode_info.mode_config_initialized) { if (rdev->mode_info.mode_config_initialized) {
drm_kms_helper_poll_fini(rdev->ddev); drm_kms_helper_poll_fini(rdev->ddev);
......
...@@ -92,7 +92,6 @@ int radeon_testing = 0; ...@@ -92,7 +92,6 @@ int radeon_testing = 0;
int radeon_connector_table = 0; int radeon_connector_table = 0;
int radeon_tv = 1; int radeon_tv = 1;
int radeon_new_pll = -1; int radeon_new_pll = -1;
int radeon_dynpm = -1;
int radeon_audio = 1; int radeon_audio = 1;
int radeon_disp_priority = 0; int radeon_disp_priority = 0;
int radeon_hw_i2c = 0; int radeon_hw_i2c = 0;
...@@ -133,9 +132,6 @@ module_param_named(tv, radeon_tv, int, 0444); ...@@ -133,9 +132,6 @@ module_param_named(tv, radeon_tv, int, 0444);
MODULE_PARM_DESC(new_pll, "Select new PLL code"); MODULE_PARM_DESC(new_pll, "Select new PLL code");
module_param_named(new_pll, radeon_new_pll, int, 0444); module_param_named(new_pll, radeon_new_pll, int, 0444);
MODULE_PARM_DESC(dynpm, "Disable/Enable dynamic power management (1 = enable)");
module_param_named(dynpm, radeon_dynpm, int, 0444);
MODULE_PARM_DESC(audio, "Audio enable (0 = disable)"); MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
module_param_named(audio, radeon_audio, int, 0444); module_param_named(audio, radeon_audio, int, 0444);
......
...@@ -23,14 +23,98 @@ ...@@ -23,14 +23,98 @@
#include "drmP.h" #include "drmP.h"
#include "radeon.h" #include "radeon.h"
#include "avivod.h" #include "avivod.h"
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#endif
#include <linux/power_supply.h>
#define RADEON_IDLE_LOOP_MS 100 #define RADEON_IDLE_LOOP_MS 100
#define RADEON_RECLOCK_DELAY_MS 200 #define RADEON_RECLOCK_DELAY_MS 200
#define RADEON_WAIT_VBLANK_TIMEOUT 200 #define RADEON_WAIT_VBLANK_TIMEOUT 200
#define RADEON_WAIT_IDLE_TIMEOUT 200 #define RADEON_WAIT_IDLE_TIMEOUT 200
static void radeon_pm_idle_work_handler(struct work_struct *work); static void radeon_dynpm_idle_work_handler(struct work_struct *work);
static int radeon_debugfs_pm_init(struct radeon_device *rdev); static int radeon_debugfs_pm_init(struct radeon_device *rdev);
static bool radeon_pm_in_vbl(struct radeon_device *rdev);
static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
static void radeon_pm_update_profile(struct radeon_device *rdev);
static void radeon_pm_set_clocks(struct radeon_device *rdev);
#define ACPI_AC_CLASS "ac_adapter"
#ifdef CONFIG_ACPI
static int radeon_acpi_event(struct notifier_block *nb,
unsigned long val,
void *data)
{
struct radeon_device *rdev = container_of(nb, struct radeon_device, acpi_nb);
struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
if (power_supply_is_system_supplied() > 0)
DRM_INFO("pm: AC\n");
else
DRM_INFO("pm: DC\n");
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
if (rdev->pm.profile == PM_PROFILE_AUTO) {
mutex_lock(&rdev->pm.mutex);
radeon_pm_update_profile(rdev);
radeon_pm_set_clocks(rdev);
mutex_unlock(&rdev->pm.mutex);
}
}
}
return NOTIFY_OK;
}
#endif
static void radeon_pm_update_profile(struct radeon_device *rdev)
{
switch (rdev->pm.profile) {
case PM_PROFILE_DEFAULT:
rdev->pm.profile_index = PM_PROFILE_DEFAULT_IDX;
break;
case PM_PROFILE_AUTO:
if (power_supply_is_system_supplied() > 0) {
if (rdev->pm.active_crtc_count > 1)
rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX;
else
rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX;
} else {
if (rdev->pm.active_crtc_count > 1)
rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX;
else
rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
}
break;
case PM_PROFILE_LOW:
if (rdev->pm.active_crtc_count > 1)
rdev->pm.profile_index = PM_PROFILE_LOW_MH_IDX;
else
rdev->pm.profile_index = PM_PROFILE_LOW_SH_IDX;
break;
case PM_PROFILE_HIGH:
if (rdev->pm.active_crtc_count > 1)
rdev->pm.profile_index = PM_PROFILE_HIGH_MH_IDX;
else
rdev->pm.profile_index = PM_PROFILE_HIGH_SH_IDX;
break;
}
if (rdev->pm.active_crtc_count == 0) {
rdev->pm.requested_power_state_index =
rdev->pm.profiles[rdev->pm.profile_index].dpms_off_ps_idx;
rdev->pm.requested_clock_mode_index =
rdev->pm.profiles[rdev->pm.profile_index].dpms_off_cm_idx;
} else {
rdev->pm.requested_power_state_index =
rdev->pm.profiles[rdev->pm.profile_index].dpms_on_ps_idx;
rdev->pm.requested_clock_mode_index =
rdev->pm.profiles[rdev->pm.profile_index].dpms_on_cm_idx;
}
}
static void radeon_unmap_vram_bos(struct radeon_device *rdev) static void radeon_unmap_vram_bos(struct radeon_device *rdev)
{ {
...@@ -54,12 +138,93 @@ static void radeon_unmap_vram_bos(struct radeon_device *rdev) ...@@ -54,12 +138,93 @@ static void radeon_unmap_vram_bos(struct radeon_device *rdev)
ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo); ttm_bo_unmap_virtual(&rdev->r600_blit.shader_obj->tbo);
} }
static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) static void radeon_sync_with_vblank(struct radeon_device *rdev)
{ {
int i; if (rdev->pm.active_crtcs) {
rdev->pm.vblank_sync = false;
wait_event_timeout(
rdev->irq.vblank_queue, rdev->pm.vblank_sync,
msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
}
}
static void radeon_set_power_state(struct radeon_device *rdev)
{
u32 sclk, mclk;
if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
return;
if (radeon_gui_idle(rdev)) {
sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
clock_info[rdev->pm.requested_clock_mode_index].sclk;
if (sclk > rdev->clock.default_sclk)
sclk = rdev->clock.default_sclk;
mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
clock_info[rdev->pm.requested_clock_mode_index].mclk;
if (mclk > rdev->clock.default_mclk)
mclk = rdev->clock.default_mclk;
/* voltage, pcie lanes, etc.*/
radeon_pm_misc(rdev);
if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
radeon_sync_with_vblank(rdev);
if (!radeon_pm_in_vbl(rdev))
return;
radeon_pm_prepare(rdev);
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
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);
}
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
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);
}
radeon_pm_finish(rdev);
} else {
/* set engine clock */
if (sclk != rdev->pm.current_sclk) {
radeon_sync_with_vblank(rdev);
radeon_pm_prepare(rdev);
radeon_set_engine_clock(rdev, sclk);
radeon_pm_finish(rdev);
rdev->pm.current_sclk = sclk;
DRM_INFO("Setting: e: %d\n", sclk);
}
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
radeon_sync_with_vblank(rdev);
radeon_pm_prepare(rdev);
radeon_set_memory_clock(rdev, mclk);
radeon_pm_finish(rdev);
rdev->pm.current_mclk = mclk;
DRM_INFO("Setting: m: %d\n", mclk);
}
}
if (rdev->pm.state != PM_STATE_DISABLED) rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
radeon_get_power_state(rdev, rdev->pm.planned_action); rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
} else
DRM_INFO("pm: GUI not idle!!!\n");
}
static void radeon_pm_set_clocks(struct radeon_device *rdev)
{
int i;
mutex_lock(&rdev->ddev->struct_mutex); mutex_lock(&rdev->ddev->struct_mutex);
mutex_lock(&rdev->vram_mutex); mutex_lock(&rdev->vram_mutex);
...@@ -67,27 +232,31 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) ...@@ -67,27 +232,31 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch)
/* gui idle int has issues on older chips it seems */ /* gui idle int has issues on older chips it seems */
if (rdev->family >= CHIP_R600) { if (rdev->family >= CHIP_R600) {
/* wait for GPU idle */ if (rdev->irq.installed) {
rdev->pm.gui_idle = false; /* wait for GPU idle */
rdev->irq.gui_idle = true; rdev->pm.gui_idle = false;
radeon_irq_set(rdev); rdev->irq.gui_idle = true;
wait_event_interruptible_timeout( radeon_irq_set(rdev);
rdev->irq.idle_queue, rdev->pm.gui_idle, wait_event_interruptible_timeout(
msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT)); rdev->irq.idle_queue, rdev->pm.gui_idle,
rdev->irq.gui_idle = false; msecs_to_jiffies(RADEON_WAIT_IDLE_TIMEOUT));
radeon_irq_set(rdev); rdev->irq.gui_idle = false;
radeon_irq_set(rdev);
}
} else { } else {
struct radeon_fence *fence; if (rdev->cp.ready) {
radeon_ring_alloc(rdev, 64); struct radeon_fence *fence;
radeon_fence_create(rdev, &fence); radeon_ring_alloc(rdev, 64);
radeon_fence_emit(rdev, fence); radeon_fence_create(rdev, &fence);
radeon_ring_commit(rdev); radeon_fence_emit(rdev, fence);
radeon_fence_wait(fence, false); radeon_ring_commit(rdev);
radeon_fence_unref(&fence); radeon_fence_wait(fence, false);
radeon_fence_unref(&fence);
}
} }
radeon_unmap_vram_bos(rdev); radeon_unmap_vram_bos(rdev);
if (!static_switch) { if (rdev->irq.installed) {
for (i = 0; i < rdev->num_crtc; i++) { for (i = 0; i < rdev->num_crtc; i++) {
if (rdev->pm.active_crtcs & (1 << i)) { if (rdev->pm.active_crtcs & (1 << i)) {
rdev->pm.req_vblank |= (1 << i); rdev->pm.req_vblank |= (1 << i);
...@@ -96,9 +265,9 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) ...@@ -96,9 +265,9 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch)
} }
} }
radeon_set_power_state(rdev, static_switch); radeon_set_power_state(rdev);
if (!static_switch) { if (rdev->irq.installed) {
for (i = 0; i < rdev->num_crtc; i++) { for (i = 0; i < rdev->num_crtc; i++) {
if (rdev->pm.req_vblank & (1 << i)) { if (rdev->pm.req_vblank & (1 << i)) {
rdev->pm.req_vblank &= ~(1 << i); rdev->pm.req_vblank &= ~(1 << i);
...@@ -112,230 +281,195 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch) ...@@ -112,230 +281,195 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, int static_switch)
if (rdev->pm.active_crtc_count) if (rdev->pm.active_crtc_count)
radeon_bandwidth_update(rdev); radeon_bandwidth_update(rdev);
rdev->pm.planned_action = PM_ACTION_NONE; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
mutex_unlock(&rdev->cp.mutex); mutex_unlock(&rdev->cp.mutex);
mutex_unlock(&rdev->vram_mutex); mutex_unlock(&rdev->vram_mutex);
mutex_unlock(&rdev->ddev->struct_mutex); mutex_unlock(&rdev->ddev->struct_mutex);
} }
static ssize_t radeon_get_power_state_static(struct device *dev, static ssize_t radeon_get_pm_profile(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private; struct radeon_device *rdev = ddev->dev_private;
int cp = rdev->pm.profile;
return snprintf(buf, PAGE_SIZE, "%d.%d\n", rdev->pm.current_power_state_index, return snprintf(buf, PAGE_SIZE, "%s\n",
rdev->pm.current_clock_mode_index); (cp == PM_PROFILE_AUTO) ? "auto" :
(cp == PM_PROFILE_LOW) ? "low" :
(cp == PM_PROFILE_HIGH) ? "high" : "default");
} }
static ssize_t radeon_set_power_state_static(struct device *dev, static ssize_t radeon_set_pm_profile(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private; struct radeon_device *rdev = ddev->dev_private;
int ps, cm;
if (sscanf(buf, "%u.%u", &ps, &cm) != 2) {
DRM_ERROR("Invalid power state!\n");
return count;
}
mutex_lock(&rdev->pm.mutex); mutex_lock(&rdev->pm.mutex);
if ((ps >= 0) && (ps < rdev->pm.num_power_states) && if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
(cm >= 0) && (cm < rdev->pm.power_state[ps].num_clock_modes)) { if (strncmp("default", buf, strlen("default")) == 0)
if ((rdev->pm.active_crtc_count > 0) && rdev->pm.profile = PM_PROFILE_DEFAULT;
(rdev->pm.power_state[ps].clock_info[cm].flags & RADEON_PM_MODE_NO_DISPLAY)) { else if (strncmp("auto", buf, strlen("auto")) == 0)
DRM_ERROR("Invalid power state for display: %d.%d\n", ps, cm); rdev->pm.profile = PM_PROFILE_AUTO;
} else if ((rdev->pm.active_crtc_count > 1) && else if (strncmp("low", buf, strlen("low")) == 0)
(rdev->pm.power_state[ps].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)) { rdev->pm.profile = PM_PROFILE_LOW;
DRM_ERROR("Invalid power state for multi-head: %d.%d\n", ps, cm); else if (strncmp("high", buf, strlen("high")) == 0)
} else { rdev->pm.profile = PM_PROFILE_HIGH;
/* disable dynpm */ else {
rdev->pm.state = PM_STATE_DISABLED; DRM_ERROR("invalid power profile!\n");
rdev->pm.planned_action = PM_ACTION_NONE; goto fail;
rdev->pm.requested_power_state_index = ps;
rdev->pm.requested_clock_mode_index = cm;
radeon_pm_set_clocks(rdev, true);
} }
} else radeon_pm_update_profile(rdev);
DRM_ERROR("Invalid power state: %d.%d\n\n", ps, cm); radeon_pm_set_clocks(rdev);
}
fail:
mutex_unlock(&rdev->pm.mutex); mutex_unlock(&rdev->pm.mutex);
return count; return count;
} }
static ssize_t radeon_get_dynpm(struct device *dev, static ssize_t radeon_get_pm_method(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private; struct radeon_device *rdev = ddev->dev_private;
int pm = rdev->pm.pm_method;
return snprintf(buf, PAGE_SIZE, "%s\n", return snprintf(buf, PAGE_SIZE, "%s\n",
(rdev->pm.state == PM_STATE_DISABLED) ? "disabled" : "enabled"); (pm == PM_METHOD_DYNPM) ? "dynpm" : "profile");
} }
static ssize_t radeon_set_dynpm(struct device *dev, static ssize_t radeon_set_pm_method(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
struct radeon_device *rdev = ddev->dev_private; struct radeon_device *rdev = ddev->dev_private;
int tmp = simple_strtoul(buf, NULL, 10);
if (tmp == 0) {
/* update power mode info */ if (strncmp("dynpm", buf, strlen("dynpm")) == 0) {
radeon_pm_compute_clocks(rdev);
/* disable dynpm */
mutex_lock(&rdev->pm.mutex); mutex_lock(&rdev->pm.mutex);
rdev->pm.state = PM_STATE_DISABLED; rdev->pm.pm_method = PM_METHOD_DYNPM;
rdev->pm.planned_action = PM_ACTION_NONE; rdev->pm.dynpm_state = DYNPM_STATE_PAUSED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
mutex_unlock(&rdev->pm.mutex); mutex_unlock(&rdev->pm.mutex);
DRM_INFO("radeon: dynamic power management disabled\n"); } else if (strncmp("profile", buf, strlen("profile")) == 0) {
} else if (tmp == 1) { mutex_lock(&rdev->pm.mutex);
if (rdev->pm.num_power_states > 1) { rdev->pm.pm_method = PM_METHOD_PROFILE;
/* enable dynpm */ /* disable dynpm */
mutex_lock(&rdev->pm.mutex); rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.state = PM_STATE_PAUSED; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
rdev->pm.planned_action = PM_ACTION_DEFAULT; cancel_delayed_work(&rdev->pm.dynpm_idle_work);
radeon_get_power_state(rdev, rdev->pm.planned_action); mutex_unlock(&rdev->pm.mutex);
mutex_unlock(&rdev->pm.mutex); } else {
/* update power mode info */ DRM_ERROR("invalid power method!\n");
radeon_pm_compute_clocks(rdev); goto fail;
DRM_INFO("radeon: dynamic power management enabled\n"); }
} else radeon_pm_compute_clocks(rdev);
DRM_ERROR("dynpm not valid on this system\n"); fail:
} else
DRM_ERROR("Invalid setting: %d\n", tmp);
return count; return count;
} }
static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, radeon_get_power_state_static, radeon_set_power_state_static); static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile);
static DEVICE_ATTR(dynpm, S_IRUGO | S_IWUSR, radeon_get_dynpm, radeon_set_dynpm); static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method);
static const char *pm_state_names[4] = { void radeon_pm_suspend(struct radeon_device *rdev)
"PM_STATE_DISABLED",
"PM_STATE_MINIMUM",
"PM_STATE_PAUSED",
"PM_STATE_ACTIVE"
};
static const char *pm_state_types[5] = {
"",
"Powersave",
"Battery",
"Balanced",
"Performance",
};
static void radeon_print_power_mode_info(struct radeon_device *rdev)
{ {
int i, j; mutex_lock(&rdev->pm.mutex);
bool is_default; cancel_delayed_work(&rdev->pm.dynpm_idle_work);
rdev->pm.current_power_state_index = -1;
DRM_INFO("%d Power State(s)\n", rdev->pm.num_power_states); rdev->pm.current_clock_mode_index = -1;
for (i = 0; i < rdev->pm.num_power_states; i++) { rdev->pm.current_sclk = 0;
if (rdev->pm.default_power_state_index == i) rdev->pm.current_mclk = 0;
is_default = true; mutex_unlock(&rdev->pm.mutex);
else
is_default = false;
DRM_INFO("State %d %s %s\n", i,
pm_state_types[rdev->pm.power_state[i].type],
is_default ? "(default)" : "");
if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].pcie_lanes);
if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
DRM_INFO("\tSingle display only\n");
DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes);
for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) {
if (rdev->flags & RADEON_IS_IGP)
DRM_INFO("\t\t%d engine: %d\n",
j,
rdev->pm.power_state[i].clock_info[j].sclk * 10);
else
DRM_INFO("\t\t%d engine/memory: %d/%d\n",
j,
rdev->pm.power_state[i].clock_info[j].sclk * 10,
rdev->pm.power_state[i].clock_info[j].mclk * 10);
if (rdev->pm.power_state[i].clock_info[j].flags & RADEON_PM_MODE_NO_DISPLAY)
DRM_INFO("\t\tNo display only\n");
}
}
} }
void radeon_sync_with_vblank(struct radeon_device *rdev) void radeon_pm_resume(struct radeon_device *rdev)
{ {
if (rdev->pm.active_crtcs) { radeon_pm_compute_clocks(rdev);
rdev->pm.vblank_sync = false;
wait_event_timeout(
rdev->irq.vblank_queue, rdev->pm.vblank_sync,
msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
}
} }
int radeon_pm_init(struct radeon_device *rdev) int radeon_pm_init(struct radeon_device *rdev)
{ {
rdev->pm.state = PM_STATE_DISABLED; /* default to profile method */
rdev->pm.planned_action = PM_ACTION_NONE; rdev->pm.pm_method = PM_METHOD_PROFILE;
rdev->pm.can_upclock = true; rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.can_downclock = true; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
rdev->pm.dynpm_can_upclock = true;
rdev->pm.dynpm_can_downclock = true;
rdev->pm.current_sclk = 0;
rdev->pm.current_mclk = 0;
if (rdev->bios) { if (rdev->bios) {
if (rdev->is_atom_bios) if (rdev->is_atom_bios)
radeon_atombios_get_power_modes(rdev); radeon_atombios_get_power_modes(rdev);
else else
radeon_combios_get_power_modes(rdev); radeon_combios_get_power_modes(rdev);
radeon_print_power_mode_info(rdev); radeon_pm_init_profile(rdev);
rdev->pm.current_power_state_index = -1;
rdev->pm.current_clock_mode_index = -1;
} }
if (radeon_debugfs_pm_init(rdev)) { if (rdev->pm.num_power_states > 1) {
DRM_ERROR("Failed to register debugfs file for PM!\n"); if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
} mutex_lock(&rdev->pm.mutex);
rdev->pm.profile = PM_PROFILE_DEFAULT;
radeon_pm_update_profile(rdev);
radeon_pm_set_clocks(rdev);
mutex_unlock(&rdev->pm.mutex);
}
/* where's the best place to put this? */ /* where's the best place to put these? */
device_create_file(rdev->dev, &dev_attr_power_state); device_create_file(rdev->dev, &dev_attr_power_profile);
device_create_file(rdev->dev, &dev_attr_dynpm); device_create_file(rdev->dev, &dev_attr_power_method);
INIT_DELAYED_WORK(&rdev->pm.idle_work, radeon_pm_idle_work_handler); #ifdef CONFIG_ACPI
rdev->acpi_nb.notifier_call = radeon_acpi_event;
register_acpi_notifier(&rdev->acpi_nb);
#endif
INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
if ((radeon_dynpm != -1 && radeon_dynpm) && (rdev->pm.num_power_states > 1)) { if (radeon_debugfs_pm_init(rdev)) {
rdev->pm.state = PM_STATE_PAUSED; DRM_ERROR("Failed to register debugfs file for PM!\n");
DRM_INFO("radeon: dynamic power management enabled\n"); }
}
DRM_INFO("radeon: power management initialized\n"); DRM_INFO("radeon: power management initialized\n");
}
return 0; return 0;
} }
void radeon_pm_fini(struct radeon_device *rdev) void radeon_pm_fini(struct radeon_device *rdev)
{ {
if (rdev->pm.state != PM_STATE_DISABLED) { if (rdev->pm.num_power_states > 1) {
/* cancel work */
cancel_delayed_work_sync(&rdev->pm.idle_work);
/* reset default clocks */
rdev->pm.state = PM_STATE_DISABLED;
rdev->pm.planned_action = PM_ACTION_DEFAULT;
radeon_pm_set_clocks(rdev, true);
} else if ((rdev->pm.current_power_state_index !=
rdev->pm.default_power_state_index) ||
(rdev->pm.current_clock_mode_index != 0)) {
rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.requested_clock_mode_index = 0;
mutex_lock(&rdev->pm.mutex); mutex_lock(&rdev->pm.mutex);
radeon_pm_set_clocks(rdev, true); if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
rdev->pm.profile = PM_PROFILE_DEFAULT;
radeon_pm_update_profile(rdev);
radeon_pm_set_clocks(rdev);
} else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
/* cancel work */
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
/* reset default clocks */
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
radeon_pm_set_clocks(rdev);
}
mutex_unlock(&rdev->pm.mutex); mutex_unlock(&rdev->pm.mutex);
}
device_remove_file(rdev->dev, &dev_attr_power_state); device_remove_file(rdev->dev, &dev_attr_power_profile);
device_remove_file(rdev->dev, &dev_attr_dynpm); device_remove_file(rdev->dev, &dev_attr_power_method);
#ifdef CONFIG_ACPI
unregister_acpi_notifier(&rdev->acpi_nb);
#endif
}
if (rdev->pm.i2c_bus) if (rdev->pm.i2c_bus)
radeon_i2c_destroy(rdev->pm.i2c_bus); radeon_i2c_destroy(rdev->pm.i2c_bus);
...@@ -347,6 +481,9 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) ...@@ -347,6 +481,9 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc; struct radeon_crtc *radeon_crtc;
if (rdev->pm.num_power_states < 2)
return;
mutex_lock(&rdev->pm.mutex); mutex_lock(&rdev->pm.mutex);
rdev->pm.active_crtcs = 0; rdev->pm.active_crtcs = 0;
...@@ -360,55 +497,56 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) ...@@ -360,55 +497,56 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
} }
} }
if (rdev->pm.state == PM_STATE_DISABLED) { if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
mutex_unlock(&rdev->pm.mutex); radeon_pm_update_profile(rdev);
return; radeon_pm_set_clocks(rdev);
} } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) {
if (rdev->pm.dynpm_state != DYNPM_STATE_DISABLED) {
/* Note, radeon_pm_set_clocks is called with static_switch set if (rdev->pm.active_crtc_count > 1) {
* to true since we always want to statically set the clocks, if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) {
* not wait for vbl. cancel_delayed_work(&rdev->pm.dynpm_idle_work);
*/
if (rdev->pm.active_crtc_count > 1) { rdev->pm.dynpm_state = DYNPM_STATE_PAUSED;
if (rdev->pm.state == PM_STATE_ACTIVE) { rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT;
cancel_delayed_work(&rdev->pm.idle_work); radeon_pm_get_dynpm_state(rdev);
radeon_pm_set_clocks(rdev);
rdev->pm.state = PM_STATE_PAUSED;
rdev->pm.planned_action = PM_ACTION_DEFAULT; DRM_DEBUG("radeon: dynamic power management deactivated\n");
radeon_pm_set_clocks(rdev, true); }
} else if (rdev->pm.active_crtc_count == 1) {
DRM_DEBUG("radeon: dynamic power management deactivated\n"); /* TODO: Increase clocks if needed for current mode */
}
} else if (rdev->pm.active_crtc_count == 1) { if (rdev->pm.dynpm_state == DYNPM_STATE_MINIMUM) {
/* TODO: Increase clocks if needed for current mode */ rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_UPCLOCK;
if (rdev->pm.state == PM_STATE_MINIMUM) { radeon_pm_get_dynpm_state(rdev);
rdev->pm.state = PM_STATE_ACTIVE; radeon_pm_set_clocks(rdev);
rdev->pm.planned_action = PM_ACTION_UPCLOCK;
radeon_pm_set_clocks(rdev, true); queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
queue_delayed_work(rdev->wq, &rdev->pm.idle_work, } else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) {
msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
} else if (rdev->pm.state == PM_STATE_PAUSED) { queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
rdev->pm.state = PM_STATE_ACTIVE; msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
queue_delayed_work(rdev->wq, &rdev->pm.idle_work, DRM_DEBUG("radeon: dynamic power management activated\n");
msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); }
DRM_DEBUG("radeon: dynamic power management activated\n"); } else { /* count == 0 */
} if (rdev->pm.dynpm_state != DYNPM_STATE_MINIMUM) {
} else { /* count == 0 */ cancel_delayed_work(&rdev->pm.dynpm_idle_work);
if (rdev->pm.state != PM_STATE_MINIMUM) {
cancel_delayed_work(&rdev->pm.idle_work); rdev->pm.dynpm_state = DYNPM_STATE_MINIMUM;
rdev->pm.dynpm_planned_action = DYNPM_ACTION_MINIMUM;
rdev->pm.state = PM_STATE_MINIMUM; radeon_pm_get_dynpm_state(rdev);
rdev->pm.planned_action = PM_ACTION_MINIMUM; radeon_pm_set_clocks(rdev);
radeon_pm_set_clocks(rdev, true); }
}
} }
} }
mutex_unlock(&rdev->pm.mutex); mutex_unlock(&rdev->pm.mutex);
} }
bool radeon_pm_in_vbl(struct radeon_device *rdev) static bool radeon_pm_in_vbl(struct radeon_device *rdev)
{ {
u32 stat_crtc = 0, vbl = 0, position = 0; u32 stat_crtc = 0, vbl = 0, position = 0;
bool in_vbl = true; bool in_vbl = true;
...@@ -480,7 +618,7 @@ bool radeon_pm_in_vbl(struct radeon_device *rdev) ...@@ -480,7 +618,7 @@ bool radeon_pm_in_vbl(struct radeon_device *rdev)
return in_vbl; return in_vbl;
} }
bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
{ {
u32 stat_crtc = 0; u32 stat_crtc = 0;
bool in_vbl = radeon_pm_in_vbl(rdev); bool in_vbl = radeon_pm_in_vbl(rdev);
...@@ -491,16 +629,16 @@ bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) ...@@ -491,16 +629,16 @@ bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
return in_vbl; return in_vbl;
} }
static void radeon_pm_idle_work_handler(struct work_struct *work) static void radeon_dynpm_idle_work_handler(struct work_struct *work)
{ {
struct radeon_device *rdev; struct radeon_device *rdev;
int resched; int resched;
rdev = container_of(work, struct radeon_device, rdev = container_of(work, struct radeon_device,
pm.idle_work.work); pm.dynpm_idle_work.work);
resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
mutex_lock(&rdev->pm.mutex); mutex_lock(&rdev->pm.mutex);
if (rdev->pm.state == PM_STATE_ACTIVE) { if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) {
unsigned long irq_flags; unsigned long irq_flags;
int not_processed = 0; int not_processed = 0;
...@@ -516,23 +654,23 @@ static void radeon_pm_idle_work_handler(struct work_struct *work) ...@@ -516,23 +654,23 @@ static void radeon_pm_idle_work_handler(struct work_struct *work)
read_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); read_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
if (not_processed >= 3) { /* should upclock */ if (not_processed >= 3) { /* should upclock */
if (rdev->pm.planned_action == PM_ACTION_DOWNCLOCK) { if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_DOWNCLOCK) {
rdev->pm.planned_action = PM_ACTION_NONE; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
} else if (rdev->pm.planned_action == PM_ACTION_NONE && } else if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_NONE &&
rdev->pm.can_upclock) { rdev->pm.dynpm_can_upclock) {
rdev->pm.planned_action = rdev->pm.dynpm_planned_action =
PM_ACTION_UPCLOCK; DYNPM_ACTION_UPCLOCK;
rdev->pm.action_timeout = jiffies + rdev->pm.dynpm_action_timeout = jiffies +
msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS); msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS);
} }
} else if (not_processed == 0) { /* should downclock */ } else if (not_processed == 0) { /* should downclock */
if (rdev->pm.planned_action == PM_ACTION_UPCLOCK) { if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_UPCLOCK) {
rdev->pm.planned_action = PM_ACTION_NONE; rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE;
} else if (rdev->pm.planned_action == PM_ACTION_NONE && } else if (rdev->pm.dynpm_planned_action == DYNPM_ACTION_NONE &&
rdev->pm.can_downclock) { rdev->pm.dynpm_can_downclock) {
rdev->pm.planned_action = rdev->pm.dynpm_planned_action =
PM_ACTION_DOWNCLOCK; DYNPM_ACTION_DOWNCLOCK;
rdev->pm.action_timeout = jiffies + rdev->pm.dynpm_action_timeout = jiffies +
msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS); msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS);
} }
} }
...@@ -540,15 +678,16 @@ static void radeon_pm_idle_work_handler(struct work_struct *work) ...@@ -540,15 +678,16 @@ static void radeon_pm_idle_work_handler(struct work_struct *work)
/* Note, radeon_pm_set_clocks is called with static_switch set /* Note, radeon_pm_set_clocks is called with static_switch set
* to false since we want to wait for vbl to avoid flicker. * to false since we want to wait for vbl to avoid flicker.
*/ */
if (rdev->pm.planned_action != PM_ACTION_NONE && if (rdev->pm.dynpm_planned_action != DYNPM_ACTION_NONE &&
jiffies > rdev->pm.action_timeout) { jiffies > rdev->pm.dynpm_action_timeout) {
radeon_pm_set_clocks(rdev, false); radeon_pm_get_dynpm_state(rdev);
radeon_pm_set_clocks(rdev);
} }
} }
mutex_unlock(&rdev->pm.mutex); mutex_unlock(&rdev->pm.mutex);
ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
queue_delayed_work(rdev->wq, &rdev->pm.idle_work, queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work,
msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
} }
...@@ -563,7 +702,6 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) ...@@ -563,7 +702,6 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
seq_printf(m, "state: %s\n", pm_state_names[rdev->pm.state]);
seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk); seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk);
seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
......
...@@ -456,7 +456,6 @@ int rs400_suspend(struct radeon_device *rdev) ...@@ -456,7 +456,6 @@ int rs400_suspend(struct radeon_device *rdev)
void rs400_fini(struct radeon_device *rdev) void rs400_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -507,8 +506,6 @@ int rs400_init(struct radeon_device *rdev) ...@@ -507,8 +506,6 @@ int rs400_init(struct radeon_device *rdev)
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize memory controller */ /* initialize memory controller */
rs400_mc_init(rdev); rs400_mc_init(rdev);
/* Fence driver */ /* Fence driver */
......
...@@ -846,7 +846,6 @@ int rs600_suspend(struct radeon_device *rdev) ...@@ -846,7 +846,6 @@ int rs600_suspend(struct radeon_device *rdev)
void rs600_fini(struct radeon_device *rdev) void rs600_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -896,8 +895,6 @@ int rs600_init(struct radeon_device *rdev) ...@@ -896,8 +895,6 @@ int rs600_init(struct radeon_device *rdev)
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize memory controller */ /* initialize memory controller */
rs600_mc_init(rdev); rs600_mc_init(rdev);
rs600_debugfs(rdev); rs600_debugfs(rdev);
......
...@@ -676,7 +676,6 @@ int rs690_suspend(struct radeon_device *rdev) ...@@ -676,7 +676,6 @@ int rs690_suspend(struct radeon_device *rdev)
void rs690_fini(struct radeon_device *rdev) void rs690_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -727,8 +726,6 @@ int rs690_init(struct radeon_device *rdev) ...@@ -727,8 +726,6 @@ int rs690_init(struct radeon_device *rdev)
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize memory controller */ /* initialize memory controller */
rs690_mc_init(rdev); rs690_mc_init(rdev);
rv515_debugfs(rdev); rv515_debugfs(rdev);
......
...@@ -445,7 +445,6 @@ void rv515_set_safe_registers(struct radeon_device *rdev) ...@@ -445,7 +445,6 @@ void rv515_set_safe_registers(struct radeon_device *rdev)
void rv515_fini(struct radeon_device *rdev) void rv515_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r100_cp_fini(rdev); r100_cp_fini(rdev);
r100_wb_fini(rdev); r100_wb_fini(rdev);
r100_ib_fini(rdev); r100_ib_fini(rdev);
...@@ -494,8 +493,6 @@ int rv515_init(struct radeon_device *rdev) ...@@ -494,8 +493,6 @@ int rv515_init(struct radeon_device *rdev)
return -EINVAL; return -EINVAL;
/* Initialize clocks */ /* Initialize clocks */
radeon_get_clock_info(rdev->ddev); radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
radeon_pm_init(rdev);
/* initialize AGP */ /* initialize AGP */
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
......
...@@ -1091,8 +1091,6 @@ int rv770_init(struct radeon_device *rdev) ...@@ -1091,8 +1091,6 @@ int rv770_init(struct radeon_device *rdev)
r = radeon_clocks_init(rdev); r = radeon_clocks_init(rdev);
if (r) if (r)
return r; return r;
/* Initialize power management */
radeon_pm_init(rdev);
/* Fence driver */ /* Fence driver */
r = radeon_fence_driver_init(rdev); r = radeon_fence_driver_init(rdev);
if (r) if (r)
...@@ -1161,7 +1159,6 @@ int rv770_init(struct radeon_device *rdev) ...@@ -1161,7 +1159,6 @@ int rv770_init(struct radeon_device *rdev)
void rv770_fini(struct radeon_device *rdev) void rv770_fini(struct radeon_device *rdev)
{ {
radeon_pm_fini(rdev);
r600_blit_fini(rdev); r600_blit_fini(rdev);
r700_cp_fini(rdev); r700_cp_fini(rdev);
r600_wb_fini(rdev); r600_wb_fini(rdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment