--- ../ati.orig/radeon_driver.c 2003-02-24 22:50:15.000000000 -0500 +++ radeon_driver.c 2003-04-14 23:04:18.000000000 -0400 @@ -116,6 +116,11 @@ int PowerManagementMode, int flags); +/* power management functions */ +static void RADEONPMDisableDynamicMode(ScrnInfoPtr pScrn); +static void RADEONPMEnableDynamicMode(ScrnInfoPtr pScrn); + + typedef enum { OPTION_NOACCEL, OPTION_SW_CURSOR, @@ -141,7 +146,8 @@ OPTION_CLONE_HSYNC, OPTION_CLONE_VREFRESH, OPTION_FBDEV, - OPTION_VIDEO_KEY + OPTION_VIDEO_KEY, + OPTION_DYN_PM } RADEONOpts; const OptionInfoRec RADEONOptions[] = { @@ -170,6 +176,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_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -4073,6 +4080,13 @@ info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; +/* power management stuff */ + info->PMActive = FALSE; + xf86GetOptValBool(info->Options, OPTION_DYN_PM, &info->PMActive); + if (info->PMActive) { + RADEONPMEnableDynamicMode(pScrn); + } + return TRUE; } @@ -5837,6 +5851,10 @@ xf86ClearPrimInitDone(pScrn->entityList[0]); +/* turn off power management */ + if (info->PMActive) + RADEONPMDisableDynamicMode(pScrn); + pScreen->BlockHandler = info->BlockHandler; pScreen->CloseScreen = info->CloseScreen; return (*pScreen->CloseScreen)(scrnIndex, pScreen); @@ -5942,3 +5960,175 @@ 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->ChipFamily != CHIP_FAMILY_M6) && + (info->ChipFamily != CHIP_FAMILY_M7) && + (info->ChipFamily != CHIP_FAMILY_M9)) + return; + + /* Force Core Clocks */ + sclk_cntl = INPLL(pScrn, RADEON_SCLK_CNTL); + sclk_cntl |= SCLK_CNTL_M6__FORCE_CP| + SCLK_CNTL_M6__FORCE_HDP| + SCLK_CNTL_M6__FORCE_DISP1| + SCLK_CNTL_M6__FORCE_DISP2| + SCLK_CNTL_M6__FORCE_TOP| + SCLK_CNTL_M6__FORCE_E2| + SCLK_CNTL_M6__FORCE_SE| + SCLK_CNTL_M6__FORCE_IDCT| + SCLK_CNTL_M6__FORCE_VIP| + SCLK_CNTL_M6__FORCE_RE| + SCLK_CNTL_M6__FORCE_PB| + SCLK_CNTL_M6__FORCE_TAM| + SCLK_CNTL_M6__FORCE_TDM| + SCLK_CNTL_M6__FORCE_RB| + SCLK_CNTL_M6__FORCE_TV_SCLK| + SCLK_CNTL_M6__FORCE_SUBPIC| + SCLK_CNTL_M6__FORCE_OV0; + OUTPLL(RADEON_SCLK_CNTL, sclk_cntl); + + + + sclk_more_cntl = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + sclk_more_cntl |= SCLK_MORE_CNTL__FORCE_DISPREGS| + SCLK_MORE_CNTL__FORCE_MC_GUI| + 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 &= ~( VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | + VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb); + + OUTPLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); + + pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + pixclks_cntl &= ~( PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | + PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb| + PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb | + PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb| + PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb| + PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb| + PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb); + + OUTPLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); + + /* Force Memory Clocks */ + mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL); + mclk_cntl |= MCLK_CNTL_M6__FORCE_MCLKA| + MCLK_CNTL_M6__FORCE_MCLKB| + MCLK_CNTL_M6__FORCE_YCLKA| + MCLK_CNTL_M6__FORCE_YCLKB; + + OUTPLL(RADEON_MCLK_CNTL, mclk_cntl); +} + +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->ChipFamily != CHIP_FAMILY_M6) && + (info->ChipFamily != CHIP_FAMILY_M7) && + (info->ChipFamily != CHIP_FAMILY_M9)) + return; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Power Management Enabled\n"); + + /* Set Latencies */ + clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL_M6); + + clk_pwrmgt_cntl &= ~( CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE_MASK| + CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK| + CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT_MASK| + CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE_MASK); + /* Mode 1 */ + clk_pwrmgt_cntl = CLK_PWRMGT_CNTL_M6__MC_CH_MODE| + CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE | + (1<