Subject: [PATCH] radeonfb: massive update of PM code

From: Benjamin Herrenschmidt <[email-masked]>
Date: Tue, 18 Jan 2005 12:48:51 +1100

Hi !

This patch is a quite massive update to radeonfb. It adds the ability to reboot
from scratch the various chip models used on the recent powermac laptops, adds
a bunch of new chips (including R420 support, untested), plus various fixes
here or there including LCD & flat panel blanking, abuse of stack usage in
radeonfb_set_par(), and finally, adapts the PM code to the recent powermac
changes.

Signed-off-by: Benjamin Herrenschmidt <[email-masked]>

Index: linux-work/drivers/video/aty/radeon_monitor.c
===================================================================
--- linux-work.orig/drivers/video/aty/radeon_monitor.c	2004-11-22 11:50:27.000000000 +1100
+++ linux-work/drivers/video/aty/radeon_monitor.c	2005-01-17 13:49:30.011589712 +1100
@@ -1,11 +1,6 @@
 #include "radeonfb.h"
 #include "../edid.h"
 
-#ifdef CONFIG_PPC_OF
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif /* CONFIG_PPC_OF */
-
 static struct fb_var_screeninfo radeonfb_default_var = {
 	.xres		= 640,
 	.yres		= 480,
@@ -64,9 +59,11 @@
  * models with broken OF probing by hard-coding known EDIDs for some Mac
  * laptops internal LVDS panel. (XXX: not done yet)
  */
-static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID, int hdno)
+static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID,
+					       int hdno)
 {
-        static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID2",  NULL };
+        static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID",
+				     "EDID1", "EDID2",  NULL };
 	u8 *pedid = NULL;
 	u8 *pmt = NULL;
 	u8 *tmp;
@@ -122,7 +119,7 @@
 
 	RTRACE("radeon_probe_OF_head\n");
 
-        dp = pci_device_to_OF_node(rinfo->pdev);
+        dp = rinfo->of_node;
         while (dp == NULL)
 		return MT_NONE;
 
@@ -502,8 +499,9 @@
 #endif /* CONFIG_PPC_OF */
 #ifdef CONFIG_FB_RADEON_I2C
 			if (rinfo->mon1_type == MT_NONE)
-				rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, ddc_dvi,
-								      &rinfo->mon1_EDID);
+				rinfo->mon1_type =
+					radeon_probe_i2c_connector(rinfo, ddc_dvi,
+								   &rinfo->mon1_EDID);
 			if (rinfo->mon1_type == MT_NONE)
 				rinfo->mon1_type =
 					radeon_probe_i2c_connector(rinfo, ddc_vga,
@@ -545,7 +543,8 @@
 		 */
 #ifdef CONFIG_PPC_OF
 		if (rinfo->mon1_type == MT_NONE)
-			rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0, &rinfo->mon1_EDID);
+			rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
+								&rinfo->mon1_EDID);
 #endif /* CONFIG_PPC_OF */
 #ifdef CONFIG_FB_RADEON_I2C
 		if (rinfo->mon1_type == MT_NONE)
@@ -572,7 +571,8 @@
 		 */
 #ifdef CONFIG_PPC_OF
 		if (rinfo->mon2_type == MT_NONE)
-			rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1, &rinfo->mon2_EDID);
+			rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1,
+								&rinfo->mon2_EDID);
 #endif /* CONFIG_PPC_OF */
 #ifdef CONFIG_FB_RADEON_I2C
 		if (rinfo->mon2_type == MT_NONE)
@@ -814,9 +814,10 @@
 	 * Now build modedb from EDID
 	 */
 	if (rinfo->mon1_EDID) {
-		rinfo->mon1_modedb = fb_create_modedb(rinfo->mon1_EDID,
-						      &rinfo->mon1_dbsize);
-		fb_get_monitor_limits(rinfo->mon1_EDID, &rinfo->info->monspecs);
+		fb_edid_to_monspecs(rinfo->mon1_EDID, &rinfo->info->monspecs);
+		fb_videomode_to_modelist(rinfo->info->monspecs.modedb,
+					 rinfo->info->monspecs.modedb_len,
+					 &rinfo->info->modelist);
 	}

Index: linux-work/include/video/radeon.h
===================================================================
--- linux-work.orig/include/video/radeon.h	2004-11-22 11:50:58.000000000 +1100
+++ linux-work/include/video/radeon.h	2005-01-17 13:49:30.025587584 +1100
@@ -21,6 +21,7 @@
 #define PAD_AGPINPUT_DELAY                     0x0164  
 #define PAD_CTLR_STRENGTH                      0x0168  
 #define PAD_CTLR_UPDATE                        0x016C
+#define PAD_CTLR_MISC                          0x0aa0
 #define AGP_CNTL                               0x0174
 #define BM_STATUS                              0x0160
 #define CAP0_TRIG_CNTL			       0x0950
@@ -68,18 +69,26 @@
 #define DAC_CNTL2                              0x007c
 #define CRTC_GEN_CNTL                          0x0050  
 #define MEM_CNTL                               0x0140  
+#define MC_CNTL                                0x0140  
 #define EXT_MEM_CNTL                           0x0144  
+#define MC_TIMING_CNTL                         0x0144  
 #define MC_AGP_LOCATION                        0x014C  
 #define MEM_IO_CNTL_A0                         0x0178  
+#define MEM_REFRESH_CNTL                       0x0178
 #define MEM_INIT_LATENCY_TIMER                 0x0154  
+#define MC_INIT_GFX_LAT_TIMER                  0x0154  
 #define MEM_SDRAM_MODE_REG                     0x0158  
 #define AGP_BASE                               0x0170  
 #define MEM_IO_CNTL_A1                         0x017C  
+#define MC_READ_CNTL_AB                        0x017C  
 #define MEM_IO_CNTL_B0                         0x0180
+#define MC_INIT_MISC_LAT_TIMER                 0x0180
 #define MEM_IO_CNTL_B1                         0x0184
+#define MC_IOPAD_CNTL                          0x0184
 #define MC_DEBUG                               0x0188
 #define MC_STATUS                              0x0150  
 #define MEM_IO_OE_CNTL                         0x018C  
+#define MC_CHIP_IO_OE_CNTL_AB                  0x018C  
 #define MC_FB_LOCATION                         0x0148  
 #define HOST_PATH_CNTL                         0x0130  
 #define MEM_VGA_WP_SEL                         0x0038  
@@ -385,6 +394,13 @@
 #define TMDS_CRC			       0x02a0
 #define TMDS_TRANSMITTER_CNTL		       0x02a4
 #define MPP_TB_CONFIG            	       0x01c0
+#define PAMAC0_DLY_CNTL                        0x0a94
+#define PAMAC1_DLY_CNTL                        0x0a98
+#define PAMAC2_DLY_CNTL                        0x0a9c
+#define FW_CNTL                                0x0118
+#define FCP_CNTL                               0x0910
+#define VGA_DDA_ON_OFF                         0x02ec
+#define TV_MASTER_CNTL                         0x0800
 
 //#define BASE_CODE			       0x0f0b
 #define BIOS_0_SCRATCH			       0x0010
@@ -418,7 +434,7 @@
 #define PPLL_DIV_3                                 0x0007
 #define VCLK_ECP_CNTL                              0x0008
 #define HTOTAL_CNTL                                0x0009
-#define X_MPLL_REF_FB_DIV                          0x000a
+#define M_SPLL_REF_FB_DIV                          0x000a
 #define AGP_PLL_CNTL                               0x000b
 #define SPLL_CNTL                                  0x000c
 #define SCLK_CNTL                                  0x000d
@@ -497,6 +513,8 @@
 #define CFG_VGA_RAM_EN                             0x00000100
 #define CFG_ATI_REV_ID_MASK			   (0xf << 16)
 #define CFG_ATI_REV_A11				   (0 << 16)
+#define CFG_ATI_REV_A12				   (1 << 16)
+#define CFG_ATI_REV_A13				   (2 << 16)
 
 /* CRTC_EXT_CNTL bit constants */
 #define VGA_ATI_LINEAR                             0x00000008
@@ -573,9 +591,17 @@
 /* FP_GEN_CNTL bit constants */
 #define FP_FPON					   (1 << 0)
 #define FP_TMDS_EN				   (1 << 2)
+#define FP_PANEL_FORMAT                            (1 << 3)
 #define FP_EN_TMDS				   (1 << 7)
 #define FP_DETECT_SENSE				   (1 << 8)
+#define R200_FP_SOURCE_SEL_MASK                    (3 << 10)
+#define R200_FP_SOURCE_SEL_CRTC1                   (0 << 10)
+#define R200_FP_SOURCE_SEL_CRTC2                   (1 << 10)
+#define R200_FP_SOURCE_SEL_RMX                     (2 << 10)
+#define R200_FP_SOURCE_SEL_TRANS                   (3 << 10)
+#define FP_SEL_CRTC1				   (0 << 13)
 #define FP_SEL_CRTC2				   (1 << 13)
+#define FP_USE_VGA_HSYNC                           (1 << 14)
 #define FP_CRTC_DONT_SHADOW_HPAR		   (1 << 15)
 #define FP_CRTC_DONT_SHADOW_VPAR		   (1 << 16)
 #define FP_CRTC_DONT_SHADOW_HEND		   (1 << 17)
@@ -671,6 +697,7 @@
 #define DAC_CMP_OUTPUT                             (1 <<  7)
 
 /* DAC_CNTL2 bit constants */   
+#define DAC2_EXPAND_MODE			   (1 << 14)
 #define DAC2_CMP_EN                                (1 << 7)
 #define DAC2_PALETTE_ACCESS_CNTL                   (1 << 5)
 
@@ -697,6 +724,11 @@
 #define MEM_ARBITER_STATUS_BUSY                    0x00400000
 #define MEM_REQ_UNLOCK                             0x00000000
 #define MEM_REQ_LOCK                               0x00800000
+#define MEM_NUM_CHANNELS_MASK 			   0x00000001
+#define MEM_USE_B_CH_ONLY                          0x00000002
+#define RV100_MEM_HALF_MODE                        0x00000008
+#define R300_MEM_NUM_CHANNELS_MASK                 0x00000003
+#define R300_MEM_USE_CD_CH_ONLY                    0x00000004

 /* RBBM_SOFT_RESET bit constants */
@@ -963,9 +995,11 @@
 
 #define MC_IND_INDEX                           0x01F8
 #define MC_IND_DATA                            0x01FC
-#define MEM_REFRESH_CNTL                       0x0178
 
-// CLK_PIN_CNTL
+/* PAD_CTLR_STRENGTH */
+#define PAD_MANUAL_OVERRIDE		0x80000000
+
+// pllCLK_PIN_CNTL
 #define CLK_PIN_CNTL__OSC_EN_MASK                          0x00000001L
 #define CLK_PIN_CNTL__OSC_EN                               0x00000001L
 #define CLK_PIN_CNTL__XTL_LOW_GAIN_MASK                    0x00000004L
@@ -991,32 +1025,32 @@
 #define CLK_PIN_CNTL__XTALIN_ALWAYS_ONb                    0x00080000L
 #define CLK_PIN_CNTL__PWRSEQ_DELAY_MASK                    0xff000000L
 
-// CLK_PWRMGT_CNTL_M6
-#define	CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF__SHIFT         0x00000000
-#define	CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF__SHIFT         0x00000001
-#define	CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF__SHIFT         0x00000002
-#define	CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF__SHIFT        0x00000003
-#define	CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF__SHIFT            0x00000004
-#define	CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF__SHIFT            0x00000005
-#define	CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF__SHIFT            0x00000006
-#define	CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF__SHIFT           0x00000007
-#define	CLK_PWRMGT_CNTL_M6__MC_CH_MODE__SHIFT              0x00000008
-#define	CLK_PWRMGT_CNTL_M6__TEST_MODE__SHIFT               0x00000009
-#define	CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN__SHIFT          0x0000000a
-#define	CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE__SHIFT      0x0000000c
-#define	CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT__SHIFT         0x0000000d
-#define	CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT__SHIFT       0x0000000f
-#define	CLK_PWRMGT_CNTL_M6__MC_BUSY__SHIFT                 0x00000010
-#define	CLK_PWRMGT_CNTL_M6__MC_INT_CNTL__SHIFT             0x00000011
-#define	CLK_PWRMGT_CNTL_M6__MC_SWITCH__SHIFT               0x00000012
-#define	CLK_PWRMGT_CNTL_M6__DLL_READY__SHIFT               0x00000013
-#define	CLK_PWRMGT_CNTL_M6__DISP_PM__SHIFT                 0x00000014
-#define	CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE__SHIFT           0x00000015
-#define	CLK_PWRMGT_CNTL_M6__CG_NO1_DEBUG__SHIFT            0x00000018
-#define	CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF__SHIFT        0x0000001e
-#define	CLK_PWRMGT_CNTL_M6__TVCLK_TURNOFF__SHIFT           0x0000001f
+// pllCLK_PWRMGT_CNTL
+#define	CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF__SHIFT         0x00000000
+#define	CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF__SHIFT         0x00000001
+#define	CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF__SHIFT         0x00000002
+#define	CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF__SHIFT        0x00000003
+#define	CLK_PWRMGT_CNTL__MCLK_TURNOFF__SHIFT            0x00000004
+#define	CLK_PWRMGT_CNTL__SCLK_TURNOFF__SHIFT            0x00000005
+#define	CLK_PWRMGT_CNTL__PCLK_TURNOFF__SHIFT            0x00000006
+#define	CLK_PWRMGT_CNTL__P2CLK_TURNOFF__SHIFT           0x00000007
+#define	CLK_PWRMGT_CNTL__MC_CH_MODE__SHIFT              0x00000008
+#define	CLK_PWRMGT_CNTL__TEST_MODE__SHIFT               0x00000009
+#define	CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN__SHIFT          0x0000000a
+#define	CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE__SHIFT      0x0000000c
+#define	CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT__SHIFT         0x0000000d
+#define	CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT__SHIFT       0x0000000f
+#define	CLK_PWRMGT_CNTL__MC_BUSY__SHIFT                 0x00000010
+#define	CLK_PWRMGT_CNTL__MC_INT_CNTL__SHIFT             0x00000011
+#define	CLK_PWRMGT_CNTL__MC_SWITCH__SHIFT               0x00000012
+#define	CLK_PWRMGT_CNTL__DLL_READY__SHIFT               0x00000013
+#define	CLK_PWRMGT_CNTL__DISP_PM__SHIFT                 0x00000014
+#define	CLK_PWRMGT_CNTL__DYN_STOP_MODE__SHIFT           0x00000015
+#define	CLK_PWRMGT_CNTL__CG_NO1_DEBUG__SHIFT            0x00000018
+#define	CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF__SHIFT        0x0000001e
+#define	CLK_PWRMGT_CNTL__TVCLK_TURNOFF__SHIFT           0x0000001f
 
-// P2PLL_CNTL
+// pllP2PLL_CNTL
 #define P2PLL_CNTL__P2PLL_RESET_MASK                       0x00000001L
 #define P2PLL_CNTL__P2PLL_RESET                            0x00000001L
 #define P2PLL_CNTL__P2PLL_SLEEP_MASK                       0x00000002L
@@ -1041,7 +1075,7 @@
 #define P2PLL_CNTL__P2PLL_DISABLE_AUTO_RESET_MASK          0x00080000L
 #define P2PLL_CNTL__P2PLL_DISABLE_AUTO_RESET               0x00080000L
 
-// PIXCLKS_CNTL
+// pllPIXCLKS_CNTL
 #define	PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT               0x00000000
 #define	PIXCLKS_CNTL__PIX2CLK_INVERT__SHIFT                0x00000004
 #define	PIXCLKS_CNTL__PIX2CLK_SRC_INVERT__SHIFT            0x00000005
@@ -1055,31 +1089,29 @@
 #define	PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb__SHIFT        0x0000000f

-// PIXCLKS_CNTL
+// pllPIXCLKS_CNTL
 #define PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK                 0x00000003L
-#define PIXCLKS_CNTL__PIX2CLK_INVERT_MASK                  0x00000010L
 #define PIXCLKS_CNTL__PIX2CLK_INVERT                       0x00000010L
-#define PIXCLKS_CNTL__PIX2CLK_SRC_INVERT_MASK              0x00000020L
 #define PIXCLKS_CNTL__PIX2CLK_SRC_INVERT                   0x00000020L
-#define PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb_MASK              0x00000040L
 #define PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb                   0x00000040L
-#define PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb_MASK          0x00000080L
 #define PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb               0x00000080L
-#define PIXCLKS_CNTL__PIXCLK_TV_SRC_SEL_MASK               0x00000100L
 #define PIXCLKS_CNTL__PIXCLK_TV_SRC_SEL                    0x00000100L
-#define PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb_MASK         0x00000800L
 #define PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb              0x00000800L
-#define PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb_MASK            0x00001000L
 #define PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb                 0x00001000L
-#define PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb_MASK      0x00002000L
 #define PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb           0x00002000L
-#define PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb_MASK          0x00004000L
 #define PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb               0x00004000L
-#define PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb_MASK          0x00008000L
 #define PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb               0x00008000L
+#define PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb      (1 << 9)
+#define PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb               (1 << 10)
+#define PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb           (1 << 13)
+#define PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb         (1 << 16)
+#define PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb           (1 << 17)
+#define PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb              (1 << 18)
+#define PIXCLKS_CNTL__R300_P2G2CLK_DAC_ALWAYS_ONb          (1 << 19)
+#define PIXCLKS_CNTL__R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF  (1 << 23)

-// P2PLL_DIV_0
+// pllP2PLL_DIV_0
 #define P2PLL_DIV_0__P2PLL_FB_DIV_MASK                     0x000007ffL
 #define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W_MASK            0x00008000L
 #define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W                 0x00008000L
@@ -1087,124 +1119,97 @@
 #define P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_R                 0x00008000L
 #define P2PLL_DIV_0__P2PLL_POST_DIV_MASK                   0x00070000L
 
