Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (95 commits)
  drm/radeon/kms: preface warning printk with driver name
  drm/radeon/kms: drop unnecessary printks.
  drm: fix regression in fb blank handling
  drm/radeon/kms: make hibernate work on IGPs
  drm/vmwgfx: Optimize memory footprint for DMA buffers.
  drm/ttm: Allow system memory as a busy placement.
  drm/ttm: Fix race condition in ttm_bo_delayed_delete (v3, final)
  drm/nv50: prevent switching off SOR when in use for DVI-over-DP
  drm/nv50: fail auxch transaction if reply count not what we expect
  drm/nouveau: fix failure path if userspace specifies no valid memtypes
  drm/nouveau: report LVDS as disconnected if lid closed
  drm/radeon/kms: fix legacy get_engine/memory clock
  drm/radeon/kms/atom: atom parser fixes
  drm/radeon/kms: clean up atombios pll code
  drm/radeon/kms: clean up pll struct
  drm/radeon/kms/atom: fix crtc lock ordering
  drm/radeon: r6xx/r7xx possible security issue, system ram access
  drm/radeon/kms: r600/r700 don't test ib if ib initialization fails
  drm/radeon/kms: Forbid creation of framebuffer with no valid GEM object
  drm/radeon/kms: r600 handle irq vector ring overflow
  ...
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index defcaf1..f665b05 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -633,8 +633,7 @@
 		return NULL;
 	}
 	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
-		printk(KERN_WARNING "integrated sync not supported\n");
-		return NULL;
+		printk(KERN_WARNING "composite sync not supported\n");
 	}
 
 	/* it is incorrect if hsync/vsync width is zero */
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 1c2b7d4..0f9e9055 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -389,7 +389,7 @@
 		break;
 	/* Display: Off; HSync: On, VSync: On */
 	case FB_BLANK_NORMAL:
-		drm_fb_helper_off(info, DRM_MODE_DPMS_ON);
+		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
 		break;
 	/* Display: Off; HSync: Off, VSync: On */
 	case FB_BLANK_HSYNC_SUSPEND:
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index ba14397..d7f8d8b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -310,63 +310,22 @@
 	struct drm_device *dev = bios->dev;
 
 	/* C51 has misaligned regs on purpose. Marvellous */
-	if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) {
-		NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n",
-			 reg);
-		return 0;
-	}
-	/*
-	 * Warn on C51 regs that have not been verified accessible in
-	 * mmiotracing
-	 */
+	if (reg & 0x2 ||
+	    (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
+		NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
+
+	/* warn on C51 regs that haven't been verified accessible in tracing */
 	if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
 	    reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
 		NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
 			reg);
 
-	/* Trust the init scripts on G80 */
-	if (dev_priv->card_type >= NV_50)
-		return 1;
-
-	#define WITHIN(x, y, z) ((x >= y) && (x < y + z))
-	if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE))
-		return 1;
-	if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE))
-		return 1;
-	if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE))
-		return 1;
-	if (dev_priv->VBIOS.pub.chip_version >= 0x30 &&
-	    (WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600))
-		return 1;
-	if (dev_priv->VBIOS.pub.chip_version >= 0x40 &&
-						WITHIN(reg, 0xc000, 0x48))
-		return 1;
-	if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204)
-		return 1;
-	if (dev_priv->VBIOS.pub.chip_version >= 0x40) {
-		if (reg == 0x00011014 || reg == 0x00020328)
-			return 1;
-		if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */
-			return 1;
+	if (reg >= (8*1024*1024)) {
+		NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg);
+		return 0;
 	}
-	if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE))
-		return 1;
-	if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE))
-		return 1;
-	if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2))
-		return 1;
-	if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2))
-		return 1;
-	if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0)
-		return 1;
-	if (dev_priv->VBIOS.pub.chip_version == 0x51 &&
-				WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE))
-		return 1;
-	#undef WITHIN
 
-	NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg);
-
-	return 0;
+	return 1;
 }
 
 static bool
@@ -3196,16 +3155,25 @@
 	}
 #ifdef __powerpc__
 	/* Powerbook specific quirks */
-	if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329))
-		nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
-	if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) {
-		if (script == LVDS_PANEL_ON) {
-			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31));
-			bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
-		}
-		if (script == LVDS_PANEL_OFF) {
-			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31));
-			bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
+	if ((dev->pci_device & 0xffff) == 0x0179 ||
+	    (dev->pci_device & 0xffff) == 0x0189 ||
+	    (dev->pci_device & 0xffff) == 0x0329) {
+		if (script == LVDS_RESET) {
+			nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
+
+		} else if (script == LVDS_PANEL_ON) {
+			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
+				  bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
+				  | (1 << 31));
+			bios_wr32(bios, NV_PCRTC_GPIO_EXT,
+				  bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
+
+		} else if (script == LVDS_PANEL_OFF) {
+			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
+				  bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
+				  & ~(1 << 31));
+			bios_wr32(bios, NV_PCRTC_GPIO_EXT,
+				  bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
 		}
 	}
 #endif
@@ -5434,52 +5402,49 @@
 parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
 		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
 {
-	if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 &&
-	    conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 &&
-	    conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 &&
-	    conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 &&
-	    conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 &&
-	    conn != 0xf2205004 && conn != 0xf2209004) {
-		NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n");
-
-		/* cause output setting to fail for !TV, so message is seen */
-		if ((conn & 0xf) != 0x1)
-			dcb->entries = 0;
-
+	switch (conn & 0x0000000f) {
+	case 0:
+		entry->type = OUTPUT_ANALOG;
+		break;
+	case 1:
+		entry->type = OUTPUT_TV;
+		break;
+	case 2:
+	case 3:
+		entry->type = OUTPUT_LVDS;
+		break;
+	case 4:
+		switch ((conn & 0x000000f0) >> 4) {
+		case 0:
+			entry->type = OUTPUT_TMDS;
+			break;
+		case 1:
+			entry->type = OUTPUT_LVDS;
+			break;
+		default:
+			NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
+				 (conn & 0x000000f0) >> 4);
+			return false;
+		}
+		break;
+	default:
+		NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
 		return false;
 	}
-	/* most of the below is a "best guess" atm */
-	entry->type = conn & 0xf;
-	if (entry->type == 2)
-		/* another way of specifying straps based lvds... */
-		entry->type = OUTPUT_LVDS;
-	if (entry->type == 4) { /* digital */
-		if (conn & 0x10)
-			entry->type = OUTPUT_LVDS;
-		else
-			entry->type = OUTPUT_TMDS;
-	}
-	/* what's in bits 5-13? could be some encoder maker thing, in tv case */
-	entry->i2c_index = (conn >> 14) & 0xf;
-	/* raw heads field is in range 0-1, so move to 1-2 */
-	entry->heads = ((conn >> 18) & 0x7) + 1;
-	entry->location = (conn >> 21) & 0xf;
-	/* unused: entry->bus = (conn >> 25) & 0x7; */
-	/* set or to be same as heads -- hopefully safe enough */
-	entry->or = entry->heads;
+
+	entry->i2c_index = (conn & 0x0003c000) >> 14;
+	entry->heads = ((conn & 0x001c0000) >> 18) + 1;
+	entry->or = entry->heads; /* same as heads, hopefully safe enough */
+	entry->location = (conn & 0x01e00000) >> 21;
+	entry->bus = (conn & 0x0e000000) >> 25;
 	entry->duallink_possible = false;
 
 	switch (entry->type) {
 	case OUTPUT_ANALOG:
 		entry->crtconf.maxfreq = (conf & 0xffff) * 10;
 		break;
-	case OUTPUT_LVDS:
-		/*
-		 * This is probably buried in conn's unknown bits.
-		 * This will upset EDID-ful models, if they exist
-		 */
-		entry->lvdsconf.use_straps_for_mode = true;
-		entry->lvdsconf.use_power_scripts = true;
+	case OUTPUT_TV:
+		entry->tvconf.has_component_output = false;
 		break;
 	case OUTPUT_TMDS:
 		/*
@@ -5488,8 +5453,12 @@
 		 */
 		fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
 		break;
-	case OUTPUT_TV:
-		entry->tvconf.has_component_output = false;
+	case OUTPUT_LVDS:
+		if ((conn & 0x00003f00) != 0x10)
+			entry->lvdsconf.use_straps_for_mode = true;
+		entry->lvdsconf.use_power_scripts = true;
+		break;
+	default:
 		break;
 	}
 
@@ -5564,11 +5533,13 @@
 	dcb->entries = newentries;
 }
 
-static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
+static int
+parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct bios_parsed_dcb *bdcb = &bios->bdcb;
 	struct parsed_dcb *dcb;
-	uint16_t dcbptr, i2ctabptr = 0;
+	uint16_t dcbptr = 0, i2ctabptr = 0;
 	uint8_t *dcbtable;
 	uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
 	bool configblock = true;
@@ -5579,16 +5550,18 @@
 	dcb->entries = 0;
 
 	/* get the offset from 0x36 */
-	dcbptr = ROM16(bios->data[0x36]);
+	if (dev_priv->card_type > NV_04) {
+		dcbptr = ROM16(bios->data[0x36]);
+		if (dcbptr == 0x0000)
+			NV_WARN(dev, "No output data (DCB) found in BIOS\n");
+	}
 
+	/* this situation likely means a really old card, pre DCB */
 	if (dcbptr == 0x0) {
-		NV_WARN(dev, "No output data (DCB) found in BIOS, "
-			       "assuming a CRT output exists\n");
-		/* this situation likely means a really old card, pre DCB */
+		NV_INFO(dev, "Assuming a CRT output exists\n");
 		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
 
-		if (nv04_tv_identify(dev,
-				     bios->legacy.i2c_indices.tv) >= 0)
+		if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
 			fabricate_tv_output(dcb, twoHeads);
 
 		return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index e342a41..db0ed4c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -469,6 +469,8 @@
 
 	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
 					evict, no_wait, new_mem);
+	if (nvbo->channel && nvbo->channel != chan)
+		ret = nouveau_fence_wait(fence, NULL, false, false);
 	nouveau_fence_unref((void *)&fence);
 	return ret;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 5a10deb..7e6d673 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -24,9 +24,12 @@
  *
  */
 
+#include <acpi/button.h>
+
 #include "drmP.h"
 #include "drm_edid.h"
 #include "drm_crtc_helper.h"
+
 #include "nouveau_reg.h"
 #include "nouveau_drv.h"
 #include "nouveau_encoder.h"
@@ -83,14 +86,16 @@
 static void
 nouveau_connector_destroy(struct drm_connector *drm_connector)
 {
-	struct nouveau_connector *connector = nouveau_connector(drm_connector);
-	struct drm_device *dev = connector->base.dev;
+	struct nouveau_connector *nv_connector =
+		nouveau_connector(drm_connector);
+	struct drm_device *dev = nv_connector->base.dev;
 
 	NV_DEBUG_KMS(dev, "\n");
 
-	if (!connector)
+	if (!nv_connector)
 		return;
 
+	kfree(nv_connector->edid);
 	drm_sysfs_connector_remove(drm_connector);
 	drm_connector_cleanup(drm_connector);
 	kfree(drm_connector);
@@ -233,10 +238,21 @@
 	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
 		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
 	if (nv_encoder && nv_connector->native_mode) {
+#ifdef CONFIG_ACPI
+		if (!nouveau_ignorelid && !acpi_lid_open())
+			return connector_status_disconnected;
+#endif
 		nouveau_connector_set_encoder(connector, nv_encoder);
 		return connector_status_connected;
 	}
 
+	/* Cleanup the previous EDID block. */
+	if (nv_connector->edid) {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		kfree(nv_connector->edid);
+		nv_connector->edid = NULL;
+	}
+
 	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
 	if (i2c) {
 		nouveau_connector_ddc_prepare(connector, &flags);
@@ -247,7 +263,7 @@
 		if (!nv_connector->edid) {
 			NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
 				 drm_get_connector_name(connector));
-			return connector_status_disconnected;
+			goto detect_analog;
 		}
 
 		if (nv_encoder->dcb->type == OUTPUT_DP &&
@@ -281,6 +297,7 @@
 		return connector_status_connected;
 	}
 
+detect_analog:
 	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
 	if (!nv_encoder)
 		nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
@@ -687,8 +704,12 @@
 	 */
 	if (!nv_connector->edid && !nv_connector->native_mode &&
 	    !dev_priv->VBIOS.pub.fp_no_ddc) {
-		nv_connector->edid =
+		struct edid *edid =
 			(struct edid *)nouveau_bios_embedded_edid(dev);
+		if (edid) {
+			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+			*(nv_connector->edid) = *edid;
+		}
 	}
 
 	if (!nv_connector->edid)
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 7afbe8b..50d9e67 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -126,47 +126,52 @@
 	chan->dma.cur += nr_dwords;
 }
 
-static inline bool
-READ_GET(struct nouveau_channel *chan, uint32_t *get)
+/* Fetch and adjust GPU GET pointer
+ *
+ * Returns:
+ *  value >= 0, the adjusted GET pointer
+ *  -EINVAL if GET pointer currently outside main push buffer
+ *  -EBUSY if timeout exceeded
+ */
+static inline int
+READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
 {
 	uint32_t val;
 
 	val = nvchan_rd32(chan, chan->user_get);
-	if (val < chan->pushbuf_base ||
-	    val > chan->pushbuf_base + (chan->dma.max << 2)) {
-		/* meaningless to dma_wait() except to know whether the
-		 * GPU has stalled or not
-		 */
-		*get = val;
-		return false;
+
+	/* reset counter as long as GET is still advancing, this is
+	 * to avoid misdetecting a GPU lockup if the GPU happens to
+	 * just be processing an operation that takes a long time
+	 */
+	if (val != *prev_get) {
+		*prev_get = val;
+		*timeout = 0;
 	}
 
-	*get = (val - chan->pushbuf_base) >> 2;
-	return true;
+	if ((++*timeout & 0xff) == 0) {
+		DRM_UDELAY(1);
+		if (*timeout > 100000)
+			return -EBUSY;
+	}
+
+	if (val < chan->pushbuf_base ||
+	    val > chan->pushbuf_base + (chan->dma.max << 2))
+		return -EINVAL;
+
+	return (val - chan->pushbuf_base) >> 2;
 }
 
 int
 nouveau_dma_wait(struct nouveau_channel *chan, int size)
 {
-	uint32_t get, prev_get = 0, cnt = 0;
-	bool get_valid;
+	uint32_t prev_get = 0, cnt = 0;
+	int get;
 
 	while (chan->dma.free < size) {
-		/* reset counter as long as GET is still advancing, this is
-		 * to avoid misdetecting a GPU lockup if the GPU happens to
-		 * just be processing an operation that takes a long time
-		 */
-		get_valid = READ_GET(chan, &get);
-		if (get != prev_get) {
-			prev_get = get;
-			cnt = 0;
-		}
-
-		if ((++cnt & 0xff) == 0) {
-			DRM_UDELAY(1);
-			if (cnt > 100000)
-				return -EBUSY;
-		}
+		get = READ_GET(chan, &prev_get, &cnt);
+		if (unlikely(get == -EBUSY))
+			return -EBUSY;
 
 		/* loop until we have a usable GET pointer.  the value
 		 * we read from the GPU may be outside the main ring if
@@ -177,7 +182,7 @@
 		 * from the SKIPS area, so the code below doesn't have to deal
 		 * with some fun corner cases.
 		 */
-		if (!get_valid || get < NOUVEAU_DMA_SKIPS)
+		if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS)
 			continue;
 
 		if (get <= chan->dma.cur) {
@@ -203,6 +208,19 @@
 			 * after processing the currently pending commands.
 			 */
 			OUT_RING(chan, chan->pushbuf_base | 0x20000000);
+
+			/* wait for GET to depart from the skips area.
+			 * prevents writing GET==PUT and causing a race
+			 * condition that causes us to think the GPU is
+			 * idle when it's not.
+			 */
+			do {
+				get = READ_GET(chan, &prev_get, &cnt);
+				if (unlikely(get == -EBUSY))
+					return -EBUSY;
+				if (unlikely(get == -EINVAL))
+					continue;
+			} while (get <= NOUVEAU_DMA_SKIPS);
 			WRITE_PUT(NOUVEAU_DMA_SKIPS);
 
 			/* we're now submitting commands at the start of
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 9e2926c..dd49372 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -490,7 +490,8 @@
 		if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) {
 			NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n",
 				 nv_rd32(dev, NV50_AUXCH_CTRL(index)));
-			return -EBUSY;
+			ret = -EBUSY;
+			goto out;
 		}
 
 		udelay(400);
@@ -501,6 +502,11 @@
 			break;
 	}
 
+	if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
+		ret = -EREMOTEIO;
+		goto out;
+	}
+
 	if (cmd & 1) {
 		for (i = 0; i < 4; i++) {
 			data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 06eb993..343ab7f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -71,6 +71,10 @@
 int nouveau_uscript_tmds = -1;
 module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400);
 
+MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
+int nouveau_ignorelid = 0;
+module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
+
 MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
 		 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
 		 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 026419f..6b96904 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -509,6 +509,8 @@
 	void __iomem *ramin;
 	uint32_t ramin_size;
 
+	struct nouveau_bo *vga_ram;
+
 	struct workqueue_struct *wq;
 	struct work_struct irq_work;
 
@@ -675,6 +677,7 @@
 extern int nouveau_reg_debug;
 extern char *nouveau_vbios;
 extern int nouveau_ctxfw;
+extern int nouveau_ignorelid;
 
 /* nouveau_state.c */
 extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 2009db2..6ac804b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -321,6 +321,7 @@
 		else {
 			NV_ERROR(dev, "invalid valid domains: 0x%08x\n",
 				 b->valid_domains);
+			list_add_tail(&nvbo->entry, &op->both_list);
 			validate_fini(op, NULL);
 			return -EINVAL;
 		}
@@ -466,13 +467,14 @@
 static int
 nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
 				struct drm_nouveau_gem_pushbuf_bo *bo,
-				int nr_relocs, uint64_t ptr_relocs,
-				int nr_dwords, int first_dword,
+				unsigned nr_relocs, uint64_t ptr_relocs,
+				unsigned nr_dwords, unsigned first_dword,
 				uint32_t *pushbuf, bool is_iomem)
 {
 	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
 	struct drm_device *dev = chan->dev;
-	int ret = 0, i;
+	int ret = 0;
+	unsigned i;
 
 	reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
 	if (IS_ERR(reloc))
@@ -667,6 +669,18 @@
 	}
 	pbbo = nouveau_gem_object(gem);
 
+	if ((req->offset & 3) || req->nr_dwords < 2 ||
+	    (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
+	    (unsigned long)req->nr_dwords >
+	     ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
+		NV_ERROR(dev, "pb call misaligned or out of bounds: "
+			      "%d + %d * 4 > %ld\n",
+			 req->offset, req->nr_dwords, pbbo->bo.mem.size);
+		ret = -EINVAL;
+		drm_gem_object_unreference(gem);
+		goto out;
+	}
+
 	ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
 			     chan->fence.sequence);
 	if (ret) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 919a619..3b9bad6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -483,6 +483,13 @@
 	if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
 		if (nouveau_pgraph_intr_swmthd(dev, &trap))
 			unhandled = 1;
+	} else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
+		uint32_t v = nv_rd32(dev, 0x402000);
+		nv_wr32(dev, 0x402000, v);
+
+		/* dump the error anyway for now: it's useful for
+		   Gallium development */
+		unhandled = 1;
 	} else {
 		unhandled = 1;
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index fb9bdd6..8f3a12f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -383,9 +383,8 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type)
-		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0);
-	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
+	nouveau_bo_unpin(dev_priv->vga_ram);
+	nouveau_bo_ref(NULL, &dev_priv->vga_ram);
 
 	ttm_bo_device_release(&dev_priv->ttm.bdev);
 
@@ -622,6 +621,15 @@
 		return ret;
 	}
 
+	ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+			     0, 0, true, true, &dev_priv->vga_ram);
+	if (ret == 0)
+		ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
+	if (ret) {
+		NV_WARN(dev, "failed to reserve VGA memory\n");
+		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+	}
+
 	/* GART */
 #if !defined(__powerpc__) && !defined(__ia64__)
 	if (drm_device_is_agp(dev) && dev->agp) {
@@ -653,6 +661,7 @@
 	dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
 					 drm_get_resource_len(dev, 1),
 					 DRM_MTRR_WC);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 09b9a46..f2d0187 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -525,6 +525,7 @@
 		engine->mc.takedown(dev);
 
 		mutex_lock(&dev->struct_mutex);
+		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
 		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
 		mutex_unlock(&dev->struct_mutex);
 		nouveau_sgdma_takedown(dev);
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c
index a20c206..a3b9563 100644
--- a/drivers/gpu/drm/nouveau/nv04_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c
@@ -30,7 +30,7 @@
 		 * of vram.  For now, only reserve a small piece until we know
 		 * more about what each chipset requires.
 		 */
-		switch (dev_priv->chipset & 0xf0) {
+		switch (dev_priv->chipset) {
 		case 0x40:
 		case 0x47:
 		case 0x49:
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index 118d328..40b7360 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -432,6 +432,7 @@
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_encoder *encoder;
+	uint32_t dac = 0, sor = 0;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
@@ -439,9 +440,28 @@
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 
-		if (drm_helper_encoder_in_use(encoder))
+		if (!drm_helper_encoder_in_use(encoder))
 			continue;
 
+		if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+		    nv_encoder->dcb->type == OUTPUT_TV)
+			dac |= (1 << nv_encoder->or);
+		else
+			sor |= (1 << nv_encoder->or);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+
+		if (nv_encoder->dcb->type == OUTPUT_ANALOG ||
+		    nv_encoder->dcb->type == OUTPUT_TV) {
+			if (dac & (1 << nv_encoder->or))
+				continue;
+		} else {
+			if (sor & (1 << nv_encoder->or))
+				continue;
+		}
+
 		nv_encoder->disconnect(nv_encoder);
 	}
 
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
index 39caf16..32b244b 100644
--- a/drivers/gpu/drm/nouveau/nv50_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
@@ -272,7 +272,7 @@
 			return ret;
 		ramfc = chan->ramfc->gpuobj;
 
