static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo) { /* Set v2clk to 65MHz */ OUTPLL(pllPIXCLKS_CNTL, INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK); OUTPLL(pllP2PLL_REF_DIV, 0x0000000c); OUTPLL(pllP2PLL_CNTL, 0x0000bf00); OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W); OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP); mdelay(1); OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET); mdelay( 1); OUTPLL(pllPIXCLKS_CNTL, (INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK) | (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT)); mdelay( 1); }
static void radeon_pm_save_regs(struct radeonfb_info *rinfo) { rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL); rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL); rinfo->save_regs[2] = INPLL(MCLK_CNTL); rinfo->save_regs[3] = INPLL(SCLK_CNTL); rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL); rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL); rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL); rinfo->save_regs[7] = INPLL(MCLK_MISC); rinfo->save_regs[8] = INPLL(P2PLL_CNTL); rinfo->save_regs[9] = INREG(DISP_MISC_CNTL); rinfo->save_regs[10] = INREG(DISP_PWR_MAN); rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL); rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL); rinfo->save_regs[13] = INREG(TV_DAC_CNTL); rinfo->save_regs[14] = INREG(BUS_CNTL1); rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL); rinfo->save_regs[16] = INREG(AGP_CNTL); rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000; rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000; rinfo->save_regs[19] = INREG(GPIOPAD_A); rinfo->save_regs[20] = INREG(GPIOPAD_EN); rinfo->save_regs[21] = INREG(GPIOPAD_MASK); rinfo->save_regs[22] = INREG(ZV_LCDPAD_A); rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN); rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK); rinfo->save_regs[25] = INREG(GPIO_VGA_DDC); rinfo->save_regs[26] = INREG(GPIO_DVI_DDC); rinfo->save_regs[27] = INREG(GPIO_MONID); rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC); rinfo->save_regs[29] = INREG(SURFACE_CNTL); rinfo->save_regs[30] = INREG(MC_FB_LOCATION); rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR); rinfo->save_regs[32] = INREG(MC_AGP_LOCATION); rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR); }
static void radeon_pm_low_current(struct radeonfb_info *rinfo) { u32 reg; reg = INREG(BUS_CNTL1); reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK; reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT); OUTREG(BUS_CNTL1, reg); reg = INPLL(PLL_PWRMGT_CNTL); reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF | PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF; reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK; reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU; OUTPLL(PLL_PWRMGT_CNTL, reg); reg = INREG(TV_DAC_CNTL); reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK); reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD | TV_DAC_CNTL_BDACPD | (8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT); OUTREG(TV_DAC_CNTL, reg); reg = INREG(TMDS_TRANSMITTER_CNTL); reg &= ~(TMDS_PLL_EN | TMDS_PLLRST); OUTREG(TMDS_TRANSMITTER_CNTL, reg); reg = INREG(DAC_CNTL); reg &= ~DAC_CMP_EN; OUTREG(DAC_CNTL, reg); reg = INREG(DAC_CNTL2); reg &= ~DAC2_CMP_EN; OUTREG(DAC_CNTL2, reg); reg = INREG(TV_DAC_CNTL); reg &= ~TV_DAC_CNTL_DETECT; OUTREG(TV_DAC_CNTL, reg); }
static int radeon_bl_update_status(struct backlight_device *bd) { struct radeon_bl_privdata *pdata = bl_get_data(bd); struct radeonfb_info *rinfo = pdata->rinfo; u32 lvds_gen_cntl, tmpPixclksCntl; int level; if (rinfo->mon1_type != MT_LCD) return 0; /* We turn off the LCD completely instead of just dimming the * backlight. This provides some greater power saving and the display * is useless without backlight anyway. */ if (bd->props.power != FB_BLANK_UNBLANK || bd->props.fb_blank != FB_BLANK_UNBLANK) level = 0; else level = bd->props.brightness; del_timer_sync(&rinfo->lvds_timer); radeon_engine_idle(); lvds_gen_cntl = INREG(LVDS_GEN_CNTL); if (level > 0) { lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); lvds_gen_cntl |= LVDS_BLON | LVDS_EN; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, level) << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= LVDS_ON; lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; mod_timer(&rinfo->lvds_timer, jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); } else { lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, level) << LVDS_BL_MOD_LEVEL_SHIFT); OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); } rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl & LVDS_STATE_MASK; } else { /* Asic bug, when turning off LVDS_ON, we have to make sure RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off */ tmpPixclksCntl = INPLL(PIXCLKS_CNTL); if (rinfo->is_mobility || rinfo->is_IGP) OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= LVDS_DISPLAY_DIS; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); udelay(100); lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~(LVDS_DIGON); rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; mod_timer(&rinfo->lvds_timer, jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); if (rinfo->is_mobility || rinfo->is_IGP) OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); } rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); return 0; }
static int radeon_bl_update_status(struct backlight_device *bd) { struct radeon_bl_privdata *pdata = bl_get_data(bd); struct radeonfb_info *rinfo = pdata->rinfo; u32 lvds_gen_cntl, tmpPixclksCntl; int level; if (rinfo->mon1_type != MT_LCD) return 0; /* */ if (bd->props.power != FB_BLANK_UNBLANK || bd->props.fb_blank != FB_BLANK_UNBLANK) level = 0; else level = bd->props.brightness; del_timer_sync(&rinfo->lvds_timer); radeon_engine_idle(); lvds_gen_cntl = INREG(LVDS_GEN_CNTL); if (level > 0) { lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); lvds_gen_cntl |= LVDS_BLON | LVDS_EN; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, level) << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= LVDS_ON; lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; mod_timer(&rinfo->lvds_timer, jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); } else { lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, level) << LVDS_BL_MOD_LEVEL_SHIFT); OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); } rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl & LVDS_STATE_MASK; } else { /* */ tmpPixclksCntl = INPLL(PIXCLKS_CNTL); if (rinfo->is_mobility || rinfo->is_IGP) OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) << LVDS_BL_MOD_LEVEL_SHIFT); lvds_gen_cntl |= LVDS_DISPLAY_DIS; OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); udelay(100); lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); lvds_gen_cntl &= ~(LVDS_DIGON); rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; mod_timer(&rinfo->lvds_timer, jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); if (rinfo->is_mobility || rinfo->is_IGP) OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); } rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); return 0; }
static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { u16 pwr_cmd; if (!rinfo->pm_reg) return; /* Set the chip into appropriate suspend mode (we use D2, * D3 would require a compete re-initialization of the chip, * including PCI config registers, clocks, AGP conf, ...) */ if (suspend) { printk(KERN_DEBUG "radeonfb: switching to D2 state...\n"); /* Disable dynamic power management of clocks for the * duration of the suspend/resume process */ radeon_pm_disable_dynamic_mode(rinfo); /* Save some registers */ radeon_pm_save_regs(rinfo); /* Prepare mobility chips for suspend. Only do that on <= RV250 chips that * have been tested */ if (rinfo->is_mobility && rinfo->family <= CHIP_FAMILY_RV250) { /* Program V2CLK */ radeon_pm_program_v2clk(rinfo); /* Disable IO PADs */ radeon_pm_disable_iopad(rinfo); /* Set low current */ radeon_pm_low_current(rinfo); /* Prepare chip for power management */ radeon_pm_setup_for_suspend(rinfo); /* Reset the MDLL */ OUTPLL( pllMDLL_CKO, INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET); } /* Switch PCI power managment to D2. */ for (;;) { pci_read_config_word( rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, &pwr_cmd); if (pwr_cmd & 2) break; pci_write_config_word( rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); mdelay(500); } } else { printk(KERN_DEBUG "radeonfb: switching to D0 state...\n"); /* Switch back PCI powermanagment to D0 */ mdelay(200); pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); mdelay(500); /* Reset the SDRAM controller */ radeon_pm_full_reset_sdram(rinfo); /* Restore some registers */ radeon_pm_restore_regs(rinfo); radeon_pm_enable_dynamic_mode(rinfo); } }
static void radeon_pm_enable_dll(struct radeonfb_info *rinfo) { #define DLL_RESET_DELAY 5 #define DLL_SLEEP_DELAY 1 u32 DLL_CKO_Value = INPLL(pllMDLL_CKO) | MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOA_RESET; u32 DLL_CKA_Value = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET; u32 DLL_CKB_Value = 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, DLL_CKO_Value); OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value); OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value); mdelay( DLL_RESET_DELAY); /* Channel A */ /* Power Up */ DLL_CKO_Value &= ~(MDLL_CKO__MCKOA_SLEEP ); OUTPLL(pllMDLL_CKO, DLL_CKO_Value); mdelay( DLL_SLEEP_DELAY); DLL_CKO_Value &= ~(MDLL_CKO__MCKOA_RESET ); OUTPLL(pllMDLL_CKO, DLL_CKO_Value); mdelay( DLL_RESET_DELAY); /* Power Up */ DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA0_SLEEP ); OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value); mdelay( DLL_SLEEP_DELAY); DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA0_RESET ); OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value); mdelay( DLL_RESET_DELAY); /* Power Up */ DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA1_SLEEP); OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value); mdelay( DLL_SLEEP_DELAY); DLL_CKA_Value &= ~(MDLL_RDCKA__MRDCKA1_RESET); OUTPLL(pllMDLL_RDCKA, DLL_CKA_Value); mdelay( DLL_RESET_DELAY); /* Channel B */ /* Power Up */ DLL_CKO_Value &= ~(MDLL_CKO__MCKOB_SLEEP ); OUTPLL(pllMDLL_CKO, DLL_CKO_Value); mdelay( DLL_SLEEP_DELAY); DLL_CKO_Value &= ~(MDLL_CKO__MCKOB_RESET ); OUTPLL(pllMDLL_CKO, DLL_CKO_Value); mdelay( DLL_RESET_DELAY); /* Power Up */ DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB0_SLEEP); OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value); mdelay( DLL_SLEEP_DELAY); DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB0_RESET); OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value); mdelay( DLL_RESET_DELAY); /* Power Up */ DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB1_SLEEP); OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value); mdelay( DLL_SLEEP_DELAY); DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB1_RESET); OUTPLL(pllMDLL_RDCKB, DLL_CKB_Value); mdelay( DLL_RESET_DELAY); #undef DLL_RESET_DELAY #undef DLL_SLEEP_DELAY }
static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo) { u32 sclk_cntl, mclk_cntl, sclk_more_cntl; u32 pll_pwrmgt_cntl; u32 clk_pwrmgt_cntl; u32 clk_pin_cntl; u32 vclk_ecp_cntl; u32 pixclks_cntl; u32 disp_mis_cntl; u32 disp_pwr_man; /* Force Core Clocks */ sclk_cntl = INPLL( pllSCLK_CNTL_M6); sclk_cntl |= SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__VIP_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__RE_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__PB_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__TAM_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__TDM_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__RB_MAX_DYN_STOP_LAT| SCLK_CNTL_M6__FORCE_DISP2| SCLK_CNTL_M6__FORCE_CP| SCLK_CNTL_M6__FORCE_HDP| SCLK_CNTL_M6__FORCE_DISP1| 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( pllSCLK_CNTL_M6, 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_M6); mclk_cntl &= ~( MCLK_CNTL_M6__FORCE_MCLKA | MCLK_CNTL_M6__FORCE_MCLKB | MCLK_CNTL_M6__FORCE_YCLKA | MCLK_CNTL_M6__FORCE_YCLKB | MCLK_CNTL_M6__FORCE_MC ); OUTPLL( pllMCLK_CNTL_M6, 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); /* 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_M6); clk_pwrmgt_cntl &= ~( CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF| CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF| CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF| CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF| CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF| CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF| CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN| CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE| CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK| CLK_PWRMGT_CNTL_M6__CG_NO1_DEBUG_MASK ); clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN | CLK_PWRMGT_CNTL_M6__DISP_PM; OUTPLL( pllCLK_PWRMGT_CNTL_M6, clk_pwrmgt_cntl); clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND; OUTPLL( pllMCLK_MISC, INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND); /* AGP PLL control */ 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 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 */ OUTPLL( pllPLL_PWRMGT_CNTL, INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL); 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_M6); 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_M6__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_M6, 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); }
void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) { u32 sclk_cntl; u32 mclk_cntl; u32 sclk_more_cntl; u32 vclk_ecp_cntl; u32 pixclks_cntl; /* Mobility chips only, untested on M9+/M10/11 */ if (!rinfo->is_mobility) return; if (rinfo->family > CHIP_FAMILY_RV250) return; /* Force Core Clocks */ sclk_cntl = INPLL( pllSCLK_CNTL_M6); 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( pllSCLK_CNTL_M6, 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); /* 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); 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); /* Force Memory Clocks */ mclk_cntl = INPLL( pllMCLK_CNTL_M6); mclk_cntl &= ~( MCLK_CNTL_M6__FORCE_MCLKA | MCLK_CNTL_M6__FORCE_MCLKB | MCLK_CNTL_M6__FORCE_YCLKA | MCLK_CNTL_M6__FORCE_YCLKB ); OUTPLL( pllMCLK_CNTL_M6, mclk_cntl); }
void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) { u32 clk_pwrmgt_cntl; u32 sclk_cntl; u32 sclk_more_cntl; u32 clk_pin_cntl; u32 pixclks_cntl; u32 vclk_ecp_cntl; u32 mclk_cntl; u32 mclk_misc; /* Mobility chips only, untested on M9+/M10/11 */ if (!rinfo->is_mobility) return; if (rinfo->family > CHIP_FAMILY_RV250) return; /* Set Latencies */ clk_pwrmgt_cntl = INPLL( pllCLK_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<<CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT__SHIFT) | (0<<CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT__SHIFT)| (0<<CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE__SHIFT); OUTPLL( pllCLK_PWRMGT_CNTL_M6, clk_pwrmgt_cntl); clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); clk_pin_cntl |= CLK_PIN_CNTL__SCLK_DYN_START_CNTL; OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); /* Enable Dyanmic mode for SCLK */ sclk_cntl = INPLL( pllSCLK_CNTL_M6); sclk_cntl &= SCLK_CNTL_M6__SCLK_SRC_SEL_MASK; sclk_cntl |= SCLK_CNTL_M6__FORCE_VIP; OUTPLL( pllSCLK_CNTL_M6, sclk_cntl); sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL); sclk_more_cntl &= ~(SCLK_MORE_CNTL__FORCE_DISPREGS); OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl); /* Enable Dynamic mode for PIXCLK & PIX2CLK */ pixclks_cntl = INPLL( pllPIXCLKS_CNTL); pixclks_cntl|= 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, pixclks_cntl); vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL); vclk_ecp_cntl|= VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb; OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl); /* Enable Dynamic mode for MCLK */ mclk_cntl = INPLL( pllMCLK_CNTL_M6); mclk_cntl |= MCLK_CNTL_M6__FORCE_MCLKA| MCLK_CNTL_M6__FORCE_MCLKB| MCLK_CNTL_M6__FORCE_YCLKA| MCLK_CNTL_M6__FORCE_YCLKB; OUTPLL( pllMCLK_CNTL_M6, mclk_cntl); mclk_misc = INPLL(pllMCLK_MISC); mclk_misc |= 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, mclk_misc); }