aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2010-11-16 03:03:53 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-11-19 04:30:28 -0500
commite7dbb2f2f8ac843ab5e4d6a8e9a71d16089d324b (patch)
tree193d71e31fecc335ef2b0f542131d99cc543d82f
parentc9a1c4cded955176479a28556f546d3d015aee91 (diff)
drm/i915: Take advantage of auto-polling CRT hotplug detection on PCH hardware
Both IBX and CPT have an automatic hotplug detection mode which appears to work reliably enough that we can dispense with the manual force hotplug trigger stuff. This means that hotplug detection is as simple as reading the current hotplug register values. The first time the hotplug detection is activated, the code synchronously waits for a hotplug sequence in case the hardware hasn't bothered to do a detection cycle since being initialized. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c95
1 files changed, 57 insertions, 38 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index e38bc6769180..8df574316063 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -34,8 +34,17 @@
34#include "i915_drm.h" 34#include "i915_drm.h"
35#include "i915_drv.h" 35#include "i915_drv.h"
36 36
37/* Here's the desired hotplug mode */
38#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
39 ADPA_CRT_HOTPLUG_WARMUP_10MS | \
40 ADPA_CRT_HOTPLUG_SAMPLE_4S | \
41 ADPA_CRT_HOTPLUG_VOLTAGE_50 | \
42 ADPA_CRT_HOTPLUG_VOLREF_325MV | \
43 ADPA_CRT_HOTPLUG_ENABLE)
44
37struct intel_crt { 45struct intel_crt {
38 struct intel_encoder base; 46 struct intel_encoder base;
47 bool force_hotplug_required;
39}; 48};
40 49
41static struct intel_crt *intel_attached_crt(struct drm_connector *connector) 50static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
@@ -139,7 +148,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
139 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); 148 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
140 } 149 }
141 150
142 adpa = 0; 151 adpa = ADPA_HOTPLUG_BITS;
143 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 152 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
144 adpa |= ADPA_HSYNC_ACTIVE_HIGH; 153 adpa |= ADPA_HSYNC_ACTIVE_HIGH;
145 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) 154 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -167,53 +176,44 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
167static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) 176static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
168{ 177{
169 struct drm_device *dev = connector->dev; 178 struct drm_device *dev = connector->dev;
179 struct intel_crt *crt = intel_attached_crt(connector);
170 struct drm_i915_private *dev_priv = dev->dev_private; 180 struct drm_i915_private *dev_priv = dev->dev_private;
171 u32 adpa, temp; 181 u32 adpa;
172 bool ret; 182 bool ret;
173 bool turn_off_dac = false;
174 183
175 temp = adpa = I915_READ(PCH_ADPA); 184 /* The first time through, trigger an explicit detection cycle */
185 if (crt->force_hotplug_required) {
186 bool turn_off_dac = HAS_PCH_SPLIT(dev);
187 u32 save_adpa;
176 188
177 if (HAS_PCH_SPLIT(dev)) 189 crt->force_hotplug_required = 0;
178 turn_off_dac = true; 190
179 191 save_adpa = adpa = I915_READ(PCH_ADPA);
180 adpa &= ~ADPA_CRT_HOTPLUG_MASK; 192 DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
181 if (turn_off_dac) 193
182 adpa &= ~ADPA_DAC_ENABLE; 194 adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
183 195 if (turn_off_dac)
184 /* disable HPD first */ 196 adpa &= ~ADPA_DAC_ENABLE;
185 I915_WRITE(PCH_ADPA, adpa); 197
186 (void)I915_READ(PCH_ADPA); 198 I915_WRITE(PCH_ADPA, adpa);
187 199
188 adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | 200 if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
189 ADPA_CRT_HOTPLUG_WARMUP_10MS | 201 1000))
190 ADPA_CRT_HOTPLUG_SAMPLE_4S | 202 DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
191 ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */ 203
192 ADPA_CRT_HOTPLUG_VOLREF_325MV | 204 if (turn_off_dac) {
193 ADPA_CRT_HOTPLUG_ENABLE | 205 I915_WRITE(PCH_ADPA, save_adpa);
194 ADPA_CRT_HOTPLUG_FORCE_TRIGGER); 206 POSTING_READ(PCH_ADPA);
195 207 }
196 DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa);
197 I915_WRITE(PCH_ADPA, adpa);
198
199 if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
200 1000))
201 DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
202
203 if (turn_off_dac) {
204 /* Make sure hotplug is enabled */
205 I915_WRITE(PCH_ADPA, temp | ADPA_CRT_HOTPLUG_ENABLE);
206 (void)I915_READ(PCH_ADPA);
207 } 208 }
208 209
209 /* Check the status to see if both blue and green are on now */ 210 /* Check the status to see if both blue and green are on now */
210 adpa = I915_READ(PCH_ADPA); 211 adpa = I915_READ(PCH_ADPA);
211 adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK; 212 if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
212 if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) ||
213 (adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO))
214 ret = true; 213 ret = true;
215 else 214 else
216 ret = false; 215 ret = false;
216 DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret);
217 217
218 return ret; 218 return ret;
219} 219}
@@ -452,8 +452,10 @@ intel_crt_detect(struct drm_connector *connector, bool force)
452 if (intel_crt_detect_hotplug(connector)) { 452 if (intel_crt_detect_hotplug(connector)) {
453 DRM_DEBUG_KMS("CRT detected via hotplug\n"); 453 DRM_DEBUG_KMS("CRT detected via hotplug\n");
454 return connector_status_connected; 454 return connector_status_connected;
455 } else 455 } else {
456 DRM_DEBUG_KMS("CRT not detected via hotplug\n");
456 return connector_status_disconnected; 457 return connector_status_disconnected;
458 }
457 } 459 }
458 460
459 if (intel_crt_detect_ddc(crt)) 461 if (intel_crt_detect_ddc(crt))
@@ -587,5 +589,22 @@ void intel_crt_init(struct drm_device *dev)
587 else 589 else
588 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 590 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
589 591
592 /*
593 * Configure the automatic hotplug detection stuff
594 */
595 crt->force_hotplug_required = 0;
596 if (HAS_PCH_SPLIT(dev)) {
597 u32 adpa;
598
599 adpa = I915_READ(PCH_ADPA);
600 adpa &= ~ADPA_CRT_HOTPLUG_MASK;
601 adpa |= ADPA_HOTPLUG_BITS;
602 I915_WRITE(PCH_ADPA, adpa);
603 POSTING_READ(PCH_ADPA);
604
605 DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa);
606 crt->force_hotplug_required = 1;
607 }
608
590 dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; 609 dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
591} 610}