aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_crt.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-07-20 18:44:45 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-09-18 10:46:19 -0400
commitf899fc64cda8569d0529452aafc0da31c042df2e (patch)
tree61b6d32abe3524b83abc9d8b9382e3f82225cd64 /drivers/gpu/drm/i915/intel_crt.c
parent373a3cf744c774478f44921c50011b896ab08f9d (diff)
drm/i915: use GMBUS to manage i2c links
Use the GMBUS interface rather than direct bit banging to grab the EDID over DDC (and for other forms of auxiliary communication with external display controllers). The hope is that this method will be much faster and more reliable than bit banging for fetching EDIDs from buggy monitors or through switches, though we still preserve the bit banging as a fallback in case GMBUS fails. Based on an original patch by Jesse Barnes. Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_crt.c')
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c48
1 files changed, 8 insertions, 40 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 2353da625d25..8b782ee63085 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -264,12 +264,13 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
264static bool intel_crt_detect_ddc(struct drm_encoder *encoder) 264static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
265{ 265{
266 struct intel_encoder *intel_encoder = to_intel_encoder(encoder); 266 struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
267 struct drm_i915_private *dev_priv = encoder->dev->dev_private;
267 268
268 /* CRT should always be at 0, but check anyway */ 269 /* CRT should always be at 0, but check anyway */
269 if (intel_encoder->type != INTEL_OUTPUT_ANALOG) 270 if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
270 return false; 271 return false;
271 272
272 return intel_ddc_probe(intel_encoder); 273 return intel_ddc_probe(intel_encoder, dev_priv->crt_ddc_pin);
273} 274}
274 275
275static enum drm_connector_status 276static enum drm_connector_status
@@ -445,29 +446,18 @@ static void intel_crt_destroy(struct drm_connector *connector)
445 446
446static int intel_crt_get_modes(struct drm_connector *connector) 447static int intel_crt_get_modes(struct drm_connector *connector)
447{ 448{
448 struct intel_encoder *encoder = intel_attached_encoder(connector);
449 struct i2c_adapter *ddc_bus;
450 struct drm_device *dev = connector->dev; 449 struct drm_device *dev = connector->dev;
450 struct drm_i915_private *dev_priv = dev->dev_private;
451 int ret; 451 int ret;
452 452
453 ret = intel_ddc_get_modes(connector, encoder->ddc_bus); 453 ret = intel_ddc_get_modes(connector,
454 &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
454 if (ret || !IS_G4X(dev)) 455 if (ret || !IS_G4X(dev))
455 goto end; 456 return ret;
456 457
457 /* Try to probe digital port for output in DVI-I -> VGA mode. */ 458 /* Try to probe digital port for output in DVI-I -> VGA mode. */
458 ddc_bus = intel_i2c_create(encoder, GPIOD, "CRTDDC_D"); 459 return intel_ddc_get_modes(connector,
459 if (!ddc_bus) { 460 &dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
460 dev_printk(KERN_ERR, &connector->dev->pdev->dev,
461 "DDC bus registration failed for CRTDDC_D.\n");
462 goto end;
463 }
464 /* Try to get modes by GPIOD port */
465 ret = intel_ddc_get_modes(connector, ddc_bus);
466 intel_i2c_destroy(ddc_bus);
467
468end:
469 return ret;
470
471} 461}
472 462
473static int intel_crt_set_property(struct drm_connector *connector, 463static int intel_crt_set_property(struct drm_connector *connector,
@@ -513,7 +503,6 @@ void intel_crt_init(struct drm_device *dev)
513 struct intel_encoder *intel_encoder; 503 struct intel_encoder *intel_encoder;
514 struct intel_connector *intel_connector; 504 struct intel_connector *intel_connector;
515 struct drm_i915_private *dev_priv = dev->dev_private; 505 struct drm_i915_private *dev_priv = dev->dev_private;
516 u32 i2c_reg;
517 506
518 intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); 507 intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
519 if (!intel_encoder) 508 if (!intel_encoder)
@@ -534,27 +523,6 @@ void intel_crt_init(struct drm_device *dev)
534 523
535 intel_connector_attach_encoder(intel_connector, intel_encoder); 524 intel_connector_attach_encoder(intel_connector, intel_encoder);
536 525
537 /* Set up the DDC bus. */
538 if (HAS_PCH_SPLIT(dev))
539 i2c_reg = PCH_GPIOA;
540 else {
541 i2c_reg = GPIOA;
542 /* Use VBT information for CRT DDC if available */
543 if (dev_priv->crt_ddc_bus != 0)
544 i2c_reg = dev_priv->crt_ddc_bus;
545 }
546 intel_encoder->ddc_bus = intel_i2c_create(intel_encoder,
547 i2c_reg, "CRTDDC_A");
548 if (!intel_encoder->ddc_bus) {
549 dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
550 "failed.\n");
551 drm_connector_cleanup(&intel_connector->base);
552 kfree(intel_connector);
553 drm_encoder_cleanup(&intel_encoder->base);
554 kfree(intel_encoder);
555 return;
556 }
557
558 intel_encoder->type = INTEL_OUTPUT_ANALOG; 526 intel_encoder->type = INTEL_OUTPUT_ANALOG;
559 intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | 527 intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
560 (1 << INTEL_ANALOG_CLONE_BIT) | 528 (1 << INTEL_ANALOG_CLONE_BIT) |