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 #include "i915_drm.h" 35 #include "i915_drv.h" 36 37 struct intel_crt { 38 struct intel_encoder base; 39 }; 40 41 static struct intel_crt *intel_attached_crt(struct drm_connector *connector) ··· 148 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); 149 } 150 151 - adpa = 0; 152 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 153 adpa |= ADPA_HSYNC_ACTIVE_HIGH; 154 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ··· 176 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) 177 { 178 struct drm_device *dev = connector->dev; 179 struct drm_i915_private *dev_priv = dev->dev_private; 180 - u32 adpa, temp; 181 bool ret; 182 - bool turn_off_dac = false; 183 184 - temp = adpa = I915_READ(PCH_ADPA); 185 186 - if (HAS_PCH_SPLIT(dev)) 187 - turn_off_dac = true; 188 189 - adpa &= ~ADPA_CRT_HOTPLUG_MASK; 190 - if (turn_off_dac) 191 - adpa &= ~ADPA_DAC_ENABLE; 192 193 - /* disable HPD first */ 194 - I915_WRITE(PCH_ADPA, adpa); 195 - (void)I915_READ(PCH_ADPA); 196 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); 204 205 - DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa); 206 - I915_WRITE(PCH_ADPA, adpa); 207 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); 216 } 217 218 /* Check the status to see if both blue and green are on now */ 219 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)) 223 ret = true; 224 else 225 ret = false; 226 227 return ret; 228 } ··· 452 if (intel_crt_detect_hotplug(connector)) { 453 DRM_DEBUG_KMS("CRT detected via hotplug\n"); 454 return connector_status_connected; 455 - } else 456 return connector_status_disconnected; 457 } 458 459 if (intel_crt_detect_ddc(crt)) ··· 588 connector->polled = DRM_CONNECTOR_POLL_HPD; 589 else 590 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 591 592 dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; 593 }
··· 34 #include "i915_drm.h" 35 #include "i915_drv.h" 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 + 45 struct intel_crt { 46 struct intel_encoder base; 47 + bool force_hotplug_required; 48 }; 49 50 static struct intel_crt *intel_attached_crt(struct drm_connector *connector) ··· 139 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); 140 } 141 142 + adpa = ADPA_HOTPLUG_BITS; 143 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 144 adpa |= ADPA_HSYNC_ACTIVE_HIGH; 145 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ··· 167 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) 168 { 169 struct drm_device *dev = connector->dev; 170 + struct intel_crt *crt = intel_attached_crt(connector); 171 struct drm_i915_private *dev_priv = dev->dev_private; 172 + u32 adpa; 173 bool ret; 174 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; 179 180 + crt->force_hotplug_required = 0; 181 182 + save_adpa = adpa = I915_READ(PCH_ADPA); 183 + DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); 184 185 + adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; 186 + if (turn_off_dac) 187 + adpa &= ~ADPA_DAC_ENABLE; 188 189 + I915_WRITE(PCH_ADPA, adpa); 190 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"); 194 195 + if (turn_off_dac) { 196 + I915_WRITE(PCH_ADPA, save_adpa); 197 + POSTING_READ(PCH_ADPA); 198 + } 199 } 200 201 /* Check the status to see if both blue and green are on now */ 202 adpa = I915_READ(PCH_ADPA); 203 + if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) 204 ret = true; 205 else 206 ret = false; 207 + DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret); 208 209 return ret; 210 } ··· 452 if (intel_crt_detect_hotplug(connector)) { 453 DRM_DEBUG_KMS("CRT detected via hotplug\n"); 454 return connector_status_connected; 455 + } else { 456 + DRM_DEBUG_KMS("CRT not detected via hotplug\n"); 457 return connector_status_disconnected; 458 + } 459 } 460 461 if (intel_crt_detect_ddc(crt)) ··· 586 connector->polled = DRM_CONNECTOR_POLL_HPD; 587 else 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 + } 606 607 dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; 608 }