drm/radeon/kms: make sure display hw is disabled when suspending
[pandora-kernel.git] / drivers / gpu / drm / i915 / i915_dma.c
index 75248be..cc6e56a 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 #include <linux/vga_switcheroo.h>
+#include <linux/slab.h>
 
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
@@ -1356,19 +1357,30 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 
        dev_priv->cfb_size = size;
 
+       intel_disable_fbc(dev);
+       dev_priv->compressed_fb = compressed_fb;
+
        if (IS_GM45(dev)) {
-               g4x_disable_fbc(dev);
                I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
        } else {
-               i8xx_disable_fbc(dev);
                I915_WRITE(FBC_CFB_BASE, cfb_base);
                I915_WRITE(FBC_LL_BASE, ll_base);
+               dev_priv->compressed_llb = compressed_llb;
        }
 
        DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
                  ll_base, size >> 20);
 }
 
+static void i915_cleanup_compression(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       drm_mm_put_block(dev_priv->compressed_fb);
+       if (!IS_GM45(dev))
+               drm_mm_put_block(dev_priv->compressed_llb);
+}
+
 /* true = enable decode, false = disable decoder */
 static unsigned int i915_vga_set_decode(void *cookie, bool state)
 {
@@ -1387,12 +1399,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
        struct drm_device *dev = pci_get_drvdata(pdev);
        pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
        if (state == VGA_SWITCHEROO_ON) {
-               printk(KERN_INFO "i915: switched off\n");
+               printk(KERN_INFO "i915: switched on\n");
                /* i915 resume handler doesn't set to D0 */
                pci_set_power_state(dev->pdev, PCI_D0);
                i915_resume(dev);
+               drm_kms_helper_poll_enable(dev);
        } else {
                printk(KERN_ERR "i915: switched off\n");
+               drm_kms_helper_poll_disable(dev);
                i915_suspend(dev, pmm);
        }
 }
@@ -1491,8 +1505,8 @@ static int i915_load_modeset_init(struct drm_device *dev,
 
        I915_WRITE(INSTPM, (1 << 5) | (1 << 21));
 
-       drm_helper_initial_config(dev);
-
+       intel_fbdev_init(dev);
+       drm_kms_helper_poll_init(dev);
        return 0;
 
 destroy_ringbuffer:
@@ -1758,6 +1772,8 @@ int i915_driver_unload(struct drm_device *dev)
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               intel_modeset_cleanup(dev);
+
                /*
                 * free the memory space allocated for the child device
                 * config parsed from VBT
@@ -1781,13 +1797,13 @@ int i915_driver_unload(struct drm_device *dev)
        intel_opregion_free(dev, 0);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               intel_modeset_cleanup(dev);
-
                i915_gem_free_all_phys_object(dev);
 
                mutex_lock(&dev->struct_mutex);
                i915_gem_cleanup_ringbuffer(dev);
                mutex_unlock(&dev->struct_mutex);
+               if (I915_HAS_FBC(dev) && i915_powersave)
+                       i915_cleanup_compression(dev);
                drm_mm_takedown(&dev_priv->vram);
                i915_gem_lastclose(dev);