-// SCLK_CNTL_M6
-#define SCLK_CNTL_M6__SCLK_SRC_SEL_MASK                    0x00000007L
-#define SCLK_CNTL_M6__CP_MAX_DYN_STOP_LAT_MASK             0x00000008L
-#define SCLK_CNTL_M6__CP_MAX_DYN_STOP_LAT                  0x00000008L
-#define SCLK_CNTL_M6__HDP_MAX_DYN_STOP_LAT_MASK            0x00000010L
-#define SCLK_CNTL_M6__HDP_MAX_DYN_STOP_LAT                 0x00000010L
-#define SCLK_CNTL_M6__TV_MAX_DYN_STOP_LAT_MASK             0x00000020L
-#define SCLK_CNTL_M6__TV_MAX_DYN_STOP_LAT                  0x00000020L
-#define SCLK_CNTL_M6__E2_MAX_DYN_STOP_LAT_MASK             0x00000040L
-#define SCLK_CNTL_M6__E2_MAX_DYN_STOP_LAT                  0x00000040L
-#define SCLK_CNTL_M6__SE_MAX_DYN_STOP_LAT_MASK             0x00000080L
-#define SCLK_CNTL_M6__SE_MAX_DYN_STOP_LAT                  0x00000080L
-#define SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT_MASK           0x00000100L
-#define SCLK_CNTL_M6__IDCT_MAX_DYN_STOP_LAT                0x00000100L
-#define SCLK_CNTL_M6__VIP_MAX_DYN_STOP_LAT_MASK            0x00000200L
-#define SCLK_CNTL_M6__VIP_MAX_DYN_STOP_LAT                 0x00000200L
-#define SCLK_CNTL_M6__RE_MAX_DYN_STOP_LAT_MASK             0x00000400L
-#define SCLK_CNTL_M6__RE_MAX_DYN_STOP_LAT                  0x00000400L
-#define SCLK_CNTL_M6__PB_MAX_DYN_STOP_LAT_MASK             0x00000800L
-#define SCLK_CNTL_M6__PB_MAX_DYN_STOP_LAT                  0x00000800L
-#define SCLK_CNTL_M6__TAM_MAX_DYN_STOP_LAT_MASK            0x00001000L
-#define SCLK_CNTL_M6__TAM_MAX_DYN_STOP_LAT                 0x00001000L
-#define SCLK_CNTL_M6__TDM_MAX_DYN_STOP_LAT_MASK            0x00002000L
-#define SCLK_CNTL_M6__TDM_MAX_DYN_STOP_LAT                 0x00002000L
-#define SCLK_CNTL_M6__RB_MAX_DYN_STOP_LAT_MASK             0x00004000L
-#define SCLK_CNTL_M6__RB_MAX_DYN_STOP_LAT                  0x00004000L
-#define SCLK_CNTL_M6__FORCE_DISP2_MASK                     0x00008000L
-#define SCLK_CNTL_M6__FORCE_DISP2                          0x00008000L
-#define SCLK_CNTL_M6__FORCE_CP_MASK                        0x00010000L
-#define SCLK_CNTL_M6__FORCE_CP                             0x00010000L
-#define SCLK_CNTL_M6__FORCE_HDP_MASK                       0x00020000L
-#define SCLK_CNTL_M6__FORCE_HDP                            0x00020000L
-#define SCLK_CNTL_M6__FORCE_DISP1_MASK                     0x00040000L
-#define SCLK_CNTL_M6__FORCE_DISP1                          0x00040000L
-#define SCLK_CNTL_M6__FORCE_TOP_MASK                       0x00080000L
-#define SCLK_CNTL_M6__FORCE_TOP                            0x00080000L
-#define SCLK_CNTL_M6__FORCE_E2_MASK                        0x00100000L
-#define SCLK_CNTL_M6__FORCE_E2                             0x00100000L
-#define SCLK_CNTL_M6__FORCE_SE_MASK                        0x00200000L
-#define SCLK_CNTL_M6__FORCE_SE                             0x00200000L
-#define SCLK_CNTL_M6__FORCE_IDCT_MASK                      0x00400000L
-#define SCLK_CNTL_M6__FORCE_IDCT                           0x00400000L
-#define SCLK_CNTL_M6__FORCE_VIP_MASK                       0x00800000L
-#define SCLK_CNTL_M6__FORCE_VIP                            0x00800000L
-#define SCLK_CNTL_M6__FORCE_RE_MASK                        0x01000000L
-#define SCLK_CNTL_M6__FORCE_RE                             0x01000000L
-#define SCLK_CNTL_M6__FORCE_PB_MASK                        0x02000000L
-#define SCLK_CNTL_M6__FORCE_PB                             0x02000000L
-#define SCLK_CNTL_M6__FORCE_TAM_MASK                       0x04000000L
-#define SCLK_CNTL_M6__FORCE_TAM                            0x04000000L
-#define SCLK_CNTL_M6__FORCE_TDM_MASK                       0x08000000L
-#define SCLK_CNTL_M6__FORCE_TDM                            0x08000000L
-#define SCLK_CNTL_M6__FORCE_RB_MASK                        0x10000000L
-#define SCLK_CNTL_M6__FORCE_RB                             0x10000000L
-#define SCLK_CNTL_M6__FORCE_TV_SCLK_MASK                   0x20000000L
-#define SCLK_CNTL_M6__FORCE_TV_SCLK                        0x20000000L
-#define SCLK_CNTL_M6__FORCE_SUBPIC_MASK                    0x40000000L
-#define SCLK_CNTL_M6__FORCE_SUBPIC                         0x40000000L
-#define SCLK_CNTL_M6__FORCE_OV0_MASK                       0x80000000L
-#define SCLK_CNTL_M6__FORCE_OV0                            0x80000000L
+// pllSCLK_CNTL
+#define SCLK_CNTL__SCLK_SRC_SEL_MASK                    0x00000007L
+#define SCLK_CNTL__CP_MAX_DYN_STOP_LAT                  0x00000008L
+#define SCLK_CNTL__HDP_MAX_DYN_STOP_LAT                 0x00000010L
+#define SCLK_CNTL__TV_MAX_DYN_STOP_LAT                  0x00000020L
+#define SCLK_CNTL__E2_MAX_DYN_STOP_LAT                  0x00000040L
+#define SCLK_CNTL__SE_MAX_DYN_STOP_LAT                  0x00000080L
+#define SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT                0x00000100L
+#define SCLK_CNTL__VIP_MAX_DYN_STOP_LAT                 0x00000200L
+#define SCLK_CNTL__RE_MAX_DYN_STOP_LAT                  0x00000400L
+#define SCLK_CNTL__PB_MAX_DYN_STOP_LAT                  0x00000800L
+#define SCLK_CNTL__TAM_MAX_DYN_STOP_LAT                 0x00001000L
+#define SCLK_CNTL__TDM_MAX_DYN_STOP_LAT                 0x00002000L
+#define SCLK_CNTL__RB_MAX_DYN_STOP_LAT                  0x00004000L
+#define SCLK_CNTL__DYN_STOP_LAT_MASK                     0x00007ff8
+#define SCLK_CNTL__FORCE_DISP2                          0x00008000L
+#define SCLK_CNTL__FORCE_CP                             0x00010000L
+#define SCLK_CNTL__FORCE_HDP                            0x00020000L
+#define SCLK_CNTL__FORCE_DISP1                          0x00040000L
+#define SCLK_CNTL__FORCE_TOP                            0x00080000L
+#define SCLK_CNTL__FORCE_E2                             0x00100000L
+#define SCLK_CNTL__FORCE_SE                             0x00200000L
+#define SCLK_CNTL__FORCE_IDCT                           0x00400000L
+#define SCLK_CNTL__FORCE_VIP                            0x00800000L
+#define SCLK_CNTL__FORCE_RE                             0x01000000L
+#define SCLK_CNTL__FORCE_PB                             0x02000000L
+#define SCLK_CNTL__FORCE_TAM                            0x04000000L
+#define SCLK_CNTL__FORCE_TDM                            0x08000000L
+#define SCLK_CNTL__FORCE_RB                             0x10000000L
+#define SCLK_CNTL__FORCE_TV_SCLK                        0x20000000L
+#define SCLK_CNTL__FORCE_SUBPIC                         0x40000000L
+#define SCLK_CNTL__FORCE_OV0                            0x80000000L
+#define SCLK_CNTL__R300_FORCE_VAP                       (1<<21)
+#define SCLK_CNTL__R300_FORCE_SR                        (1<<25)
+#define SCLK_CNTL__R300_FORCE_PX                        (1<<26)
+#define SCLK_CNTL__R300_FORCE_TX                        (1<<27)
+#define SCLK_CNTL__R300_FORCE_US                        (1<<28)
+#define SCLK_CNTL__R300_FORCE_SU                        (1<<30)
+#define SCLK_CNTL__FORCEON_MASK                         0xffff8000L
+
+// pllSCLK_CNTL2
+#define SCLK_CNTL2__R300_TCL_MAX_DYN_STOP_LAT           (1<<10)
+#define SCLK_CNTL2__R300_GA_MAX_DYN_STOP_LAT            (1<<11)
+#define SCLK_CNTL2__R300_CBA_MAX_DYN_STOP_LAT           (1<<12)
+#define SCLK_CNTL2__R300_FORCE_TCL                      (1<<13)
+#define SCLK_CNTL2__R300_FORCE_CBA                      (1<<14)
+#define SCLK_CNTL2__R300_FORCE_GA                       (1<<15)
 
 // SCLK_MORE_CNTL
-#define SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT_MASK     0x00000001L
 #define SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT          0x00000001L
-#define SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT_MASK       0x00000002L
 #define SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT            0x00000002L
-#define SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT_MASK      0x00000004L
 #define SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT           0x00000004L
-#define SCLK_MORE_CNTL__FORCE_DISPREGS_MASK                0x00000100L
 #define SCLK_MORE_CNTL__FORCE_DISPREGS                     0x00000100L
-#define SCLK_MORE_CNTL__FORCE_MC_GUI_MASK                  0x00000200L
 #define SCLK_MORE_CNTL__FORCE_MC_GUI                       0x00000200L
-#define SCLK_MORE_CNTL__FORCE_MC_HOST_MASK                 0x00000400L
 #define SCLK_MORE_CNTL__FORCE_MC_HOST                      0x00000400L
-#define SCLK_MORE_CNTL__STOP_SCLK_EN_MASK                  0x00001000L
 #define SCLK_MORE_CNTL__STOP_SCLK_EN                       0x00001000L
-#define SCLK_MORE_CNTL__STOP_SCLK_A_MASK                   0x00002000L
 #define SCLK_MORE_CNTL__STOP_SCLK_A                        0x00002000L
-#define SCLK_MORE_CNTL__STOP_SCLK_B_MASK                   0x00004000L
 #define SCLK_MORE_CNTL__STOP_SCLK_B                        0x00004000L
-#define SCLK_MORE_CNTL__STOP_SCLK_C_MASK                   0x00008000L
 #define SCLK_MORE_CNTL__STOP_SCLK_C                        0x00008000L
-#define SCLK_MORE_CNTL__HALF_SPEED_SCLK_MASK               0x00010000L
 #define SCLK_MORE_CNTL__HALF_SPEED_SCLK                    0x00010000L
-#define SCLK_MORE_CNTL__IO_CG_VOLTAGE_DROP_MASK            0x00020000L
 #define SCLK_MORE_CNTL__IO_CG_VOLTAGE_DROP                 0x00020000L
-#define SCLK_MORE_CNTL__TVFB_SOFT_RESET_MASK               0x00040000L
 #define SCLK_MORE_CNTL__TVFB_SOFT_RESET                    0x00040000L
-#define SCLK_MORE_CNTL__VOLTAGE_DROP_SYNC_MASK             0x00080000L
 #define SCLK_MORE_CNTL__VOLTAGE_DROP_SYNC                  0x00080000L
-#define SCLK_MORE_CNTL__VOLTAGE_DELAY_SEL_MASK             0x00300000L
-#define SCLK_MORE_CNTL__IDLE_DELAY_HALF_SCLK_MASK          0x00400000L
 #define SCLK_MORE_CNTL__IDLE_DELAY_HALF_SCLK               0x00400000L
-#define SCLK_MORE_CNTL__AGP_BUSY_HALF_SCLK_MASK            0x00800000L
 #define SCLK_MORE_CNTL__AGP_BUSY_HALF_SCLK                 0x00800000L
 #define SCLK_MORE_CNTL__CG_SPARE_RD_C_MASK                 0xff000000L
+#define SCLK_MORE_CNTL__FORCEON                            0x00000700L
 
-// MCLK_CNTL_M6
-#define MCLK_CNTL_M6__MCLKA_SRC_SEL_MASK                   0x00000007L
-#define MCLK_CNTL_M6__YCLKA_SRC_SEL_MASK                   0x00000070L
-#define MCLK_CNTL_M6__MCLKB_SRC_SEL_MASK                   0x00000700L
-#define MCLK_CNTL_M6__YCLKB_SRC_SEL_MASK                   0x00007000L
-#define MCLK_CNTL_M6__FORCE_MCLKA_MASK                     0x00010000L
-#define MCLK_CNTL_M6__FORCE_MCLKA                          0x00010000L
-#define MCLK_CNTL_M6__FORCE_MCLKB_MASK                     0x00020000L
-#define MCLK_CNTL_M6__FORCE_MCLKB                          0x00020000L
-#define MCLK_CNTL_M6__FORCE_YCLKA_MASK                     0x00040000L
-#define MCLK_CNTL_M6__FORCE_YCLKA                          0x00040000L
-#define MCLK_CNTL_M6__FORCE_YCLKB_MASK                     0x00080000L
-#define MCLK_CNTL_M6__FORCE_YCLKB                          0x00080000L
-#define MCLK_CNTL_M6__FORCE_MC_MASK                        0x00100000L
-#define MCLK_CNTL_M6__FORCE_MC                             0x00100000L
-#define MCLK_CNTL_M6__FORCE_AIC_MASK                       0x00200000L
-#define MCLK_CNTL_M6__FORCE_AIC                            0x00200000L
-#define MCLK_CNTL_M6__MRDCKA0_SOUTSEL_MASK                 0x03000000L
-#define MCLK_CNTL_M6__MRDCKA1_SOUTSEL_MASK                 0x0c000000L
-#define MCLK_CNTL_M6__MRDCKB0_SOUTSEL_MASK                 0x30000000L
-#define MCLK_CNTL_M6__MRDCKB1_SOUTSEL_MASK                 0xc0000000L
+// MCLK_CNTL
+#define MCLK_CNTL__MCLKA_SRC_SEL_MASK                   0x00000007L
+#define MCLK_CNTL__YCLKA_SRC_SEL_MASK                   0x00000070L
+#define MCLK_CNTL__MCLKB_SRC_SEL_MASK                   0x00000700L
+#define MCLK_CNTL__YCLKB_SRC_SEL_MASK                   0x00007000L
+#define MCLK_CNTL__FORCE_MCLKA_MASK                     0x00010000L
+#define MCLK_CNTL__FORCE_MCLKA                          0x00010000L
+#define MCLK_CNTL__FORCE_MCLKB_MASK                     0x00020000L
+#define MCLK_CNTL__FORCE_MCLKB                          0x00020000L
+#define MCLK_CNTL__FORCE_YCLKA_MASK                     0x00040000L
+#define MCLK_CNTL__FORCE_YCLKA                          0x00040000L
+#define MCLK_CNTL__FORCE_YCLKB_MASK                     0x00080000L
+#define MCLK_CNTL__FORCE_YCLKB                          0x00080000L
+#define MCLK_CNTL__FORCE_MC_MASK                        0x00100000L
+#define MCLK_CNTL__FORCE_MC                             0x00100000L
+#define MCLK_CNTL__FORCE_AIC_MASK                       0x00200000L
+#define MCLK_CNTL__FORCE_AIC                            0x00200000L
+#define MCLK_CNTL__MRDCKA0_SOUTSEL_MASK                 0x03000000L
+#define MCLK_CNTL__MRDCKA1_SOUTSEL_MASK                 0x0c000000L
+#define MCLK_CNTL__MRDCKB0_SOUTSEL_MASK                 0x30000000L
+#define MCLK_CNTL__MRDCKB1_SOUTSEL_MASK                 0xc0000000L
+#define MCLK_CNTL__R300_DISABLE_MC_MCLKA                (1 << 21)
+#define MCLK_CNTL__R300_DISABLE_MC_MCLKB                (1 << 21)
 
 // MCLK_MISC
 #define MCLK_MISC__SCLK_SOURCED_FROM_MPLL_SEL_MASK         0x00000003L
@@ -1238,19 +1243,14 @@
 
 // VCLK_ECP_CNTL
 #define VCLK_ECP_CNTL__VCLK_SRC_SEL_MASK                   0x00000003L
-#define VCLK_ECP_CNTL__VCLK_INVERT_MASK                    0x00000010L
 #define VCLK_ECP_CNTL__VCLK_INVERT                         0x00000010L
-#define VCLK_ECP_CNTL__PIXCLK_SRC_INVERT_MASK              0x00000020L
 #define VCLK_ECP_CNTL__PIXCLK_SRC_INVERT                   0x00000020L
-#define VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb_MASK              0x00000040L
 #define VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb                   0x00000040L
-#define VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb_MASK          0x00000080L
 #define VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb               0x00000080L
 #define VCLK_ECP_CNTL__ECP_DIV_MASK                        0x00000300L
-#define VCLK_ECP_CNTL__ECP_FORCE_ON_MASK                   0x00040000L
 #define VCLK_ECP_CNTL__ECP_FORCE_ON                        0x00040000L
-#define VCLK_ECP_CNTL__SUBCLK_FORCE_ON_MASK                0x00080000L
 #define VCLK_ECP_CNTL__SUBCLK_FORCE_ON                     0x00080000L
+#define VCLK_ECP_CNTL__R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF  (1<<23)
 
 // PLL_PWRMGT_CNTL
 #define PLL_PWRMGT_CNTL__MPLL_TURNOFF_MASK                 0x00000001L
@@ -1282,54 +1282,54 @@
 #define PLL_PWRMGT_CNTL__SU_SUSTAIN_DISABLE                0x00080000L
 #define PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE_MASK           0x00100000L
 #define PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE                0x00100000L
-#define PLL_PWRMGT_CNTL__TCL_CLOCK_ACTIVE_RD_MASK          0x00200000L
+#define PLL_PWRMGT_CNTL__TCL_CLOCK_CTIVE_RD_MASK          0x00200000L
 #define PLL_PWRMGT_CNTL__TCL_CLOCK_ACTIVE_RD               0x00200000L
 #define PLL_PWRMGT_CNTL__CG_NO2_DEBUG_MASK                 0xff000000L
 
-// CLK_PWRMGT_CNTL_M6
-#define CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF_MASK           0x00000001L
-#define CLK_PWRMGT_CNTL_M6__MPLL_PWRMGT_OFF                0x00000001L
-#define CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF_MASK           0x00000002L
-#define CLK_PWRMGT_CNTL_M6__SPLL_PWRMGT_OFF                0x00000002L
-#define CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF_MASK           0x00000004L
-#define CLK_PWRMGT_CNTL_M6__PPLL_PWRMGT_OFF                0x00000004L
-#define CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF_MASK          0x00000008L
-#define CLK_PWRMGT_CNTL_M6__P2PLL_PWRMGT_OFF               0x00000008L
-#define CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF_MASK              0x00000010L
-#define CLK_PWRMGT_CNTL_M6__MCLK_TURNOFF                   0x00000010L
-#define CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF_MASK              0x00000020L
-#define CLK_PWRMGT_CNTL_M6__SCLK_TURNOFF                   0x00000020L
-#define CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF_MASK              0x00000040L
-#define CLK_PWRMGT_CNTL_M6__PCLK_TURNOFF                   0x00000040L
-#define CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF_MASK             0x00000080L
-#define CLK_PWRMGT_CNTL_M6__P2CLK_TURNOFF                  0x00000080L
-#define CLK_PWRMGT_CNTL_M6__MC_CH_MODE_MASK                0x00000100L
-#define CLK_PWRMGT_CNTL_M6__MC_CH_MODE                     0x00000100L
-#define CLK_PWRMGT_CNTL_M6__TEST_MODE_MASK                 0x00000200L
-#define CLK_PWRMGT_CNTL_M6__TEST_MODE                      0x00000200L
-#define CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN_MASK            0x00000400L
-#define CLK_PWRMGT_CNTL_M6__GLOBAL_PMAN_EN                 0x00000400L
-#define CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE_MASK        0x00001000L
-#define CLK_PWRMGT_CNTL_M6__ENGINE_DYNCLK_MODE             0x00001000L
-#define CLK_PWRMGT_CNTL_M6__ACTIVE_HILO_LAT_MASK           0x00006000L
-#define CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT_MASK         0x00008000L
-#define CLK_PWRMGT_CNTL_M6__DISP_DYN_STOP_LAT              0x00008000L
-#define CLK_PWRMGT_CNTL_M6__MC_BUSY_MASK                   0x00010000L
-#define CLK_PWRMGT_CNTL_M6__MC_BUSY                        0x00010000L
-#define CLK_PWRMGT_CNTL_M6__MC_INT_CNTL_MASK               0x00020000L
-#define CLK_PWRMGT_CNTL_M6__MC_INT_CNTL                    0x00020000L
-#define CLK_PWRMGT_CNTL_M6__MC_SWITCH_MASK                 0x00040000L
-#define CLK_PWRMGT_CNTL_M6__MC_SWITCH                      0x00040000L
-#define CLK_PWRMGT_CNTL_M6__DLL_READY_MASK                 0x00080000L
-#define CLK_PWRMGT_CNTL_M6__DLL_READY                      0x00080000L
-#define CLK_PWRMGT_CNTL_M6__DISP_PM_MASK                   0x00100000L
-#define CLK_PWRMGT_CNTL_M6__DISP_PM                        0x00100000L
-#define CLK_PWRMGT_CNTL_M6__DYN_STOP_MODE_MASK             0x00e00000L
-#define CLK_PWRMGT_CNTL_M6__CG_NO1_DEBUG_MASK              0x3f000000L
-#define CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF_MASK          0x40000000L
-#define CLK_PWRMGT_CNTL_M6__TVPLL_PWRMGT_OFF               0x40000000L
-#define CLK_PWRMGT_CNTL_M6__TVCLK_TURNOFF_MASK             0x80000000L
-#define CLK_PWRMGT_CNTL_M6__TVCLK_TURNOFF                  0x80000000L
+// CLK_PWRMGT_CNTL
+#define CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF_MASK           0x00000001L
+#define CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF                0x00000001L
+#define CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF_MASK           0x00000002L
+#define CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF                0x00000002L
+#define CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF_MASK           0x00000004L
+#define CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF                0x00000004L
+#define CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF_MASK          0x00000008L
+#define CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF               0x00000008L
+#define CLK_PWRMGT_CNTL__MCLK_TURNOFF_MASK              0x00000010L
+#define CLK_PWRMGT_CNTL__MCLK_TURNOFF                   0x00000010L
+#define CLK_PWRMGT_CNTL__SCLK_TURNOFF_MASK              0x00000020L
+#define CLK_PWRMGT_CNTL__SCLK_TURNOFF                   0x00000020L
+#define CLK_PWRMGT_CNTL__PCLK_TURNOFF_MASK              0x00000040L
+#define CLK_PWRMGT_CNTL__PCLK_TURNOFF                   0x00000040L
+#define CLK_PWRMGT_CNTL__P2CLK_TURNOFF_MASK             0x00000080L
+#define CLK_PWRMGT_CNTL__P2CLK_TURNOFF                  0x00000080L
+#define CLK_PWRMGT_CNTL__MC_CH_MODE_MASK                0x00000100L
+#define CLK_PWRMGT_CNTL__MC_CH_MODE                     0x00000100L
+#define CLK_PWRMGT_CNTL__TEST_MODE_MASK                 0x00000200L
+#define CLK_PWRMGT_CNTL__TEST_MODE                      0x00000200L
+#define CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN_MASK            0x00000400L
+#define CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN                 0x00000400L
+#define CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE_MASK        0x00001000L
+#define CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE             0x00001000L
+#define CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK           0x00006000L
+#define CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT_MASK         0x00008000L
+#define CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT              0x00008000L
+#define CLK_PWRMGT_CNTL__MC_BUSY_MASK                   0x00010000L
+#define CLK_PWRMGT_CNTL__MC_BUSY                        0x00010000L
+#define CLK_PWRMGT_CNTL__MC_INT_CNTL_MASK               0x00020000L
+#define CLK_PWRMGT_CNTL__MC_INT_CNTL                    0x00020000L
+#define CLK_PWRMGT_CNTL__MC_SWITCH_MASK                 0x00040000L
+#define CLK_PWRMGT_CNTL__MC_SWITCH                      0x00040000L
+#define CLK_PWRMGT_CNTL__DLL_READY_MASK                 0x00080000L
+#define CLK_PWRMGT_CNTL__DLL_READY                      0x00080000L
+#define CLK_PWRMGT_CNTL__DISP_PM_MASK                   0x00100000L
+#define CLK_PWRMGT_CNTL__DISP_PM                        0x00100000L
+#define CLK_PWRMGT_CNTL__DYN_STOP_MODE_MASK             0x00e00000L
+#define CLK_PWRMGT_CNTL__CG_NO1_DEBUG_MASK              0x3f000000L
+#define CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF_MASK          0x40000000L
+#define CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF               0x40000000L
+#define CLK_PWRMGT_CNTL__TVCLK_TURNOFF_MASK             0x80000000L
+#define CLK_PWRMGT_CNTL__TVCLK_TURNOFF                  0x80000000L
 
 // BUS_CNTL1
 #define BUS_CNTL1__PMI_IO_DISABLE_MASK                     0x00000001L
