Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
[sfrench/cifs-2.6.git] / drivers / gpu / drm / nouveau / nouveau_state.c
index b02a231d6937489fe972bfc813dc72d5d421aa70..ee3729e7823ba312001985790e54f4844610416d 100644 (file)
@@ -38,6 +38,7 @@
 #include "nv50_display.h"
 
 static void nouveau_stub_takedown(struct drm_device *dev) {}
+static int nouveau_stub_init(struct drm_device *dev) { return 0; }
 
 static int nouveau_init_engine_ptrs(struct drm_device *dev)
 {
@@ -54,8 +55,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->instmem.clear           = nv04_instmem_clear;
                engine->instmem.bind            = nv04_instmem_bind;
                engine->instmem.unbind          = nv04_instmem_unbind;
-               engine->instmem.prepare_access  = nv04_instmem_prepare_access;
-               engine->instmem.finish_access   = nv04_instmem_finish_access;
+               engine->instmem.flush           = nv04_instmem_flush;
                engine->mc.init                 = nv04_mc_init;
                engine->mc.takedown             = nv04_mc_takedown;
                engine->timer.init              = nv04_timer_init;
@@ -85,6 +85,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv04_fifo_destroy_context;
                engine->fifo.load_context       = nv04_fifo_load_context;
                engine->fifo.unload_context     = nv04_fifo_unload_context;
+               engine->display.early_init      = nv04_display_early_init;
+               engine->display.late_takedown   = nv04_display_late_takedown;
+               engine->display.create          = nv04_display_create;
+               engine->display.init            = nv04_display_init;
+               engine->display.destroy         = nv04_display_destroy;
+               engine->gpio.init               = nouveau_stub_init;
+               engine->gpio.takedown           = nouveau_stub_takedown;
+               engine->gpio.get                = NULL;
+               engine->gpio.set                = NULL;
+               engine->gpio.irq_enable         = NULL;
                break;
        case 0x10:
                engine->instmem.init            = nv04_instmem_init;
@@ -95,8 +105,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->instmem.clear           = nv04_instmem_clear;
                engine->instmem.bind            = nv04_instmem_bind;
                engine->instmem.unbind          = nv04_instmem_unbind;
-               engine->instmem.prepare_access  = nv04_instmem_prepare_access;
-               engine->instmem.finish_access   = nv04_instmem_finish_access;
+               engine->instmem.flush           = nv04_instmem_flush;
                engine->mc.init                 = nv04_mc_init;
                engine->mc.takedown             = nv04_mc_takedown;
                engine->timer.init              = nv04_timer_init;
@@ -128,6 +137,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv10_fifo_destroy_context;
                engine->fifo.load_context       = nv10_fifo_load_context;
                engine->fifo.unload_context     = nv10_fifo_unload_context;
+               engine->display.early_init      = nv04_display_early_init;
+               engine->display.late_takedown   = nv04_display_late_takedown;
+               engine->display.create          = nv04_display_create;
+               engine->display.init            = nv04_display_init;
+               engine->display.destroy         = nv04_display_destroy;
+               engine->gpio.init               = nouveau_stub_init;
+               engine->gpio.takedown           = nouveau_stub_takedown;
+               engine->gpio.get                = nv10_gpio_get;
+               engine->gpio.set                = nv10_gpio_set;
+               engine->gpio.irq_enable         = NULL;
                break;
        case 0x20:
                engine->instmem.init            = nv04_instmem_init;
@@ -138,8 +157,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->instmem.clear           = nv04_instmem_clear;
                engine->instmem.bind            = nv04_instmem_bind;
                engine->instmem.unbind          = nv04_instmem_unbind;
-               engine->instmem.prepare_access  = nv04_instmem_prepare_access;
-               engine->instmem.finish_access   = nv04_instmem_finish_access;
+               engine->instmem.flush           = nv04_instmem_flush;
                engine->mc.init                 = nv04_mc_init;
                engine->mc.takedown             = nv04_mc_takedown;
                engine->timer.init              = nv04_timer_init;
@@ -171,6 +189,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv10_fifo_destroy_context;
                engine->fifo.load_context       = nv10_fifo_load_context;
                engine->fifo.unload_context     = nv10_fifo_unload_context;
+               engine->display.early_init      = nv04_display_early_init;
+               engine->display.late_takedown   = nv04_display_late_takedown;
+               engine->display.create          = nv04_display_create;
+               engine->display.init            = nv04_display_init;
+               engine->display.destroy         = nv04_display_destroy;
+               engine->gpio.init               = nouveau_stub_init;
+               engine->gpio.takedown           = nouveau_stub_takedown;
+               engine->gpio.get                = nv10_gpio_get;
+               engine->gpio.set                = nv10_gpio_set;
+               engine->gpio.irq_enable         = NULL;
                break;
        case 0x30:
                engine->instmem.init            = nv04_instmem_init;
@@ -181,15 +209,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->instmem.clear           = nv04_instmem_clear;
                engine->instmem.bind            = nv04_instmem_bind;
                engine->instmem.unbind          = nv04_instmem_unbind;
-               engine->instmem.prepare_access  = nv04_instmem_prepare_access;
-               engine->instmem.finish_access   = nv04_instmem_finish_access;
+               engine->instmem.flush           = nv04_instmem_flush;
                engine->mc.init                 = nv04_mc_init;
                engine->mc.takedown             = nv04_mc_takedown;
                engine->timer.init              = nv04_timer_init;
                engine->timer.read              = nv04_timer_read;
                engine->timer.takedown          = nv04_timer_takedown;
-               engine->fb.init                 = nv10_fb_init;
-               engine->fb.takedown             = nv10_fb_takedown;
+               engine->fb.init                 = nv30_fb_init;
+               engine->fb.takedown             = nv30_fb_takedown;
                engine->fb.set_region_tiling    = nv10_fb_set_region_tiling;
                engine->graph.grclass           = nv30_graph_grclass;
                engine->graph.init              = nv30_graph_init;
@@ -214,6 +241,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv10_fifo_destroy_context;
                engine->fifo.load_context       = nv10_fifo_load_context;
                engine->fifo.unload_context     = nv10_fifo_unload_context;
+               engine->display.early_init      = nv04_display_early_init;
+               engine->display.late_takedown   = nv04_display_late_takedown;
+               engine->display.create          = nv04_display_create;
+               engine->display.init            = nv04_display_init;
+               engine->display.destroy         = nv04_display_destroy;
+               engine->gpio.init               = nouveau_stub_init;
+               engine->gpio.takedown           = nouveau_stub_takedown;
+               engine->gpio.get                = nv10_gpio_get;
+               engine->gpio.set                = nv10_gpio_set;
+               engine->gpio.irq_enable         = NULL;
                break;
        case 0x40:
        case 0x60:
@@ -225,8 +262,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->instmem.clear           = nv04_instmem_clear;
                engine->instmem.bind            = nv04_instmem_bind;
                engine->instmem.unbind          = nv04_instmem_unbind;
-               engine->instmem.prepare_access  = nv04_instmem_prepare_access;
-               engine->instmem.finish_access   = nv04_instmem_finish_access;
+               engine->instmem.flush           = nv04_instmem_flush;
                engine->mc.init                 = nv40_mc_init;
                engine->mc.takedown             = nv40_mc_takedown;
                engine->timer.init              = nv04_timer_init;
@@ -258,6 +294,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv40_fifo_destroy_context;
                engine->fifo.load_context       = nv40_fifo_load_context;
                engine->fifo.unload_context     = nv40_fifo_unload_context;
+               engine->display.early_init      = nv04_display_early_init;
+               engine->display.late_takedown   = nv04_display_late_takedown;
+               engine->display.create          = nv04_display_create;
+               engine->display.init            = nv04_display_init;
+               engine->display.destroy         = nv04_display_destroy;
+               engine->gpio.init               = nouveau_stub_init;
+               engine->gpio.takedown           = nouveau_stub_takedown;
+               engine->gpio.get                = nv10_gpio_get;
+               engine->gpio.set                = nv10_gpio_set;
+               engine->gpio.irq_enable         = NULL;
                break;
        case 0x50:
        case 0x80: /* gotta love NVIDIA's consistency.. */
@@ -271,8 +317,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->instmem.clear           = nv50_instmem_clear;
                engine->instmem.bind            = nv50_instmem_bind;
                engine->instmem.unbind          = nv50_instmem_unbind;
-               engine->instmem.prepare_access  = nv50_instmem_prepare_access;
-               engine->instmem.finish_access   = nv50_instmem_finish_access;
+               if (dev_priv->chipset == 0x50)
+                       engine->instmem.flush   = nv50_instmem_flush;
+               else
+                       engine->instmem.flush   = nv84_instmem_flush;
                engine->mc.init                 = nv50_mc_init;
                engine->mc.takedown             = nv50_mc_takedown;
                engine->timer.init              = nv04_timer_init;
@@ -300,6 +348,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
                engine->fifo.destroy_context    = nv50_fifo_destroy_context;
                engine->fifo.load_context       = nv50_fifo_load_context;
                engine->fifo.unload_context     = nv50_fifo_unload_context;
+               engine->display.early_init      = nv50_display_early_init;
+               engine->display.late_takedown   = nv50_display_late_takedown;
+               engine->display.create          = nv50_display_create;
+               engine->display.init            = nv50_display_init;
+               engine->display.destroy         = nv50_display_destroy;
+               engine->gpio.init               = nv50_gpio_init;
+               engine->gpio.takedown           = nouveau_stub_takedown;
+               engine->gpio.get                = nv50_gpio_get;
+               engine->gpio.set                = nv50_gpio_set;
+               engine->gpio.irq_enable         = nv50_gpio_irq_enable;
                break;
        default:
                NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -407,11 +465,6 @@ nouveau_card_init(struct drm_device *dev)
        struct nouveau_engine *engine;
        int ret;
 
-       NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
-
-       if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
-               return 0;
-
        vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
        vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
                                       nouveau_switcheroo_can_switch);
