aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2010-05-27 17:26:45 -0400
committerEric Anholt <eric@anholt.net>2010-06-04 20:21:41 -0400
commitc496fa1fff0248ef8cd637efb52b70dea7afaa9d (patch)
treebbdc1b56f61f12d68509a2f927a9c777dc35eee7 /drivers/gpu
parentf458823b864c6def488f951a79986fa205aba4f1 (diff)
drm/i915/gen4: Fix interrupt setup ordering
Unmask, then enable interrupts, then enable interrupt sources; matches PCH ordering. The old way (sources, enable, unmask) gives a window during which interrupt conditions would appear in ISR but would never reach IIR and thus never raise an IRQ. Since interrupts only trigger on rising edges in ISR, this would lead to conditions where (for example) output hotplugging would never fire an interrupt because it was already stuck on in ISR. Also, since we know IIR and PIPExSTAT have been cleared during irq_preinstall, don't clear them again during irq_postinstall, nothing good can come of that. Signed-off-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c50
1 files changed, 23 insertions, 27 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2479be001e40..e9710a7005d4 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1387,29 +1387,10 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
1387 dev_priv->pipestat[1] = 0; 1387 dev_priv->pipestat[1] = 0;
1388 1388
1389 if (I915_HAS_HOTPLUG(dev)) { 1389 if (I915_HAS_HOTPLUG(dev)) {
1390 u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
1391
1392 /* Note HDMI and DP share bits */
1393 if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
1394 hotplug_en |= HDMIB_HOTPLUG_INT_EN;
1395 if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
1396 hotplug_en |= HDMIC_HOTPLUG_INT_EN;
1397 if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
1398 hotplug_en |= HDMID_HOTPLUG_INT_EN;
1399 if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
1400 hotplug_en |= SDVOC_HOTPLUG_INT_EN;
1401 if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
1402 hotplug_en |= SDVOB_HOTPLUG_INT_EN;
1403 if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
1404 hotplug_en |= CRT_HOTPLUG_INT_EN;
1405 /* Ignore TV since it's buggy */
1406
1407 I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
1408
1409 /* Enable in IER... */ 1390 /* Enable in IER... */
1410 enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 1391 enable_mask |= I915_DISPLAY_PORT_INTERRUPT;
1411 /* and unmask in IMR */ 1392 /* and unmask in IMR */
1412 i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT); 1393 dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT;
1413 } 1394 }
1414 1395
1415 /* 1396 /*
@@ -1427,16 +1408,31 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
1427 } 1408 }
1428 I915_WRITE(EMR, error_mask); 1409 I915_WRITE(EMR, error_mask);
1429 1410
1430 /* Disable pipe interrupt enables, clear pending pipe status */
1431 I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
1432 I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
1433 /* Clear pending interrupt status */
1434 I915_WRITE(IIR, I915_READ(IIR));
1435
1436 I915_WRITE(IER, enable_mask);
1437 I915_WRITE(IMR, dev_priv->irq_mask_reg); 1411 I915_WRITE(IMR, dev_priv->irq_mask_reg);
1412 I915_WRITE(IER, enable_mask);
1438 (void) I915_READ(IER); 1413 (void) I915_READ(IER);
1439 1414
1415 if (I915_HAS_HOTPLUG(dev)) {
1416 u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);
1417
1418 /* Note HDMI and DP share bits */
1419 if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)
1420 hotplug_en |= HDMIB_HOTPLUG_INT_EN;
1421 if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS)
1422 hotplug_en |= HDMIC_HOTPLUG_INT_EN;
1423 if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS)
1424 hotplug_en |= HDMID_HOTPLUG_INT_EN;
1425 if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS)
1426 hotplug_en |= SDVOC_HOTPLUG_INT_EN;
1427 if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS)
1428 hotplug_en |= SDVOB_HOTPLUG_INT_EN;
1429 if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS)
1430 hotplug_en |= CRT_HOTPLUG_INT_EN;
1431 /* Ignore TV since it's buggy */
1432
1433 I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
1434 }
1435
1440 opregion_enable_asle(dev); 1436 opregion_enable_asle(dev);
1441 1437
1442 return 0; 1438 return 0;