@@ -1876,53 +1876,63 @@
 #define MDLL_RDCKB__MRDCKB1_BP_SEL_MASK                    0x80000000L
 #define MDLL_RDCKB__MRDCKB1_BP_SEL                         0x80000000L
 
-#define pllVCLK_ECP_CNTL                            0x0008
-#define pllDISP_TEST_MACRO_RW_WRITE                 0x001A
-#define pllDISP_TEST_MACRO_RW_READ                  0x001B
-#define pllDISP_TEST_MACRO_RW_DATA                  0x001C
-#define pllDISP_TEST_MACRO_RW_CNTL                  0x001D
-#define pllPIXCLKS_CNTL                             0x002D
+#define MDLL_R300_RDCK__MRDCKA_SLEEP                       0x00000001L
+#define MDLL_R300_RDCK__MRDCKA_RESET                       0x00000002L
+#define MDLL_R300_RDCK__MRDCKB_SLEEP                       0x00000004L
+#define MDLL_R300_RDCK__MRDCKB_RESET                       0x00000008L
+#define MDLL_R300_RDCK__MRDCKC_SLEEP                       0x00000010L
+#define MDLL_R300_RDCK__MRDCKC_RESET                       0x00000020L
+#define MDLL_R300_RDCK__MRDCKD_SLEEP                       0x00000040L
+#define MDLL_R300_RDCK__MRDCKD_RESET                       0x00000080L
+
+#define pllCLK_PIN_CNTL                             0x0001
+#define pllPPLL_CNTL                                0x0002
+#define pllPPLL_REF_DIV                             0x0003
 #define pllPPLL_DIV_0                               0x0004
 #define pllPPLL_DIV_1                               0x0005
 #define pllPPLL_DIV_2                               0x0006
 #define pllPPLL_DIV_3                               0x0007
+#define pllVCLK_ECP_CNTL                            0x0008
 #define pllHTOTAL_CNTL                              0x0009
-#define pllPLL_TEST_CNTL_M6                         0x0013
-#define pllP2PLL_DIV_0                              0x002C
-#define pllHTOTAL2_CNTL                             0x002E
-#define pllCLK_PIN_CNTL                             0x0001
-#define pllPPLL_CNTL                                0x0002
-#define pllPPLL_REF_DIV                             0x0003
-#define pllSPLL_CNTL                                0x000C
-#define pllSPLL_AUX_CNTL                            0x0024
-#define pllSCLK_CNTL_M6                             0x000D
+#define pllM_SPLL_REF_FB_DIV                        0x000A
 #define pllAGP_PLL_CNTL                             0x000B
+#define pllSPLL_CNTL                                0x000C
+#define pllSCLK_CNTL                                0x000D
+#define pllMPLL_CNTL                                0x000E
+#define pllMDLL_CKO                                 0x000F
+#define pllMDLL_RDCKA                               0x0010
+#define pllMDLL_RDCKB                               0x0011
+#define pllMCLK_CNTL                                0x0012
+#define pllPLL_TEST_CNTL                            0x0013
+#define pllCLK_PWRMGT_CNTL                          0x0014
+#define pllPLL_PWRMGT_CNTL                          0x0015
+#define pllCG_TEST_MACRO_RW_WRITE                   0x0016
+#define pllCG_TEST_MACRO_RW_READ                    0x0017
+#define pllCG_TEST_MACRO_RW_DATA                    0x0018
+#define pllCG_TEST_MACRO_RW_CNTL                    0x0019
+#define pllDISP_TEST_MACRO_RW_WRITE                 0x001A
+#define pllDISP_TEST_MACRO_RW_READ                  0x001B
+#define pllDISP_TEST_MACRO_RW_DATA                  0x001C
+#define pllDISP_TEST_MACRO_RW_CNTL                  0x001D
+#define pllSCLK_CNTL2                               0x001E
+#define pllMCLK_MISC                                0x001F
 #define pllTV_PLL_FINE_CNTL                         0x0020
 #define pllTV_PLL_CNTL                              0x0021
 #define pllTV_PLL_CNTL1                             0x0022
 #define pllTV_DTO_INCREMENTS                        0x0023
+#define pllSPLL_AUX_CNTL                            0x0024
+#define pllMPLL_AUX_CNTL                            0x0025
 #define pllP2PLL_CNTL                               0x002A
 #define pllP2PLL_REF_DIV                            0x002B
+#define pllP2PLL_DIV_0                              0x002C
+#define pllPIXCLKS_CNTL                             0x002D
+#define pllHTOTAL2_CNTL                             0x002E
 #define pllSSPLL_CNTL                               0x0030
 #define pllSSPLL_REF_DIV                            0x0031
 #define pllSSPLL_DIV_0                              0x0032
 #define pllSS_INT_CNTL                              0x0033
 #define pllSS_TST_CNTL                              0x0034
 #define pllSCLK_MORE_CNTL                           0x0035
-#define pllCLK_PWRMGT_CNTL_M6                       0x0014
-#define pllPLL_PWRMGT_CNTL                          0x0015
-#define pllM_SPLL_REF_FB_DIV                        0x000A
-#define pllMPLL_CNTL                                0x000E
-#define pllMPLL_AUX_CNTL                            0x0025
-#define pllMDLL_CKO                                 0x000F
-#define pllMDLL_RDCKA                               0x0010
-#define pllMDLL_RDCKB                               0x0011
-#define pllMCLK_CNTL_M6                             0x0012
-#define pllMCLK_MISC                                0x001F
-#define pllCG_TEST_MACRO_RW_WRITE                   0x0016
-#define pllCG_TEST_MACRO_RW_READ                    0x0017
-#define pllCG_TEST_MACRO_RW_DATA                    0x0018
-#define pllCG_TEST_MACRO_RW_CNTL                    0x0019
 
 #define ixMC_PERF_CNTL                             0x0000
 #define ixMC_PERF_SEL                              0x0001
@@ -1945,7 +1955,29 @@
 #define ixMC_BIST_CTRL                             0x0012
 #define ixREG_COLLAR_WRITE                         0x0013
 #define ixREG_COLLAR_READ                          0x0014
-
+#define ixR300_MC_IMP_CNTL                         0x0018
+#define ixR300_MC_CHP_IO_CNTL_A0                   0x0019
+#define ixR300_MC_CHP_IO_CNTL_A1                   0x001a
+#define ixR300_MC_CHP_IO_CNTL_B0                   0x001b
+#define ixR300_MC_CHP_IO_CNTL_B1                   0x001c
+#define ixR300_MC_CHP_IO_CNTL_C0                   0x001d
+#define ixR300_MC_CHP_IO_CNTL_C1                   0x001e
+#define ixR300_MC_CHP_IO_CNTL_D0                   0x001f
+#define ixR300_MC_CHP_IO_CNTL_D1                   0x0020
+#define ixR300_MC_IMP_CNTL_0                       0x0021
+#define ixR300_MC_ELPIDA_CNTL                      0x0022
+#define ixR300_MC_CHP_IO_OE_CNTL_CD                0x0023
+#define ixR300_MC_READ_CNTL_CD                     0x0024
+#define ixR300_MC_MC_INIT_WR_LAT_TIMER             0x0025
+#define ixR300_MC_DEBUG_CNTL                       0x0026
+#define ixR300_MC_BIST_CNTL_0                      0x0028
+#define ixR300_MC_BIST_CNTL_1                      0x0029
+#define ixR300_MC_BIST_CNTL_2                      0x002a
+#define ixR300_MC_BIST_CNTL_3                      0x002b
+#define ixR300_MC_BIST_CNTL_4                      0x002c
+#define ixR300_MC_BIST_CNTL_5                      0x002d
+#define ixR300_MC_IMP_STATUS                       0x002e
+#define ixR300_MC_DLL_CNTL                         0x002f
 #define NB_TOM                                     0x15C

Index: linux-work/drivers/video/aty/radeon_base.c
===================================================================
--- linux-work.orig/drivers/video/aty/radeon_base.c	2005-01-17 13:24:18.000000000 +1100
+++ linux-work/drivers/video/aty/radeon_base.c	2005-01-17 13:49:30.043584848 +1100
@@ -1,5 +1,7 @@
+
 /*
- *	drivers/video/radeonfb.c
+ *	drivers/video/aty/radeon_base.c
+ *
  *	framebuffer driver for ATI Radeon chipset video boards
  *
  *	Copyright 2003	Ben. Herrenschmidt <[email-masked]>
@@ -75,7 +77,6 @@
 
 #ifdef CONFIG_PPC_OF
 
-#include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include "../macmodes.h"
 
@@ -150,8 +151,10 @@
 	CHIP_DEF(PCI_CHIP_RV250_Ig,	RV250,	CHIP_HAS_CRTC2),
 	/* Mobility 9100 IGP (U3) */
 	CHIP_DEF(PCI_CHIP_RS300_5835,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RS350_7835,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
 	/* 9100 IGP (A5) */
 	CHIP_DEF(PCI_CHIP_RS300_5834,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	CHIP_DEF(PCI_CHIP_RS350_7834,	RS300,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
 	/* Mobility 9200 (M9+) */
 	CHIP_DEF(PCI_CHIP_RV280_5C61,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
 	CHIP_DEF(PCI_CHIP_RV280_5C63,	RV280,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
@@ -194,6 +197,33 @@
 	CHIP_DEF(PCI_CHIP_R350_NI,	R350,	CHIP_HAS_CRTC2),
 	CHIP_DEF(PCI_CHIP_R360_NJ,	R350,	CHIP_HAS_CRTC2),
 	CHIP_DEF(PCI_CHIP_R350_NK,	R350,	CHIP_HAS_CRTC2),
+	/* Newer stuff */ 
+	CHIP_DEF(PCI_CHIP_RV380_3E50,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV380_3E54,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV380_3150,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV380_3154,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV370_5B60,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B62,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B64,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5B65,	RV380,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV370_5460,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV370_5464,	RV380,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_R420_JH,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JI,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JJ,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JK,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JL,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JM,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R420_JN,	R420,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_R420_JP,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UH,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UI,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UJ,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UK,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UQ,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UR,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_UT,	R420,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R423_5D57,	R420,	CHIP_HAS_CRTC2),
 	/* Original Radeon/7200 */
 	CHIP_DEF(PCI_CHIP_RADEON_QD,	RADEON,	0),
 	CHIP_DEF(PCI_CHIP_RADEON_QE,	RADEON,	0),
@@ -233,6 +263,7 @@
 static char *mode_option;
 static char *monitor_layout;
 static int noaccel = 0;
+static int default_dynclk = -2;
 static int nomodeset = 0;
 static int ignore_edid = 0;
 static int mirror = 0;
@@ -290,7 +321,8 @@
                                                                                                           
 	rom = pci_map_rom(dev, &rom_size);
 	if (!rom) {
-		printk(KERN_ERR "radeonfb: ROM failed to map\n");
+		printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
+		       pci_name(rinfo->pdev));
 		return -ENOMEM;
 	}
 	
@@ -298,8 +330,8 @@
 
 	/* Very simple test to make sure it appeared */
 	if (BIOS_IN16(0) != 0xaa55) {
-		printk(KERN_ERR "radeonfb: Invalid ROM signature %x should be 0xaa55\n",
-		       BIOS_IN16(0));
+		printk(KERN_ERR "radeonfb (%s): Invalid ROM signature %x should be"
+		       "0xaa55\n", pci_name(rinfo->pdev), BIOS_IN16(0));
 		goto failed;
 	}
 	/* Look for the PCI data to check the ROM type */
@@ -330,8 +362,8 @@
 	 * } pci_data_t;
 	 */
 	if (BIOS_IN32(dptr) !=  (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
-		printk(KERN_WARNING "radeonfb: PCI DATA signature in ROM incorrect: %08x\n",
-		       BIOS_IN32(dptr));
+		printk(KERN_WARNING "radeonfb (%s): PCI DATA signature in ROM"
+		       "incorrect: %08x\n", pci_name(rinfo->pdev), BIOS_IN32(dptr));
 		goto anyway;
 	}
 	rom_type = BIOS_IN8(dptr + 0x14);
@@ -398,14 +430,11 @@
  */
 static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo)
 {
-	struct device_node *dp;
+	struct device_node *dp = rinfo->of_node;
 	u32 *val;
 
-	dp = pci_device_to_OF_node(rinfo->pdev);
-	if (dp == NULL) {
-		printk(KERN_WARNING "radeonfb: Cannot match card to OF node !\n");
+	if (dp == NULL)
 		return -ENODEV;
-	}
 	val = (u32 *) get_property(dp, "ATY,RefCLK", NULL);
 	if (!val || !*val) {
 		printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");
@@ -488,20 +517,20 @@
 		denom = 1;
 		break;
 	case 1:
-		n = ((INPLL(X_MPLL_REF_FB_DIV) >> 16) & 0xff);
-		m = (INPLL(X_MPLL_REF_FB_DIV) & 0xff);
+		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 16) & 0xff);
+		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
 		num = 2*n;
 		denom = 2*m;
 		break;
 	case 2:
-		n = ((INPLL(X_MPLL_REF_FB_DIV) >> 8) & 0xff);
-		m = (INPLL(X_MPLL_REF_FB_DIV) & 0xff);
+		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff);
+		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);
 		num = 2*n;
 		denom = 2*m;
         break;
 	}
 
-	ppll_div_sel = INREG(CLOCK_CNTL_INDEX + 1) & 0x3;
+	ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
 
 	n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
 	m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -545,7 +574,7 @@
 		return -1;
 	}
 
-	tmp = INPLL(X_MPLL_REF_FB_DIV);
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
 	ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
 
 	Ns = (tmp & 0xff0000) >> 16;
@@ -625,7 +654,7 @@
 		rinfo->pll.ref_clk = 2700;
 		break;
 	}
-	rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;
+	rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;

 #ifdef CONFIG_PPC_OF
@@ -906,10 +935,11 @@
 }

-static int radeon_screen_blank (struct radeonfb_info *rinfo, int blank, int mode_switch)
+int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
 {
         u32 val;
 	u32 tmp_pix_clks;
+	int unblank = 0;
 
 	if (rinfo->lock_blank)
 		return 0;
@@ -920,9 +950,6 @@
         val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
                  CRTC_VSYNC_DIS);
         switch (blank) {
-	case FB_BLANK_UNBLANK:
-	case FB_BLANK_NORMAL:
-		break;
 	case FB_BLANK_VSYNC_SUSPEND:
 		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);
 		break;
@@ -933,42 +960,51 @@
 		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
 			CRTC_HSYNC_DIS);
 		break;
+	case FB_BLANK_NORMAL:
+		val |= CRTC_DISPLAY_DIS;
+		break;
+	case FB_BLANK_UNBLANK:
+	default:
+		unblank = 1;
         }
 	OUTREG(CRTC_EXT_CNTL, val);

 	switch (rinfo->mon1_type) {
 	case MT_DFP:
-		if (mode_switch)
-			break;
-		if (blank == FB_BLANK_UNBLANK ||
-		    blank == FB_BLANK_NORMAL)
+		if (unblank)
 			OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),
 				~(FP_FPON | FP_TMDS_EN));
-		else
+		else {	
+			if (mode_switch || blank == FB_BLANK_NORMAL)
+				break;
 			OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));
+		}
 		break;
 	case MT_LCD:
+		del_timer_sync(&rinfo->lvds_timer);
 		val = INREG(LVDS_GEN_CNTL);
-		if (blank == FB_BLANK_UNBLANK ||
-		    blank == FB_BLANK_NORMAL) {
+		if (unblank) {
 			u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON
-				| LVDS_ON | (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
+				| LVDS_EN | (rinfo->init_state.lvds_gen_cntl
+					     & (LVDS_DIGON | LVDS_BL_MOD_EN));
 			if ((val ^ target_val) == LVDS_DISPLAY_DIS)
 				OUTREG(LVDS_GEN_CNTL, target_val);
 			else if ((val ^ target_val) != 0) {
-				del_timer_sync(&rinfo->lvds_timer);
-				OUTREG(LVDS_GEN_CNTL, target_val & ~LVDS_ON);
+				OUTREG(LVDS_GEN_CNTL, target_val
+				       & ~(LVDS_ON | LVDS_BL_MOD_EN));
 				rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-				rinfo->init_state.lvds_gen_cntl |= target_val & LVDS_STATE_MASK;
+				rinfo->init_state.lvds_gen_cntl |=
+					target_val & LVDS_STATE_MASK;
 				if (mode_switch) {
-					msleep(rinfo->panel_info.pwr_delay);
+					radeon_msleep(rinfo->panel_info.pwr_delay);
 					OUTREG(LVDS_GEN_CNTL, target_val);
 				}
 				else {
 					rinfo->pending_lvds_gen_cntl = target_val;
 					mod_timer(&rinfo->lvds_timer,
-						jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+					   jiffies +
+					   msecs_to_jiffies(rinfo->panel_info.pwr_delay));
 				}
 			}
 		} else {
@@ -976,7 +1012,7 @@
 			OUTREG(LVDS_GEN_CNTL, val);
 
 			/* We don't do a full switch-off on a simple mode switch */
-			if (mode_switch)
+			if (mode_switch || blank == FB_BLANK_NORMAL)
 				break;
 
 			/* Asic bug, when turning off LVDS_ON, we have to make sure
@@ -985,8 +1021,16 @@
 			tmp_pix_clks = INPLL(PIXCLKS_CNTL);
 			if (rinfo->is_mobility || rinfo->is_IGP)
 				OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
-			val &= ~(LVDS_BLON | LVDS_ON);
+			val &= ~(LVDS_BL_MOD_EN);
+			OUTREG(LVDS_GEN_CNTL, val);
+			udelay(100);
+			val &= ~(LVDS_ON | LVDS_EN);
 			OUTREG(LVDS_GEN_CNTL, val);
+			val &= ~LVDS_DIGON;
+			rinfo->pending_lvds_gen_cntl = val;
+			mod_timer(&rinfo->lvds_timer,
+				  jiffies +
+				  msecs_to_jiffies(rinfo->panel_info.pwr_delay));
 			rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
 			rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;
 			if (rinfo->is_mobility || rinfo->is_IGP)
@@ -1003,16 +1047,14 @@
 	return (blank == FB_BLANK_NORMAL) ? -EINVAL : 0;
 }
 
-int radeonfb_blank (int blank, struct fb_info *info)
+static int radeonfb_blank (int blank, struct fb_info *info)
 {
         struct radeonfb_info *rinfo = info->par;
 
 	if (rinfo->asleep)
 		return 0;
 		
-	radeon_screen_blank(rinfo, blank, 0);
-
-	return 0;
+	return radeon_screen_blank(rinfo, blank, 0);
 }
 
 static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
@@ -1097,7 +1139,7 @@
 }

-static void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
+void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
 {
 	/* CRTC regs */
 	save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
@@ -1121,8 +1163,14 @@
 	save->fp_vert_stretch = INREG(FP_VERT_STRETCH);
 	save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
 	save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);
-	save->tmds_crc = INREG(TMDS_CRC);	save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
+	save->tmds_crc = INREG(TMDS_CRC);
+	save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);
 	save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
+
+	/* PLL regs */
+	save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
+	save->ppll_div_3 = INPLL(PPLL_DIV_3);
+	save->ppll_ref_div = INPLL(PPLL_REF_DIV);
 }

@@ -1134,19 +1182,22 @@
 
 	/* Workaround from XFree */
 	if (rinfo->is_mobility) {
-	        /* A temporal workaround for the occational blanking on certain laptop panels. 
-	           This appears to related to the PLL divider registers (fail to lock?).  
-		   It occurs even when all dividers are the same with their old settings.  
-	           In this case we really don't need to fiddle with PLL registers. 
-	           By doing this we can avoid the blanking problem with some panels.
-	        */
+	        /* A temporal workaround for the occational blanking on certain laptop
+		 * panels. This appears to related to the PLL divider registers
+		 * (fail to lock?). It occurs even when all dividers are the same
+		 * with their old settings. In this case we really don't need to
+		 * fiddle with PLL registers. By doing this we can avoid the blanking
+		 * problem with some panels.
+	         */
 		if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
 		    (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
 					  (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
-			/* We still have to force a switch to PPLL div 3 thanks to
+			/* We still have to force a switch to selected PPLL div thanks to
 			 * an XFree86 driver bug which will switch it away in some cases
 			 * even when using UseFDev */
-			OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK);
+			OUTREGP(CLOCK_CNTL_INDEX,
+				mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+				~PPLL_DIV_SEL_MASK);
             		return;
 		}
 	}
@@ -1159,8 +1210,10 @@
 		PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
 		~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
 
-	/* Switch to PPLL div 3 */
-	OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, ~PPLL_DIV_SEL_MASK);
+	/* Switch to selected PPLL divider */
+	OUTREGP(CLOCK_CNTL_INDEX,
+		mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+		~PPLL_DIV_SEL_MASK);
 
 	/* Set PPLL ref. div */
 	if (rinfo->family == CHIP_FAMILY_R300 ||
@@ -1205,7 +1258,7 @@
 		~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
 
 	/* We may want some locking ... oh well */
-       	msleep(5);
+       	radeon_msleep(5);
 
 	/* Switch back VCLK source to PPLL */
 	OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
@@ -1218,21 +1271,17 @@
 {
 	struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
 
-	radeon_fifo_wait(3);
+	radeon_engine_idle();
 
 	OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl);
-	if (rinfo->pending_pixclks_cntl) {
-		OUTPLL(PIXCLKS_CNTL, rinfo->pending_pixclks_cntl);
-		rinfo->pending_pixclks_cntl = 0;
-	}
 }
 
 /*
  * Apply a video mode. This will apply the whole register set, including
  * the PLL registers, to the card
  */
-static void radeon_write_mode (struct radeonfb_info *rinfo,
-                               struct radeon_regs *mode)
+void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
+			int regs_only)
 {
 	int i;
 	int primary_mon = PRIMARY_MONITOR(rinfo);
@@ -1240,10 +1289,8 @@
 	if (nomodeset)
 		return;
 
-	del_timer_sync(&rinfo->lvds_timer);
-
-	radeon_screen_blank(rinfo, FB_BLANK_POWERDOWN, 1);
-	msleep(100);
+	if (!regs_only)
+		radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
 
 	radeon_fifo_wait(31);
 	for (i=0; i<10; i++)
@@ -1285,7 +1332,8 @@
 		OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);
 	}
 
-	radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 1);
+	if (!regs_only)
+		radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);
 
 	radeon_fifo_wait(2);
 	OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
@@ -1396,6 +1444,16 @@
 	       rinfo->pll.ref_div, rinfo->pll.ref_clk,
 	       pll_output_freq);
 
+	/* If we fall through the bottom, try the "default value"
+	   given by the terminal post_div->bitvalue */
+	if ( !post_div->divider ) {
+		post_div = &post_divs[post_div->bitvalue];
+		pll_output_freq = post_div->divider * freq;
+	}
+	RTRACE("ref_div = %d, ref_clk = %d, output_freq = %d\n",
+	       rinfo->pll.ref_div, rinfo->pll.ref_clk,
+	       pll_output_freq);
+
 	fb_div = round_div(rinfo->pll.ref_div*pll_output_freq,
 				  rinfo->pll.ref_clk);
 	regs->ppll_ref_div = rinfo->pll.ref_div;
@@ -1406,22 +1464,27 @@
 	RTRACE("ppll_div_3 = 0x%x\n", regs->ppll_div_3);
 }
 
-int radeonfb_set_par(struct fb_info *info)
+static int radeonfb_set_par(struct fb_info *info)
 {
 	struct radeonfb_info *rinfo = info->par;
 	struct fb_var_screeninfo *mode = &info->var;
-	struct radeon_regs newmode;
+	struct radeon_regs *newmode;
 	int hTotal, vTotal, hSyncStart, hSyncEnd,
 	    hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
 	u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
 	u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
 	u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock;
 	int i, freq;
-        int format = 0;
+	int format = 0;
 	int nopllcalc = 0;
 	int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
 	int primary_mon = PRIMARY_MONITOR(rinfo);
 	int depth = var_to_depth(mode);
+	int use_rmx = 0;
+
+	newmode = kmalloc(sizeof(struct radeon_regs), GFP_KERNEL);
+	if (!newmode)
+		return -ENOMEM;
 
 	/* We always want engine to be idle on a mode switch, even
 	 * if we won't actually change the mode
@@ -1462,9 +1525,9 @@
 
 		if (rinfo->panel_info.use_bios_dividers) {
 			nopllcalc = 1;
-			newmode.ppll_div_3 = rinfo->panel_info.fbk_divider |
+			newmode->ppll_div_3 = rinfo->panel_info.fbk_divider |
 				(rinfo->panel_info.post_divider << 16);
-			newmode.ppll_ref_div = rinfo->panel_info.ref_divider;
+			newmode->ppll_ref_div = rinfo->panel_info.ref_divider;
 		}
 	}
 	dotClock = 1000000000 / pixClock;
@@ -1502,38 +1565,38 @@
 
 	hsync_start = hSyncStart - 8 + hsync_fudge;
 
-	newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
+	newmode->crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
 				(format << 8);
 
 	/* Clear auto-center etc... */
-	newmode.crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
-	newmode.crtc_more_cntl &= 0xfffffff0;
+	newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
+	newmode->crtc_more_cntl &= 0xfffffff0;
 	
 	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
-		newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
+		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
 		if (mirror)
-			newmode.crtc_ext_cntl |= CRTC_CRT_ON;
+			newmode->crtc_ext_cntl |= CRTC_CRT_ON;
 
-		newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
+		newmode->crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
 					   CRTC_INTERLACE_EN);
 	} else {
-		newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
+		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
 					CRTC_CRT_ON;
 	}
 
-	newmode.dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
+	newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
 			   DAC_8BIT_EN;
 
-	newmode.crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
+	newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |
 				     (((mode->xres / 8) - 1) << 16));
 
-	newmode.crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
+	newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |
 					(hsync_wid << 16) | (h_sync_pol << 23));
 
-	newmode.crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
+	newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) |
 				    ((mode->yres - 1) << 16);
 
-	newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
+	newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
 					 (vsync_wid << 16) | (v_sync_pol  << 23));
 
 	if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {
@@ -1542,18 +1605,18 @@
  				& ~(0x3f)) >> 6;
 
 		/* Then, re-multiply it to get the CRTC pitch */
-		newmode.crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
+		newmode->crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);
 	} else
-		newmode.crtc_pitch = (mode->xres_virtual >> 3);
+		newmode->crtc_pitch = (mode->xres_virtual >> 3);
 
-	newmode.crtc_pitch |= (newmode.crtc_pitch << 16);
+	newmode->crtc_pitch |= (newmode->crtc_pitch << 16);
 
 	/*
 	 * It looks like recent chips have a problem with SURFACE_CNTL,
 	 * setting SURF_TRANSLATION_DIS completely disables the
 	 * swapper as well, so we leave it unset now.
 	 */
-	newmode.surface_cntl = 0;
+	newmode->surface_cntl = 0;
 
 #if defined(__BIG_ENDIAN)
 
@@ -1563,28 +1626,28 @@
 	 */
 	switch (mode->bits_per_pixel) {
 		case 16:
-			newmode.surface_cntl |= NONSURF_AP0_SWP_16BPP;
-			newmode.surface_cntl |= NONSURF_AP1_SWP_16BPP;
+			newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP;
+			newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP;
 			break;
 		case 24:	
 		case 32:
-			newmode.surface_cntl |= NONSURF_AP0_SWP_32BPP;
-			newmode.surface_cntl |= NONSURF_AP1_SWP_32BPP;
+			newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP;
+			newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP;
 			break;
 	}
 #endif
 
 	/* Clear surface registers */
 	for (i=0; i<8; i++) {
-		newmode.surf_lower_bound[i] = 0;
-		newmode.surf_upper_bound[i] = 0x1f;
-		newmode.surf_info[i] = 0;
+		newmode->surf_lower_bound[i] = 0;
+		newmode->surf_upper_bound[i] = 0x1f;
+		newmode->surf_info[i] = 0;
 	}
 
 	RTRACE("h_total_disp = 0x%x\t   hsync_strt_wid = 0x%x\n",
-		newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid);
+		newmode->crtc_h_total_disp, newmode->crtc_h_sync_strt_wid);
 	RTRACE("v_total_disp = 0x%x\t   vsync_strt_wid = 0x%x\n",
-		newmode.crtc_v_total_disp, newmode.crtc_v_sync_strt_wid);
+		newmode->crtc_v_total_disp, newmode->crtc_v_sync_strt_wid);
 
 	rinfo->bpp = mode->bits_per_pixel;
 	rinfo->depth = depth;
@@ -1592,10 +1655,14 @@
 	RTRACE("pixclock = %lu\n", (unsigned long)pixClock);
 	RTRACE("freq = %lu\n", (unsigned long)freq);
 
+	/* We use PPLL_DIV_3 */
+	newmode->clk_cntl_index = 0x300;
+
+	/* Calculate PPLL value if necessary */
 	if (!nopllcalc)
-		radeon_calc_pll_regs(rinfo, &newmode, freq);
+		radeon_calc_pll_regs(rinfo, newmode, freq);
 
-	newmode.vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
+	newmode->vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;
 
 	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
 		unsigned int hRatio, vRatio;
@@ -1605,35 +1672,37 @@
 		if (mode->yres > rinfo->panel_info.yres)
 			mode->yres = rinfo->panel_info.yres;
 
-		newmode.fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1)
+		newmode->fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1)
 					   << HORZ_PANEL_SHIFT);
-		newmode.fp_vert_stretch = ((rinfo->panel_info.yres - 1)
+		newmode->fp_vert_stretch = ((rinfo->panel_info.yres - 1)
 					   << VERT_PANEL_SHIFT);
 
 		if (mode->xres != rinfo->panel_info.xres) {
 			hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,
 					   rinfo->panel_info.xres);
-			newmode.fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
-						   (newmode.fp_horz_stretch &
+			newmode->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
+						   (newmode->fp_horz_stretch &
 						    (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
 						     HORZ_AUTO_RATIO_INC)));
-			newmode.fp_horz_stretch |= (HORZ_STRETCH_BLEND |
+			newmode->fp_horz_stretch |= (HORZ_STRETCH_BLEND |
 						    HORZ_STRETCH_ENABLE);
+			use_rmx = 1;
 		}
-		newmode.fp_horz_stretch &= ~HORZ_AUTO_RATIO;
+		newmode->fp_horz_stretch &= ~HORZ_AUTO_RATIO;
 
 		if (mode->yres != rinfo->panel_info.yres) {
 			vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,
 					   rinfo->panel_info.yres);
-			newmode.fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
-						   (newmode.fp_vert_stretch &
+			newmode->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
+						   (newmode->fp_vert_stretch &
 						   (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
-			newmode.fp_vert_stretch |= (VERT_STRETCH_BLEND |
+			newmode->fp_vert_stretch |= (VERT_STRETCH_BLEND |
 						    VERT_STRETCH_ENABLE);
+			use_rmx = 1;
 		}
-		newmode.fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
+		newmode->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
 
-		newmode.fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
+		newmode->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
 				       ~(FP_SEL_CRTC2 |
 					 FP_RMX_HVSYNC_CONTROL_EN |
 					 FP_DFP_SYNC_SEL |
@@ -1643,46 +1712,56 @@
 					 FP_CRTC_USE_SHADOW_VEND |
 					 FP_CRT_SYNC_ALT));
 
-		newmode.fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |
-					FP_CRTC_DONT_SHADOW_HEND);
-
-		newmode.lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
-		newmode.lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
-		newmode.tmds_crc = rinfo->init_state.tmds_crc;
-		newmode.tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
+		newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |
+					FP_CRTC_DONT_SHADOW_HEND |
+					FP_PANEL_FORMAT);
+
+		if (IS_R300_VARIANT(rinfo) ||
+		    (rinfo->family == CHIP_FAMILY_R200)) {
+			newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+			if (use_rmx)
+				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
+			else
+				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
+		} else 
+			newmode->fp_gen_cntl |= FP_SEL_CRTC1;
+
+		newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl;
+		newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl;
+		newmode->tmds_crc = rinfo->init_state.tmds_crc;
+		newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;
 
 		if (primary_mon == MT_LCD) {
-			newmode.lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
-			newmode.fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
+			newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
+			newmode->fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
 		} else {
 			/* DFP */
-			newmode.fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
-			newmode.tmds_transmitter_cntl = (TMDS_RAN_PAT_RST | TMDS_ICHCSEL) &
+			newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
+			newmode->tmds_transmitter_cntl = (TMDS_RAN_PAT_RST | TMDS_ICHCSEL) &
 							 ~(TMDS_PLLRST);
 			/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
-			if ((rinfo->family == CHIP_FAMILY_R300) ||
-			    (rinfo->family == CHIP_FAMILY_R350) ||
-			    (rinfo->family == CHIP_FAMILY_RV350) ||
+			if (IS_R300_VARIANT(rinfo) ||
 			    (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
-				newmode.tmds_transmitter_cntl &= ~TMDS_PLL_EN;
+				newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN;
 			else
-				newmode.tmds_transmitter_cntl |= TMDS_PLL_EN;
-			newmode.crtc_ext_cntl &= ~CRTC_CRT_ON;
+				newmode->tmds_transmitter_cntl |= TMDS_PLL_EN;
+			newmode->crtc_ext_cntl &= ~CRTC_CRT_ON;
 		}
 
-		newmode.fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) |
+		newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) |
 				(((mode->xres / 8) - 1) << 16));
-		newmode.fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) |
+		newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) |
 				((mode->yres - 1) << 16);
-		newmode.fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) |
+		newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) |
 				(hsync_wid << 16) | (h_sync_pol << 23));
-		newmode.fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) |
+		newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) |
 				(vsync_wid << 16) | (v_sync_pol  << 23));
 	}
 
 	/* do it! */
 	if (!rinfo->asleep) {
-		radeon_write_mode (rinfo, &newmode);
+		memcpy(&rinfo->state, newmode, sizeof(*newmode));
+		radeon_write_mode (rinfo, newmode, 0);
 		/* (re)initialize the engine */
 		if (!(info->flags & FBINFO_HWACCEL_DISABLED))
 			radeonfb_engine_init (rinfo);
@@ -1702,6 +1781,7 @@
 			     rinfo->depth, info->fix.line_length);
 #endif
 
+	kfree(newmode);
 	return 0;
 }
 
@@ -1811,12 +1891,14 @@
 	if (on && (level > BACKLIGHT_OFF)) {
 		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
 		if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
-			lvds_gen_cntl |= LVDS_BLON /* | LVDS_EN | LVDS_DIGON */;
+			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 |= (conv_table[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));
@@ -1836,13 +1918,18 @@
 		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_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
 		lvds_gen_cntl |= (conv_table[0] <<
 				  LVDS_BL_MOD_LEVEL_SHIFT);
 		lvds_gen_cntl |= LVDS_DISPLAY_DIS;
 		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		lvds_gen_cntl &= ~(LVDS_ON | LVDS_BLON /* | LVDS_EN | LVDS_DIGON */);
+		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);
 	}
@@ -1872,7 +1959,7 @@
  * local (0xe0000000 for now) that will be changed by XFree/DRI anyway
  */
 #ifdef CONFIG_PPC_OF
-#undef SET_MC_FB_FROM_APERTURE
+#define SET_MC_FB_FROM_APERTURE
 static void fixup_memory_mappings(struct radeonfb_info *rinfo)
 {
 	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
@@ -1925,10 +2012,12 @@
 	OUTREG(DISPLAY_BASE_ADDR, aper_base);
 	if (rinfo->has_CRTC2)
 		OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);
+	OUTREG(OV0_BASE_ADDR, aper_base);
 #else
 	OUTREG(DISPLAY_BASE_ADDR, 0);
 	if (rinfo->has_CRTC2)
 		OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);
+	OUTREG(OV0_BASE_ADDR, 0);
 #endif
 	mdelay(100);
 
@@ -1946,6 +2035,100 @@
 #endif /* CONFIG_PPC_OF */

