static void radeon_pm_enable_dynamic_mode()

in fbdev/aty/radeon_pm.c [331:546]


static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
{
	u32 tmp;

	/* R100 */
	if (!rinfo->has_CRTC2) {
                tmp = INPLL(pllSCLK_CNTL);

		if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
                    tmp &= ~(SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_RB);
                tmp &= ~(SCLK_CNTL__FORCE_HDP		| SCLK_CNTL__FORCE_DISP1 |
			 SCLK_CNTL__FORCE_TOP		| SCLK_CNTL__FORCE_SE   |
			 SCLK_CNTL__FORCE_IDCT		| SCLK_CNTL__FORCE_RE   |
			 SCLK_CNTL__FORCE_PB		| SCLK_CNTL__FORCE_TAM  |
			 SCLK_CNTL__FORCE_TDM);
                OUTPLL(pllSCLK_CNTL, tmp);
		return;
	}

	/* M10/M11 */
	if (rinfo->family == CHIP_FAMILY_RV350) {
		tmp = INPLL(pllSCLK_CNTL2);
		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
			 SCLK_CNTL2__R300_FORCE_GA  |
			 SCLK_CNTL2__R300_FORCE_CBA);
		tmp |=  (SCLK_CNTL2__R300_TCL_MAX_DYN_STOP_LAT |
			 SCLK_CNTL2__R300_GA_MAX_DYN_STOP_LAT  |
			 SCLK_CNTL2__R300_CBA_MAX_DYN_STOP_LAT);
		OUTPLL(pllSCLK_CNTL2, tmp);

		tmp = INPLL(pllSCLK_CNTL);
		tmp &= ~(SCLK_CNTL__FORCE_DISP2 | SCLK_CNTL__FORCE_CP      |
			 SCLK_CNTL__FORCE_HDP   | SCLK_CNTL__FORCE_DISP1   |
			 SCLK_CNTL__FORCE_TOP   | SCLK_CNTL__FORCE_E2      |
			 SCLK_CNTL__R300_FORCE_VAP | SCLK_CNTL__FORCE_IDCT |
			 SCLK_CNTL__FORCE_VIP   | SCLK_CNTL__R300_FORCE_SR |
			 SCLK_CNTL__R300_FORCE_PX | SCLK_CNTL__R300_FORCE_TX |
			 SCLK_CNTL__R300_FORCE_US | SCLK_CNTL__FORCE_TV_SCLK |
			 SCLK_CNTL__R300_FORCE_SU | SCLK_CNTL__FORCE_OV0);
		tmp |= SCLK_CNTL__DYN_STOP_LAT_MASK;
		OUTPLL(pllSCLK_CNTL, tmp);

		tmp = INPLL(pllSCLK_MORE_CNTL);
		tmp &= ~SCLK_MORE_CNTL__FORCEON;
		tmp |=  SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT |
			SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT |
			SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT;
		OUTPLL(pllSCLK_MORE_CNTL, tmp);

		tmp = INPLL(pllVCLK_ECP_CNTL);
		tmp |= (VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
			VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
		OUTPLL(pllVCLK_ECP_CNTL, tmp);

		tmp = INPLL(pllPIXCLKS_CNTL);
		tmp |= (PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb         |
			PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb     |
			PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
			PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb            |
			PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb    |
			PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb       |
			PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb        |
			PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb     |
			PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb     |
			PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb      |
			PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb        |
			PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb           |
			PIXCLKS_CNTL__R300_P2G2CLK_DAC_ALWAYS_ONb);
		OUTPLL(pllPIXCLKS_CNTL, tmp);

		tmp = INPLL(pllMCLK_MISC);
		tmp |= (MCLK_MISC__MC_MCLK_DYN_ENABLE |
			MCLK_MISC__IO_MCLK_DYN_ENABLE);
		OUTPLL(pllMCLK_MISC, tmp);

		tmp = INPLL(pllMCLK_CNTL);
		tmp |= (MCLK_CNTL__FORCE_MCLKA | MCLK_CNTL__FORCE_MCLKB);
		tmp &= ~(MCLK_CNTL__FORCE_YCLKA  |
			 MCLK_CNTL__FORCE_YCLKB  |
			 MCLK_CNTL__FORCE_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 & MCLK_CNTL__R300_DISABLE_MC_MCLKA) &&
		    (tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKB)) {
			/* If both bits are set, then check the active channels */
			tmp = INPLL(pllMCLK_CNTL);
			if (rinfo->vram_width == 64) {
			    if (INREG(MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY)
				tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKB;
			    else
				tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKA;
			} else {
			    tmp &= ~(MCLK_CNTL__R300_DISABLE_MC_MCLKA |
				     MCLK_CNTL__R300_DISABLE_MC_MCLKB);
			}
		}
		OUTPLL(pllMCLK_CNTL, tmp);
		return;
	}

	/* R300 */
	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
		tmp = INPLL(pllSCLK_CNTL);
		tmp &= ~(SCLK_CNTL__R300_FORCE_VAP);
		tmp |= SCLK_CNTL__FORCE_CP;
		OUTPLL(pllSCLK_CNTL, tmp);
		radeon_msleep(15);

		tmp = INPLL(pllSCLK_CNTL2);
		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
			 SCLK_CNTL2__R300_FORCE_GA  |
			 SCLK_CNTL2__R300_FORCE_CBA);
		OUTPLL(pllSCLK_CNTL2, tmp);
	}

	/* Others */

	tmp = INPLL( pllCLK_PWRMGT_CNTL);
	tmp &= ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK|
		 CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT_MASK|
		 CLK_PWRMGT_CNTL__DYN_STOP_MODE_MASK);
	tmp |= CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE_MASK |
	       (0x01 << CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT__SHIFT);
	OUTPLL( pllCLK_PWRMGT_CNTL, tmp);
	radeon_msleep(15);

	tmp = INPLL(pllCLK_PIN_CNTL);
	tmp |= CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
	OUTPLL(pllCLK_PIN_CNTL, tmp);
	radeon_msleep(15);

	/* 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(pllSCLK_CNTL);
	tmp &= ~SCLK_CNTL__FORCEON_MASK;

	/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
	if ((rinfo->family == CHIP_FAMILY_RV250 &&
	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
	    ((rinfo->family == CHIP_FAMILY_RV100) &&
	     ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) {
		tmp |= SCLK_CNTL__FORCE_CP;
		tmp |= SCLK_CNTL__FORCE_VIP;
	}
	OUTPLL(pllSCLK_CNTL, tmp);
	radeon_msleep(15);

	if ((rinfo->family == CHIP_FAMILY_RV200) ||
	    (rinfo->family == CHIP_FAMILY_RV250) ||
	    (rinfo->family == CHIP_FAMILY_RV280)) {
		tmp = INPLL(pllSCLK_MORE_CNTL);
		tmp &= ~SCLK_MORE_CNTL__FORCEON;

		/* RV200::A11 A12 RV250::A11 A12 */
		if (((rinfo->family == CHIP_FAMILY_RV200) ||
		     (rinfo->family == CHIP_FAMILY_RV250)) &&
		    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
			tmp |= SCLK_MORE_CNTL__FORCEON;

		OUTPLL(pllSCLK_MORE_CNTL, tmp);
		radeon_msleep(15);
	}
	

	/* RV200::A11 A12, RV250::A11 A12 */
	if (((rinfo->family == CHIP_FAMILY_RV200) ||
	     (rinfo->family == CHIP_FAMILY_RV250)) &&
	    ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) {
		tmp = INPLL(pllPLL_PWRMGT_CNTL);
		tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE;
		OUTPLL(pllPLL_PWRMGT_CNTL, tmp);
		radeon_msleep(15);
	}

	tmp = INPLL(pllPIXCLKS_CNTL);
	tmp |=  PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb |
		PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb|
		PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb|
		PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb|
		PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb|
		PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb|
		PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb;
	OUTPLL(pllPIXCLKS_CNTL, tmp);
	radeon_msleep(15);
		
	tmp = INPLL(pllVCLK_ECP_CNTL);
	tmp |=  VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
		VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb;
	OUTPLL(pllVCLK_ECP_CNTL, tmp);

	/* X doesn't do that ... hrm, we do on mobility && Macs */
#ifdef CONFIG_PPC
	if (rinfo->is_mobility) {
		tmp  = INPLL(pllMCLK_CNTL);
		tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
			 MCLK_CNTL__FORCE_MCLKB |
			 MCLK_CNTL__FORCE_YCLKA |
			 MCLK_CNTL__FORCE_YCLKB);
		OUTPLL(pllMCLK_CNTL, tmp);
		radeon_msleep(15);

		tmp = INPLL(pllMCLK_MISC);
		tmp |= 	MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT|
			MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT|
			MCLK_MISC__MC_MCLK_DYN_ENABLE|
			MCLK_MISC__IO_MCLK_DYN_ENABLE;
		OUTPLL(pllMCLK_MISC, tmp);
		radeon_msleep(15);
	}
#endif /* CONFIG_PPC */
}