|
@@ -2028,7 +2028,13 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
|
|
|
|
|
|
/* south display irq */
|
|
|
I915_WRITE(SDEIMR, 0xffffffff);
|
|
|
- I915_WRITE(SDEIER, 0x0);
|
|
|
+ /*
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+ I915_WRITE(SDEIER, 0xffffffff);
|
|
|
POSTING_READ(SDEIER);
|
|
|
}
|
|
|
|
|
@@ -2064,18 +2070,30 @@ static void valleyview_irq_preinstall(struct drm_device *dev)
|
|
|
POSTING_READ(VLV_IER);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Enable digital hotplug on the PCH, and configure the DP short pulse
|
|
|
- * duration to 2ms (which is the minimum in the Display Port spec)
|
|
|
- *
|
|
|
- * This register is the same on all known PCH chips.
|
|
|
- */
|
|
|
-
|
|
|
-static void ibx_enable_hotplug(struct drm_device *dev)
|
|
|
+static void ibx_hpd_irq_setup(struct drm_device *dev)
|
|
|
{
|
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
- u32 hotplug;
|
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
+ struct intel_encoder *intel_encoder;
|
|
|
+ u32 mask = ~I915_READ(SDEIMR);
|
|
|
+ u32 hotplug;
|
|
|
+
|
|
|
+ if (HAS_PCH_IBX(dev)) {
|
|
|
+ list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
|
|
+ mask |= hpd_ibx[intel_encoder->hpd_pin];
|
|
|
+ } else {
|
|
|
+ list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
|
|
+ mask |= hpd_cpt[intel_encoder->hpd_pin];
|
|
|
+ }
|
|
|
|
|
|
+ I915_WRITE(SDEIMR, ~mask);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Enable digital hotplug on the PCH, and configure the DP short pulse
|
|
|
+ * duration to 2ms (which is the minimum in the Display Port spec)
|
|
|
+ *
|
|
|
+ * This register is the same on all known PCH chips.
|
|
|
+ */
|
|
|
hotplug = I915_READ(PCH_PORT_HOTPLUG);
|
|
|
hotplug &= ~(PORTD_PULSE_DURATION_MASK|PORTC_PULSE_DURATION_MASK|PORTB_PULSE_DURATION_MASK);
|
|
|
hotplug |= PORTD_HOTPLUG_ENABLE | PORTD_PULSE_DURATION_2ms;
|
|
@@ -2087,27 +2105,14 @@ static void ibx_enable_hotplug(struct drm_device *dev)
|
|
|
static void ibx_irq_postinstall(struct drm_device *dev)
|
|
|
{
|
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
- struct drm_mode_config *mode_config = &dev->mode_config;
|
|
|
- struct intel_encoder *intel_encoder;
|
|
|
- u32 mask = I915_READ(SDEIER);
|
|
|
+ u32 mask;
|
|
|
|
|
|
- if (HAS_PCH_IBX(dev)) {
|
|
|
- mask &= ~SDE_HOTPLUG_MASK;
|
|
|
- list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
|
|
- mask |= hpd_ibx[intel_encoder->hpd_pin];
|
|
|
- mask |= SDE_GMBUS | SDE_AUX_MASK;
|
|
|
- } else {
|
|
|
- mask &= ~SDE_HOTPLUG_MASK_CPT;
|
|
|
- list_for_each_entry(intel_encoder, &mode_config->encoder_list, base.head)
|
|
|
- mask |= hpd_cpt[intel_encoder->hpd_pin];
|
|
|
- mask |= SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
|
|
- }
|
|
|
+ if (HAS_PCH_IBX(dev))
|
|
|
+ mask = SDE_GMBUS | SDE_AUX_MASK;
|
|
|
+ else
|
|
|
+ mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
|
|
|
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
|
|
|
I915_WRITE(SDEIMR, ~mask);
|
|
|
- I915_WRITE(SDEIER, mask);
|
|
|
- POSTING_READ(SDEIER);
|
|
|
-
|
|
|
- ibx_enable_hotplug(dev);
|
|
|
}
|
|
|
|
|
|
static int ironlake_irq_postinstall(struct drm_device *dev)
|
|
@@ -2977,6 +2982,7 @@ void intel_irq_init(struct drm_device *dev)
|
|
|
dev->driver->irq_uninstall = ironlake_irq_uninstall;
|
|
|
dev->driver->enable_vblank = ivybridge_enable_vblank;
|
|
|
dev->driver->disable_vblank = ivybridge_disable_vblank;
|
|
|
+ dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
|
|
|
} else if (HAS_PCH_SPLIT(dev)) {
|
|
|
dev->driver->irq_handler = ironlake_irq_handler;
|
|
|
dev->driver->irq_preinstall = ironlake_irq_preinstall;
|
|
@@ -2984,6 +2990,7 @@ void intel_irq_init(struct drm_device *dev)
|
|
|
dev->driver->irq_uninstall = ironlake_irq_uninstall;
|
|
|
dev->driver->enable_vblank = ironlake_enable_vblank;
|
|
|
dev->driver->disable_vblank = ironlake_disable_vblank;
|
|
|
+ dev_priv->display.hpd_irq_setup = ibx_hpd_irq_setup;
|
|
|
} else {
|
|
|
if (INTEL_INFO(dev)->gen == 2) {
|
|
|
dev->driver->irq_preinstall = i8xx_irq_preinstall;
|