drm/nouveau: Move display init to a new nouveau_engine.
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 24 Jul 2010 15:37:33 +0000 (17:37 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 26 Jul 2010 01:43:36 +0000 (11:43 +1000)
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_drv.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_display.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_display.h

index eeaf1f15a4289d57a60e992708daf0f7e56644ec..1de5eb53e0164be3cc81cf5a17f7969bc211e4ef 100644 (file)
@@ -263,6 +263,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
        if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
                nouveau_mem_reset_agp(dev);
 
+       /* Make the CRTCs accessible */
+       engine->display.early_init(dev);
+
        NV_INFO(dev, "POSTing device...\n");
        ret = nouveau_run_vbios_init(dev);
        if (ret)
@@ -325,10 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
                        NV_ERROR(dev, "Could not pin/map cursor.\n");
        }
 
-       if (dev_priv->card_type < NV_50)
-               nv04_display_restore(dev);
-       else
-               nv50_display_init(dev);
+       engine->display.init(dev);
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
index 8590032d36ade10abd281c71b2ce8abedbeed96b..0687e6ab91875652380bc447eb899c008e111db9 100644 (file)
@@ -351,6 +351,14 @@ struct nouveau_pgraph_engine {
                                  uint32_t size, uint32_t pitch);
 };
 
+struct nouveau_display_engine {
+       int (*early_init)(struct drm_device *);
+       void (*late_takedown)(struct drm_device *);
+       int (*create)(struct drm_device *);
+       int (*init)(struct drm_device *);
+       void (*destroy)(struct drm_device *);
+};
+
 struct nouveau_engine {
        struct nouveau_instmem_engine instmem;
        struct nouveau_mc_engine      mc;
@@ -358,6 +366,7 @@ struct nouveau_engine {
        struct nouveau_fb_engine      fb;
        struct nouveau_pgraph_engine  graph;
        struct nouveau_fifo_engine    fifo;
+       struct nouveau_display_engine display;
 };
 
 struct nouveau_pll_vals {
@@ -1081,9 +1090,11 @@ extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *);
 extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *);
 
 /* nv04_display.c */
+extern int nv04_display_early_init(struct drm_device *);
+extern void nv04_display_late_takedown(struct drm_device *);
 extern int nv04_display_create(struct drm_device *);
+extern int nv04_display_init(struct drm_device *);
 extern void nv04_display_destroy(struct drm_device *);
-extern void nv04_display_restore(struct drm_device *);
 
 /* nv04_crtc.c */
 extern int nv04_crtc_create(struct drm_device *, int index);
index 8d59c904b045388b578072a377fba7a7bd5c5b47..17176ad5b22aecc784858aa44e38b8799b2de704 100644 (file)
@@ -84,6 +84,11 @@ 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;
                break;
        case 0x10:
                engine->instmem.init            = nv04_instmem_init;
@@ -126,6 +131,11 @@ 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;
                break;
        case 0x20:
                engine->instmem.init            = nv04_instmem_init;
@@ -168,6 +178,11 @@ 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;
                break;
        case 0x30:
                engine->instmem.init            = nv04_instmem_init;
@@ -210,6 +225,11 @@ 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;
                break;
        case 0x40:
        case 0x60:
@@ -253,6 +273,11 @@ 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;
                break;
        case 0x50:
        case 0x80: /* gotta love NVIDIA's consistency.. */
@@ -297,6 +322,11 @@ 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;
                break;
        default:
                NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -415,10 +445,15 @@ nouveau_card_init(struct drm_device *dev)
        engine = &dev_priv->engine;
        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 */
        ret = nouveau_bios_init(dev);
        if (ret)
-               goto out;
+               goto out_display_early;
 
        ret = nouveau_mem_detect(dev);
        if (ret)
@@ -474,10 +509,7 @@ nouveau_card_init(struct drm_device *dev)
                        goto out_graph;
        }
 
-       if (dev_priv->card_type >= NV_50)
-               ret = nv50_display_create(dev);
-       else
-               ret = nv04_display_create(dev);
+       ret = engine->display.create(dev);
        if (ret)
                goto out_fifo;
 
@@ -511,10 +543,7 @@ nouveau_card_init(struct drm_device *dev)
 out_irq:
        drm_irq_uninstall(dev);
 out_display:
-       if (dev_priv->card_type >= NV_50)
-               nv50_display_destroy(dev);
-       else
-               nv04_display_destroy(dev);
+       engine->display.destroy(dev);
 out_fifo:
        if (!nouveau_noaccel)
                engine->fifo.takedown(dev);
@@ -538,6 +567,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;
@@ -562,6 +593,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
        engine->fb.takedown(dev);
        engine->timer.takedown(dev);
        engine->mc.takedown(dev);
+       engine->display.late_takedown(dev);
 
        mutex_lock(&dev->struct_mutex);
        ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