-		ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 256,
+		ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024,
 					     0, &chan->cache);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index ca79f32..20319e5 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -84,7 +84,7 @@
 	nv_wr32(dev, 0x400804, 0xc0000000);
 	nv_wr32(dev, 0x406800, 0xc0000000);
 	nv_wr32(dev, 0x400c04, 0xc0000000);
-	nv_wr32(dev, 0x401804, 0xc0000000);
+	nv_wr32(dev, 0x401800, 0xc0000000);
 	nv_wr32(dev, 0x405018, 0xc0000000);
 	nv_wr32(dev, 0x402000, 0xc0000000);
 
@@ -282,6 +282,7 @@
 		return 0;
 	inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
 
+	nouveau_wait_for_idle(dev);
 	nv_wr32(dev, 0x400500, fifo & ~1);
 	nv_wr32(dev, 0x400784, inst);
 	nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index e395c16..ecf1936 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -90,11 +90,24 @@
 {
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct drm_encoder *enc;
 	uint32_t val;
 	int or = nv_encoder->or;
 
 	NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);
 
+	nv_encoder->last_dpms = mode;
+	list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
+		struct nouveau_encoder *nvenc = nouveau_encoder(enc);
+
+		if (nvenc == nv_encoder ||
+		    nvenc->dcb->or != nv_encoder->dcb->or)
+			continue;
+
+		if (nvenc->last_dpms == DRM_MODE_DPMS_ON)
+			return;
+	}
+
 	/* wait for it to be done */
 	if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or),
 		     NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) {
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index 388140a7..e3b4456 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -246,6 +246,9 @@
 		case ATOM_WS_ATTRIBUTES:
 			val = gctx->io_attr;
 			break;
+		case ATOM_WS_REGPTR:
+			val = gctx->reg_block;
+			break;
 		default:
 			val = ctx->ws[idx];
 		}
@@ -385,6 +388,32 @@
 	return atom_get_src_int(ctx, attr, ptr, NULL, 1);
 }
 
+static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr)
+{
+	uint32_t val = 0xCDCDCDCD;
+
+	switch (align) {
+	case ATOM_SRC_DWORD:
+		val = U32(*ptr);
+		(*ptr) += 4;
+		break;
+	case ATOM_SRC_WORD0:
+	case ATOM_SRC_WORD8:
+	case ATOM_SRC_WORD16:
+		val = U16(*ptr);
+		(*ptr) += 2;
+		break;
+	case ATOM_SRC_BYTE0:
+	case ATOM_SRC_BYTE8:
+	case ATOM_SRC_BYTE16:
+	case ATOM_SRC_BYTE24:
+		val = U8(*ptr);
+		(*ptr)++;
+		break;
+	}
+	return val;
+}
+
 static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr,
 			     int *ptr, uint32_t *saved, int print)
 {
@@ -482,6 +511,9 @@
 		case ATOM_WS_ATTRIBUTES:
 			gctx->io_attr = val;
 			break;
+		case ATOM_WS_REGPTR:
+			gctx->reg_block = val;
+			break;
 		default:
 			ctx->ws[idx] = val;
 		}
@@ -677,7 +709,7 @@
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
 	SDEBUG("   src1: ");
-	src1 = atom_get_src(ctx, attr, ptr);
+	src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr);
 	SDEBUG("   src2: ");
 	src2 = atom_get_src(ctx, attr, ptr);
 	dst &= src1;
@@ -809,6 +841,38 @@
 	SDEBUG("   base: 0x%04X\n", ctx->ctx->reg_block);
 }
 
+static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++), shift;
+	uint32_t saved, dst;
+	int dptr = *ptr;
+	attr &= 0x38;
+	attr |= atom_def_dst[attr >> 3] << 6;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
+	SDEBUG("   shift: %d\n", shift);
+	dst <<= shift;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
+static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg)
+{
+	uint8_t attr = U8((*ptr)++), shift;
+	uint32_t saved, dst;
+	int dptr = *ptr;
+	attr &= 0x38;
+	attr |= atom_def_dst[attr >> 3] << 6;
+	SDEBUG("   dst: ");
+	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
+	shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr);
+	SDEBUG("   shift: %d\n", shift);
+	dst >>= shift;
+	SDEBUG("   dst: ");
+	atom_put_dst(ctx, arg, attr, &dptr, dst, saved);
+}
+
 static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg)
 {
 	uint8_t attr = U8((*ptr)++), shift;
@@ -818,7 +882,7 @@
 	attr |= atom_def_dst[attr >> 3] << 6;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-	shift = U8((*ptr)++);
+	shift = atom_get_src(ctx, attr, ptr);
 	SDEBUG("   shift: %d\n", shift);
 	dst <<= shift;
 	SDEBUG("   dst: ");
@@ -834,7 +898,7 @@
 	attr |= atom_def_dst[attr >> 3] << 6;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
-	shift = U8((*ptr)++);
+	shift = atom_get_src(ctx, attr, ptr);
 	SDEBUG("   shift: %d\n", shift);
 	dst >>= shift;
 	SDEBUG("   dst: ");
@@ -937,18 +1001,18 @@
 	atom_op_or, ATOM_ARG_FB}, {
 	atom_op_or, ATOM_ARG_PLL}, {
 	atom_op_or, ATOM_ARG_MC}, {
-	atom_op_shl, ATOM_ARG_REG}, {
-	atom_op_shl, ATOM_ARG_PS}, {
-	atom_op_shl, ATOM_ARG_WS}, {
-	atom_op_shl, ATOM_ARG_FB}, {
-	atom_op_shl, ATOM_ARG_PLL}, {
-	atom_op_shl, ATOM_ARG_MC}, {
-	atom_op_shr, ATOM_ARG_REG}, {
-	atom_op_shr, ATOM_ARG_PS}, {
-	atom_op_shr, ATOM_ARG_WS}, {
-	atom_op_shr, ATOM_ARG_FB}, {
-	atom_op_shr, ATOM_ARG_PLL}, {
-	atom_op_shr, ATOM_ARG_MC}, {
+	atom_op_shift_left, ATOM_ARG_REG}, {
+	atom_op_shift_left, ATOM_ARG_PS}, {
+	atom_op_shift_left, ATOM_ARG_WS}, {
+	atom_op_shift_left, ATOM_ARG_FB}, {
+	atom_op_shift_left, ATOM_ARG_PLL}, {
+	atom_op_shift_left, ATOM_ARG_MC}, {
+	atom_op_shift_right, ATOM_ARG_REG}, {
+	atom_op_shift_right, ATOM_ARG_PS}, {
+	atom_op_shift_right, ATOM_ARG_WS}, {
+	atom_op_shift_right, ATOM_ARG_FB}, {
+	atom_op_shift_right, ATOM_ARG_PLL}, {
+	atom_op_shift_right, ATOM_ARG_MC}, {
 	atom_op_mul, ATOM_ARG_REG}, {
 	atom_op_mul, ATOM_ARG_PS}, {
 	atom_op_mul, ATOM_ARG_WS}, {
@@ -1058,8 +1122,6 @@
 
 	SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps);
 
-	/* reset reg block */
-	ctx->reg_block = 0;
 	ectx.ctx = ctx;
 	ectx.ps_shift = ps / 4;
 	ectx.start = base;
@@ -1096,6 +1158,12 @@
 void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
 {
 	mutex_lock(&ctx->mutex);
+	/* reset reg block */
+	ctx->reg_block = 0;
+	/* reset fb window */
+	ctx->fb_base = 0;
+	/* reset io mode */
+	ctx->io_mode = ATOM_IO_MM;
 	atom_execute_table_locked(ctx, index, params);
 	mutex_unlock(&ctx->mutex);
 }
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h
index 47fd943..bc73781 100644
--- a/drivers/gpu/drm/radeon/atom.h
+++ b/drivers/gpu/drm/radeon/atom.h
@@ -91,6 +91,7 @@
 #define ATOM_WS_AND_MASK	0x45
 #define ATOM_WS_FB_WINDOW	0x46
 #define ATOM_WS_ATTRIBUTES	0x47
+#define ATOM_WS_REGPTR  	0x48
 
 #define ATOM_IIO_NOP		0
 #define ATOM_IIO_START		1
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 260fcf5..af464e35 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -307,7 +307,6 @@
 	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 	args.ucCRTC = radeon_crtc->crtc_id;
 
-	printk("executing set crtc dtd timing\n");
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
@@ -347,7 +346,6 @@
 	args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
 	args.ucCRTC = radeon_crtc->crtc_id;
 
-	printk("executing set crtc timing\n");
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
@@ -409,59 +407,57 @@
 	}
 }
 
-void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+union adjust_pixel_clock {
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
+};
+
+static u32 atombios_adjust_pll(struct drm_crtc *crtc,
+			       struct drm_display_mode *mode,
+			       struct radeon_pll *pll)
 {
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_encoder *encoder = NULL;
 	struct radeon_encoder *radeon_encoder = NULL;
-	uint8_t frev, crev;
-	int index;
-	SET_PIXEL_CLOCK_PS_ALLOCATION args;
-	PIXEL_CLOCK_PARAMETERS *spc1_ptr;
-	PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
-	PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
-	uint32_t pll_clock = mode->clock;
-	uint32_t adjusted_clock;
-	uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
-	struct radeon_pll *pll;
-	int pll_flags = 0;
+	u32 adjusted_clock = mode->clock;
 
-	memset(&args, 0, sizeof(args));
+	/* reset the pll flags */
+	pll->flags = 0;
 
 	if (ASIC_IS_AVIVO(rdev)) {
 		if ((rdev->family == CHIP_RS600) ||
 		    (rdev->family == CHIP_RS690) ||
 		    (rdev->family == CHIP_RS740))
-			pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
-				      RADEON_PLL_PREFER_CLOSEST_LOWER);
+			pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+				       RADEON_PLL_PREFER_CLOSEST_LOWER);
 
 		if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)	/* range limits??? */
-			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
-			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 	} else {
-		pll_flags |= RADEON_PLL_LEGACY;
+		pll->flags |= RADEON_PLL_LEGACY;
 
 		if (mode->clock > 200000)	/* range limits??? */
-			pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
-			pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
 	}
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
-			if (!ASIC_IS_AVIVO(rdev)) {
-				if (encoder->encoder_type !=
-				    DRM_MODE_ENCODER_DAC)
-					pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
-				if (encoder->encoder_type ==
-					DRM_MODE_ENCODER_LVDS)
-					pll_flags |= RADEON_PLL_USE_REF_DIV;
-			}
 			radeon_encoder = to_radeon_encoder(encoder);
