summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-04-01 16:22:02 -0400
committerAlex Deucher <alexdeucher@gmail.com>2009-04-15 11:45:52 -0400
commit63cb57c5eb0d6bc083f54eb100cb972b0e7bca69 (patch)
treecccada8790b2cd91d4b2ab52c6450fad400d3a51
parenta34a8b37afbea6ed4bf8ca42364195e174250c48 (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.man4
-rw-r--r--src/radeon.h14
-rw-r--r--src/radeon_driver.c28
-rw-r--r--src/radeon_pm.c68
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");
}