diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_display.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.h | 6 |
6 files changed, 106 insertions, 39 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index eeaf1f1..1de5eb5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 8590032d..0687e6a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 8d59c90..17176ad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -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); diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index c6df391..cd70bd8 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -76,6 +76,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) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index fbd91c2..13a4489 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -178,6 +178,17 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) } 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) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -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 diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index 581d405..c551f0b 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -38,9 +38,11 @@ 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); |