diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 62b27be..065ce01 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -733,6 +733,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
 	udelay(10);
 	rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
 	rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR);
+	/* protect against crazy HW on resume */
+	rdev->cp.wptr &= rdev->cp.ptr_mask;
 	/* Set cp mode to bus mastering & enable cp*/
 	WREG32(RADEON_CP_CSQ_MODE,
 	       REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
@@ -1793,6 +1795,7 @@ int r100_gpu_reset(struct radeon_device *rdev)
 
 void r100_set_common_regs(struct radeon_device *rdev)
 {
+	u32 tmp;
 	/* set these so they don't interfere with anything */
 	WREG32(RADEON_OV0_SCALE_CNTL, 0);
 	WREG32(RADEON_SUBPIC_CNTL, 0);
@@ -1801,6 +1804,11 @@ void r100_set_common_regs(struct radeon_device *rdev)
 	WREG32(RADEON_DVI_I2C_CNTL_1, 0);
 	WREG32(RADEON_CAP0_TRIG_CNTL, 0);
 	WREG32(RADEON_CAP1_TRIG_CNTL, 0);
+
+	/* switch PM block to ACPI mode */
+	tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL);
+	tmp &= ~RADEON_PM_MODE_SEL;
+	WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
 }
 
 /*
@@ -3336,6 +3344,7 @@ static int r100_startup(struct radeon_device *rdev)
 
 int r100_resume(struct radeon_device *rdev)
 {
+	u32 save, tmp;
 	/* Make sur GART are not working */
 	if (rdev->flags & RADEON_IS_PCI)
 		r100_pci_gart_disable(rdev);
@@ -3347,8 +3356,36 @@ int r100_resume(struct radeon_device *rdev)
 			RREG32(R_000E40_RBBM_STATUS),
 			RREG32(R_0007C0_CP_STAT));
 	}
+	printk("SCLK %08x, MCLK %08x, PIN %08x, PLL_PWR %08x, CLK_PWR %08x\n",
+		RREG32_PLL(RADEON_SCLK_CNTL), RREG32_PLL(RADEON_MCLK_CNTL),
+		RREG32_PLL(RADEON_CLK_PIN_CNTL), RREG32_PLL(RADEON_PLL_PWRMGT_CNTL),
+		RREG32_PLL(RADEON_CLK_PWRMGT_CNTL));
+	{
+	  save = RREG32_PLL(RADEON_SCLK_CNTL);
+	  tmp = save |=	RADEON_SCLK_FORCE_HDP|
+			RADEON_SCLK_FORCE_DISP1|
+			RADEON_SCLK_FORCE_DISP2|
+			RADEON_SCLK_FORCE_TOP|
+			RADEON_SCLK_FORCE_SE|
+			RADEON_SCLK_FORCE_IDCT|
+			RADEON_SCLK_FORCE_VIP|
+			RADEON_SCLK_FORCE_PB|
+			RADEON_SCLK_FORCE_RE|
+			RADEON_SCLK_FORCE_TAM|
+			RADEON_SCLK_FORCE_TDM|
+			RADEON_SCLK_FORCE_RB|
+			RADEON_SCLK_FORCE_TV_SCLK|
+			RADEON_SCLK_FORCE_SUBPIC|
+			RADEON_SCLK_FORCE_OV0;
+	  WREG32_PLL(RADEON_SCLK_CNTL, tmp);
+	}
 	/* post */
 	radeon_combios_asic_init(rdev->ddev);
+	printk("SCLK %08x, MCLK %08x, PIN %08x, PLL_PWR %08x, CLK_PWR %08x\n",
+		RREG32_PLL(RADEON_SCLK_CNTL), RREG32_PLL(RADEON_MCLK_CNTL),
+		RREG32_PLL(RADEON_CLK_PIN_CNTL), RREG32_PLL(RADEON_PLL_PWRMGT_CNTL),
+		RREG32_PLL(RADEON_CLK_PWRMGT_CNTL));
+	WREG32_PLL(RADEON_SCLK_CNTL, save);
 	/* Resume clock after posting */
 	r100_clock_startup(rdev);
 	/* Initialize surface registers */
@@ -3358,11 +3395,19 @@ int r100_resume(struct radeon_device *rdev)
 
 int r100_suspend(struct radeon_device *rdev)
 {
+	struct r100_mc_save save;
 	r100_cp_disable(rdev);
 	r100_wb_disable(rdev);
 	r100_irq_disable(rdev);
 	if (rdev->flags & RADEON_IS_PCI)
 		r100_pci_gart_disable(rdev);
+	r100_mc_stop(rdev, &save);
+
+	printk("SCLK %08x, MCLK %08x, PIN %08x, PLL_PWR %08x, CLK_PWR %08x\n",
+		RREG32_PLL(RADEON_SCLK_CNTL), RREG32_PLL(RADEON_MCLK_CNTL),
+		RREG32_PLL(RADEON_CLK_PIN_CNTL), RREG32_PLL(RADEON_PLL_PWRMGT_CNTL),
+		RREG32_PLL(RADEON_CLK_PWRMGT_CNTL));
+	
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 768b150..3290e88 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -728,7 +728,43 @@ void radeon_device_fini(struct radeon_device *rdev)
 	rdev->rmmio = NULL;
 }
 