@@ -421,15 +474,17 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out;
        engine = &dev_priv->engine;
-       dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
        spin_lock_init(&dev_priv->context_switch_lock);
 
+       /* Make the CRTCs and I2C buses accessible */
+       ret = engine->display.early_init(dev);
+       if (ret)
+               goto out;
+
        /* Parse BIOS tables / Run init tables if card not POSTed */
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = nouveau_bios_init(dev);
-               if (ret)
-                       goto out;
-       }
+       ret = nouveau_bios_init(dev);
+       if (ret)
+               goto out_display_early;
 
        ret = nouveau_mem_detect(dev);
        if (ret)
@@ -461,10 +516,15 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_gpuobj;
 
+       /* PGPIO */
+       ret = engine->gpio.init(dev);
+       if (ret)
+               goto out_mc;
+
        /* PTIMER */
        ret = engine->timer.init(dev);
        if (ret)
-               goto out_mc;
+               goto out_gpio;
 
        /* PFB */
        ret = engine->fb.init(dev);
@@ -485,12 +545,16 @@ nouveau_card_init(struct drm_device *dev)
                        goto out_graph;
        }
 
+       ret = engine->display.create(dev);
+       if (ret)
+               goto out_fifo;
+
        /* this call irq_preinstall, register irq handler and
         * call irq_postinstall
         */
        ret = drm_irq_install(dev);
        if (ret)
