aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2009-08-23 22:25:23 -0400
committerEric Anholt <eric@anholt.net>2009-09-04 16:05:30 -0400
commit043029655816ed4cfc2ed247020ef97e5d637392 (patch)
treee5e6b1798e8f4843956e5534254819a489eec9c7 /drivers/gpu
parentce6feabd1b38f9adf4a962d71bc4762047e8f889 (diff)
drm/i915: Support IGD EOS
In the event that any one of the DAC analog outputs (R,G,B) were driven at full-scale (white video) or some analog level close to full-scale voltage, and if the video cable were then disconnected, the analog video voltage level would exceed the maximum electrical overstress limit of the native (thin-oxide) transistors thus causing a long-term reliability concern. The electrical overstress condition occurs in this particular case. This patch address the IGD EOS (electrical overstress condition) issue. When the EOS interrupt occurs, OS should disable DAC and then disable EOS, then the normal hotplug operation follows. TODO: it appears the normal unplug interrupt is missed as reported by Li Peng, need more checks here. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c21
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h2
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c28
3 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 7ebc84c2881e..6c89f2ff2495 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -565,6 +565,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
565 565
566 I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); 566 I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
567 I915_READ(PORT_HOTPLUG_STAT); 567 I915_READ(PORT_HOTPLUG_STAT);
568
569 /* EOS interrupts occurs */
570 if (IS_IGD(dev) &&
571 (hotplug_status & CRT_EOS_INT_STATUS)) {
572 u32 temp;
573
574 DRM_DEBUG("EOS interrupt occurs\n");
575 /* status is already cleared */
576 temp = I915_READ(ADPA);
577 temp &= ~ADPA_DAC_ENABLE;
578 I915_WRITE(ADPA, temp);
579
580 temp = I915_READ(PORT_HOTPLUG_EN);
581 temp &= ~CRT_EOS_INT_EN;
582 I915_WRITE(PORT_HOTPLUG_EN, temp);
583
584 temp = I915_READ(PORT_HOTPLUG_STAT);
585 if (temp & CRT_EOS_INT_STATUS)
586 I915_WRITE(PORT_HOTPLUG_STAT,
587 CRT_EOS_INT_STATUS);
588 }
568 } 589 }
569 590
570 I915_WRITE(IIR, iir); 591 I915_WRITE(IIR, iir);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2955083aa471..87a737ff3d72 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -683,6 +683,7 @@
683#define SDVOB_HOTPLUG_INT_EN (1 << 26) 683#define SDVOB_HOTPLUG_INT_EN (1 << 26)
684#define SDVOC_HOTPLUG_INT_EN (1 << 25) 684#define SDVOC_HOTPLUG_INT_EN (1 << 25)
685#define TV_HOTPLUG_INT_EN (1 << 18) 685#define TV_HOTPLUG_INT_EN (1 << 18)
686#define CRT_EOS_INT_EN (1 << 10)
686#define CRT_HOTPLUG_INT_EN (1 << 9) 687#define CRT_HOTPLUG_INT_EN (1 << 9)
687#define CRT_HOTPLUG_FORCE_DETECT (1 << 3) 688#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
688#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) 689#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
@@ -717,6 +718,7 @@
717#define DPC_HOTPLUG_INT_STATUS (1 << 28) 718#define DPC_HOTPLUG_INT_STATUS (1 << 28)
718#define HDMID_HOTPLUG_INT_STATUS (1 << 27) 719#define HDMID_HOTPLUG_INT_STATUS (1 << 27)
719#define DPD_HOTPLUG_INT_STATUS (1 << 27) 720#define DPD_HOTPLUG_INT_STATUS (1 << 27)
721#define CRT_EOS_INT_STATUS (1 << 12)
720#define CRT_HOTPLUG_INT_STATUS (1 << 11) 722#define CRT_HOTPLUG_INT_STATUS (1 << 11)
721#define TV_HOTPLUG_INT_STATUS (1 << 10) 723#define TV_HOTPLUG_INT_STATUS (1 << 10)
722#define CRT_HOTPLUG_MONITOR_MASK (3 << 8) 724#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 590f81c8f594..88814fa2dfd2 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -64,6 +64,34 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
64 } 64 }
65 65
66 I915_WRITE(reg, temp); 66 I915_WRITE(reg, temp);
67
68 if (IS_IGD(dev)) {
69 if (mode == DRM_MODE_DPMS_OFF) {
70 /* turn off DAC */
71 temp = I915_READ(PORT_HOTPLUG_EN);
72 temp &= ~CRT_EOS_INT_EN;
73 I915_WRITE(PORT_HOTPLUG_EN, temp);
74
75 temp = I915_READ(PORT_HOTPLUG_STAT);
76 if (temp & CRT_EOS_INT_STATUS)
77 I915_WRITE(PORT_HOTPLUG_STAT,
78 CRT_EOS_INT_STATUS);
79 } else {
80 /* turn on DAC. EOS interrupt must be enabled after DAC
81 * is enabled, so it sounds not good to enable it in
82 * i915_driver_irq_postinstall()
83 * wait 12.5ms after DAC is enabled
84 */
85 msleep(13);
86 temp = I915_READ(PORT_HOTPLUG_STAT);
87 if (temp & CRT_EOS_INT_STATUS)
88 I915_WRITE(PORT_HOTPLUG_STAT,
89 CRT_EOS_INT_STATUS);
90 temp = I915_READ(PORT_HOTPLUG_EN);
91 temp |= CRT_EOS_INT_EN;
92 I915_WRITE(PORT_HOTPLUG_EN, temp);
93 }
94 }
67} 95}
68 96
69static int intel_crt_mode_valid(struct drm_connector *connector, 97static int intel_crt_mode_valid(struct drm_connector *connector,