+			if (ASIC_IS_AVIVO(rdev)) {
+				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
+				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
+					adjusted_clock = mode->clock * 2;
+			} else {
+				if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
+					pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
+				if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
+					pll->flags |= RADEON_PLL_USE_REF_DIV;
+			}
 			break;
 		}
 	}
@@ -471,46 +467,101 @@
 	 * special hw requirements.
 	 */
 	if (ASIC_IS_DCE3(rdev)) {
-		ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
+		union adjust_pixel_clock args;
+		struct radeon_encoder_atom_dig *dig;
+		u8 frev, crev;
+		int index;
 
-		if (!encoder)
-			return;
-
-		memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
-		adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
-		adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
-		adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
+		if (!radeon_encoder->enc_priv)
+			return adjusted_clock;
+		dig = radeon_encoder->enc_priv;
 
 		index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
-		atom_execute_table(rdev->mode_info.atom_context,
-				   index, (uint32_t *)&adjust_pll_args);
-		adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
-	} else {
-		/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
-		if (ASIC_IS_AVIVO(rdev) &&
-		    (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1))
-			adjusted_clock = mode->clock * 2;
-		else
-			adjusted_clock = mode->clock;
+		atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+				      &crev);
+
+		memset(&args, 0, sizeof(args));
+
+		switch (frev) {
+		case 1:
+			switch (crev) {
+			case 1:
+			case 2:
+				args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+				args.v1.ucTransmitterID = radeon_encoder->encoder_id;
+				args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
+
+				atom_execute_table(rdev->mode_info.atom_context,
+						   index, (uint32_t *)&args);
+				adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
+				break;
+			default:
+				DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+				return adjusted_clock;
+			}
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+			return adjusted_clock;
+		}
 	}
+	return adjusted_clock;
+}
+
+union set_pixel_clock {
+	SET_PIXEL_CLOCK_PS_ALLOCATION base;
+	PIXEL_CLOCK_PARAMETERS v1;
+	PIXEL_CLOCK_PARAMETERS_V2 v2;
+	PIXEL_CLOCK_PARAMETERS_V3 v3;
+};
+
+void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *encoder = NULL;
+	struct radeon_encoder *radeon_encoder = NULL;
+	u8 frev, crev;
+	int index;
+	union set_pixel_clock args;
+	u32 pll_clock = mode->clock;
+	u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
+	struct radeon_pll *pll;
+	u32 adjusted_clock;
+
+	memset(&args, 0, sizeof(args));
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc == crtc) {
+			radeon_encoder = to_radeon_encoder(encoder);
+			break;
+		}
+	}
+
+	if (!radeon_encoder)
+		return;
 
 	if (radeon_crtc->crtc_id == 0)
 		pll = &rdev->clock.p1pll;
 	else
 		pll = &rdev->clock.p2pll;
 
+	/* adjust pixel clock as needed */
+	adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
+
 	if (ASIC_IS_AVIVO(rdev)) {
 		if (radeon_new_pll)
 			radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
 						 &fb_div, &frac_fb_div,
-						 &ref_div, &post_div, pll_flags);
+						 &ref_div, &post_div);
 		else
 			radeon_compute_pll(pll, adjusted_clock, &pll_clock,
 					   &fb_div, &frac_fb_div,
-					   &ref_div, &post_div, pll_flags);
+					   &ref_div, &post_div);
 	} else
 		radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
-				   &ref_div, &post_div, pll_flags);
+				   &ref_div, &post_div);
 
 	index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
@@ -520,45 +571,38 @@
 	case 1:
 		switch (crev) {
 		case 1:
-			spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
-			spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-			spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
-			spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
-			spc1_ptr->ucFracFbDiv = frac_fb_div;
-			spc1_ptr->ucPostDiv = post_div;
-			spc1_ptr->ucPpll =
+			args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v1.usRefDiv = cpu_to_le16(ref_div);
+			args.v1.usFbDiv = cpu_to_le16(fb_div);
+			args.v1.ucFracFbDiv = frac_fb_div;
+			args.v1.ucPostDiv = post_div;
+			args.v1.ucPpll =
 			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
-			spc1_ptr->ucRefDivSrc = 1;
+			args.v1.ucCRTC = radeon_crtc->crtc_id;
+			args.v1.ucRefDivSrc = 1;
 			break;
 		case 2:
-			spc2_ptr =
-			    (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
-			spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-			spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
-			spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
-			spc2_ptr->ucFracFbDiv = frac_fb_div;
-			spc2_ptr->ucPostDiv = post_div;
-			spc2_ptr->ucPpll =
+			args.v2.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v2.usRefDiv = cpu_to_le16(ref_div);
+			args.v2.usFbDiv = cpu_to_le16(fb_div);
+			args.v2.ucFracFbDiv = frac_fb_div;
+			args.v2.ucPostDiv = post_div;
+			args.v2.ucPpll =
 			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
-			spc2_ptr->ucRefDivSrc = 1;
+			args.v2.ucCRTC = radeon_crtc->crtc_id;
+			args.v2.ucRefDivSrc = 1;
 			break;
 		case 3:
-			if (!encoder)
-				return;
-			spc3_ptr =
-			    (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
-			spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
-			spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
-			spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
-			spc3_ptr->ucFracFbDiv = frac_fb_div;
-			spc3_ptr->ucPostDiv = post_div;
-			spc3_ptr->ucPpll =
+			args.v3.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v3.usRefDiv = cpu_to_le16(ref_div);
+			args.v3.usFbDiv = cpu_to_le16(fb_div);
+			args.v3.ucFracFbDiv = frac_fb_div;
+			args.v3.ucPostDiv = post_div;
+			args.v3.ucPpll =
 			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
-			spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
-			spc3_ptr->ucEncoderMode =
+			args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
+			args.v3.ucTransmitterId = radeon_encoder->encoder_id;
+			args.v3.ucEncoderMode =
 			    atombios_get_encoder_mode(encoder);
 			break;
 		default:
@@ -571,12 +615,11 @@
 		return;
 	}
 
-	printk("executing set pll\n");
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-			   struct drm_framebuffer *old_fb)
+static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+			       struct drm_framebuffer *old_fb)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
@@ -706,6 +749,42 @@
 	return 0;
 }
 
+int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+			   struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (ASIC_IS_AVIVO(rdev))
+		return avivo_crtc_set_base(crtc, x, y, old_fb);
+	else
+		return radeon_crtc_set_base(crtc, x, y, old_fb);
+}
+
+/* properly set additional regs when using atombios */
+static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	u32 disp_merge_cntl;
+
+	switch (radeon_crtc->crtc_id) {
+	case 0:
+		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
+		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
+		break;
+	case 1:
+		disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
+		disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
+		WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
+		WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
+		WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
+		break;
+	}
+}
+
 int atombios_crtc_mode_set(struct drm_crtc *crtc,
 			   struct drm_display_mode *mode,
 			   struct drm_display_mode *adjusted_mode,
@@ -727,8 +806,8 @@
 	else {
 		if (radeon_crtc->crtc_id == 0)
 			atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
-		radeon_crtc_set_base(crtc, x, y, old_fb);
-		radeon_legacy_atom_set_surface(crtc);
+		atombios_crtc_set_base(crtc, x, y, old_fb);
+		radeon_legacy_atom_fixup(crtc);
 	}
 	atombios_overscan_setup(crtc, mode, adjusted_mode);
 	atombios_scaler_setup(crtc);
@@ -746,8 +825,8 @@
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
-	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 	atombios_lock_crtc(crtc, 1);
+	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
 static void atombios_crtc_commit(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 8760d66..11c9a3f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1504,6 +1504,7 @@
 			DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
 			return -EINVAL;
 		}
+		track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0));
 		track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
 		track->immd_dwords = pkt->count - 1;
 		r = r100_cs_track_check(p->rdev, track);
@@ -3399,9 +3400,7 @@
 	if (rdev->flags & RADEON_IS_AGP) {
 		r = radeon_agp_init(rdev);
 		if (r) {
-			printk(KERN_WARNING "[drm] Disabling AGP\n");
-			rdev->flags &= ~RADEON_IS_AGP;
-			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+			radeon_agp_disable(rdev);
 		} else {
 			rdev->mc.gtt_location = rdev->mc.agp_base;
 		}
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
index 2094212..ff1e0cd 100644
--- a/drivers/gpu/drm/radeon/r200.c
+++ b/drivers/gpu/drm/radeon/r200.c
@@ -371,13 +371,16 @@
 		case 5:
 		case 6:
 		case 7:
+			/* 1D/2D */
 			track->textures[i].tex_coord_type = 0;
 			break;
 		case 1:
-			track->textures[i].tex_coord_type = 1;
+			/* CUBE */
+			track->textures[i].tex_coord_type = 2;
 			break;
 		case 2:
-			track->textures[i].tex_coord_type = 2;
+			/* 3D */
+			track->textures[i].tex_coord_type = 1;
 			break;
 		}
 		break;
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 053404e..4526faa 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -50,9 +50,7 @@
 	if (rdev->flags & RADEON_IS_AGP) {
 		r = radeon_agp_init(rdev);
 		if (r) {
-			printk(KERN_WARNING "[drm] Disabling AGP\n");
-			rdev->flags &= ~RADEON_IS_AGP;
-			rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+			radeon_agp_disable(rdev);
 		} else {
 			rdev->mc.gtt_location = rdev->mc.agp_base;
 		}
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index f5ff349..da9aa3c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -624,7 +624,6 @@
 	fixed20_12 a;
 	u32 tmp;
 	int chansize, numchan;
-	int r;
 
 	/* Get VRAM informations */
 	rdev->mc.vram_is_ddr = true;
@@ -667,9 +666,6 @@
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
 
 	if (rdev->flags & RADEON_IS_AGP) {
-		r = radeon_agp_init(rdev);
-		if (r)
-			return r;
 		/* gtt_size is setup by radeon_agp_init */
 		rdev->mc.gtt_location = rdev->mc.agp_base;
 		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
@@ -1958,14 +1954,17 @@
 	/* FIXME: we should wait for ring to be empty */
 	r600_cp_stop(rdev);
 	rdev->cp.ready = false;
+	r600_irq_suspend(rdev);
 	r600_wb_disable(rdev);
 	r600_pcie_gart_disable(rdev);
 	/* unpin shaders bo */
-	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (unlikely(r != 0))
-		return r;
-	radeon_bo_unpin(rdev->r600_blit.shader_obj);
-	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (!r) {
+			radeon_bo_unpin(rdev->r600_blit.shader_obj);
+			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		}
+	}
 	return 0;
 }
 
