aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Müller <d.mueller@elsoft.ch>2011-01-06 07:29:32 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-01-11 15:26:33 -0500
commitf5afcd3dd0dca7fe869311c51da54d5a889191ba (patch)
tree95217912d2c7265c12ec8c45c37067fb84be84ac
parent37f809755845cc3e18e8216c04525bdb885fa13b (diff)
drm/i915/crt: Check for a analog monitor in case of DVI-I
Since Linux 2.6.36 the digital output on my system (855GME + DVI-I) is not working any longer. The analog output is always activated regardless of the type of monitor attached. The culprit seems to be intel_crt_detect_ddc(), which returns true as soon as an ACK from the EDID device is received. Obviously this approach does not work with DVI-I where the analog and digital outputs share a common DDC bus. In a similar manner to the shared DDC wire, ala the "Mac Mini Hack", we need an additional check to make sure that there really is an analog device attached to the DDC. Signed-off-by: David Müller <d.mueller@elsoft.ch> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: stable@kernel.org
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 8df574316063..17035b87ee46 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -30,6 +30,7 @@
30#include "drm.h" 30#include "drm.h"
31#include "drm_crtc.h" 31#include "drm_crtc.h"
32#include "drm_crtc_helper.h" 32#include "drm_crtc_helper.h"
33#include "drm_edid.h"
33#include "intel_drv.h" 34#include "intel_drv.h"
34#include "i915_drm.h" 35#include "i915_drm.h"
35#include "i915_drv.h" 36#include "i915_drv.h"
@@ -287,8 +288,9 @@ static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus)
287 return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; 288 return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1;
288} 289}
289 290
290static bool intel_crt_detect_ddc(struct intel_crt *crt) 291static bool intel_crt_detect_ddc(struct drm_connector *connector)
291{ 292{
293 struct intel_crt *crt = intel_attached_crt(connector);
292 struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private; 294 struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
293 295
294 /* CRT should always be at 0, but check anyway */ 296 /* CRT should always be at 0, but check anyway */
@@ -301,8 +303,26 @@ static bool intel_crt_detect_ddc(struct intel_crt *crt)
301 } 303 }
302 304
303 if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) { 305 if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
304 DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); 306 struct edid *edid;
305 return true; 307 bool is_digital = false;
308
309 edid = drm_get_edid(connector,
310 &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
311 /*
312 * This may be a DVI-I connector with a shared DDC
313 * link between analog and digital outputs, so we
314 * have to check the EDID input spec of the attached device.
315 */
316 if (edid != NULL) {
317 is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
318 connector->display_info.raw_edid = NULL;
319 kfree(edid);
320 }
321
322 if (!is_digital) {
323 DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
324 return true;
325 }
306 } 326 }
307 327
308 return false; 328 return false;
@@ -458,7 +478,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
458 } 478 }
459 } 479 }
460 480
461 if (intel_crt_detect_ddc(crt)) 481 if (intel_crt_detect_ddc(connector))
462 return connector_status_connected; 482 return connector_status_connected;
463 483
464 if (!force) 484 if (!force)
@@ -472,7 +492,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
472 crtc = intel_get_load_detect_pipe(&crt->base, connector, 492 crtc = intel_get_load_detect_pipe(&crt->base, connector,
473 NULL, &dpms_mode); 493 NULL, &dpms_mode);
474 if (crtc) { 494 if (crtc) {
475 if (intel_crt_detect_ddc(crt)) 495 if (intel_crt_detect_ddc(connector))
476 status = connector_status_connected; 496 status = connector_status_connected;
477 else 497 else
478 status = intel_crt_load_detect(crtc, crt); 498 status = intel_crt_load_detect(crtc, crt);