diff options
-rw-r--r-- | src/radeon.h | 35 | ||||
-rw-r--r-- | src/radeon_atombios.c | 4 | ||||
-rw-r--r-- | src/radeon_atombios.h | 4 | ||||
-rw-r--r-- | src/radeon_driver.c | 41 | ||||
-rw-r--r-- | src/radeon_pm.c | 171 |
5 files changed, 146 insertions, 109 deletions
diff --git a/src/radeon.h b/src/radeon.h index c1ad2c3e..7e84aebc 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -414,11 +414,30 @@ typedef enum { } RADEONCardType; typedef enum { - POWER_MODE_NONE, - POWER_MODE_STATIC, - POWER_MODE_DYNAMIC + POWER_DEFAULT, + POWER_LOW, + POWER_HIGH +} RADEONPMType; + +typedef struct { + RADEONPMType type; + uint32_t sclk; + uint32_t mclk; + uint32_t pcie_lanes; + uint32_t flags; } RADEONPowerMode; +typedef struct { + /* power modes */ + int num_modes; + int current_mode; + RADEONPowerMode mode[3]; + + Bool clock_gating_enabled; + Bool dynamic_mode_enabled; + Bool force_low_power_enabled; +} RADEONPowerManagement; + typedef struct _atomBiosHandle *atomBiosHandlePtr; typedef struct { @@ -900,8 +919,7 @@ typedef struct { Bool r4xx_atom; /* pm */ - RADEONPowerMode power_mode; - Bool low_power_active; + RADEONPowerManagement pm; } RADEONInfoRec, *RADEONInfoPtr; @@ -1083,10 +1101,11 @@ extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore); /* radeon_pm.c */ -extern void RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable); -extern void RADEONStaticLowPowerMode(ScrnInfoPtr pScrn, Bool enable); +extern void RADEONPMInit(ScrnInfoPtr pScrn); extern void RADEONPMBlockHandler(ScrnInfoPtr pScrn); -extern void RADEONDynamicLowPowerMode(ScrnInfoPtr pScrn, Bool enable); +extern void RADEONPMEnterVT(ScrnInfoPtr pScrn); +extern void RADEONPMLeaveVT(ScrnInfoPtr pScrn); +extern void RADEONPMFini(ScrnInfoPtr pScrn); #ifdef USE_EXA /* radeon_exa.c */ diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index f6fe9615..e2348a43 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -572,7 +572,7 @@ atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, Bool enable) } int -atombios_set_engine_clock(ScrnInfoPtr pScrn, int engclock) +atombios_set_engine_clock(ScrnInfoPtr pScrn, uint32_t engclock) { RADEONInfoPtr info = RADEONPTR(pScrn); SET_ENGINE_CLOCK_PS_ALLOCATION eng_clock_ps; @@ -597,7 +597,7 @@ atombios_set_engine_clock(ScrnInfoPtr pScrn, int engclock) } int -atombios_set_memory_clock(ScrnInfoPtr pScrn, int memclock) +atombios_set_memory_clock(ScrnInfoPtr pScrn, uint32_t memclock) { RADEONInfoPtr info = RADEONPTR(pScrn); SET_MEMORY_CLOCK_PS_ALLOCATION mem_clock_ps; diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h index 69e27a34..b81cbbbd 100644 --- a/src/radeon_atombios.h +++ b/src/radeon_atombios.h @@ -123,10 +123,10 @@ extern int atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, Bool enable); extern int -atombios_set_engine_clock(ScrnInfoPtr pScrn, int engclock); +atombios_set_engine_clock(ScrnInfoPtr pScrn, uint32_t engclock); extern int -atombios_set_memory_clock(ScrnInfoPtr pScrn, int memclock); +atombios_set_memory_clock(ScrnInfoPtr pScrn, uint32_t memclock); extern Bool RADEONGetATOMTVInfo(xf86OutputPtr output); diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 8e70e654..105a9f39 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -3221,7 +3221,7 @@ static void RADEONBlockHandler(int i, pointer blockData, info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; #endif - if (info->power_mode == POWER_MODE_DYNAMIC) + if (info->pm.dynamic_mode_enabled) RADEONPMBlockHandler(pScrn); } @@ -3356,22 +3356,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* blank the outputs/crtcs */ RADEONBlank(pScrn); - if (xf86ReturnOptValBool(info->Options, OPTION_CLOCK_GATING, FALSE)) - RADEONSetClockGating(pScrn, TRUE); - else - RADEONSetClockGating(pScrn, FALSE); - - info->power_mode = POWER_MODE_NONE; - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_PM, FALSE)) { - info->power_mode = POWER_MODE_DYNAMIC; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Enabled\n"); - } else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Disabled\n"); - - if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_LOW_POWER, FALSE)) { - info->power_mode = POWER_MODE_STATIC; - RADEONStaticLowPowerMode(pScrn, TRUE); - } + RADEONPMInit(pScrn); if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -5628,13 +5613,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) /* Makes sure the engine is idle before doing anything */ RADEONWaitForIdleMMIO(pScrn); - if (xf86ReturnOptValBool(info->Options, OPTION_CLOCK_GATING, FALSE)) - RADEONSetClockGating(pScrn, TRUE); - else - RADEONSetClockGating(pScrn, FALSE); - - if (info->power_mode == POWER_MODE_STATIC) - RADEONStaticLowPowerMode(pScrn, TRUE); + RADEONPMEnterVT(pScrn); for (i = 0; i < config->num_crtc; i++) radeon_crtc_modeset_ioctl(config->crtc[i], TRUE); @@ -5773,6 +5752,8 @@ void RADEONLeaveVT(int scrnIndex, int flags) xf86_hide_cursors (pScrn); + RADEONPMLeaveVT(pScrn); + RADEONRestore(pScrn); for (i = 0; i < config->num_crtc; i++) @@ -5796,17 +5777,7 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONCloseScreen\n"); - switch (info->power_mode) { - case POWER_MODE_STATIC: - RADEONStaticLowPowerMode(pScrn, FALSE); - break; - case POWER_MODE_DYNAMIC: - RADEONDynamicLowPowerMode(pScrn, FALSE); - break; - case POWER_MODE_NONE: - default: - break; - } + RADEONPMFini(pScrn); /* Mark acceleration as stopped or we might try to access the engine at * wrong times, especially if we had DRI, after DRI has been stopped diff --git a/src/radeon_pm.c b/src/radeon_pm.c index 41b797a8..2fcf45a4 100644 --- a/src/radeon_pm.c +++ b/src/radeon_pm.c @@ -38,7 +38,7 @@ #include "radeon_macros.h" #include "radeon_atombios.h" -static int calc_div(int num, int den) +static int calc_div(uint32_t num, uint32_t den) { int div = (num + (den / 2)) / den; @@ -51,7 +51,7 @@ static int calc_div(int num, int den) /* 10 khz */ static void -RADEONSetEngineClock(ScrnInfoPtr pScrn, int eng_clock) +RADEONSetEngineClock(ScrnInfoPtr pScrn, uint32_t eng_clock) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPLLPtr pll = &info->pll; @@ -75,7 +75,7 @@ RADEONSetEngineClock(ScrnInfoPtr pScrn, int eng_clock) /* 10 khz */ static void -RADEONSetMemoryClock(ScrnInfoPtr pScrn, int mem_clock) +RADEONSetMemoryClock(ScrnInfoPtr pScrn, uint32_t mem_clock) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPLLPtr pll = &info->pll; @@ -551,7 +551,7 @@ RADEONSetPCIELanes(ScrnInfoPtr pScrn, int lanes) } -void +static void RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -575,48 +575,126 @@ RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable) enable ? "En" : "Dis"); } -void RADEONDynamicLowPowerMode(ScrnInfoPtr pScrn, Bool enable) +static void RADEONSetStaticPowerMode(ScrnInfoPtr pScrn, RADEONPMType type) { RADEONInfoPtr info = RADEONPTR(pScrn); - int sclk = (int)info->sclk * 100; /* 10 khz */ + int i; + + for (i = 0; i < info->pm.num_modes; i++) { + if (info->pm.mode[i].type == type) + break; + } - if (enable && info->low_power_active) + if (i == info->pm.num_modes) return; - if (!enable && !info->low_power_active) + if (i == info->pm.current_mode) return; RADEONWaitForIdleMMIO(pScrn); - if (enable) { - if (info->IsAtomBios) - atombios_set_engine_clock(pScrn, sclk/4); - else - RADEONSetEngineClock(pScrn, sclk/4); + if (info->IsAtomBios) + atombios_set_engine_clock(pScrn, info->pm.mode[i].sclk); + else + RADEONSetEngineClock(pScrn, info->pm.mode[i].sclk); - if (info->cardType == CARD_PCIE) - RADEONSetPCIELanes(pScrn, 1); + if (info->cardType == CARD_PCIE) + RADEONSetPCIELanes(pScrn, info->pm.mode[i].pcie_lanes); - info->low_power_active = TRUE; - } else { - if (info->IsAtomBios) - atombios_set_engine_clock(pScrn, sclk); - else - RADEONSetEngineClock(pScrn, sclk); + info->pm.current_mode = i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Power Mode Switch\n"); +} - if (info->cardType == CARD_PCIE) - RADEONSetPCIELanes(pScrn, 16); - info->low_power_active = FALSE; +void RADEONPMInit(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (xf86ReturnOptValBool(info->Options, OPTION_CLOCK_GATING, FALSE)) + info->pm.clock_gating_enabled = TRUE; + else + info->pm.clock_gating_enabled = FALSE; + + RADEONSetClockGating(pScrn, info->pm.clock_gating_enabled); + + info->pm.mode[0].type = POWER_DEFAULT; + info->pm.mode[0].sclk = (uint32_t)info->sclk * 100; /* 10 khz */ + info->pm.mode[0].mclk = (uint32_t)info->mclk * 100; /* 10 khz */ + info->pm.mode[0].pcie_lanes = 16; /* XXX: read back current lane config */ + info->pm.current_mode = 0; + info->pm.num_modes = 1; + + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_PM, FALSE)) { + info->pm.dynamic_mode_enabled = TRUE; + info->pm.mode[1].type = POWER_LOW; + info->pm.mode[1].sclk = info->pm.mode[0].sclk / 4; + info->pm.mode[1].mclk = info->pm.mode[0].mclk / 4; + info->pm.mode[1].pcie_lanes = 1; + + info->pm.mode[2].type = POWER_HIGH; + info->pm.mode[2].sclk = info->pm.mode[0].sclk; + info->pm.mode[2].mclk = info->pm.mode[0].mclk; + info->pm.mode[2].pcie_lanes = 16; + + info->pm.num_modes += 2; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Enabled\n"); + } else { + info->pm.dynamic_mode_enabled = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Disabled\n"); } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Low Power Mode %sabled\n", - enable ? "En" : "Dis"); + if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_LOW_POWER, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Force Low Power Mode Enabled\n"); + info->pm.force_low_power_enabled = TRUE; + if (info->pm.dynamic_mode_enabled) { + info->pm.mode[2].type = POWER_HIGH; + info->pm.mode[2].sclk = info->pm.mode[0].sclk / 2; + info->pm.mode[2].mclk = info->pm.mode[0].mclk / 2; + info->pm.mode[2].pcie_lanes = 2; + } else { + info->pm.mode[1].type = POWER_HIGH; + info->pm.mode[1].sclk = info->pm.mode[0].sclk / 2; + info->pm.mode[1].mclk = info->pm.mode[0].mclk / 2; + info->pm.mode[1].pcie_lanes = 2; + info->pm.num_modes += 1; + } + RADEONSetStaticPowerMode(pScrn, POWER_HIGH); + } else + info->pm.force_low_power_enabled = FALSE; + } -void RADEONPMBlockHandler(ScrnInfoPtr pScrn) +void RADEONPMEnterVT(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONSetClockGating(pScrn, info->pm.clock_gating_enabled); + if (info->pm.force_low_power_enabled || info->pm.dynamic_mode_enabled) + RADEONSetStaticPowerMode(pScrn, POWER_HIGH); +} + +void RADEONPMLeaveVT(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONSetClockGating(pScrn, FALSE); + if (info->pm.force_low_power_enabled || info->pm.dynamic_mode_enabled) + RADEONSetStaticPowerMode(pScrn, POWER_DEFAULT); +} + +void RADEONPMFini(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONSetClockGating(pScrn, FALSE); + if (info->pm.force_low_power_enabled || info->pm.dynamic_mode_enabled) + RADEONSetStaticPowerMode(pScrn, POWER_DEFAULT); +} + +void RADEONPMBlockHandler(ScrnInfoPtr pScrn) +{ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; @@ -628,40 +706,9 @@ void RADEONPMBlockHandler(ScrnInfoPtr pScrn) break; } - if (i == xf86_config->num_crtc) { - if (!info->low_power_active) - RADEONDynamicLowPowerMode(pScrn, TRUE); - } else { - if (info->low_power_active) - RADEONDynamicLowPowerMode(pScrn, FALSE); - } + if (i == xf86_config->num_crtc) + RADEONSetStaticPowerMode(pScrn, POWER_HIGH); + else + RADEONSetStaticPowerMode(pScrn, POWER_LOW); } -void RADEONStaticLowPowerMode(ScrnInfoPtr pScrn, Bool enable) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int sclk = (int)info->sclk * 100; /* 10 khz */ - - RADEONWaitForIdleMMIO(pScrn); - - if (enable) { - if (info->IsAtomBios) - atombios_set_engine_clock(pScrn, sclk/2); - else - RADEONSetEngineClock(pScrn, sclk/2); - - if (info->cardType == CARD_PCIE) - RADEONSetPCIELanes(pScrn, 2); - } else { - if (info->IsAtomBios) - atombios_set_engine_clock(pScrn, sclk); - else - RADEONSetEngineClock(pScrn, sclk); - - if (info->cardType == CARD_PCIE) - RADEONSetPCIELanes(pScrn, 16); - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Static Low Power Mode %sabled\n", - enable ? "En" : "Dis"); -} |