drm/radeon/kms: add support for gui idle interrupts (v4)
[deliverable/linux.git] / drivers / gpu / drm / radeon / radeon_device.c
index bddf17f97da8eb23904424750a866408d5db5fb7..53a2c27dd8fa3556985c1844b07e3d8b41d1b5d3 100644 (file)
 #include "radeon.h"
 #include "atom.h"
 
+static const char radeon_family_name[][16] = {
+       "R100",
+       "RV100",
+       "RS100",
+       "RV200",
+       "RS200",
+       "R200",
+       "RV250",
+       "RS300",
+       "RV280",
+       "R300",
+       "R350",
+       "RV350",
+       "RV380",
+       "R420",
+       "R423",
+       "RV410",
+       "RS400",
+       "RS480",
+       "RS600",
+       "RS690",
+       "RS740",
+       "RV515",
+       "R520",
+       "RV530",
+       "RV560",
+       "RV570",
+       "R580",
+       "R600",
+       "RV610",
+       "RV630",
+       "RV670",
+       "RV620",
+       "RV635",
+       "RS780",
+       "RS880",
+       "RV770",
+       "RV730",
+       "RV710",
+       "RV740",
+       "CEDAR",
+       "REDWOOD",
+       "JUNIPER",
+       "CYPRESS",
+       "HEMLOCK",
+       "LAST",
+};
+
 /*
  * Clear GPU surface registers.
  */
@@ -526,7 +574,6 @@ int radeon_device_init(struct radeon_device *rdev,
        int r;
        int dma_bits;
 
-       DRM_INFO("radeon: Initializing kernel modesetting.\n");
        rdev->shutdown = false;
        rdev->dev = &pdev->dev;
        rdev->ddev = ddev;
@@ -538,6 +585,10 @@ int radeon_device_init(struct radeon_device *rdev,
        rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
        rdev->gpu_lockup = false;
        rdev->accel_working = false;
+
+       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
+               radeon_family_name[rdev->family], pdev->vendor, pdev->device);
+
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
        mutex_init(&rdev->cs_mutex);
@@ -551,6 +602,7 @@ int radeon_device_init(struct radeon_device *rdev,
        rwlock_init(&rdev->fence_drv.lock);
        INIT_LIST_HEAD(&rdev->gem.objects);
        init_waitqueue_head(&rdev->irq.vblank_queue);
+       init_waitqueue_head(&rdev->irq.idle_queue);
 
        /* setup workqueue */
        rdev->wq = create_workqueue("radeon");
@@ -620,7 +672,7 @@ int radeon_device_init(struct radeon_device *rdev,
                /* Acceleration not working on AGP card try again
                 * with fallback to PCI or PCIE GART
                 */
-               radeon_gpu_reset(rdev);
+               radeon_asic_reset(rdev);
                radeon_fini(rdev);
                radeon_agp_disable(rdev);
                r = radeon_init(rdev);
@@ -640,6 +692,8 @@ void radeon_device_fini(struct radeon_device *rdev)
 {
        DRM_INFO("radeon: finishing device.\n");
        rdev->shutdown = true;
+       /* evict vram memory */
+       radeon_bo_evict_vram(rdev);
        radeon_fini(rdev);
        destroy_workqueue(rdev->wq);
        vga_switcheroo_unregister_client(rdev->pdev);
@@ -677,9 +731,10 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
                        continue;
                }
                robj = rfb->obj->driver_private;
-               if (robj != rdev->fbdev_rbo) {
+               /* don't unpin kernel fb objects */
+               if (!radeon_fbdev_robj_is_fb(rdev, robj)) {
                        r = radeon_bo_reserve(robj, false);
-                       if (unlikely(r == 0)) {
+                       if (r == 0) {
                                radeon_bo_unpin(robj);
                                radeon_bo_unreserve(robj);
                        }
@@ -704,7 +759,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
                pci_set_power_state(dev->pdev, PCI_D3hot);
        }
        acquire_console_sem();
-       fb_set_suspend(rdev->fbdev_info, 1);
+       radeon_fbdev_set_suspend(rdev, 1);
        release_console_sem();
        return 0;
 }
@@ -728,7 +783,7 @@ int radeon_resume_kms(struct drm_device *dev)
        radeon_agp_resume(rdev);
        radeon_resume(rdev);
        radeon_restore_bios_scratch_regs(rdev);
-       fb_set_suspend(rdev->fbdev_info, 0);
+       radeon_fbdev_set_suspend(rdev, 0);
        release_console_sem();
 
        /* reset hpd state */
@@ -738,6 +793,26 @@ int radeon_resume_kms(struct drm_device *dev)
        return 0;
 }
 
+int radeon_gpu_reset(struct radeon_device *rdev)
+{
+       int r;
+
+       radeon_save_bios_scratch_regs(rdev);
+       radeon_suspend(rdev);
+
+       r = radeon_asic_reset(rdev);
+       if (!r) {
+               dev_info(rdev->dev, "GPU reset succeed\n");
+               radeon_resume(rdev);
+               radeon_restore_bios_scratch_regs(rdev);
+               drm_helper_resume_force_mode(rdev->ddev);
+               return 0;
+       }
+       /* bad news, how to tell it to userspace ? */
+       dev_info(rdev->dev, "GPU reset failed\n");
+       return r;
+}
+
 
 /*
  * Debugfs
This page took 0.036651 seconds and 5 git commands to generate.