f3846d8a8ca6bffee36d39116f86589a37a6d7e5
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 04d3120..62f8ffd 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -4,6 +4,12 @@
 
 menu "Graphics support"
 
+config RADEON_LL
+	tristate "Radeon lowlevel driver"
+	depends on PCI
+	---help---
+	   Lowlevel driver for radeon card
+
 config FB
 	tristate "Support for frame buffer devices"
 	---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b018df4..b87b131 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -4,6 +4,7 @@
 
 # Each configuration option enables a list of files.
 
+obj-y				  += vga_lowlevel.o
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
 obj-$(CONFIG_SYSFS)		  += backlight/
@@ -100,3 +101,5 @@ obj-$(CONFIG_FB_OF)               += off
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
+
+obj-$(CONFIG_RADEON_LL)		  += radeon_lowlevel.o
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index 3ca27cb..72a1574 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -203,9 +203,9 @@ void radeonfb_engine_reset(struct radeon
 	host_path_cntl = INREG(HOST_PATH_CNTL);
 	rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
 
-	if (rinfo->family == CHIP_FAMILY_R300 ||
-	    rinfo->family == CHIP_FAMILY_R350 ||
-	    rinfo->family == CHIP_FAMILY_RV350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_R300 ||
+	    rinfo->lowlevel->family == CHIP_FAMILY_R350 ||
+	    rinfo->lowlevel->family == CHIP_FAMILY_RV350) {
 		u32 tmp;
 
 		OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
@@ -241,9 +241,9 @@ void radeonfb_engine_reset(struct radeon
 	INREG(HOST_PATH_CNTL);
 	OUTREG(HOST_PATH_CNTL, host_path_cntl);
 
-	if (rinfo->family != CHIP_FAMILY_R300 ||
-	    rinfo->family != CHIP_FAMILY_R350 ||
-	    rinfo->family != CHIP_FAMILY_RV350)
+	if (rinfo->lowlevel->family != CHIP_FAMILY_R300 ||
+	    rinfo->lowlevel->family != CHIP_FAMILY_R350 ||
+	    rinfo->lowlevel->family != CHIP_FAMILY_RV350)
 		OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
 
 	OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
@@ -260,9 +260,9 @@ void radeonfb_engine_init (struct radeon
 	radeonfb_engine_reset(rinfo);
 
 	radeon_fifo_wait (1);
-	if ((rinfo->family != CHIP_FAMILY_R300) &&
-	    (rinfo->family != CHIP_FAMILY_R350) &&
-	    (rinfo->family != CHIP_FAMILY_RV350))
+	if ((rinfo->lowlevel->family != CHIP_FAMILY_R300) &&
+	    (rinfo->lowlevel->family != CHIP_FAMILY_R350) &&
+	    (rinfo->lowlevel->family != CHIP_FAMILY_RV350))
 		OUTREG(RB2D_DSTCACHE_MODE, 0);
 
 	radeon_fifo_wait (3);
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 47a6b12..e4aa657 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -103,135 +103,6 @@
 #define MAX_MAPPED_VRAM	(2048*2048*4)
 #define MIN_MAPPED_VRAM	(1024*768*1)
 
-#define CHIP_DEF(id, family, flags)					\
-	{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
-
-static struct pci_device_id radeonfb_pci_table[] = {
-	/* Mobility M6 */
-	CHIP_DEF(PCI_CHIP_RADEON_LY, 	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RADEON_LZ,	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* Radeon VE/7000 */
-	CHIP_DEF(PCI_CHIP_RV100_QY, 	RV100,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV100_QZ, 	RV100,	CHIP_HAS_CRTC2),
-	/* Radeon IGP320M (U1) */
-	CHIP_DEF(PCI_CHIP_RS100_4336,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* Radeon IGP320 (A3) */
-	CHIP_DEF(PCI_CHIP_RS100_4136,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP), 
-	/* IGP330M/340M/350M (U2) */
-	CHIP_DEF(PCI_CHIP_RS200_4337,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* IGP330/340/350 (A4) */
-	CHIP_DEF(PCI_CHIP_RS200_4137,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
-	/* Mobility 7000 IGP */
-	CHIP_DEF(PCI_CHIP_RS250_4437,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
-	/* 7000 IGP (A4+) */
-	CHIP_DEF(PCI_CHIP_RS250_4237,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
-	/* 8500 AIW */
-	CHIP_DEF(PCI_CHIP_R200_BB,	R200,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R200_BC,	R200,	CHIP_HAS_CRTC2),
-	/* 8700/8800 */
-	CHIP_DEF(PCI_CHIP_R200_QH,	R200,	CHIP_HAS_CRTC2),
-	/* 8500 */
-	CHIP_DEF(PCI_CHIP_R200_QL,	R200,	CHIP_HAS_CRTC2),
-	/* 9100 */
-	CHIP_DEF(PCI_CHIP_R200_QM,	R200,	CHIP_HAS_CRTC2),
-	/* Mobility M7 */
-	CHIP_DEF(PCI_CHIP_RADEON_LW,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RADEON_LX,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 7500 */
-	CHIP_DEF(PCI_CHIP_RV200_QW,	RV200,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV200_QX,	RV200,	CHIP_HAS_CRTC2),
-	/* Mobility M9 */
-	CHIP_DEF(PCI_CHIP_RV250_Ld,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV250_Le,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV250_Lf,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV250_Lg,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 9000/Pro */
-	CHIP_DEF(PCI_CHIP_RV250_If,	RV250,	CHIP_HAS_CRTC2),
-	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),
-	/* 9200 */
-	CHIP_DEF(PCI_CHIP_RV280_5960,	RV280,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV280_5961,	RV280,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV280_5962,	RV280,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV280_5964,	RV280,	CHIP_HAS_CRTC2),
-	/* 9500 */
-	CHIP_DEF(PCI_CHIP_R300_AD,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_AE,	R300,	CHIP_HAS_CRTC2),
-	/* 9600TX / FireGL Z1 */
-	CHIP_DEF(PCI_CHIP_R300_AF,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_AG,	R300,	CHIP_HAS_CRTC2),
-	/* 9700/9500/Pro/FireGL X1 */
-	CHIP_DEF(PCI_CHIP_R300_ND,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_NE,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_NF,	R300,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R300_NG,	R300,	CHIP_HAS_CRTC2),
-	/* Mobility M10/M11 */
-	CHIP_DEF(PCI_CHIP_RV350_NP,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NQ,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NR,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NS,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NT,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	CHIP_DEF(PCI_CHIP_RV350_NV,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
-	/* 9600/FireGL T2 */
-	CHIP_DEF(PCI_CHIP_RV350_AP,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AQ,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV360_AR,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AS,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AT,	RV350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_RV350_AV,	RV350,	CHIP_HAS_CRTC2),
-	/* 9800/Pro/FileGL X2 */
-	CHIP_DEF(PCI_CHIP_R350_AH,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_AI,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_AJ,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_AK,	R350,	CHIP_HAS_CRTC2),
-	CHIP_DEF(PCI_CHIP_R350_NH,	R350,	CHIP_HAS_CRTC2),
-	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),
-	CHIP_DEF(PCI_CHIP_RADEON_QF,	RADEON,	0),
-	CHIP_DEF(PCI_CHIP_RADEON_QG,	RADEON,	0),
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, radeonfb_pci_table);
-
 
 typedef struct {
 	u16 reg;
@@ -304,6 +175,7 @@ static int __devinit radeon_map_ROM(stru
 	u16 dptr;
 	u8 rom_type;
 	size_t rom_size;
+	struct pci_dev *pdev = rinfo->lowlevel->vll.pdev;
 
 	/* If this is a primary card, there is a shadow copy of the
 	 * ROM somewhere in the first meg. We will just ignore the copy
@@ -321,7 +193,7 @@ static int __devinit radeon_map_ROM(stru
 	rom = pci_map_rom(dev, &rom_size);
 	if (!rom) {
 		printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
-		       pci_name(rinfo->pdev));
+		       pci_name(pdev));
 		return -ENOMEM;
 	}
 	
@@ -330,7 +202,7 @@ static int __devinit radeon_map_ROM(stru
 	/* Very simple test to make sure it appeared */
 	if (BIOS_IN16(0) != 0xaa55) {
 		printk(KERN_ERR "radeonfb (%s): Invalid ROM signature %x should be"
-		       "0xaa55\n", pci_name(rinfo->pdev), BIOS_IN16(0));
+		       "0xaa55\n", pci_name(pdev), BIOS_IN16(0));
 		goto failed;
 	}
 	/* Look for the PCI data to check the ROM type */
@@ -362,7 +234,7 @@ static int __devinit radeon_map_ROM(stru
 	 */
 	if (BIOS_IN32(dptr) !=  (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
 		printk(KERN_WARNING "radeonfb (%s): PCI DATA signature in ROM"
-		       "incorrect: %08x\n", pci_name(rinfo->pdev), BIOS_IN32(dptr));
+		       "incorrect: %08x\n", pci_name(pdev), BIOS_IN32(dptr));
 		goto anyway;
 	}
 	rom_type = BIOS_IN8(dptr + 0x14);
@@ -530,7 +402,7 @@ static int __devinit radeon_probe_pll_pa
 	}
 
 	ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
-	radeon_pll_errata_after_index(rinfo);
+	radeon_pll_errata_after_index(rinfo->lowlevel);
 
 	n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
 	m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -602,7 +474,7 @@ static void __devinit radeon_get_pllinfo
 	 * incomplete, however.  It does provide ppll_max and _min values
 	 * even for most other methods, however.
 	 */
-	switch (rinfo->chipset) {
+	switch (rinfo->lowlevel->chipset) {
 	case PCI_DEVICE_ID_ATI_RADEON_QW:
 	case PCI_DEVICE_ID_ATI_RADEON_QX:
 		rinfo->pll.ppll_max = 35000;
@@ -878,7 +750,7 @@ static int radeonfb_ioctl (struct inode 
 		 *        routing to second output
 		 */
 		case FBIO_RADEON_SET_MIRROR:
-			if (!rinfo->is_mobility)
+			if (!rinfo->lowlevel->is_mobility)
 				return -EINVAL;
 
 			rc = get_user(value, (__u32 __user *)arg);
@@ -915,7 +787,7 @@ static int radeonfb_ioctl (struct inode 
 
 			return 0;
 		case FBIO_RADEON_GET_MIRROR:
-			if (!rinfo->is_mobility)
+			if (!rinfo->lowlevel->is_mobility)
 				return -EINVAL;
 
 			tmp = INREG(LVDS_GEN_CNTL);
@@ -1019,7 +891,7 @@ int radeon_screen_blank(struct radeonfb_
 			 * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
 			 */
 			tmp_pix_clks = INPLL(PIXCLKS_CNTL);
-			if (rinfo->is_mobility || rinfo->is_IGP)
+			if (rinfo->lowlevel->is_mobility || rinfo->lowlevel->is_IGP)
 				OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
 			val &= ~(LVDS_BL_MOD_EN);
 			OUTREG(LVDS_GEN_CNTL, val);
@@ -1033,7 +905,7 @@ int radeon_screen_blank(struct radeonfb_
 				  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)
+			if (rinfo->lowlevel->is_mobility || rinfo->lowlevel->is_IGP)
 				OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
 		}
 		break;
@@ -1138,14 +1010,14 @@ static int radeonfb_setcolreg (unsigned 
 	int rc;
 
         if (!rinfo->asleep) {
-		if (rinfo->is_mobility) {
+		if (rinfo->lowlevel->is_mobility) {
 			vclk_cntl = INPLL(VCLK_ECP_CNTL);
 			OUTPLL(VCLK_ECP_CNTL,
 			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
 		}
 
 		/* Make sure we are on first palette */
-		if (rinfo->has_CRTC2) {
+		if (rinfo->lowlevel->has_CRTC2) {
 			dac_cntl2 = INREG(DAC_CNTL2);
 			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
 			OUTREG(DAC_CNTL2, dac_cntl2);
@@ -1154,7 +1026,7 @@ static int radeonfb_setcolreg (unsigned 
 
 	rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo);
 
-	if (!rinfo->asleep && rinfo->is_mobility)
+	if (!rinfo->asleep && rinfo->lowlevel->is_mobility)
 		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
 
 	return rc;
@@ -1168,14 +1040,14 @@ static int radeonfb_setcmap(struct fb_cm
 	int i, start, rc = 0;
 
         if (!rinfo->asleep) {
-		if (rinfo->is_mobility) {
+		if (rinfo->lowlevel->is_mobility) {
 			vclk_cntl = INPLL(VCLK_ECP_CNTL);
 			OUTPLL(VCLK_ECP_CNTL,
 			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
 		}
 
 		/* Make sure we are on first palette */
-		if (rinfo->has_CRTC2) {
+		if (rinfo->lowlevel->has_CRTC2) {
 			dac_cntl2 = INREG(DAC_CNTL2);
 			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
 			OUTREG(DAC_CNTL2, dac_cntl2);
@@ -1202,7 +1074,7 @@ static int radeonfb_setcmap(struct fb_cm
 			break;
 	}
 
-	if (!rinfo->asleep && rinfo->is_mobility)
+	if (!rinfo->asleep && rinfo->lowlevel->is_mobility)
 		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);
 
 	return rc;
@@ -1239,7 +1111,7 @@ static void radeon_save_state (struct ra
 
 	/* PLL regs */
 	save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
-	radeon_pll_errata_after_index(rinfo);
+	radeon_pll_errata_after_index(rinfo->lowlevel);
 	save->ppll_div_3 = INPLL(PPLL_DIV_3);
 	save->ppll_ref_div = INPLL(PPLL_REF_DIV);
 }
@@ -1252,7 +1124,7 @@ static void radeon_write_pll_regs(struct
 	radeon_fifo_wait(20);
 
 	/* Workaround from XFree */
-	if (rinfo->is_mobility) {
+	if (rinfo->lowlevel->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
@@ -1269,8 +1141,8 @@ static void radeon_write_pll_regs(struct
 			OUTREGP(CLOCK_CNTL_INDEX,
 				mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
 				~PPLL_DIV_SEL_MASK);
-			radeon_pll_errata_after_index(rinfo);
-			radeon_pll_errata_after_data(rinfo);
+			radeon_pll_errata_after_index(rinfo->lowlevel);
+			radeon_pll_errata_after_data(rinfo->lowlevel);
             		return;
 		}
 	}
@@ -1287,14 +1159,14 @@ static void radeon_write_pll_regs(struct
 	OUTREGP(CLOCK_CNTL_INDEX,
 		mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
 		~PPLL_DIV_SEL_MASK);
-	radeon_pll_errata_after_index(rinfo);
-	radeon_pll_errata_after_data(rinfo);
+	radeon_pll_errata_after_index(rinfo->lowlevel);
+	radeon_pll_errata_after_data(rinfo->lowlevel);
 
 	/* Set PPLL ref. div */
-	if (rinfo->family == CHIP_FAMILY_R300 ||
-	    rinfo->family == CHIP_FAMILY_RS300 ||
-	    rinfo->family == CHIP_FAMILY_R350 ||
-	    rinfo->family == CHIP_FAMILY_RV350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_R300 ||
+	    rinfo->lowlevel->family == CHIP_FAMILY_RS300 ||
+	    rinfo->lowlevel->family == CHIP_FAMILY_R350 ||
+	    rinfo->lowlevel->family == CHIP_FAMILY_RV350) {
 		if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
 			/* When restoring console mode, use saved PPLL_REF_DIV
 			 * setting.
@@ -1454,7 +1326,7 @@ static void radeon_calc_pll_regs(struct 
 	 * divider. I'll find a better fix once I have more infos on the
 	 * real cause of the problem.
 	 */
-	while (rinfo->has_CRTC2) {
+	while (rinfo->lowlevel->has_CRTC2) {
 		u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);
 		u32 disp_output_cntl;
 		int source;
@@ -1465,10 +1337,10 @@ static void radeon_calc_pll_regs(struct 
 		/* Not all chip revs have the same format for this register,
 		 * extract the source selection
 		 */
-		if (rinfo->family == CHIP_FAMILY_R200 ||
-		    rinfo->family == CHIP_FAMILY_R300 ||
-		    rinfo->family == CHIP_FAMILY_R350 ||
-		    rinfo->family == CHIP_FAMILY_RV350) {
+		if (rinfo->lowlevel->family == CHIP_FAMILY_R200 ||
+		    rinfo->lowlevel->family == CHIP_FAMILY_R300 ||
+		    rinfo->lowlevel->family == CHIP_FAMILY_R350 ||
+		    rinfo->lowlevel->family == CHIP_FAMILY_RV350) {
 			source = (fp2_gen_cntl >> 10) & 0x3;
 			/* sourced from transform unit, check for transform unit
 			 * own source
@@ -1791,8 +1663,8 @@ static int radeonfb_set_par(struct fb_in
 					FP_CRTC_DONT_SHADOW_HEND |
 					FP_PANEL_FORMAT);
 
-		if (IS_R300_VARIANT(rinfo) ||
-		    (rinfo->family == CHIP_FAMILY_R200)) {
+		if (IS_R300_VARIANT(rinfo->lowlevel) ||
+		    (rinfo->lowlevel->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;
@@ -1814,8 +1686,8 @@ static int radeonfb_set_par(struct fb_in
 			newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
 			newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
 			/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
-			if (IS_R300_VARIANT(rinfo) ||
-			    (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
+			if (IS_R300_VARIANT(rinfo->lowlevel) ||
+			    (rinfo->lowlevel->family == CHIP_FAMILY_R200) || !rinfo->lowlevel->has_CRTC2)
 				newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN;
 			else
 				newmode->tmds_transmitter_cntl |= TMDS_PLL_EN;
@@ -1851,7 +1723,7 @@ static int radeonfb_set_par(struct fb_in
 
 #ifdef CONFIG_BOOTX_TEXT
 	/* Update debug text engine */
-	btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres,
+	btext_update_display(rinfo->lowlevel->fb_base_phys, mode->xres, mode->yres,
 			     rinfo->depth, info->fix.line_length);
 #endif
 
@@ -1893,7 +1765,7 @@ static int __devinit radeon_set_fbinfo (
 	info->screen_size = rinfo->mapped_vram;
 	/* Fill fix common fields */
 	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
-        info->fix.smem_start = rinfo->fb_base_phys;
+        info->fix.smem_start = rinfo->lowlevel->fb_base_phys;
         info->fix.smem_len = rinfo->video_ram;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
         info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -1901,7 +1773,7 @@ static int __devinit radeon_set_fbinfo (
         info->fix.ypanstep = 1;
         info->fix.ywrapstep = 0;
         info->fix.type_aux = 0;
-        info->fix.mmio_start = rinfo->mmio_base_phys;
+        info->fix.mmio_start = rinfo->lowlevel->mmio_base_phys;
         info->fix.mmio_len = RADEON_REGSIZE;
 	info->fix.accel = FB_ACCEL_ATI_RADEON;
 
@@ -1949,10 +1821,10 @@ static int radeon_set_backlight_enable(i
 	 * out in what direction backlight should work on a given
 	 * panel ?
 	 */
-	if ((rinfo->family == CHIP_FAMILY_RV200 ||
-	     rinfo->family == CHIP_FAMILY_RV250 ||
-	     rinfo->family == CHIP_FAMILY_RV280 ||
-	     rinfo->family == CHIP_FAMILY_RV350) &&
+	if ((rinfo->lowlevel->family == CHIP_FAMILY_RV200 ||
+	     rinfo->lowlevel->family == CHIP_FAMILY_RV250 ||
+	     rinfo->lowlevel->family == CHIP_FAMILY_RV280 ||
+	     rinfo->lowlevel->family == CHIP_FAMILY_RV350) &&
 	    !machine_is_compatible("PowerBook4,3") &&
 	    !machine_is_compatible("PowerBook6,3") &&
 	    !machine_is_compatible("PowerBook6,5"))
@@ -1992,7 +1864,7 @@ static int radeon_set_backlight_enable(i
 		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
 		*/
 		tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
-		if (rinfo->is_mobility || rinfo->is_IGP)
+		if (rinfo->lowlevel->is_mobility || rinfo->lowlevel->is_IGP)
 			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
 		lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
 		lvds_gen_cntl |= (conv_table[0] <<
@@ -2006,7 +1878,7 @@ static int radeon_set_backlight_enable(i
 		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)
+		if (rinfo->lowlevel->is_mobility || rinfo->lowlevel->is_IGP)
 			OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
 	}
 	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
@@ -2044,7 +1916,7 @@ static void fixup_memory_mappings(struct
 	u32 agp_base;
 
 	/* First, we disable display to avoid interfering */
-	if (rinfo->has_CRTC2) {
+	if (rinfo->lowlevel->has_CRTC2) {
 		save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL);
 		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B);
 	}
@@ -2086,12 +1958,12 @@ static void fixup_memory_mappings(struct
 	 */
 #ifdef SET_MC_FB_FROM_APERTURE
 	OUTREG(DISPLAY_BASE_ADDR, aper_base);
-	if (rinfo->has_CRTC2)
+	if (rinfo->lowlevel->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)
+	if (rinfo->lowlevel->has_CRTC2)
 		OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);
 	OUTREG(OV0_BASE_ADDR, 0);
 #endif
@@ -2100,7 +1972,7 @@ static void fixup_memory_mappings(struct
 	/* Restore display settings */
 	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl);
 	OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl);
-	if (rinfo->has_CRTC2)
+	if (rinfo->lowlevel->has_CRTC2)
 		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);	
 
 	RTRACE("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
@@ -2114,11 +1986,12 @@ static void fixup_memory_mappings(struct
 static void radeon_identify_vram(struct radeonfb_info *rinfo)
 {
 	u32 tmp;
+	struct pci_dev *pdev = rinfo->lowlevel->vll.pdev;
 
 	/* framebuffer size */
-        if ((rinfo->family == CHIP_FAMILY_RS100) ||
-            (rinfo->family == CHIP_FAMILY_RS200) ||
-            (rinfo->family == CHIP_FAMILY_RS300)) {
+        if ((rinfo->lowlevel->family == CHIP_FAMILY_RS100) ||
+            (rinfo->lowlevel->family == CHIP_FAMILY_RS200) ||
+            (rinfo->lowlevel->family == CHIP_FAMILY_RS300)) {
           u32 tom = INREG(NB_TOM);
           tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
 
@@ -2131,8 +2004,8 @@ static void radeon_identify_vram(struct 
           /* 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)) {
+          if ((rinfo->lowlevel->family == CHIP_FAMILY_RS100) ||
+              (rinfo->lowlevel->family == CHIP_FAMILY_RS200)) {
              /* This is to workaround the asic bug for RMX, some versions
                 of BIOS dosen't have this register initialized correctly.
              */
@@ -2151,7 +2024,7 @@ static void radeon_identify_vram(struct 
 	 * reporting no ram
 	 */
 	if (rinfo->video_ram == 0) {
-		switch (rinfo->pdev->device) {
+		switch (pdev->device) {
 	       	case PCI_CHIP_RADEON_LY:
 		case PCI_CHIP_RADEON_LZ:
 	       		rinfo->video_ram = 8192 * 1024;
@@ -2165,14 +2038,14 @@ static void radeon_identify_vram(struct 
 	/*
 	 * Now try to identify VRAM type
 	 */
-	if (rinfo->is_IGP || (rinfo->family >= CHIP_FAMILY_R300) ||
+	if (rinfo->lowlevel->is_IGP || (rinfo->lowlevel->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)) {
+	if (IS_R300_VARIANT(rinfo->lowlevel)) {
 		tmp &=  R300_MEM_NUM_CHANNELS_MASK;
 		switch (tmp) {
 		case 0:  rinfo->vram_width = 64; break;
@@ -2180,9 +2053,9 @@ static void radeon_identify_vram(struct 
 		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)){
+	} else if ((rinfo->lowlevel->family == CHIP_FAMILY_RV100) ||
+		   (rinfo->lowlevel->family == CHIP_FAMILY_RS100) ||
+		   (rinfo->lowlevel->family == CHIP_FAMILY_RS200)){
 		if (tmp & RV100_MEM_HALF_MODE)
 			rinfo->vram_width = 32;
 		else
@@ -2199,7 +2072,7 @@ static void radeon_identify_vram(struct 
 	 */
 
 	RTRACE("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n",
-	       pci_name(rinfo->pdev),
+	       pci_name(pdev),
 	       rinfo->video_ram / 1024,
 	       rinfo->vram_ddr ? "DDR" : "SDRAM",
 	       rinfo->vram_width);
@@ -2265,24 +2138,17 @@ static struct bin_attribute edid2_attr =
 };
 
 
-static int radeonfb_pci_register (struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
+static int radeonfb_register(struct vll_driver *vdrv, struct vll_dev *vdev)
 {
 	struct fb_info *info;
 	struct radeonfb_info *rinfo;
+	struct pci_dev *pdev = vdev->dev->parent->pdev;
 	int ret;
-
-	RTRACE("radeonfb_pci_register BEGIN\n");
 	
-	/* Enable device in PCI config */
-	ret = pci_enable_device(pdev);
-	if (ret < 0) {
-		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);
+	printk("radeonfb_register BEGIN %p\n", pdev);
+	//	RTRACE("radeonfb_pci_register BEGIN\n");
+	
+	info = framebuffer_alloc(sizeof(struct radeonfb_info), &vdev->dev);
 	if (!info) {
 		printk (KERN_ERR "radeonfb (%s): could not allocate memory\n",
 			pci_name(pdev));
@@ -2290,63 +2156,18 @@ static int radeonfb_pci_register (struct
 		goto err_disable;
 	}
 	rinfo = info->par;
-	rinfo->info = info;	
-	rinfo->pdev = pdev;
+	rinfo->info = info;
 	
-	spin_lock_init(&rinfo->reg_lock);
 	init_timer(&rinfo->lvds_timer);
 	rinfo->lvds_timer.function = radeon_lvds_timer_func;
 	rinfo->lvds_timer.data = (unsigned long)rinfo;
 
 	strcpy(rinfo->name, "ATI Radeon XX ");
-	rinfo->name[11] = ent->device >> 8;
-	rinfo->name[12] = ent->device & 0xFF;
-	rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;
-	rinfo->chipset = pdev->device;
-	rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
-	rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
-	rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
-
-	/* Set base addrs */
-	rinfo->fb_base_phys = pci_resource_start (pdev, 0);
-	rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
-
-	/* request the mem regions */
-	ret = pci_request_regions(pdev, "radeonfb");
-	if (ret < 0) {
-		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 (%s): cannot map MMIO\n", pci_name(rinfo->pdev));
-		ret = -EIO;
-		goto err_release_pci;
-	}
+	rinfo->name[11] = pdev->device >> 8;
+	rinfo->name[12] = pdev->device & 0xFF;
 
 	rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
 
-	/*
-	 * Check for errata
-	 */
-	rinfo->errata = 0;
-	if (rinfo->family == CHIP_FAMILY_R300 &&
-	    (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
-	    == CFG_ATI_REV_A11)
-		rinfo->errata |= CHIP_ERRATA_R300_CG;
-
-	if (rinfo->family == CHIP_FAMILY_RV200 ||
-	    rinfo->family == CHIP_FAMILY_RS200)
-		rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
-
-	if (rinfo->family == CHIP_FAMILY_RV100 ||
-	    rinfo->family == CHIP_FAMILY_RS100 ||
-	    rinfo->family == CHIP_FAMILY_RS200)
-		rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
-
 #ifdef CONFIG_PPC_OF
 	/* On PPC, we obtain the OF device-node pointer to the firmware
 	 * data for this chip
@@ -2354,7 +2175,7 @@ static int radeonfb_pci_register (struct
 	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));
+		       pci_name(pdev));
 
 	/* On PPC, the firmware sets up a memory mapping that tends
 	 * to cause lockups when enabling the engine. We reconfigure
@@ -2369,19 +2190,19 @@ static int radeonfb_pci_register (struct
 	rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
 
 	do {
-		rinfo->fb_base = ioremap (rinfo->fb_base_phys,
+		rinfo->fb_base = ioremap (rinfo->lowlevel->fb_base_phys,
 					  rinfo->mapped_vram);
 	} while (   rinfo->fb_base == 0 &&
 		  ((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
 
 	if (rinfo->fb_base == NULL) {
 		printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
-			pci_name(rinfo->pdev));
+			pci_name(pdev));
 		ret = -EIO;
 		goto err_unmap_rom;
 	}
 
-	RTRACE("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev),
+	RTRACE("radeonfb (%s): mapped %ldk videoram\n", pci_name(pdev),
 	       rinfo->mapped_vram/1024);
 
 	/*
@@ -2395,7 +2216,7 @@ static int radeonfb_pci_register (struct
 	 * archs who would store that elsewhere and/or could initialize
 	 * more than one adapter during boot).
 	 */
-	if (!rinfo->is_mobility)
+	if (!rinfo->lowlevel->is_mobility)
 		radeon_map_ROM(rinfo, pdev);
 
 	/*
@@ -2412,7 +2233,7 @@ static int radeonfb_pci_register (struct
 	/* If both above failed, try the BIOS ROM again for mobility
 	 * chips
 	 */
-	if (rinfo->bios_seg == NULL && rinfo->is_mobility)
+	if (rinfo->bios_seg == NULL && rinfo->lowlevel->is_mobility)
 		radeon_map_ROM(rinfo, pdev);
 
 	/* Get informations about the board's PLL */
@@ -2434,9 +2255,9 @@ static int radeonfb_pci_register (struct
 
 	/* Register some sysfs stuff (should be done better) */
 	if (rinfo->mon1_EDID)
-		sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr);
+		sysfs_create_bin_file(&pdev->dev.kobj, &edid1_attr);
 	if (rinfo->mon2_EDID)
-		sysfs_create_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr);
+		sysfs_create_bin_file(&pdev->dev.kobj, &edid2_attr);
 
 	/* save current mode regs before we switch into the new one
 	 * so we can restore this upon __exit
@@ -2449,22 +2270,22 @@ static int radeonfb_pci_register (struct
 		/* -2 is special: means  ON on mobility chips and do not
 		 * change on others
 		 */
-		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
+		radeonfb_pm_init(rinfo, rinfo->lowlevel->is_mobility ? 1 : -1);
 	} else
 		radeonfb_pm_init(rinfo, default_dynclk);
 
-	pci_set_drvdata(pdev, info);
+	vll_set_drvdata(vdev, info);
 
 	/* Register with fbdev layer */
 	ret = register_framebuffer(info);
 	if (ret < 0) {
 		printk (KERN_ERR "radeonfb (%s): could not register framebuffer\n",
-			pci_name(rinfo->pdev));
+			pci_name(pdev));
 		goto err_unmap_fb;
 	}
 
 #ifdef CONFIG_MTRR
-	rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
+	rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->lowlevel->fb_base_phys,
 						 rinfo->video_ram,
 						 MTRR_TYPE_WRCOMB, 1);
 #endif
@@ -2478,7 +2299,7 @@ static int radeonfb_pci_register (struct
 	}
 #endif
 
-	printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
+	printk ("radeonfb (%s): %s\n", pci_name(pdev), rinfo->name);
 
 	if (rinfo->bios_seg)
 		radeon_unmap_ROM(rinfo, pdev);
@@ -2498,9 +2319,9 @@ err_unmap_rom:
 #endif
 	if (rinfo->bios_seg)
 		radeon_unmap_ROM(rinfo, pdev);
-	iounmap(rinfo->mmio_base);
+//	iounmap(rinfo->mmio_base);
 err_release_pci:
-	pci_release_regions(pdev);
+//	pci_release_regions(pdev);
 err_release_fb:
 	framebuffer_release(info);
 err_disable:
@@ -2510,10 +2331,9 @@ err_out:
 }
 
 
-
-static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
+static void __devexit radeonfb_unregister (struct vll_dev *vdev)
 {
-        struct fb_info *info = pci_get_drvdata(pdev);
+	struct fb_info *info = vll_get_drvdata(vdev);
         struct radeonfb_info *rinfo = info->par;
  
         if (!rinfo)
@@ -2540,11 +2360,9 @@ static void __devexit radeonfb_pci_unreg
 
         unregister_framebuffer(info);
 
-        iounmap(rinfo->mmio_base);
+//        iounmap(rinfo->mmio_base);
         iounmap(rinfo->fb_base);
  
- 	pci_release_regions(pdev);
-
 	kfree(rinfo->mon1_EDID);
 	kfree(rinfo->mon2_EDID);
 	if (rinfo->mon1_modedb)
@@ -2554,10 +2372,9 @@ static void __devexit radeonfb_pci_unreg
 #endif        
 	fb_dealloc_cmap(&info->cmap);
         framebuffer_release(info);
-	pci_disable_device(pdev);
 }
 
-
+#if 0
 static struct pci_driver radeonfb_driver = {
 	.name		= "radeonfb",
 	.id_table	= radeonfb_pci_table,
@@ -2568,6 +2385,23 @@ static struct pci_driver radeonfb_driver
 	.resume		= radeonfb_pci_resume,
 #endif /* CONFIG_PM */
 };
+#endif
+
+void *radeonfb_getentrypoints(void)
+{
+	return NULL;
+}
+
+static struct vll_driver radeonfb_driver = {
+	.name = "radeonfb",
+	.type = VGA_FB,
+ 	.probe = radeonfb_register,
+	.remove = __devexit_p(radeonfb_unregister),
+	.suspend = radeonfb_suspend,
+	.resume = radeonfb_resume,
+	.get_entrypoints = radeonfb_getentrypoints,
+};
+  
 
 #ifndef MODULE
 static int __init radeonfb_setup (char *options)
@@ -2615,13 +2449,13 @@ static int __init radeonfb_init (void)
 		return -ENODEV;
 	radeonfb_setup(option);
 #endif
-	return pci_register_driver (&radeonfb_driver);
+	return radeonll_register_driver (&radeonfb_driver);
 }
 
 
 static void __exit radeonfb_exit (void)
 {
-	pci_unregister_driver (&radeonfb_driver);
+	radeonll_unregister_driver (&radeonfb_driver);
 }
 
 module_init(radeonfb_init);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 7622441..6acb451 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -72,12 +72,13 @@ static int radeon_gpio_getsda(void* data
 static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
 {
 	int rc;
+	struct pci_dev *pdev = chan->rinfo->lowlevel->vll.pdev;
 
 	strcpy(chan->adapter.name, name);
 	chan->adapter.owner		= THIS_MODULE;
 	chan->adapter.id		= I2C_ALGO_ATI;
 	chan->adapter.algo_data		= &chan->algo;
-	chan->adapter.dev.parent	= &chan->rinfo->pdev->dev;
+	chan->adapter.dev.parent	= &pdev->dev;
 	chan->algo.setsda		= radeon_gpio_setsda;
 	chan->algo.setscl		= radeon_gpio_setscl;
 	chan->algo.getsda		= radeon_gpio_getsda;
@@ -95,9 +96,9 @@ static int radeon_setup_i2c_bus(struct r
 
 	rc = i2c_bit_add_bus(&chan->adapter);
 	if (rc == 0)
-		dev_dbg(&chan->rinfo->pdev->dev, "I2C bus %s registered.\n", name);
+		dev_dbg(&pdev->dev, "I2C bus %s registered.\n", name);
 	else
-		dev_warn(&chan->rinfo->pdev->dev, "Failed to register I2C bus %s.\n", name);
+		dev_warn(&pdev->dev, "Failed to register I2C bus %s.\n", name);
 	return rc;
 }
 
@@ -143,6 +144,7 @@ void radeon_delete_i2c_busses(struct rad
 static u8 *radeon_do_probe_i2c_edid(struct radeon_i2c_chan *chan)
 {
 	u8 start = 0x0;
+	struct pci_dev *pdev = chan->rinfo->lowlevel->vll.pdev;
 	struct i2c_msg msgs[] = {
 		{
 			.addr	= RADEON_DDC,
@@ -158,14 +160,14 @@ static u8 *radeon_do_probe_i2c_edid(stru
 
 	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
 	if (!buf) {
-		dev_warn(&chan->rinfo->pdev->dev, "Out of memory!\n");
+		dev_warn(&pdev->dev, "Out of memory!\n");
 		return NULL;
 	}
 	msgs[1].buf = buf;
 
 	if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
 		return buf;
-	dev_dbg(&chan->rinfo->pdev->dev, "Unable to read EDID block.\n");
+	dev_dbg(&pdev->dev, "Unable to read EDID block.\n");
 	kfree(buf);
 	return NULL;
 }
@@ -250,7 +252,7 @@ int radeon_probe_i2c_connector(struct ra
 	}
 	if (edid[0x14] & 0x80) {
 		/* Fix detection using BIOS tables */
-		if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
+		if (rinfo->lowlevel->is_mobility /*&& conn == ddc_dvi*/ &&
 		    (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
 			RTRACE("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
 			return MT_LCD;
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index ea7c863..b74b53f 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -329,8 +329,8 @@ static int __devinit radeon_crt_is_conne
 	ulData            |=  (DAC_FORCE_BLANK_OFF_EN
 			       |DAC_FORCE_DATA_EN
 			       |DAC_FORCE_DATA_SEL_MASK);
-	if ((rinfo->family == CHIP_FAMILY_RV250) ||
-	    (rinfo->family == CHIP_FAMILY_RV280))
+	if ((rinfo->lowlevel->family == CHIP_FAMILY_RV250) ||
+	    (rinfo->lowlevel->family == CHIP_FAMILY_RV280))
 	    ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT);
 	else
 	    ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT);
@@ -491,7 +491,7 @@ void __devinit radeon_probe_screens(stru
 		/*
 		 * Old single head cards
 		 */
-		if (!rinfo->has_CRTC2) {
+		if (!rinfo->lowlevel->has_CRTC2) {
 #ifdef CONFIG_PPC_OF
 			if (rinfo->mon1_type == MT_NONE)
 				rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0,
@@ -557,7 +557,7 @@ void __devinit radeon_probe_screens(stru
 				ddc_crt2_used = 1;
 		}
 #endif /* CONFIG_FB_RADEON_I2C */
-		if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility &&
+		if (rinfo->mon1_type == MT_NONE && rinfo->lowlevel->is_mobility &&
 		    ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4))
 		     || (INREG(LVDS_GEN_CNTL) & LVDS_ON))) {
 			rinfo->mon1_type = MT_LCD;
@@ -629,7 +629,7 @@ void __devinit radeon_probe_screens(stru
 	       radeon_get_mon_name(rinfo->mon1_type));
 	if (rinfo->mon1_EDID)
 		printk(KERN_INFO "radeonfb: EDID probed\n");
-	if (!rinfo->has_CRTC2)
+	if (!rinfo->lowlevel->has_CRTC2)
 		return;
 	printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n",
 	       radeon_get_mon_name(rinfo->mon2_type));
@@ -652,7 +652,7 @@ static void radeon_fixup_panel_info(stru
 	 * PPC only for now...
 	 */
 	if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
-	    && rinfo->is_mobility) {
+	    && rinfo->lowlevel->is_mobility) {
 		int ppll_div_sel;
 		u32 ppll_divn;
 		ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 98352af..e8b7c3b 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -32,8 +32,8 @@ static void radeon_pm_disable_dynamic_mo
 	u32 tmp;
 
 	/* RV100 */
-	if ((rinfo->family == CHIP_FAMILY_RV100) && (!rinfo->is_mobility)) {
-		if (rinfo->has_CRTC2) {
+	if ((rinfo->lowlevel->family == CHIP_FAMILY_RV100) && (!rinfo->lowlevel->is_mobility)) {
+		if (rinfo->lowlevel->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;
@@ -50,7 +50,7 @@ static void radeon_pm_disable_dynamic_mo
 		return;
 	}
 	/* R100 */
-	if (!rinfo->has_CRTC2) {
+	if (!rinfo->lowlevel->has_CRTC2) {
                 tmp = INPLL(pllSCLK_CNTL);
                 tmp |= (SCLK_CNTL__FORCE_CP	| SCLK_CNTL__FORCE_HDP	|
 			SCLK_CNTL__FORCE_DISP1	| SCLK_CNTL__FORCE_TOP	|
@@ -63,7 +63,7 @@ static void radeon_pm_disable_dynamic_mo
 		return;
 	}
 	/* RV350 (M10) */
-	if (rinfo->family == CHIP_FAMILY_RV350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_RV350) {
                 /* for RV350/M10, no delays are required. */
                 tmp = INPLL(pllSCLK_CNTL2);
                 tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
@@ -130,7 +130,7 @@ static void radeon_pm_disable_dynamic_mo
 	/* 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) {
+	if (rinfo->lowlevel->is_mobility) {
 		tmp |= 	SCLK_CNTL__FORCE_HDP|
 			SCLK_CNTL__FORCE_DISP1|
 			SCLK_CNTL__FORCE_DISP2|
@@ -147,8 +147,8 @@ static void radeon_pm_disable_dynamic_mo
 			SCLK_CNTL__FORCE_SUBPIC|
 			SCLK_CNTL__FORCE_OV0;
 	}
-	else if (rinfo->family == CHIP_FAMILY_R300 ||
-		   rinfo->family == CHIP_FAMILY_R350) {
+	else if (rinfo->lowlevel->family == CHIP_FAMILY_R300 ||
+		   rinfo->lowlevel->family == CHIP_FAMILY_R350) {
 		tmp |=  SCLK_CNTL__FORCE_HDP   |
 			SCLK_CNTL__FORCE_DISP1 |
 			SCLK_CNTL__FORCE_DISP2 |
@@ -159,7 +159,7 @@ static void radeon_pm_disable_dynamic_mo
     	OUTPLL(pllSCLK_CNTL, tmp);
 	radeon_msleep(16);
 
-	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_R300 || rinfo->lowlevel->family == CHIP_FAMILY_R350) {
 		tmp = INPLL(pllSCLK_CNTL2);
 		tmp |=  SCLK_CNTL2__R300_FORCE_TCL |
 			SCLK_CNTL2__R300_FORCE_GA  |
@@ -173,7 +173,7 @@ static void radeon_pm_disable_dynamic_mo
 	OUTPLL(pllCLK_PIN_CNTL, tmp);
 	radeon_msleep(15);
 
-	if (rinfo->is_IGP) {
+	if (rinfo->lowlevel->is_IGP) {
 		/* Weird  ... X is _un_ forcing clocks here, I think it's
 		 * doing backward. Imitate it for now...
 		 */
@@ -184,7 +184,7 @@ static void radeon_pm_disable_dynamic_mo
 		radeon_msleep(16);
 	}
 	/* Hrm... same shit, X doesn't do that but I have to */
-	else if (rinfo->is_mobility) {
+	else if (rinfo->lowlevel->is_mobility) {
 		tmp = INPLL(pllMCLK_CNTL);
 		tmp |= (MCLK_CNTL__FORCE_MCLKA |
 			MCLK_CNTL__FORCE_MCLKB |
@@ -202,7 +202,7 @@ static void radeon_pm_disable_dynamic_mo
 		radeon_msleep(15);
 	}
 
-	if (rinfo->is_mobility) {
+	if (rinfo->lowlevel->is_mobility) {
 		tmp = INPLL(pllSCLK_MORE_CNTL);
 		tmp |= 	SCLK_MORE_CNTL__FORCE_DISPREGS|
 			SCLK_MORE_CNTL__FORCE_MC_GUI|
@@ -234,7 +234,7 @@ static void radeon_pm_enable_dynamic_mod
 	u32 tmp;
 
 	/* R100 */
-	if (!rinfo->has_CRTC2) {
+	if (!rinfo->lowlevel->has_CRTC2) {
                 tmp = INPLL(pllSCLK_CNTL);
 
 		if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13)
@@ -249,7 +249,7 @@ static void radeon_pm_enable_dynamic_mod
 	}
 
 	/* M10 */
-	if (rinfo->family == CHIP_FAMILY_RV350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_RV350) {
 		tmp = INPLL(pllSCLK_CNTL2);
 		tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
 			 SCLK_CNTL2__R300_FORCE_GA  |
@@ -334,7 +334,7 @@ static void radeon_pm_enable_dynamic_mod
 	}
 
 	/* R300 */
-	if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_R300 || rinfo->lowlevel->family == CHIP_FAMILY_R350) {
 		tmp = INPLL(pllSCLK_CNTL);
 		tmp &= ~(SCLK_CNTL__R300_FORCE_VAP);
 		tmp |= SCLK_CNTL__FORCE_CP;
@@ -371,9 +371,9 @@ static void radeon_pm_enable_dynamic_mod
 	tmp &= ~SCLK_CNTL__FORCEON_MASK;
 
 	/*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
-	if ((rinfo->family == CHIP_FAMILY_RV250 &&
+	if ((rinfo->lowlevel->family == CHIP_FAMILY_RV250 &&
 	     ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) ||
-	    ((rinfo->family == CHIP_FAMILY_RV100) &&
+	    ((rinfo->lowlevel->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;
@@ -381,15 +381,15 @@ static void radeon_pm_enable_dynamic_mod
 	OUTPLL(pllSCLK_CNTL, tmp);
 	radeon_msleep(15);
 
-	if ((rinfo->family == CHIP_FAMILY_RV200) ||
-	    (rinfo->family == CHIP_FAMILY_RV250) ||
-	    (rinfo->family == CHIP_FAMILY_RV280)) {
+	if ((rinfo->lowlevel->family == CHIP_FAMILY_RV200) ||
+	    (rinfo->lowlevel->family == CHIP_FAMILY_RV250) ||
+	    (rinfo->lowlevel->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)) &&
+		if (((rinfo->lowlevel->family == CHIP_FAMILY_RV200) ||
+		     (rinfo->lowlevel->family == CHIP_FAMILY_RV250)) &&
 		    ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13))
 			tmp |= SCLK_MORE_CNTL__FORCEON;
 
@@ -399,8 +399,8 @@ static void radeon_pm_enable_dynamic_mod
 	
 
 	/* RV200::A11 A12, RV250::A11 A12 */
-	if (((rinfo->family == CHIP_FAMILY_RV200) ||
-	     (rinfo->family == CHIP_FAMILY_RV250)) &&
+	if (((rinfo->lowlevel->family == CHIP_FAMILY_RV200) ||
+	     (rinfo->lowlevel->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;
@@ -426,7 +426,7 @@ static void radeon_pm_enable_dynamic_mod
 
 	/* X doesn't do that ... hrm, we do on mobility && Macs */
 #ifdef CONFIG_PPC_OF
-	if (rinfo->is_mobility) {
+	if (rinfo->lowlevel->is_mobility) {
 		tmp  = INPLL(pllMCLK_CNTL);
 		tmp &= ~(MCLK_CNTL__FORCE_MCLKA |
 			 MCLK_CNTL__FORCE_MCLKB |
@@ -507,7 +507,7 @@ static void radeon_pm_save_regs(struct r
 	rinfo->save_regs[37] = INREG(MPP_TB_CONFIG);
 	rinfo->save_regs[38] = INREG(FCP_CNTL);
 
-	if (rinfo->is_mobility) {
+	if (rinfo->lowlevel->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);
@@ -517,7 +517,7 @@ static void radeon_pm_save_regs(struct r
 		rinfo->save_regs[81] = INREG(LVDS_GEN_CNTL);
 	}
 
-	if (rinfo->family >= CHIP_FAMILY_RV200) {
+	if (rinfo->lowlevel->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);
@@ -533,7 +533,7 @@ static void radeon_pm_save_regs(struct r
 	rinfo->save_regs[56] = INREG(PAD_CTLR_MISC);
 	rinfo->save_regs[57] = INREG(FW_CNTL);
 
-	if (rinfo->family >= CHIP_FAMILY_R300) {
+	if (rinfo->lowlevel->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);
@@ -598,7 +598,7 @@ static void radeon_pm_restore_regs(struc
 	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)
+	if (rinfo->lowlevel->family == CHIP_FAMILY_RV350)
 		OUTPLL(SCLK_MORE_CNTL, rinfo->save_regs[34]);
 
 	OUTREG(SURFACE_CNTL, rinfo->save_regs[29]);
@@ -649,9 +649,9 @@ static void radeon_pm_disable_iopad(stru
 static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo)
 {
 	/* Set v2clk to 65MHz */
-	if (rinfo->family <= CHIP_FAMILY_RV280) {
+	if (rinfo->lowlevel->family <= CHIP_FAMILY_RV280) {
 		OUTPLL(pllPIXCLKS_CNTL,
-			 __INPLL(rinfo, pllPIXCLKS_CNTL)
+			 radeon_INPLL(rinfo->lowlevel, pllPIXCLKS_CNTL)
 			 & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK);
 	 
 		OUTPLL(pllP2PLL_REF_DIV, 0x0000000c);
@@ -681,7 +681,7 @@ static void radeon_pm_low_current(struct
 	u32 reg;
 
 	reg  = INREG(BUS_CNTL1);
-	if (rinfo->family <= CHIP_FAMILY_RV280) {
+	if (rinfo->lowlevel->family <= CHIP_FAMILY_RV280) {
 		reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK;
 		reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT);
 	} else {
@@ -761,7 +761,7 @@ static void radeon_pm_setup_for_suspend(
 			SCLK_CNTL__FORCE_TV_SCLK|
 			SCLK_CNTL__FORCE_SUBPIC|
 			SCLK_CNTL__FORCE_OV0;
-	if (rinfo->family <= CHIP_FAMILY_RV280)
+	if (rinfo->lowlevel->family <= CHIP_FAMILY_RV280)
 		sclk_cntl |= SCLK_CNTL__FORCE_RE;
 	else
 		sclk_cntl |= SCLK_CNTL__SE_MAX_DYN_STOP_LAT |
@@ -854,7 +854,7 @@ static void radeon_pm_setup_for_suspend(
 	OUTPLL( pllMCLK_MISC, tmp);
 	
 	/* AGP PLL control */
-	if (rinfo->family <= CHIP_FAMILY_RV280) {
+	if (rinfo->lowlevel->family <= CHIP_FAMILY_RV280) {
 		OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
 
 		OUTREG(BUS_CNTL1,
@@ -1156,7 +1156,7 @@ static void radeon_pm_full_reset_sdram(s
 	OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
   
 	/* This is the code for the Aluminium PowerBooks M10 */
-	if (rinfo->family == CHIP_FAMILY_RV350) {
+	if (rinfo->lowlevel->family == CHIP_FAMILY_RV350) {
 		u32 sdram_mode_reg = rinfo->save_regs[35];
 		static u32 default_mrtable[] =
 			{ 0x21320032,
@@ -1217,7 +1217,7 @@ static void radeon_pm_full_reset_sdram(s
 
 	}
 	/* Here come the desktop RV200 "QW" card */
-	else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) {
+	else if (!rinfo->lowlevel->is_mobility && rinfo->lowlevel->family == CHIP_FAMILY_RV200) {
 		/* Disable refresh */
 		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
 			& ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS;
@@ -1240,7 +1240,7 @@ static void radeon_pm_full_reset_sdram(s
 
 	}
 	/* The M6 */
-	else if (rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV100) {
+	else if (rinfo->lowlevel->is_mobility && rinfo->lowlevel->family == CHIP_FAMILY_RV100) {
 		/* Disable refresh */
 		memRefreshCntl = INREG(EXT_MEM_CNTL) & ~(1 << 20);
 		OUTREG( EXT_MEM_CNTL, memRefreshCntl | (1 << 20));
@@ -1270,7 +1270,7 @@ static void radeon_pm_full_reset_sdram(s
 		OUTREG(EXT_MEM_CNTL, memRefreshCntl);
 	}
 	/* And finally, the M7..M9 models, including M9+ (RV280) */
-	else if (rinfo->is_mobility) {
+	else if (rinfo->lowlevel->is_mobility) {
 
 		/* Disable refresh */
 		memRefreshCntl 	= INREG( MEM_REFRESH_CNTL)
@@ -1290,7 +1290,7 @@ static void radeon_pm_full_reset_sdram(s
 		radeon_pm_yclk_mclk_sync(rinfo);
 
 		/* M6, M7 and M9 so far ... */
-		if (rinfo->family <= CHIP_FAMILY_RV250) {
+		if (rinfo->lowlevel->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);
@@ -1298,7 +1298,7 @@ static void radeon_pm_full_reset_sdram(s
 			radeon_pm_program_mode_reg(rinfo, 0x0032, 1);
 		}
 		/* M9+ (iBook G4) */
-		else if (rinfo->family == CHIP_FAMILY_RV280) {
+		else if (rinfo->lowlevel->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);
@@ -2408,7 +2408,8 @@ static void radeon_set_suspend(struct ra
 	u16 pwr_cmd;
 	u32 tmp;
 	int i;
-
+	struct pci_dev *pdev = rinfo->lowlevel->vll.pdev;
+	
 	if (!rinfo->pm_reg)
 		return;
 
@@ -2418,7 +2419,7 @@ static void radeon_set_suspend(struct ra
 	 */
 	if (suspend) {
 		printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n",
-		       pci_name(rinfo->pdev));
+		       pci_name(pdev));
 
 		/* Disable dynamic power management of clocks for the
 		 * duration of the suspend/resume process
@@ -2430,7 +2431,7 @@ static void radeon_set_suspend(struct ra
 
 		/* Prepare mobility chips for suspend.
 		 */
-		if (rinfo->is_mobility) {
+		if (rinfo->lowlevel->is_mobility) {
 			/* Program V2CLK */
 			radeon_pm_program_v2clk(rinfo);
 		
@@ -2443,7 +2444,7 @@ static void radeon_set_suspend(struct ra
 			/* Prepare chip for power management */
 			radeon_pm_setup_for_suspend(rinfo);
 
-			if (rinfo->family <= CHIP_FAMILY_RV280) {
+			if (rinfo->lowlevel->family <= CHIP_FAMILY_RV280) {
 				/* Reset the MDLL */
 				/* because both INPLL and OUTPLL take the same
 				 * lock, that's why. */
@@ -2454,32 +2455,32 @@ static void radeon_set_suspend(struct ra
 		}
 
 		for (i = 0; i < 64; ++i)
-			pci_read_config_dword(rinfo->pdev, i * 4,
+			pci_read_config_dword(pdev, i * 4,
 					      &rinfo->cfg_save[i]);
 
 		/* Switch PCI power managment to D2. */
-		pci_disable_device(rinfo->pdev);
+		pci_disable_device(pdev);
 		for (;;) {
 			pci_read_config_word(
-				rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
+				pdev, rinfo->pm_reg+PCI_PM_CTRL,
 				&pwr_cmd);
 			if (pwr_cmd & 2)
 				break;			
 			pci_write_config_word(
-				rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL,
+				pdev, rinfo->pm_reg+PCI_PM_CTRL,
 				(pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2);
 			mdelay(500);
 		}
 	} else {
 		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
-		       pci_name(rinfo->pdev));
+		       pci_name(pdev));
 
 		/* Switch back PCI powermanagment to D0 */
 		mdelay(200);
-		pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
+		pci_write_config_word(pdev, rinfo->pm_reg+PCI_PM_CTRL, 0);
 		mdelay(500);
 
-		if (rinfo->family <= CHIP_FAMILY_RV250) {
+		if (rinfo->lowlevel->family <= CHIP_FAMILY_RV250) {
 			/* Reset the SDRAM controller  */
 			radeon_pm_full_reset_sdram(rinfo);
 
@@ -2496,11 +2497,13 @@ static void radeon_set_suspend(struct ra
 
 static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
 {
+	struct pci_dev *pdev = rinfo->lowlevel->vll.pdev;
 	int i;
 	static u32 radeon_cfg_after_resume[64];
 
+
 	for (i = 0; i < 64; ++i)
-		pci_read_config_dword(rinfo->pdev, i * 4,
+		pci_read_config_dword(pdev, i * 4,
 				      &radeon_cfg_after_resume[i]);
 
 	if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4]
@@ -2509,21 +2512,22 @@ static int radeon_restore_pci_cfg(struct
 
 	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,
+			pci_write_config_dword(pdev, i * 4,
 					       rinfo->cfg_save[i]);
 	}
-	pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE,
+	pci_write_config_word(pdev, PCI_CACHE_LINE_SIZE,
 			      rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]);
-	pci_write_config_word(rinfo->pdev, PCI_COMMAND,
+	pci_write_config_word(pdev, PCI_COMMAND,
 			      rinfo->cfg_save[PCI_COMMAND/4]);
 	return 1;
 }
 
 
-int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int radeonfb_suspend(struct vll_dev *vdev, pm_message_t state)
 {
-        struct fb_info *info = pci_get_drvdata(pdev);
+        struct fb_info *info = vll_get_drvdata(vdev);
         struct radeonfb_info *rinfo = info->par;
+	struct pci_dev *pdev = vdev->parent->pdev;
 	int i;
 
 	if (state == pdev->dev.power.power_state)
@@ -2581,7 +2585,7 @@ int radeonfb_pci_suspend(struct pci_dev 
 		mdelay(50);
 		radeon_pm_save_regs(rinfo, 1);
 
-		if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
+		if (rinfo->lowlevel->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));
@@ -2610,16 +2614,17 @@ int radeonfb_pci_suspend(struct pci_dev 
 	return 0;
 }
 
-int radeonfb_pci_resume(struct pci_dev *pdev)
+int radeonfb_resume(struct vll_dev *vdev)
 {
-        struct fb_info *info = pci_get_drvdata(pdev);
+	struct pci_dev *pdev = vdev->parent->pdev;
+        struct fb_info *info = vll_get_drvdata(vdev);
         struct radeonfb_info *rinfo = info->par;
 	int rc = 0;
 
 	if (pdev->dev.power.power_state == 0)
 		return 0;
 
-	if (rinfo->no_schedule) {
+	if (rinfo->lowlevel->no_schedule) {
 		if (try_acquire_console_sem())
 			return 0;
 	} else
@@ -2705,9 +2710,9 @@ static void radeonfb_early_resume(void *
 {
         struct radeonfb_info *rinfo = data;
 
-	rinfo->no_schedule = 1;
+	rinfo->lowlevel->no_schedule = 1;
 	radeonfb_pci_resume(rinfo->pdev);
-	rinfo->no_schedule = 0;
+	rinfo->lowlevel->no_schedule = 0;
 }
 #endif /* CONFIG_PPC_OF */
 
@@ -2715,8 +2720,10 @@ static void radeonfb_early_resume(void *
 
 void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
 {
+	struct pci_dev *pdev = rinfo->lowlevel->vll.pdev;
+
 	/* Find PM registers in config space if any*/
-	rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
+	rinfo->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
 
 	/* Enable/Disable dynamic clocks: TODO add sysfs access */
 	rinfo->dynclk = dynclk;
@@ -2736,8 +2743,8 @@ void radeonfb_pm_init(struct radeonfb_in
 	 */
 #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)
+		if (rinfo->lowlevel->is_mobility && rinfo->pm_reg &&
+		    rinfo->lowlevel->family <= CHIP_FAMILY_RV250)
 			rinfo->pm_mode |= radeon_pm_d2;
 
 		/* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 659bc9f..7ea5002 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -26,67 +26,7 @@
  * Most of the definitions here are adapted right from XFree86 *
  ***************************************************************/
 
-
-/*
- * Chip families. Must fit in the low 16 bits of a long word
- */
-enum radeon_family {
-	CHIP_FAMILY_UNKNOW,
-	CHIP_FAMILY_LEGACY,
-	CHIP_FAMILY_RADEON,
-	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_R200,
-	CHIP_FAMILY_RV250,
-	CHIP_FAMILY_RS300,    /* Radeon 9000 IGP */
-	CHIP_FAMILY_RV280,
-	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
- */
-enum radeon_chip_flags {
-	CHIP_FAMILY_MASK	= 0x0000ffffUL,
-	CHIP_FLAGS_MASK		= 0xffff0000UL,
-	CHIP_IS_MOBILITY	= 0x00010000UL,
-	CHIP_IS_IGP		= 0x00020000UL,
-	CHIP_HAS_CRTC2		= 0x00040000UL,	
-};
-
-/*
- * Errata workarounds
- */
-enum radeon_errata {
-	CHIP_ERRATA_R300_CG		= 0x00000001,
-	CHIP_ERRATA_PLL_DUMMYREADS	= 0x00000002,
-	CHIP_ERRATA_PLL_DELAY		= 0x00000004,
-};
-
-
+#include "../radeon_lowlevel.h"
 /*
  * Monitor types
  */
@@ -276,20 +216,17 @@ enum radeon_pm_mode {
 struct radeonfb_info {
 	struct fb_info		*info;
 
+	struct radeonll_info    *lowlevel;
 	struct radeon_regs 	state;
 	struct radeon_regs	init_state;
 
 	char			name[DEVICE_NAME_SIZE];
 
-	unsigned long		mmio_base_phys;
-	unsigned long		fb_base_phys;
-
-	void __iomem		*mmio_base;
 	void __iomem		*fb_base;
-
 	unsigned long		fb_local_base;
 
-	struct pci_dev		*pdev;
+	struct vll_dev          *vdev;
+
 #ifdef CONFIG_PPC_OF
 	struct device_node	*of_node;
 #endif
@@ -301,10 +238,6 @@ struct radeonfb_info {
 	struct { u8 red, green, blue, pad; }
 				palette[256];
 
-	int			chipset;
-	u8			family;
-	u8			rev;
-	unsigned int		errata;
 	unsigned long		video_ram;
 	unsigned long		mapped_vram;
 	int			vram_width;
@@ -312,9 +245,6 @@ struct radeonfb_info {
 
 	int			pitch, bpp, depth;
 
-	int			has_CRTC2;
-	int			is_mobility;
-	int			is_IGP;
 	int			reversed_DAC;
 	int			reversed_TMDS;
 	struct panel_info	panel_info;
@@ -336,13 +266,9 @@ struct radeonfb_info {
 	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;
-
 	/* Timer used for delayed LVDS operations */
 	struct timer_list	lvds_timer;
 	u32			pending_lvds_gen_cntl;
@@ -374,125 +300,15 @@ struct radeonfb_info {
 #endif
 
 
-/*
- * IO macros
- */
-
-/* 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 || oops_in_progress)
-		mdelay(ms);
-	else
-		msleep(ms);
-}
-
-
-#define INREG8(addr)		readb((rinfo->mmio_base)+addr)
-#define OUTREG8(addr,val)	writeb(val, (rinfo->mmio_base)+addr)
-#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)
-
-/*
- * Note about PLL register accesses:
- *
- * I have removed the spinlock on them on purpose. The driver now
- * expects that it will only manipulate the PLL registers in normal
- * task environment, where radeon_msleep() will be called, protected
- * by a semaphore (currently the console semaphore) so that no conflict
- * will happen on the PLL register index.
- *
- * With the latest changes to the VT layer, this is guaranteed for all
- * calls except the actual drawing/blits which aren't supposed to use
- * the PLL registers anyway
- *
- * This is very important for the workarounds to work properly. The only
- * possible exception to this rule is the call to unblank(), which may
- * be done at irq time if an oops is in progress.
- */
-static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
-{
-	if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
-		return;
-
-	(void)INREG(CLOCK_CNTL_DATA);
-	(void)INREG(CRTC_GEN_CNTL);
-}
-
-static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
-{
-	if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
-		/* we can't deal with posted writes here ... */
-		_radeon_msleep(rinfo, 5);
-	}
-	if (rinfo->errata & CHIP_ERRATA_R300_CG) {
-		u32 save, tmp;
-		save = INREG(CLOCK_CNTL_INDEX);
-		tmp = save & ~(0x3f | PLL_WR_EN);
-		OUTREG(CLOCK_CNTL_INDEX, tmp);
-		tmp = INREG(CLOCK_CNTL_DATA);
-		OUTREG(CLOCK_CNTL_INDEX, save);
-	}
-}
-
-static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
-	u32 data;
-
-	OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
-	radeon_pll_errata_after_index(rinfo);
-	data = INREG(CLOCK_CNTL_DATA);
-	radeon_pll_errata_after_data(rinfo);
-	return data;
-}
-
-static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
-			    u32 val)
-{
-
-	OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
-	radeon_pll_errata_after_index(rinfo);
-	OUTREG(CLOCK_CNTL_DATA, val);
-	radeon_pll_errata_after_data(rinfo);
-}
-
-
-static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
-			     u32 val, u32 mask)
-{
-	unsigned int tmp;
-
-	tmp  = __INPLL(rinfo, index);
-	tmp &= (mask);
-	tmp |= (val);
-	__OUTPLL(rinfo, index, tmp);
-}
-
-
-#define INPLL(addr)			__INPLL(rinfo, addr)
-#define OUTPLL(index, val)		__OUTPLL(rinfo, index, val)
-#define OUTPLLP(index, val, mask)	__OUTPLLP(rinfo, index, val, mask)
+#define INREG8(addr)		radeon_INREG8(rinfo->lowlevel, addr)
+#define OUTREG8(addr,val)	radeon_OUTREG8(rinfo->lowlevel, addr, val)
+#define INREG(addr)		radeon_INREG(rinfo->lowlevel, addr)
+#define OUTREG(addr,val)	radeon_OUTREG(rinfo->lowlevel, addr, val)
+
+#define INPLL(index) radeon_INPLL(rinfo->lowlevel, index)
+#define OUTPLL(index, val) radeon_OUTPLL(rinfo->lowlevel, index, val)
+#define OUTPLLP(index, val, mask) radeon_OUTPLLP(rinfo->lowlevel, index, val, mask)
+#define OUTREGP(addr, val, mask) radeon_OUTREGP(rinfo->lowlevel, addr, val, mask)
 
 
 #define BIOS_IN8(v)  	(readb(rinfo->bios_seg + (v)))
@@ -587,7 +403,7 @@ static inline void _radeon_engine_idle(s
 
 #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)
+#define radeon_msleep(ms)		_radeon_msleep(rinfo->lowlevel,ms)
 
 
 /* I2C Functions */
@@ -596,8 +412,8 @@ extern void radeon_delete_i2c_busses(str
 extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
 
 /* PM Functions */
-extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-extern int radeonfb_pci_resume(struct pci_dev *pdev);
+extern int radeonfb_suspend(struct vll_dev *vdev, pm_message_t state);
+extern int radeonfb_resume(struct vll_dev *vdev);
 extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk);
 extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
 
diff --git a/drivers/video/radeon_lowlevel.c b/drivers/video/radeon_lowlevel.c
new file mode 100644
index 0000000..51f75bc
--- /dev/null
+++ b/drivers/video/radeon_lowlevel.c
@@ -0,0 +1,292 @@
+/* Radeon Lowlevel driver */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "aty/ati_ids.h"
+#include "radeon_lowlevel.h"
+
+#define CHIP_DEF(id, family, flags)					\
+	{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) }
+
+static struct pci_device_id radeonll_pci_table[] = {
+	/* Mobility M6 */
+	CHIP_DEF(PCI_CHIP_RADEON_LY, 	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RADEON_LZ,	RV100,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* Radeon VE/7000 */
+	CHIP_DEF(PCI_CHIP_RV100_QY, 	RV100,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV100_QZ, 	RV100,	CHIP_HAS_CRTC2),
+	/* Radeon IGP320M (U1) */
+	CHIP_DEF(PCI_CHIP_RS100_4336,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* Radeon IGP320 (A3) */
+	CHIP_DEF(PCI_CHIP_RS100_4136,	RS100,	CHIP_HAS_CRTC2 | CHIP_IS_IGP), 
+	/* IGP330M/340M/350M (U2) */
+	CHIP_DEF(PCI_CHIP_RS200_4337,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* IGP330/340/350 (A4) */
+	CHIP_DEF(PCI_CHIP_RS200_4137,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	/* Mobility 7000 IGP */
+	CHIP_DEF(PCI_CHIP_RS250_4437,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
+	/* 7000 IGP (A4+) */
+	CHIP_DEF(PCI_CHIP_RS250_4237,	RS200,	CHIP_HAS_CRTC2 | CHIP_IS_IGP),
+	/* 8500 AIW */
+	CHIP_DEF(PCI_CHIP_R200_BB,	R200,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R200_BC,	R200,	CHIP_HAS_CRTC2),
+	/* 8700/8800 */
+	CHIP_DEF(PCI_CHIP_R200_QH,	R200,	CHIP_HAS_CRTC2),
+	/* 8500 */
+	CHIP_DEF(PCI_CHIP_R200_QL,	R200,	CHIP_HAS_CRTC2),
+	/* 9100 */
+	CHIP_DEF(PCI_CHIP_R200_QM,	R200,	CHIP_HAS_CRTC2),
+	/* Mobility M7 */
+	CHIP_DEF(PCI_CHIP_RADEON_LW,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RADEON_LX,	RV200,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 7500 */
+	CHIP_DEF(PCI_CHIP_RV200_QW,	RV200,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV200_QX,	RV200,	CHIP_HAS_CRTC2),
+	/* Mobility M9 */
+	CHIP_DEF(PCI_CHIP_RV250_Ld,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV250_Le,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV250_Lf,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV250_Lg,	RV250,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 9000/Pro */
+	CHIP_DEF(PCI_CHIP_RV250_If,	RV250,	CHIP_HAS_CRTC2),
+	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),
+	/* 9200 */
+	CHIP_DEF(PCI_CHIP_RV280_5960,	RV280,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV280_5961,	RV280,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV280_5962,	RV280,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV280_5964,	RV280,	CHIP_HAS_CRTC2),
+	/* 9500 */
+	CHIP_DEF(PCI_CHIP_R300_AD,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_AE,	R300,	CHIP_HAS_CRTC2),
+	/* 9600TX / FireGL Z1 */
+	CHIP_DEF(PCI_CHIP_R300_AF,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_AG,	R300,	CHIP_HAS_CRTC2),
+	/* 9700/9500/Pro/FireGL X1 */
+	CHIP_DEF(PCI_CHIP_R300_ND,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_NE,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_NF,	R300,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R300_NG,	R300,	CHIP_HAS_CRTC2),
+	/* Mobility M10/M11 */
+	CHIP_DEF(PCI_CHIP_RV350_NP,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NQ,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NR,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NS,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NT,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	CHIP_DEF(PCI_CHIP_RV350_NV,	RV350,	CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY),
+	/* 9600/FireGL T2 */
+	CHIP_DEF(PCI_CHIP_RV350_AP,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AQ,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV360_AR,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AS,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AT,	RV350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_RV350_AV,	RV350,	CHIP_HAS_CRTC2),
+	/* 9800/Pro/FileGL X2 */
+	CHIP_DEF(PCI_CHIP_R350_AH,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_AI,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_AJ,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_AK,	R350,	CHIP_HAS_CRTC2),
+	CHIP_DEF(PCI_CHIP_R350_NH,	R350,	CHIP_HAS_CRTC2),
+	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),
+	CHIP_DEF(PCI_CHIP_RADEON_QF,	RADEON,	0),
+	CHIP_DEF(PCI_CHIP_RADEON_QG,	RADEON,	0),
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, radeonll_pci_table);
+
+MODULE_AUTHOR("Dave Airlie");
+MODULE_DESCRIPTION("Lowlevel driver for Radeon Chipset");
+MODULE_LICENSE("GPL");
+
+struct bus_type radeon_bus_type;
+EXPORT_SYMBOL(radeon_bus_type);
+
+int radeonll_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	return 0;
+}
+
+int radeonll_pci_resume(struct pci_dev *pdev)
+{
+	return 0;
+}
+
+static int radeonll_pci_register(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	int ret;
+	struct radeonll_info *rll_info;
+	
+	/* Enable device in PCI config */
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
+		printk(KERN_ERR "radeonll (%s): Cannot enable PCI device\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+	
+	rll_info = (struct radeonll_info *)kcalloc(1, sizeof(struct radeonll_info), GFP_KERNEL);
+	if (!rll_info) {
+		printk(KERN_ERR "radeonll (%s): Unable to allocate radeon lowlevel\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+	
+	spin_lock_init(&rll_info->reg_lock);
+	
+	rll_info->family = ent->driver_data & CHIP_FAMILY_MASK;
+	rll_info->chipset = pdev->device;
+	rll_info->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
+	rll_info->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
+	rll_info->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
+	
+	/* Set base addrs */
+	rll_info->fb_base_phys = pci_resource_start (pdev, 0);
+	rll_info->mmio_base_phys = pci_resource_start (pdev, 2);
+	
+	/* request the mem regions */
+	ret = pci_request_regions(pdev, "radeonll");
+	if (ret < 0) {
+		printk( KERN_ERR "radeonll (%s): cannot reserve PCI regions."
+			"  Someone already got them?\n", pci_name(pdev));
+		goto err_free_info;
+	}
+	
+	/* map the regions */
+	rll_info->mmio_base = ioremap(rll_info->mmio_base_phys, RADEON_REGSIZE);
+	if (!rll_info->mmio_base) {
+		printk(KERN_ERR "radeonll (%s): cannot map MMIO\n", pci_name(pdev));
+		ret = -EIO;
+		goto err_release_pci;
+	}
+	
+	/*
+	 * Check for errata
+	 */
+	rll_info->errata = 0;
+	if (rll_info->family == CHIP_FAMILY_R300 &&
+	    (radeon_INREG(rll_info, CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+	    == CFG_ATI_REV_A11)
+		rll_info->errata |= CHIP_ERRATA_R300_CG;
+	
+	if (rll_info->family == CHIP_FAMILY_RV200 ||
+	    rll_info->family == CHIP_FAMILY_RS200)
+		rll_info->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+	
+	if (rll_info->family == CHIP_FAMILY_RV100 ||
+	    rll_info->family == CHIP_FAMILY_RS100 ||
+	    rll_info->family == CHIP_FAMILY_RS200)
+		rll_info->errata |= CHIP_ERRATA_PLL_DELAY;
+	
+	pci_set_drvdata(pdev, rll_info);
+	
+	rll_info->vll.dev.parent = &pdev->dev;
+	rll_info->vll.dev.bus = &radeon_bus_type;
+	strcpy(rll_info->vll.dev.bus_id, pdev->dev.bus_id);
+	vll_device_register(&rll_info->vll);
+	return 0;
+	
+err_release_pci:
+err_free_info:
+	kfree(rll_info);
+err_out:
+	return ret;
+}
+
+static void __devexit radeonll_pci_unregister (struct pci_dev *pdev)
+{
+	struct radeonll_info *rll_info = pci_get_drvdata(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+	iounmap(rll_info->mmio_base);
+	pci_release_regions(pdev);
+	kfree(rll_info);
+}
+
+static struct pci_driver radeonll_driver = {
+	.name		= "radeonll",
+	.id_table	= radeonll_pci_table,
+	.probe		= radeonll_pci_register,
+	.remove		= __devexit_p(radeonll_pci_unregister),
+#ifdef CONFIG_PM
+	.suspend       	= radeonll_pci_suspend,
+	.resume		= radeonll_pci_resume,
+#endif /* CONFIG_PM */
+};
+ 
+static int __init radeonll_init (void)
+{
+	radeon_bus_type.name = "radeon";
+	vll_bus_driver_init(&radeon_bus_type);
+	return pci_register_driver (&radeonll_driver);
+}
+
+
+static void __exit radeonll_exit (void)
+{
+	vll_bus_driver_fini(&radeon_bus_type);
+	pci_unregister_driver (&radeonll_driver);
+}
+
+module_init(radeonll_init);
+module_exit(radeonll_exit);
diff --git a/drivers/video/radeon_lowlevel.h b/drivers/video/radeon_lowlevel.h
new file mode 100644
index 0000000..249010c
--- /dev/null
+++ b/drivers/video/radeon_lowlevel.h
@@ -0,0 +1,230 @@
+#ifndef __RADEON_LOWLEVEL_H_
+#define __RADEON_LOWLEVEL_H_
+
+#include <linux/vga_lowlevel.h>
+#include <video/radeon.h>
+/*
+ * Chip families. Must fit in the low 16 bits of a long word
+ */
+enum radeon_family {
+	CHIP_FAMILY_UNKNOW,
+	CHIP_FAMILY_LEGACY,
+	CHIP_FAMILY_RADEON,
+	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_R200,
+	CHIP_FAMILY_RV250,
+	CHIP_FAMILY_RS300,    /* Radeon 9000 IGP */
+	CHIP_FAMILY_RV280,
+	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(rll) (((rll)->family == CHIP_FAMILY_RV100)  || \
+				 ((rll)->family == CHIP_FAMILY_RV200)  || \
+				 ((rll)->family == CHIP_FAMILY_RS100)  || \
+				 ((rll)->family == CHIP_FAMILY_RS200)  || \
+				 ((rll)->family == CHIP_FAMILY_RV250)  || \
+				 ((rll)->family == CHIP_FAMILY_RV280)  || \
+				 ((rll)->family == CHIP_FAMILY_RS300))
+
+
+#define IS_R300_VARIANT(rll) (((rll)->family == CHIP_FAMILY_R300)  || \
+				((rll)->family == CHIP_FAMILY_RV350) || \
+				((rll)->family == CHIP_FAMILY_R350)  || \
+				((rll)->family == CHIP_FAMILY_RV380) || \
+				((rll)->family == CHIP_FAMILY_R420))
+
+/*
+ * Chip flags
+ */
+enum radeon_chip_flags {
+	CHIP_FAMILY_MASK	= 0x0000ffffUL,
+	CHIP_FLAGS_MASK		= 0xffff0000UL,
+	CHIP_IS_MOBILITY	= 0x00010000UL,
+	CHIP_IS_IGP		= 0x00020000UL,
+	CHIP_HAS_CRTC2		= 0x00040000UL,	
+};
+
+/*
+ * Errata workarounds
+ */
+enum radeon_errata {
+	CHIP_ERRATA_R300_CG		= 0x00000001,
+	CHIP_ERRATA_PLL_DUMMYREADS	= 0x00000002,
+	CHIP_ERRATA_PLL_DELAY		= 0x00000004,
+};
+
+struct radeonll_info {
+	struct vll vll;
+	unsigned long		mmio_base_phys;
+	unsigned long		fb_base_phys;
+	
+	void __iomem		*mmio_base;
+	
+	int			chipset;
+	u8			family;
+	u8			rev;
+	unsigned int		errata;
+
+	int			has_CRTC2;
+	int			is_mobility;
+	int			is_IGP;
+
+	/* Lock on register access */
+	spinlock_t		reg_lock;
+	int			no_schedule;
+
+};
+
+/*
+ * IO macros
+ */
+
+/* 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 radeonll_info *rll_info, unsigned long ms)
+{
+	if (rll_info->no_schedule || oops_in_progress)
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+static inline u8 radeon_INREG8(struct radeonll_info *rll_info, u32 addr)
+{
+	return readb(rll_info->mmio_base+addr);
+}
+
+static inline void radeon_OUTREG8(struct radeonll_info *rll_info, u32 addr, u8 val)
+{
+	writeb(val, rll_info->mmio_base+addr);
+}
+
+static inline u32 radeon_INREG(struct radeonll_info *rll_info, u32 addr)
+{
+	return readl(rll_info->mmio_base+addr);
+}
+
+static inline void radeon_OUTREG(struct radeonll_info *rll_info, u32 addr, u32 val)
+{
+	writel(val, rll_info->mmio_base+addr);
+}
+
+
+static inline void radeon_OUTREGP(struct radeonll_info *rll_info, u32 addr,
+		       u32 val, u32 mask)
+{
+	unsigned long flags;
+	unsigned int tmp;
+
+	spin_lock_irqsave(&rll_info->reg_lock, flags);
+	tmp = radeon_INREG(rll_info, addr);
+	tmp &= (mask);
+	tmp |= (val);
+	radeon_OUTREG(rll_info, addr, tmp);
+	spin_unlock_irqrestore(&rll_info->reg_lock, flags);
+}
+
+/*
+ * Note about PLL register accesses:
+ *
+ * I have removed the spinlock on them on purpose. The driver now
+ * expects that it will only manipulate the PLL registers in normal
+ * task environment, where radeon_msleep() will be called, protected
+ * by a semaphore (currently the console semaphore) so that no conflict
+ * will happen on the PLL register index.
+ *
+ * With the latest changes to the VT layer, this is guaranteed for all
+ * calls except the actual drawing/blits which aren't supposed to use
+ * the PLL registers anyway
+ *
+ * This is very important for the workarounds to work properly. The only
+ * possible exception to this rule is the call to unblank(), which may
+ * be done at irq time if an oops is in progress.
+ */
+static inline void radeon_pll_errata_after_index(struct radeonll_info *rll_info)
+{
+	if (!(rll_info->errata & CHIP_ERRATA_PLL_DUMMYREADS))
+		return;
+
+	(void)radeon_INREG(rll_info, CLOCK_CNTL_DATA);
+	(void)radeon_INREG(rll_info, CRTC_GEN_CNTL);
+}
+
+static inline void radeon_pll_errata_after_data(struct radeonll_info *rll_info)
+{
+	if (rll_info->errata & CHIP_ERRATA_PLL_DELAY) {
+		/* we can't deal with posted writes here ... */
+		_radeon_msleep(rll_info, 5);
+	}
+	if (rll_info->errata & CHIP_ERRATA_R300_CG) {
+		u32 save, tmp;
+		save = radeon_INREG(rll_info, CLOCK_CNTL_INDEX);
+		tmp = save & ~(0x3f | PLL_WR_EN);
+		radeon_OUTREG(rll_info, CLOCK_CNTL_INDEX, tmp);
+		tmp = radeon_INREG(rll_info, CLOCK_CNTL_DATA);
+		radeon_OUTREG(rll_info, CLOCK_CNTL_INDEX, save);
+	}
+}
+
+static inline u32 radeon_INPLL(struct radeonll_info *rll_info, u32 addr)
+{
+	u32 data;
+
+	radeon_OUTREG8(rll_info, CLOCK_CNTL_INDEX, addr & 0x0000003f);
+	radeon_pll_errata_after_index(rll_info);
+	data = radeon_INREG(rll_info, CLOCK_CNTL_DATA);
+	radeon_pll_errata_after_data(rll_info);
+	return data;
+}
+
+static inline void radeon_OUTPLL(struct radeonll_info *rll_info, unsigned int index,
+			    u32 val)
+{
+
+	radeon_OUTREG8(rll_info, CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+	radeon_pll_errata_after_index(rll_info);
+	radeon_OUTREG(rll_info, CLOCK_CNTL_DATA, val);
+	radeon_pll_errata_after_data(rll_info);
+}
+
+
+static inline void radeon_OUTPLLP(struct radeonll_info *rll_info, unsigned int index,
+			     u32 val, u32 mask)
+{
+	unsigned int tmp;
+
+	tmp  = radeon_INPLL(rll_info, index);
+	tmp &= (mask);
+	tmp |= (val);
+	radeon_OUTPLL(rll_info, index, tmp);
+}
+
+extern struct bus_type radeon_bus_type;
+static __inline__ int radeonll_register_driver(struct vll_driver *vll_dev)
+{
+	return vll_register_driver(&radeon_bus_type, vll_dev);
+}
+
+static __inline__ void radeonll_unregister_driver(struct vll_driver *vll_dev)
+{
+	vll_unregister_driver(vll_dev);
+}
+
+/* not sure if I need this */
+#define radeon_getll(vdev) ((radeonll_info *)vdev->parent)
+
+#endif
+
diff --git a/drivers/video/vga_lowlevel.c b/drivers/video/vga_lowlevel.c
new file mode 100644
index 0000000..e3fb159
--- /dev/null
+++ b/drivers/video/vga_lowlevel.c
@@ -0,0 +1,166 @@
+#include <linux/device.h>
+#include <linux/vga_lowlevel.h>
+
+/* match the device to a driver on the bus */
+int vga_bus_match(struct device *dev, struct device_driver *drv)
+{
+	const struct vll_dev *vdev = to_vll_dev(dev);
+
+	dev->driver = drv;
+	printk("%s called\n", __FUNCTION__);
+	return 1;
+}
+EXPORT_SYMBOL(vga_bus_match);
+
+int vga_bus_hotplug(struct device *dev, char **envp, int num_envp,
+		      char *buffer, int buffer_size)
+{
+	printk("%s called\n", __FUNCTION__);
+	return -ENODEV;
+}
+EXPORT_SYMBOL(vga_bus_hotplug);
+
+int vga_bus_device_suspend(struct device *dev, u32 state)
+{
+	return 0;
+}
+EXPORT_SYMBOL(vga_bus_device_suspend);
+
+int vga_bus_device_resume(struct device *dev)
+{
+	return 0;
+}
+EXPORT_SYMBOL(vga_bus_device_resume);
+		     
+
+#define kobj_to_vga_driver(obj) container_of(obj, struct device_driver, kobj)
+#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
+
+static ssize_t
+vga_driver_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct device_driver *driver = kobj_to_vga_driver(kobj);
+	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
+	ssize_t ret;
+
+	if (!get_driver(driver))
+		return -ENODEV;
+
+	ret = dattr->show ? dattr->show(driver, buf) : -EIO;
+	
+	put_driver(driver);
+	return ret;
+}
+
+static ssize_t 
+vga_driver_attr_store(struct kobject *kobj, struct attribute *attr, 
+			const char *buf, size_t count)
+{
+	struct device_driver *driver = kobj_to_vga_driver(kobj);
+	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
+	ssize_t ret;
+
+	if (!get_driver(driver))
+		return -ENODEV;
+	
+	ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
+
+	put_driver(driver);
+	return ret;
+}
+
+static struct sysfs_ops vga_driver_sysfs_ops = {
+	.show = vga_driver_attr_show,
+	.store = vga_driver_attr_store,
+};
+
+static struct kobj_type vga_driver_kobj_type = {
+	.sysfs_ops = &vga_driver_sysfs_ops,
+};
+
+static int 
+__vga_device_probe(struct vll_driver *drv, struct vll_dev *vll_dev)
+{
+	int error = 0;
+	
+	if (!vll_dev->driver && drv->probe) {
+		error = drv->probe(vll_dev);
+	}
+
+	if (error>=0) {
+		vll_dev->driver = drv;
+		error = 0;
+	}
+
+	return error;
+}
+
+static int vga_device_probe(struct device *dev)
+{
+	int error = 0;
+	struct vll_driver *drv;
+	struct vll_dev *vll_dev;
+
+	drv = to_vll_driver(dev->driver);
+	vll_dev = to_vll_dev(dev);
+//	vll_dev_get(vll_dev);
+	error = __vga_device_probe(drv, vll_dev);
+//	if (error)
+		//vll_dev_put(vll_dev);
+	printk("%s called\n", __FUNCTION__);
+	
+	return error;
+}
+
+static int vga_driver_remove(struct device *dev)
+{
+	printk("%s called\n", __FUNCTION__);
+	return 0;
+}
+/*
+  register a video lowlevel driver.
+*/
+int vll_register_driver(struct bus_type *bus_type, struct vll_driver *vdrv)
+{
+	vdrv->driver.name = vdrv->name;
+	vdrv->driver.bus = bus_type;
+	vdrv->driver.probe = vga_device_probe;
+	vdrv->driver.remove = vga_driver_remove;
+	vdrv->driver.kobj.ktype = &vga_driver_kobj_type;
+	return driver_register(&vdrv->driver);
+}
+EXPORT_SYMBOL(vll_register_driver);
+
+void vll_unregister_driver(struct vll_driver *vdrv)
+{
+	struct list_head *list;
+	struct vll_dev *vdev;
+	struct vll *vll;
+	
+}
+EXPORT_SYMBOL(vll_unregister_driver);
+
+int vll_bus_driver_init(struct bus_type *bus_type)
+{
+	bus_type->match = vga_bus_match;
+	bus_type->hotplug = vga_bus_hotplug;
+	bus_type->suspend = vga_bus_device_suspend;
+	bus_type->resume = vga_bus_device_resume;
+	
+	if (bus_register(bus_type) < 0)
+		printk(KERN_ERR "Unable to register %s bus type.\n", bus_type->name);
+	return 0;
+}
+EXPORT_SYMBOL(vll_bus_driver_init);
+
+void vll_bus_driver_fini(struct bus_type *bus_type)
+{
+	bus_unregister(bus_type);
+}
+EXPORT_SYMBOL(vll_bus_driver_fini);
+
+int vll_device_register(struct vll *vll)
+{
+	return device_register(&vll->dev);
+}
+EXPORT_SYMBOL(vll_device_register);
diff --git a/include/linux/vga_lowlevel.h b/include/linux/vga_lowlevel.h
new file mode 100644
index 0000000..a69cfd9
--- /dev/null
+++ b/include/linux/vga_lowlevel.h
@@ -0,0 +1,108 @@
+
+#ifndef _VGA_LOWLEVEL_H_
+#define _VGA_LOWLEVEL_H_
+
+#include <linux/interrupt.h>
+#define VGA_COMMON 1 // common should always be loaded otherwise this layer won't exist
+#define VGA_FB 2
+#define VGA_DRM 3
+
+/* lowlevel stores two lists */
+/* list of lowlevel drivers per card */
+/* each list of lowlevel drivers has a list of registered higher drivers */
+
+struct vll;
+struct vll_dev;
+//struct list_head *head;
+
+struct vll_driver {
+	char *name;
+	int type; // from above list
+	irqreturn_t (*irq_handler)(int irq, void *arg, struct pt_regs *regs);
+	int (*probe)(struct vll_driver *vdrv, struct vll_dev *vdev);
+	void (*remove)(struct vll_dev *vdev);
+	int (*suspend)(struct vll_dev *vdev, pm_message_t state);
+	int (*resume)(struct vll_dev *vdev);
+	void *(*get_entrypoints)(void);
+	struct device_driver	driver;
+};
+
+struct vll_dev {
+	struct list_head drivers;  /* pointer to next registered driver */
+	struct vll_driver *driver; /* pointer back to driver registered on this device */
+	struct device dev;
+};
+
+#define to_vll_driver(n) container_of(n, struct vll_driver, driver)
+#define to_vll_dev(n) container_of(n, struct vll_dev, dev)
+
+struct vll {
+	struct list_head cards; // list of card drivers
+	struct list_head drivers; // drivers for this card
+//	struct vll_dev *devs; // list of registered higher layer vll_drivers
+	struct pci_dev *pdev;
+	struct device dev;
+  //	struct bus_type bus_type;
+};
+
+struct vll_layer {
+  struct bus_type bus_type;
+  struct device dev;
+};
+
+extern int vll_register_driver(struct bus_type *bus_type, struct vll_driver *vdrv);
+extern void vll_unregister_driver(struct vll_driver *driver);
+extern int vll_bus_driver_init(struct bus_type *bus_type);
+extern void vll_bus_driver_fini(struct bus_type *bus_type);
+extern int vll_device_register(struct vll *vll);
+
+extern int vga_bus_device_resume(struct device *dev);
+extern int vga_bus_device_suspend(struct device *dev, u32 state);
+extern int vga_bus_hotplug(struct device *dev, char **envp, int num_envp,
+			     char *buffer, int buffer_size);
+extern int vga_bus_match(struct device *dev, struct device_driver *drv);
+
+/* check is a driver loaded */
+static __inline__ int vll_is_driver_loaded(struct vll *vga_ll, int drv_type)
+{
+	struct list_head *list;
+	struct vll_dev *vdev;
+
+	list_for_each(list, &(vga_ll->drivers)) {
+		vdev = list_entry(list, struct vll_dev, drivers);
+		
+		if (vdev->driver->type==drv_type)
+			return 1;
+	}
+
+	return 0;
+
+}
+static __inline__ void *vll_get_entrypoints(struct vll *vga_ll, int drv_type)
+{
+	struct list_head *list;
+	struct vll_dev *vdev;
+
+	list_for_each(list, &(vga_ll->drivers)) {
+		vdev = list_entry(list, struct vll_dev, drivers);
+		
+		if (vdev->driver->type==drv_type)
+			return vdev->driver->get_entrypoints();
+	}
+
+	return NULL;
+}
+
+static __inline__ void vll_set_drvdata(struct vll_dev *vdev, void *data)
+{
+	dev_set_drvdata(&vdev->dev, data);
+}
+
+static __inline__ void *vll_get_drvdata(struct vll_dev *vdev)
+{
+	return dev_get_drvdata(&vdev->dev);
+}
+
+
+
+#endif