+static int radeon_m9_whack_power_state(struct drm_device *dev, pci_power_t state)
+{
+	u16 pwr_cmd;
+	struct radeon_device *rdev = dev->dev_private;
+	u32 tmp;
+	int pm_reg;
+	int loop_count = 0;
+
+	pm_reg = pci_find_capability(dev->pdev, PCI_CAP_ID_PM);
+	if (!pm_reg)
+		return 0; 
+
+	if (state > 3)
+		return 0;
 
+	for (loop_count = 0; loop_count < 20; loop_count++) {
+		pci_read_config_word(dev->pdev, pm_reg+PCI_PM_CTRL, &pwr_cmd);
+		printk(KERN_ERR "pwr_cmd is %04x\n", pwr_cmd);
+
+		if ((pwr_cmd & 3) == state)
+			break;
+		pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state;
+		pci_write_config_word(dev->pdev, pm_reg+PCI_PM_CTRL, pwr_cmd);
+
+    		/* switch PM block to ACPI mode */
+		tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL);
+		tmp &= ~RADEON_PM_MODE_SEL;
+		WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
+		
+		msleep(500);
+	}
+	if (loop_count >= 20)
+		printk(KERN_ERR "Unable to whack into D3\n");
+	dev->pdev->current_state = state;
+	__pci_complete_power_transition(dev->pdev, state);
+	return 0;
+}
 /*
  * Suspend & resume.
  */
@@ -779,6 +815,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 	if (state.event == PM_EVENT_SUSPEND) {
 		/* Shut down the device */
 		pci_disable_device(dev->pdev);
+		radeon_m9_whack_power_state(dev, PCI_D3hot);
 		pci_set_power_state(dev->pdev, PCI_D3hot);
 	}
 	acquire_console_sem();
@@ -791,18 +828,23 @@ int radeon_resume_kms(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
 
-	acquire_console_sem();
+	printk("in rrk\n");
 	pci_set_power_state(dev->pdev, PCI_D0);
 	pci_restore_state(dev->pdev);
 	if (pci_enable_device(dev->pdev)) {
 		release_console_sem();
+		printk("in rrkfail \n");
 		return -1;
 	}
+	printk("in rrksuccess \n");
 	pci_set_master(dev->pdev);
 	/* resume AGP if in use */
 	radeon_agp_resume(rdev);
+	printk("in rrksuccess post agp resume\n");
 	radeon_resume(rdev);
+	printk("in rrksuccess post resume\n");
 	radeon_restore_bios_scratch_regs(rdev);
+	acquire_console_sem();
 	fb_set_suspend(rdev->fbdev_info, 0);
 	release_console_sem();
 
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index f23b056..c73e52a 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -172,15 +172,34 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
 int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
 {
 	struct radeon_device *rdev = dev->dev_private;
-
+	u32 tmp;
 	if (crtc < 0 || crtc > 1) {
 		DRM_ERROR("Invalid crtc %d\n", crtc);
 		return -EINVAL;
 	}
 
+	if (ASIC_IS_AVIVO(rdev)) {
+
+	} else {
+		switch (crtc) {
+		case 0:
+			tmp = RREG32(RADEON_CRTC_GEN_CNTL);
+			if (!(tmp & RADEON_CRTC_EN))
+				goto fail;
+			break;
+		case 1:
+			tmp = RREG32(RADEON_CRTC2_GEN_CNTL);
+			if (!(tmp & RADEON_CRTC_EN))
+				goto fail;
+			break;
+		}
+	}
 	rdev->irq.crtc_vblank_int[crtc] = true;
 
 	return radeon_irq_set(rdev);
+fail:
+	printk(KERN_ERR "tried to enable vbl on disabled crtc %d\n", crtc);
+	return -1;
 }
 
 void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index 6d0a009..b85202c 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -346,6 +346,7 @@
 #       define RADEON_TVPLL_PWRMGT_OFF      (1 << 30)
 #       define RADEON_TVCLK_TURNOFF         (1 << 31)
 #define RADEON_PLL_PWRMGT_CNTL              0x0015 /* PLL */
+#	define RADEON_PM_MODE_SEL           (1 << 13)
 #       define RADEON_TCL_BYPASS_DISABLE    (1 << 20)
 #define RADEON_CLR_CMP_CLR_3D               0x1a24
 #define RADEON_CLR_CMP_CLR_DST              0x15c8
