aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}