📄 radeon_pm.c
字号:
/* Force Core Clocks */ sclk_cntl = INPLL( pllSCLK_CNTL); sclk_cntl |= SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT| SCLK_CNTL__VIP_MAX_DYN_STOP_LAT| SCLK_CNTL__RE_MAX_DYN_STOP_LAT| SCLK_CNTL__PB_MAX_DYN_STOP_LAT| SCLK_CNTL__TAM_MAX_DYN_STOP_LAT| SCLK_CNTL__TDM_MAX_DYN_STOP_LAT| SCLK_CNTL__RB_MAX_DYN_STOP_LAT| 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__FORCE_SE| SCLK_CNTL__FORCE_IDCT| SCLK_CNTL__FORCE_VIP| SCLK_CNTL__FORCE_PB| SCLK_CNTL__FORCE_TAM| SCLK_CNTL__FORCE_TDM| SCLK_CNTL__FORCE_RB| SCLK_CNTL__FORCE_TV_SCLK| SCLK_CNTL__FORCE_SUBPIC| SCLK_CNTL__FORCE_OV0; if (rinfo->family <= CHIP_FAMILY_RV280) sclk_cntl |= SCLK_CNTL__FORCE_RE; else sclk_cntl |= SCLK_CNTL__SE_MAX_DYN_STOP_LAT | SCLK_CNTL__E2_MAX_DYN_STOP_LAT | SCLK_CNTL__TV_MAX_DYN_STOP_LAT | SCLK_CNTL__HDP_MAX_DYN_STOP_LAT | SCLK_CNTL__CP_MAX_DYN_STOP_LAT; OUTPLL( pllSCLK_CNTL, sclk_cntl); sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL); sclk_more_cntl |= SCLK_MORE_CNTL__FORCE_DISPREGS | SCLK_MORE_CNTL__FORCE_MC_GUI | SCLK_MORE_CNTL__FORCE_MC_HOST; OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl); mclk_cntl = INPLL( pllMCLK_CNTL); mclk_cntl &= ~( MCLK_CNTL__FORCE_MCLKA | MCLK_CNTL__FORCE_MCLKB | MCLK_CNTL__FORCE_YCLKA | MCLK_CNTL__FORCE_YCLKB | MCLK_CNTL__FORCE_MC ); OUTPLL( pllMCLK_CNTL, mclk_cntl); /* Force Display clocks */ vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL); vclk_ecp_cntl &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb); vclk_ecp_cntl |= VCLK_ECP_CNTL__ECP_FORCE_ON; OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl); pixclks_cntl = INPLL( pllPIXCLKS_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( pllPIXCLKS_CNTL, pixclks_cntl); /* Switch off LVDS interface */ OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BLON | LVDS_EN | LVDS_ON | LVDS_DIGON)); /* Enable System power management */ pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL); pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__SPLL_TURNOFF | PLL_PWRMGT_CNTL__MPLL_TURNOFF| PLL_PWRMGT_CNTL__PPLL_TURNOFF| PLL_PWRMGT_CNTL__P2PLL_TURNOFF| PLL_PWRMGT_CNTL__TVPLL_TURNOFF; OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl); clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL); clk_pwrmgt_cntl &= ~( CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__MCLK_TURNOFF| CLK_PWRMGT_CNTL__SCLK_TURNOFF| CLK_PWRMGT_CNTL__PCLK_TURNOFF| CLK_PWRMGT_CNTL__P2CLK_TURNOFF| CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN| CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE| CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK| CLK_PWRMGT_CNTL__CG_NO1_DEBUG_MASK ); clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN | CLK_PWRMGT_CNTL__DISP_PM; OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl); clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND; /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; OUTPLL( pllMCLK_MISC, tmp); /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset * and radeon chip dependent. Thus we only enable it on Mac for * now (until we get more info on how to compute the correct * value for various X86 bridges). */#ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { /* AGP PLL control */ if (rinfo->family <= CHIP_FAMILY_RV280) { OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX } else { OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); } }#endif OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); clk_pin_cntl &= ~CLK_PIN_CNTL__CG_CLK_TO_OUTPIN; clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb; OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); /* Solano2M */ OUTREG(AGP_CNTL, (INREG(AGP_CNTL) & ~(AGP_CNTL__MAX_IDLE_CLK_MASK)) | (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT)); /* ACPI mode */ /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL; OUTPLL( pllPLL_PWRMGT_CNTL, tmp); disp_mis_cntl = INREG(DISP_MISC_CNTL); disp_mis_cntl &= ~( DISP_MISC_CNTL__SOFT_RESET_GRPH_PP | DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP | DISP_MISC_CNTL__SOFT_RESET_OV0_PP | DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK| DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK| DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK| DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP| DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK| DISP_MISC_CNTL__SOFT_RESET_LVDS| DISP_MISC_CNTL__SOFT_RESET_TMDS| DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS| DISP_MISC_CNTL__SOFT_RESET_TV); OUTREG(DISP_MISC_CNTL, disp_mis_cntl); disp_pwr_man = INREG(DISP_PWR_MAN); disp_pwr_man &= ~( DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN | DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK| DISP_PWR_MAN__DISP_D3_RST| DISP_PWR_MAN__DISP_D3_REG_RST ); disp_pwr_man |= DISP_PWR_MAN__DISP_D3_GRPH_RST| DISP_PWR_MAN__DISP_D3_SUBPIC_RST| DISP_PWR_MAN__DISP_D3_OV0_RST| DISP_PWR_MAN__DISP_D1D2_GRPH_RST| DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST| DISP_PWR_MAN__DISP_D1D2_OV0_RST| DISP_PWR_MAN__DIG_TMDS_ENABLE_RST| DISP_PWR_MAN__TV_ENABLE_RST| // DISP_PWR_MAN__AUTO_PWRUP_EN| 0; OUTREG(DISP_PWR_MAN, disp_pwr_man); clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL); pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL) ; clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); disp_pwr_man = INREG(DISP_PWR_MAN); /* D2 */ clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__DISP_PM; pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__MOBILE_SU | PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK; clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb; disp_pwr_man &= ~(DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK); OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl); OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl); OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); OUTREG(DISP_PWR_MAN, disp_pwr_man); /* disable display request & disable display */ OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN) | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B); OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN) | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B); mdelay(17); }static void radeon_pm_yclk_mclk_sync(struct radeonfb_info *rinfo){ u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1; mc_chp_io_cntl_a1 = INMC( rinfo, ixMC_CHP_IO_CNTL_A1) & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK; mc_chp_io_cntl_b1 = INMC( rinfo, ixMC_CHP_IO_CNTL_B1) & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK; OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT)); OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT)); OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1); OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1); mdelay( 1);}static void radeon_pm_yclk_mclk_sync_m10(struct radeonfb_info *rinfo){ u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1; mc_chp_io_cntl_a1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1) & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK; mc_chp_io_cntl_b1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1) & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK; OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT)); OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT)); OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, mc_chp_io_cntl_a1); OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, mc_chp_io_cntl_b1); mdelay( 1);}static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value, u8 delay_required){ u32 mem_sdram_mode; mem_sdram_mode = INREG( MEM_SDRAM_MODE_REG); mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK; mem_sdram_mode |= (value<<MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT) | MEM_SDRAM_MODE_REG__MEM_CFG_TYPE; OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); if (delay_required >= 2) mdelay(1); mem_sdram_mode |= MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET; OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); if (delay_required >= 2) mdelay(1); mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET; OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); if (delay_required >= 2) mdelay(1); if (delay_required) { do { if (delay_required >= 2) mdelay(1); } while ((INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A | MC_STATUS__MEM_PWRUP_COMPL_B)) == 0); }}static void radeon_pm_m10_program_mode_wait(struct radeonfb_info *rinfo){ int cnt; for (cnt = 0; cnt < 100; ++cnt) { mdelay(1); if (INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A | MC_STATUS__MEM_PWRUP_COMPL_B)) break; }}static void radeon_pm_enable_dll(struct radeonfb_info *rinfo){ #define DLL_RESET_DELAY 5#define DLL_SLEEP_DELAY 1 u32 cko = INPLL(pllMDLL_CKO) | MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOA_RESET; u32 cka = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET; u32 ckb = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET; /* Setting up the DLL range for write */ OUTPLL(pllMDLL_CKO, cko); OUTPLL(pllMDLL_RDCKA, cka); OUTPLL(pllMDLL_RDCKB, ckb); mdelay(DLL_RESET_DELAY*2); cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP); OUTPLL(pllMDLL_CKO, cko); mdelay(DLL_SLEEP_DELAY); cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET); OUTPLL(pllMDLL_CKO, cko); mdelay(DLL_RESET_DELAY); cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP); OUTPLL(pllMDLL_RDCKA, cka); mdelay(DLL_SLEEP_DELAY); cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET); OUTPLL(pllMDLL_RDCKA, cka); mdelay(DLL_RESET_DELAY); ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP); OUTPLL(pllMDLL_RDCKB, ckb); mdelay(DLL_SLEEP_DELAY); ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET); OUTPLL(pllMDLL_RDCKB, ckb); mdelay(DLL_RESET_DELAY);#undef DLL_RESET_DELAY#undef DLL_SLEEP_DELAY}static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo){ u32 dll_value; u32 dll_sleep_mask = 0; u32 dll_reset_mask = 0; u32 mc;#define DLL_RESET_DELAY 5#define DLL_SLEEP_DELAY 1 OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]); mc = INREG(MC_CNTL); /* Check which channels are enabled */ switch (mc & 0x3) { case 1: if (mc & 0x4) break; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET; case 0: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET; } switch (mc & 0x3) { case 1: if (!(mc & 0x4)) break; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET; dll_sleep_mask |= MDLL_R300_RDCK__MRDCKC_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKC_RESET; } dll_value = INPLL(pllMDLL_RDCKA); /* Power Up */ dll_value &= ~(dll_sleep_mask); OUTPLL(pllMDLL_RDCKA, dll_value); mdelay( DLL_SLEEP_DELAY); dll_value &= ~(dll_reset_mask); OUTPLL(pllMDLL_RDCKA, dll_value); mdelay( DLL_RESET_DELAY); #undef DLL_RESET_DELAY #undef DLL_SLEEP_DELAY}static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo){ u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl, fp_gen_cntl, fp2_gen_cntl; crtcGenCntl = INREG( CRTC_GEN_CNTL); crtcGenCntl2 = INREG( CRTC2_GEN_CNTL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -