diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/radeon.h | 5 | ||||
-rw-r--r-- | src/radeon_atombios.c | 4 | ||||
-rw-r--r-- | src/radeon_atombios.h | 4 | ||||
-rw-r--r-- | src/radeon_driver.c | 401 | ||||
-rw-r--r-- | src/radeon_pm.c | 416 |
6 files changed, 434 insertions, 398 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7cc2a6fb..1864f96e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -92,7 +92,7 @@ radeon_drv_la_SOURCES = \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ radeon_vip.c radeon_misc.c radeon_probe.c \ legacy_crtc.c legacy_output.c \ - radeon_textured_video.c \ + radeon_textured_video.c radeon_pm.c \ radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \ $(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \ $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c diff --git a/src/radeon.h b/src/radeon.h index d56d94df..60d56db2 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -186,7 +186,7 @@ typedef enum { OPTION_SUBPIXEL_ORDER, #endif OPTION_SHOWCACHE, - OPTION_DYNAMIC_CLOCKS, + OPTION_CLOCK_GATING, OPTION_BIOS_HOTKEYS, OPTION_VGA_ACCESS, OPTION_REVERSE_DDC, @@ -1068,6 +1068,9 @@ extern void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore); +/* radeon_pm.c */ +extern void RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable); + #ifdef USE_EXA /* radeon_exa.c */ extern Bool RADEONSetupMemEXA(ScreenPtr pScreen); diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index a657fac7..e32f7ba4 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -524,7 +524,7 @@ rhdAtomASICInit(atomBiosHandlePtr handle) } int -atombios_dyn_clk_setup(ScrnInfoPtr pScrn, int enable) +atombios_clk_gating_setup(ScrnInfoPtr pScrn, Bool enable) { RADEONInfoPtr info = RADEONPTR(pScrn); DYNAMIC_CLOCK_GATING_PS_ALLOCATION dynclk_data; @@ -548,7 +548,7 @@ atombios_dyn_clk_setup(ScrnInfoPtr pScrn, int enable) } int -atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, int enable) +atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, Bool enable) { RADEONInfoPtr info = RADEONPTR(pScrn); ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION pwrmgt_data; diff --git a/src/radeon_atombios.h b/src/radeon_atombios.h index b9a5398c..806df303 100644 --- a/src/radeon_atombios.h +++ b/src/radeon_atombios.h @@ -117,10 +117,10 @@ extern Bool RADEONGetATOMConnectorInfoFromBIOSConnectorTable (ScrnInfoPtr pScrn); extern int -atombios_dyn_clk_setup(ScrnInfoPtr pScrn, int enable); +atombios_clk_gating_setup(ScrnInfoPtr pScrn, Bool enable); extern int -atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, int enable); +atombios_static_pwrmgt_setup(ScrnInfoPtr pScrn, Bool enable); extern Bool RADEONGetATOMTVInfo(xf86OutputPtr output); diff --git a/src/radeon_driver.c b/src/radeon_driver.c index f1991e89..fe00dd79 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -118,8 +118,6 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode); static void RADEONSave(ScrnInfoPtr pScrn); -static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); -static void RADEONForceSomeClocks(ScrnInfoPtr pScrn); static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); static void @@ -176,7 +174,7 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE }, #endif { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_DYNAMIC_CLOCKS, "DynamicClocks", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CLOCK_GATING, "ClockGating", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VGA_ACCESS, "VGAAccess", OPTV_BOOLEAN, {0}, TRUE }, { OPTION_REVERSE_DDC, "ReverseDDC", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, @@ -3330,21 +3328,10 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* blank the outputs/crtcs */ RADEONBlank(pScrn); - if (info->IsMobility && !IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); - } - } else if (IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - atombios_static_pwrmgt_setup(pScrn, 1); - atombios_dyn_clk_setup(pScrn, 1); - } - } - - if (IS_R300_VARIANT || IS_RV100_VARIANT) - RADEONForceSomeClocks(pScrn); + if (xf86ReturnOptValBool(info->Options, OPTION_CLOCK_GATING, FALSE)) + RADEONSetClockGating(pScrn, TRUE); + else + RADEONSetClockGating(pScrn, FALSE); if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -5601,21 +5588,10 @@ Bool RADEONEnterVT(int scrnIndex, int flags) /* Makes sure the engine is idle before doing anything */ RADEONWaitForIdleMMIO(pScrn); - if (info->IsMobility && !IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); - } - } else if (IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - atombios_static_pwrmgt_setup(pScrn, 1); - atombios_dyn_clk_setup(pScrn, 1); - } - } - - if (IS_R300_VARIANT || IS_RV100_VARIANT) - RADEONForceSomeClocks(pScrn); + if (xf86ReturnOptValBool(info->Options, OPTION_CLOCK_GATING, FALSE)) + RADEONSetClockGating(pScrn, TRUE); + else + RADEONSetClockGating(pScrn, FALSE); for (i = 0; i < config->num_crtc; i++) radeon_crtc_modeset_ioctl(config->crtc[i], TRUE); @@ -5874,362 +5850,3 @@ void RADEONFreeScreen(int scrnIndex, int flags) #endif RADEONFreeRec(pScrn); } - -static void RADEONForceSomeClocks(ScrnInfoPtr pScrn) -{ - /* It appears from r300 and rv100 may need some clocks forced-on */ - uint32_t tmp; - - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); -} - -static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - uint32_t tmp; - switch(mode) { - case 0: /* Turn everything OFF (ForceON to everything)*/ - if ( !pRADEONEnt->HasCRTC2 ) { - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | - RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP | - RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | - RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | - RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | - RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | - RADEON_SCLK_FORCE_RB); - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - } else if (info->ChipFamily == CHIP_FAMILY_RV350) { - /* for RV350/M10, no delays are required. */ - tmp = INPLL(pScrn, R300_SCLK_CNTL2); - tmp |= (R300_SCLK_FORCE_TCL | - R300_SCLK_FORCE_GA | - R300_SCLK_FORCE_CBA); - OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); - - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | - RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | - RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | - R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | - RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | - R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | - R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | - R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); - tmp |= RADEON_SCLK_MORE_FORCEON; - OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_MCLK_CNTL); - tmp |= (RADEON_FORCEON_MCLKA | - RADEON_FORCEON_MCLKB | - RADEON_FORCEON_YCLKA | - RADEON_FORCEON_YCLKB | - RADEON_FORCEON_MC); - OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | - RADEON_PIXCLK_DAC_ALWAYS_ONb | - R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); - OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | - RADEON_PIX2CLK_DAC_ALWAYS_ONb | - RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | - R300_DVOCLK_ALWAYS_ONb | - RADEON_PIXCLK_BLEND_ALWAYS_ONb | - RADEON_PIXCLK_GV_ALWAYS_ONb | - R300_PIXCLK_DVO_ALWAYS_ONb | - RADEON_PIXCLK_LVDS_ALWAYS_ONb | - RADEON_PIXCLK_TMDS_ALWAYS_ONb | - R300_PIXCLK_TRANS_ALWAYS_ONb | - R300_PIXCLK_TVO_ALWAYS_ONb | - R300_P2G2CLK_ALWAYS_ONb | - R300_P2G2CLK_ALWAYS_ONb | - R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); - } else { - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); - tmp |= RADEON_SCLK_FORCE_SE; - - if ( !pRADEONEnt->HasCRTC2 ) { - tmp |= ( RADEON_SCLK_FORCE_RB | - RADEON_SCLK_FORCE_TDM | - RADEON_SCLK_FORCE_TAM | - RADEON_SCLK_FORCE_PB | - RADEON_SCLK_FORCE_RE | - RADEON_SCLK_FORCE_VIP | - RADEON_SCLK_FORCE_IDCT | - RADEON_SCLK_FORCE_TOP | - RADEON_SCLK_FORCE_DISP1 | - RADEON_SCLK_FORCE_DISP2 | - RADEON_SCLK_FORCE_HDP ); - } else if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350)) { - tmp |= ( RADEON_SCLK_FORCE_HDP | - RADEON_SCLK_FORCE_DISP1 | - RADEON_SCLK_FORCE_DISP2 | - RADEON_SCLK_FORCE_TOP | - RADEON_SCLK_FORCE_IDCT | - RADEON_SCLK_FORCE_VIP); - } - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - - usleep(16000); - - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350)) { - tmp = INPLL(pScrn, R300_SCLK_CNTL2); - tmp |= ( R300_SCLK_FORCE_TCL | - R300_SCLK_FORCE_GA | - R300_SCLK_FORCE_CBA); - OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); - usleep(16000); - } - - if (info->IsIGP) { - tmp = INPLL(pScrn, RADEON_MCLK_CNTL); - tmp &= ~(RADEON_FORCEON_MCLKA | - RADEON_FORCEON_YCLKA); - OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); - usleep(16000); - } - - if ((info->ChipFamily == CHIP_FAMILY_RV200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) { - tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); - tmp |= RADEON_SCLK_MORE_FORCEON; - OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); - usleep(16000); - } - - tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | - RADEON_PIX2CLK_DAC_ALWAYS_ONb | - RADEON_PIXCLK_BLEND_ALWAYS_ONb | - RADEON_PIXCLK_GV_ALWAYS_ONb | - RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | - RADEON_PIXCLK_LVDS_ALWAYS_ONb | - RADEON_PIXCLK_TMDS_ALWAYS_ONb); - - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); - usleep(16000); - - tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | - RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Disabled\n"); - break; - case 1: - if (!pRADEONEnt->HasCRTC2) { - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - if ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) > - RADEON_CFG_ATI_REV_A13) { - tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB); - } - tmp &= ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | - RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | - RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | - RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | - RADEON_SCLK_FORCE_TDM); - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - } else if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { - if (info->ChipFamily == CHIP_FAMILY_RV350) { - tmp = INPLL(pScrn, R300_SCLK_CNTL2); - tmp &= ~(R300_SCLK_FORCE_TCL | - R300_SCLK_FORCE_GA | - R300_SCLK_FORCE_CBA); - tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | - R300_SCLK_GA_MAX_DYN_STOP_LAT | - R300_SCLK_CBA_MAX_DYN_STOP_LAT); - OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); - - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | - RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | - RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | - R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | - RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | - R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | - R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | - R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); - tmp |= RADEON_DYN_STOP_LAT_MASK; - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); - tmp &= ~RADEON_SCLK_MORE_FORCEON; - tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; - OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - tmp |= (RADEON_PIXCLK_ALWAYS_ONb | - RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | - RADEON_PIX2CLK_DAC_ALWAYS_ONb | - RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | - R300_DVOCLK_ALWAYS_ONb | - RADEON_PIXCLK_BLEND_ALWAYS_ONb | - RADEON_PIXCLK_GV_ALWAYS_ONb | - R300_PIXCLK_DVO_ALWAYS_ONb | - RADEON_PIXCLK_LVDS_ALWAYS_ONb | - RADEON_PIXCLK_TMDS_ALWAYS_ONb | - R300_PIXCLK_TRANS_ALWAYS_ONb | - R300_PIXCLK_TVO_ALWAYS_ONb | - R300_P2G2CLK_ALWAYS_ONb | - R300_P2G2CLK_ALWAYS_ONb); - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); - - tmp = INPLL(pScrn, RADEON_MCLK_MISC); - tmp |= (RADEON_MC_MCLK_DYN_ENABLE | - RADEON_IO_MCLK_DYN_ENABLE); - OUTPLL(pScrn, RADEON_MCLK_MISC, tmp); - - tmp = INPLL(pScrn, RADEON_MCLK_CNTL); - tmp |= (RADEON_FORCEON_MCLKA | - RADEON_FORCEON_MCLKB); - - tmp &= ~(RADEON_FORCEON_YCLKA | - RADEON_FORCEON_YCLKB | - RADEON_FORCEON_MC); - - /* Some releases of vbios have set DISABLE_MC_MCLKA - and DISABLE_MC_MCLKB bits in the vbios table. Setting these - bits will cause H/W hang when reading video memory with dynamic clocking - enabled. */ - if ((tmp & R300_DISABLE_MC_MCLKA) && - (tmp & R300_DISABLE_MC_MCLKB)) { - /* If both bits are set, then check the active channels */ - tmp = INPLL(pScrn, RADEON_MCLK_CNTL); - if (info->RamWidth == 64) { - if (INREG(RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY) - tmp &= ~R300_DISABLE_MC_MCLKB; - else - tmp &= ~R300_DISABLE_MC_MCLKA; - } else { - tmp &= ~(R300_DISABLE_MC_MCLKA | - R300_DISABLE_MC_MCLKB); - } - } - - OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); - } else { - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - tmp &= ~(R300_SCLK_FORCE_VAP); - tmp |= RADEON_SCLK_FORCE_CP; - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - usleep(15000); - - tmp = INPLL(pScrn, R300_SCLK_CNTL2); - tmp &= ~(R300_SCLK_FORCE_TCL | - R300_SCLK_FORCE_GA | - R300_SCLK_FORCE_CBA); - OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); - } - } else { - tmp = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); - - tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | - RADEON_DISP_DYN_STOP_LAT_MASK | - RADEON_DYN_STOP_MODE_MASK); - - tmp |= (RADEON_ENGIN_DYNCLK_MODE | - (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); - OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, tmp); - usleep(15000); - - tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL); - tmp |= RADEON_SCLK_DYN_START_CNTL; - OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp); - usleep(15000); - - /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 - to lockup randomly, leave them as set by BIOS. - */ - tmp = INPLL(pScrn, RADEON_SCLK_CNTL); - /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/ - tmp &= ~RADEON_SCLK_FORCEON_MASK; - - /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ - if (((info->ChipFamily == CHIP_FAMILY_RV250) && - ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < - RADEON_CFG_ATI_REV_A13)) || - ((info->ChipFamily == CHIP_FAMILY_RV100) && - ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <= - RADEON_CFG_ATI_REV_A13))){ - tmp |= RADEON_SCLK_FORCE_CP; - tmp |= RADEON_SCLK_FORCE_VIP; - } - - OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); - - if ((info->ChipFamily == CHIP_FAMILY_RV200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) { - tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); - tmp &= ~RADEON_SCLK_MORE_FORCEON; - - /* RV200::A11 A12 RV250::A11 A12 */ - if (((info->ChipFamily == CHIP_FAMILY_RV200) || - (info->ChipFamily == CHIP_FAMILY_RV250)) && - ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < - RADEON_CFG_ATI_REV_A13)) { - tmp |= RADEON_SCLK_MORE_FORCEON; - } - OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); - usleep(15000); - } - - /* RV200::A11 A12, RV250::A11 A12 */ - if (((info->ChipFamily == CHIP_FAMILY_RV200) || - (info->ChipFamily == CHIP_FAMILY_RV250)) && - ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < - RADEON_CFG_ATI_REV_A13)) { - tmp = INPLL(pScrn, RADEON_PLL_PWRMGT_CNTL); - tmp |= RADEON_TCL_BYPASS_DISABLE; - OUTPLL(pScrn, RADEON_PLL_PWRMGT_CNTL, tmp); - } - usleep(15000); - - /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/ - tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | - RADEON_PIX2CLK_DAC_ALWAYS_ONb | - RADEON_PIXCLK_BLEND_ALWAYS_ONb | - RADEON_PIXCLK_GV_ALWAYS_ONb | - RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | - RADEON_PIXCLK_LVDS_ALWAYS_ONb | - RADEON_PIXCLK_TMDS_ALWAYS_ONb); - - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); - usleep(15000); - - tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - tmp |= (RADEON_PIXCLK_ALWAYS_ONb | - RADEON_PIXCLK_DAC_ALWAYS_ONb); - - OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); - usleep(15000); - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Enabled\n"); - break; - default: - break; - } -} diff --git a/src/radeon_pm.c b/src/radeon_pm.c new file mode 100644 index 00000000..4f3f4c7a --- /dev/null +++ b/src/radeon_pm.c @@ -0,0 +1,416 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR + * AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Alex Deucher <alexander.deucher@amd.com> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + /* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_atombios.h" + +static void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + uint32_t tmp; + + if (enable) { + if (!pRADEONEnt->HasCRTC2) { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + if ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) > + RADEON_CFG_ATI_REV_A13) { + tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB); + } + tmp &= ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_TDM); + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + } else if (IS_R300_VARIANT) { + if (info->ChipFamily >= CHIP_FAMILY_RV350) { + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | + R300_SCLK_GA_MAX_DYN_STOP_LAT | + R300_SCLK_CBA_MAX_DYN_STOP_LAT); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + tmp |= RADEON_DYN_STOP_LAT_MASK; + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_MCLK_MISC); + tmp |= (RADEON_MC_MCLK_DYN_ENABLE | + RADEON_IO_MCLK_DYN_ENABLE); + OUTPLL(pScrn, RADEON_MCLK_MISC, tmp); + + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB); + + tmp &= ~(RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + + /* Some releases of vbios have set DISABLE_MC_MCLKA + and DISABLE_MC_MCLKB bits in the vbios table. Setting these + bits will cause H/W hang when reading video memory with dynamic clocking + enabled. */ + if ((tmp & R300_DISABLE_MC_MCLKA) && + (tmp & R300_DISABLE_MC_MCLKB)) { + /* If both bits are set, then check the active channels */ + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + if (info->RamWidth == 64) { + if (INREG(RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY) + tmp &= ~R300_DISABLE_MC_MCLKB; + else + tmp &= ~R300_DISABLE_MC_MCLKA; + } else { + tmp &= ~(R300_DISABLE_MC_MCLKA | + R300_DISABLE_MC_MCLKB); + } + } + + OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); + } else { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp &= ~(R300_SCLK_FORCE_VAP); + tmp |= RADEON_SCLK_FORCE_CP; + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + usleep(15000); + + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp &= ~(R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + } + } else { + tmp = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); + + tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | + RADEON_DISP_DYN_STOP_LAT_MASK | + RADEON_DYN_STOP_MODE_MASK); + + tmp |= (RADEON_ENGIN_DYNCLK_MODE | + (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); + OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, tmp); + usleep(15000); + + tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL); + tmp |= RADEON_SCLK_DYN_START_CNTL; + OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp); + usleep(15000); + + /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 + to lockup randomly, leave them as set by BIOS. + */ + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/ + tmp &= ~RADEON_SCLK_FORCEON_MASK; + + /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ + if (((info->ChipFamily == CHIP_FAMILY_RV250) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) || + ((info->ChipFamily == CHIP_FAMILY_RV100) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <= + RADEON_CFG_ATI_REV_A13))) { + tmp |= RADEON_SCLK_FORCE_CP; + tmp |= RADEON_SCLK_FORCE_VIP; + } + + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + if ((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp &= ~RADEON_SCLK_MORE_FORCEON; + + /* RV200::A11 A12 RV250::A11 A12 */ + if (((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250)) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) { + tmp |= RADEON_SCLK_MORE_FORCEON; + } + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + usleep(15000); + } + + /* RV200::A11 A12, RV250::A11 A12 */ + if (((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250)) && + ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) < + RADEON_CFG_ATI_REV_A13)) { + tmp = INPLL(pScrn, RADEON_PLL_PWRMGT_CNTL); + tmp |= RADEON_TCL_BYPASS_DISABLE; + OUTPLL(pScrn, RADEON_PLL_PWRMGT_CNTL, tmp); + } + usleep(15000); + + /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/ + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + usleep(15000); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp |= (RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + usleep(15000); + } + } else { + /* Turn everything OFF (ForceON to everything)*/ + if ( !pRADEONEnt->HasCRTC2 ) { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | + RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_RB); + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + } else if (info->ChipFamily >= CHIP_FAMILY_RV350) { + /* for RV350/M10, no delays are required. */ + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp |= (R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | + RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | + R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | + R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | + R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | + R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + tmp |= (RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC); + OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | + R300_DVOCLK_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + R300_PIXCLK_DVO_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb | + R300_PIXCLK_TRANS_ALWAYS_ONb | + R300_PIXCLK_TVO_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_P2G2CLK_ALWAYS_ONb | + R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + } else { + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); + tmp |= RADEON_SCLK_FORCE_SE; + + if ( !pRADEONEnt->HasCRTC2 ) { + tmp |= ( RADEON_SCLK_FORCE_RB | + RADEON_SCLK_FORCE_TDM | + RADEON_SCLK_FORCE_TAM | + RADEON_SCLK_FORCE_PB | + RADEON_SCLK_FORCE_RE | + RADEON_SCLK_FORCE_VIP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_HDP ); + } else if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350)) { + tmp |= ( RADEON_SCLK_FORCE_HDP | + RADEON_SCLK_FORCE_DISP1 | + RADEON_SCLK_FORCE_DISP2 | + RADEON_SCLK_FORCE_TOP | + RADEON_SCLK_FORCE_IDCT | + RADEON_SCLK_FORCE_VIP); + } + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); + + usleep(16000); + + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350)) { + tmp = INPLL(pScrn, R300_SCLK_CNTL2); + tmp |= ( R300_SCLK_FORCE_TCL | + R300_SCLK_FORCE_GA | + R300_SCLK_FORCE_CBA); + OUTPLL(pScrn, R300_SCLK_CNTL2, tmp); + usleep(16000); + } + + if (info->IsIGP) { + tmp = INPLL(pScrn, RADEON_MCLK_CNTL); + tmp &= ~(RADEON_FORCEON_MCLKA | + RADEON_FORCEON_YCLKA); + OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp); + usleep(16000); + } + + if ((info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); + tmp |= RADEON_SCLK_MORE_FORCEON; + OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp); + usleep(16000); + } + + tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | + RADEON_PIX2CLK_DAC_ALWAYS_ONb | + RADEON_PIXCLK_BLEND_ALWAYS_ONb | + RADEON_PIXCLK_GV_ALWAYS_ONb | + RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | + RADEON_PIXCLK_LVDS_ALWAYS_ONb | + RADEON_PIXCLK_TMDS_ALWAYS_ONb); + + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + usleep(16000); + + tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | + RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + } + } +} + +void RADEONForceSomeClocks(ScrnInfoPtr pScrn) +{ + /* It appears from r300 and rv100 may need some clocks forced-on */ + uint32_t tmp; + + tmp = INPLL(pScrn, RADEON_SCLK_CNTL); + tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; + OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp); +} + +void +RADEONSetClockGating(ScrnInfoPtr pScrn, Bool enable) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONWaitForIdleMMIO(pScrn); + + if (info->ChipFamily >= CHIP_FAMILY_R600) + atombios_static_pwrmgt_setup(pScrn, enable); + else { + if (info->IsAtomBios) { + atombios_static_pwrmgt_setup(pScrn, enable); + atombios_clk_gating_setup(pScrn, enable); + } else if (info->IsMobility) + LegacySetClockGating(pScrn, enable); + + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Gating %sabled\n", + enable ? "En" : "Dis"); +} + |