@@ -798,13 +830,11 @@ void nouveau_lastclose(struct drm_device *dev)
 int nouveau_unload(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_engine *engine = &dev_priv->engine;
 
        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);
+       engine->display.destroy(dev);
        nouveau_card_takedown(dev);
 
        iounmap(dev_priv->mmio);
index c6df391ebb2e58008a5037f2ad3976f3cc9ae192..cd70bd8276144507aac80142f12219ad746d3f96 100644 (file)
@@ -75,6 +75,32 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
        }
 }
 
+int
+nv04_display_early_init(struct drm_device *dev)
+{
+       /* Unlock the VGA CRTCs. */
+       NVLockVgaCrtcs(dev, false);
+
+       /* Make sure the CRTCs aren't in slaved mode. */
+       if (nv_two_heads(dev)) {
+               nv04_display_store_initial_head_owner(dev);
+               NVSetOwner(dev, 0);
+       }
+
+       return 0;
+}
+
+void
+nv04_display_late_takedown(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+       if (nv_two_heads(dev))
+               NVSetOwner(dev, dev_priv->crtc_owner);
+
+       NVLockVgaCrtcs(dev, true);
+}
+
 int
 nv04_display_create(struct drm_device *dev)
 {
@@ -87,13 +113,6 @@ nv04_display_create(struct drm_device *dev)
 
        NV_DEBUG_KMS(dev, "\n");
 
-       NVLockVgaCrtcs(dev, false);
-
-       if (nv_two_heads(dev)) {
-               nv04_display_store_initial_head_owner(dev);
-               NVSetOwner(dev, 0);
-       }
-
        nouveau_hw_save_vga_fonts(dev, 1);
 
        drm_mode_config_init(dev);
@@ -176,7 +195,6 @@ nv04_display_create(struct drm_device *dev)
 void
 nv04_display_destroy(struct drm_device *dev)
 {
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct drm_encoder *encoder;
        struct drm_crtc *crtc;
 
@@ -204,20 +222,14 @@ nv04_display_destroy(struct drm_device *dev)
        drm_mode_config_cleanup(dev);
 
        nouveau_hw_save_vga_fonts(dev, 0);
-
-       if (nv_two_heads(dev))
-               NVSetOwner(dev, dev_priv->crtc_owner);
-       NVLockVgaCrtcs(dev, true);
 }
 
-void
-nv04_display_restore(struct drm_device *dev)
+int
+nv04_display_init(struct drm_device *dev)
 {
        struct drm_encoder *encoder;
        struct drm_crtc *crtc;
 
-       NVLockVgaCrtcs(dev, false);
-
        /* meh.. modeset apparently doesn't setup all the regs and depends
         * on pre-existing state, for now load the state of the card *before*
         * nouveau was loaded, and then do a modeset.
@@ -234,5 +246,7 @@ nv04_display_restore(struct drm_device *dev)
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                crtc->funcs->restore(crtc);
+
+       return 0;
 }
 
index fbd91c251ee95ee8e645c1e7c9b325803f3dba33..13a448985637cb277f57f0d7b26dc75b5d8b018b 100644 (file)
@@ -177,6 +177,17 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)
        return 0;
 }
 
+int
+nv50_display_early_init(struct drm_device *dev)
+{
+       return 0;
+}
+
+void
+nv50_display_late_takedown(struct drm_device *dev)
+{
+}
+
 int
 nv50_display_init(struct drm_device *dev)
 {
@@ -528,7 +539,8 @@ int nv50_display_create(struct drm_device *dev)
        return 0;
 }
 
-int nv50_display_destroy(struct drm_device *dev)
+void
+nv50_display_destroy(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
@@ -538,8 +550,6 @@ int nv50_display_destroy(struct drm_device *dev)
 
        nv50_display_disable(dev);
        nv50_evo_channel_del(&dev_priv->evo);
-
-       return 0;
 }
 
 static u16
index 581d405ac014606041e253c7830c137569e63af6..c551f0b85ee02124bdf66b9e28fc0574f7e3caa8 100644 (file)
 void nv50_display_irq_handler(struct drm_device *dev);
 void nv50_display_irq_handler_bh(struct work_struct *work);
 void nv50_display_irq_hotplug_bh(struct work_struct *work);
-int nv50_display_init(struct drm_device *dev);
+int nv50_display_early_init(struct drm_device *dev);
+void nv50_display_late_takedown(struct drm_device *dev);
 int nv50_display_create(struct drm_device *dev);
-int nv50_display_destroy(struct drm_device *dev);
+int nv50_display_init(struct drm_device *dev);
+void nv50_display_destroy(struct drm_device *dev);
 int nv50_crtc_blank(struct nouveau_crtc *, bool blank);
 int nv50_crtc_set_clock(struct drm_device *, int head, int pclk);