diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index d6d6be4..4a22df6 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -72,38 +72,33 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, } /** - * Install IRQ handler. + * drm_irq_install - ioctl to set up IRQ + * @dev: DRM device * - * \param dev DRM device. - * \param irq IRQ number. + * Back in the bad old days, userspace drivers would tell the DRM when + * to call request_irq(). This is a bad idea on several levels, so now + * we just stub out the old ioctl and let the kernel driver set things + * up at load time. + */ +int drm_irq_install(struct drm_device * dev) +{ + return 0; +} + +/** + * drm_irq_init - setup core DRM irq structures + * @dev: DRM device * - * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver - * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions - * before and after the installation. + * Drivers that support IRQs should call this at load time to initialize + * the core DRM IRQ handling structures and register their IRQ with the + * kernel. */ -static int drm_irq_install(struct drm_device * dev) +int drm_irq_init(struct drm_device *dev) { - int ret; unsigned long sh_flags = 0; - - if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) - return -EINVAL; - - if (dev->pdev->irq == 0) - return -EINVAL; + int ret; mutex_lock(&dev->struct_mutex); - - /* Driver must have been initialized */ - if (!dev->dev_private) { - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - if (dev->irq_enabled) { - mutex_unlock(&dev->struct_mutex); - return -EBUSY; - } dev->irq_enabled = 1; mutex_unlock(&dev->struct_mutex); @@ -120,9 +115,6 @@ static int drm_irq_install(struct drm_device * dev) dev->vbl_pending = 0; } - /* Before installing handler */ - dev->driver->irq_preinstall(dev); - /* Install handler */ if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED)) sh_flags = IRQF_SHARED; @@ -139,46 +131,46 @@ static int drm_irq_install(struct drm_device * dev) return ret; } - /* After installing handler */ - dev->driver->irq_postinstall(dev); - return 0; } +EXPORT_SYMBOL(drm_irq_init); /** - * Uninstall the IRQ handler. + * drm_irq_uninstall - ioctl to free IRQ + * @dev: DRM device * - * \param dev DRM device. - * - * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq. + * See description for drm_irq_install()--we don't actually let userspace + * control the IRQ anymore. */ int drm_irq_uninstall(struct drm_device * dev) { - int irq_enabled; + return 0; +} - if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) +/** + * drm_irq_teardown - clean up core DRM IRQ handling + * @dev: DRM device + * + * Clean up and free IRQ. Call should be symmetric with drm_irq_init(). + */ +int drm_irq_teardown(struct drm_device *dev) +{ + if (!dev->irq_enabled) return -EINVAL; mutex_lock(&dev->struct_mutex); - irq_enabled = dev->irq_enabled; dev->irq_enabled = 0; mutex_unlock(&dev->struct_mutex); - if (!irq_enabled) - return -EINVAL; - DRM_DEBUG("irq=%d\n", dev->pdev->irq); - dev->driver->irq_uninstall(dev); - free_irq(dev->pdev->irq, dev); dev->locked_tasklet_func = NULL; return 0; } - -EXPORT_SYMBOL(drm_irq_uninstall); +EXPORT_SYMBOL(drm_irq_teardown); /** * IRQ control ioctl. diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index cead62f..477171e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -814,12 +814,54 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->user_irq_lock); + /* Disable IRQs before setting them up */ + I915_WRITE(HWSTAM, 0xfffe); + I915_WRITE(IER, 0x0); + I915_WRITE(IMR, 0x0); + + drm_irq_init(dev); + + spin_lock_init(&dev_priv->swaps_lock); + INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); + dev_priv->swaps_pending = 0; + + if (!dev_priv->vblank_pipe) + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; + + /* Set initial unmasked IRQs to just the selected vblank pipes. */ + dev_priv->irq_mask_reg = ~0; + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) + dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) + dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; + + dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK; + + I915_WRITE(IMR, dev_priv->irq_mask_reg); + I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); + (void) I915_READ(IER); + + opregion_enable_asle(dev); + + DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); + return ret; } int i915_driver_unload(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long temp; + + /* Clear & disable IRQs */ + I915_WRITE(HWSTAM, 0xffff); + I915_WRITE(IMR, 0xffff); + I915_WRITE(IER, 0x0); + + temp = I915_READ(IIR); + I915_WRITE(IIR, temp); + + drm_irq_teardown(dev); if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d95eca2..b8546d2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -556,9 +556,6 @@ static struct drm_driver driver = { .device_is_agp = i915_driver_device_is_agp, .vblank_wait = i915_driver_vblank_wait, .vblank_wait2 = i915_driver_vblank_wait2, - .irq_preinstall = i915_driver_irq_preinstall, - .irq_postinstall = i915_driver_irq_postinstall, - .irq_uninstall = i915_driver_irq_uninstall, .irq_handler = i915_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, .get_map_ofs = drm_core_get_map_ofs, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e4bd01c..f107195 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -275,6 +275,13 @@ extern void intel_opregion_free(struct drm_device *dev); extern void opregion_asle_intr(struct drm_device *dev); extern void opregion_enable_asle(struct drm_device *dev); +/** These are the interrupts used by the driver */ +#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ + I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \ + I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \ + I915_ASLE_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) + #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg)) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ae7d3a8..fbb13a8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -33,13 +33,6 @@ #define MAX_NOPID ((u32)~0) -/** These are the interrupts used by the driver */ -#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ - I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \ - I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \ - I915_ASLE_INTERRUPT | \ - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) - void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) { @@ -637,58 +630,3 @@ int i915_vblank_swap(struct drm_device *dev, void *data, return 0; } -/* drm_dma.h hooks -*/ -void i915_driver_irq_preinstall(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - - I915_WRITE(HWSTAM, 0xfffe); - I915_WRITE(IMR, 0x0); - I915_WRITE(IER, 0x0); -} - -void i915_driver_irq_postinstall(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - - spin_lock_init(&dev_priv->swaps_lock); - INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); - dev_priv->swaps_pending = 0; - - if (!dev_priv->vblank_pipe) - dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; - - /* Set initial unmasked IRQs to just the selected vblank pipes. */ - dev_priv->irq_mask_reg = ~0; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) - dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; - if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) - dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; - - dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK; - - I915_WRITE(IMR, dev_priv->irq_mask_reg); - I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); - (void) I915_READ(IER); - - opregion_enable_asle(dev); - - DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); -} - -void i915_driver_irq_uninstall(struct drm_device * dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 temp; - - if (!dev_priv) - return; - - I915_WRITE(HWSTAM, 0xffff); - I915_WRITE(IMR, 0xffff); - I915_WRITE(IER, 0x0); - - temp = I915_READ(IIR); - I915_WRITE(IIR, temp); -} diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index c1d12db..0e1cb97 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf) int mga_driver_load(struct drm_device * dev, unsigned long flags) { drm_mga_private_t *dev_priv; + int ret = 0; dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if (!dev_priv) @@ -410,11 +411,31 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags) dev_priv->mmio_base = drm_get_resource_start(dev, 1); dev_priv->mmio_size = drm_get_resource_len(dev, 1); + ret = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size, + _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, + &dev_priv->mmio); + if (ret) { + DRM_ERROR("failed to map registers: %d\n", ret); + return ret; + } + dev->counters += 3; dev->types[6] = _DRM_STAT_IRQ; dev->types[7] = _DRM_STAT_PRIMARY; dev->types[8] = _DRM_STAT_SECONDARY; + /* Disable *all* interrupts */ + MGA_WRITE(MGA_IEN, 0); + /* Clear bits if they're already high */ + MGA_WRITE(MGA_ICLEAR, ~0); + + drm_irq_init(dev); + + DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); + + /* Turn on vertical blank interrupt and soft trap interrupt. */ + MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); + return 0; } @@ -1141,6 +1162,15 @@ int mga_dma_buffers(struct drm_device *dev, void *data, */ int mga_driver_unload(struct drm_device * dev) { + drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; + + /* Disable *all* interrupts */ + MGA_WRITE(MGA_IEN, 0); + + drm_rmmap(dev, dev_priv->mmio); + + drm_irq_teardown(dev); + drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER); dev->dev_private = NULL; diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 5572939..6aa8673 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -54,9 +54,6 @@ static struct drm_driver driver = { .dma_quiescent = mga_driver_dma_quiescent, .device_is_agp = mga_driver_device_is_agp, .vblank_wait = mga_driver_vblank_wait, - .irq_preinstall = mga_driver_irq_preinstall, - .irq_postinstall = mga_driver_irq_postinstall, - .irq_uninstall = mga_driver_irq_uninstall, .irq_handler = mga_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, .get_map_ofs = drm_core_get_map_ofs, diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c index 9302cb8..f643dc0 100644 --- a/drivers/gpu/drm/mga/mga_irq.c +++ b/drivers/gpu/drm/mga/mga_irq.c @@ -114,35 +114,3 @@ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence) return ret; } - -void mga_driver_irq_preinstall(struct drm_device * dev) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - - /* Disable *all* interrupts */ - MGA_WRITE(MGA_IEN, 0); - /* Clear bits if they're already high */ - MGA_WRITE(MGA_ICLEAR, ~0); -} - -void mga_driver_irq_postinstall(struct drm_device * dev) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - - DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); - - /* Turn on vertical blank interrupt and soft trap interrupt. */ - MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); -} - -void mga_driver_irq_uninstall(struct drm_device * dev) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - if (!dev_priv) - return; - - /* Disable *all* interrupts */ - MGA_WRITE(MGA_IEN, 0); - - dev->irq_enabled = 0; -} diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c index c31afbd..a5d8584 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c @@ -349,21 +349,14 @@ static void r128_cce_init_ring_buffer(struct drm_device * dev, static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) { - drm_r128_private_t *dev_priv; + drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); - if (dev_priv == NULL) - return -ENOMEM; - - memset(dev_priv, 0, sizeof(drm_r128_private_t)); - dev_priv->is_pci = init->is_pci; if (dev_priv->is_pci && !dev->sg) { DRM_ERROR("PCI GART memory not allocated!\n"); - dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); return -EINVAL; } @@ -587,42 +580,6 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) int r128_do_cleanup_cce(struct drm_device * dev) { - - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (dev->irq_enabled) - drm_irq_uninstall(dev); - - if (dev->dev_private) { - drm_r128_private_t *dev_priv = dev->dev_private; - -#if __OS_HAS_AGP - if (!dev_priv->is_pci) { - if (dev_priv->cce_ring != NULL) - drm_core_ioremapfree(dev_priv->cce_ring, dev); - if (dev_priv->ring_rptr != NULL) - drm_core_ioremapfree(dev_priv->ring_rptr, dev); - if (dev->agp_buffer_map != NULL) { - drm_core_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; - } - } else -#endif - { - if (dev_priv->gart_info.bus_addr) - if (!drm_ati_pcigart_cleanup(dev, - &dev_priv->gart_info)) - DRM_ERROR - ("failed to cleanup PCI GART!\n"); - } - - drm_free(dev->dev_private, sizeof(drm_r128_private_t), - DRM_MEM_DRIVER); - dev->dev_private = NULL; - } - return 0; } @@ -644,6 +601,76 @@ int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv return -EINVAL; } +int r128_driver_load(struct drm_device *dev, unsigned long flags) +{ + drm_r128_private_t *dev_priv; + int ret = 0; + + dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) + return -ENOMEM; + + memset(dev_priv, 0, sizeof(drm_r128_private_t)); + + dev->dev_private = (void *)dev_priv; + + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), + drm_get_resource_len(dev, 2), _DRM_REGISTERS, + _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio); + if (ret != 0) + return ret; + + /* Disable *all* interrupts */ + R128_WRITE(R128_GEN_INT_CNTL, 0); + /* Clear vblank bit if it's already high */ + R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); + + R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); + + return ret; +} + +int r128_driver_unload(struct drm_device *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + /* Make sure interrupts are disabled here because the uninstall ioctl + * may not have been called from userspace and after dev_private + * is freed, it's too late. + */ + /* Disable *all* interrupts */ + R128_WRITE(R128_GEN_INT_CNTL, 0); + + drm_irq_teardown(dev); + + drm_rmmap(dev, dev_priv->mmio); + +#if __OS_HAS_AGP + if (!dev_priv->is_pci) { + if (dev_priv->cce_ring != NULL) + drm_core_ioremapfree(dev_priv->cce_ring, dev); + if (dev_priv->ring_rptr != NULL) + drm_core_ioremapfree(dev_priv->ring_rptr, dev); + if (dev->agp_buffer_map != NULL) { + drm_core_ioremapfree(dev->agp_buffer_map, dev); + dev->agp_buffer_map = NULL; + } + } else +#endif + { + if (dev_priv->gart_info.bus_addr) + if (!drm_ati_pcigart_cleanup(dev, + &dev_priv->gart_info)) + DRM_ERROR + ("failed to cleanup PCI GART!\n"); + } + + drm_free(dev->dev_private, sizeof(drm_r128_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + + return 0; +} + int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_r128_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 6108e75..9699f25 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -40,18 +40,20 @@ static struct pci_device_id pciidlist[] = { r128_PCI_IDS }; +extern int r128_driver_load(struct drm_device *dev, unsigned long flags); +extern int r128_driver_unload(struct drm_device *dev); + static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, + .load = r128_driver_load, + .unload = r128_driver_unload, .dev_priv_size = sizeof(drm_r128_buf_priv_t), .preclose = r128_driver_preclose, .lastclose = r128_driver_lastclose, .vblank_wait = r128_driver_vblank_wait, - .irq_preinstall = r128_driver_irq_preinstall, - .irq_postinstall = r128_driver_irq_postinstall, - .irq_uninstall = r128_driver_irq_uninstall, .irq_handler = r128_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, .get_map_ofs = drm_core_get_map_ofs, diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c index c76fdca..027d4b1 100644 --- a/drivers/gpu/drm/r128/r128_irq.c +++ b/drivers/gpu/drm/r128/r128_irq.c @@ -71,31 +71,3 @@ int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) return ret; } - -void r128_driver_irq_preinstall(struct drm_device * dev) -{ - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - - /* Disable *all* interrupts */ - R128_WRITE(R128_GEN_INT_CNTL, 0); - /* Clear vblank bit if it's already high */ - R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); -} - -void r128_driver_irq_postinstall(struct drm_device * dev) -{ - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - - /* Turn on VBL interrupt */ - R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); -} - -void r128_driver_irq_uninstall(struct drm_device * dev) -{ - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - if (!dev_priv) - return; - - /* Disable *all* interrupts */ - R128_WRITE(R128_GEN_INT_CNTL, 0); -} diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 3331f88..96d3265 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -1727,6 +1727,29 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) else dev_priv->flags |= RADEON_IS_PCI; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), + drm_get_resource_len(dev, 2), _DRM_REGISTERS, + _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio); + if (ret != 0) + return ret; + + /* Disable *all* interrupts */ + RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); + + /* Clear bits if they're already high */ + radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | + RADEON_CRTC_VBLANK_STAT | + RADEON_CRTC2_VBLANK_STAT)); + + drm_irq_init(dev); + + atomic_set(&dev_priv->swi_emitted, 0); + DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); + + radeon_enable_interrupt(dev); + DRM_DEBUG("%s card detected\n", ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); return ret; @@ -1741,18 +1764,11 @@ int radeon_driver_firstopen(struct drm_device *dev) drm_local_map_t *map; drm_radeon_private_t *dev_priv = dev->dev_private; - dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - - ret = drm_addmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), _DRM_REGISTERS, - _DRM_READ_ONLY, &dev_priv->mmio); - if (ret != 0) - return ret; - dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); ret = drm_addmap(dev, dev_priv->fb_aper_offset, drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, - _DRM_WRITE_COMBINING, &map); + _DRM_WRITE_COMBINING | _DRM_KERNEL | _DRM_DRIVER, + &map); if (ret != 0) return ret; @@ -1764,6 +1780,8 @@ int radeon_driver_unload(struct drm_device *dev) drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); + RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); + drm_rmmap(dev, dev_priv->mmio); drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); dev->dev_private = NULL; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 349ac3d..7942a30 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -72,9 +72,6 @@ static struct drm_driver driver = { .vblank_wait = radeon_driver_vblank_wait, .vblank_wait2 = radeon_driver_vblank_wait2, .dri_library_name = dri_library_name, - .irq_preinstall = radeon_driver_irq_preinstall, - .irq_postinstall = radeon_driver_irq_postinstall, - .irq_uninstall = radeon_driver_irq_uninstall, .irq_handler = radeon_driver_irq_handler, .reclaim_buffers = drm_core_reclaim_buffers, .get_map_ofs = drm_core_get_map_ofs, diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 0993816..9866c7a 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -1408,4 +1408,13 @@ do { \ write &= mask; \ } while (0) +static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, + u32 mask) +{ + u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; + if (irqs) + RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); + return irqs; +} + #endif /* __RADEON_DRV_H__ */ diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index ee40d19..38a838f 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -35,15 +35,6 @@ #include "radeon_drm.h" #include "radeon_drv.h" -static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, - u32 mask) -{ - u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; - if (irqs) - RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); - return irqs; -} - /* Interrupts - Used for device synchronization and flushing in the * following circumstances: * @@ -249,47 +240,6 @@ void radeon_enable_interrupt(struct drm_device *dev) dev_priv->irq_enabled = 1; } -/* drm_dma.h hooks -*/ -void radeon_driver_irq_preinstall(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - - /* Disable *all* interrupts */ - RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); - - /* Clear bits if they're already high */ - radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | - RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT)); -} - -void radeon_driver_irq_postinstall(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - - atomic_set(&dev_priv->swi_emitted, 0); - DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); - - radeon_enable_interrupt(dev); -} - -void radeon_driver_irq_uninstall(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - if (!dev_priv) - return; - - dev_priv->irq_enabled = 0; - - /* Disable *all* interrupts */ - RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); -} - - int radeon_vblank_crtc_get(struct drm_device *dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index 80c01cd..1ffa9f4 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -45,9 +45,6 @@ static struct drm_driver driver = { .unload = via_driver_unload, .context_dtor = via_final_context, .vblank_wait = via_driver_vblank_wait, - .irq_preinstall = via_driver_irq_preinstall, - .irq_postinstall = via_driver_irq_postinstall, - .irq_uninstall = via_driver_irq_uninstall, .irq_handler = via_driver_irq_handler, .dma_quiescent = via_driver_dma_quiescent, .dri_library_name = dri_library_name, diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 2daae81..06e19ef 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -150,4 +150,50 @@ extern void via_lastclose(struct drm_device *dev); extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq); extern void via_init_dmablit(struct drm_device *dev); +#define VIA_REG_INTERRUPT 0x200 + +/* VIA_REG_INTERRUPT */ +#define VIA_IRQ_GLOBAL (1 << 31) +#define VIA_IRQ_VBLANK_ENABLE (1 << 19) +#define VIA_IRQ_VBLANK_PENDING (1 << 3) +#define VIA_IRQ_HQV0_ENABLE (1 << 11) +#define VIA_IRQ_HQV1_ENABLE (1 << 25) +#define VIA_IRQ_HQV0_PENDING (1 << 9) +#define VIA_IRQ_HQV1_PENDING (1 << 10) +#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) +#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) +#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) +#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) +#define VIA_IRQ_DMA0_DD_PENDING (1 << 4) +#define VIA_IRQ_DMA0_TD_PENDING (1 << 5) +#define VIA_IRQ_DMA1_DD_PENDING (1 << 6) +#define VIA_IRQ_DMA1_TD_PENDING (1 << 7) + + +/* + * Device-specific IRQs go here. This type might need to be extended with + * the register if there are multiple IRQ control registers. + * Currently we activate the HQV interrupts of Unichrome Pro group A. + */ + +extern maskarray_t via_pro_group_a_irqs[]; +extern int via_num_pro_group_a; +extern int via_irqmap_pro_group_a[]; + +extern maskarray_t via_unichrome_irqs[]; +extern int via_num_unichrome; +extern int via_irqmap_unichrome[]; + +static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) +{ + u32 status; + + if (dev_priv) { + /* Acknowlege interrupts */ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | + dev_priv->irq_pending_mask); + } +} + #endif diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index 3d926f8..831c04d 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -40,33 +40,13 @@ #include "via_drm.h" #include "via_drv.h" -#define VIA_REG_INTERRUPT 0x200 - -/* VIA_REG_INTERRUPT */ -#define VIA_IRQ_GLOBAL (1 << 31) -#define VIA_IRQ_VBLANK_ENABLE (1 << 19) -#define VIA_IRQ_VBLANK_PENDING (1 << 3) -#define VIA_IRQ_HQV0_ENABLE (1 << 11) -#define VIA_IRQ_HQV1_ENABLE (1 << 25) -#define VIA_IRQ_HQV0_PENDING (1 << 9) -#define VIA_IRQ_HQV1_PENDING (1 << 10) -#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) -#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) -#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) -#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) -#define VIA_IRQ_DMA0_DD_PENDING (1 << 4) -#define VIA_IRQ_DMA0_TD_PENDING (1 << 5) -#define VIA_IRQ_DMA1_DD_PENDING (1 << 6) -#define VIA_IRQ_DMA1_TD_PENDING (1 << 7) - - /* * Device-specific IRQs go here. This type might need to be extended with * the register if there are multiple IRQ control registers. * Currently we activate the HQV interrupts of Unichrome Pro group A. */ -static maskarray_t via_pro_group_a_irqs[] = { +maskarray_t via_pro_group_a_irqs[] = { {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 0x00000000}, {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, @@ -76,18 +56,18 @@ static maskarray_t via_pro_group_a_irqs[] = { {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, }; -static int via_num_pro_group_a = +int via_num_pro_group_a = sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t); -static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; +int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; -static maskarray_t via_unichrome_irqs[] = { +maskarray_t via_unichrome_irqs[] = { {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} }; -static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t); -static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; +int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t); +int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; static unsigned time_diff(struct timeval *now, struct timeval *then) { @@ -151,18 +131,6 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_NONE; } -static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv) -{ - u32 status; - - if (dev_priv) { - /* Acknowlege interrupts */ - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | - dev_priv->irq_pending_mask); - } -} - int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence) { drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; @@ -239,97 +207,6 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc return ret; } -/* - * drm_dma.h hooks - */ - -void via_driver_irq_preinstall(struct drm_device * dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - drm_via_irq_t *cur_irq; - int i; - - DRM_DEBUG("dev_priv: %p\n", dev_priv); - if (dev_priv) { - cur_irq = dev_priv->via_irqs; - - dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; - dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; - - if (dev_priv->chipset == VIA_PRO_GROUP_A || - dev_priv->chipset == VIA_DX9_0) { - dev_priv->irq_masks = via_pro_group_a_irqs; - dev_priv->num_irqs = via_num_pro_group_a; - dev_priv->irq_map = via_irqmap_pro_group_a; - } else { - dev_priv->irq_masks = via_unichrome_irqs; - dev_priv->num_irqs = via_num_unichrome; - dev_priv->irq_map = via_irqmap_unichrome; - } - - for (i = 0; i < dev_priv->num_irqs; ++i) { - atomic_set(&cur_irq->irq_received, 0); - cur_irq->enable_mask = dev_priv->irq_masks[i][0]; - cur_irq->pending_mask = dev_priv->irq_masks[i][1]; - DRM_INIT_WAITQUEUE(&cur_irq->irq_queue); - dev_priv->irq_enable_mask |= cur_irq->enable_mask; - dev_priv->irq_pending_mask |= cur_irq->pending_mask; - cur_irq++; - - DRM_DEBUG("Initializing IRQ %d\n", i); - } - - dev_priv->last_vblank_valid = 0; - - /* Clear VSync interrupt regs */ - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & - ~(dev_priv->irq_enable_mask)); - - /* Clear bits if they're already high */ - viadrv_acknowledge_irqs(dev_priv); - } -} - -void via_driver_irq_postinstall(struct drm_device * dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - - DRM_DEBUG("\n"); - if (dev_priv) { - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL - | dev_priv->irq_enable_mask); - - /* Some magic, oh for some data sheets ! */ - - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); - - } -} - -void via_driver_irq_uninstall(struct drm_device * dev) -{ - drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - u32 status; - - DRM_DEBUG("\n"); - if (dev_priv) { - - /* Some more magic, oh for some data sheets ! */ - - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); - - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & - ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); - } -} - int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_irqwait_t *irqwait = data; diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c index a967556..a5e1d14 100644 --- a/drivers/gpu/drm/via/via_map.c +++ b/drivers/gpu/drm/via/via_map.c @@ -94,6 +94,9 @@ int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv) int via_driver_load(struct drm_device *dev, unsigned long chipset) { drm_via_private_t *dev_priv; + u32 status; + drm_via_irq_t *cur_irq; + int i; int ret = 0; dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); @@ -108,12 +111,76 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) if (ret) { drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); } + + ret = drm_addmap(dev, drm_get_resource_start(dev, 1), + drm_get_resource_len(dev, 1), _DRM_REGISTERS, + _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio); + if (ret != 0) + return ret; + + cur_irq = dev_priv->via_irqs; + + dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; + dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; + + if (dev_priv->chipset == VIA_PRO_GROUP_A || + dev_priv->chipset == VIA_DX9_0) { + dev_priv->irq_masks = via_pro_group_a_irqs; + dev_priv->num_irqs = via_num_pro_group_a; + dev_priv->irq_map = via_irqmap_pro_group_a; + } else { + dev_priv->irq_masks = via_unichrome_irqs; + dev_priv->num_irqs = via_num_unichrome; + dev_priv->irq_map = via_irqmap_unichrome; + } + + for (i = 0; i < dev_priv->num_irqs; ++i) { + atomic_set(&cur_irq->irq_received, 0); + cur_irq->enable_mask = dev_priv->irq_masks[i][0]; + cur_irq->pending_mask = dev_priv->irq_masks[i][1]; + DRM_INIT_WAITQUEUE(&cur_irq->irq_queue); + dev_priv->irq_enable_mask |= cur_irq->enable_mask; + dev_priv->irq_pending_mask |= cur_irq->pending_mask; + cur_irq++; + + DRM_DEBUG("Initializing IRQ %d\n", i); + } + + dev_priv->last_vblank_valid = 0; + + /* Clear VSync interrupt regs */ + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & + ~(dev_priv->irq_enable_mask)); + + /* Clear bits if they're already high */ + viadrv_acknowledge_irqs(dev_priv); + + drm_irq_init(dev); + + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + | dev_priv->irq_enable_mask); + + /* Some magic, oh for some data sheets ! */ + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + return ret; } int via_driver_unload(struct drm_device *dev) { drm_via_private_t *dev_priv = dev->dev_private; + u32 status; + + VIA_WRITE8(0x83d4, 0x11); + VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); + + status = VIA_READ(VIA_REG_INTERRUPT); + VIA_WRITE(VIA_REG_INTERRUPT, status & + ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); drm_sman_takedown(&dev_priv->sman); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 50d8b77..e81ee12 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -600,9 +600,6 @@ struct drm_driver { /* these have to be filled in */ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); - void (*irq_preinstall) (struct drm_device *dev); - void (*irq_postinstall) (struct drm_device *dev); - void (*irq_uninstall) (struct drm_device *dev); void (*reclaim_buffers) (struct drm_device *dev, struct drm_file * file_priv); void (*reclaim_buffers_locked) (struct drm_device *dev, @@ -984,11 +981,12 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev, extern int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); -extern int drm_irq_uninstall(struct drm_device *dev); -extern void drm_driver_irq_preinstall(struct drm_device *dev); -extern void drm_driver_irq_postinstall(struct drm_device *dev); -extern void drm_driver_irq_uninstall(struct drm_device *dev); +extern int drm_irq_install(struct drm_device * dev); +extern int drm_irq_uninstall(struct drm_device * dev); + +extern int drm_irq_init(struct drm_device *dev); +extern int drm_irq_teardown(struct drm_device *dev); extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);