+static void radeon_identify_vram(struct radeonfb_info *rinfo)
+{
+	u32 tmp;
+
+	/* framebuffer size */
+        if ((rinfo->family == CHIP_FAMILY_RS100) ||
+            (rinfo->family == CHIP_FAMILY_RS200) ||
+            (rinfo->family == CHIP_FAMILY_RS300)) {
+          u32 tom = INREG(NB_TOM);
+          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+ 
+ 		radeon_fifo_wait(6);
+          OUTREG(MC_FB_LOCATION, tom);
+          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
+ 
+          /* This is supposed to fix the crtc2 noise problem. */
+          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
+ 
+          if ((rinfo->family == CHIP_FAMILY_RS100) ||
+              (rinfo->family == CHIP_FAMILY_RS200)) {
+             /* This is to workaround the asic bug for RMX, some versions
+                of BIOS dosen't have this register initialized correctly.
+             */
+             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
+                     ~CRTC_H_CUTOFF_ACTIVE_EN);
+          }
+        } else {
+          tmp = INREG(CONFIG_MEMSIZE);
+        }
+
+	/* mem size is bits [28:0], mask off the rest */
+	rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
+
+	/*
+	 * Hack to get around some busted production M6's
+	 * reporting no ram
+	 */
+	if (rinfo->video_ram == 0) {
+		switch (rinfo->pdev->device) {
+	       	case PCI_CHIP_RADEON_LY:
+		case PCI_CHIP_RADEON_LZ:
+	       		rinfo->video_ram = 8192 * 1024;
+	       		break;
+	       	default:
+	       		break;
+		}
+	}
+
+
+	/*
+	 * Now try to identify VRAM type
+	 */
+	if (rinfo->is_IGP || (rinfo->family >= CHIP_FAMILY_R300) ||
+	    (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
+		rinfo->vram_ddr = 1;
+	else
+		rinfo->vram_ddr = 0;
+
+	tmp = INREG(MEM_CNTL);
+	if (IS_R300_VARIANT(rinfo)) {
+		tmp &=  R300_MEM_NUM_CHANNELS_MASK;
+		switch (tmp) {
+		case 0:  rinfo->vram_width = 64; break;
+		case 1:  rinfo->vram_width = 128; break;
+		case 2:  rinfo->vram_width = 256; break;
+		default: rinfo->vram_width = 128; break;
+		}
+	} else if ((rinfo->family == CHIP_FAMILY_RV100) ||
+		   (rinfo->family == CHIP_FAMILY_RS100) ||
+		   (rinfo->family == CHIP_FAMILY_RS200)){
+		if (tmp & RV100_MEM_HALF_MODE)
+			rinfo->vram_width = 32;
+		else
+			rinfo->vram_width = 64;
+	} else {
+		if (tmp & MEM_NUM_CHANNELS_MASK)
+			rinfo->vram_width = 128;
+		else
+			rinfo->vram_width = 64;
+	}
+
+	/* This may not be correct, as some cards can have half of channel disabled 
+	 * ToDo: identify these cases
+	 */
+
+	RTRACE("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
+	       pci_name(rinfo->pdev),
+	       rinfo->video_ram / 1024,
+	       rinfo->vram_ddr ? "DDR" : "SDRAM",
+	       rinfo->vram_width);
+}
+
 /*
  * Sysfs
  */
@@ -2011,7 +2194,6 @@
 {
 	struct fb_info *info;
 	struct radeonfb_info *rinfo;
-	u32 tmp;
 	int ret;
 
 	RTRACE("radeonfb_pci_register BEGIN\n");
@@ -2019,13 +2201,15 @@
 	/* Enable device in PCI config */
 	ret = pci_enable_device(pdev);
 	if (ret < 0) {
-		printk(KERN_ERR "radeonfb: Cannot enable PCI device\n");
+		printk(KERN_ERR "radeonfb (%s): Cannot enable PCI device\n",
+		       pci_name(pdev));
 		goto err_out;
 	}
 
 	info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
 	if (!info) {
-		printk (KERN_ERR "radeonfb: could not allocate memory\n");
+		printk (KERN_ERR "radeonfb (%s): could not allocate memory\n",
+			pci_name(pdev));
 		ret = -ENOMEM;
 		goto err_disable;
 	}
@@ -2054,121 +2238,39 @@
 	/* request the mem regions */
 	ret = pci_request_regions(pdev, "radeonfb");
 	if (ret < 0) {
-		printk( KERN_ERR "radeonfb: cannot reserve PCI regions."
-			"  Someone already got them?\n");
+		printk( KERN_ERR "radeonfb (%s): cannot reserve PCI regions."
+			"  Someone already got them?\n", pci_name(rinfo->pdev));
 		goto err_release_fb;
 	}
 
 	/* map the regions */
 	rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
 	if (!rinfo->mmio_base) {
-		printk(KERN_ERR "radeonfb: cannot map MMIO\n");
+		printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n", pci_name(rinfo->pdev));
 		ret = -EIO;
 		goto err_release_pci;
 	}
 
+	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+
+#ifdef CONFIG_PPC_OF
+	/* On PPC, we obtain the OF device-node pointer to the firmware
+	 * data for this chip
+	 */
+	rinfo->of_node = pci_device_to_OF_node(pdev);
+	if (rinfo->of_node == NULL)
+		printk(KERN_WARNING "radeonfb (%s): Cannot match card to OF node !\n",
+		       pci_name(rinfo->pdev));
+
 	/* On PPC, the firmware sets up a memory mapping that tends
 	 * to cause lockups when enabling the engine. We reconfigure
 	 * the card internal memory mappings properly
 	 */
-#ifdef CONFIG_PPC_OF
 	fixup_memory_mappings(rinfo);
-#else	
-	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
 #endif /* CONFIG_PPC_OF */
 
-	/* framebuffer size */
-        if ((rinfo->family == CHIP_FAMILY_RS100) ||
-            (rinfo->family == CHIP_FAMILY_RS200) ||
-            (rinfo->family == CHIP_FAMILY_RS300)) {
-          u32 tom = INREG(NB_TOM);
-          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
- 
- 		radeon_fifo_wait(6);
-          OUTREG(MC_FB_LOCATION, tom);
-          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
- 
-          /* This is supposed to fix the crtc2 noise problem. */
-          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
- 
-          if ((rinfo->family == CHIP_FAMILY_RS100) ||
-              (rinfo->family == CHIP_FAMILY_RS200)) {
-             /* This is to workaround the asic bug for RMX, some versions
-                of BIOS dosen't have this register initialized correctly.
-             */
-             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
-                     ~CRTC_H_CUTOFF_ACTIVE_EN);
-          }
-        } else {
-          tmp = INREG(CONFIG_MEMSIZE);
-        }
-
-	/* mem size is bits [28:0], mask off the rest */
-	rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
-
-	/* ram type */
-	tmp = INREG(MEM_SDRAM_MODE_REG);
-	switch ((MEM_CFG_TYPE & tmp) >> 30) {
-       	case 0:
-       		/* SDR SGRAM (2:1) */
-       		strcpy(rinfo->ram_type, "SDR SGRAM");
-       		rinfo->ram.ml = 4;
-       		rinfo->ram.mb = 4;
-       		rinfo->ram.trcd = 1;
-       		rinfo->ram.trp = 2;
-       		rinfo->ram.twr = 1;
-       		rinfo->ram.cl = 2;
-       		rinfo->ram.loop_latency = 16;
-       		rinfo->ram.rloop = 16;
-       		break;
-       	case 1:
-       		/* DDR SGRAM */
-       		strcpy(rinfo->ram_type, "DDR SGRAM");
-       		rinfo->ram.ml = 4;
-       		rinfo->ram.mb = 4;
-       		rinfo->ram.trcd = 3;
-       		rinfo->ram.trp = 3;
-       		rinfo->ram.twr = 2;
-       		rinfo->ram.cl = 3;
-       		rinfo->ram.tr2w = 1;
-       		rinfo->ram.loop_latency = 16;
-       		rinfo->ram.rloop = 16;
-		break;
-       	default:
-       		/* 64-bit SDR SGRAM */
-       		strcpy(rinfo->ram_type, "SDR SGRAM 64");
-       		rinfo->ram.ml = 4;
-       		rinfo->ram.mb = 8;
-       		rinfo->ram.trcd = 3;
-       		rinfo->ram.trp = 3;
-       		rinfo->ram.twr = 1;
-       		rinfo->ram.cl = 3;
-       		rinfo->ram.tr2w = 1;
-       		rinfo->ram.loop_latency = 17;
-       		rinfo->ram.rloop = 17;
-		break;
-	}
-
-	/*
-	 * Hack to get around some busted production M6's
-	 * reporting no ram
-	 */
-	if (rinfo->video_ram == 0) {
-		switch (pdev->device) {
-	       	case PCI_CHIP_RADEON_LY:
-		case PCI_CHIP_RADEON_LZ:
-	       		rinfo->video_ram = 8192 * 1024;
-	       		break;
-	       	default:
-			printk (KERN_ERR "radeonfb: no video RAM reported\n");
-			ret = -ENXIO;
-			goto err_unmap_rom;
-		}
-	}
-
-	RTRACE("radeonfb: probed %s %ldk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
+	/* Get VRAM size and type */
+	radeon_identify_vram(rinfo);
 
 	rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
 
@@ -2181,12 +2283,13 @@
 	if (rinfo->fb_base)
 		memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
 	else {
-		printk (KERN_ERR "radeonfb: cannot map FB\n");
+		printk (KERN_ERR "radeonfb (%s): cannot map FB\n", pci_name(rinfo->pdev));
 		ret = -EIO;
 		goto err_unmap_rom;
 	}
 
-	RTRACE("radeonfb: mapped %ldk videoram\n", rinfo->mapped_vram/1024);
+	RTRACE("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
+	       rinfo->mapped_vram/1024);
 
 	/*
 	 * Check for required workaround for PLL accesses
@@ -2253,21 +2356,22 @@
 	 * so we can restore this upon __exit
 	 */
 	radeon_save_state (rinfo, &rinfo->init_state);
+	memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs));
 
 	pci_set_drvdata(pdev, info);
 
-	/* Enable PM on mobility chips */
-	if (rinfo->is_mobility) {
-		/* Find PM registers in config space */
-		rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
-		/* Enable dynamic PM of chip clocks */
-		radeon_pm_enable_dynamic_mode(rinfo);
-		printk("radeonfb: Power Management enabled for Mobility chipsets\n");
-	}
+	/* Setup Power Management capabilities */
+	if (default_dynclk < -1) {
+		/* -2 is special: means  ON on mobility chips and do not change on others */
+		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
+	} else
+		radeonfb_pm_init(rinfo, default_dynclk);
 
+	/* Register with fbdev layer */
 	ret = register_framebuffer(info);
 	if (ret < 0) {
-		printk (KERN_ERR "radeonfb: could not register framebuffer\n");
+		printk (KERN_ERR "radeonfb (%s): could not register framebuffer\n",
+			pci_name(rinfo->pdev));
 		goto err_unmap_fb;
 	}
 
@@ -2286,8 +2390,7 @@
 	}
 #endif
 
-	printk ("radeonfb: %s %s %ld MB\n", rinfo->name, rinfo->ram_type,
-		(rinfo->video_ram/(1024*1024)));
+	printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
 
 	if (rinfo->bios_seg)
 		radeon_unmap_ROM(rinfo, pdev);
@@ -2330,12 +2433,14 @@
         if (!rinfo)
                 return;
  
+	radeonfb_pm_exit(rinfo);
+
 	/* restore original state
 	 * 
 	 * Doesn't quite work yet, possibly because of the PPC hacking
 	 * I do on startup, disable for now. --BenH
 	 */
-        radeon_write_mode (rinfo, &rinfo->init_state);
+        radeon_write_mode (rinfo, &rinfo->init_state, 1);
  
 	del_timer_sync(&rinfo->lvds_timer);
 
@@ -2442,6 +2547,8 @@
 MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
 MODULE_LICENSE("GPL");
 module_param(noaccel, bool, 0);
+module_param(default_dynclk, int, -2);
+MODULE_PARM_DESC(default_dynclk, "int: -2=enable on mobility only,-1=do not change,0=off,1=on");
 MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
 module_param(nomodeset, bool, 0);
 MODULE_PARM_DESC(nomodeset, "bool: disable actual setting of video mode");
Index: linux-work/drivers/video/aty/radeon_pm.c
===================================================================
--- linux-work.orig/drivers/video/aty/radeon_pm.c	2004-11-22 11:50:27.000000000 +1100
+++ linux-work/drivers/video/aty/radeon_pm.c	2005-01-17 13:49:30.069580896 +1100
@@ -1,207 +1,449 @@
+/*
+ *	drivers/video/aty/radeon_pm.c
+ *
+ *	Copyright 2003,2004 Ben. Herrenschmidt <[email-masked]>
+ *	Copyright 2004 Paul Mackerras <[email-masked]>
+ *
+ *	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>
 
-/*
- * Currently, only PowerMac do D2 state
- */
-#define CONFIG_RADEON_HAS_D2	CONFIG_PPC_PMAC
-
-#ifdef CONFIG_RADEON_HAS_D2
-/*
- * On PowerMac, we assume any mobility chip based machine does D2
- */
 #ifdef CONFIG_PPC_PMAC
-static inline int radeon_suspend_to_d2(struct radeonfb_info *rinfo, u32 state)
-{
-	return rinfo->is_mobility;
-}
-#else
-static inline int radeon_suspend_to_d2(struct radeonfb_info *rinfo, u32 state)
-{
-	return 0;
-}
+#include <asm/processor.h>
+#include <asm/prom.h>
+#include <asm/pmac_feature.h>
 #endif
 
-#endif /* CONFIG_RADEON_HAS_D2 */
-
-/*
- * Radeon M6, M7 and M9 Power Management code. This code currently
- * only supports the mobile chips in D2 mode, that is typically what
- * is used on Apple laptops, it's based from some informations provided
- * by ATI along with hours of tracing of MacOS drivers.
- * 
- * New version of this code almost totally rewritten by ATI, many thanks
- * for their support.
- */
+#include "ati_ids.h"
 
 void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
 {
+	u32 tmp;
 
-	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)
+	/* 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;
-	if (rinfo->family > CHIP_FAMILY_RV250)
+	}
+	/* 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 */
-	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);
+	tmp = INPLL(pllSCLK_CNTL);
+	tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_E2);
 
-	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);
+	/* 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);
+		OUTREG(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);
+	}
 
-	/* 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);
+	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);
 }
 
 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;
+	u32 tmp;
 
-	/* Mobility chips only, untested on M9+/M10/11 */
-	if (!rinfo->is_mobility)
+	/* 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;
-	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);
+	/* 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;
+	}
 
-	/* Enable Dyanmic mode for SCLK */
+	/* 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);
+	}
 
-	sclk_cntl = INPLL( pllSCLK_CNTL_M6);	
-	sclk_cntl &= SCLK_CNTL_M6__SCLK_SRC_SEL_MASK;
-	sclk_cntl |= SCLK_CNTL_M6__FORCE_VIP;		
+	/* Others */
 
-	OUTPLL( pllSCLK_CNTL_M6, sclk_cntl);
+	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;	
 
-	sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
-	sclk_more_cntl &= ~(SCLK_MORE_CNTL__FORCE_DISPREGS);
-				                    
-	OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl);
+	/*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);
+	}
 	
-	/* 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;
+	/* 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;
+		OUTREG(pllPLL_PWRMGT_CNTL, tmp);
+		radeon_msleep(15);
+	}
 
-	OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl);
+	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);
 		
-		
-	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);
+	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);
 
-
-	/* 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|
+		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, mclk_misc);
+			MCLK_MISC__IO_MCLK_DYN_ENABLE;
+		OUTPLL(pllMCLK_MISC, tmp);
+		radeon_msleep(15);
+	}
+#endif /* CONFIG_PPC_OF */
 }
 
 #ifdef CONFIG_PM
@@ -218,7 +460,7 @@
 	return INREG( MC_IND_DATA);
 }
 
-static void radeon_pm_save_regs(struct radeonfb_info *rinfo)
+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);
@@ -233,7 +475,6 @@
 	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);
@@ -256,6 +497,93 @@
 	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)
@@ -270,12 +598,15 @@
 	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]);
@@ -287,10 +618,8 @@
 	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
 	OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]);
 	OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]);
-
-	// wait VBL before that one  ?
 	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]);
@@ -319,30 +648,32 @@
 
 static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
 {
-	/* we use __INPLL and _OUTPLL and do the locking ourselves... */
-	unsigned long flags;
-	spin_lock_irqsave(&rinfo->reg_lock, flags);
 	/* Set v2clk to 65MHz */
-  	__OUTPLL(pllPIXCLKS_CNTL,
-  		__INPLL(rinfo, pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
+	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);
-	__OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W);
+		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(rinfo, pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
+	OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP);
 	mdelay(1);
 
-	__OUTPLL(pllP2PLL_CNTL,
-		__INPLL(rinfo, pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
+	OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET);
 	mdelay( 1);
 
-  	__OUTPLL(pllPIXCLKS_CNTL,
-  		(__INPLL(rinfo, pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
+  	OUTPLL(pllPIXCLKS_CNTL,
+  		(INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK)
   		| (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT));
 	mdelay( 1);	
-	spin_unlock_irqrestore(&rinfo->reg_lock, flags);
 }
 
 static void radeon_pm_low_current(struct radeonfb_info *rinfo)
@@ -350,8 +681,12 @@
 	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);
+	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);
@@ -400,35 +735,42 @@
 	u32 tmp;
 	
 	/* 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 = 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_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__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_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;
+			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_M6, sclk_cntl);
+	OUTPLL( pllSCLK_CNTL, sclk_cntl);
 
 	sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL);
 	sclk_more_cntl |= 	SCLK_MORE_CNTL__FORCE_DISPREGS |
@@ -438,18 +780,19 @@
 	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
+	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_M6, mclk_cntl);
+    	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__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);
 	
@@ -480,26 +823,27 @@
 						
 	OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl);
 	
-	clk_pwrmgt_cntl	 = INPLL( pllCLK_PWRMGT_CNTL_M6);
+	clk_pwrmgt_cntl	 = INPLL( pllCLK_PWRMGT_CNTL);
 	
-	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__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_M6__GLOBAL_PMAN_EN | CLK_PWRMGT_CNTL_M6__DISP_PM;
+	clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN 
+		| CLK_PWRMGT_CNTL__DISP_PM;
 	
-	OUTPLL( pllCLK_PWRMGT_CNTL_M6, clk_pwrmgt_cntl);	
+	OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl);	
 	
 	clk_pin_cntl = INPLL( pllCLK_PIN_CNTL);
 	
@@ -510,12 +854,19 @@
 	OUTPLL( pllMCLK_MISC, tmp);
 	
 	/* AGP PLL control */
-	OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
+	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(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));
+	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;	
@@ -547,16 +898,16 @@
 				DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS|
 				DISP_MISC_CNTL__SOFT_RESET_TV);
 	
-	OUTREG(DISP_MISC_CNTL, disp_mis_cntl);					
+	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__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|
@@ -571,27 +922,29 @@
 	
 	OUTREG(DISP_PWR_MAN, disp_pwr_man);					
 							
-	clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL_M6);
+	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_M6__DISP_PM;
+	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);							
-						
+	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( 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);
+	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);				   
 
@@ -601,17 +954,15 @@
 {
 	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));
-
-	/* Wassup ? This doesn't seem to be defined, let's hope we are ok this way --BenH */
-#ifdef MCLK_YCLK_SYNC_ENABLE
-	mc_chp_io_cntl_a1 |= (2<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT);
-	mc_chp_io_cntl_b1 |= (2<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT);
-#endif
+	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);
@@ -619,25 +970,70 @@
 	mdelay( 1);
 }
 
-static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value, u8 delay_required)
+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;
+	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 == 1)
-		while( (INREG( MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A | MC_STATUS__MEM_PWRUP_COMPL_B) ) == 0 )
-			{ }; 	
+	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;
+	}
 }

@@ -646,126 +1042,274 @@
 #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;
+	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,   	DLL_CKO_Value);
-	OUTPLL(pllMDLL_RDCKA,  	DLL_CKA_Value);
-	OUTPLL(pllMDLL_RDCKB,	DLL_CKB_Value);
-
-	mdelay( DLL_RESET_DELAY);
+	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);
 
-	/* 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);  		
 
+#undef DLL_RESET_DELAY 
+#undef DLL_SLEEP_DELAY
+}
 
-	/* Channel B */
+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;
 
-	/* 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);  		
+#define DLL_RESET_DELAY 	5
+#define DLL_SLEEP_DELAY		1
 
-	/* Power Up */
-	DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB0_SLEEP);
-	OUTPLL(pllMDLL_RDCKB,   DLL_CKB_Value);
-	mdelay( DLL_SLEEP_DELAY);  		
+	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_CKB_Value &= ~(MDLL_RDCKB__MRDCKB0_RESET);
-	OUTPLL(pllMDLL_RDCKB,   DLL_CKB_Value);
-	mdelay( DLL_RESET_DELAY);  		
+	dll_value = INPLL(pllMDLL_RDCKA);
 
 	/* Power Up */
-	DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB1_SLEEP);
-	OUTPLL(pllMDLL_RDCKB,   DLL_CKB_Value);
+	dll_value &= ~(dll_sleep_mask);
+	OUTPLL(pllMDLL_RDCKA, dll_value);
 	mdelay( DLL_SLEEP_DELAY);  		
 
-	DLL_CKB_Value &= ~(MDLL_RDCKB__MRDCKB1_RESET);
-	OUTPLL(pllMDLL_RDCKB,   DLL_CKB_Value);
+	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;
+	u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl,
+		fp_gen_cntl, fp2_gen_cntl;
  
 	crtcGenCntl  = INREG( CRTC_GEN_CNTL);
 	crtcGenCntl2 = INREG( CRTC2_GEN_CNTL);
 
-	memRefreshCntl 	= INREG( MEM_REFRESH_CNTL);
 	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_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) );
   