-               goto out_fifo;
+               goto out_display;
 
        ret = drm_vblank_init(dev, 0);
        if (ret)
@@ -504,35 +568,18 @@ nouveau_card_init(struct drm_device *dev)
                        goto out_irq;
        }
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               if (dev_priv->card_type >= NV_50)
-                       ret = nv50_display_create(dev);
-               else
-                       ret = nv04_display_create(dev);
-               if (ret)
-                       goto out_channel;
-       }
-
        ret = nouveau_backlight_init(dev);
        if (ret)
                NV_ERROR(dev, "Error %d registering backlight\n", ret);
 
-       dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
-
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               nouveau_fbcon_init(dev);
-               drm_kms_helper_poll_init(dev);
-       }
-
+       nouveau_fbcon_init(dev);
+       drm_kms_helper_poll_init(dev);
        return 0;
 
-out_channel:
-       if (dev_priv->channel) {
-               nouveau_channel_free(dev_priv->channel);
-               dev_priv->channel = NULL;
-       }
 out_irq:
        drm_irq_uninstall(dev);
+out_display:
+       engine->display.destroy(dev);
 out_fifo:
        if (!nouveau_noaccel)
                engine->fifo.takedown(dev);
@@ -543,6 +590,8 @@ out_fb:
        engine->fb.takedown(dev);
 out_timer:
        engine->timer.takedown(dev);
+out_gpio:
+       engine->gpio.takedown(dev);
 out_mc:
        engine->mc.takedown(dev);
 out_gpuobj:
@@ -556,6 +605,8 @@ out_gpuobj_early:
        nouveau_gpuobj_late_takedown(dev);
 out_bios:
        nouveau_bios_takedown(dev);
+out_display_early:
+       engine->display.late_takedown(dev);
 out:
        vga_client_register(dev->pdev, NULL, NULL, NULL);
        return ret;
@@ -566,45 +617,39 @@ static void nouveau_card_takedown(struct drm_device *dev)
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_engine *engine = &dev_priv->engine;
 
