diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-22 18:17:01 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-22 18:32:55 +0100 |
commit | 6ec3d0c0e9c0c605696e91048eebaca7b0c36695 (patch) | |
tree | 35fa69d34bfb1839d894565bcceb143346b3468d | |
parent | a5cad620b36f15ef3aad434712ae290640aae96c (diff) | |
download | op-kernel-dev-6ec3d0c0e9c0c605696e91048eebaca7b0c36695.zip op-kernel-dev-6ec3d0c0e9c0c605696e91048eebaca7b0c36695.tar.gz |
drm/i915/crt: Use a DDC probe on 0xA0 before load-detect
The BIOS writer's guide suggests that a VGA connection will ACK a write
to address 0xA0 and that this should be used before doing legacy
load-detection. Considering the extreme cost of load-detection,
performing an extra DDC seems a risk worth taking.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 8e484c9..389fcd2 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -261,6 +261,21 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) return ret; } +static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus) +{ + u8 buf; + struct i2c_msg msgs[] = { + { + .addr = 0xA0, + .flags = 0, + .len = 1, + .buf = &buf, + }, + }; + /* DDC monitor detect: Does it ACK a write to 0xA0? */ + return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; +} + static bool intel_crt_detect_ddc(struct drm_encoder *encoder) { struct intel_encoder *intel_encoder = to_intel_encoder(encoder); @@ -270,7 +285,17 @@ static bool intel_crt_detect_ddc(struct drm_encoder *encoder) if (intel_encoder->type != INTEL_OUTPUT_ANALOG) return false; - return intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin); + if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) { + DRM_DEBUG_KMS("CRT detected via DDC:0xa0\n"); + return true; + } + + if (intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin)) { + DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); + return true; + } + + return false; } static enum drm_connector_status @@ -296,6 +321,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder uint8_t st00; enum drm_connector_status status; + DRM_DEBUG_KMS("starting load-detect on CRT\n"); + if (pipe == 0) { bclrpat_reg = BCLRPAT_A; vtotal_reg = VTOTAL_A; @@ -412,9 +439,10 @@ intel_crt_detect(struct drm_connector *connector, bool force) enum drm_connector_status status; if (I915_HAS_HOTPLUG(dev)) { - if (intel_crt_detect_hotplug(connector)) + if (intel_crt_detect_hotplug(connector)) { + DRM_DEBUG_KMS("CRT detected via hotplug\n"); return connector_status_connected; - else + } else return connector_status_disconnected; } @@ -431,7 +459,10 @@ intel_crt_detect(struct drm_connector *connector, bool force) crtc = intel_get_load_detect_pipe(encoder, connector, NULL, &dpms_mode); if (crtc) { - status = intel_crt_load_detect(crtc, encoder); + if (intel_crt_detect_ddc(&encoder->base)) + status = connector_status_connected; + else + status = intel_crt_load_detect(crtc, encoder); intel_release_load_detect_pipe(encoder, connector, dpms_mode); } else |