-	/* Disable refresh */
-	OUTREG( MEM_REFRESH_CNTL, memRefreshCntl | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+	/* This is the code for the Aluminium PowerBooks M10 */
+	if (rinfo->family == CHIP_FAMILY_RV350) {
+		u32 sdram_mode_reg = rinfo->save_regs[35];
+		static 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 };
+
+		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 = (u32 *)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); // Init  Not Complete
+		/* 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);
+		/* DLL */
+		radeon_pm_enable_dll(rinfo);
 
-	// MLCK /YCLK sync 
-	radeon_pm_yclk_mclk_sync(rinfo);
+		/* MLCK / YCLK sync */
+		radeon_pm_yclk_mclk_sync(rinfo);
 
-       	/* M6, M7 and M9 so far ... */
-	if (rinfo->is_mobility && rinfo->family <= CHIP_FAMILY_RV250) {
+		/* 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); 
-	}	
 
-	OUTREG( MEM_SDRAM_MODE_REG,
-		INREG( MEM_SDRAM_MODE_REG) |  MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); // Init Complete
+		/* 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) {
 
-	OUTREG( MEM_REFRESH_CNTL, 	memRefreshCntl);
+		/* 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);
@@ -777,10 +1321,1076 @@
 	mdelay( 15);
 }
 
+#ifdef CONFIG_PPC_OF
+
+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);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+
+	/* 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);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+
+	/* 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);
+	OUTREG8(CLOCK_CNTL_DATA, 0);
+
+	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);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+
+	/* Not sure what was intended here ... */
+	tmp = INREG(CLOCK_CNTL_INDEX);
+	OUTREG(CLOCK_CNTL_INDEX, tmp);
+
+	/* 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);
+
+	tmp = INPLL(pllPPLL_CNTL);
+	OUTPLL(pllPPLL_CNTL, tmp & ~0x1);
+	mdelay(5);
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp | 3);
+	mdelay(5);
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp | 3);
+	mdelay(5);
+
+	/* Switch pixel clock to firmware default div 0 */
+	OUTREG8(CLOCK_CNTL_INDEX+1, 0);
+}
+
+static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
+{
+	OUTREG(MC_CNTL, rinfo->save_regs[46]);
+	OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]);
+	OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]);
+	OUTREG(MEM_SDRAM_MODE_REG,
+	       rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+	OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]);
+	OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]);
+	OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]);
+	OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]);
+	OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]);
+	OUTREG(MC_DEBUG, rinfo->save_regs[53]);
+
+	OUTMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER, rinfo->save_regs[58]);
+	OUTMC(rinfo, ixR300_MC_IMP_CNTL, rinfo->save_regs[59]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0, rinfo->save_regs[60]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1, rinfo->save_regs[61]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0, rinfo->save_regs[62]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1, rinfo->save_regs[63]);
+	OUTMC(rinfo, ixR300_MC_BIST_CNTL_3, rinfo->save_regs[64]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0, rinfo->save_regs[65]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1, rinfo->save_regs[66]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0, rinfo->save_regs[67]);
+	OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1, rinfo->save_regs[68]);
+	OUTMC(rinfo, ixR300_MC_DEBUG_CNTL, rinfo->save_regs[69]);
+	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
+	OUTMC(rinfo, ixR300_MC_IMP_CNTL_0, rinfo->save_regs[71]);
+	OUTMC(rinfo, ixR300_MC_ELPIDA_CNTL, rinfo->save_regs[72]);
+	OUTMC(rinfo, ixR300_MC_READ_CNTL_CD, rinfo->save_regs[96]);
+	OUTREG(MC_IND_INDEX, 0);
+}
+
+static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
+{
+	u32 tmp, i;
+
+	/* Restore a bunch of registers first */
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
+	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+	OUTREG(BUS_CNTL, rinfo->save_regs[36]);	
+	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
+	OUTREG(FCP_CNTL, rinfo->save_regs[38]);
+	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
+	OUTREG(DAC_CNTL, rinfo->save_regs[40]);
+	OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8);
+	OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8);
+
+	/* Hrm... */
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE);
+
+	/* Reset the PAD CTLR */
+	radeon_pm_reset_pad_ctlr_strength(rinfo);
+       
+	/* Some PLLs are Read & written identically in the trace here...
+	 * I suppose it's actually to switch them all off & reset,
+	 * let's assume off is what we want. I'm just doing that for all major PLLs now.
+	 */
+	radeon_pm_all_ppls_off(rinfo);
+
+	/* Clear tiling, reset swappers */
+	INREG(SURFACE_CNTL);
+	OUTREG(SURFACE_CNTL, 0);
+
+	/* Some black magic with TV_DAC_CNTL, we should restore those from backups
+	 * rather than hard coding...
+	 */
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK;
+	tmp |= 8 << TV_DAC_CNTL_BGADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK;
+	tmp |= 7 << TV_DAC_CNTL_DACADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	/* More registers restored */
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]);
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+
+	/* Hrmmm ... What is that ? */
+	tmp = rinfo->save_regs[1]
+		& ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK |
+		    CLK_PWRMGT_CNTL__MC_BUSY);
+	OUTPLL(pllCLK_PWRMGT_CNTL, tmp);
+
+	OUTREG(PAD_CTLR_MISC, rinfo->save_regs[56]);
+	OUTREG(FW_CNTL, rinfo->save_regs[57]);
+	OUTREG(HDP_DEBUG, rinfo->save_regs[96]);
+	OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]);
+	OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]);
+	OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]);
+
+	/* Restore Memory Controller configuration */
+	radeon_pm_m10_reconfigure_mc(rinfo);
+
+	/* Make sure CRTC's dont touch memory */
+	OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL) 
+	       | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B);
+	OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL)
+	       | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B);
+	mdelay(30);
+      
+	/* Disable SDRAM refresh */
+	OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL)
+	       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+	/* Restore XTALIN routing (CLK_PIN_CNTL) */
+	OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]);
+
+	/* Switch MCLK, YCLK and SCLK PLLs to PCI source & force them ON */
+	tmp = rinfo->save_regs[2] & 0xff000000;
+	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);
+
+	/* Force all clocks on in SCLK */
+	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__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;
+	tmp |=	SCLK_CNTL__CP_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__HDP_MAX_DYN_STOP_LAT |
+		SCLK_CNTL__TV_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__E2_MAX_DYN_STOP_LAT  |
+		SCLK_CNTL__SE_MAX_DYN_STOP_LAT  |
+		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;
+	OUTPLL(pllSCLK_CNTL, tmp);
+
+	OUTPLL(pllVCLK_ECP_CNTL, 0);
+	OUTPLL(pllPIXCLKS_CNTL, 0);
+	OUTPLL(pllMCLK_MISC,
+	       MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT |
+	       MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT);
+
+	mdelay(5);
+
+	/* Restore the M_SPLL_REF_FB_DIV, MPLL_AUX_CNTL and SPLL_AUX_CNTL values */
+	OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]);
+	OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]);
+	OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]);
+	
+	/* Now restore the major PLLs settings, keeping them off & reset though */
+	OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3);
+	OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3);
+	OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03);
+	OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03);
+
+	/* Restore MC DLL state and switch it off/reset too  */ 
+	OUTMC(rinfo, ixR300_MC_DLL_CNTL, rinfo->save_regs[70]);
+
+	/* Switch MDLL off & reset */
+	OUTPLL(pllMDLL_RDCKA, rinfo->save_regs[98] | 0xff);
+	mdelay(5);
+
+	/* Setup some black magic bits in PLL_PWRMGT_CNTL. Hrm... we saved
+	 * 0xa1100007... and MacOS writes 0xa1000007 ..
+	 */
+	OUTPLL(pllPLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+
+	/* Restore more stuffs */
+	OUTPLL(pllHTOTAL_CNTL, 0);
+	OUTPLL(pllHTOTAL2_CNTL, 0);
+
+	/* More PLL initial configuration */
+	tmp = INPLL(pllSCLK_CNTL2); /* What for ? */
+	OUTPLL(pllSCLK_CNTL2, tmp);
+
+	tmp = INPLL(pllSCLK_MORE_CNTL);
+	tmp |= 	SCLK_MORE_CNTL__FORCE_DISPREGS |	/* a guess */
+		SCLK_MORE_CNTL__FORCE_MC_GUI |
+		SCLK_MORE_CNTL__FORCE_MC_HOST;
+	OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+	/* Now we actually start MCLK and SCLK */
+	radeon_pm_start_mclk_sclk(rinfo);
+
+	/* Full reset sdrams, this also re-inits the MDLL */
+	radeon_pm_full_reset_sdram(rinfo);
+
+	/* Fill palettes */
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20);	
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20);
+	udelay(20);
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20);
+	mdelay(3);
+
+	/* Restore TMDS */
+	OUTREG(FP_GEN_CNTL, rinfo->save_regs[82]);
+	OUTREG(FP2_GEN_CNTL, rinfo->save_regs[83]);
+
+	/* Set LVDS registers but keep interface & pll down */
+	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] &
+	       ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN));
+	OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000);
+
+	OUTREG(DISP_OUTPUT_CNTL, rinfo->save_regs[86]);
+
+	/* Restore GPIOPAD state */
+	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+
+	/* write some stuff to the framebuffer... */
+	for (i = 0; i < 0x8000; ++i)
+		writeb(0, rinfo->fb_base + i);
+	
+	mdelay(40);
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON);
+	mdelay(40);
+
+	/* Restore a few more things */
+	OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]);
+	OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]);
+
+	/* Take care of spread spectrum & PPLLs now */
+	radeon_pm_m10_disable_spread_spectrum(rinfo);
+	radeon_pm_restore_pixel_pll(rinfo);
+
+	/* GRRRR... I can't figure out the proper LVDS power sequence, and the
+	 * code I have for blank/unblank doesn't quite work on some laptop models
+	 * it seems ... Hrm. What I have here works most of the time ...
+	 */
+	radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
+}
+
+static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
+{
+	OUTREG(MC_CNTL, rinfo->save_regs[46]);
+	OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]);
+	OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]);
+	OUTREG(MEM_SDRAM_MODE_REG,
+	       rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE);
+	OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]);
+	OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]);
+	OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]);
+	OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]);
+	OUTREG(MC_DEBUG, rinfo->save_regs[53]);
+	OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]);
+
+	OUTMC(rinfo, ixMC_IMP_CNTL, rinfo->save_regs[59] /*0x00f460d6*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, rinfo->save_regs[65] /*0xfecfa666*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, rinfo->save_regs[66] /*0x141555ff*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, rinfo->save_regs[67] /*0xfecfa666*/);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/);
+	OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+
+	mdelay(20);
+}
+
+static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo)
+{
+	u32 tmp, i;
+	
+	/* Restore a bunch of registers first */
+	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]);
+	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
+	OUTREG(BUS_CNTL1, rinfo->save_regs[14]);
+	OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]);
+	OUTREG(FCP_CNTL, rinfo->save_regs[38]);
+	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
+
+	OUTREG(DAC_CNTL, rinfo->save_regs[40]);
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE);
+
+	/* Reset the PAD CTLR */
+	radeon_pm_reset_pad_ctlr_strength(rinfo);
+
+	/* Some PLLs are Read & written identically in the trace here...
+	 * I suppose it's actually to switch them all off & reset,
+	 * let's assume off is what we want. I'm just doing that for all major PLLs now.
+	 */
+	radeon_pm_all_ppls_off(rinfo);
+
+	/* Clear tiling, reset swappers */
+	INREG(SURFACE_CNTL);
+	OUTREG(SURFACE_CNTL, 0);
+
+	/* Some black magic with TV_DAC_CNTL, we should restore those from backups
+	 * rather than hard coding...
+	 */
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK;
+	tmp |= 6 << TV_DAC_CNTL_BGADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+
+	tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK;
+	tmp |= 6 << TV_DAC_CNTL_DACADJ__SHIFT;
+	OUTREG(TV_DAC_CNTL, tmp);
+	
+	OUTPLL(pllAGP_PLL_CNTL, rinfo->save_regs[78]);
+
+	OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]);
+	OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]);
+	OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]);
+
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]); /* MacOS sets that to 0 !!! */
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+
+	tmp  = rinfo->save_regs[1]
+		& ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK |
+		    CLK_PWRMGT_CNTL__MC_BUSY);
+	OUTPLL(pllCLK_PWRMGT_CNTL, tmp);
+
+	OUTREG(FW_CNTL, rinfo->save_regs[57]);
+
+	/* Disable SDRAM refresh */
+	OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL)
+	       | MEM_REFRESH_CNTL__MEM_REFRESH_DIS);
+
+	/* Restore XTALIN routing (CLK_PIN_CNTL) */
+       	OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]);
+
+	/* Force MCLK to be PCI sourced and forced ON */
+	tmp = rinfo->save_regs[2] & 0xff000000;
+	tmp |=	MCLK_CNTL__FORCE_MCLKA |
+		MCLK_CNTL__FORCE_MCLKB |
+		MCLK_CNTL__FORCE_YCLKA |
+		MCLK_CNTL__FORCE_YCLKB |
+		MCLK_CNTL__FORCE_MC    |
+		MCLK_CNTL__FORCE_AIC;
+	OUTPLL(pllMCLK_CNTL, tmp);
+
+	/* Force SCLK to be PCI sourced with a bunch forced */
+	tmp =	0 |
+		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_RE|
+		SCLK_CNTL__FORCE_PB|
+		SCLK_CNTL__FORCE_TAM|
+		SCLK_CNTL__FORCE_TDM|
+		SCLK_CNTL__FORCE_RB;
+	OUTPLL(pllSCLK_CNTL, tmp);
+
+	/* Clear VCLK_ECP_CNTL & PIXCLKS_CNTL  */
+	OUTPLL(pllVCLK_ECP_CNTL, 0);
+	OUTPLL(pllPIXCLKS_CNTL, 0);
+
+	/* Setup MCLK_MISC, non dynamic mode */
+	OUTPLL(pllMCLK_MISC,
+	       MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT |
+	       MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT);
+
+	mdelay(5);
+
+	/* Set back the default clock dividers */
+	OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]);
+	OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]);
+	OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]);
+
+	/* PPLL and P2PLL default values & off */
+	OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3);
+	OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3);
+
+	/* S and M PLLs are reset & off, configure them */
+	OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03);
+	OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03);
+
+	/* Default values for MDLL ... fixme */
+	OUTPLL(pllMDLL_CKO, 0x9c009c);
+	OUTPLL(pllMDLL_RDCKA, 0x08830883);
+	OUTPLL(pllMDLL_RDCKB, 0x08830883);
+	mdelay(5);
+
+	/* Restore PLL_PWRMGT_CNTL */ // XXXX
+	tmp = rinfo->save_regs[0];
+	tmp &= ~PLL_PWRMGT_CNTL_SU_SCLK_USE_BCLK;
+	tmp |= PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK;
+	OUTPLL(PLL_PWRMGT_CNTL,  tmp);
+	
+	/* Clear HTOTAL_CNTL & HTOTAL2_CNTL */
+	OUTPLL(pllHTOTAL_CNTL, 0);
+	OUTPLL(pllHTOTAL2_CNTL, 0);
+
+	/* All outputs off */
+	OUTREG(CRTC_GEN_CNTL, 0x04000000);
+	OUTREG(CRTC2_GEN_CNTL, 0x04000000);
+	OUTREG(FP_GEN_CNTL, 0x00004008);
+	OUTREG(FP2_GEN_CNTL, 0x00000008);
+	OUTREG(LVDS_GEN_CNTL, 0x08000008);
+
+	/* Restore Memory Controller configuration */
+	radeon_pm_m9p_reconfigure_mc(rinfo);
+
+	/* Now we actually start MCLK and SCLK */
+	radeon_pm_start_mclk_sclk(rinfo);
+
+	/* Full reset sdrams, this also re-inits the MDLL */
+	radeon_pm_full_reset_sdram(rinfo);
+
+	/* Fill palettes */
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20);	
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20);
+	udelay(20);
+	for (i=0; i<256; i++)
+		OUTREG(PALETTE_30_DATA, 0x15555555);
+
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20);
+	mdelay(3);
+
+	/* Restore TV stuff, make sure TV DAC is down */
+	OUTREG(TV_MASTER_CNTL, rinfo->save_regs[88]);
+	OUTREG(TV_DAC_CNTL, rinfo->save_regs[13] | 0x07000000);
+
+	/* Restore GPIOS. MacOS does some magic here with one of the GPIO bits,
+	 * possibly related to the weird PLL related workarounds and to the
+	 * fact that CLK_PIN_CNTL is tweaked in ways I don't fully understand,
+	 * but we keep things the simple way here
+	 */
+	OUTREG(GPIOPAD_A, rinfo->save_regs[19]);
+	OUTREG(GPIOPAD_EN, rinfo->save_regs[20]);
+	OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]);
+
+	/* Now do things with SCLK_MORE_CNTL. Force bits are already set, copy
+	 * high bits from backup
+	 */
+	tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff;
+	tmp |= rinfo->save_regs[34] & 0xffff0000;
+	tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS;
+	OUTPLL(pllSCLK_MORE_CNTL, tmp);
+
+	tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff;
+	tmp |= rinfo->save_regs[34] & 0xffff0000;
+	tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS;
+	OUTPLL(pllSCLK_MORE_CNTL, tmp);
+	
+	OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] &
+	       ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN));
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_BLON);
+	OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000);
+	mdelay(20);
+
+	/* write some stuff to the framebuffer... */
+	for (i = 0; i < 0x8000; ++i)
+		writeb(0, rinfo->fb_base + i);
+		
+	OUTREG(0x2ec, 0x6332a020);
+	OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44] /*0x3f */);
+	OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45] /*0x000081bb */);
+	tmp = INPLL(pllSSPLL_CNTL);
+	tmp &= ~2;
+	OUTPLL(pllSSPLL_CNTL, tmp);
+	mdelay(6);
+	tmp &= ~1;
+	OUTPLL(pllSSPLL_CNTL, tmp);
+	mdelay(5);
+	tmp |= 3;
+	OUTPLL(pllSSPLL_CNTL, tmp);
+	mdelay(5);
+	
+	OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3);/*0x0020300c*/
+	OUTREG(0x2ec, 0x6332a3f0);
+	mdelay(17);
+
+	OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div);;
+	OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]);
+	
+	mdelay(40);
+	OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON);
+	mdelay(40);
+
+	/* Restore a few more things */
+	OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]);
+	OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]);
+
+	/* Restore PPLL, spread spectrum & LVDS */
+	radeon_pm_m10_disable_spread_spectrum(rinfo);
+	radeon_pm_restore_pixel_pll(rinfo);
+	radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
+}
+
+#if 0 /* Not ready yet */
+static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
+{
+	int i;
+	u32 tmp, tmp2;
+	u32 cko, cka, ckb;
+	u32 cgc, cec, c2gc;
+
+	OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]);
+	OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]);
+	OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]);
+	OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]);
+	OUTREG(BUS_CNTL, rinfo->save_regs[36]);
+	OUTREG(RBBM_CNTL, rinfo->save_regs[39]);
+
+	INREG(PAD_CTLR_STRENGTH);
+	OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~0x10000);
+	for (i = 0; i < 65; ++i) {
+		mdelay(1);
+		INREG(PAD_CTLR_STRENGTH);
+	}
+
+	OUTREG(DISP_TEST_DEBUG_CNTL, INREG(DISP_TEST_DEBUG_CNTL) | 0x10000000);
+	OUTREG(OV0_FLAG_CNTRL, INREG(OV0_FLAG_CNTRL) | 0x100);
+	OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL));
+	OUTREG(DAC_CNTL, 0xff00410a);
+	OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL));
+	OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x4000);
+
+	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
+	OUTREG(AGP_CNTL, rinfo->save_regs[16]);
+	OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]);
+	OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]);
+
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, 0xf7bb4433);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, 0xf7bb4433);
+	OUTREG(MC_IND_INDEX, 0);
+
+	OUTREG(CRTC_MORE_CNTL, INREG(CRTC_MORE_CNTL));
+
+	tmp = INPLL(pllVCLK_ECP_CNTL);
+	OUTPLL(pllVCLK_ECP_CNTL, tmp);
+	tmp = INPLL(pllPIXCLKS_CNTL);
+	OUTPLL(pllPIXCLKS_CNTL, tmp);
+
+	OUTPLL(MCLK_CNTL, 0xaa3f0000);
+	OUTPLL(SCLK_CNTL, 0xffff0000);
+	OUTPLL(pllMPLL_AUX_CNTL, 6);
+	OUTPLL(pllSPLL_AUX_CNTL, 1);
+	OUTPLL(MDLL_CKO, 0x9f009f);
+	OUTPLL(MDLL_RDCKA, 0x830083);
+	OUTPLL(pllMDLL_RDCKB, 0x830083);
+	OUTPLL(PPLL_CNTL, 0xa433);
+	OUTPLL(P2PLL_CNTL, 0xa433);
+	OUTPLL(MPLL_CNTL, 0x0400a403);
+	OUTPLL(SPLL_CNTL, 0x0400a433);
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp);
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0xc);
+	INPLL(M_SPLL_REF_FB_DIV);
+
+	tmp = INPLL(MPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900);
+
+	tmp = INPLL(MPLL_CNTL);
+	OUTPLL(MPLL_CNTL, tmp & ~0x2);
+	mdelay(1);
+	tmp = INPLL(MPLL_CNTL);
+	OUTPLL(MPLL_CNTL, tmp & ~0x1);
+	mdelay(10);
+
+	OUTPLL(MCLK_CNTL, 0xaa3f1212);
+	mdelay(1);
+
+	INPLL(M_SPLL_REF_FB_DIV);
+	INPLL(MCLK_CNTL);
+	INPLL(M_SPLL_REF_FB_DIV);
+
+	tmp = INPLL(SPLL_CNTL);
+	OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN);
+	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+
+	tmp = INPLL(M_SPLL_REF_FB_DIV);
+	OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000);
+
+	tmp = INPLL(SPLL_CNTL);
+	OUTPLL(SPLL_CNTL, tmp & ~0x1);
+	mdelay(1);
+	tmp = INPLL(SPLL_CNTL);
+	OUTPLL(SPLL_CNTL, tmp & ~0x2);
+	mdelay(10);
+
+	tmp = INPLL(SCLK_CNTL);
+	OUTPLL(SCLK_CNTL, tmp | 2);
+	mdelay(1);
+
+	cko = INPLL(pllMDLL_CKO);
+	cka = INPLL(pllMDLL_RDCKA);
+	ckb = INPLL(pllMDLL_RDCKB);
+
+	cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP);
+	OUTPLL(pllMDLL_CKO, cko);
+	mdelay(1);
+	cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET);
+	OUTPLL(pllMDLL_CKO, cko);
+	mdelay(5);
+
+	cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP);
+	OUTPLL(pllMDLL_RDCKA, cka);
+	mdelay(1);
+	cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET);
+	OUTPLL(pllMDLL_RDCKA, cka);
+	mdelay(5);
+
+	ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP);
+	OUTPLL(pllMDLL_RDCKB, ckb);
+	mdelay(1);
+	ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET);
+	OUTPLL(pllMDLL_RDCKB, ckb);
+	mdelay(5);
+
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x151550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x151550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	mdelay(1);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x141550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x141550ff);
+	OUTREG(MC_IND_INDEX, 0);
+	mdelay(1);
+
+	OUTPLL(pllHTOTAL_CNTL, 0);
+	OUTPLL(pllHTOTAL2_CNTL, 0);
+
+	OUTREG(MEM_CNTL, 0x29002901);
+	OUTREG(MEM_SDRAM_MODE_REG, 0x45320032);	/* XXX use save_regs[35]? */
+	OUTREG(EXT_MEM_CNTL, 0x1a394333);
+	OUTREG(MEM_IO_CNTL_A1, 0x0aac0aac);
+	OUTREG(MEM_INIT_LATENCY_TIMER, 0x34444444);
+	OUTREG(MEM_REFRESH_CNTL, 0x1f1f7218);	/* XXX or save_regs[42]? */
+	OUTREG(MC_DEBUG, 0);
+	OUTREG(MEM_IO_OE_CNTL, 0x04300430);
+
+	OUTMC(rinfo, ixMC_IMP_CNTL, 0x00f460d6);
+	OUTREG(MC_IND_INDEX, 0);
+	OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249);
+	OUTREG(MC_IND_INDEX, 0);
+
+	OUTREG(CONFIG_MEMSIZE, rinfo->video_ram);
+
+	radeon_pm_full_reset_sdram(rinfo);
+
+	INREG(FP_GEN_CNTL);
+	OUTREG(TMDS_CNTL, 0x01000000);	/* XXX ? */
+	tmp = INREG(FP_GEN_CNTL);
+	tmp |= FP_CRTC_DONT_SHADOW_HEND | FP_CRTC_DONT_SHADOW_VPAR | 0x200;
+	OUTREG(FP_GEN_CNTL, tmp);
+
+	tmp = INREG(DISP_OUTPUT_CNTL);
+	tmp &= ~0x400;
+	OUTREG(DISP_OUTPUT_CNTL, tmp);
+
+	OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]);
+	OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]);
+	OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]);
+
+	tmp = INPLL(MCLK_MISC);
+	tmp |= MCLK_MISC__MC_MCLK_DYN_ENABLE | MCLK_MISC__IO_MCLK_DYN_ENABLE;
+	OUTPLL(MCLK_MISC, tmp);
+
+	tmp = INPLL(SCLK_CNTL);
+	OUTPLL(SCLK_CNTL, tmp);
+
+	OUTREG(CRTC_MORE_CNTL, 0);
+	OUTREG8(CRTC_GEN_CNTL+1, 6);
+	OUTREG8(CRTC_GEN_CNTL+3, 1);
+	OUTREG(CRTC_PITCH, 32);
+
+	tmp = INPLL(VCLK_ECP_CNTL);
+	OUTPLL(VCLK_ECP_CNTL, tmp);
+
+	tmp = INPLL(PPLL_CNTL);
+	OUTPLL(PPLL_CNTL, tmp);
+
+	/* palette stuff and BIOS_1_SCRATCH... */
+
+	tmp = INREG(FP_GEN_CNTL);
+	tmp2 = INREG(TMDS_TRANSMITTER_CNTL);
+	tmp |= 2;
+	OUTREG(FP_GEN_CNTL, tmp);
+	mdelay(5);
+	OUTREG(FP_GEN_CNTL, tmp);
+	mdelay(5);
+	OUTREG(TMDS_TRANSMITTER_CNTL, tmp2);
+	OUTREG(CRTC_MORE_CNTL, 0);
+	mdelay(20);
+
+	tmp = INREG(CRTC_MORE_CNTL);
+	OUTREG(CRTC_MORE_CNTL, tmp);
+
+	cgc = INREG(CRTC_GEN_CNTL);
+	cec = INREG(CRTC_EXT_CNTL);
+	c2gc = INREG(CRTC2_GEN_CNTL);
+
+	OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580);
+	OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2);
+	OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN);
+	OUTREG8(CLOCK_CNTL_DATA, 0);
+	OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403);
+	OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429);
+	OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033);
+	OUTREG(FP_H_SYNC_STRT_WID, 0x008e0080);
+	OUTREG(CRT_CRTC_H_SYNC_STRT_WID, 0x008e0080);
+	OUTREG(FP_CRTC_V_TOTAL_DISP, 0x03ff002a);
+	OUTREG(FP_V_SYNC_STRT_WID, 0x00830004);
+	OUTREG(CRT_CRTC_V_SYNC_STRT_WID, 0x00830004);
+	OUTREG(FP_HORZ_VERT_ACTIVE, 0x009f03ff);
+	OUTREG(FP_HORZ_STRETCH, 0);
+	OUTREG(FP_VERT_STRETCH, 0);
+	OUTREG(OVR_CLR, 0);
+	OUTREG(OVR_WID_LEFT_RIGHT, 0);
+	OUTREG(OVR_WID_TOP_BOTTOM, 0);
+
+	tmp = INPLL(PPLL_REF_DIV);
+	tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div;
+	OUTPLL(PPLL_REF_DIV, tmp);
+	INPLL(PPLL_REF_DIV);
+
+	OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN);
+	OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc);
+
+	tmp = INREG(CLOCK_CNTL_INDEX);
+	OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff);
+
+	OUTPLL(PPLL_DIV_0, 0x48090);
+
+	tmp = INPLL(PPLL_CNTL);
+	OUTPLL(PPLL_CNTL, tmp & ~0x2);
+	mdelay(1);
+	tmp = INPLL(PPLL_CNTL);
+	OUTPLL(PPLL_CNTL, tmp & ~0x1);
+	mdelay(10);
+
+	tmp = INPLL(VCLK_ECP_CNTL);
+	OUTPLL(VCLK_ECP_CNTL, tmp | 3);
+	mdelay(1);
+
+	tmp = INPLL(VCLK_ECP_CNTL);
+	OUTPLL(VCLK_ECP_CNTL, tmp);
+
+	c2gc |= CRTC2_DISP_REQ_EN_B;
+	OUTREG(CRTC2_GEN_CNTL, c2gc);
+	cgc |= CRTC_EN;
+	OUTREG(CRTC_GEN_CNTL, cgc);
+	OUTREG(CRTC_EXT_CNTL, cec);
+	OUTREG(CRTC_PITCH, 0xa0);
+	OUTREG(CRTC_OFFSET, 0);
+	OUTREG(CRTC_OFFSET_CNTL, 0);
+
+	OUTREG(GRPH_BUFFER_CNTL, 0x20117c7c);
+	OUTREG(GRPH2_BUFFER_CNTL, 0x00205c5c);
+
+	tmp2 = INREG(FP_GEN_CNTL);
+	tmp = INREG(TMDS_TRANSMITTER_CNTL);
+	OUTREG(0x2a8, 0x0000061b);
+	tmp |= TMDS_PLL_EN;
+	OUTREG(TMDS_TRANSMITTER_CNTL, tmp);
+	mdelay(1);
+	tmp &= ~TMDS_PLLRST;
+	OUTREG(TMDS_TRANSMITTER_CNTL, tmp);
+	tmp2 &= ~2;
+	tmp2 |= FP_TMDS_EN;
+	OUTREG(FP_GEN_CNTL, tmp2);
+	mdelay(5);
+	tmp2 |= FP_FPON;
+	OUTREG(FP_GEN_CNTL, tmp2);
+
+	OUTREG(CUR_HORZ_VERT_OFF, CUR_LOCK | 1);
+	cgc = INREG(CRTC_GEN_CNTL);
+	OUTREG(CUR_HORZ_VERT_POSN, 0xbfff0fff);
+	cgc |= 0x10000;
+	OUTREG(CUR_OFFSET, 0);
+}
+#endif /* 0 */
+
+#endif /* CONFIG_PPC_OF */
+
 static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
 {
 	u16 pwr_cmd;
 	u32 tmp;
+	int i;
 
 	if (!rinfo->pm_reg)
 		return;
@@ -796,13 +2406,13 @@
 		 * duration of the suspend/resume process
 		 */
 		radeon_pm_disable_dynamic_mode(rinfo);
+
 		/* Save some registers */
-		radeon_pm_save_regs(rinfo);
+		radeon_pm_save_regs(rinfo, 0);
 
-		/* Prepare mobility chips for suspend. Only do that on <= RV250 chips that
-		 * have been tested
+		/* Prepare mobility chips for suspend.
 		 */
-		if (rinfo->is_mobility && rinfo->family <= CHIP_FAMILY_RV250) {
+		if (rinfo->is_mobility) {
 			/* Program V2CLK */
 			radeon_pm_program_v2clk(rinfo);
 		
@@ -815,13 +2425,22 @@
 			/* Prepare chip for power management */
 			radeon_pm_setup_for_suspend(rinfo);
 
-			/* Reset the MDLL */
-			/* because both INPLL and OUTPLL take the same lock, that's why. */
-			tmp = INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET;
-			OUTPLL( pllMDLL_CKO, tmp );
+			if (rinfo->family <= CHIP_FAMILY_RV280) {
+				/* Reset the MDLL */
+				/* because both INPLL and OUTPLL take the same
+				 * lock, that's why. */
+				tmp = INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET
+					| MDLL_CKO__MCKOB_RESET;
+				OUTPLL( pllMDLL_CKO, tmp );
+			}
 		}
 
+		for (i = 0; i < 64; ++i)
+			pci_read_config_dword(rinfo->pdev, i * 4,
+					      &rinfo->cfg_save[i]);
+
 		/* Switch PCI power managment to D2. */
+		pci_disable_device(rinfo->pdev);
 		for (;;) {
 			pci_read_config_word(
 				rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
@@ -841,37 +2460,74 @@
 		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);
+		if (rinfo->family <= CHIP_FAMILY_RV250) {
+			/* Reset the SDRAM controller  */
+			radeon_pm_full_reset_sdram(rinfo);
+
+			/* Restore some registers */
+			radeon_pm_restore_regs(rinfo);
+		} else {
+			/* Restore registers first */
+			radeon_pm_restore_regs(rinfo);
+			/* init sdram controller */
+			radeon_pm_full_reset_sdram(rinfo);
+		}
 	}
 }
 
+static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
+{
+	int i;
+	static u32 radeon_cfg_after_resume[64];
+
+	for (i = 0; i < 64; ++i)
+		pci_read_config_dword(rinfo->pdev, i * 4,
+				      &radeon_cfg_after_resume[i]);
+
+	if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4]
+	    == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4])
+		return 0;	/* assume everything is ok */
+
+	for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) {
+		if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i])
+			pci_write_config_dword(rinfo->pdev, i * 4,
+					       rinfo->cfg_save[i]);
+	}
+	pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE,
+			      rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]);
+	pci_write_config_word(rinfo->pdev, PCI_COMMAND,
+			      rinfo->cfg_save[PCI_COMMAND/4]);
+	return 1;
+}
+
+
+static/*extern*/ int susdisking = 0;
+
 int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
+	int i;
 
-	/* We don't do anything but D2, for now we return 0, but
-	 * we may want to change that. How do we know if the BIOS
-	 * can properly take care of D3 ? Also, with swsusp, we
-	 * know we'll be rebooted, ...
-	 */
+	if (state == pdev->dev.power.power_state)
+		return 0;
 
-	printk(KERN_DEBUG "radeonfb: suspending to state: %d...\n", state);
-	
-	acquire_console_sem();
+	printk(KERN_DEBUG "radeonfb (%s): suspending to state: %d...\n",
+	       pci_name(pdev), state);
 
-	/* Userland should do this but doesn't... bridge gets suspended
-	 * too late. Unfortunately, that works only when AGP is built-in,
-	 * not for a module.
+	/* For suspend-to-disk, we cheat here. We don't suspend anything and
+	 * let fbcon continue drawing until we are all set. That shouldn't
+	 * really cause any problem at this point, provided that the wakeup
+	 * code knows that any state in memory may not match the HW
 	 */
-#ifdef CONFIG_AGP
-	agp_enable(0);
-#endif
+	if (state != PM_SUSPEND_MEM)
+		goto done;
+	if (susdisking) {
+		printk("suspending to disk but state = %d\n", state);
+		goto done;
+	}
+
+	acquire_console_sem();
 
 	fb_set_suspend(info, 1);
 
@@ -883,21 +2539,52 @@
 	}
 
 	/* Blank display and LCD */
-	radeonfb_blank(VESA_POWERDOWN, info);
+	radeon_screen_blank(rinfo, FB_BLANK_POWERDOWN, 1);
 
 	/* Sleep */
 	rinfo->asleep = 1;
 	rinfo->lock_blank = 1;
+	del_timer_sync(&rinfo->lvds_timer);
 
-	/* Suspend the chip to D2 state when supported
+	/* If we support wakeup from poweroff, we save all regs we can including cfg
+	 * space
 	 */
-#ifdef CONFIG_RADEON_HAS_D2
-	if (radeon_suspend_to_d2(rinfo, state))
+	if (rinfo->pm_mode & radeon_pm_off) {
+		/* Always disable dynamic clocks or weird things are happening when
+		 * the chip goes off (basically the panel doesn't shut down properly
+		 * and we crash on wakeup),
+		 * also, we want the saved regs context to have no dynamic clocks in
+		 * it, we'll restore the dynamic clocks state on wakeup
+		 */
+		radeon_pm_disable_dynamic_mode(rinfo);
+		mdelay(50);
+		radeon_pm_save_regs(rinfo, 1);
+
+		if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
+			/* Switch off LVDS interface */
+			mdelay(1);
+			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BL_MOD_EN));
+			mdelay(1);
+			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_EN | LVDS_ON));
+			OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000);
+			mdelay(20);
+			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
+
+			// FIXME: Use PCI layer
+			for (i = 0; i < 64; ++i)
+				pci_read_config_dword(rinfo->pdev, i * 4,
+						      &rinfo->cfg_save[i]);
+		}
+	}
+	/* If we support D2, we go to it (should be fixed later with a flag forcing
+	 * D3 only for some laptops)
+	 */
+	if (rinfo->pm_mode & radeon_pm_d2)
 		radeon_set_suspend(rinfo, 1);
-#endif /* CONFIG_RADEON_HAS_D2 */
 
 	release_console_sem();
 
+ done:
 	pdev->dev.power.power_state = state;
 
 	return 0;
@@ -907,22 +2594,59 @@
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
+	int rc = 0;
 
 	if (pdev->dev.power.power_state == 0)
 		return 0;
 
-	acquire_console_sem();
+	if (rinfo->no_schedule) {
+		if (try_acquire_console_sem())
+			return 0;
+	} else
+		acquire_console_sem();
+
+	printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n",
+	       pci_name(pdev), pdev->dev.power.power_state);
+
 
-	/* Wakeup chip */
-#ifdef CONFIG_RADEON_HAS_D2
-	if (radeon_suspend_to_d2(rinfo, 0))
-		radeon_set_suspend(rinfo, 0);
-#endif /* CONFIG_RADEON_HAS_D2 */
+	if (pci_enable_device(pdev)) {
+		rc = -ENODEV;
+		printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n",
+		       pci_name(pdev));
+		goto bail;
+	}
+	pci_set_master(pdev);
+
+	if (pdev->dev.power.power_state == PM_SUSPEND_MEM) {
+		/* Wakeup chip. Check from config space if we were powered off
+		 * (todo: additionally, check CLK_PIN_CNTL too)
+		 */
+		if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) {
+			if (rinfo->reinit_func != NULL)
+				rinfo->reinit_func(rinfo);
+			else {
+				printk(KERN_ERR "radeonfb (%s): can't resume radeon from"
+				       " D3 cold, need softboot !", pci_name(pdev));
+				rc = -EIO;
+				goto bail;
+			}
+		}
+		/* If we support D2, try to resume... we should check what was our
+		 * state though... (were we really in D2 state ?). Right now, this code
+		 * is only enable on Macs so it's fine.
+		 */
+		else if (rinfo->pm_mode & radeon_pm_d2)
+			radeon_set_suspend(rinfo, 0);
 
-	rinfo->asleep = 0;
+		rinfo->asleep = 0;
+	} else
+		radeon_engine_idle();
 
 	/* Restore display & engine */
-	radeonfb_set_par(info);
+	radeon_write_mode (rinfo, &rinfo->state, 1);
+	if (!(info->flags & FBINFO_HWACCEL_DISABLED))
+		radeonfb_engine_init (rinfo);
+
 	fb_pan_display(info, &info->var);
 	fb_set_cmap(&info->cmap, info);
 
@@ -931,15 +2655,105 @@
 
 	/* Unblank */
 	rinfo->lock_blank = 0;
-	radeonfb_blank(0, info);
+	radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 1);
 
-	release_console_sem();
+	/* Check status of dynclk */
+	if (rinfo->dynclk == 1)
+		radeon_pm_enable_dynamic_mode(rinfo);
+	else if (rinfo->dynclk == 0)
+		radeon_pm_disable_dynamic_mode(rinfo);
 
 	pdev->dev.power.power_state = 0;
 
-	printk(KERN_DEBUG "radeonfb: resumed !\n");
+ bail:
+	release_console_sem();
 
-	return 0;
+	return rc;
+}
+
+#ifdef CONFIG_PPC_OF
+static void radeonfb_early_resume(void *data)
+{
+        struct radeonfb_info *rinfo = data;
+
+	rinfo->no_schedule = 1;
+	radeonfb_pci_resume(rinfo->pdev);
+	rinfo->no_schedule = 0;
 }
+#endif /* CONFIG_PPC_OF */
 
 #endif /* CONFIG_PM */
+
+void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
+{
+	/* Find PM registers in config space if any*/
+	rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
+
+	/* Enable/Disable dynamic clocks: TODO add sysfs access */
+	rinfo->dynclk = dynclk;
+	if (dynclk == 1) {
+		radeon_pm_enable_dynamic_mode(rinfo);
+		printk("radeonfb: Dynamic Clock Power Management enabled\n");
+	} else if (dynclk == 0) {
+		radeon_pm_disable_dynamic_mode(rinfo);
+		printk("radeonfb: Dynamic Clock Power Management disabled\n");
+	}
+
+	/* Check if we can power manage on suspend/resume. We can do
+	 * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
+	 * "Mac" cards, but that's all. We need more infos about what the
+	 * BIOS does tho. Right now, all this PM stuff is pmac-only for that
+	 * reason. --BenH
+	 */
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+	if (_machine == _MACH_Pmac && rinfo->of_node) {
+		if (rinfo->is_mobility && rinfo->pm_reg &&
+		    rinfo->family <= CHIP_FAMILY_RV250)
+			rinfo->pm_mode |= radeon_pm_d2;
+
+		/* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
+		 * in some desktop G4s), and Via (M9+ chip on iBook G4)
+		 */
+		if (!strcmp(rinfo->of_node->name, "ATY,JasperParent")) {
+			rinfo->reinit_func = radeon_reinitialize_M10;
+			rinfo->pm_mode |= radeon_pm_off;
+		}
+#if 0 /* Not ready yet */
+		if (!strcmp(rinfo->of_node->name, "ATY,BlueStoneParent")) {
+			rinfo->reinit_func = radeon_reinitialize_QW;
+			rinfo->pm_mode |= radeon_pm_off;
+		}
+#endif
+		if (!strcmp(rinfo->of_node->name, "ATY,ViaParent")) {
+			rinfo->reinit_func = radeon_reinitialize_M9P;
+			rinfo->pm_mode |= radeon_pm_off;
+			/* Workaround not used for now */
+			rinfo->m9p_workaround = 1;
+		}
+
+		/* If any of the above is set, we assume the machine can sleep/resume.
+		 * It's a bit of a "shortcut" but will work fine. Ideally, we need infos
+		 * from the platform about what happens to the chip...
+		 * Now we tell the platform about our capability
+		 */
+		if (rinfo->pm_mode != radeon_pm_none) {
+			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1);
+			pmac_set_early_video_resume(radeonfb_early_resume, rinfo);
+		}
+
+		/* Power down TV DAC, taht saves a significant amount of power,
+		 * we'll have something better once we actually have some TVOut
+		 * support
+		 */
+		OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
+	}
+#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */
+}
+
+void radeonfb_pm_exit(struct radeonfb_info *rinfo)
+{
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+	if (rinfo->pm_mode != radeon_pm_none)
+		pmac_set_early_video_resume(NULL, NULL);
+#endif
+}
Index: linux-work/drivers/video/aty/radeonfb.h
===================================================================
--- linux-work.orig/drivers/video/aty/radeonfb.h	2004-11-22 11:50:27.000000000 +1100
+++ linux-work/drivers/video/aty/radeonfb.h	2005-01-17 13:49:30.073580288 +1100
@@ -16,8 +16,17 @@
 
 #include <asm/io.h>
 
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#endif
+
 #include <video/radeon.h>
 
+/* Some weird black magic use by Apple driver that we don't use for
+ * now --BenH
+ */
+#undef HAS_PLL_M9_GPIO_MAGIC
+
 /***************************************************************
  * Most of the definitions here are adapted right from XFree86 *
  ***************************************************************/
@@ -33,7 +42,8 @@
 	CHIP_FAMILY_RV100,
 	CHIP_FAMILY_RS100,    /* U1 (IGP320M) or A3 (IGP320)*/
 	CHIP_FAMILY_RV200,
-	CHIP_FAMILY_RS200,    /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */
+	CHIP_FAMILY_RS200,    /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
+				 RS250 (IGP 7000) */
 	CHIP_FAMILY_R200,
 	CHIP_FAMILY_RV250,
 	CHIP_FAMILY_RS300,    /* Radeon 9000 IGP */
@@ -41,9 +51,26 @@
 	CHIP_FAMILY_R300,
 	CHIP_FAMILY_R350,
 	CHIP_FAMILY_RV350,
+	CHIP_FAMILY_RV380,    /* RV370/RV380/M22/M24 */
+	CHIP_FAMILY_R420,     /* R420/R423/M18 */
 	CHIP_FAMILY_LAST,
 };
 
+#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RV200)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RS100)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RS200)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RV250)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RV280)  || \
+				 ((rinfo)->family == CHIP_FAMILY_RS300))
+
+
+#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300)  || \
+				((rinfo)->family == CHIP_FAMILY_RV350) || \
+				((rinfo)->family == CHIP_FAMILY_R350)  || \
+				((rinfo)->family == CHIP_FAMILY_RV380) || \
+				((rinfo)->family == CHIP_FAMILY_R420))
+
 /*
  * Chip flags
  */
@@ -102,21 +129,6 @@
 	int ref_clk;
 };
 
-/*
- * VRAM infos
- */
-struct ram_info {
-	int ml;
-	int mb;
-	int trcd;
-	int trp;
-	int twr;
-	int cl;
-	int tr2w;
-	int loop_latency;
-	int rloop;
-};
-
 
 /*
  * This structure contains the various registers manipulated by this
@@ -210,6 +222,7 @@
 	u32		ppll_div_3;
 	u32		ppll_ref_div;
 	u32		vclk_ecp_cntl;
+	u32		clk_cntl_index;
 
 	/* Computed values for PLL2 */
 	u32		dot_clock_freq_2;
@@ -250,6 +263,12 @@
 };
 #endif
 
+enum radeon_pm_mode {
+	radeon_pm_none	= 0,		/* Nothing supported */
+	radeon_pm_d2	= 0x00000001,	/* Can do D2 state */
+	radeon_pm_off	= 0x00000002,	/* Can resume from D3 cold */
+};
+
 struct radeonfb_info {
 	struct fb_info		*info;
 
@@ -257,7 +276,6 @@
 	struct radeon_regs	init_state;
 
 	char			name[DEVICE_NAME_SIZE];
-	char			ram_type[12];
 
 	unsigned long		mmio_base_phys;
 	unsigned long		fb_base_phys;
@@ -268,6 +286,9 @@
 	unsigned long		fb_local_base;
 
 	struct pci_dev		*pdev;
+#ifdef CONFIG_PPC_OF
+	struct device_node	*of_node;
+#endif
 
 	void __iomem		*bios_seg;
 	int			fp_bios_start;
@@ -281,6 +302,8 @@
 	u8			rev;
 	unsigned long		video_ram;
 	unsigned long		mapped_vram;
+	int			vram_width;
+	int			vram_ddr;
 
 	int			pitch, bpp, depth;
 
@@ -288,6 +311,7 @@
 	int			is_mobility;
 	int			is_IGP;
 	int			R300_cg_workaround;
+	int			m9p_workaround;
 	int			reversed_DAC;
 	int			reversed_TMDS;
 	struct panel_info	panel_info;
@@ -302,14 +326,16 @@
 
 	struct pll_info		pll;
 
-	struct ram_info		ram;
-
 	int			mtrr_hdl;
 
 	int			pm_reg;
-	u32			save_regs[64];
+	u32			save_regs[100];
 	int			asleep;
 	int			lock_blank;
+	int			dynclk;
+	int			no_schedule;
+	enum radeon_pm_mode	pm_mode;
+	void			(*reinit_func)(struct radeonfb_info *rinfo);
 
 	/* Lock on register access */
 	spinlock_t		reg_lock;
@@ -317,11 +343,12 @@
 	/* Timer used for delayed LVDS operations */
 	struct timer_list	lvds_timer;
 	u32			pending_lvds_gen_cntl;
-	u32			pending_pixclks_cntl;
 
 #ifdef CONFIG_FB_RADEON_I2C
 	struct radeon_i2c_chan 	i2c[4];
 #endif
+
+	u32			cfg_save[64];
 };

@@ -353,6 +380,22 @@
 #define INREG(addr)		readl((rinfo->mmio_base)+addr)
 #define OUTREG(addr,val)	writel(val, (rinfo->mmio_base)+addr)
 
+static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
+		       u32 val, u32 mask)
+{
+	unsigned long flags;
+	unsigned int tmp;
+	
+	spin_lock_irqsave(&rinfo->reg_lock, flags);
+	tmp = INREG(addr);
+	tmp &= (mask);
+	tmp |= (val);
+	OUTREG(addr, tmp);
+	spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+}
+
+#define OUTREGP(addr,val,mask)	_OUTREGP(rinfo, addr, val,mask)
+
 static inline void R300_cg_workardound(struct radeonfb_info *rinfo)
 {
 	u32 save, tmp;
@@ -363,18 +406,35 @@
 	OUTREG(CLOCK_CNTL_INDEX, save);
 }
 
-#define __OUTPLL(addr,val)	\
-	do {	\
-		OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
-		OUTREG(CLOCK_CNTL_DATA, val); \
-} while(0)
-
 
 static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
 {
 	u32 data;
+#ifdef HAS_PLL_M9_GPIO_MAGIC
+	u32 sv[3];
+
+	if (rinfo->m9p_workaround) {
+		sv[0] = INREG(0x19c);
+		sv[1] = INREG(0x1a0);
+		sv[2] = INREG(0x198);
+		OUTREG(0x198, 0);
+		OUTREG(0x1a0, 0);
+		OUTREG(0x19c, 0);
+	}
+#endif /* HAS_PLL_M9_GPIO_MAGIC */
+
 	OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
 	data = (INREG(CLOCK_CNTL_DATA));
+
+#ifdef HAS_PLL_M9_GPIO_MAGIC
+	if (rinfo->m9p_workaround) {
+		(void)INREG(CRTC_GEN_CNTL);
+		data = INREG(CLOCK_CNTL_DATA);
+		OUTREG(0x19c, sv[0]);
+		OUTREG(0x1a0, sv[1]);
+		OUTREG(0x198, sv[2]);
+	}
+#endif /* HAS_PLL_M9_GPIO_MAGIC */
 	if (rinfo->R300_cg_workaround)
 		R300_cg_workardound(rinfo);
 	return data;
@@ -393,37 +453,61 @@
 
 #define INPLL(addr)		_INPLL(rinfo, addr)
 
-#define OUTPLL(addr,val)	\
-	do {	\
-		unsigned long flags;\
-		spin_lock_irqsave(&rinfo->reg_lock, flags); \
-		__OUTPLL(addr, val); \
-		spin_unlock_irqrestore(&rinfo->reg_lock, flags); \
-	} while(0)
-
-#define OUTPLLP(addr,val,mask)  					\
-	do {								\
-		unsigned long flags;                                    \
-		unsigned int _tmp;					\
-		spin_lock_irqsave(&rinfo->reg_lock, flags); 		\
-		_tmp  = __INPLL(rinfo,addr);				\
-		_tmp &= (mask);						\
-		_tmp |= (val);						\
-		__OUTPLL(addr, _tmp);					\
-		spin_unlock_irqrestore(&rinfo->reg_lock, flags); 	\
-	} while (0)
-
-#define OUTREGP(addr,val,mask)  					\
-	do {								\
-		unsigned long flags;                                    \
-		unsigned int _tmp;					\
-		spin_lock_irqsave(&rinfo->reg_lock, flags); 		\
-		_tmp = INREG(addr);				       	\
-		_tmp &= (mask);						\
-		_tmp |= (val);						\
-		OUTREG(addr, _tmp);					\
-		spin_unlock_irqrestore(&rinfo->reg_lock, flags); 	\
-	} while (0)
+
+static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
+{
+#ifdef HAS_PLL_M9_GPIO_MAGIC
+	u32 sv[3];
+
+	if (rinfo->m9p_workaround) {
+		sv[0] = INREG(0x19c);
+		sv[1] = INREG(0x1a0);
+		sv[2] = INREG(0x198);
+		OUTREG(0x198, 0);
+		OUTREG(0x1a0, 0);
+		OUTREG(0x19c, 0);
+		mdelay(1);
+	}
+#endif /* HAS_PLL_M9_GPIO_MAGIC */
+
+	OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+	OUTREG(CLOCK_CNTL_DATA, val);
+
+#ifdef HAS_PLL_M9_GPIO_MAGIC
+	if (rinfo->m9p_workaround) {
+		OUTREG(0x19c, sv[0]);
+		OUTREG(0x1a0, sv[1]);
+		OUTREG(0x198, sv[2]);
+	}
+#endif /* HAS_PLL_M9_GPIO_MAGIC */
+}
+	
+static inline void _OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
+{
+       	unsigned long flags;
+	spin_lock_irqsave(&rinfo->reg_lock, flags);
+	__OUTPLL(rinfo, index, val);
+	spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+}
+
+static inline void _OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+			    u32 val, u32 mask)
+{
+	unsigned long flags;
+	unsigned int tmp;
+
+	spin_lock_irqsave(&rinfo->reg_lock, flags);
+	tmp  = __INPLL(rinfo, index);
+	tmp &= (mask);
+	tmp |= (val);
+	__OUTPLL(rinfo, index, tmp);
+	spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+}
+
+
+#define OUTPLL(index, val)		_OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask)	_OUTPLLP(rinfo, index, val, mask)
+
 
 #define BIOS_IN8(v)  	(readb(rinfo->bios_seg + (v)))
 #define BIOS_IN16(v) 	(readb(rinfo->bios_seg + (v)) | \
@@ -484,7 +568,7 @@
 }

-static inline void _radeon_fifo_wait (struct radeonfb_info *rinfo, int entries)
+static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
 {
 	int i;
 
@@ -497,7 +581,7 @@
 }

-static inline void _radeon_engine_idle (struct radeonfb_info *rinfo)
+static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
 {
 	int i;
 
@@ -514,8 +598,24 @@
 	printk(KERN_ERR "radeonfb: Idle Timeout !\n");
 }
 
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mecanism. At this point, interrupts are off
+ * and scheduling is not permitted
+ */
+static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+	if (rinfo->no_schedule)
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+
 #define radeon_engine_idle()		_radeon_engine_idle(rinfo)
 #define radeon_fifo_wait(entries)	_radeon_fifo_wait(rinfo,entries)
+#define radeon_msleep(ms)		_radeon_msleep(rinfo,ms)

 /* I2C Functions */
@@ -524,10 +624,10 @@
 extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
 
 /* PM Functions */
-extern void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo);
-extern void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo);
 extern int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state);
 extern int radeonfb_pci_resume(struct pci_dev *pdev);
+extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk);
+extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
 
 /* Monitor probe functions */
 extern void radeon_probe_screens(struct radeonfb_info *rinfo,
@@ -546,7 +646,9 @@
 extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
 
 /* Other functions */
-extern int radeonfb_blank(int blank, struct fb_info *info);
-extern int radeonfb_set_par(struct fb_info *info);
+extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
+extern void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save);
+extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
+			       int reg_only);
 
 #endif /* __RADEONFB_H__ */
Index: linux-work/drivers/video/aty/ati_ids.h
===================================================================
--- linux-work.orig/drivers/video/aty/ati_ids.h	2004-11-22 11:50:26.000000000 +1100
+++ linux-work/drivers/video/aty/ati_ids.h	2005-01-17 13:49:30.075579984 +1100
@@ -4,6 +4,18 @@
  * radeonfb
  */
 
+#define PCI_CHIP_RV380_3150             0x3150
+#define PCI_CHIP_RV380_3151             0x3151
+#define PCI_CHIP_RV380_3152             0x3152
+#define PCI_CHIP_RV380_3153             0x3153
+#define PCI_CHIP_RV380_3154             0x3154
+#define PCI_CHIP_RV380_3156             0x3156
+#define PCI_CHIP_RV380_3E50             0x3E50
+#define PCI_CHIP_RV380_3E51             0x3E51
+#define PCI_CHIP_RV380_3E52             0x3E52
+#define PCI_CHIP_RV380_3E53             0x3E53
+#define PCI_CHIP_RV380_3E54             0x3E54
+#define PCI_CHIP_RV380_3E56             0x3E56
 #define PCI_CHIP_RS100_4136		0x4136
 #define PCI_CHIP_RS200_4137		0x4137
 #define PCI_CHIP_R300_AD		0x4144
@@ -52,6 +64,14 @@
 #define PCI_CHIP_RV250_Ie		0x4965
 #define PCI_CHIP_RV250_If		0x4966
 #define PCI_CHIP_RV250_Ig		0x4967
+#define PCI_CHIP_R420_JH                0x4A48
+#define PCI_CHIP_R420_JI                0x4A49
+#define PCI_CHIP_R420_JJ                0x4A4A
+#define PCI_CHIP_R420_JK                0x4A4B
+#define PCI_CHIP_R420_JL                0x4A4C
+#define PCI_CHIP_R420_JM                0x4A4D
+#define PCI_CHIP_R420_JN                0x4A4E
+#define PCI_CHIP_R420_JP                0x4A50
 #define PCI_CHIP_MACH64LB		0x4C42
 #define PCI_CHIP_MACH64LD		0x4C44
 #define PCI_CHIP_RAGE128LE		0x4C45
@@ -73,6 +93,7 @@
 #define PCI_CHIP_RV250_Le		0x4C65
 #define PCI_CHIP_RV250_Lf		0x4C66
 #define PCI_CHIP_RV250_Lg		0x4C67
+#define PCI_CHIP_RV250_Ln		0x4C6E
 #define PCI_CHIP_RAGE128MF		0x4D46
 #define PCI_CHIP_RAGE128ML		0x4D4C
 #define PCI_CHIP_R300_ND		0x4E44
@@ -148,6 +169,21 @@
 #define PCI_CHIP_RAGE128TS		0x5453
 #define PCI_CHIP_RAGE128TT		0x5454
 #define PCI_CHIP_RAGE128TU		0x5455
+#define PCI_CHIP_RV370_5460             0x5460
+#define PCI_CHIP_RV370_5461             0x5461
+#define PCI_CHIP_RV370_5462             0x5462
+#define PCI_CHIP_RV370_5463             0x5463
+#define PCI_CHIP_RV370_5464             0x5464
+#define PCI_CHIP_RV370_5465             0x5465
+#define PCI_CHIP_RV370_5466             0x5466
+#define PCI_CHIP_RV370_5467             0x5467
+#define PCI_CHIP_R423_UH                0x5548
+#define PCI_CHIP_R423_UI                0x5549
+#define PCI_CHIP_R423_UJ                0x554A
+#define PCI_CHIP_R423_UK                0x554B
+#define PCI_CHIP_R423_UQ                0x5551
+#define PCI_CHIP_R423_UR                0x5552
+#define PCI_CHIP_R423_UT                0x5554
 #define PCI_CHIP_MACH64VT		0x5654
 #define PCI_CHIP_MACH64VU		0x5655
 #define PCI_CHIP_MACH64VV		0x5656
@@ -155,14 +191,21 @@
 #define PCI_CHIP_RS300_5835		0x5835
 #define PCI_CHIP_RS300_5836		0x5836
 #define PCI_CHIP_RS300_5837		0x5837
+#define PCI_CHIP_RV370_5B60             0x5B60
+#define PCI_CHIP_RV370_5B61             0x5B61
+#define PCI_CHIP_RV370_5B62             0x5B62
+#define PCI_CHIP_RV370_5B63             0x5B63
+#define PCI_CHIP_RV370_5B64             0x5B64
+#define PCI_CHIP_RV370_5B65             0x5B65
+#define PCI_CHIP_RV370_5B66             0x5B66
+#define PCI_CHIP_RV370_5B67             0x5B67
 #define PCI_CHIP_RV280_5960		0x5960
 #define PCI_CHIP_RV280_5961		0x5961
 #define PCI_CHIP_RV280_5962		0x5962
-#define PCI_CHIP_RV280_5963		0x5963
 #define PCI_CHIP_RV280_5964		0x5964
-#define PCI_CHIP_RV280_5968		0x5968
-#define PCI_CHIP_RV280_5969		0x5969
-#define PCI_CHIP_RV280_596A		0x596A
-#define PCI_CHIP_RV280_596B		0x596B
 #define PCI_CHIP_RV280_5C61		0x5C61
 #define PCI_CHIP_RV280_5C63		0x5C63
+#define PCI_CHIP_R423_5D57              0x5D57
+#define PCI_CHIP_RS350_7834             0x7834
+#define PCI_CHIP_RS350_7835             0x7835
+