@@ -2026,6 +2025,11 @@
 	r = radeon_fence_driver_init(rdev);
 	if (r)
 		return r;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r)
+			radeon_agp_disable(rdev);
+	}
 	r = r600_mc_init(rdev);
 	if (r)
 		return r;
@@ -2060,13 +2064,14 @@
 	if (rdev->accel_working) {
 		r = radeon_ib_pool_init(rdev);
 		if (r) {
-			DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
+			dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
 			rdev->accel_working = false;
-		}
-		r = r600_ib_test(rdev);
-		if (r) {
-			DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-			rdev->accel_working = false;
+		} else {
+			r = r600_ib_test(rdev);
+			if (r) {
+				dev_err(rdev->dev, "IB test failed (%d).\n", r);
+				rdev->accel_working = false;
+			}
 		}
 	}
 
@@ -2197,14 +2202,14 @@
 	rb_bufsz = drm_order(ring_size / 4);
 	ring_size = (1 << rb_bufsz) * 4;
 	rdev->ih.ring_size = ring_size;
-	rdev->ih.align_mask = 4 - 1;
+	rdev->ih.ptr_mask = rdev->ih.ring_size - 1;
+	rdev->ih.rptr = 0;
 }
 
-static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size)
+static int r600_ih_ring_alloc(struct radeon_device *rdev)
 {
 	int r;
 
-	rdev->ih.ring_size = ring_size;
 	/* Allocate ring buffer */
 	if (rdev->ih.ring_obj == NULL) {
 		r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
@@ -2234,9 +2239,6 @@
 			return r;
 		}
 	}
-	rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1;
-	rdev->ih.rptr = 0;
-
 	return 0;
 }
 
@@ -2386,7 +2388,7 @@
 	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
 
 	/* allocate ring */
-	ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size);
+	ret = r600_ih_ring_alloc(rdev);
 	if (ret)
 		return ret;
 
@@ -2449,10 +2451,15 @@
 	return ret;
 }
 
-void r600_irq_fini(struct radeon_device *rdev)
+void r600_irq_suspend(struct radeon_device *rdev)
 {
 	r600_disable_interrupts(rdev);
 	r600_rlc_stop(rdev);
+}
+
+void r600_irq_fini(struct radeon_device *rdev)
+{
+	r600_irq_suspend(rdev);
 	r600_ih_ring_fini(rdev);
 }
 
@@ -2467,8 +2474,12 @@
 		return -EINVAL;
 	}
 	/* don't enable anything if the ih is disabled */
-	if (!rdev->ih.enabled)
+	if (!rdev->ih.enabled) {
+		r600_disable_interrupts(rdev);
+		/* force the active interrupt state to all disabled */
+		r600_disable_interrupt_state(rdev);
 		return 0;
+	}
 
 	if (ASIC_IS_DCE3(rdev)) {
 		hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
@@ -2638,16 +2649,18 @@
 	wptr = RREG32(IH_RB_WPTR);
 
 	if (wptr & RB_OVERFLOW) {
-		WARN_ON(1);
-		/* XXX deal with overflow */
-		DRM_ERROR("IH RB overflow\n");
+		/* When a ring buffer overflow happen start parsing interrupt
+		 * from the last not overwritten vector (wptr + 16). Hopefully
+		 * this should allow us to catchup.
+		 */
+		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n",
+			wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask);
+		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
 		tmp = RREG32(IH_RB_CNTL);
 		tmp |= IH_WPTR_OVERFLOW_CLEAR;
 		WREG32(IH_RB_CNTL, tmp);
 	}
-	wptr = wptr & WPTR_OFFSET_MASK;
-
-	return wptr;
+	return (wptr & rdev->ih.ptr_mask);
 }
 
 /*        r600 IV Ring
@@ -2683,12 +2696,13 @@
 	u32 wptr = r600_get_ih_wptr(rdev);
 	u32 rptr = rdev->ih.rptr;
 	u32 src_id, src_data;
-	u32 last_entry = rdev->ih.ring_size - 16;
 	u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
 	unsigned long flags;
 	bool queue_hotplug = false;
 
 	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
+	if (!rdev->ih.enabled)
+		return IRQ_NONE;
 
 	spin_lock_irqsave(&rdev->ih.lock, flags);
 
@@ -2817,10 +2831,8 @@
 		}
 
 		/* wptr/rptr are in bytes! */
-		if (rptr == last_entry)
-			rptr = 0;
-		else
-			rptr += 16;
+		rptr += 16;
+		rptr &= rdev->ih.ptr_mask;
 	}
 	/* make sure wptr hasn't changed while processing */
 	wptr = r600_get_ih_wptr(rdev);
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index 8787ea8..2bedce4 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -512,14 +512,16 @@
 {
 	int r;
 
+	if (rdev->r600_blit.shader_obj == NULL)
+		return;
+	/* If we can't reserve the bo, unref should be enough to destroy
+	 * it when it becomes idle.
+	 */
 	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (unlikely(r != 0)) {
-		dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r);
-		goto out_unref;
+	if (!r) {
+		radeon_bo_unpin(rdev->r600_blit.shader_obj);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
 	}
-	radeon_bo_unpin(rdev->r600_blit.shader_obj);
-	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
-out_unref:
 	radeon_bo_unref(&rdev->r600_blit.shader_obj);
 }
 
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 44060b9..e4c45ec 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -36,6 +36,10 @@
 typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
 static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
 
+struct r600_cs_track {
+	u32	cb_color0_base_last;
+};
+
 /**
  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
  * @parser:	parser structure holding parsing context.
@@ -177,6 +181,28 @@
 }
 
 /**
+ * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
+ * @parser:		parser structure holding parsing context.
+ *
+ * Check next packet is relocation packet3, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
+{
+	struct radeon_cs_packet p3reloc;
+	int r;
+
+	r = r600_cs_packet_parse(p, &p3reloc, p->idx);
+	if (r) {
+		return 0;
+	}
+	if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
+		return 0;
+	}
+	return 1;
+}
+
+/**
  * r600_cs_packet_next_vline() - parse userspace VLINE packet
  * @parser:		parser structure holding parsing context.
  *
@@ -337,6 +363,7 @@
 				struct radeon_cs_packet *pkt)
 {
 	struct radeon_cs_reloc *reloc;
+	struct r600_cs_track *track;
 	volatile u32 *ib;
 	unsigned idx;
 	unsigned i;
@@ -344,6 +371,7 @@
 	int r;
 	u32 idx_value;
 
+	track = (struct r600_cs_track *)p->track;
 	ib = p->ib->ptr;
 	idx = pkt->idx + 1;
 	idx_value = radeon_get_ib_value(p, idx);
@@ -503,9 +531,60 @@
 		for (i = 0; i < pkt->count; i++) {
 			reg = start_reg + (4 * i);
 			switch (reg) {
+			/* This register were added late, there is userspace
+			 * which does provide relocation for those but set
+			 * 0 offset. In order to avoid breaking old userspace
+			 * we detect this and set address to point to last
+			 * CB_COLOR0_BASE, note that if userspace doesn't set
+			 * CB_COLOR0_BASE before this register we will report
+			 * error. Old userspace always set CB_COLOR0_BASE
+			 * before any of this.
+			 */
+			case R_0280E0_CB_COLOR0_FRAG:
+			case R_0280E4_CB_COLOR1_FRAG:
+			case R_0280E8_CB_COLOR2_FRAG:
+			case R_0280EC_CB_COLOR3_FRAG:
+			case R_0280F0_CB_COLOR4_FRAG:
+			case R_0280F4_CB_COLOR5_FRAG:
+			case R_0280F8_CB_COLOR6_FRAG:
+			case R_0280FC_CB_COLOR7_FRAG:
+			case R_0280C0_CB_COLOR0_TILE:
+			case R_0280C4_CB_COLOR1_TILE:
+			case R_0280C8_CB_COLOR2_TILE:
+			case R_0280CC_CB_COLOR3_TILE:
+			case R_0280D0_CB_COLOR4_TILE:
+			case R_0280D4_CB_COLOR5_TILE:
+			case R_0280D8_CB_COLOR6_TILE:
+			case R_0280DC_CB_COLOR7_TILE:
+				if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+					if (!track->cb_color0_base_last) {
+						dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
+						return -EINVAL;
+					}
+					ib[idx+1+i] = track->cb_color0_base_last;
+					printk_once(KERN_WARNING "radeon: You have old & broken userspace "
+						"please consider updating mesa & xf86-video-ati\n");
+				} else {
+					r = r600_cs_packet_next_reloc(p, &reloc);
+					if (r) {
+						dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+						return -EINVAL;
+					}
+					ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				}
+				break;
 			case DB_DEPTH_BASE:
 			case DB_HTILE_DATA_BASE:
 			case CB_COLOR0_BASE:
+				r = r600_cs_packet_next_reloc(p, &reloc);
+				if (r) {
+					DRM_ERROR("bad SET_CONTEXT_REG "
+							"0x%04X\n", reg);
+					return -EINVAL;
+				}
+				ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				track->cb_color0_base_last = ib[idx+1+i];
+				break;
 			case CB_COLOR1_BASE:
 			case CB_COLOR2_BASE:
 			case CB_COLOR3_BASE:
