aboutsummaryrefslogtreecommitdiff
path: root/drivers/video/aty/radeon_pm.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/video/aty/radeon_pm.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/video/aty/radeon_pm.c')
-rw-r--r--drivers/video/aty/radeon_pm.c2801
1 files changed, 2801 insertions, 0 deletions
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
new file mode 100644
index 00000000000..23c677e5093
--- /dev/null
+++ b/drivers/video/aty/radeon_pm.c
@@ -0,0 +1,2801 @@
+/*
+ * drivers/video/aty/radeon_pm.c
+ *
+ * Copyright 2003,2004 Ben. Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright 2004 Paul Mackerras <paulus@samba.org>
+ *
+ * This is the power management code for ATI radeon chipsets. It contains
+ * some dynamic clock PM enable/disable code similar to what X.org does,
+ * some D2-state (APM-style) sleep/wakeup code for use on some PowerMacs,
+ * and the necessary bits to re-initialize from scratch a few chips found
+ * on PowerMacs as well. The later could be extended to more platforms
+ * provided the memory controller configuration code be made more generic,
+ * and you can get the proper mode register commands for your RAMs.
+ * Those things may be found in the BIOS image...
+ */
+
+#include "radeonfb.h"
+
+#include <linux/console.h>
+#include <linux/agp_backend.h>
+
+#ifdef CONFIG_PPC_PMAC
+#include <asm/processor.h>
+#include <asm/prom.h>
+#include <asm/pmac_feature.h>
+#endif
+
+#include "ati_ids.h"
+
+static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
+{
+ u32 tmp;
+
+ /* RV100 */
+ if ((rinfo->family == CHIP_FAMILY_RV100) && (!rinfo->is_mobility)) {
+ if (rinfo->has_CRTC2) {
+ tmp = INPLL(pllSCLK_CNTL);
+ tmp &= ~SCLK_CNTL__DYN_STOP_LAT_MASK;
+ tmp |= SCLK_CNTL__CP_MAX_DYN_STOP_LAT | SCLK_CNTL__FORCEON_MASK;
+ OUTPLL(pllSCLK_CNTL, tmp);
+ }
+ tmp = INPLL(pllMCLK_CNTL);
+ tmp |= (MCLK_CNTL__FORCE_MCLKA |
+ MCLK_CNTL__FORCE_MCLKB |
+ MCLK_CNTL__FORCE_YCLKA |
+ MCLK_CNTL__FORCE_YCLKB |
+ MCLK_CNTL__FORCE_AIC |
+ MCLK_CNTL__FORCE_MC);
+ OUTPLL(pllMCLK_CNTL, tmp);
+ return;
+ }
+ /* R100 */
+ if (!rinfo->has_CRTC2) {
+ tmp = INPLL(pllSCLK_CNTL);
+ tmp |= (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_RE | SCLK_CNTL__FORCE_PB |
+ SCLK_CNTL__FORCE_TAM | SCLK_CNTL__FORCE_TDM |
+ SCLK_CNTL__FORCE_RB);
+ OUTPLL(pllSCLK_CNTL, tmp);
+ return;
+ }
+ /* RV350 (M10) */
+ if (rinfo->family == CHIP_FAMILY_RV350) {
+ /* for RV350/M10, no delays are required. */
+ tmp = INPLL(pllSCLK_CNTL2);
+ tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
+ SCLK_CNTL2__R300_FORCE_GA |
+ SCLK_CNTL2__R300_FORCE_CBA);
+ 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);
+ OUTPLL(pllSCLK_CNTL, tmp);
+
+ tmp = INPLL(pllSCLK_MORE_CNTL);
+ tmp |= (SCLK_MORE_CNTL__FORCE_DISPREGS | SCLK_MORE_CNTL__FORCE_MC_GUI |
+ SCLK_MORE_CNTL__FORCE_MC_HOST);
+ OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+ tmp = INPLL(pllMCLK_CNTL);
+ tmp |= (MCLK_CNTL__FORCE_MCLKA |
+ MCLK_CNTL__FORCE_MCLKB |
+ MCLK_CNTL__FORCE_YCLKA |
+ MCLK_CNTL__FORCE_YCLKB |
+ MCLK_CNTL__FORCE_MC);
+ OUTPLL(pllMCLK_CNTL, tmp);
+
+ tmp = INPLL(pllVCLK_ECP_CNTL);
+ tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+ VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb |
+ VCLK_ECP_CNTL__R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
+ 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_ALWAYS_ONb |
+ PIXCLKS_CNTL__R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
+ OUTPLL(pllPIXCLKS_CNTL, tmp);
+
+ return;
+ }
+
+ /* Default */
+
+ /* Force Core Clocks */
+ tmp = INPLL(pllSCLK_CNTL);
+ tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_E2);
+
+ /* XFree doesn't do that case, but we had this code from Apple and it
+ * seem necessary for proper suspend/resume operations
+ */
+ if (rinfo->is_mobility) {
+ tmp |= SCLK_CNTL__FORCE_HDP|
+ SCLK_CNTL__FORCE_DISP1|
+ SCLK_CNTL__FORCE_DISP2|
+ SCLK_CNTL__FORCE_TOP|
+ SCLK_CNTL__FORCE_SE|
+ SCLK_CNTL__FORCE_IDCT|
+ SCLK_CNTL__FORCE_VIP|
+ SCLK_CNTL__FORCE_PB|
+ SCLK_CNTL__FORCE_RE|
+ 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;
+ }
+ else if (rinfo->family == CHIP_FAMILY_R300 ||
+ rinfo->family == CHIP_FAMILY_R350) {
+ tmp |= SCLK_CNTL__FORCE_HDP |
+ SCLK_CNTL__FORCE_DISP1 |
+ SCLK_CNTL__FORCE_DISP2 |
+ SCLK_CNTL__FORCE_TOP |
+ SCLK_CNTL__FORCE_IDCT |
+ SCLK_CNTL__FORCE_VIP;
+ }
+ OUTPLL(pllSCLK_CNTL, tmp);
+ radeon_msleep(16);
+
+ if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+ tmp = INPLL(pllSCLK_CNTL2);
+ tmp |= SCLK_CNTL2__R300_FORCE_TCL |
+ SCLK_CNTL2__R300_FORCE_GA |
+ SCLK_CNTL2__R300_FORCE_CBA;
+ OUTPLL(pllSCLK_CNTL2, tmp);
+ radeon_msleep(16);
+ }
+
+ tmp = INPLL(pllCLK_PIN_CNTL);
+ tmp &= ~CLK_PIN_CNTL__SCLK_DYN_START_CNTL;
+ OUTPLL(pllCLK_PIN_CNTL, tmp);
+ radeon_msleep(15);
+
+ if (rinfo->is_IGP) {
+ /* Weird ... X is _un_ forcing clocks here, I think it's
+ * doing backward. Imitate it for now...
+ */
+ tmp = INPLL(pllMCLK_CNTL);
+ tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
+ MCLK_CNTL__FORCE_YCLKA);
+ OUTPLL(pllMCLK_CNTL, tmp);
+ radeon_msleep(16);
+ }
+ /* Hrm... same shit, X doesn't do that but I have to */
+ else 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(16);
+
+ 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);
+ }
+
+ if (rinfo->is_mobility) {
+ tmp = INPLL(pllSCLK_MORE_CNTL);
+ tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS|
+ SCLK_MORE_CNTL__FORCE_MC_GUI|
+ SCLK_MORE_CNTL__FORCE_MC_HOST;
+ OUTPLL(pllSCLK_MORE_CNTL, tmp);
+ radeon_msleep(16);
+ }
+
+ tmp = INPLL(pllPIXCLKS_CNTL);
+ tmp &= ~(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, tmp);
+ radeon_msleep(16);
+
+ tmp = INPLL( pllVCLK_ECP_CNTL);
+ tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
+ VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb);
+ OUTPLL( pllVCLK_ECP_CNTL, tmp);
+ radeon_msleep(16);
+}
+
+static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
+{
+ u32 tmp;
+
+ /* R100 */
+ if (!rinfo->has_CRTC2) {
+ tmp = INPLL(pllSCLK_CNTL);
+
+ if ((INREG(CONFIG_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 */
+ 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_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(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
+ ((rinfo->family == CHIP_FAMILY_RV100) &&
+ ((INREG(CONFIG_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(CONFIG_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(CONFIG_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_OF
+ 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_OF */
+}
+
+#ifdef CONFIG_PM
+
+static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value)
+{
+ OUTREG( MC_IND_INDEX, indx | MC_IND_INDEX__MC_IND_WR_EN);
+ OUTREG( MC_IND_DATA, value);
+}
+
+static u32 INMC(struct radeonfb_info *rinfo, u8 indx)
+{
+ OUTREG( MC_IND_INDEX, indx);
+ return INREG( MC_IND_DATA);
+}
+
+static void radeon_pm_save_regs(struct radeonfb_info *rinfo, int saving_for_d3)
+{
+ 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[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);
+
+ rinfo->save_regs[34] = INPLL(SCLK_MORE_CNTL);
+ rinfo->save_regs[35] = INREG(MEM_SDRAM_MODE_REG);
+ rinfo->save_regs[36] = INREG(BUS_CNTL);
+ rinfo->save_regs[39] = INREG(RBBM_CNTL);
+ rinfo->save_regs[40] = INREG(DAC_CNTL);
+ rinfo->save_regs[41] = INREG(HOST_PATH_CNTL);
+ rinfo->save_regs[37] = INREG(MPP_TB_CONFIG);
+ rinfo->save_regs[38] = INREG(FCP_CNTL);
+
+ if (rinfo->is_mobility) {
+ rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL);
+ rinfo->save_regs[43] = INPLL(pllSSPLL_CNTL);
+ rinfo->save_regs[44] = INPLL(pllSSPLL_REF_DIV);
+ rinfo->save_regs[45] = INPLL(pllSSPLL_DIV_0);
+ rinfo->save_regs[90] = INPLL(pllSS_INT_CNTL);
+ rinfo->save_regs[91] = INPLL(pllSS_TST_CNTL);
+ rinfo->save_regs[81] = INREG(LVDS_GEN_CNTL);
+ }
+
+ if (rinfo->family >= CHIP_FAMILY_RV200) {
+ rinfo->save_regs[42] = INREG(MEM_REFRESH_CNTL);
+ rinfo->save_regs[46] = INREG(MC_CNTL);
+ rinfo->save_regs[47] = INREG(MC_INIT_GFX_LAT_TIMER);
+ rinfo->save_regs[48] = INREG(MC_INIT_MISC_LAT_TIMER);
+ rinfo->save_regs[49] = INREG(MC_TIMING_CNTL);
+ rinfo->save_regs[50] = INREG(MC_READ_CNTL_AB);
+ rinfo->save_regs[51] = INREG(MC_IOPAD_CNTL);
+ rinfo->save_regs[52] = INREG(MC_CHIP_IO_OE_CNTL_AB);
+ rinfo->save_regs[53] = INREG(MC_DEBUG);
+ }
+ rinfo->save_regs[54] = INREG(PAMAC0_DLY_CNTL);
+ rinfo->save_regs[55] = INREG(PAMAC1_DLY_CNTL);
+ rinfo->save_regs[56] = INREG(PAD_CTLR_MISC);
+ rinfo->save_regs[57] = INREG(FW_CNTL);
+
+ if (rinfo->family >= CHIP_FAMILY_R300) {
+ rinfo->save_regs[58] = INMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER);
+ rinfo->save_regs[59] = INMC(rinfo, ixR300_MC_IMP_CNTL);
+ rinfo->save_regs[60] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0);
+ rinfo->save_regs[61] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1);
+ rinfo->save_regs[62] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0);
+ rinfo->save_regs[63] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1);
+ rinfo->save_regs[64] = INMC(rinfo, ixR300_MC_BIST_CNTL_3);
+ rinfo->save_regs[65] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0);
+ rinfo->save_regs[66] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1);
+ rinfo->save_regs[67] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0);
+ rinfo->save_regs[68] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1);
+ rinfo->save_regs[69] = INMC(rinfo, ixR300_MC_DEBUG_CNTL);
+ rinfo->save_regs[70] = INMC(rinfo, ixR300_MC_DLL_CNTL);
+ rinfo->save_regs[71] = INMC(rinfo, ixR300_MC_IMP_CNTL_0);
+ rinfo->save_regs[72] = INMC(rinfo, ixR300_MC_ELPIDA_CNTL);
+ rinfo->save_regs[96] = INMC(rinfo, ixR300_MC_READ_CNTL_CD);
+ } else {
+ rinfo->save_regs[59] = INMC(rinfo, ixMC_IMP_CNTL);
+ rinfo->save_regs[65] = INMC(rinfo, ixMC_CHP_IO_CNTL_A0);
+ rinfo->save_regs[66] = INMC(rinfo, ixMC_CHP_IO_CNTL_A1);
+ rinfo->save_regs[67] = INMC(rinfo, ixMC_CHP_IO_CNTL_B0);
+ rinfo->save_regs[68] = INMC(rinfo, ixMC_CHP_IO_CNTL_B1);
+ rinfo->save_regs[71] = INMC(rinfo, ixMC_IMP_CNTL_0);
+ }
+
+ rinfo->save_regs[73] = INPLL(pllMPLL_CNTL);
+ rinfo->save_regs[74] = INPLL(pllSPLL_CNTL);
+ rinfo->save_regs[75] = INPLL(pllMPLL_AUX_CNTL);
+ rinfo->save_regs[76] = INPLL(pllSPLL_AUX_CNTL);
+ rinfo->save_regs[77] = INPLL(pllM_SPLL_REF_FB_DIV);
+ rinfo->save_regs[78] = INPLL(pllAGP_PLL_CNTL);
+ rinfo->save_regs[79] = INREG(PAMAC2_DLY_CNTL);
+
+ rinfo->save_regs[80] = INREG(OV0_BASE_ADDR);
+ rinfo->save_regs[82] = INREG(FP_GEN_CNTL);
+ rinfo->save_regs[83] = INREG(FP2_GEN_CNTL);
+ rinfo->save_regs[84] = INREG(TMDS_CNTL);
+ rinfo->save_regs[85] = INREG(TMDS_TRANSMITTER_CNTL);
+ rinfo->save_regs[86] = INREG(DISP_OUTPUT_CNTL);
+ rinfo->save_regs[87] = INREG(DISP_HW_DEBUG);
+ rinfo->save_regs[88] = INREG(TV_MASTER_CNTL);
+ rinfo->save_regs[89] = INPLL(pllP2PLL_REF_DIV);
+ rinfo->save_regs[92] = INPLL(pllPPLL_DIV_0);
+ rinfo->save_regs[93] = INPLL(pllPPLL_CNTL);
+ rinfo->save_regs[94] = INREG(GRPH_BUFFER_CNTL);
+ rinfo->save_regs[95] = INREG(GRPH2_BUFFER_CNTL);
+ rinfo->save_regs[96] = INREG(HDP_DEBUG);
+ rinfo->save_regs[97] = INPLL(pllMDLL_CKO);
+ rinfo->save_regs[98] = INPLL(pllMDLL_RDCKA);
+ rinfo->save_regs[99] = INPLL(pllMDLL_RDCKB);
+}
+
+static void radeon_pm_restore_regs(struct radeonfb_info *rinfo)
+{
+ OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */
+
+ OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+ OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
+ OUTPLL(MCLK_CNTL, rinfo->save_regs[2]);
+ OUTPLL(SCLK_CNTL, rinfo->save_regs[3]);
+ OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
+ OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]);
+ OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]);
+ OUTPLL(MCLK_MISC, rinfo->save_regs[7]);
+ if (rinfo->family == CHIP_FAMILY_RV350)
+ OUTPLL(SCLK_MORE_CNTL, rinfo->save_regs[34]);
+
+ OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+ OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+ OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+ OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+ OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+ OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+
+ OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+ OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]);
+ OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]);
+ OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]);
+ OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]);
+ OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+ OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]);
+ OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+ OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
+ OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
+ OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]);
+
+ OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+ OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+ OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+ OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]);
+ OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]);
+ OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]);
+ OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]);
+ OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]);
+ OUTREG(GPIO_MONID, rinfo->save_regs[27]);
+ OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]);
+}
+
+static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo)
+{
+ OUTREG(GPIOPAD_MASK, 0x0001ffff);
+ OUTREG(GPIOPAD_EN, 0x00000400);
+ OUTREG(GPIOPAD_A, 0x00000000);
+ OUTREG(ZV_LCDPAD_MASK, 0x00000000);
+ OUTREG(ZV_LCDPAD_EN, 0x00000000);
+ OUTREG(ZV_LCDPAD_A, 0x00000000);
+ OUTREG(GPIO_VGA_DDC, 0x00030000);
+ OUTREG(GPIO_DVI_DDC, 0x00000000);
+ OUTREG(GPIO_MONID, 0x00030000);
+ OUTREG(GPIO_CRT2_DDC, 0x00000000);
+}
+
+static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
+{
+ /* Set v2clk to 65MHz */
+ if (rinfo->family <= CHIP_FAMILY_RV280) {
+ OUTPLL(pllPIXCLKS_CNTL,
+ __INPLL(rinfo, pllPIXCLKS_CNTL)
+ & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
+
+ OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
+ OUTPLL(pllP2PLL_CNTL, 0x0000bf00);
+ } else {
+ OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
+ INPLL(pllP2PLL_REF_DIV);
+ OUTPLL(pllP2PLL_CNTL, 0x0000a700);
+ }
+
+ 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_low_current(struct radeonfb_info *rinfo)
+{
+ u32 reg;
+
+ reg = INREG(BUS_CNTL1);
+ if (rinfo->family <= CHIP_FAMILY_RV280) {
+ reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
+ reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
+ } else {
+ reg |= 0x4080;
+ }
+ 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 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;
+ u32 tmp;
+
+ /* 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);
+
+ /* 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);
+ }
+
+ 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);
+