diff options
author | rnoland <rnoland@FreeBSD.org> | 2009-02-25 18:44:50 +0000 |
---|---|---|
committer | rnoland <rnoland@FreeBSD.org> | 2009-02-25 18:44:50 +0000 |
commit | ca01a44d40c374f06bbd39d32618437862a9adf2 (patch) | |
tree | 135e30368d3742f4dbe1693742d1a438aa8c734c /sys/dev/drm/i915_irq.c | |
parent | 12840cf0056fa062ed952cfd8b488c70eeeb00b8 (diff) | |
download | FreeBSD-src-ca01a44d40c374f06bbd39d32618437862a9adf2.zip FreeBSD-src-ca01a44d40c374f06bbd39d32618437862a9adf2.tar.gz |
This was part of a sync to the code that Intel is shipping in linux.
- Remove the old TTM interface
- Move register definitions to i915_reg.h
- Overhaul the irq handler
MFC after: 2 weeks
Diffstat (limited to 'sys/dev/drm/i915_irq.c')
-rw-r--r-- | sys/dev/drm/i915_irq.c | 454 |
1 files changed, 192 insertions, 262 deletions
diff --git a/sys/dev/drm/i915_irq.c b/sys/dev/drm/i915_irq.c index 345ca35..3407e82 100644 --- a/sys/dev/drm/i915_irq.c +++ b/sys/dev/drm/i915_irq.c @@ -36,16 +36,29 @@ __FBSDID("$FreeBSD$"); #define MAX_NOPID ((u32)~0) -/* - * These are the interrupts used by the driver +/** + * Interrupts that are always left unmasked. + * + * Since pipe events are edge-triggered from the PIPESTAT register to IIR, + * we leave them always unmasked in IMR and then control enabling them through + * PIPESTAT alone. */ -#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) +#define I915_INTERRUPT_ENABLE_FIX (I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) + +/** Interrupts that we mask and unmask at runtime. */ +#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) + +/** These are all of the interrupts used by the driver */ +#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \ + I915_INTERRUPT_ENABLE_VAR) static inline void -i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask) +i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) { + DRM_DEBUG("irq_enable_reg = 0x%08x, mask = 0x%08x\n", + dev_priv->irq_mask_reg, mask); + mask &= I915_INTERRUPT_ENABLE_VAR; if ((dev_priv->irq_mask_reg & mask) != 0) { dev_priv->irq_mask_reg &= ~mask; I915_WRITE(IMR, dev_priv->irq_mask_reg); @@ -54,8 +67,9 @@ i915_enable_irq(drm_i915_private_t *dev_priv, uint32_t mask) } static inline void -i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask) +i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask) { + mask &= I915_INTERRUPT_ENABLE_VAR; if ((dev_priv->irq_mask_reg & mask) != mask) { dev_priv->irq_mask_reg |= mask; I915_WRITE(IMR, dev_priv->irq_mask_reg); @@ -63,41 +77,39 @@ i915_disable_irq(drm_i915_private_t *dev_priv, uint32_t mask) } } -/** - * i915_get_pipe - return the the pipe associated with a given plane - * @dev: DRM device - * @plane: plane to look for - * - * The Intel Mesa & 2D drivers call the vblank routines with a plane number - * rather than a pipe number, since they may not always be equal. This routine - * maps the given @plane back to a pipe number. - */ -static int -i915_get_pipe(struct drm_device *dev, int plane) +static inline u32 +i915_pipestat(int pipe) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 dspcntr; + if (pipe == 0) + return PIPEASTAT; + if (pipe == 1) + return PIPEBSTAT; + return -EINVAL; +} - dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR); +void +i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) +{ + if ((dev_priv->pipestat[pipe] & mask) != mask) { + u32 reg = i915_pipestat(pipe); - return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0; + dev_priv->pipestat[pipe] |= mask; + /* Enable the interrupt, clear any pending status */ + I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16)); + (void) I915_READ(reg); + } } -/** - * i915_get_plane - return the the plane associated with a given pipe - * @dev: DRM device - * @pipe: pipe to look for - * - * The Intel Mesa & 2D drivers call the vblank routines with a plane number - * rather than a plane number, since they may not always be equal. This routine - * maps the given @pipe back to a plane number. - */ -static int -i915_get_plane(struct drm_device *dev, int pipe) +void +i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) { - if (i915_get_pipe(dev, 0) == pipe) - return 0; - return 1; + if ((dev_priv->pipestat[pipe] & mask) != 0) { + u32 reg = i915_pipestat(pipe); + + dev_priv->pipestat[pipe] &= ~mask; + I915_WRITE(reg, dev_priv->pipestat[pipe]); + (void) I915_READ(reg); + } } /** @@ -121,21 +133,22 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) return 0; } -u32 i915_get_vblank_counter(struct drm_device *dev, int plane) +/* Called from drm generic code, passed a 'crtc', which + * we use as a pipe index + */ +u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long high_frame; unsigned long low_frame; u32 high1, high2, low, count; - int pipe; - pipe = i915_get_pipe(dev, plane); high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH; low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL; if (!i915_pipe_enabled(dev, pipe)) { - DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe); - return 0; + DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe); + return 0; } /* @@ -161,104 +174,65 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 iir; - u32 pipea_stats = 0, pipeb_stats = 0; - int vblank = 0; -#ifdef __linux__ - if (dev->pdev->msi_enabled) - I915_WRITE(IMR, ~0); -#endif - iir = I915_READ(IIR); -#if 0 - DRM_DEBUG("flag=%08x\n", iir); -#endif + u32 iir, new_iir; + u32 pipea_stats, pipeb_stats; + atomic_inc(&dev_priv->irq_received); - if (iir == 0) { -#ifdef __linux__ - if (dev->pdev->msi_enabled) { - I915_WRITE(IMR, dev_priv->irq_mask_reg); - (void) I915_READ(IMR); - } -#endif - return IRQ_NONE; - } - /* - * Clear the PIPE(A|B)STAT regs before the IIR otherwise - * we may get extra interrupts. - */ - if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { - pipea_stats = I915_READ(PIPEASTAT); - - /* 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_A)) - pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | - PIPE_VBLANK_INTERRUPT_ENABLE); - else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| - PIPE_VBLANK_INTERRUPT_STATUS)) - { - vblank++; - drm_handle_vblank(dev, i915_get_plane(dev, 0)); - } + for (iir = I915_READ(IIR) ; iir != 0 ; iir = new_iir) { - I915_WRITE(PIPEASTAT, pipea_stats); - } - if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { - pipeb_stats = I915_READ(PIPEBSTAT); - - /* 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 &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | - PIPE_VBLANK_INTERRUPT_ENABLE); - else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| - PIPE_VBLANK_INTERRUPT_STATUS)) - { - vblank++; - drm_handle_vblank(dev, i915_get_plane(dev, 1)); + pipea_stats = pipeb_stats = 0; + + /* + * Clear the PIPE(A|B)STAT regs before the IIR + */ + if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { + DRM_SPINLOCK(&dev_priv->user_irq_lock); + pipea_stats = I915_READ(PIPEASTAT); + I915_WRITE(PIPEASTAT, pipea_stats); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } -#ifdef __linux__ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) - if (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE) - opregion_asle_intr(dev); -#endif -#endif - I915_WRITE(PIPEBSTAT, pipeb_stats); - } + if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { + DRM_SPINLOCK(&dev_priv->user_irq_lock); + pipeb_stats = I915_READ(PIPEBSTAT); + I915_WRITE(PIPEBSTAT, pipeb_stats); + DRM_SPINUNLOCK(&dev_priv->user_irq_lock); + } -#ifdef __linux__ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) - if (iir & I915_ASLE_INTERRUPT) - opregion_asle_intr(dev); -#endif -#endif + I915_WRITE(IIR, iir); + new_iir = I915_READ(IIR); - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + DRM_DEBUG("iir = 0x%08x, pipestats a = 0x%08x, b = 0x%08x\n", + iir, pipea_stats, pipeb_stats); - I915_WRITE(IIR, iir); -#ifdef __linux__ - if (dev->pdev->msi_enabled) - I915_WRITE(IMR, dev_priv->irq_mask_reg); -#endif - (void) I915_READ(IIR); /* Flush posted writes */ + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); - if (iir & I915_USER_INTERRUPT) { + if (iir & I915_USER_INTERRUPT) { #ifdef I915_HAVE_GEM - dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); + dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); #endif - DRM_WAKEUP(&dev_priv->irq_queue); -#ifdef I915_HAVE_FENCE - i915_fence_handler(dev); + DRM_WAKEUP(&dev_priv->irq_queue); + } + + if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS | + PIPE_VBLANK_INTERRUPT_STATUS)) + drm_handle_vblank(dev, 0); + + if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS | + PIPE_VBLANK_INTERRUPT_STATUS)) + drm_handle_vblank(dev, 1); +#ifdef __linux__ + if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || + (iir & I915_ASLE_INTERRUPT)) + opregion_asle_intr(dev); #endif } - - return IRQ_HANDLED; } -int i915_emit_irq(struct drm_device *dev) +static int i915_emit_irq(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; RING_LOCALS; @@ -267,60 +241,71 @@ int i915_emit_irq(struct drm_device *dev) DRM_DEBUG("\n"); - i915_emit_breadcrumb(dev); + dev_priv->counter++; + if (dev_priv->counter > 0x7FFFFFFFUL) + dev_priv->counter = 1; + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_enqueue = dev_priv->counter; - BEGIN_LP_RING(2); - OUT_RING(0); + BEGIN_LP_RING(4); + OUT_RING(MI_STORE_DWORD_INDEX); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(dev_priv->counter); OUT_RING(MI_USER_INTERRUPT); ADVANCE_LP_RING(); return dev_priv->counter; } -void i915_user_irq_on(drm_i915_private_t *dev_priv) +void i915_user_irq_get(struct drm_device *dev) { - DRM_SPINLOCK(&dev_priv->user_irq_lock); - if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)) + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; + + DRM_DEBUG("\n"); + DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags); + if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) i915_enable_irq(dev_priv, I915_USER_INTERRUPT); - DRM_SPINUNLOCK(&dev_priv->user_irq_lock); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags); } -void i915_user_irq_off(drm_i915_private_t *dev_priv) +void i915_user_irq_put(struct drm_device *dev) { - DRM_SPINLOCK(&dev_priv->user_irq_lock); + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; + + DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags); #ifdef __linux__ - BUG_ON(dev_priv->irq_enabled && dev_priv->user_irq_refcount <= 0); + BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); #endif - if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) + if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) i915_disable_irq(dev_priv, I915_USER_INTERRUPT); - DRM_SPINUNLOCK(&dev_priv->user_irq_lock); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags); } - -int i915_wait_irq(struct drm_device * dev, int irq_nr) +static int i915_wait_irq(struct drm_device * dev, int irq_nr) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 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) { - if (dev_priv->sarea_priv) + if (dev_priv->sarea_priv) { dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + } return 0; } - i915_user_irq_on(dev_priv); + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; + + i915_user_irq_get(dev); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); - i915_user_irq_off(dev_priv); + i915_user_irq_put(dev); if (ret == -EBUSY) { DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", @@ -330,6 +315,7 @@ int i915_wait_irq(struct drm_device * dev, int irq_nr) if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + return ret; } @@ -342,7 +328,7 @@ int i915_irq_emit(struct drm_device *dev, void *data, drm_i915_irq_emit_t *emit = data; int result; - LOCK_TEST_WITH_RETURN(dev, file_priv); + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("called with no initialization\n"); @@ -362,7 +348,7 @@ int i915_irq_emit(struct drm_device *dev, void *data, /* Doesn't need the hardware lock. */ int i915_irq_wait(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_irq_wait_t *irqwait = data; @@ -375,112 +361,42 @@ int i915_irq_wait(struct drm_device *dev, void *data, return i915_wait_irq(dev, irqwait->irq_seq); } -int i915_enable_vblank(struct drm_device *dev, int plane) +/* Called from drm generic code, passed 'crtc' which + * we use as a pipe index + */ +int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) 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; - mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; - break; - case 1: - pipestat_reg = PIPEBSTAT; - mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; - break; - default: - DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", - pipe); - break; - } - - if (pipestat_reg) - { - pipestat = I915_READ (pipestat_reg); - /* - * Older chips didn't have the start vblank interrupt, - * but - */ - if (IS_I965G (dev)) - pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE; - else - pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE; - /* - * Clear any pending status - */ - pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS | - PIPE_VBLANK_INTERRUPT_STATUS); - I915_WRITE(pipestat_reg, pipestat); - } - DRM_SPINLOCK(&dev_priv->user_irq_lock); - i915_enable_irq(dev_priv, mask_reg); - DRM_SPINUNLOCK(&dev_priv->user_irq_lock); + unsigned long irqflags; + u32 pipestat; + /* + * Older chips didn't have the start vblank interrupt, + * but + */ + if (IS_I965G (dev)) + pipestat = PIPE_START_VBLANK_INTERRUPT_ENABLE; + else + pipestat = PIPE_VBLANK_INTERRUPT_ENABLE; + + DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags); + i915_enable_pipestat(dev_priv, pipe, pipestat); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags); return 0; } -void i915_disable_vblank(struct drm_device *dev, int plane) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) 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; - mask_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; - break; - case 1: - pipestat_reg = PIPEBSTAT; - mask_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; - break; - default: - DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", - pipe); - break; - } - - DRM_SPINLOCK(&dev_priv->user_irq_lock); - i915_disable_irq(dev_priv, mask_reg); - DRM_SPINUNLOCK(&dev_priv->user_irq_lock); - - if (pipestat_reg) - { - pipestat = I915_READ (pipestat_reg); - pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | - PIPE_VBLANK_INTERRUPT_ENABLE); - /* - * Clear any pending status - */ - pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS | - PIPE_VBLANK_INTERRUPT_STATUS); - I915_WRITE(pipestat_reg, pipestat); - (void) I915_READ(pipestat_reg); - } -} - -static void i915_enable_interrupt (struct drm_device *dev) +/* Called from drm generic code, passed 'crtc' which + * we use as a pipe index + */ +void i915_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; - dev_priv->irq_mask_reg = ~0; - I915_WRITE(IMR, dev_priv->irq_mask_reg); - I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); - (void) I915_READ (IER); - -#ifdef __linux__ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25) - opregion_enable_asle(dev); -#endif -#endif - - dev_priv->irq_enabled = 1; + DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags); + i915_disable_pipestat(dev_priv, pipe, + PIPE_START_VBLANK_INTERRUPT_ENABLE | PIPE_VBLANK_INTERRUPT_ENABLE); + DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags); } /* Set the vblank monitor pipe @@ -545,55 +461,69 @@ 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, 0xeffe); + I915_WRITE(PIPEASTAT, 0); + I915_WRITE(PIPEBSTAT, 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); + (void) I915_READ(IER); } -int i915_driver_irq_postinstall(struct drm_device * dev) +int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret, num_pipes = 2; - dev_priv->user_irq_refcount = 0; - dev_priv->irq_mask_reg = ~0; - ret = drm_vblank_init(dev, num_pipes); 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); + /* Unmask the interrupts that we always want on. */ + dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; + + dev_priv->pipestat[0] = 0; + dev_priv->pipestat[1] = 0; + + /* Disable pipe interrupt enables, clear pending pipe status */ + I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); + I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); + + /* Clear pending interrupt status */ + I915_WRITE(IIR, I915_READ(IIR)); + + I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); + I915_WRITE(IMR, dev_priv->irq_mask_reg); + (void) I915_READ(IER); +#ifdef __linux__ + opregion_enable_asle(dev); +#endif DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); - /* - * Initialize the hardware status page IRQ location. - */ + i915_enable_vblank(dev, 0); + i915_enable_vblank(dev, 1); - I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); return 0; } void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) 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(PIPEASTAT, 0); + I915_WRITE(PIPEBSTAT, 0); 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(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); + I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); + I915_WRITE(IIR, I915_READ(IIR)); } |