--- ../ati.orig/radeon_accel.c 2003-07-30 22:10:33.000000000 -0400 +++ radeon_accel.c 2003-08-08 17:49:57.000000000 -0400 @@ -177,6 +177,9 @@ /* Some ASICs have bugs with dynamic-on feature, which are * ASIC-version dependent, so we force all blocks on for now */ + +/* does anyone know which ASICS? This disables dynamicPM */ + if ((!info->PowerManAlways) || (!info->PowerManDPMS)) { if (info->HasCRTC2) { CARD32 tmp; @@ -200,6 +203,8 @@ RADEON_FORCEON_MC | RADEON_FORCEON_AIC)); + } /* dynamicPM */ + /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some * unexpected behaviour on some machines. Here we use * RADEON_HOST_PATH_CNTL to reset it. --- ../ati.orig/radeon_driver.c 2003-07-30 22:14:40.000000000 -0400 +++ radeon_driver.c 2003-08-08 17:54:14.000000000 -0400 @@ -103,6 +103,9 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); +/* power management functions */ +static void RADEONPMDisableDynamicMode(ScrnInfoPtr pScrn); +static void RADEONPMEnableDynamicMode(ScrnInfoPtr pScrn); typedef enum { OPTION_NOACCEL, @@ -131,7 +134,8 @@ OPTION_CLONE_HSYNC, OPTION_CLONE_VREFRESH, OPTION_FBDEV, - OPTION_VIDEO_KEY + OPTION_VIDEO_KEY, + OPTION_DYN_PM } RADEONOpts; const OptionInfoRec RADEONOptions[] = { @@ -162,6 +166,7 @@ { OPTION_CLONE_VREFRESH, "CloneVRefresh", OPTV_ANYSTR, {0}, FALSE }, { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_DYN_PM, "DynamicPM", OPTV_ANYSTR, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -4021,6 +4026,7 @@ RADEONInfoPtr info = RADEONPTR(pScrn); BoxRec MemBox; int y2; + char *strptr; RADEONTRACE(("RADEONScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); @@ -4525,6 +4531,33 @@ info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; + /* power management stuff */ + info->PowerManAlways = FALSE; + info->PowerManDPMS = FALSE; + info->PMActive = FALSE; + strptr = (char *)xf86GetOptValString(info->Options, OPTION_DYN_PM); + if(strptr) { + if((!strcmp(strptr,"Always")) || (!strcmp(strptr,"always"))) { + if (!info->PMActive) { + info->PowerManAlways = TRUE; + RADEONPMEnableDynamicMode(pScrn); + info->PMActive = TRUE; + } + } + else if((!strcmp(strptr,"DPMS")) || (!strcmp(strptr,"dpms"))) { + if (!info->PMActive) { + info->PowerManDPMS = TRUE; + } + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"DynamicPM\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"Always\", or \"DPMS\"\n"); + } + } + + return TRUE; } @@ -6443,6 +6476,12 @@ xf86ClearPrimInitDone(info->pEnt->index); + /* turn off power management */ + if (info->PMActive) { + RADEONPMDisableDynamicMode(pScrn); + info->PMActive = FALSE; + } + pScreen->BlockHandler = info->BlockHandler; pScreen->CloseScreen = info->CloseScreen; return (*pScreen->CloseScreen)(scrnIndex, pScreen); @@ -6570,6 +6609,11 @@ OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); } } + /* power management */ + if (info->PowerManDPMS && info->PMActive) { + RADEONPMDisableDynamicMode(pScrn); + info->PMActive = FALSE; + } } else if ((PowerManagementMode == DPMSModeOff) || (PowerManagementMode == DPMSModeSuspend) || (PowerManagementMode == DPMSModeStandby)) { @@ -6609,6 +6653,10 @@ } } } + if (info->PowerManDPMS && !info->PMActive) { + RADEONPMEnableDynamicMode(pScrn); + info->PMActive = TRUE; + } } } @@ -6616,3 +6664,174 @@ if (info->CPStarted) DRIUnlock(pScrn->pScreen); #endif } + +static void RADEONPMDisableDynamicMode(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long sclk_cntl; + unsigned long mclk_cntl; + unsigned long sclk_more_cntl; + unsigned long vclk_ecp_cntl; + unsigned long pixclks_cntl; + + /* Mobility chips only */ + if (!info->IsMobility) + return; + + /* Force Core Clocks */ + sclk_cntl = INPLL(pScrn, RADEON_SCLK_CNTL); + sclk_cntl |= RADEON_SCLK_CNTL_M6__FORCE_CP| + RADEON_SCLK_CNTL_M6__FORCE_HDP| + RADEON_SCLK_CNTL_M6__FORCE_DISP1| + RADEON_SCLK_CNTL_M6__FORCE_DISP2| + RADEON_SCLK_CNTL_M6__FORCE_TOP| + RADEON_SCLK_CNTL_M6__FORCE_E2| + RADEON_SCLK_CNTL_M6__FORCE_SE| + RADEON_SCLK_CNTL_M6__FORCE_IDCT| + RADEON_SCLK_CNTL_M6__FORCE_VIP| + RADEON_SCLK_CNTL_M6__FORCE_RE| + RADEON_SCLK_CNTL_M6__FORCE_PB| + RADEON_SCLK_CNTL_M6__FORCE_TAM| + RADEON_SCLK_CNTL_M6__FORCE_TDM| + RADEON_SCLK_CNTL_M6__FORCE_RB| + RADEON_SCLK_CNTL_M6__FORCE_TV_SCLK| + RADEON_SCLK_CNTL_M6__FORCE_SUBPIC| + RADEON_SCLK_CNTL_M6__FORCE_OV0; + OUTPLL(RADEON_SCLK_CNTL, sclk_cntl); + + + + sclk_more_cntl = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + sclk_more_cntl |= RADEON_SCLK_MORE_CNTL__FORCE_DISPREGS| + RADEON_SCLK_MORE_CNTL__FORCE_MC_GUI| + RADEON_SCLK_MORE_CNTL__FORCE_MC_HOST; + OUTPLL(RADEON_SCLK_MORE_CNTL, sclk_more_cntl); + + /* Force Display clocks */ + vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + vclk_ecp_cntl &= ~( RADEON_VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | + RADEON_VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb); + + OUTPLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); + + pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + pixclks_cntl &= ~( RADEON_PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb| + RADEON_PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb| + RADEON_PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb| + RADEON_PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb| + RADEON_PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb); + + OUTPLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); + + /* Force Memory Clocks */ + mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL); + mclk_cntl |= RADEON_MCLK_CNTL_M6__FORCE_MCLKA| + RADEON_MCLK_CNTL_M6__FORCE_MCLKB| + RADEON_MCLK_CNTL_M6__FORCE_YCLKA| + RADEON_MCLK_CNTL_M6__FORCE_YCLKB; + + OUTPLL(RADEON_MCLK_CNTL, mclk_cntl); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Disabled\n"); + +} + +static void RADEONPMEnableDynamicMode(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long clk_pwrmgt_cntl; + unsigned long sclk_cntl; + unsigned long sclk_more_cntl; + unsigned long clk_pin_cntl; + unsigned long pixclks_cntl; + unsigned long vclk_ecp_cntl; + unsigned long mclk_cntl; + unsigned long mclk_misc; + + /* Mobility chips only */ + if (!info->IsMobility) + return; + + /* Set Latencies */ + clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL_M6); + + clk_pwrmgt_cntl &= ~( RADEON_CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE_MASK| + RADEON_CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK| + RADEON_CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT_MASK| + RADEON_CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE_MASK); + /* Mode 1 */ + clk_pwrmgt_cntl = RADEON_CLK_PWRMGT_CNTL_M6__MC_CH_MODE| + RADEON_CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE | + (1<scrnIndex, X_INFO, "Dynamic Power Management Enabled\n"); + +} --- ../ati.orig/radeon.h 2003-07-30 22:09:43.000000000 -0400 +++ radeon.h 2003-08-08 17:49:57.000000000 -0400 @@ -540,6 +540,12 @@ #ifdef XFree86LOADER XF86ModReqInfo xaaReq; #endif + + /* Power management support */ + Bool PMActive; /* PM is on */ + Bool PowerManAlways; /* PM always on */ + Bool PowerManDPMS; /* PM only on when in DPMS */ + } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ --- ../ati.orig/radeon_reg.h 2003-07-30 22:16:02.000000000 -0400 +++ radeon_reg.h 2003-08-08 17:49:58.000000000 -0400 @@ -2061,4 +2061,67 @@ # define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) # define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) # define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 + +/* dynamic power management */ +#define RADEON_CLK_PWRMGT_CNTL_M6 0x0014 +#define RADEON_MCLK_MISC 0x001F + +#define RADEON_CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT__SHIFT 0x0000000d +#define RADEON_CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT__SHIFT 0x0000000f +#define RADEON_CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE__SHIFT 0x00000015 + +#define RADEON_PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb 0x00000040L +#define RADEON_PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb 0x00000080L +#define RADEON_PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb 0x00000800L +#define RADEON_PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb 0x00001000L +#define RADEON_PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb 0x00002000L +#define RADEON_PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb 0x00004000L +#define RADEON_PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb 0x00008000L + +#define RADEON_SCLK_CNTL_M6__SCLK_SRC_SEL_MASK 0x00000007L +#define RADEON_SCLK_CNTL_M6__FORCE_DISP2 0x00008000L +#define RADEON_SCLK_CNTL_M6__FORCE_CP 0x00010000L +#define RADEON_SCLK_CNTL_M6__FORCE_HDP 0x00020000L +#define RADEON_SCLK_CNTL_M6__FORCE_DISP1 0x00040000L +#define RADEON_SCLK_CNTL_M6__FORCE_TOP 0x00080000L +#define RADEON_SCLK_CNTL_M6__FORCE_E2 0x00100000L +#define RADEON_SCLK_CNTL_M6__FORCE_SE 0x00200000L +#define RADEON_SCLK_CNTL_M6__FORCE_IDCT 0x00400000L +#define RADEON_SCLK_CNTL_M6__FORCE_VIP 0x00800000L +#define RADEON_SCLK_CNTL_M6__FORCE_RE 0x01000000L +#define RADEON_SCLK_CNTL_M6__FORCE_PB 0x02000000L +#define RADEON_SCLK_CNTL_M6__FORCE_TV_SCLK 0x20000000L +#define RADEON_SCLK_CNTL_M6__FORCE_SUBPIC 0x40000000L +#define RADEON_SCLK_CNTL_M6__FORCE_OV0 0x80000000L +#define RADEON_SCLK_CNTL_M6__FORCE_TAM 0x04000000L +#define RADEON_SCLK_CNTL_M6__FORCE_TDM 0x08000000L +#define RADEON_SCLK_CNTL_M6__FORCE_RB 0x10000000L + +#define RADEON_SCLK_MORE_CNTL__FORCE_DISPREGS 0x00000100L +#define RADEON_SCLK_MORE_CNTL__FORCE_MC_GUI 0x00000200L +#define RADEON_SCLK_MORE_CNTL__FORCE_MC_HOST 0x00000400L + +#define RADEON_MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT 0x00001000L +#define RADEON_MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT 0x00002000L +#define RADEON_MCLK_MISC__MC_MCLK_DYN_ENABLE 0x00004000L +#define RADEON_MCLK_MISC__IO_MCLK_DYN_ENABLE 0x00008000L + +#define RADEON_VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb 0x00000040L +#define RADEON_VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb 0x00000080L + +#define RADEON_CLK_PWRMGT_CNTL_M6__MC_CH_MODE 0x00000100L +#define RADEON_CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE_MASK 0x00001000L +#define RADEON_CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE 0x00001000L +#define RADEON_CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK 0x00006000L +#define RADEON_CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT_MASK 0x00008000L +#define RADEON_CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE_MASK 0x00e00000L + +#define RADEON_MCLK_CNTL_M6__FORCE_MCLKA 0x00010000L +#define RADEON_MCLK_CNTL_M6__FORCE_MCLKB 0x00020000L +#define RADEON_MCLK_CNTL_M6__FORCE_YCLKA 0x00040000L +#define RADEON_MCLK_CNTL_M6__FORCE_YCLKB 0x00080000L + +#define RADEON_CLK_PIN_CNTL__SCLK_DYN_START_CNTL 0x00008000L +/* dymanic power managment */ + #endif