|
@@ -80,17 +80,64 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */
|
|
[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
|
[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* IIR can theoretically queue up two events. Be paranoid. */
|
|
|
|
+#define GEN8_IRQ_RESET_NDX(type, which) do { \
|
|
|
|
+ I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
|
|
|
|
+ POSTING_READ(GEN8_##type##_IMR(which)); \
|
|
|
|
+ I915_WRITE(GEN8_##type##_IER(which), 0); \
|
|
|
|
+ I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
|
|
|
+ POSTING_READ(GEN8_##type##_IIR(which)); \
|
|
|
|
+ I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
|
|
|
+ POSTING_READ(GEN8_##type##_IIR(which)); \
|
|
|
|
+} while (0)
|
|
|
|
+
|
|
|
|
+#define GEN5_IRQ_RESET(type) do { \
|
|
|
|
+ I915_WRITE(type##IMR, 0xffffffff); \
|
|
|
|
+ POSTING_READ(type##IMR); \
|
|
|
|
+ I915_WRITE(type##IER, 0); \
|
|
|
|
+ I915_WRITE(type##IIR, 0xffffffff); \
|
|
|
|
+ POSTING_READ(type##IIR); \
|
|
|
|
+ I915_WRITE(type##IIR, 0xffffffff); \
|
|
|
|
+ POSTING_READ(type##IIR); \
|
|
|
|
+} while (0)
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * We should clear IMR at preinstall/uninstall, and just check at postinstall.
|
|
|
|
+ */
|
|
|
|
+#define GEN5_ASSERT_IIR_IS_ZERO(reg) do { \
|
|
|
|
+ u32 val = I915_READ(reg); \
|
|
|
|
+ if (val) { \
|
|
|
|
+ WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", \
|
|
|
|
+ (reg), val); \
|
|
|
|
+ I915_WRITE((reg), 0xffffffff); \
|
|
|
|
+ POSTING_READ(reg); \
|
|
|
|
+ I915_WRITE((reg), 0xffffffff); \
|
|
|
|
+ POSTING_READ(reg); \
|
|
|
|
+ } \
|
|
|
|
+} while (0)
|
|
|
|
+
|
|
|
|
+#define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \
|
|
|
|
+ GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \
|
|
|
|
+ I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \
|
|
|
|
+ I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \
|
|
|
|
+ POSTING_READ(GEN8_##type##_IER(which)); \
|
|
|
|
+} while (0)
|
|
|
|
+
|
|
|
|
+#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \
|
|
|
|
+ GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \
|
|
|
|
+ I915_WRITE(type##IMR, (imr_val)); \
|
|
|
|
+ I915_WRITE(type##IER, (ier_val)); \
|
|
|
|
+ POSTING_READ(type##IER); \
|
|
|
|
+} while (0)
|
|
|
|
+
|
|
/* For display hotplug interrupt */
|
|
/* For display hotplug interrupt */
|
|
static void
|
|
static void
|
|
ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
|
|
ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
|
|
{
|
|
{
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (dev_priv->pm.irqs_disabled) {
|
|
|
|
- WARN(1, "IRQs disabled\n");
|
|
|
|
- dev_priv->pm.regsave.deimr &= ~mask;
|
|
|
|
|
|
+ if (WARN_ON(dev_priv->pm.irqs_disabled))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
|
|
if ((dev_priv->irq_mask & mask) != 0) {
|
|
if ((dev_priv->irq_mask & mask) != 0) {
|
|
dev_priv->irq_mask &= ~mask;
|
|
dev_priv->irq_mask &= ~mask;
|
|
@@ -104,11 +151,8 @@ ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
|
|
{
|
|
{
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (dev_priv->pm.irqs_disabled) {
|
|
|
|
- WARN(1, "IRQs disabled\n");
|
|
|
|
- dev_priv->pm.regsave.deimr |= mask;
|
|
|
|
|
|
+ if (WARN_ON(dev_priv->pm.irqs_disabled))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
|
|
if ((dev_priv->irq_mask & mask) != mask) {
|
|
if ((dev_priv->irq_mask & mask) != mask) {
|
|
dev_priv->irq_mask |= mask;
|
|
dev_priv->irq_mask |= mask;
|
|
@@ -129,13 +173,8 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
|
|
{
|
|
{
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (dev_priv->pm.irqs_disabled) {
|
|
|
|
- WARN(1, "IRQs disabled\n");
|
|
|
|
- dev_priv->pm.regsave.gtimr &= ~interrupt_mask;
|
|
|
|
- dev_priv->pm.regsave.gtimr |= (~enabled_irq_mask &
|
|
|
|
- interrupt_mask);
|
|
|
|
|
|
+ if (WARN_ON(dev_priv->pm.irqs_disabled))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
|
|
dev_priv->gt_irq_mask &= ~interrupt_mask;
|
|
dev_priv->gt_irq_mask &= ~interrupt_mask;
|
|
dev_priv->gt_irq_mask |= (~enabled_irq_mask & interrupt_mask);
|
|
dev_priv->gt_irq_mask |= (~enabled_irq_mask & interrupt_mask);
|
|
@@ -167,13 +206,8 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (dev_priv->pm.irqs_disabled) {
|
|
|
|
- WARN(1, "IRQs disabled\n");
|
|
|
|
- dev_priv->pm.regsave.gen6_pmimr &= ~interrupt_mask;
|
|
|
|
- dev_priv->pm.regsave.gen6_pmimr |= (~enabled_irq_mask &
|
|
|
|
- interrupt_mask);
|
|
|
|
|
|
+ if (WARN_ON(dev_priv->pm.irqs_disabled))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
|
|
new_val = dev_priv->pm_irq_mask;
|
|
new_val = dev_priv->pm_irq_mask;
|
|
new_val &= ~interrupt_mask;
|
|
new_val &= ~interrupt_mask;
|
|
@@ -313,14 +347,8 @@ static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
|
|
|
|
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (dev_priv->pm.irqs_disabled &&
|
|
|
|
- (interrupt_mask & SDE_HOTPLUG_MASK_CPT)) {
|
|
|
|
- WARN(1, "IRQs disabled\n");
|
|
|
|
- dev_priv->pm.regsave.sdeimr &= ~interrupt_mask;
|
|
|
|
- dev_priv->pm.regsave.sdeimr |= (~enabled_irq_mask &
|
|
|
|
- interrupt_mask);
|
|
|
|
|
|
+ if (WARN_ON(dev_priv->pm.irqs_disabled))
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
|
|
I915_WRITE(SDEIMR, sdeimr);
|
|
I915_WRITE(SDEIMR, sdeimr);
|
|
POSTING_READ(SDEIMR);
|
|
POSTING_READ(SDEIMR);
|
|
@@ -503,8 +531,10 @@ __i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|
|
|
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
|
|
|
|
- status_mask & ~PIPESTAT_INT_STATUS_MASK))
|
|
|
|
|
|
+ if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
|
|
|
|
+ status_mask & ~PIPESTAT_INT_STATUS_MASK,
|
|
|
|
+ "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
|
|
|
|
+ pipe_name(pipe), enable_mask, status_mask))
|
|
return;
|
|
return;
|
|
|
|
|
|
if ((pipestat & enable_mask) == enable_mask)
|
|
if ((pipestat & enable_mask) == enable_mask)
|
|
@@ -527,8 +557,10 @@ __i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
|
|
|
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
assert_spin_locked(&dev_priv->irq_lock);
|
|
|
|
|
|
- if (WARN_ON_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
|
|
|
|
- status_mask & ~PIPESTAT_INT_STATUS_MASK))
|
|
|
|
|
|
+ if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK ||
|
|
|
|
+ status_mask & ~PIPESTAT_INT_STATUS_MASK,
|
|
|
|
+ "pipe %c: enable_mask=0x%x, status_mask=0x%x\n",
|
|
|
|
+ pipe_name(pipe), enable_mask, status_mask))
|
|
return;
|
|
return;
|
|
|
|
|
|
if ((pipestat & enable_mask) == 0)
|
|
if ((pipestat & enable_mask) == 0)
|
|
@@ -1619,6 +1651,33 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
|
|
gmbus_irq_handler(dev);
|
|
gmbus_irq_handler(dev);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void i9xx_hpd_irq_handler(struct drm_device *dev)
|
|
|
|
+{
|
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
|
|
|
+
|
|
|
|
+ if (IS_G4X(dev)) {
|
|
|
|
+ u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
|
|
|
|
+
|
|
|
|
+ intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_g4x);
|
|
|
|
+ } else {
|
|
|
|
+ u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
|
|
|
|
+
|
|
|
|
+ intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)) &&
|
|
|
|
+ hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
|
|
|
|
+ dp_aux_irq_handler(dev);
|
|
|
|
+
|
|
|
|
+ I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
|
|
|
+ /*
|
|
|
|
+ * Make sure hotplug status is cleared before we clear IIR, or else we
|
|
|
|
+ * may miss hotplug events.
|
|
|
|
+ */
|
|
|
|
+ POSTING_READ(PORT_HOTPLUG_STAT);
|
|
|
|
+}
|
|
|
|
+
|
|
static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|
static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|
{
|
|
{
|
|
struct drm_device *dev = (struct drm_device *) arg;
|
|
struct drm_device *dev = (struct drm_device *) arg;
|
|
@@ -1641,19 +1700,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
|
|
valleyview_pipestat_irq_handler(dev, iir);
|
|
valleyview_pipestat_irq_handler(dev, iir);
|
|
|
|
|
|
/* Consume port. Then clear IIR or we'll miss events */
|
|
/* Consume port. Then clear IIR or we'll miss events */
|
|
- if (iir & I915_DISPLAY_PORT_INTERRUPT) {
|
|
|
|
- u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
|
|
|
- u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
|
|
|
|
-
|
|
|
|
- intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
|
|
|
|
-
|
|
|
|
- if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
|
|
|
|
- dp_aux_irq_handler(dev);
|
|
|
|
-
|
|
|
|
- I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
|
|
|
- I915_READ(PORT_HOTPLUG_STAT);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ if (iir & I915_DISPLAY_PORT_INTERRUPT)
|
|
|
|
+ i9xx_hpd_irq_handler(dev);
|
|
|
|
|
|
if (pm_iir)
|
|
if (pm_iir)
|
|
gen6_rps_irq_handler(dev_priv, pm_iir);
|
|
gen6_rps_irq_handler(dev_priv, pm_iir);
|
|
@@ -2022,7 +2070,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
|
if (pipe_iir & GEN8_PIPE_VBLANK)
|
|
if (pipe_iir & GEN8_PIPE_VBLANK)
|
|
drm_handle_vblank(dev, pipe);
|
|
drm_handle_vblank(dev, pipe);
|
|
|
|
|
|
- if (pipe_iir & GEN8_PIPE_FLIP_DONE) {
|
|
|
|
|
|
+ if (pipe_iir & GEN8_PIPE_PRIMARY_FLIP_DONE) {
|
|
intel_prepare_page_flip(dev, pipe);
|
|
intel_prepare_page_flip(dev, pipe);
|
|
intel_finish_page_flip_plane(dev, pipe);
|
|
intel_finish_page_flip_plane(dev, pipe);
|
|
}
|
|
}
|
|
@@ -2511,6 +2559,56 @@ ring_idle(struct intel_ring_buffer *ring, u32 seqno)
|
|
i915_seqno_passed(seqno, ring_last_seqno(ring)));
|
|
i915_seqno_passed(seqno, ring_last_seqno(ring)));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool
|
|
|
|
+ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
|
|
|
|
+{
|
|
|
|
+ if (INTEL_INFO(dev)->gen >= 8) {
|
|
|
|
+ /*
|
|
|
|
+ * FIXME: gen8 semaphore support - currently we don't emit
|
|
|
|
+ * semaphores on bdw anyway, but this needs to be addressed when
|
|
|
|
+ * we merge that code.
|
|
|
|
+ */
|
|
|
|
+ return false;
|
|
|
|
+ } else {
|
|
|
|
+ ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
|
|
|
|
+ return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
|
|
|
|
+ MI_SEMAPHORE_REGISTER);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct intel_ring_buffer *
|
|
|
|
+semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
|
|
|
|
+{
|
|
|
|
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
|
|
|
+ struct intel_ring_buffer *signaller;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
|
|
|
|
+ /*
|
|
|
|
+ * FIXME: gen8 semaphore support - currently we don't emit
|
|
|
|
+ * semaphores on bdw anyway, but this needs to be addressed when
|
|
|
|
+ * we merge that code.
|
|
|
|
+ */
|
|
|
|
+ return NULL;
|
|
|
|
+ } else {
|
|
|
|
+ u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
|
|
|
|
+
|
|
|
|
+ for_each_ring(signaller, dev_priv, i) {
|
|
|
|
+ if(ring == signaller)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (sync_bits ==
|
|
|
|
+ signaller->semaphore_register[ring->id])
|
|
|
|
+ return signaller;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x\n",
|
|
|
|
+ ring->id, ipehr);
|
|
|
|
+
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
static struct intel_ring_buffer *
|
|
static struct intel_ring_buffer *
|
|
semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
|
|
semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
|
|
{
|
|
{
|
|
@@ -2519,8 +2617,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
|
|
int i;
|
|
int i;
|
|
|
|
|
|
ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
|
|
ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
|
|
- if ((ipehr & ~(0x3 << 16)) !=
|
|
|
|
- (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | MI_SEMAPHORE_REGISTER))
|
|
|
|
|
|
+ if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2552,7 +2649,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
*seqno = ioread32(ring->virtual_start + head + 4) + 1;
|
|
*seqno = ioread32(ring->virtual_start + head + 4) + 1;
|
|
- return &dev_priv->ring[(ring->id + (((ipehr >> 17) & 1) + 1)) % 3];
|
|
|
|
|
|
+ return semaphore_wait_to_signaller_ring(ring, ipehr);
|
|
}
|
|
}
|
|
|
|
|
|
static int semaphore_passed(struct intel_ring_buffer *ring)
|
|
static int semaphore_passed(struct intel_ring_buffer *ring)
|
|
@@ -2759,57 +2856,68 @@ void i915_queue_hangcheck(struct drm_device *dev)
|
|
round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
|
|
round_jiffies_up(jiffies + DRM_I915_HANGCHECK_JIFFIES));
|
|
}
|
|
}
|
|
|
|
|
|
-static void ibx_irq_preinstall(struct drm_device *dev)
|
|
|
|
|
|
+static void ibx_irq_reset(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
if (HAS_PCH_NOP(dev))
|
|
if (HAS_PCH_NOP(dev))
|
|
return;
|
|
return;
|
|
|
|
|
|
- /* south display irq */
|
|
|
|
- I915_WRITE(SDEIMR, 0xffffffff);
|
|
|
|
- /*
|
|
|
|
- * SDEIER is also touched by the interrupt handler to work around missed
|
|
|
|
- * PCH interrupts. Hence we can't update it after the interrupt handler
|
|
|
|
- * is enabled - instead we unconditionally enable all PCH interrupt
|
|
|
|
- * sources here, but then only unmask them as needed with SDEIMR.
|
|
|
|
- */
|
|
|
|
|
|
+ GEN5_IRQ_RESET(SDE);
|
|
|
|
+
|
|
|
|
+ if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
|
|
|
|
+ I915_WRITE(SERR_INT, 0xffffffff);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * SDEIER is also touched by the interrupt handler to work around missed PCH
|
|
|
|
+ * interrupts. Hence we can't update it after the interrupt handler is enabled -
|
|
|
|
+ * instead we unconditionally enable all PCH interrupt sources here, but then
|
|
|
|
+ * only unmask them as needed with SDEIMR.
|
|
|
|
+ *
|
|
|
|
+ * This function needs to be called before interrupts are enabled.
|
|
|
|
+ */
|
|
|
|
+static void ibx_irq_pre_postinstall(struct drm_device *dev)
|
|
|
|
+{
|
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+
|
|
|
|
+ if (HAS_PCH_NOP(dev))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ WARN_ON(I915_READ(SDEIER) != 0);
|
|
I915_WRITE(SDEIER, 0xffffffff);
|
|
I915_WRITE(SDEIER, 0xffffffff);
|
|
POSTING_READ(SDEIER);
|
|
POSTING_READ(SDEIER);
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen5_gt_irq_preinstall(struct drm_device *dev)
|
|
|
|
|
|
+static void gen5_gt_irq_reset(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
- /* and GT */
|
|
|
|
- I915_WRITE(GTIMR, 0xffffffff);
|
|
|
|
- I915_WRITE(GTIER, 0x0);
|
|
|
|
- POSTING_READ(GTIER);
|
|
|
|
-
|
|
|
|
- if (INTEL_INFO(dev)->gen >= 6) {
|
|
|
|
- /* and PM */
|
|
|
|
- I915_WRITE(GEN6_PMIMR, 0xffffffff);
|
|
|
|
- I915_WRITE(GEN6_PMIER, 0x0);
|
|
|
|
- POSTING_READ(GEN6_PMIER);
|
|
|
|
- }
|
|
|
|
|
|
+ GEN5_IRQ_RESET(GT);
|
|
|
|
+ if (INTEL_INFO(dev)->gen >= 6)
|
|
|
|
+ GEN5_IRQ_RESET(GEN6_PM);
|
|
}
|
|
}
|
|
|
|
|
|
/* drm_dma.h hooks
|
|
/* drm_dma.h hooks
|
|
*/
|
|
*/
|
|
-static void ironlake_irq_preinstall(struct drm_device *dev)
|
|
|
|
|
|
+static void ironlake_irq_reset(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
- I915_WRITE(HWSTAM, 0xeffe);
|
|
|
|
|
|
+ I915_WRITE(HWSTAM, 0xffffffff);
|
|
|
|
|
|
- I915_WRITE(DEIMR, 0xffffffff);
|
|
|
|
- I915_WRITE(DEIER, 0x0);
|
|
|
|
- POSTING_READ(DEIER);
|
|
|
|
|
|
+ GEN5_IRQ_RESET(DE);
|
|
|
|
+ if (IS_GEN7(dev))
|
|
|
|
+ I915_WRITE(GEN7_ERR_INT, 0xffffffff);
|
|
|
|
|
|
- gen5_gt_irq_preinstall(dev);
|
|
|
|
|
|
+ gen5_gt_irq_reset(dev);
|
|
|
|
+
|
|
|
|
+ ibx_irq_reset(dev);
|
|
|
|
+}
|
|
|
|
|
|
- ibx_irq_preinstall(dev);
|
|
|
|
|
|
+static void ironlake_irq_preinstall(struct drm_device *dev)
|
|
|
|
+{
|
|
|
|
+ ironlake_irq_reset(dev);
|
|
}
|
|
}
|
|
|
|
|
|
static void valleyview_irq_preinstall(struct drm_device *dev)
|
|
static void valleyview_irq_preinstall(struct drm_device *dev)
|
|
@@ -2827,7 +2935,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
|
|
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
|
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
|
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
|
I915_WRITE(GTIIR, I915_READ(GTIIR));
|
|
|
|
|
|
- gen5_gt_irq_preinstall(dev);
|
|
|
|
|
|
+ gen5_gt_irq_reset(dev);
|
|
|
|
|
|
I915_WRITE(DPINVGTT, 0xff);
|
|
I915_WRITE(DPINVGTT, 0xff);
|
|
|
|
|
|
@@ -2841,7 +2949,7 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
|
|
POSTING_READ(VLV_IER);
|
|
POSTING_READ(VLV_IER);
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen8_irq_preinstall(struct drm_device *dev)
|
|
|
|
|
|
+static void gen8_irq_reset(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
int pipe;
|
|
int pipe;
|
|
@@ -2849,43 +2957,24 @@ static void gen8_irq_preinstall(struct drm_device *dev)
|
|
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
|
I915_WRITE(GEN8_MASTER_IRQ, 0);
|
|
POSTING_READ(GEN8_MASTER_IRQ);
|
|
POSTING_READ(GEN8_MASTER_IRQ);
|
|
|
|
|
|
- /* IIR can theoretically queue up two events. Be paranoid */
|
|
|
|
-#define GEN8_IRQ_INIT_NDX(type, which) do { \
|
|
|
|
- I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
|
|
|
|
- POSTING_READ(GEN8_##type##_IMR(which)); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IER(which), 0); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
|
|
|
- POSTING_READ(GEN8_##type##_IIR(which)); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
|
|
|
- } while (0)
|
|
|
|
-
|
|
|
|
-#define GEN8_IRQ_INIT(type) do { \
|
|
|
|
- I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
|
|
|
|
- POSTING_READ(GEN8_##type##_IMR); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IER, 0); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
|
|
|
|
- POSTING_READ(GEN8_##type##_IIR); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
|
|
|
|
- } while (0)
|
|
|
|
-
|
|
|
|
- GEN8_IRQ_INIT_NDX(GT, 0);
|
|
|
|
- GEN8_IRQ_INIT_NDX(GT, 1);
|
|
|
|
- GEN8_IRQ_INIT_NDX(GT, 2);
|
|
|
|
- GEN8_IRQ_INIT_NDX(GT, 3);
|
|
|
|
|
|
+ GEN8_IRQ_RESET_NDX(GT, 0);
|
|
|
|
+ GEN8_IRQ_RESET_NDX(GT, 1);
|
|
|
|
+ GEN8_IRQ_RESET_NDX(GT, 2);
|
|
|
|
+ GEN8_IRQ_RESET_NDX(GT, 3);
|
|
|
|
|
|
- for_each_pipe(pipe) {
|
|
|
|
- GEN8_IRQ_INIT_NDX(DE_PIPE, pipe);
|
|
|
|
- }
|
|
|
|
|
|
+ for_each_pipe(pipe)
|
|
|
|
+ GEN8_IRQ_RESET_NDX(DE_PIPE, pipe);
|
|
|
|
|
|
- GEN8_IRQ_INIT(DE_PORT);
|
|
|
|
- GEN8_IRQ_INIT(DE_MISC);
|
|
|
|
- GEN8_IRQ_INIT(PCU);
|
|
|
|
-#undef GEN8_IRQ_INIT
|
|
|
|
-#undef GEN8_IRQ_INIT_NDX
|
|
|
|
|
|
+ GEN5_IRQ_RESET(GEN8_DE_PORT_);
|
|
|
|
+ GEN5_IRQ_RESET(GEN8_DE_MISC_);
|
|
|
|
+ GEN5_IRQ_RESET(GEN8_PCU_);
|
|
|
|
|
|
- POSTING_READ(GEN8_PCU_IIR);
|
|
|
|
|
|
+ ibx_irq_reset(dev);
|
|
|
|
+}
|
|
|
|
|
|
- ibx_irq_preinstall(dev);
|
|
|
|
|
|
+static void gen8_irq_preinstall(struct drm_device *dev)
|
|
|
|
+{
|
|
|
|
+ gen8_irq_reset(dev);
|
|
}
|
|
}
|
|
|
|
|
|
static void ibx_hpd_irq_setup(struct drm_device *dev)
|
|
static void ibx_hpd_irq_setup(struct drm_device *dev)
|
|
@@ -2931,15 +3020,12 @@ static void ibx_irq_postinstall(struct drm_device *dev)
|
|
if (HAS_PCH_NOP(dev))
|
|
if (HAS_PCH_NOP(dev))
|
|
return;
|
|
return;
|
|
|
|
|
|
- if (HAS_PCH_IBX(dev)) {
|
|
|
|
|
|
+ if (HAS_PCH_IBX(dev))
|
|
mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
|
|
mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
|
|
- } else {
|
|
|
|
|
|
+ else
|
|
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
|
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
|
|
|
|
|
- I915_WRITE(SERR_INT, I915_READ(SERR_INT));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- I915_WRITE(SDEIIR, I915_READ(SDEIIR));
|
|
|
|
|
|
+ GEN5_ASSERT_IIR_IS_ZERO(SDEIIR);
|
|
I915_WRITE(SDEIMR, ~mask);
|
|
I915_WRITE(SDEIMR, ~mask);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2965,10 +3051,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
|
|
gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
|
|
gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
|
|
}
|
|
}
|
|
|
|
|
|
- I915_WRITE(GTIIR, I915_READ(GTIIR));
|
|
|
|
- I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
|
|
|
|
- I915_WRITE(GTIER, gt_irqs);
|
|
|
|
- POSTING_READ(GTIER);
|
|
|
|
|
|
+ GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs);
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 6) {
|
|
if (INTEL_INFO(dev)->gen >= 6) {
|
|
pm_irqs |= dev_priv->pm_rps_events;
|
|
pm_irqs |= dev_priv->pm_rps_events;
|
|
@@ -2977,10 +3060,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
|
|
pm_irqs |= PM_VEBOX_USER_INTERRUPT;
|
|
pm_irqs |= PM_VEBOX_USER_INTERRUPT;
|
|
|
|
|
|
dev_priv->pm_irq_mask = 0xffffffff;
|
|
dev_priv->pm_irq_mask = 0xffffffff;
|
|
- I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
|
|
|
|
- I915_WRITE(GEN6_PMIMR, dev_priv->pm_irq_mask);
|
|
|
|
- I915_WRITE(GEN6_PMIER, pm_irqs);
|
|
|
|
- POSTING_READ(GEN6_PMIER);
|
|
|
|
|
|
+ GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_irq_mask, pm_irqs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2997,8 +3077,6 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
|
|
DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB);
|
|
DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB);
|
|
extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
|
|
extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB |
|
|
DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB);
|
|
DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB);
|
|
-
|
|
|
|
- I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
|
|
|
|
} else {
|
|
} else {
|
|
display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
|
|
display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
|
|
DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
|
|
DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
|
|
@@ -3011,11 +3089,11 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
|
|
|
|
|
|
dev_priv->irq_mask = ~display_mask;
|
|
dev_priv->irq_mask = ~display_mask;
|
|
|
|
|
|
- /* should always can generate irq */
|
|
|
|
- I915_WRITE(DEIIR, I915_READ(DEIIR));
|
|
|
|
- I915_WRITE(DEIMR, dev_priv->irq_mask);
|
|
|
|
- I915_WRITE(DEIER, display_mask | extra_mask);
|
|
|
|
- POSTING_READ(DEIER);
|
|
|
|
|
|
+ I915_WRITE(HWSTAM, 0xeffe);
|
|
|
|
+
|
|
|
|
+ ibx_irq_pre_postinstall(dev);
|
|
|
|
+
|
|
|
|
+ GEN5_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask);
|
|
|
|
|
|
gen5_gt_irq_postinstall(dev);
|
|
gen5_gt_irq_postinstall(dev);
|
|
|
|
|
|
@@ -3175,21 +3253,14 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
|
|
GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT
|
|
GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT
|
|
};
|
|
};
|
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++) {
|
|
|
|
- u32 tmp = I915_READ(GEN8_GT_IIR(i));
|
|
|
|
- if (tmp)
|
|
|
|
- DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n",
|
|
|
|
- i, tmp);
|
|
|
|
- I915_WRITE(GEN8_GT_IMR(i), ~gt_interrupts[i]);
|
|
|
|
- I915_WRITE(GEN8_GT_IER(i), gt_interrupts[i]);
|
|
|
|
- }
|
|
|
|
- POSTING_READ(GEN8_GT_IER(0));
|
|
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++)
|
|
|
|
+ GEN8_IRQ_INIT_NDX(GT, i, ~gt_interrupts[i], gt_interrupts[i]);
|
|
}
|
|
}
|
|
|
|
|
|
static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
|
|
static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
|
|
{
|
|
{
|
|
struct drm_device *dev = dev_priv->dev;
|
|
struct drm_device *dev = dev_priv->dev;
|
|
- uint32_t de_pipe_masked = GEN8_PIPE_FLIP_DONE |
|
|
|
|
|
|
+ uint32_t de_pipe_masked = GEN8_PIPE_PRIMARY_FLIP_DONE |
|
|
GEN8_PIPE_CDCLK_CRC_DONE |
|
|
GEN8_PIPE_CDCLK_CRC_DONE |
|
|
GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
|
|
GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
|
|
uint32_t de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
|
|
uint32_t de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
|
|
@@ -3199,25 +3270,19 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
|
|
dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
|
|
dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked;
|
|
dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
|
|
dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked;
|
|
|
|
|
|
- for_each_pipe(pipe) {
|
|
|
|
- u32 tmp = I915_READ(GEN8_DE_PIPE_IIR(pipe));
|
|
|
|
- if (tmp)
|
|
|
|
- DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n",
|
|
|
|
- pipe, tmp);
|
|
|
|
- I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
|
|
|
|
- I915_WRITE(GEN8_DE_PIPE_IER(pipe), de_pipe_enables);
|
|
|
|
- }
|
|
|
|
- POSTING_READ(GEN8_DE_PIPE_ISR(0));
|
|
|
|
|
|
+ for_each_pipe(pipe)
|
|
|
|
+ GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, dev_priv->de_irq_mask[pipe],
|
|
|
|
+ de_pipe_enables);
|
|
|
|
|
|
- I915_WRITE(GEN8_DE_PORT_IMR, ~GEN8_AUX_CHANNEL_A);
|
|
|
|
- I915_WRITE(GEN8_DE_PORT_IER, GEN8_AUX_CHANNEL_A);
|
|
|
|
- POSTING_READ(GEN8_DE_PORT_IER);
|
|
|
|
|
|
+ GEN5_IRQ_INIT(GEN8_DE_PORT_, ~GEN8_AUX_CHANNEL_A, GEN8_AUX_CHANNEL_A);
|
|
}
|
|
}
|
|
|
|
|
|
static int gen8_irq_postinstall(struct drm_device *dev)
|
|
static int gen8_irq_postinstall(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
|
|
|
|
+ ibx_irq_pre_postinstall(dev);
|
|
|
|
+
|
|
gen8_gt_irq_postinstall(dev_priv);
|
|
gen8_gt_irq_postinstall(dev_priv);
|
|
gen8_de_irq_postinstall(dev_priv);
|
|
gen8_de_irq_postinstall(dev_priv);
|
|
|
|
|
|
@@ -3232,41 +3297,13 @@ static int gen8_irq_postinstall(struct drm_device *dev)
|
|
static void gen8_irq_uninstall(struct drm_device *dev)
|
|
static void gen8_irq_uninstall(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- int pipe;
|
|
|
|
|
|
|
|
if (!dev_priv)
|
|
if (!dev_priv)
|
|
return;
|
|
return;
|
|
|
|
|
|
- I915_WRITE(GEN8_MASTER_IRQ, 0);
|
|
|
|
-
|
|
|
|
-#define GEN8_IRQ_FINI_NDX(type, which) do { \
|
|
|
|
- I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IER(which), 0); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff); \
|
|
|
|
- } while (0)
|
|
|
|
-
|
|
|
|
-#define GEN8_IRQ_FINI(type) do { \
|
|
|
|
- I915_WRITE(GEN8_##type##_IMR, 0xffffffff); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IER, 0); \
|
|
|
|
- I915_WRITE(GEN8_##type##_IIR, 0xffffffff); \
|
|
|
|
- } while (0)
|
|
|
|
-
|
|
|
|
- GEN8_IRQ_FINI_NDX(GT, 0);
|
|
|
|
- GEN8_IRQ_FINI_NDX(GT, 1);
|
|
|
|
- GEN8_IRQ_FINI_NDX(GT, 2);
|
|
|
|
- GEN8_IRQ_FINI_NDX(GT, 3);
|
|
|
|
-
|
|
|
|
- for_each_pipe(pipe) {
|
|
|
|
- GEN8_IRQ_FINI_NDX(DE_PIPE, pipe);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- GEN8_IRQ_FINI(DE_PORT);
|
|
|
|
- GEN8_IRQ_FINI(DE_MISC);
|
|
|
|
- GEN8_IRQ_FINI(PCU);
|
|
|
|
-#undef GEN8_IRQ_FINI
|
|
|
|
-#undef GEN8_IRQ_FINI_NDX
|
|
|
|
|
|
+ intel_hpd_irq_uninstall(dev_priv);
|
|
|
|
|
|
- POSTING_READ(GEN8_PCU_IIR);
|
|
|
|
|
|
+ gen8_irq_reset(dev);
|
|
}
|
|
}
|
|
|
|
|
|
static void valleyview_irq_uninstall(struct drm_device *dev)
|
|
static void valleyview_irq_uninstall(struct drm_device *dev)
|
|
@@ -3309,26 +3346,7 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
|
|
|
|
|
|
intel_hpd_irq_uninstall(dev_priv);
|
|
intel_hpd_irq_uninstall(dev_priv);
|
|
|
|
|
|
- I915_WRITE(HWSTAM, 0xffffffff);
|
|
|
|
-
|
|
|
|
- I915_WRITE(DEIMR, 0xffffffff);
|
|
|
|
- I915_WRITE(DEIER, 0x0);
|
|
|
|
- I915_WRITE(DEIIR, I915_READ(DEIIR));
|
|
|
|
- if (IS_GEN7(dev))
|
|
|
|
- I915_WRITE(GEN7_ERR_INT, I915_READ(GEN7_ERR_INT));
|
|
|
|
-
|
|
|
|
- I915_WRITE(GTIMR, 0xffffffff);
|
|
|
|
- I915_WRITE(GTIER, 0x0);
|
|
|
|
- I915_WRITE(GTIIR, I915_READ(GTIIR));
|
|
|
|
-
|
|
|
|
- if (HAS_PCH_NOP(dev))
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- I915_WRITE(SDEIMR, 0xffffffff);
|
|
|
|
- I915_WRITE(SDEIER, 0x0);
|
|
|
|
- I915_WRITE(SDEIIR, I915_READ(SDEIIR));
|
|
|
|
- if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
|
|
|
|
- I915_WRITE(SERR_INT, I915_READ(SERR_INT));
|
|
|
|
|
|
+ ironlake_irq_reset(dev);
|
|
}
|
|
}
|
|
|
|
|
|
static void i8xx_irq_preinstall(struct drm_device * dev)
|
|
static void i8xx_irq_preinstall(struct drm_device * dev)
|
|
@@ -3636,16 +3654,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|
break;
|
|
break;
|
|
|
|
|
|
/* Consume port. Then clear IIR or we'll miss events */
|
|
/* Consume port. Then clear IIR or we'll miss events */
|
|
- if ((I915_HAS_HOTPLUG(dev)) &&
|
|
|
|
- (iir & I915_DISPLAY_PORT_INTERRUPT)) {
|
|
|
|
- u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
|
|
|
- u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_I915;
|
|
|
|
-
|
|
|
|
- intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
|
|
|
|
-
|
|
|
|
- I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
|
|
|
- POSTING_READ(PORT_HOTPLUG_STAT);
|
|
|
|
- }
|
|
|
|
|
|
+ if (I915_HAS_HOTPLUG(dev) &&
|
|
|
|
+ iir & I915_DISPLAY_PORT_INTERRUPT)
|
|
|
|
+ i9xx_hpd_irq_handler(dev);
|
|
|
|
|
|
I915_WRITE(IIR, iir & ~flip_mask);
|
|
I915_WRITE(IIR, iir & ~flip_mask);
|
|
new_iir = I915_READ(IIR); /* Flush posted writes */
|
|
new_iir = I915_READ(IIR); /* Flush posted writes */
|
|
@@ -3879,22 +3890,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|
ret = IRQ_HANDLED;
|
|
ret = IRQ_HANDLED;
|
|
|
|
|
|
/* Consume port. Then clear IIR or we'll miss events */
|
|
/* Consume port. Then clear IIR or we'll miss events */
|
|
- if (iir & I915_DISPLAY_PORT_INTERRUPT) {
|
|
|
|
- u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
|
|
|
|
- u32 hotplug_trigger = hotplug_status & (IS_G4X(dev) ?
|
|
|
|
- HOTPLUG_INT_STATUS_G4X :
|
|
|
|
- HOTPLUG_INT_STATUS_I915);
|
|
|
|
-
|
|
|
|
- intel_hpd_irq_handler(dev, hotplug_trigger,
|
|
|
|
- IS_G4X(dev) ? hpd_status_g4x : hpd_status_i915);
|
|
|
|
-
|
|
|
|
- if (IS_G4X(dev) &&
|
|
|
|
- (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X))
|
|
|
|
- dp_aux_irq_handler(dev);
|
|
|
|
-
|
|
|
|
- I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
|
|
|
- I915_READ(PORT_HOTPLUG_STAT);
|
|
|
|
- }
|
|
|
|
|
|
+ if (iir & I915_DISPLAY_PORT_INTERRUPT)
|
|
|
|
+ i9xx_hpd_irq_handler(dev);
|
|
|
|
|
|
I915_WRITE(IIR, iir & ~flip_mask);
|
|
I915_WRITE(IIR, iir & ~flip_mask);
|
|
new_iir = I915_READ(IIR); /* Flush posted writes */
|
|
new_iir = I915_READ(IIR); /* Flush posted writes */
|
|
@@ -4121,57 +4118,20 @@ void intel_hpd_init(struct drm_device *dev)
|
|
}
|
|
}
|
|
|
|
|
|
/* Disable interrupts so we can allow runtime PM. */
|
|
/* Disable interrupts so we can allow runtime PM. */
|
|
-void hsw_runtime_pm_disable_interrupts(struct drm_device *dev)
|
|
|
|
|
|
+void intel_runtime_pm_disable_interrupts(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- unsigned long irqflags;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
|
|
|
-
|
|
|
|
- dev_priv->pm.regsave.deimr = I915_READ(DEIMR);
|
|
|
|
- dev_priv->pm.regsave.sdeimr = I915_READ(SDEIMR);
|
|
|
|
- dev_priv->pm.regsave.gtimr = I915_READ(GTIMR);
|
|
|
|
- dev_priv->pm.regsave.gtier = I915_READ(GTIER);
|
|
|
|
- dev_priv->pm.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
|
|
|
|
-
|
|
|
|
- ironlake_disable_display_irq(dev_priv, 0xffffffff);
|
|
|
|
- ibx_disable_display_interrupt(dev_priv, 0xffffffff);
|
|
|
|
- ilk_disable_gt_irq(dev_priv, 0xffffffff);
|
|
|
|
- snb_disable_pm_irq(dev_priv, 0xffffffff);
|
|
|
|
|
|
|
|
|
|
+ dev->driver->irq_uninstall(dev);
|
|
dev_priv->pm.irqs_disabled = true;
|
|
dev_priv->pm.irqs_disabled = true;
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* Restore interrupts so we can recover from runtime PM. */
|
|
/* Restore interrupts so we can recover from runtime PM. */
|
|
-void hsw_runtime_pm_restore_interrupts(struct drm_device *dev)
|
|
|
|
|
|
+void intel_runtime_pm_restore_interrupts(struct drm_device *dev)
|
|
{
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- unsigned long irqflags;
|
|
|
|
- uint32_t val;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
|
|
|
|
-
|
|
|
|
- val = I915_READ(DEIMR);
|
|
|
|
- WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
|
|
|
|
-
|
|
|
|
- val = I915_READ(SDEIMR);
|
|
|
|
- WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
|
|
|
|
-
|
|
|
|
- val = I915_READ(GTIMR);
|
|
|
|
- WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
|
|
|
|
-
|
|
|
|
- val = I915_READ(GEN6_PMIMR);
|
|
|
|
- WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
|
|
|
|
|
|
|
|
dev_priv->pm.irqs_disabled = false;
|
|
dev_priv->pm.irqs_disabled = false;
|
|
-
|
|
|
|
- ironlake_enable_display_irq(dev_priv, ~dev_priv->pm.regsave.deimr);
|
|
|
|
- ibx_enable_display_interrupt(dev_priv, ~dev_priv->pm.regsave.sdeimr);
|
|
|
|
- ilk_enable_gt_irq(dev_priv, ~dev_priv->pm.regsave.gtimr);
|
|
|
|
- snb_enable_pm_irq(dev_priv, ~dev_priv->pm.regsave.gen6_pmimr);
|
|
|
|
- I915_WRITE(GTIER, dev_priv->pm.regsave.gtier);
|
|
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
|
|
|
|
|
|
+ dev->driver->irq_preinstall(dev);
|
|
|
|
+ dev->driver->irq_postinstall(dev);
|
|
}
|
|
}
|