📄 radeon_pm.c
字号:
crtc_more_cntl = INREG( CRTC_MORE_CNTL); fp_gen_cntl = INREG( FP_GEN_CNTL); fp2_gen_cntl = INREG( FP2_GEN_CNTL); OUTREG( CRTC_MORE_CNTL, 0); OUTREG( FP_GEN_CNTL, 0); OUTREG( FP2_GEN_CNTL,0); OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) ); OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) ); /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */ if (rinfo->family == CHIP_FAMILY_RV350) { u32 sdram_mode_reg = rinfo->save_regs[35]; static const u32 default_mrtable[] = { 0x21320032, 0x21321000, 0xa1321000, 0x21321000, 0xffffffff, 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, 0x21321002, 0xa1321002, 0x21321002, 0xffffffff, 0x21320132, 0xa1320132, 0x21320132, 0xffffffff, 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, 0x31320032 }; const u32 *mrtable = default_mrtable; int i, mrtable_size = ARRAY_SIZE(default_mrtable); mdelay(30); /* Disable refresh */ memRefreshCntl = INREG( MEM_REFRESH_CNTL) & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; OUTREG( MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); /* Configure and enable M & SPLLs */ radeon_pm_enable_dll_m10(rinfo); radeon_pm_yclk_mclk_sync_m10(rinfo);#ifdef CONFIG_PPC_OF if (rinfo->of_node != NULL) { int size; mrtable = of_get_property(rinfo->of_node, "ATY,MRT", &size); if (mrtable) mrtable_size = size >> 2; else mrtable = default_mrtable; }#endif /* CONFIG_PPC_OF */ /* Program the SDRAM */ sdram_mode_reg = mrtable[0]; OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg); for (i = 0; i < mrtable_size; i++) { if (mrtable[i] == 0xffffffffu) radeon_pm_m10_program_mode_wait(rinfo); else { sdram_mode_reg &= ~(MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE | MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET); sdram_mode_reg |= mrtable[i]; OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg); mdelay(1); } } /* Restore memory refresh */ OUTREG(MEM_REFRESH_CNTL, memRefreshCntl); mdelay(30); } /* Here come the desktop RV200 "QW" card */ else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) { /* Disable refresh */ memRefreshCntl = INREG( MEM_REFRESH_CNTL) & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; OUTREG(MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); mdelay(30); /* Reset memory */ OUTREG(MEM_SDRAM_MODE_REG, INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); radeon_pm_program_mode_reg(rinfo, 0x2002, 2); radeon_pm_program_mode_reg(rinfo, 0x0132, 2); radeon_pm_program_mode_reg(rinfo, 0x0032, 2); OUTREG(MEM_SDRAM_MODE_REG, INREG(MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); OUTREG( MEM_REFRESH_CNTL, memRefreshCntl); } /* The M6 */ else if (rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV100) { /* Disable refresh */ memRefreshCntl = INREG(EXT_MEM_CNTL) & ~(1 << 20); OUTREG( EXT_MEM_CNTL, memRefreshCntl | (1 << 20)); /* Reset memory */ OUTREG( MEM_SDRAM_MODE_REG, INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); /* DLL */ radeon_pm_enable_dll(rinfo); /* MLCK / YCLK sync */ radeon_pm_yclk_mclk_sync(rinfo); /* Program Mode Register */ radeon_pm_program_mode_reg(rinfo, 0x2000, 1); radeon_pm_program_mode_reg(rinfo, 0x2001, 1); radeon_pm_program_mode_reg(rinfo, 0x2002, 1); radeon_pm_program_mode_reg(rinfo, 0x0132, 1); radeon_pm_program_mode_reg(rinfo, 0x0032, 1); /* Complete & re-enable refresh */ OUTREG( MEM_SDRAM_MODE_REG, INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); OUTREG(EXT_MEM_CNTL, memRefreshCntl); } /* And finally, the M7..M9 models, including M9+ (RV280) */ else if (rinfo->is_mobility) { /* Disable refresh */ memRefreshCntl = INREG( MEM_REFRESH_CNTL) & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; OUTREG( MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); /* Reset memory */ OUTREG( MEM_SDRAM_MODE_REG, INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); /* DLL */ radeon_pm_enable_dll(rinfo); /* MLCK / YCLK sync */ radeon_pm_yclk_mclk_sync(rinfo); /* M6, M7 and M9 so far ... */ if (rinfo->family <= CHIP_FAMILY_RV250) { radeon_pm_program_mode_reg(rinfo, 0x2000, 1); radeon_pm_program_mode_reg(rinfo, 0x2001, 1); radeon_pm_program_mode_reg(rinfo, 0x2002, 1); radeon_pm_program_mode_reg(rinfo, 0x0132, 1); radeon_pm_program_mode_reg(rinfo, 0x0032, 1); } /* M9+ (iBook G4) */ else if (rinfo->family == CHIP_FAMILY_RV280) { radeon_pm_program_mode_reg(rinfo, 0x2000, 1); radeon_pm_program_mode_reg(rinfo, 0x0132, 1); radeon_pm_program_mode_reg(rinfo, 0x0032, 1); } /* Complete & re-enable refresh */ OUTREG( MEM_SDRAM_MODE_REG, INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); OUTREG( MEM_REFRESH_CNTL, memRefreshCntl); } OUTREG( CRTC_GEN_CNTL, crtcGenCntl); OUTREG( CRTC2_GEN_CNTL, crtcGenCntl2); OUTREG( FP_GEN_CNTL, fp_gen_cntl); OUTREG( FP2_GEN_CNTL, fp2_gen_cntl); OUTREG( CRTC_MORE_CNTL, crtc_more_cntl); mdelay( 15);}static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo){ u32 tmp, tmp2; int i,j; /* Reset the PAD_CTLR_STRENGTH & wait for it to be stable */ INREG(PAD_CTLR_STRENGTH); OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~PAD_MANUAL_OVERRIDE); tmp = INREG(PAD_CTLR_STRENGTH); for (i = j = 0; i < 65; ++i) { mdelay(1); tmp2 = INREG(PAD_CTLR_STRENGTH); if (tmp != tmp2) { tmp = tmp2; i = 0; j++; if (j > 10) { printk(KERN_WARNING "radeon: PAD_CTLR_STRENGTH doesn't " "stabilize !\n"); break; } } }}static void radeon_pm_all_ppls_off(struct radeonfb_info *rinfo){ u32 tmp; tmp = INPLL(pllPPLL_CNTL); OUTPLL(pllPPLL_CNTL, tmp | 0x3); tmp = INPLL(pllP2PLL_CNTL); OUTPLL(pllP2PLL_CNTL, tmp | 0x3); tmp = INPLL(pllSPLL_CNTL); OUTPLL(pllSPLL_CNTL, tmp | 0x3); tmp = INPLL(pllMPLL_CNTL); OUTPLL(pllMPLL_CNTL, tmp | 0x3);}static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo){ u32 tmp; /* Switch SPLL to PCI source */ tmp = INPLL(pllSCLK_CNTL); OUTPLL(pllSCLK_CNTL, tmp & ~SCLK_CNTL__SCLK_SRC_SEL_MASK); /* Reconfigure SPLL charge pump, VCO gain, duty cycle */ tmp = INPLL(pllSPLL_CNTL); OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN); radeon_pll_errata_after_index(rinfo); OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); radeon_pll_errata_after_data(rinfo); /* Set SPLL feedback divider */ tmp = INPLL(pllM_SPLL_REF_FB_DIV); tmp = (tmp & 0xff00fffful) | (rinfo->save_regs[77] & 0x00ff0000ul); OUTPLL(pllM_SPLL_REF_FB_DIV, tmp); /* Power up SPLL */ tmp = INPLL(pllSPLL_CNTL); OUTPLL(pllSPLL_CNTL, tmp & ~1); (void)INPLL(pllSPLL_CNTL); mdelay(10); /* Release SPLL reset */ tmp = INPLL(pllSPLL_CNTL); OUTPLL(pllSPLL_CNTL, tmp & ~0x2); (void)INPLL(pllSPLL_CNTL); mdelay(10); /* Select SCLK source */ tmp = INPLL(pllSCLK_CNTL); tmp &= ~SCLK_CNTL__SCLK_SRC_SEL_MASK; tmp |= rinfo->save_regs[3] & SCLK_CNTL__SCLK_SRC_SEL_MASK; OUTPLL(pllSCLK_CNTL, tmp); (void)INPLL(pllSCLK_CNTL); mdelay(10); /* Reconfigure MPLL charge pump, VCO gain, duty cycle */ tmp = INPLL(pllMPLL_CNTL); OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN); radeon_pll_errata_after_index(rinfo); OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); radeon_pll_errata_after_data(rinfo); /* Set MPLL feedback divider */ tmp = INPLL(pllM_SPLL_REF_FB_DIV); tmp = (tmp & 0xffff00fful) | (rinfo->save_regs[77] & 0x0000ff00ul); OUTPLL(pllM_SPLL_REF_FB_DIV, tmp); /* Power up MPLL */ tmp = INPLL(pllMPLL_CNTL); OUTPLL(pllMPLL_CNTL, tmp & ~0x2); (void)INPLL(pllMPLL_CNTL); mdelay(10); /* Un-reset MPLL */ tmp = INPLL(pllMPLL_CNTL); OUTPLL(pllMPLL_CNTL, tmp & ~0x1); (void)INPLL(pllMPLL_CNTL); mdelay(10); /* Select source for MCLK */ tmp = INPLL(pllMCLK_CNTL); tmp |= rinfo->save_regs[2] & 0xffff; OUTPLL(pllMCLK_CNTL, tmp); (void)INPLL(pllMCLK_CNTL); mdelay(10);}static void radeon_pm_m10_disable_spread_spectrum(struct radeonfb_info *rinfo){ u32 r2ec; /* GACK ! I though we didn't have a DDA on Radeon's anymore * here we rewrite with the same value, ... I suppose we clear * some bits that are already clear ? Or maybe this 0x2ec * register is something new ? */ mdelay(20); r2ec = INREG(VGA_DDA_ON_OFF); OUTREG(VGA_DDA_ON_OFF, r2ec); mdelay(1); /* Spread spectrum PLLL off */ OUTPLL(pllSSPLL_CNTL, 0xbf03); /* Spread spectrum disabled */ OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3); /* The trace shows read & rewrite of LVDS_PLL_CNTL here with same * value, not sure what for... */ r2ec |= 0x3f0; OUTREG(VGA_DDA_ON_OFF, r2ec); mdelay(1);}static void radeon_pm_m10_enable_lvds_spread_spectrum(struct radeonfb_info *rinfo){ u32 r2ec, tmp; /* GACK (bis) ! I though we didn't have a DDA on Radeon's anymore * here we rewrite with the same value, ... I suppose we clear/set * some bits that are already clear/set ? */ r2ec = INREG(VGA_DDA_ON_OFF); OUTREG(VGA_DDA_ON_OFF, r2ec); mdelay(1); /* Enable spread spectrum */ OUTPLL(pllSSPLL_CNTL, rinfo->save_regs[43] | 3); mdelay(3); OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44]); OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45]); tmp = INPLL(pllSSPLL_CNTL); OUTPLL(pllSSPLL_CNTL, tmp & ~0x2); mdelay(6); tmp = INPLL(pllSSPLL_CNTL); OUTPLL(pllSSPLL_CNTL, tmp & ~0x1); mdelay(5); OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90]); r2ec |= 8; OUTREG(VGA_DDA_ON_OFF, r2ec); mdelay(20); /* Enable LVDS interface */ tmp = INREG(LVDS_GEN_CNTL); OUTREG(LVDS_GEN_CNTL, tmp | LVDS_EN); /* Enable LVDS_PLL */ tmp = INREG(LVDS_PLL_CNTL); tmp &= ~0x30000; tmp |= 0x10000; OUTREG(LVDS_PLL_CNTL, tmp); OUTPLL(pllSCLK_MORE_CNTL, rinfo->save_regs[34]); OUTPLL(pllSS_TST_CNTL, rinfo->save_regs[91]); /* The trace reads that one here, waiting for something to settle down ? */ INREG(RBBM_STATUS); /* Ugh ? SS_TST_DEC is supposed to be a read register in the * R300 register spec at least... */ tmp = INPLL(pllSS_TST_CNTL); tmp |= 0x00400000; OUTPLL(pllSS_TST_CNTL, tmp);}static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo){ u32 tmp; OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN); radeon_pll_errata_after_index(rinfo); OUTREG8(CLOCK_CNTL_DATA, 0); radeon_pll_errata_after_data(rinfo); tmp = INPLL(pllVCLK_ECP_CNTL); OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80); mdelay(5); tmp = INPLL(pllPPLL_REF_DIV); tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div; OUTPLL(pllPPLL_REF_DIV, tmp); INPLL(pllPPLL_REF_DIV); /* Reconfigure SPLL charge pump, VCO gain, duty cycle, * probably useless since we already did it ... */ tmp = INPLL(pllPPLL_CNTL); OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN); radeon_pll_errata_after_index(rinfo); OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); radeon_pll_errata_after_data(rinfo); /* Restore our "reference" PPLL divider set by firmware * according to proper spread spectrum calculations */ OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]); tmp = INPLL(pllPPLL_CNTL); OUTPLL(pllPPLL_CNTL, tmp & ~0x2); mdelay(5);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -