aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2018-06-14 13:56:25 -0400
committerRodrigo Vivi <rodrigo.vivi@intel.com>2018-07-09 17:36:47 -0400
commit96a85cc517a9ee4ae5e8d7f5a36cba05023784eb (patch)
treebaeaca6ea93d33df91fc7c3c683faf6162d6c3f9 /drivers
parent1e4b044d22517cae7047c99038abb444423243ca (diff)
drm/i915: Fix hotplug irq ack on i965/g4x
Just like with PIPESTAT, the edge triggered IIR on i965/g4x also causes problems for hotplug interrupts. To make sure we don't get the IIR port interrupt bit stuck low with the ISR bit high we must force an edge in ISR. Unfortunately we can't borrow the PIPESTAT trick and toggle the enable bits in PORT_HOTPLUG_EN as that act itself generates hotplug interrupts. Instead we just have to loop until we've cleared PORT_HOTPLUG_STAT, or we just give up and WARN. v2: Don't frob with PORT_HOTPLUG_EN Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180614175625.1615-1-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak <imre.deak@intel.com> (cherry picked from commit 0ba7c51a6fd80a89236f6ceb52e63f8a7f62bfd3) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4a02747ac658..c16cb025755e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1998,10 +1998,38 @@ static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv,
1998 1998
1999static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv) 1999static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
2000{ 2000{
2001 u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); 2001 u32 hotplug_status = 0, hotplug_status_mask;
2002 int i;
2003
2004 if (IS_G4X(dev_priv) ||
2005 IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
2006 hotplug_status_mask = HOTPLUG_INT_STATUS_G4X |
2007 DP_AUX_CHANNEL_MASK_INT_STATUS_G4X;
2008 else
2009 hotplug_status_mask = HOTPLUG_INT_STATUS_I915;
2002 2010
2003 if (hotplug_status) 2011 /*
2012 * We absolutely have to clear all the pending interrupt
2013 * bits in PORT_HOTPLUG_STAT. Otherwise the ISR port
2014 * interrupt bit won't have an edge, and the i965/g4x
2015 * edge triggered IIR will not notice that an interrupt
2016 * is still pending. We can't use PORT_HOTPLUG_EN to
2017 * guarantee the edge as the act of toggling the enable
2018 * bits can itself generate a new hotplug interrupt :(
2019 */
2020 for (i = 0; i < 10; i++) {
2021 u32 tmp = I915_READ(PORT_HOTPLUG_STAT) & hotplug_status_mask;
2022
2023 if (tmp == 0)
2024 return hotplug_status;
2025
2026 hotplug_status |= tmp;
2004 I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); 2027 I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
2028 }
2029
2030 WARN_ONCE(1,
2031 "PORT_HOTPLUG_STAT did not clear (0x%08x)\n",
2032 I915_READ(PORT_HOTPLUG_STAT));
2005 2033
2006 return hotplug_status; 2034 return hotplug_status;
2007} 2035}