Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / radeon_kms.c
index dce09ad..c633319 100644 (file)
 #include "radeon.h"
 #include "radeon_drm.h"
 
+#include <linux/vga_switcheroo.h>
+#include <linux/slab.h>
+
+int radeon_driver_unload_kms(struct drm_device *dev)
+{
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (rdev == NULL)
+               return 0;
+       radeon_modeset_fini(rdev);
+       radeon_device_fini(rdev);
+       kfree(rdev);
+       dev->dev_private = NULL;
+       return 0;
+}
 
-/*
- * Driver load/unload
- */
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
 {
        struct radeon_device *rdev;
@@ -54,25 +66,28 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
                flags |= RADEON_IS_PCI;
        }
 
+       /* radeon_device_init should report only fatal error
+        * like memory allocation failure or iomapping failure,
+        * or memory manager initialization failure, it must
+        * properly initialize the GPU MC controller and permit
+        * VRAM allocation
+        */
        r = radeon_device_init(rdev, dev, dev->pdev, flags);
        if (r) {
-               DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n");
-               radeon_device_fini(rdev);
-               kfree(rdev);
-               dev->dev_private = NULL;
-               return r;
+               dev_err(&dev->pdev->dev, "Fatal error during GPU init\n");
+               goto out;
        }
-       return 0;
-}
-
-int radeon_driver_unload_kms(struct drm_device *dev)
-{
-       struct radeon_device *rdev = dev->dev_private;
-
-       radeon_device_fini(rdev);
-       kfree(rdev);
-       dev->dev_private = NULL;
-       return 0;
+       /* Again modeset_init should fail only on fatal error
+        * otherwise it should provide enough functionalities
+        * for shadowfb to run
+        */
+       r = radeon_modeset_init(rdev);
+       if (r)
+               dev_err(&dev->pdev->dev, "Fatal error during modeset init\n");
+out:
+       if (r)
+               radeon_driver_unload_kms(dev);
+       return r;
 }
 
 
@@ -98,6 +113,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_NUM_Z_PIPES:
                value = rdev->num_z_pipes;
                break;
+       case RADEON_INFO_ACCEL_WORKING:
+               value = rdev->accel_working;
+               break;
        default:
                DRM_DEBUG("Invalid request %d\n", info->request);
                return -EINVAL;
@@ -121,6 +139,7 @@ int radeon_driver_firstopen_kms(struct drm_device *dev)
 
 void radeon_driver_lastclose_kms(struct drm_device *dev)
 {
+       vga_switcheroo_process_delayed_switch();
 }
 
 int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
@@ -146,7 +165,7 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
 {
        struct radeon_device *rdev = dev->dev_private;
 
-       if (crtc < 0 || crtc > 1) {
+       if (crtc < 0 || crtc >= rdev->num_crtc) {
                DRM_ERROR("Invalid crtc %d\n", crtc);
                return -EINVAL;
        }
@@ -158,7 +177,7 @@ int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
 {
        struct radeon_device *rdev = dev->dev_private;
 
-       if (crtc < 0 || crtc > 1) {
+       if (crtc < 0 || crtc >= rdev->num_crtc) {
                DRM_ERROR("Invalid crtc %d\n", crtc);
                return -EINVAL;
        }
@@ -172,7 +191,7 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
 {
        struct radeon_device *rdev = dev->dev_private;
 
-       if (crtc < 0 || crtc > 1) {
+       if (crtc < 0 || crtc >= rdev->num_crtc) {
                DRM_ERROR("Invalid crtc %d\n", crtc);
                return;
        }
@@ -184,55 +203,6 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
 
 
 /*
- * For multiple master (like multiple X).
- */
-struct drm_radeon_master_private {
-       drm_local_map_t *sarea;
-       drm_radeon_sarea_t *sarea_priv;
-};
-
-int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master)
-{
-       struct drm_radeon_master_private *master_priv;
-       unsigned long sareapage;
-       int ret;
-
-       master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
-       if (master_priv == NULL) {
-               return -ENOMEM;
-       }
-       /* prebuild the SAREA */
-       sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
-       ret = drm_addmap(dev, 0, sareapage, _DRM_SHM,
-                        _DRM_CONTAINS_LOCK,
-                        &master_priv->sarea);
-       if (ret) {
-               DRM_ERROR("SAREA setup failed\n");
-               return ret;
-       }
-       master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
-       master_priv->sarea_priv->pfCurrentPage = 0;
-       master->driver_priv = master_priv;
-       return 0;
-}
-
-void radeon_master_destroy_kms(struct drm_device *dev,
-                              struct drm_master *master)
-{
-       struct drm_radeon_master_private *master_priv = master->driver_priv;
-
-       if (master_priv == NULL) {
-               return;
-       }
-       if (master_priv->sarea) {
-               drm_rmmap_locked(dev, master_priv->sarea);
-       }
-       kfree(master_priv);
-       master->driver_priv = NULL;
-}
-
-
-/*
  * IOCTL.
  */
 int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
@@ -310,17 +280,17 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
        DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
        /* KMS */
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
 };
 int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);