-       NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
-
-       if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
-
-               nouveau_backlight_exit(dev);
-
-               if (dev_priv->channel) {
-                       nouveau_channel_free(dev_priv->channel);
-                       dev_priv->channel = NULL;
-               }
+       nouveau_backlight_exit(dev);
 
-               if (!nouveau_noaccel) {
-                       engine->fifo.takedown(dev);
-                       engine->graph.takedown(dev);
-               }
-               engine->fb.takedown(dev);
-               engine->timer.takedown(dev);
-               engine->mc.takedown(dev);
+       if (dev_priv->channel) {
+               nouveau_channel_free(dev_priv->channel);
+               dev_priv->channel = NULL;
+       }
 
-               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);
+       if (!nouveau_noaccel) {
+               engine->fifo.takedown(dev);
+               engine->graph.takedown(dev);
+       }
+       engine->fb.takedown(dev);
+       engine->timer.takedown(dev);
+       engine->gpio.takedown(dev);
+       engine->mc.takedown(dev);
+       engine->display.late_takedown(dev);
 
-               nouveau_gpuobj_takedown(dev);
-               nouveau_mem_close(dev);
-               engine->instmem.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);
 
-               if (drm_core_check_feature(dev, DRIVER_MODESET))
-                       drm_irq_uninstall(dev);
+       nouveau_gpuobj_takedown(dev);
+       nouveau_mem_close(dev);
+       engine->instmem.takedown(dev);
 
-               nouveau_gpuobj_late_takedown(dev);
-               nouveau_bios_takedown(dev);
+       drm_irq_uninstall(dev);
 
-               vga_client_register(dev->pdev, NULL, NULL, NULL);
+       nouveau_gpuobj_late_takedown(dev);
+       nouveau_bios_takedown(dev);
 
-               dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
-       }
+       vga_client_register(dev->pdev, NULL, NULL, NULL);
 }
 
 /* here a client dies, release the stuff that was allocated for its
@@ -691,6 +736,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        struct drm_nouveau_private *dev_priv;
        uint32_t reg0;
        resource_size_t mmio_start_offs;
+       int ret;
 
        dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
        if (!dev_priv)
@@ -699,7 +745,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        dev_priv->dev = dev;
 
        dev_priv->flags = flags & NOUVEAU_FLAGS;
-       dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
 
        NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
                 dev->pci_vendor, dev->pci_device, dev->pdev->class);
@@ -773,11 +818,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
                dev_priv->card_type, reg0);
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               int ret = nouveau_remove_conflicting_drivers(dev);
-               if (ret)
-                       return ret;
-       }
+       ret = nouveau_remove_conflicting_drivers(dev);
+       if (ret)
+               return ret;
 
        /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
        if (dev_priv->card_type >= NV_40) {
@@ -812,46 +855,26 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
                dev_priv->flags |= NV_NFORCE2;
 
        /* For kernel modesetting, init card now and bring up fbcon */
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               int ret = nouveau_card_init(dev);
-               if (ret)
-                       return ret;
-       }
+       ret = nouveau_card_init(dev);
+       if (ret)
+               return ret;
 
        return 0;
 }
 
-static void nouveau_close(struct drm_device *dev)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-       /* In the case of an error dev_priv may not be allocated yet */
-       if (dev_priv)
-               nouveau_card_takedown(dev);
-}
-
-/* KMS: we need mmio at load time, not when the first drm client opens. */
 void nouveau_lastclose(struct drm_device *dev)
 {
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return;
-
-       nouveau_close(dev);
 }
 
 int nouveau_unload(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->engine;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               drm_kms_helper_poll_fini(dev);
-               nouveau_fbcon_fini(dev);
-               if (dev_priv->card_type >= NV_50)
-                       nv50_display_destroy(dev);
-               else
-                       nv04_display_destroy(dev);
-               nouveau_close(dev);
-       }
+       drm_kms_helper_poll_fini(dev);
+       nouveau_fbcon_fini(dev);
+       engine->display.destroy(dev);
+       nouveau_card_takedown(dev);
 
        iounmap(dev_priv->mmio);
        iounmap(dev_priv->ramin);
@@ -867,8 +890,6 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct drm_nouveau_getparam *getparam = data;
 
-       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
        switch (getparam->param) {
        case NOUVEAU_GETPARAM_CHIPSET_ID:
                getparam->value = dev_priv->chipset;
@@ -937,8 +958,6 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data,
 {
        struct drm_nouveau_setparam *setparam = data;
 
-       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
        switch (setparam->param) {
        default:
                NV_ERROR(dev, "unknown parameter %lld\n", setparam->param);