@@ -678,8 +757,11 @@
 int r600_cs_parse(struct radeon_cs_parser *p)
 {
 	struct radeon_cs_packet pkt;
+	struct r600_cs_track *track;
 	int r;
 
+	track = kzalloc(sizeof(*track), GFP_KERNEL);
+	p->track = track;
 	do {
 		r = r600_cs_packet_parse(p, &pkt, p->idx);
 		if (r) {
@@ -757,6 +839,7 @@
 	/* initialize parser */
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
+	parser.dev = &dev->pdev->dev;
 	parser.rdev = NULL;
 	parser.family = family;
 	parser.ib = &fake_ib;
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 05894ed..3048088 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -882,4 +882,29 @@
 #define		S_000E60_SOFT_RESET_VMC(x)		(((x) & 1) << 17)
 
 #define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL		0x5480
+
+#define R_0280E0_CB_COLOR0_FRAG                      0x0280E0
+#define   S_0280E0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280E0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280E0_BASE_256B                           0x00000000
+#define R_0280E4_CB_COLOR1_FRAG                      0x0280E4
+#define R_0280E8_CB_COLOR2_FRAG                      0x0280E8
+#define R_0280EC_CB_COLOR3_FRAG                      0x0280EC
+#define R_0280F0_CB_COLOR4_FRAG                      0x0280F0
+#define R_0280F4_CB_COLOR5_FRAG                      0x0280F4
+#define R_0280F8_CB_COLOR6_FRAG                      0x0280F8
+#define R_0280FC_CB_COLOR7_FRAG                      0x0280FC
+#define R_0280C0_CB_COLOR0_TILE                      0x0280C0
+#define   S_0280C0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
+#define   G_0280C0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
+#define   C_0280C0_BASE_256B                           0x00000000
+#define R_0280C4_CB_COLOR1_TILE                      0x0280C4
+#define R_0280C8_CB_COLOR2_TILE                      0x0280C8
+#define R_0280CC_CB_COLOR3_TILE                      0x0280CC
+#define R_0280D0_CB_COLOR4_TILE                      0x0280D0
+#define R_0280D4_CB_COLOR5_TILE                      0x0280D4
+#define R_0280D8_CB_COLOR6_TILE                      0x0280D8
+#define R_0280DC_CB_COLOR7_TILE                      0x0280DC
+
+
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index eb5f99b..f7df1a7 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -410,7 +410,6 @@
 	unsigned		wptr_old;
 	unsigned		ring_size;
 	uint64_t		gpu_addr;
-	uint32_t		align_mask;
 	uint32_t		ptr_mask;
 	spinlock_t              lock;
 	bool                    enabled;
@@ -465,6 +464,7 @@
 };
 
 struct radeon_cs_parser {
+	struct device		*dev;
 	struct radeon_device	*rdev;
 	struct drm_file		*filp;
 	/* chunks */
@@ -847,7 +847,7 @@
 
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
-	if (reg < 0x10000)
+	if (reg < rdev->rmmio_size)
 		return readl(((void __iomem *)rdev->rmmio) + reg);
 	else {
 		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -857,7 +857,7 @@
 
 static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
-	if (reg < 0x10000)
+	if (reg < rdev->rmmio_size)
 		writel(v, ((void __iomem *)rdev->rmmio) + reg);
 	else {
 		writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
@@ -1017,6 +1017,8 @@
 #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
 
 /* Common functions */
+/* AGP */
+extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
@@ -1160,7 +1162,8 @@
 extern void r600_irq_fini(struct radeon_device *rdev);
 extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
 extern int r600_irq_set(struct radeon_device *rdev);
-
+extern void r600_irq_suspend(struct radeon_device *rdev);
+/* r600 audio */
 extern int r600_audio_init(struct radeon_device *rdev);
 extern int r600_audio_tmds_index(struct drm_encoder *encoder);
 extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c
index 220f454..c9ad7f5 100644
--- a/drivers/gpu/drm/radeon/radeon_agp.c
+++ b/drivers/gpu/drm/radeon/radeon_agp.c
@@ -133,6 +133,13 @@
 	bool is_v3;
 	int ret;
 
+	if (rdev->ddev->agp->agp_info.aper_size < 32) {
+		dev_warn(rdev->dev, "AGP aperture to small (%dM) "
+			"need at least 32M, disabling AGP\n",
+			rdev->ddev->agp->agp_info.aper_size);
+		return -EINVAL;
+	}
+
 	/* Acquire AGP. */
 	if (!rdev->ddev->agp->acquired) {
 		ret = drm_agp_acquire(rdev->ddev);
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index 812f24d..73c4405 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -56,7 +56,7 @@
 	else if (post_div == 3)
 		sclk >>= 2;
 	else if (post_div == 4)
-		sclk >>= 4;
+		sclk >>= 3;
 
 	return sclk;
 }
@@ -86,7 +86,7 @@
 	else if (post_div == 3)
 		mclk >>= 2;
 	else if (post_div == 4)
-		mclk >>= 4;
+		mclk >>= 3;
 
 	return mclk;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 65590a0..1496cb8 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -231,6 +231,7 @@
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
 	parser.rdev = rdev;
+	parser.dev = rdev->dev;
 	r = radeon_cs_parser_init(&parser, data);
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 0c51f8e..768b150 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -544,6 +544,7 @@
 		rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
 		rdev->asic->gart_set_page = &r100_pci_gart_set_page;
 	}
+	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 }
 
 void radeon_check_arguments(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 0ec491e..6a92f99 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -357,7 +357,8 @@
 	if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
 	    (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
 		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
-		if (dig->dp_i2c_bus)
+		if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
+		     dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus)
 			radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter);
 	}
 	if (!radeon_connector->ddc_bus)
@@ -410,11 +411,12 @@
 			uint32_t *fb_div_p,
 			uint32_t *frac_fb_div_p,
 			uint32_t *ref_div_p,
-			uint32_t *post_div_p,
-			int flags)
+			uint32_t *post_div_p)
 {
 	uint32_t min_ref_div = pll->min_ref_div;
 	uint32_t max_ref_div = pll->max_ref_div;
+	uint32_t min_post_div = pll->min_post_div;
+	uint32_t max_post_div = pll->max_post_div;
 	uint32_t min_fractional_feed_div = 0;
 	uint32_t max_fractional_feed_div = 0;
 	uint32_t best_vco = pll->best_vco;
@@ -430,7 +432,7 @@
 	DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
 	freq = freq * 1000;
 
-	if (flags & RADEON_PLL_USE_REF_DIV)
+	if (pll->flags & RADEON_PLL_USE_REF_DIV)
 		min_ref_div = max_ref_div = pll->reference_div;
 	else {
 		while (min_ref_div < max_ref_div-1) {
@@ -445,19 +447,22 @@
 		}
 	}
 
-	if (flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+	if (pll->flags & RADEON_PLL_USE_POST_DIV)
+		min_post_div = max_post_div = pll->post_div;
+
+	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
 		min_fractional_feed_div = pll->min_frac_feedback_div;
 		max_fractional_feed_div = pll->max_frac_feedback_div;
 	}
 
-	for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
+	for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
 		uint32_t ref_div;
 
-		if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+		if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
 			continue;
 
 		/* legacy radeons only have a few post_divs */
-		if (flags & RADEON_PLL_LEGACY) {
+		if (pll->flags & RADEON_PLL_LEGACY) {
 			if ((post_div == 5) ||
 			    (post_div == 7) ||
 			    (post_div == 9) ||
@@ -504,7 +509,7 @@
 					tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
 					current_freq = radeon_div(tmp, ref_div * post_div);
 
-					if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
+					if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
 						error = freq - current_freq;
 						error = error < 0 ? 0xffffffff : error;
 					} else
@@ -531,12 +536,12 @@
 							best_freq = current_freq;
 							best_error = error;
 							best_vco_diff = vco_diff;
-						} else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
-							   ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
-							   ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
-							   ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
-							   ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
-							   ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
+						} else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) ||
+							   ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) {
 							best_post_div = post_div;
 							best_ref_div = ref_div;
 							best_feedback_div = feedback_div;
@@ -572,8 +577,7 @@
 			      uint32_t *fb_div_p,
 			      uint32_t *frac_fb_div_p,
 			      uint32_t *ref_div_p,
-			      uint32_t *post_div_p,
-			      int flags)
+			      uint32_t *post_div_p)
 {
 	fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq;
 	fixed20_12 pll_out_max, pll_out_min;
@@ -667,7 +671,6 @@
 		radeonfb_remove(dev, fb);
 
 	if (radeon_fb->obj) {
-		radeon_gem_object_unpin(radeon_fb->obj);
 		mutex_lock(&dev->struct_mutex);
 		drm_gem_object_unreference(radeon_fb->obj);
 		mutex_unlock(&dev->struct_mutex);
@@ -715,7 +718,11 @@
 	struct drm_gem_object *obj;
 
 	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle);
-
+	if (obj ==  NULL) {
+		dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
+			"can't create framebuffer\n", mode_cmd->handle);
+		return NULL;
+	}
 	return radeon_framebuffer_create(dev, mode_cmd, obj);
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index cc27485..b6d8081 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -339,69 +339,6 @@
 	}
 }
 
-/* properly set crtc bpp when using atombios */
-void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct radeon_device *rdev = dev->dev_private;
-	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
-	int format;
-	uint32_t crtc_gen_cntl;
-	uint32_t disp_merge_cntl;
-	uint32_t crtc_pitch;
-
-	switch (crtc->fb->bits_per_pixel) {
-	case 8:
-		format = 2;
-		break;
-	case 15:      /*  555 */
-		format = 3;
-		break;
-	case 16:      /*  565 */
-		format = 4;
-		break;
-	case 24:      /*  RGB */
-		format = 5;
-		break;
-	case 32:      /* xRGB */
-		format = 6;
-		break;
-	default:
-		return;
-	}
-
-	crtc_pitch  = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) +
-			((crtc->fb->bits_per_pixel * 8) - 1)) /
-		       (crtc->fb->bits_per_pixel * 8));
-	crtc_pitch |= crtc_pitch << 16;
-
-	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
-
-	switch (radeon_crtc->crtc_id) {
-	case 0:
-		disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL);
-		disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN;
-		WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl);
-
-		crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff;
-		crtc_gen_cntl |= (format << 8);
-		crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN;
-		WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);
-		break;
-	case 1:
-		disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL);
-		disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN;
-		WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl);
-
-		crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff;
-		crtc_gen_cntl |= (format << 8);
-		WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl);
-		WREG32(RADEON_FP_H2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_H_SYNC_STRT_WID));
-		WREG32(RADEON_FP_V2_SYNC_STRT_WID,   RREG32(RADEON_CRTC2_V_SYNC_STRT_WID));
-		break;
-	}
-}
-
 int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 			 struct drm_framebuffer *old_fb)
 {
@@ -755,7 +692,6 @@
 	uint32_t post_divider = 0;
 	uint32_t freq = 0;
 	uint8_t pll_gain;
-	int pll_flags = RADEON_PLL_LEGACY;
 	bool use_bios_divs = false;
 	/* PLL registers */
 	uint32_t pll_ref_div = 0;
@@ -789,10 +725,12 @@
 	else
 		pll = &rdev->clock.p1pll;
 
+	pll->flags = RADEON_PLL_LEGACY;
+
 	if (mode->clock > 200000) /* range limits??? */
-		pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+		pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 	else
-		pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+		pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
@@ -804,7 +742,7 @@
 			}
 
 			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
-				pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+				pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
 			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
 				if (!rdev->is_atom_bios) {
 					struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -819,7 +757,7 @@
 						}
 					}
 				}
-				pll_flags |= RADEON_PLL_USE_REF_DIV;
+				pll->flags |= RADEON_PLL_USE_REF_DIV;
 			}
 		}
 	}
@@ -829,8 +767,7 @@
 	if (!use_bios_divs) {
 		radeon_compute_pll(pll, mode->clock,
 				   &freq, &feedback_div, &frac_fb_div,
-				   &reference_div, &post_divider,
-				   pll_flags);
+				   &reference_div, &post_divider);
 
 		for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
 			if (post_div->divider == post_divider)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 91cb041..96b851f 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -125,16 +125,24 @@
 #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
 #define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
