diff options
Diffstat (limited to 'shared-core/i915_irq.c')
| -rw-r--r-- | shared-core/i915_irq.c | 366 |
1 files changed, 163 insertions, 203 deletions
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 2d355688..28fa35fd 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -35,6 +35,33 @@ #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_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) + +static inline void +i915_enable_irq(struct drm_i915_private *dev_priv, uint32_t mask) +{ + if ((dev_priv->irq_mask_reg & mask) != 0) { + dev_priv->irq_mask_reg &= ~mask; + I915_WRITE(IMR, dev_priv->irq_mask_reg); + (void) I915_READ(IMR); + } +} + +static inline void +i915_disable_irq(struct drm_i915_private *dev_priv, uint32_t mask) +{ + if ((dev_priv->irq_mask_reg & mask) != mask) { + dev_priv->irq_mask_reg |= mask; + I915_WRITE(IMR, dev_priv->irq_mask_reg); + (void) I915_READ(IMR); + } +} + /** * i915_get_pipe - return the the pipe associated with a given plane * @dev: DRM device @@ -165,11 +192,11 @@ static void i915_vblank_tasklet(struct drm_device *dev) u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24); RING_LOCALS; - if (sarea_priv->front_tiled) { + if (IS_I965G(dev) && sarea_priv->front_tiled) { cmd |= XY_SRC_COPY_BLT_DST_TILED; dst_pitch >>= 2; } - if (sarea_priv->back_tiled) { + if (IS_I965G(dev) && sarea_priv->back_tiled) { cmd |= XY_SRC_COPY_BLT_SRC_TILED; src_pitch >>= 2; } @@ -367,28 +394,7 @@ static void i915_vblank_tasklet(struct drm_device *dev) drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER); } } -#if 0 -static int i915_in_vblank(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - unsigned long pipedsl, vblank, vtotal; - unsigned long vbl_start, vbl_end, cur_line; - - pipedsl = pipe ? PIPEBDSL : PIPEADSL; - vblank = pipe ? VBLANK_B : VBLANK_A; - vtotal = pipe ? VTOTAL_B : VTOTAL_A; - - vbl_start = I915_READ(vblank) & VBLANK_START_MASK; - vbl_end = (I915_READ(vblank) >> VBLANK_END_SHIFT) & VBLANK_END_MASK; - - cur_line = I915_READ(pipedsl); - if (cur_line >= vbl_start) - return 1; - - return 0; -} -#endif u32 i915_get_vblank_counter(struct drm_device *dev, int plane) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; @@ -422,30 +428,17 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) count = (high1 << 8) | low; - /* - * If we're in the middle of the vblank period, the - * above regs won't have been updated yet, so return - * an incremented count to stay accurate - */ -#if 0 - if (i915_in_vblank(dev, pipe)) - count++; -#endif - /* count may be reset by other driver(e.g. 2D driver), - we have no way to know if it is wrapped or resetted - when count is zero. do a rough guess. - */ - if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2) - dev->last_vblank[pipe] = 0; - return count; } static struct drm_device *hotplug_dev; -/* - * This code is called in a more safe envirmoent to handle the hotplugs. - * Add code here for hotplug love to userspace. +/** + * Handler for user interrupts in process context (able to sleep, do VFS + * operations, etc. + * + * If another IRQ comes in while we're in this handler, it will still get put + * on the queue again to be rerun when we finish. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void i915_hotplug_work_func(void *work) @@ -485,7 +478,6 @@ static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat) if (stat & SDVOC_HOTPLUG_INT_STATUS) { DRM_DEBUG("sDVOC event\n"); } - queue_work(dev_priv->wq, &hotplug); return 0; @@ -497,30 +489,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) struct drm_i915_master_private *master_priv; struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; u32 iir; - u32 pipea_stats = 0, pipeb_stats, tvdac; + u32 pipea_stats = 0, pipeb_stats = 0, tvdac; int hotplug = 0; int vblank = 0; - /* On i8xx/i915 hw the IIR and IER are 16bit on i9xx its 32bit */ - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - iir = I915_READ(IIR); - else - iir = I915_READ16(IIR); - - iir &= (dev_priv->irq_enable_reg | I915_USER_INTERRUPT); - -#if 0 - DRM_DEBUG("flag=%08x\n", iir); -#endif + if (dev->pdev->msi_enabled) + I915_WRITE(IMR, ~0); + iir = I915_READ(IIR); + atomic_inc(&dev_priv->irq_received); if (iir == 0) { -#if 0 - DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n", - iir, - I915_READ(IMR), - I915_READ(IER), - I915_READ(PIPEASTAT), - I915_READ(PIPEBSTAT)); -#endif + if (dev->pdev->msi_enabled) { + I915_WRITE(IMR, dev_priv->irq_mask_reg); + (void) I915_READ(IMR); + } return IRQ_NONE; } @@ -530,46 +511,29 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) */ if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { pipea_stats = I915_READ(PIPEASTAT); - if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| - PIPE_VBLANK_INTERRUPT_STATUS)) - { - vblank++; - drm_handle_vblank(dev, i915_get_plane(dev, 0)); - } - - /* This is a global event, and not a pipe A event */ - if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS) - hotplug = 1; - - if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) { - hotplug = 1; - /* Toggle hotplug detection to clear hotplug status */ - tvdac = I915_READ(TV_DAC); - I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN); - I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN); - } - I915_WRITE(PIPEASTAT, pipea_stats); } if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { pipeb_stats = I915_READ(PIPEBSTAT); - if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| - PIPE_VBLANK_INTERRUPT_STATUS)) - { - vblank++; - drm_handle_vblank(dev, i915_get_plane(dev, 1)); - } I915_WRITE(PIPEBSTAT, pipeb_stats); } - /* Clear the generated interrupt */ - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { - I915_WRITE(IIR, iir); - (void) I915_READ(IIR); - } else { - I915_WRITE16(IIR, iir); - (void) I915_READ16(IIR); + I915_WRITE(IIR, iir); + if (dev->pdev->msi_enabled) + I915_WRITE(IMR, dev_priv->irq_mask_reg); + (void) I915_READ(IIR); /* Flush posted writes */ + + /* This is a global event, and not a pipe A event */ + if (pipea_stats & PIPE_HOTPLUG_INTERRUPT_STATUS) + hotplug = 1; + + if (pipea_stats & PIPE_HOTPLUG_TV_INTERRUPT_STATUS) { + hotplug = 1; + /* Toggle hotplug detection to clear hotplug status */ + tvdac = I915_READ(TV_DAC); + I915_WRITE(TV_DAC, tvdac & ~TVDAC_STATE_CHG_EN); + I915_WRITE(TV_DAC, tvdac | TVDAC_STATE_CHG_EN); } if (dev->primary->master) { @@ -577,13 +541,41 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); } +#ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) + if ((iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) && + (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE)) + opregion_asle_intr(dev); + if (iir & I915_ASLE_INTERRUPT) + opregion_asle_intr(dev); +#endif +#endif + if (iir & I915_USER_INTERRUPT) { + dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); DRM_WAKEUP(&dev_priv->irq_queue); #ifdef I915_HAVE_FENCE i915_fence_handler(dev); #endif } + if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| + PIPE_VBLANK_INTERRUPT_STATUS)) { + vblank++; + drm_handle_vblank(dev, i915_get_plane(dev, 0)); + } + + /* The vblank interrupt gets enabled even if we didn't ask for + it, so make sure it's shut down again */ + if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)) + pipeb_stats &= ~(I915_VBLANK_INTERRUPT_ENABLE); + + if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| + PIPE_VBLANK_INTERRUPT_STATUS)) { + vblank++; + drm_handle_vblank(dev, i915_get_plane(dev, 1)); + } + if (vblank) { if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); @@ -635,15 +627,9 @@ void i915_user_irq_on(struct drm_device *dev) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ - dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - I915_WRITE(IER, dev_priv->irq_enable_reg); - else - I915_WRITE16(IER, dev_priv->irq_enable_reg); - } + if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)) + i915_enable_irq(dev_priv, I915_USER_INTERRUPT); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); - } void i915_user_irq_off(struct drm_device *dev) @@ -651,28 +637,38 @@ void i915_user_irq_off(struct drm_device *dev) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { - // dev_priv->irq_enable_reg &= ~I915_USER_INTERRUPT; - // if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - // I915_WRITE(IER, dev_priv->irq_enable_reg); - // else - // I915_WRITE16(IER, dev_priv->irq_enable_reg); - } + BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); + if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) + i915_disable_irq(dev_priv, I915_USER_INTERRUPT); DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } -static int i915_wait_irq(struct drm_device * dev, int irq_nr) +int i915_wait_irq(struct drm_device * dev, int irq_nr) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct drm_i915_master_private *master_priv; int ret = 0; + if (!dev_priv) { + DRM_ERROR("called with no initialization\n"); + return -EINVAL; + } + DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); - if (READ_BREADCRUMB(dev_priv) >= irq_nr) + master_priv = dev->primary->master->driver_priv; + + if (!master_priv) { + DRM_ERROR("no master priv?\n"); + return -EINVAL; + } + + if (READ_BREADCRUMB(dev_priv) >= irq_nr) { + master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); return 0; + } i915_user_irq_on(dev); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, @@ -684,10 +680,8 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); } - if (dev->primary->master) { - master_priv = dev->primary->master->driver_priv; + if (READ_BREADCRUMB(dev_priv) >= irq_nr) master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - } return ret; } @@ -739,16 +733,17 @@ int i915_enable_vblank(struct drm_device *dev, int plane) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; int pipe = i915_get_pipe(dev, plane); u32 pipestat_reg = 0; + u32 mask_reg = 0; u32 pipestat; switch (pipe) { case 0: pipestat_reg = PIPEASTAT; - dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; break; case 1: pipestat_reg = PIPEBSTAT; - dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; break; default: DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", @@ -774,12 +769,9 @@ int i915_enable_vblank(struct drm_device *dev, int plane) PIPE_VBLANK_INTERRUPT_STATUS); I915_WRITE(pipestat_reg, pipestat); } - - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - I915_WRITE(IER, dev_priv->irq_enable_reg); - else - I915_WRITE16(IER, dev_priv->irq_enable_reg); - + DRM_SPINLOCK(&dev_priv->user_irq_lock); + i915_enable_irq(dev_priv, mask_reg); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); return 0; } @@ -789,16 +781,17 @@ void i915_disable_vblank(struct drm_device *dev, int plane) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; int pipe = i915_get_pipe(dev, plane); u32 pipestat_reg = 0; + u32 mask_reg = 0; u32 pipestat; switch (pipe) { case 0: pipestat_reg = PIPEASTAT; - dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; break; case 1: pipestat_reg = PIPEBSTAT; - dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; + mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; break; default: DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", @@ -806,13 +799,11 @@ void i915_disable_vblank(struct drm_device *dev, int plane) break; } - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - I915_WRITE(IER, dev_priv->irq_enable_reg); - else - I915_WRITE16(IER, dev_priv->irq_enable_reg); + DRM_SPINLOCK(&dev_priv->user_irq_lock); + i915_disable_irq(dev_priv, mask_reg); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); - if (pipestat_reg) - { + if (pipestat_reg) { pipestat = I915_READ (pipestat_reg); pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | PIPE_VBLANK_INTERRUPT_ENABLE); @@ -822,6 +813,7 @@ void i915_disable_vblank(struct drm_device *dev, int plane) pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS | PIPE_VBLANK_INTERRUPT_STATUS); I915_WRITE(pipestat_reg, pipestat); + (void) I915_READ(pipestat_reg); } } @@ -829,15 +821,15 @@ void i915_enable_interrupt (struct drm_device *dev) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; struct drm_connector *o; - - dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; + + dev_priv->irq_mask_reg &= ~0; if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { if (dev->mode_config.num_connector) - dev_priv->irq_enable_reg |= I915_DISPLAY_PORT_INTERRUPT; + dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT; } else { if (dev->mode_config.num_connector) - dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; + dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; /* Enable global interrupts for hotplug - not a pipeA event */ I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) | @@ -847,7 +839,8 @@ void i915_enable_interrupt (struct drm_device *dev) PIPE_HOTPLUG_INTERRUPT_STATUS); } - if (dev_priv->irq_enable_reg & (I915_DISPLAY_PORT_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)) { + if (!(dev_priv->irq_mask_reg & I915_DISPLAY_PORT_INTERRUPT) || + !(dev_priv->irq_mask_reg & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)) { u32 temp = 0; if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { @@ -891,11 +884,11 @@ void i915_enable_interrupt (struct drm_device *dev) } } - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - I915_WRITE(IER, dev_priv->irq_enable_reg); - else - I915_WRITE16(IER, dev_priv->irq_enable_reg); - +#ifdef __linux__ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) + opregion_enable_asle(dev); +#endif +#endif dev_priv->irq_enabled = 1; } @@ -905,20 +898,12 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_vblank_pipe *pipe = data; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } - if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { - DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe); - return -EINVAL; - } - - dev_priv->vblank_pipe = pipe->pipe; - return 0; } @@ -927,17 +912,15 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_vblank_pipe *pipe = data; - u16 flag; + u32 flag = 0; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) - flag = I915_READ(IER); - else - flag = I915_READ16(IER); + if (dev_priv->irq_enabled) + flag = ~dev_priv->irq_mask_reg; pipe->pipe = 0; if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) @@ -1010,7 +993,13 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); - drm_update_vblank_count(dev, pipe); + /* + * We take the ref here and put it when the swap actually completes + * in the tasklet. + */ + ret = drm_vblank_get(dev, pipe); + if (ret) + return ret; curseq = drm_vblank_count(dev, pipe); if (seqtype == _DRM_VBLANK_RELATIVE) @@ -1021,6 +1010,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, swap->sequence = curseq + 1; } else { DRM_DEBUG("Missed target sequence\n"); + drm_vblank_put(dev, pipe); return -EINVAL; } } @@ -1042,6 +1032,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, irqflags); DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); + drm_vblank_put(dev, pipe); return -EINVAL; } @@ -1049,6 +1040,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, DRM_SPINUNLOCK_IRQRESTORE(&dev->drw_lock, irqflags); + drm_vblank_put(dev, pipe); return 0; } } @@ -1072,6 +1064,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data, if (dev_priv->swaps_pending >= 100) { DRM_DEBUG("Too many swaps queued\n"); + drm_vblank_put(dev, pipe); return -EBUSY; } @@ -1079,17 +1072,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data, if (!vbl_swap) { DRM_ERROR("Failed to allocate memory to queue swap\n"); + drm_vblank_put(dev, pipe); return -ENOMEM; } DRM_DEBUG("\n"); - ret = drm_vblank_get(dev, pipe); - if (ret) { - drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); - return ret; - } - vbl_swap->drw_id = swap->drawable; vbl_swap->plane = plane; vbl_swap->sequence = swap->sequence; @@ -1113,33 +1101,16 @@ int i915_vblank_swap(struct drm_device *dev, void *data, */ void i915_driver_irq_preinstall(struct drm_device * dev) { - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; - u32 tmp; - - tmp = I915_READ(PIPEASTAT); - I915_WRITE(PIPEASTAT, tmp); - tmp = I915_READ(PIPEBSTAT); - I915_WRITE(PIPEBSTAT, tmp); - + struct drm_i915_private *dev_priv = dev->dev_private; I915_WRITE16(HWSTAM, 0xeffe); - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { - I915_WRITE(IMR, 0x0); - I915_WRITE(IER, 0x0); - tmp = I915_READ(IIR); - I915_WRITE(IIR, tmp); - } else { - I915_WRITE16(IMR, 0x0); - I915_WRITE16(IER, 0x0); - tmp = I915_READ16(IIR); - I915_WRITE16(IIR, tmp); - } - + I915_WRITE16(IMR, 0x0); + I915_WRITE16(IER, 0x0); } int i915_driver_irq_postinstall(struct drm_device * dev) { - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; int ret, num_pipes = 2; DRM_SPININIT(&dev_priv->swaps_lock, "swap"); @@ -1148,16 +1119,13 @@ int i915_driver_irq_postinstall(struct drm_device * dev) DRM_SPININIT(&dev_priv->user_irq_lock, "userirq"); dev_priv->user_irq_refcount = 0; - dev_priv->irq_enable_reg = 0; + dev_priv->irq_mask_reg = ~0; ret = drm_vblank_init(dev, num_pipes); if (ret) return ret; - ret = drm_hotplug_init(dev); - if (ret) - return ret; - + 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); @@ -1173,31 +1141,23 @@ int i915_driver_irq_postinstall(struct drm_device * dev) void i915_driver_irq_uninstall(struct drm_device * dev) { - struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + struct drm_i915_private *dev_priv = dev->dev_private; u32 temp; if (!dev_priv) return; + 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); - if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { - I915_WRITE(HWSTAM, 0xffffffff); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - - temp = I915_READ(IIR); - I915_WRITE(IIR, temp); - } else { - I915_WRITE16(HWSTAM, 0xffff); - I915_WRITE16(IMR, 0xffff); - I915_WRITE16(IER, 0x0); - - temp = I915_READ16(IIR); - I915_WRITE16(IIR, temp); - } + temp = I915_READ(IIR); + I915_WRITE(IIR, temp); } |
