aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2010-05-24 16:46:29 -0400
committerEric Anholt <eric@anholt.net>2010-05-26 16:53:20 -0400
commit7a772c492fcfffae812ffca78a628e76fa57fe58 (patch)
tree1e837133d9b386cc11773f1ba3ed265b6907068c /drivers/gpu
parent734b4157b367d66405f7dab80085d17c9c8dd3b5 (diff)
drm/i915/gen4: Extra CRT hotplug paranoia
Disable the CRT plug interrupt while doing the force cycle, explicitly clear any CRT interrupt we may have generated, and restore when done. Should mitigate interrupt storms from hotplug detection. 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_reg.h1
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c21
2 files changed, 14 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 784cf3c914e9..7a726840efa7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1067,7 +1067,6 @@
1067#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) 1067#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
1068#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) 1068#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
1069#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ 1069#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
1070#define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f
1071 1070
1072#define PORT_HOTPLUG_STAT 0x61114 1071#define PORT_HOTPLUG_STAT 0x61114
1073#define HDMIB_HOTPLUG_INT_STATUS (1 << 29) 1072#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index d5c130202396..22ff38455731 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -217,7 +217,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
217{ 217{
218 struct drm_device *dev = connector->dev; 218 struct drm_device *dev = connector->dev;
219 struct drm_i915_private *dev_priv = dev->dev_private; 219 struct drm_i915_private *dev_priv = dev->dev_private;
220 u32 hotplug_en; 220 u32 hotplug_en, orig, stat;
221 bool ret = false;
221 int i, tries = 0; 222 int i, tries = 0;
222 223
223 if (HAS_PCH_SPLIT(dev)) 224 if (HAS_PCH_SPLIT(dev))
@@ -232,8 +233,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
232 tries = 2; 233 tries = 2;
233 else 234 else
234 tries = 1; 235 tries = 1;
235 hotplug_en = I915_READ(PORT_HOTPLUG_EN); 236 hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
236 hotplug_en &= CRT_FORCE_HOTPLUG_MASK; 237 hotplug_en &= CRT_HOTPLUG_MASK;
237 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; 238 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
238 239
239 if (IS_G4X(dev)) 240 if (IS_G4X(dev))
@@ -255,11 +256,17 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
255 } while (time_after(timeout, jiffies)); 256 } while (time_after(timeout, jiffies));
256 } 257 }
257 258
258 if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != 259 stat = I915_READ(PORT_HOTPLUG_STAT);
259 CRT_HOTPLUG_MONITOR_NONE) 260 if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
260 return true; 261 ret = true;
262
263 /* clear the interrupt we just generated, if any */
264 I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
261 265
262 return false; 266 /* and put the bits back */
267 I915_WRITE(PORT_HOTPLUG_EN, orig);
268
269 return ret;
263} 270}
264 271
265static bool intel_crt_detect_ddc(struct drm_encoder *encoder) 272static bool intel_crt_detect_ddc(struct drm_encoder *encoder)