+#define RADEON_PLL_USE_POST_DIV         (1 << 12)
 
 struct radeon_pll {
-	uint16_t reference_freq;
-	uint16_t reference_div;
+	/* reference frequency */
+	uint32_t reference_freq;
+
+	/* fixed dividers */
+	uint32_t reference_div;
+	uint32_t post_div;
+
+	/* pll in/out limits */
 	uint32_t pll_in_min;
 	uint32_t pll_in_max;
 	uint32_t pll_out_min;
 	uint32_t pll_out_max;
-	uint16_t xclk;
+	uint32_t best_vco;
 
+	/* divider limits */
 	uint32_t min_ref_div;
 	uint32_t max_ref_div;
 	uint32_t min_post_div;
@@ -143,7 +151,12 @@
 	uint32_t max_feedback_div;
 	uint32_t min_frac_feedback_div;
 	uint32_t max_frac_feedback_div;
-	uint32_t best_vco;
+
+	/* flags for the current clock */
+	uint32_t flags;
+
+	/* pll id */
+	uint32_t id;
 };
 
 struct radeon_i2c_chan {
@@ -417,8 +430,7 @@
 			       uint32_t *fb_div_p,
 			       uint32_t *frac_fb_div_p,
 			       uint32_t *ref_div_p,
-			       uint32_t *post_div_p,
-			       int flags);
+			       uint32_t *post_div_p);
 
 extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
 				     uint64_t freq,
@@ -426,8 +438,7 @@
 				     uint32_t *fb_div_p,
 				     uint32_t *frac_fb_div_p,
 				     uint32_t *ref_div_p,
-				     uint32_t *post_div_p,
-				     int flags);
+				     uint32_t *post_div_p);
 
 extern void radeon_setup_encoder_clones(struct drm_device *dev);
 
@@ -453,7 +464,6 @@
 
 extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 				 struct drm_framebuffer *old_fb);
-extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc);
 
 extern int radeon_crtc_cursor_set(struct drm_crtc *crtc,
 				  struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 4e636de..d72a71b 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -220,7 +220,8 @@
 
 int radeon_bo_evict_vram(struct radeon_device *rdev)
 {
-	if (rdev->flags & RADEON_IS_IGP) {
+	/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
+	if (0 && (rdev->flags & RADEON_IS_IGP)) {
 		if (rdev->mc.igp_sideport_enabled == false)
 			/* Useless to evict on IGP chips */
 			return 0;
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r200 b/drivers/gpu/drm/radeon/reg_srcs/r200
index 6021c88..c29ac43 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/r200
+++ b/drivers/gpu/drm/radeon/reg_srcs/r200
@@ -91,6 +91,8 @@
 0x22b8 SE_TCL_TEX_CYL_WRAP_CTL
 0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL
 0x22c4 SE_TCL_POINT_SPRITE_CNTL
+0x22d0 SE_PVS_CNTL
+0x22d4 SE_PVS_CONST_CNTL
 0x2648 RE_POINTSIZE
 0x26c0 RE_TOP_LEFT
 0x26c4 RE_MISC
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 59c7124..55f6ffc 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -779,7 +779,6 @@
 	fixed20_12 a;
 	u32 tmp;
 	int chansize, numchan;
-	int r;
 
 	/* Get VRAM informations */
 	rdev->mc.vram_is_ddr = true;
@@ -822,9 +821,6 @@
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
 
 	if (rdev->flags & RADEON_IS_AGP) {
-		r = radeon_agp_init(rdev);
-		if (r)
-			return r;
 		/* gtt_size is setup by radeon_agp_init */
 		rdev->mc.gtt_location = rdev->mc.agp_base;
 		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
@@ -972,13 +968,16 @@
 	/* FIXME: we should wait for ring to be empty */
 	r700_cp_stop(rdev);
 	rdev->cp.ready = false;
+	r600_irq_suspend(rdev);
 	r600_wb_disable(rdev);
 	rv770_pcie_gart_disable(rdev);
 	/* unpin shaders bo */
-	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
-	if (likely(r == 0)) {
-		radeon_bo_unpin(rdev->r600_blit.shader_obj);
-		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	if (rdev->r600_blit.shader_obj) {
+		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+		if (likely(r == 0)) {
+			radeon_bo_unpin(rdev->r600_blit.shader_obj);
+			radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+		}
 	}
 	return 0;
 }
@@ -1037,6 +1036,11 @@
 	r = radeon_fence_driver_init(rdev);
 	if (r)
 		return r;
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r)
+			radeon_agp_disable(rdev);
+	}
 	r = rv770_mc_init(rdev);
 	if (r)
 		return r;
@@ -1071,13 +1075,14 @@
 	if (rdev->accel_working) {
 		r = radeon_ib_pool_init(rdev);
 		if (r) {
-			DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
+			dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
 			rdev->accel_working = false;
-		}
-		r = r600_ib_test(rdev);
-		if (r) {
-			DRM_ERROR("radeon: failed testing IB (%d).\n", r);
-			rdev->accel_working = false;
+		} else {
+			r = r600_ib_test(rdev);
+			if (r) {
+				dev_err(rdev->dev, "IB test failed (%d).\n", r);
+				rdev->accel_working = false;
+			}
 		}
 	}
 	return 0;
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 2920f9a..1a3e909 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -426,7 +426,8 @@
 		    bdev->man[bo->mem.mem_type].gpu_offset;
 		bo->cur_placement = bo->mem.placement;
 		spin_unlock(&bo->lock);
-	}
+	} else
+		bo->offset = 0;
 
 	return 0;
 
@@ -523,52 +524,44 @@
 static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
 {
 	struct ttm_bo_global *glob = bdev->glob;
-	struct ttm_buffer_object *entry, *nentry;
-	struct list_head *list, *next;
-	int ret;
+	struct ttm_buffer_object *entry = NULL;
+	int ret = 0;
 
 	spin_lock(&glob->lru_lock);
-	list_for_each_safe(list, next, &bdev->ddestroy) {
-		entry = list_entry(list, struct ttm_buffer_object, ddestroy);
-		nentry = NULL;
+	if (list_empty(&bdev->ddestroy))
+		goto out_unlock;
 
-		/*
-		 * Protect the next list entry from destruction while we
-		 * unlock the lru_lock.
-		 */
+	entry = list_first_entry(&bdev->ddestroy,
+		struct ttm_buffer_object, ddestroy);
+	kref_get(&entry->list_kref);
 
-		if (next != &bdev->ddestroy) {
-			nentry = list_entry(next, struct ttm_buffer_object,
-					    ddestroy);
+	for (;;) {
+		struct ttm_buffer_object *nentry = NULL;
+
+		if (entry->ddestroy.next != &bdev->ddestroy) {
+			nentry = list_first_entry(&entry->ddestroy,
+				struct ttm_buffer_object, ddestroy);
 			kref_get(&nentry->list_kref);
 		}
-		kref_get(&entry->list_kref);
 
 		spin_unlock(&glob->lru_lock);
 		ret = ttm_bo_cleanup_refs(entry, remove_all);
 		kref_put(&entry->list_kref, ttm_bo_release_list);
+		entry = nentry;
+
+		if (ret || !entry)
+			goto out;
 
 		spin_lock(&glob->lru_lock);
-		if (nentry) {
-			bool next_onlist = !list_empty(next);
-			spin_unlock(&glob->lru_lock);
-			kref_put(&nentry->list_kref, ttm_bo_release_list);
-			spin_lock(&glob->lru_lock);
-			/*
-			 * Someone might have raced us and removed the
-			 * next entry from the list. We don't bother restarting
-			 * list traversal.
-			 */
-
-			if (!next_onlist)
-				break;
-		}
-		if (ret)
+		if (list_empty(&entry->ddestroy))
 			break;
 	}
-	ret = !list_empty(&bdev->ddestroy);
-	spin_unlock(&glob->lru_lock);
 
+out_unlock:
+	spin_unlock(&glob->lru_lock);
+out:
+	if (entry)
+		kref_put(&entry->list_kref, ttm_bo_release_list);
 	return ret;
 }
 
@@ -950,6 +943,14 @@
 		ttm_flag_masked(&cur_flags, placement->busy_placement[i],
 				~TTM_PL_MASK_MEMTYPE);
 
+
+		if (mem_type == TTM_PL_SYSTEM) {
+			mem->mem_type = mem_type;
+			mem->placement = cur_flags;
+			mem->mm_node = NULL;
+			return 0;
+		}
+
 		ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem,
 						interruptible, no_wait);
 		if (ret == 0 && mem->mm_node) {
@@ -1844,6 +1845,9 @@
 	 * anyone tries to access a ttm page.
 	 */
 
+	if (bo->bdev->driver->swap_notify)
+		bo->bdev->driver->swap_notify(bo);
+
 	ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage);
 out:
 
@@ -1864,3 +1868,4 @@
 	while (ttm_bo_swapout(&bdev->glob->shrink) == 0)
 		;
 }
+EXPORT_SYMBOL(ttm_bo_swapout_all);
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c
index f619ebc..3d172ef 100644
--- a/drivers/gpu/drm/ttm/ttm_lock.c
+++ b/drivers/gpu/drm/ttm/ttm_lock.c
@@ -288,6 +288,7 @@
 	wake_up_all(&lock->queue);
 	spin_unlock(&lock->lock);
 }
+EXPORT_SYMBOL(ttm_suspend_unlock);
 
 static bool __ttm_suspend_lock(struct ttm_lock *lock)
 {
@@ -309,3 +310,4 @@
 {
 	wait_event(lock->queue, __ttm_suspend_lock(lock));
 }
+EXPORT_SYMBOL(ttm_suspend_lock);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index d6f2d2b..825ebe3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -48,6 +48,15 @@
 	.busy_placement = &vram_placement_flags
 };
 
+struct ttm_placement vmw_vram_sys_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &vram_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &sys_placement_flags
+};
+
 struct ttm_placement vmw_vram_ne_placement = {
 	.fpfn = 0,
 	.lpfn = 0,
@@ -172,6 +181,18 @@
 	return 0;
 }
 
