diff options
Diffstat (limited to 'shared-core/i915_init.c')
-rw-r--r-- | shared-core/i915_init.c | 186 |
1 files changed, 90 insertions, 96 deletions
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index dc218688..7b88cc8d 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -100,92 +100,32 @@ int i915_probe_agp(struct pci_dev *pdev, unsigned long *aperture_size, return 0; } -static int i915_init_hwstatus(struct drm_device *dev) +static int +i915_init_hws_phys(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_memrange_node *free_space; int ret = 0; - /* Program Hardware Status Page */ - if (!IS_G33(dev)) { - dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, + 0xffffffff); - if (!dev_priv->status_page_dmah) { - DRM_ERROR("Can not allocate hardware status page\n"); - ret = -ENOMEM; - goto out; - } - dev_priv->hws_vaddr = dev_priv->status_page_dmah->vaddr; - dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; - - I915_WRITE(HWS_PGA, dev_priv->dma_status_page); - } else { - free_space = drm_memrange_search_free(&dev_priv->vram, - PAGE_SIZE, - PAGE_SIZE, 0); - if (!free_space) { - DRM_ERROR("No free vram available, aborting\n"); - ret = -ENOMEM; - goto out; - } - - dev_priv->hws = drm_memrange_get_block(free_space, PAGE_SIZE, - PAGE_SIZE); - if (!dev_priv->hws) { - DRM_ERROR("Unable to allocate or pin hw status page\n"); - ret = -EINVAL; - goto out; - } - - dev_priv->hws_agpoffset = dev_priv->hws->start; - dev_priv->hws_map.offset = dev->agp->base + - dev_priv->hws->start; - dev_priv->hws_map.size = PAGE_SIZE; - dev_priv->hws_map.type= 0; - dev_priv->hws_map.flags= 0; - dev_priv->hws_map.mtrr = 0; - - drm_core_ioremap(&dev_priv->hws_map, dev); - if (dev_priv->hws_map.handle == NULL) { - dev_priv->hws_agpoffset = 0; - DRM_ERROR("can not ioremap virtual addr for" - "G33 hw status page\n"); - ret = -ENOMEM; - goto out_free; - } - dev_priv->hws_vaddr = dev_priv->hws_map.handle; - I915_WRITE(HWS_PGA, dev_priv->hws_agpoffset); + if (!dev_priv->status_page_dmah) { + DRM_ERROR("Can not allocate hardware status page\n"); + ret = -ENOMEM; + goto out; } + dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; + dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; - memset(dev_priv->hws_vaddr, 0, PAGE_SIZE); + memset(dev_priv->hw_status_page, 0, PAGE_SIZE); - DRM_DEBUG("Enabled hardware status page\n"); + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); + DRM_DEBUG("hws kernel virt: 0x%p\n", dev_priv->hw_status_page); - return 0; - -out_free: - /* free hws */ out: return ret; } -static void i915_cleanup_hwstatus(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!IS_G33(dev)) { - if (dev_priv->status_page_dmah) - drm_pci_free(dev, dev_priv->status_page_dmah); - } else { - if (dev_priv->hws_map.handle) - drm_core_ioremapfree(&dev_priv->hws_map, dev); - if (dev_priv->hws) - drm_memrange_put_block(dev_priv->hws); - } - I915_WRITE(HWS_PGA, 0x1ffff000); -} - static int i915_load_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -195,18 +135,17 @@ static int i915_load_modeset_init(struct drm_device *dev) i915_probe_agp(dev->pdev, &agp_size, &prealloc_size); /* Basic memrange allocator for stolen space (aka vram) */ - drm_memrange_init(&dev_priv->vram, 0, prealloc_size); + drm_mm_init(&dev_priv->vram, 0, prealloc_size); /* Let GEM Manage from end of prealloc space to end of aperture */ i915_gem_do_init(dev, prealloc_size, agp_size); + if (!I915_NEED_GFX_HWS(dev)) + i915_init_hws_phys(dev); + ret = i915_gem_init_ringbuffer(dev); if (ret) goto out; - ret = i915_init_hwstatus(dev); - if (ret) - goto destroy_ringbuffer; - /* Allow hardware batchbuffers unless told otherwise. */ dev_priv->allow_batchbuffer = 1; @@ -217,7 +156,7 @@ static int i915_load_modeset_init(struct drm_device *dev) if (dev_priv->wq == 0) { DRM_DEBUG("Error\n"); ret = -EINVAL; - goto destroy_hws; + goto destroy_ringbuffer; } ret = intel_init_bios(dev); @@ -247,8 +186,6 @@ modeset_cleanup: intel_modeset_cleanup(dev); destroy_wq: destroy_workqueue(dev_priv->wq); -destroy_hws: - i915_cleanup_hwstatus(dev); destroy_ringbuffer: i915_gem_cleanup_ringbuffer(dev); out: @@ -269,7 +206,8 @@ out: int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv; - int ret = 0; + int ret = 0, num_pipes = 2; + u32 tmp; dev_priv = drm_alloc(sizeof(struct drm_i915_private), DRM_MEM_DRIVER); if (dev_priv == NULL) @@ -323,20 +261,55 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } - INIT_LIST_HEAD(&dev_priv->mm.active_list); - INIT_LIST_HEAD(&dev_priv->mm.flushing_list); - INIT_LIST_HEAD(&dev_priv->mm.inactive_list); - INIT_LIST_HEAD(&dev_priv->mm.request_list); - INIT_DELAYED_WORK(&dev_priv->mm.retire_work, - i915_gem_retire_work_handler); - dev_priv->mm.next_gem_seqno = 1; + i915_gem_load(dev); #ifdef __linux__ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) - intel_init_chipset_flush_compat(dev); + intel_init_chipset_flush_compat(dev); +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) + intel_opregion_init(dev); #endif #endif + tmp = I915_READ(PIPEASTAT); + I915_WRITE(PIPEASTAT, tmp); + tmp = I915_READ(PIPEBSTAT); + I915_WRITE(PIPEBSTAT, tmp); + + atomic_set(&dev_priv->irq_received, 0); + I915_WRITE(HWSTAM, 0xeffe); + I915_WRITE(IMR, 0x0); + I915_WRITE(IER, 0x0); + + DRM_SPININIT(&dev_priv->swaps_lock, "swap"); + INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); + dev_priv->swaps_pending = 0; + + DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); + dev_priv->user_irq_refcount = 0; + dev_priv->irq_mask_reg = ~0; + + ret = drm_vblank_init(dev, num_pipes); + if (ret) + goto out_rmmap; + + ret = drm_hotplug_init(dev); + if (ret) + goto out_rmmap; + + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ + + i915_enable_interrupt(dev); + DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); + + /* + * Initialize the hardware status page IRQ location. + */ + + I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); if (ret < 0) { @@ -344,6 +317,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_rmmap; } } + return 0; out_rmmap: @@ -357,6 +331,23 @@ int i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + u32 temp; + + dev_priv->vblank_pipe = 0; + + dev_priv->irq_enabled = 0; + + I915_WRITE(HWSTAM, 0xffffffff); + I915_WRITE(IMR, 0xffffffff); + I915_WRITE(IER, 0x0); + + temp = I915_READ(PIPEASTAT); + I915_WRITE(PIPEASTAT, temp); + temp = I915_READ(PIPEBSTAT); + I915_WRITE(PIPEBSTAT, temp); + temp = I915_READ(IIR); + I915_WRITE(IIR, temp); + I915_WRITE(PRB0_CTL, 0); if (drm_core_check_feature(dev, DRIVER_MODESET)) { @@ -385,25 +376,28 @@ int i915_driver_unload(struct drm_device *dev) dev_priv->sarea_bo = NULL; } #endif - i915_cleanup_hwstatus(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); - drm_memrange_takedown(&dev_priv->vram); + drm_mm_takedown(&dev_priv->vram); i915_gem_lastclose(dev); + if (!I915_NEED_GFX_HWS(dev)) + drm_pci_free(dev, dev_priv->status_page_dmah); } + drm_rmmap(dev, dev_priv->mmio_map); + #ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) + intel_opregion_free(dev); +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) - intel_init_chipset_flush_compat(dev); + intel_fini_chipset_flush_compat(dev); #endif #endif - DRM_DEBUG("%p\n", dev_priv->mmio_map); - drm_rmmap(dev, dev_priv->mmio_map); - drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); dev->dev_private = NULL; |