diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-04-01 16:22:02 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-04-15 11:45:52 -0400 |
commit | 63cb57c5eb0d6bc083f54eb100cb972b0e7bca69 (patch) | |
tree | cccada8790b2cd91d4b2ab52c6450fad400d3a51 | |
parent | a34a8b37afbea6ed4bf8ca42364195e174250c48 (diff) |
Add DynamicPM Option
Dyanmically switch between power states. Switch to a low
power state when the system is idle (DPMS off).
-rw-r--r-- | man/radeon.man | 4 | ||||
-rw-r--r-- | src/radeon.h | 14 | ||||
-rw-r--r-- | src/radeon_driver.c | 28 | ||||
-rw-r--r-- | src/radeon_pm.c | 68 |
4 files changed, 104 insertions, 10 deletions
diff --git a/man/radeon.man b/man/radeon.man index f6167038..eb133c33 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -423,6 +423,10 @@ with this enabled. The default is Enable a static low power mode. This can help reduce heat and increase battery life by reducing power usage at the expense of performance. The default is .B off. +.BI "Option \*qDynamicPM\*q \*q" boolean \*q +Enable dynamic power mode switching. This can help reduce heat and increase battery +life by reducing power usage when the system is idle (DPMS active). The default is +.B off. .TP .BI "Option \*qVGAAccess\*q \*q" boolean \*q Tell the driver if it can do legacy VGA IOs to the card. This is diff --git a/src/radeon.h b/src/radeon.h index 3a9130cb..c1ad2c3e 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -208,7 +208,8 @@ typedef enum { OPTION_EXA_VSYNC, OPTION_ATOM_TVOUT, OPTION_R4XX_ATOM, - OPTION_FORCE_LOW_POWER + OPTION_FORCE_LOW_POWER, + OPTION_DYNAMIC_PM } RADEONOpts; @@ -412,6 +413,12 @@ typedef enum { CARD_PCIE } RADEONCardType; +typedef enum { + POWER_MODE_NONE, + POWER_MODE_STATIC, + POWER_MODE_DYNAMIC +} RADEONPowerMode; + typedef struct _atomBiosHandle *atomBiosHandlePtr; typedef struct { @@ -893,7 +900,8 @@ typedef struct { Bool r4xx_atom; /* pm */ - Bool low_power_mode; + RADEONPowerMode power_mode; + Bool low_power_active; } RADEONInfoRec, *RADEONInfoPtr; @@ -1077,6 +1085,8 @@ extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, /* radeon_pm.c */ extern void RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable); extern void RADEONStaticLowPowerMode(ScrnInfoPtr pScrn, Bool enable); +extern void RADEONPMBlockHandler(ScrnInfoPtr pScrn); +extern void RADEONDynamicLowPowerMode(ScrnInfoPtr pScrn, Bool enable); #ifdef USE_EXA /* radeon_exa.c */ diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 7c758f86..8e70e654 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -196,6 +196,7 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_ATOM_TVOUT, "ATOMTVOut", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_R4XX_ATOM, "R4xxATOM", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_FORCE_LOW_POWER, "ForceLowPowerMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DYNAMIC_PM, "DynamicPM", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -3219,6 +3220,9 @@ static void RADEONBlockHandler(int i, pointer blockData, #ifdef USE_EXA info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; #endif + + if (info->power_mode == POWER_MODE_DYNAMIC) + RADEONPMBlockHandler(pScrn); } static void @@ -3357,8 +3361,17 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, else RADEONSetClockGating(pScrn, FALSE); - if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_LOW_POWER, 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); + } if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -5620,7 +5633,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) else RADEONSetClockGating(pScrn, FALSE); - if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_LOW_POWER, FALSE)) + if (info->power_mode == POWER_MODE_STATIC) RADEONStaticLowPowerMode(pScrn, TRUE); for (i = 0; i < config->num_crtc; i++) @@ -5783,8 +5796,17 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONCloseScreen\n"); - if (xf86ReturnOptValBool(info->Options, OPTION_FORCE_LOW_POWER, FALSE)) + 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; + } /* 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 ac6b972b..41b797a8 100644 --- a/src/radeon_pm.c +++ b/src/radeon_pm.c @@ -575,6 +575,68 @@ RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable) enable ? "En" : "Dis"); } +void RADEONDynamicLowPowerMode(ScrnInfoPtr pScrn, Bool enable) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int sclk = (int)info->sclk * 100; /* 10 khz */ + + if (enable && info->low_power_active) + return; + + if (!enable && !info->low_power_active) + return; + + RADEONWaitForIdleMMIO(pScrn); + + if (enable) { + if (info->IsAtomBios) + atombios_set_engine_clock(pScrn, sclk/4); + else + RADEONSetEngineClock(pScrn, sclk/4); + + if (info->cardType == CARD_PCIE) + RADEONSetPCIELanes(pScrn, 1); + + info->low_power_active = TRUE; + } else { + if (info->IsAtomBios) + atombios_set_engine_clock(pScrn, sclk); + else + RADEONSetEngineClock(pScrn, sclk); + + if (info->cardType == CARD_PCIE) + RADEONSetPCIELanes(pScrn, 16); + + info->low_power_active = FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Low Power Mode %sabled\n", + enable ? "En" : "Dis"); +} + +void RADEONPMBlockHandler(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if (radeon_crtc->enabled) + break; + } + + if (i == xf86_config->num_crtc) { + if (!info->low_power_active) + RADEONDynamicLowPowerMode(pScrn, TRUE); + } else { + if (info->low_power_active) + RADEONDynamicLowPowerMode(pScrn, FALSE); + } +} + void RADEONStaticLowPowerMode(ScrnInfoPtr pScrn, Bool enable) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -590,8 +652,6 @@ void RADEONStaticLowPowerMode(ScrnInfoPtr pScrn, Bool enable) if (info->cardType == CARD_PCIE) RADEONSetPCIELanes(pScrn, 2); - - info->low_power_mode = TRUE; } else { if (info->IsAtomBios) atombios_set_engine_clock(pScrn, sclk); @@ -600,10 +660,8 @@ void RADEONStaticLowPowerMode(ScrnInfoPtr pScrn, Bool enable) if (info->cardType == CARD_PCIE) RADEONSetPCIELanes(pScrn, 16); - - info->low_power_mode = FALSE; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Low Power Mode %sabled\n", + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Static Low Power Mode %sabled\n", enable ? "En" : "Dis"); } |