+static void vmw_move_notify(struct ttm_buffer_object *bo,
+		     struct ttm_mem_reg *new_mem)
+{
+	if (new_mem->mem_type != TTM_PL_SYSTEM)
+		vmw_dmabuf_gmr_unbind(bo);
+}
+
+static void vmw_swap_notify(struct ttm_buffer_object *bo)
+{
+	vmw_dmabuf_gmr_unbind(bo);
+}
+
 /**
  * FIXME: We're using the old vmware polling method to sync.
  * Do this with fences instead.
@@ -225,5 +246,7 @@
 	.sync_obj_wait = vmw_sync_obj_wait,
 	.sync_obj_flush = vmw_sync_obj_flush,
 	.sync_obj_unref = vmw_sync_obj_unref,
-	.sync_obj_ref = vmw_sync_obj_ref
+	.sync_obj_ref = vmw_sync_obj_ref,
+	.move_notify = vmw_move_notify,
+	.swap_notify = vmw_swap_notify
 };
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 1db1ef3..dedd121 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -147,6 +147,8 @@
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
+static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+			      void *ptr);
 
 static void vmw_print_capabilities(uint32_t capabilities)
 {
@@ -217,6 +219,7 @@
 
 	dev_priv->dev = dev;
 	dev_priv->vmw_chipset = chipset;
+	dev_priv->last_read_sequence = (uint32_t) -100;
 	mutex_init(&dev_priv->hw_mutex);
 	mutex_init(&dev_priv->cmdbuf_mutex);
 	rwlock_init(&dev_priv->resource_lock);
@@ -351,6 +354,9 @@
 		vmw_fb_init(dev_priv);
 	}
 
+	dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
+	register_pm_notifier(&dev_priv->pm_nb);
+
 	return 0;
 
 out_no_device:
@@ -385,6 +391,8 @@
 
 	DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
 
+	unregister_pm_notifier(&dev_priv->pm_nb);
+
 	if (!dev_priv->stealth) {
 		vmw_fb_close(dev_priv);
 		vmw_kms_close(dev_priv);
@@ -650,6 +658,57 @@
 	drm_put_dev(dev);
 }
 
+static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+			      void *ptr)
+{
+	struct vmw_private *dev_priv =
+		container_of(nb, struct vmw_private, pm_nb);
+	struct vmw_master *vmaster = dev_priv->active_master;
+
+	switch (val) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		ttm_suspend_lock(&vmaster->lock);
+
+		/**
+		 * This empties VRAM and unbinds all GMR bindings.
+		 * Buffer contents is moved to swappable memory.
+		 */
+		ttm_bo_swapout_all(&dev_priv->bdev);
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		ttm_suspend_unlock(&vmaster->lock);
+		break;
+	case PM_RESTORE_PREPARE:
+		break;
+	case PM_POST_RESTORE:
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/**
+ * These might not be needed with the virtual SVGA device.
+ */
+
+int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+	return 0;
+}
+
+int vmw_pci_resume(struct pci_dev *pdev)
+{
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	return pci_enable_device(pdev);
+}
+
 static struct drm_driver driver = {
 	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
 	DRIVER_MODESET,
@@ -689,7 +748,9 @@
 		       .name = VMWGFX_DRIVER_NAME,
 		       .id_table = vmw_pci_id_list,
 		       .probe = vmw_probe,
-		       .remove = vmw_remove
+		       .remove = vmw_remove,
+		       .suspend = vmw_pci_suspend,
+		       .resume = vmw_pci_resume
 		       },
 	.name = VMWGFX_DRIVER_NAME,
 	.desc = VMWGFX_DRIVER_DESC,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index e61bd85..50529a7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -32,6 +32,7 @@
 #include "drmP.h"
 #include "vmwgfx_drm.h"
 #include "drm_hashtab.h"
+#include "linux/suspend.h"
 #include "ttm/ttm_bo_driver.h"
 #include "ttm/ttm_object.h"
 #include "ttm/ttm_lock.h"
@@ -258,6 +259,7 @@
 
 	struct vmw_master *active_master;
 	struct vmw_master fbdev_master;
+	struct notifier_block pm_nb;
 };
 
 static inline struct vmw_private *vmw_priv(struct drm_device *dev)
@@ -353,6 +355,7 @@
 				       struct vmw_dma_buffer *bo);
 extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
 				struct vmw_dma_buffer *bo);
+extern void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo);
 extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv);
 extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -401,6 +404,7 @@
 
 extern struct ttm_placement vmw_vram_placement;
 extern struct ttm_placement vmw_vram_ne_placement;
+extern struct ttm_placement vmw_vram_sys_placement;
 extern struct ttm_placement vmw_sys_placement;
 extern struct ttm_bo_driver vmw_bo_driver;
 extern int vmw_dma_quiescent(struct drm_device *dev);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 2e92da5..d69caf9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -490,10 +490,29 @@
 	if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
 		return 0;
 
+	/**
+	 * Put BO in VRAM, only if there is space.
+	 */
+
+	ret = ttm_bo_validate(bo, &vmw_vram_sys_placement, true, false);
+	if (unlikely(ret == -ERESTARTSYS))
+		return ret;
+
+	/**
+	 * Otherwise, set it up as GMR.
+	 */
+
+	if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
+		return 0;
+
 	ret = vmw_gmr_bind(dev_priv, bo);
 	if (likely(ret == 0 || ret == -ERESTARTSYS))
 		return ret;
 
+	/**
+	 * If that failed, try VRAM again, this time evicting
+	 * previous contents.
+	 */
 
 	ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false);
 	return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 641dde7..4f4f643 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -649,14 +649,6 @@
 	if (unlikely(ret != 0))
 		goto err_unlock;
 
-	if (vmw_bo->gmr_bound) {
-		vmw_gmr_unbind(vmw_priv, vmw_bo->gmr_id);
-		spin_lock(&bo->glob->lru_lock);
-		ida_remove(&vmw_priv->gmr_ida, vmw_bo->gmr_id);
-		spin_unlock(&bo->glob->lru_lock);
-		vmw_bo->gmr_bound = NULL;
-	}
-
 	ret = ttm_bo_validate(bo, &ne_placement, false, false);
 	ttm_bo_unreserve(bo);
 err_unlock:
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
index 01feb48..f7d5f70 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -98,8 +98,7 @@
 		 (unsigned int) min,
 		 (unsigned int) fifo->capabilities);
 
-	dev_priv->fence_seq = (uint32_t) -100;
-	dev_priv->last_read_sequence = (uint32_t) -100;
+	dev_priv->fence_seq = dev_priv->last_read_sequence;
 	iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
 
 	return vmw_fifo_send_fence(dev_priv, &dummy);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index b1af76e..686692d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -553,9 +553,7 @@
 	} *cmd;
 	int i, increment = 1;
 
-	if (!num_clips ||
-	    !(dev_priv->fifo.capabilities &
-	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
+	if (!num_clips) {
 		num_clips = 1;
 		clips = &norect;
 		norect.x1 = norect.y1 = 0;
@@ -574,10 +572,10 @@
 
 	for (i = 0; i < num_clips; i++, clips += increment) {
 		cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
-		cmd[i].body.x = cpu_to_le32(clips[i].x1);
-		cmd[i].body.y = cpu_to_le32(clips[i].y1);
-		cmd[i].body.width = cpu_to_le32(clips[i].x2 - clips[i].x1);
-		cmd[i].body.height = cpu_to_le32(clips[i].y2 - clips[i].y1);
+		cmd[i].body.x = cpu_to_le32(clips->x1);
+		cmd[i].body.y = cpu_to_le32(clips->y1);
+		cmd[i].body.width = cpu_to_le32(clips->x2 - clips->x1);
+		cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1);
 	}
 
 	vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
index bb6e6a0..5b6eabe 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -104,7 +104,6 @@
 				  bool pin, bool interruptible)
 {
 	struct ttm_buffer_object *bo = &buf->base;
-	struct ttm_bo_global *glob = bo->glob;
 	struct ttm_placement *overlay_placement = &vmw_vram_placement;
 	int ret;
 
@@ -116,14 +115,6 @@
 	if (unlikely(ret != 0))
 		goto err;
 
-	if (buf->gmr_bound) {
-		vmw_gmr_unbind(dev_priv, buf->gmr_id);
-		spin_lock(&glob->lru_lock);
-		ida_remove(&dev_priv->gmr_ida, buf->gmr_id);
-		spin_unlock(&glob->lru_lock);
-		buf->gmr_bound = NULL;
-	}
-
 	if (pin)
 		overlay_placement = &vmw_vram_ne_placement;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index c012d59..e01db12 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -599,6 +599,27 @@
 	if (unlikely(ret != 0))
 		goto out_err1;
 
+
+	if (srf->flags & (1 << 9) &&
+	    srf->num_sizes == 1 &&
+	    srf->sizes[0].width == 64 &&
+	    srf->sizes[0].height == 64 &&
+	    srf->format == SVGA3D_A8R8G8B8) {
+
+		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
+		/* clear the image */
+		if (srf->snooper.image) {
+			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
+		} else {
+			DRM_ERROR("Failed to allocate cursor_image\n");
+			ret = -ENOMEM;
+			goto out_err1;
+		}
+	} else {
+		srf->snooper.image = NULL;
+	}
+	srf->snooper.crtc = NULL;
+
 	user_srf->base.shareable = false;
 	user_srf->base.tfile = NULL;
 
@@ -622,24 +643,6 @@
 		return ret;
 	}
 
-	if (srf->flags & (1 << 9) &&
-	    srf->num_sizes == 1 &&
-	    srf->sizes[0].width == 64 &&
-	    srf->sizes[0].height == 64 &&
-	    srf->format == SVGA3D_A8R8G8B8) {
-
-		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
-		/* clear the image */
-		if (srf->snooper.image)
-			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
-		else
-			DRM_ERROR("Failed to allocate cursor_image\n");
-
-	} else {
-		srf->snooper.image = NULL;
-	}
-	srf->snooper.crtc = NULL;
-
 	rep->sid = user_srf->base.hash.key;
 	if (rep->sid == SVGA3D_INVALID_ID)
 		DRM_ERROR("Created bad Surface ID.\n");
@@ -754,20 +757,29 @@
 	return bo_user_size + page_array_size;
 }
 
-void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
+void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo)
 {
 	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
 	struct ttm_bo_global *glob = bo->glob;
 	struct vmw_private *dev_priv =
 		container_of(bo->bdev, struct vmw_private, bdev);
 
-	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
 	if (vmw_bo->gmr_bound) {
 		vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
 		spin_lock(&glob->lru_lock);
 		ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
 		spin_unlock(&glob->lru_lock);
+		vmw_bo->gmr_bound = false;
 	}
+}
+
+void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	struct ttm_bo_global *glob = bo->glob;
+
+	vmw_dmabuf_gmr_unbind(bo);
+	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
 	kfree(vmw_bo);
 }
 
@@ -813,18 +825,10 @@
 static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
 {
 	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
-	struct vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma;
 	struct ttm_bo_global *glob = bo->glob;
-	struct vmw_private *dev_priv =
-		container_of(bo->bdev, struct vmw_private, bdev);
 
+	vmw_dmabuf_gmr_unbind(bo);
 	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
-	if (vmw_bo->gmr_bound) {
-		vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
-		spin_lock(&glob->lru_lock);
-		ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
-		spin_unlock(&glob->lru_lock);
-	}
 	kfree(vmw_user_bo);
 }
 
@@ -868,7 +872,7 @@
 	}
 
 	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
-			      &vmw_vram_placement, true,
+			      &vmw_vram_sys_placement, true,
 			      &vmw_user_dmabuf_destroy);
 	if (unlikely(ret != 0))
 		return ret;
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index ff7664e..4c4e0f8 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -353,6 +353,11 @@
 	/* notify the driver we are taking a fault on this BO
 	 * and have reserved it */
 	void (*fault_reserve_notify)(struct ttm_buffer_object *bo);
+
+	/**
+	 * notify the driver that we're about to swap out this bo
+	 */
+	void (*swap_notify) (struct ttm_buffer_object *bo);
 };
 
 /**