void nouveau_vga_fini(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); }
void nouveau_vga_init(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops); }
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; int e; if (dev->mode_config.num_crtc) { nouveau_fbcon_fini(dev); nouveau_display_fini(dev); } if (dev_priv->channel) { nouveau_channel_put_unlocked(&dev_priv->channel); nouveau_fence_fini(dev); } nouveau_backlight_exit(dev); nouveau_display_destroy(dev); if (!dev_priv->noaccel) { engine->fifo.takedown(dev); for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { if (dev_priv->eng[e]) { dev_priv->eng[e]->fini(dev, e, false); dev_priv->eng[e]->destroy(dev,e ); } } } engine->fb.takedown(dev); engine->timer.takedown(dev); nouveau_gpio_destroy(dev); engine->mc.takedown(dev); engine->display.late_takedown(dev); if (dev_priv->vga_ram) { nouveau_bo_unpin(dev_priv->vga_ram); nouveau_bo_ref(NULL, &dev_priv->vga_ram); } 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_mem_gart_fini(dev); nouveau_mem_vram_fini(dev); engine->instmem.takedown(dev); nouveau_gpuobj_takedown(dev); engine->vram.takedown(dev); nouveau_irq_fini(dev); nouveau_pm_fini(dev); nouveau_bios_takedown(dev); vga_client_register(dev->pdev, NULL, NULL, NULL); }
/** * drm_irq_install - install IRQ handler * @dev: DRM device * @irq: IRQ number to install the handler for * * Initializes the IRQ related data. Installs the handler, calling the driver * &drm_driver.irq_preinstall and &drm_driver.irq_postinstall functions before * and after the installation. * * This is the simplified helper interface provided for drivers with no special * needs. Drivers which need to install interrupt handlers for multiple * interrupts must instead set &drm_device.irq_enabled to signal the DRM core * that vblank interrupts are available. * * @irq must match the interrupt number that would be passed to request_irq(), * if called directly instead of using this helper function. * * &drm_driver.irq_handler is called to handle the registered interrupt. * * Returns: * Zero on success or a negative error code on failure. */ int drm_irq_install(struct drm_device *dev, int irq) { int ret; unsigned long sh_flags = 0; if (irq == 0) return -EINVAL; /* Driver must have been initialized */ if (!dev->dev_private) return -EINVAL; if (dev->irq_enabled) return -EBUSY; dev->irq_enabled = true; DRM_DEBUG("irq=%d\n", irq); /* Before installing handler */ if (dev->driver->irq_preinstall) dev->driver->irq_preinstall(dev); /* PCI devices require shared interrupts. */ if (dev->pdev) sh_flags = IRQF_SHARED; ret = request_irq(irq, dev->driver->irq_handler, sh_flags, dev->driver->name, dev); if (ret < 0) { dev->irq_enabled = false; return ret; } /* After installing handler */ if (dev->driver->irq_postinstall) ret = dev->driver->irq_postinstall(dev); if (ret < 0) { dev->irq_enabled = false; if (drm_core_check_feature(dev, DRIVER_LEGACY)) vga_client_register(dev->pdev, NULL, NULL, NULL); free_irq(irq, dev); } else { dev->irq = irq; } return ret; }
void nouveau_vga_init(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; bool runtime = false; vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); if (nouveau_runtime_pm == 1) runtime = true; if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) runtime = true; vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime); if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) vga_switcheroo_init_domain_pm_ops(drm->dev->dev, &drm->vga_pm_domain); }
void nouveau_vga_fini(struct nouveau_drm *drm) { struct drm_device *dev = drm->dev; bool runtime = false; if (nouveau_runtime_pm == 1) runtime = true; if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) runtime = true; vga_switcheroo_unregister_client(dev->pdev); if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); vga_client_register(dev->pdev, NULL, NULL, NULL); }
/** * drm_irq_uninstall - uninstall the IRQ handler * @dev: DRM device * * Calls the driver's &drm_driver.irq_uninstall function and unregisters the IRQ * handler. This should only be called by drivers which used drm_irq_install() * to set up their interrupt handler. Other drivers must only reset * &drm_device.irq_enabled to false. * * Note that for kernel modesetting drivers it is a bug if this function fails. * The sanity checks are only to catch buggy user modesetting drivers which call * the same function through an ioctl. * * Returns: * Zero on success or a negative error code on failure. */ int drm_irq_uninstall(struct drm_device *dev) { unsigned long irqflags; bool irq_enabled; int i; irq_enabled = dev->irq_enabled; dev->irq_enabled = false; /* * Wake up any waiters so they don't hang. This is just to paper over * issues for UMS drivers which aren't in full control of their * vblank/irq handling. KMS drivers must ensure that vblanks are all * disabled when uninstalling the irq handler. */ if (dev->num_crtcs) { spin_lock_irqsave(&dev->vbl_lock, irqflags); for (i = 0; i < dev->num_crtcs; i++) { struct drm_vblank_crtc *vblank = &dev->vblank[i]; if (!vblank->enabled) continue; WARN_ON(drm_core_check_feature(dev, DRIVER_MODESET)); drm_vblank_disable_and_save(dev, i); wake_up(&vblank->queue); } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } if (!irq_enabled) return -EINVAL; DRM_DEBUG("irq=%d\n", dev->irq); if (drm_core_check_feature(dev, DRIVER_LEGACY)) vga_client_register(dev->pdev, NULL, NULL, NULL); if (dev->driver->irq_uninstall) dev->driver->irq_uninstall(dev); free_irq(dev->irq, dev); return 0; }
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; } if (!nouveau_noaccel) { engine->fifo.takedown(dev); engine->graph.takedown(dev); } engine->fb.takedown(dev); engine->timer.takedown(dev); engine->mc.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); nouveau_gpuobj_takedown(dev); nouveau_mem_close(dev); engine->instmem.takedown(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_irq_uninstall(dev); nouveau_gpuobj_late_takedown(dev); nouveau_bios_takedown(dev); vga_client_register(dev->pdev, NULL, NULL, NULL); dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; } }
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; if (!engine->graph.accel_blocked) { nouveau_fence_fini(dev); nouveau_channel_put_unlocked(&dev_priv->channel); } if (!nouveau_noaccel) { engine->fifo.takedown(dev); engine->crypt.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); if (dev_priv->vga_ram) { nouveau_bo_unpin(dev_priv->vga_ram); nouveau_bo_ref(NULL, &dev_priv->vga_ram); } 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_mem_gart_fini(dev); engine->instmem.takedown(dev); nouveau_gpuobj_takedown(dev); nouveau_mem_vram_fini(dev); nouveau_irq_fini(dev); drm_vblank_cleanup(dev); nouveau_pm_fini(dev); nouveau_bios_takedown(dev); vga_client_register(dev->pdev, NULL, NULL, NULL); }
int nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; int ret; vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, nouveau_switcheroo_reprobe, nouveau_switcheroo_can_switch); /* Initialise internal driver API hooks */ ret = nouveau_init_engine_ptrs(dev); if (ret) goto out; engine = &dev_priv->engine; spin_lock_init(&dev_priv->channels.lock); spin_lock_init(&dev_priv->tile.lock); spin_lock_init(&dev_priv->context_switch_lock); spin_lock_init(&dev_priv->vm_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_display_early; nouveau_pm_init(dev); ret = nouveau_mem_vram_init(dev); if (ret) goto out_bios; ret = nouveau_gpuobj_init(dev); if (ret) goto out_vram; ret = engine->instmem.init(dev); if (ret) goto out_gpuobj; ret = nouveau_mem_gart_init(dev); if (ret) goto out_instmem; /* PMC */ ret = engine->mc.init(dev); if (ret) goto out_gart; /* PGPIO */ ret = engine->gpio.init(dev); if (ret) goto out_mc; /* PTIMER */ ret = engine->timer.init(dev); if (ret) goto out_gpio; /* PFB */ ret = engine->fb.init(dev); if (ret) goto out_timer; if (nouveau_noaccel) engine->graph.accel_blocked = true; else { /* PGRAPH */ ret = engine->graph.init(dev); if (ret) goto out_fb; /* PCRYPT */ ret = engine->crypt.init(dev); if (ret) goto out_graph; /* PFIFO */ ret = engine->fifo.init(dev); if (ret) goto out_crypt; } ret = engine->display.create(dev); if (ret) goto out_fifo; ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); if (ret) goto out_vblank; ret = nouveau_irq_init(dev); if (ret) goto out_vblank; /* what about PVIDEO/PCRTC/PRAMDAC etc? */ if (!engine->graph.accel_blocked) { ret = nouveau_fence_init(dev); if (ret) goto out_irq; ret = nouveau_card_init_channel(dev); if (ret) goto out_fence; } nouveau_fbcon_init(dev); drm_kms_helper_poll_init(dev); return 0; out_fence: nouveau_fence_fini(dev); out_irq: nouveau_irq_fini(dev); out_vblank: drm_vblank_cleanup(dev); engine->display.destroy(dev); out_fifo: if (!nouveau_noaccel) engine->fifo.takedown(dev); out_crypt: if (!nouveau_noaccel) engine->crypt.takedown(dev); out_graph: if (!nouveau_noaccel) engine->graph.takedown(dev); 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_gart: nouveau_mem_gart_fini(dev); out_instmem: engine->instmem.takedown(dev); out_gpuobj: nouveau_gpuobj_takedown(dev); out_vram: nouveau_mem_vram_fini(dev); out_bios: nouveau_pm_fini(dev); nouveau_bios_takedown(dev); out_display_early: engine->display.late_takedown(dev); out: vga_client_register(dev->pdev, NULL, NULL, NULL); return ret; }
int nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; int ret, e = 0; vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, nouveau_switcheroo_reprobe, nouveau_switcheroo_can_switch); /* Initialise internal driver API hooks */ ret = nouveau_init_engine_ptrs(dev); if (ret) goto out; engine = &dev_priv->engine; spin_lock_init(&dev_priv->channels.lock); spin_lock_init(&dev_priv->tile.lock); spin_lock_init(&dev_priv->context_switch_lock); spin_lock_init(&dev_priv->vm_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_display_early; /* workaround an odd issue on nvc1 by disabling the device's * nosnoop capability. hopefully won't cause issues until a * better fix is found - assuming there is one... */ if (dev_priv->chipset == 0xc1) { nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); } /* PMC */ ret = engine->mc.init(dev); if (ret) goto out_bios; /* PTIMER */ ret = engine->timer.init(dev); if (ret) goto out_mc; /* PFB */ ret = engine->fb.init(dev); if (ret) goto out_timer; ret = engine->vram.init(dev); if (ret) goto out_fb; /* PGPIO */ ret = nouveau_gpio_create(dev); if (ret) goto out_vram; ret = nouveau_gpuobj_init(dev); if (ret) goto out_gpio; ret = engine->instmem.init(dev); if (ret) goto out_gpuobj; ret = nouveau_mem_vram_init(dev); if (ret) goto out_instmem; ret = nouveau_mem_gart_init(dev); if (ret) goto out_ttmvram; if (!dev_priv->noaccel) { switch (dev_priv->card_type) { case NV_04: nv04_graph_create(dev); break; case NV_10: nv10_graph_create(dev); break; case NV_20: case NV_30: nv20_graph_create(dev); break; case NV_40: nv40_graph_create(dev); break; case NV_50: nv50_graph_create(dev); break; case NV_C0: case NV_D0: nvc0_graph_create(dev); break; default: break; } switch (dev_priv->chipset) { case 0x84: case 0x86: case 0x92: case 0x94: case 0x96: case 0xa0: nv84_crypt_create(dev); break; case 0x98: case 0xaa: case 0xac: nv98_crypt_create(dev); break; } switch (dev_priv->card_type) { case NV_50: switch (dev_priv->chipset) { case 0xa3: case 0xa5: case 0xa8: case 0xaf: nva3_copy_create(dev); break; } break; case NV_C0: nvc0_copy_create(dev, 0); nvc0_copy_create(dev, 1); break; default: break; } if (dev_priv->chipset >= 0xa3 || dev_priv->chipset == 0x98) { nv84_bsp_create(dev); nv84_vp_create(dev); nv98_ppp_create(dev); } else if (dev_priv->chipset >= 0x84) { nv50_mpeg_create(dev); nv84_bsp_create(dev); nv84_vp_create(dev); } else if (dev_priv->chipset >= 0x50) { nv50_mpeg_create(dev); } else if (dev_priv->card_type == NV_40 || dev_priv->chipset == 0x31 || dev_priv->chipset == 0x34 || dev_priv->chipset == 0x36) { nv31_mpeg_create(dev); } for (e = 0; e < NVOBJ_ENGINE_NR; e++) { if (dev_priv->eng[e]) { ret = dev_priv->eng[e]->init(dev, e); if (ret) goto out_engine; } } /* PFIFO */ ret = engine->fifo.init(dev); if (ret) goto out_engine; } ret = nouveau_irq_init(dev); if (ret) goto out_fifo; ret = nouveau_display_create(dev); if (ret) goto out_irq; nouveau_backlight_init(dev); nouveau_pm_init(dev); ret = nouveau_fence_init(dev); if (ret) goto out_pm; if (dev_priv->eng[NVOBJ_ENGINE_GR]) { ret = nouveau_card_channel_init(dev); if (ret) goto out_fence; } if (dev->mode_config.num_crtc) { ret = nouveau_display_init(dev); if (ret) goto out_chan; nouveau_fbcon_init(dev); } return 0; out_chan: nouveau_card_channel_fini(dev); out_fence: nouveau_fence_fini(dev); out_pm: nouveau_pm_fini(dev); nouveau_backlight_exit(dev); nouveau_display_destroy(dev); out_irq: nouveau_irq_fini(dev); out_fifo: if (!dev_priv->noaccel) engine->fifo.takedown(dev); out_engine: if (!dev_priv->noaccel) { for (e = e - 1; e >= 0; e--) { if (!dev_priv->eng[e]) continue; dev_priv->eng[e]->fini(dev, e, false); dev_priv->eng[e]->destroy(dev,e ); } } nouveau_mem_gart_fini(dev); out_ttmvram: nouveau_mem_vram_fini(dev); out_instmem: engine->instmem.takedown(dev); out_gpuobj: nouveau_gpuobj_takedown(dev); out_gpio: nouveau_gpio_destroy(dev); out_vram: engine->vram.takedown(dev); out_fb: engine->fb.takedown(dev); out_timer: engine->timer.takedown(dev); out_mc: engine->mc.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; }
int i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; ret = i915_gem_suspend(dev); if (ret) { DRM_ERROR("failed to idle hardware: %d\n", ret); return ret; } intel_power_domains_fini(dev_priv); intel_gpu_ips_teardown(); i915_teardown_sysfs(dev); WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier)); unregister_shrinker(&dev_priv->mm.shrinker); io_mapping_free(dev_priv->gtt.mappable); arch_phys_wc_del(dev_priv->gtt.mtrr); acpi_video_unregister(); if (drm_core_check_feature(dev, DRIVER_MODESET)) intel_fbdev_fini(dev); drm_vblank_cleanup(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_modeset_cleanup(dev); /* * free the memory space allocated for the child device * config parsed from VBT */ if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) { kfree(dev_priv->vbt.child_dev); dev_priv->vbt.child_dev = NULL; dev_priv->vbt.child_dev_num = 0; } vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); } /* Free error state after interrupts are fully disabled. */ del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); cancel_work_sync(&dev_priv->gpu_error.work); i915_destroy_error_state(dev); if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); intel_opregion_fini(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { /* Flush any outstanding unpin_work. */ flush_workqueue(dev_priv->wq); mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_stolen(dev); } intel_teardown_gmbus(dev); intel_teardown_mchbar(dev); destroy_workqueue(dev_priv->dp_wq); destroy_workqueue(dev_priv->wq); pm_qos_remove_request(&dev_priv->pm_qos); i915_global_gtt_cleanup(dev); intel_uncore_fini(dev); if (dev_priv->regs != NULL) pci_iounmap(dev->pdev, dev_priv->regs); if (dev_priv->slab) kmem_cache_destroy(dev_priv->slab); pci_dev_put(dev_priv->bridge_dev); kfree(dev_priv); return 0; }
static int i915_load_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; ret = intel_parse_bios(dev); if (ret) DRM_INFO("failed to find VBIOS tables\n"); /* If we have > 1 VGA cards, then we need to arbitrate access * to the common VGA resources. * * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA), * then we do not take part in VGA arbitration and the * vga_client_register() fails with -ENODEV. */ ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); if (ret && ret != -ENODEV) goto out; intel_register_dsm_handler(); ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false); if (ret) goto cleanup_vga_client; /* Initialise stolen first so that we may reserve preallocated * objects for the BIOS to KMS transition. */ ret = i915_gem_init_stolen(dev); if (ret) goto cleanup_vga_switcheroo; intel_power_domains_init_hw(dev_priv); ret = intel_irq_install(dev_priv); if (ret) goto cleanup_gem_stolen; /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ intel_modeset_init(dev); ret = i915_gem_init(dev); if (ret) goto cleanup_irq; intel_modeset_gem_init(dev); /* Always safe in the mode setting case. */ /* FIXME: do pre/post-mode set stuff in core KMS code */ dev->vblank_disable_allowed = true; if (INTEL_INFO(dev)->num_pipes == 0) return 0; ret = intel_fbdev_init(dev); if (ret) goto cleanup_gem; /* Only enable hotplug handling once the fbdev is fully set up. */ intel_hpd_init(dev_priv); /* * Some ports require correctly set-up hpd registers for detection to * work properly (leading to ghost connected connector status), e.g. VGA * on gm45. Hence we can only set up the initial fbdev config after hpd * irqs are fully enabled. Now we should scan for the initial config * only once hotplug handling is enabled, but due to screwed-up locking * around kms/fbdev init we can't protect the fdbev initial config * scanning against hotplug events. Hence do this first and ignore the * tiny window where we will loose hotplug notifactions. */ async_schedule(intel_fbdev_initial_config, dev_priv); drm_kms_helper_poll_init(dev); return 0; cleanup_gem: mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: drm_irq_uninstall(dev); cleanup_gem_stolen: i915_gem_cleanup_stolen(dev); cleanup_vga_switcheroo: vga_switcheroo_unregister_client(dev->pdev); cleanup_vga_client: vga_client_register(dev->pdev, NULL, NULL, NULL); out: return ret; }
int nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; 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); /* Initialise internal driver API hooks */ ret = nouveau_init_engine_ptrs(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); /* 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_mem_detect(dev); if (ret) goto out_bios; ret = nouveau_gpuobj_early_init(dev); if (ret) goto out_bios; /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" * purposes. */ ret = engine->instmem.init(dev); if (ret) goto out_gpuobj_early; /* Setup the memory manager */ ret = nouveau_mem_init(dev); if (ret) goto out_instmem; ret = nouveau_gpuobj_init(dev); if (ret) goto out_mem; /* PMC */ ret = engine->mc.init(dev); if (ret) goto out_gpuobj; /* PTIMER */ ret = engine->timer.init(dev); if (ret) goto out_mc; /* PFB */ ret = engine->fb.init(dev); if (ret) goto out_timer; if (nouveau_noaccel) engine->graph.accel_blocked = true; else { /* PGRAPH */ ret = engine->graph.init(dev); if (ret) goto out_fb; /* PFIFO */ ret = engine->fifo.init(dev); if (ret) goto out_graph; } /* this call irq_preinstall, register irq handler and * call irq_postinstall */ ret = drm_irq_install(dev); if (ret) goto out_fifo; ret = drm_vblank_init(dev, 0); if (ret) goto out_irq; /* what about PVIDEO/PCRTC/PRAMDAC etc? */ if (!engine->graph.accel_blocked) { ret = nouveau_card_init_channel(dev); if (ret) 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); } 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_fifo: if (!nouveau_noaccel) engine->fifo.takedown(dev); out_graph: if (!nouveau_noaccel) engine->graph.takedown(dev); out_fb: engine->fb.takedown(dev); out_timer: engine->timer.takedown(dev); out_mc: engine->mc.takedown(dev); out_gpuobj: nouveau_gpuobj_takedown(dev); out_mem: nouveau_sgdma_takedown(dev); nouveau_mem_close(dev); out_instmem: engine->instmem.takedown(dev); out_gpuobj_early: nouveau_gpuobj_late_takedown(dev); out_bios: nouveau_bios_takedown(dev); out: vga_client_register(dev->pdev, NULL, NULL, NULL); return ret; }