diff options
| -rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 95 |
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 e38bc676918..8df57431606 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 | |||
| 37 | struct intel_crt { | 45 | struct intel_crt { |
| 38 | struct intel_encoder base; | 46 | struct intel_encoder base; |
| 47 | bool force_hotplug_required; | ||
| 39 | }; | 48 | }; |
| 40 | 49 | ||
| 41 | static struct intel_crt *intel_attached_crt(struct drm_connector *connector) | 50 | static 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, | |||
| 167 | static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | 176 | static 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 | } |
