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>

authored by Keith Packard and committed by Chris Wilson e7dbb2f2 c9a1c4cd

+52 -33
+52 -33
drivers/gpu/drm/i915/intel_crt.c
··· 34 34 #include "i915_drm.h" 35 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 + 37 45 struct intel_crt { 38 46 struct intel_encoder base; 47 + bool force_hotplug_required; 39 48 }; 40 49 41 50 static struct intel_crt *intel_attached_crt(struct drm_connector *connector) ··· 148 139 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); 149 140 } 150 141 151 - adpa = 0; 142 + adpa = ADPA_HOTPLUG_BITS; 152 143 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 153 144 adpa |= ADPA_HSYNC_ACTIVE_HIGH; 154 145 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ··· 176 167 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) 177 168 { 178 169 struct drm_device *dev = connector->dev; 170 + struct intel_crt *crt = intel_attached_crt(connector); 179 171 struct drm_i915_private *dev_priv = dev->dev_private; 180 - u32 adpa, temp; 172 + u32 adpa; 181 173 bool ret; 182 - bool turn_off_dac = false; 183 174 184 - temp = adpa = I915_READ(PCH_ADPA); 175 + /* The first time through, trigger an explicit detection cycle */ 176 + if (crt->force_hotplug_required) { 177 + bool turn_off_dac = HAS_PCH_SPLIT(dev); 178 + u32 save_adpa; 185 179 186 - if (HAS_PCH_SPLIT(dev)) 187 - turn_off_dac = true; 180 + crt->force_hotplug_required = 0; 188 181 189 - adpa &= ~ADPA_CRT_HOTPLUG_MASK; 190 - if (turn_off_dac) 191 - adpa &= ~ADPA_DAC_ENABLE; 182 + save_adpa = adpa = I915_READ(PCH_ADPA); 183 + DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); 192 184 193 - /* disable HPD first */ 194 - I915_WRITE(PCH_ADPA, adpa); 195 - (void)I915_READ(PCH_ADPA); 185 + adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; 186 + if (turn_off_dac) 187 + adpa &= ~ADPA_DAC_ENABLE; 196 188 197 - adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | 198 - ADPA_CRT_HOTPLUG_WARMUP_10MS | 199 - ADPA_CRT_HOTPLUG_SAMPLE_4S | 200 - ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */ 201 - ADPA_CRT_HOTPLUG_VOLREF_325MV | 202 - ADPA_CRT_HOTPLUG_ENABLE | 203 - ADPA_CRT_HOTPLUG_FORCE_TRIGGER); 189 + I915_WRITE(PCH_ADPA, adpa); 204 190 205 - DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa); 206 - I915_WRITE(PCH_ADPA, adpa); 191 + if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, 192 + 1000)) 193 + DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); 207 194 208 - if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, 209 - 1000)) 210 - DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); 211 - 212 - if (turn_off_dac) { 213 - /* Make sure hotplug is enabled */ 214 - I915_WRITE(PCH_ADPA, temp | ADPA_CRT_HOTPLUG_ENABLE); 215 - (void)I915_READ(PCH_ADPA); 195 + if (turn_off_dac) { 196 + I915_WRITE(PCH_ADPA, save_adpa); 197 + POSTING_READ(PCH_ADPA); 198 + } 216 199 } 217 200 218 201 /* Check the status to see if both blue and green are on now */ 219 202 adpa = I915_READ(PCH_ADPA); 220 - adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK; 221 - if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) || 222 - (adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO)) 203 + if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) 223 204 ret = true; 224 205 else 225 206 ret = false; 207 + DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret); 226 208 227 209 return ret; 228 210 } ··· 452 452 if (intel_crt_detect_hotplug(connector)) { 453 453 DRM_DEBUG_KMS("CRT detected via hotplug\n"); 454 454 return connector_status_connected; 455 - } else 455 + } else { 456 + DRM_DEBUG_KMS("CRT not detected via hotplug\n"); 456 457 return connector_status_disconnected; 458 + } 457 459 } 458 460 459 461 if (intel_crt_detect_ddc(crt)) ··· 588 586 connector->polled = DRM_CONNECTOR_POLL_HPD; 589 587 else 590 588 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 589 + 590 + /* 591 + * Configure the automatic hotplug detection stuff 592 + */ 593 + crt->force_hotplug_required = 0; 594 + if (HAS_PCH_SPLIT(dev)) { 595 + u32 adpa; 596 + 597 + adpa = I915_READ(PCH_ADPA); 598 + adpa &= ~ADPA_CRT_HOTPLUG_MASK; 599 + adpa |= ADPA_HOTPLUG_BITS; 600 + I915_WRITE(PCH_ADPA, adpa); 601 + POSTING_READ(PCH_ADPA); 602 + 603 + DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa); 604 + crt->force_hotplug_required = 1; 605 + } 591 606 592 607 dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; 593 608 }