aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_connectors.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-10-15 16:16:35 -0400
committerDave Airlie <airlied@redhat.com>2009-10-15 18:46:52 -0400
commit0294cf4f7f895ddcf284b1ce7cf27a2c9d7106f7 (patch)
tree7c69f11e946519457c08e8106c05df1a850b77fd /drivers/gpu/drm/radeon/radeon_connectors.c
parent1b4d7d75ccff38008ccd40f8e2d74e33a087caaa (diff)
drm/radeon/kms: fix connector edid handling
Based partly on a patch from Christian Koenig <deathsimple@vodafone.de> - fix several memory leaks in radeon_connector->edid handling - store edid in radeon_connector->edid in detect() or get_modes() - switch hdmi detect code to use radeon_connector->edid - add support for oem boards multiple connectors that share a ddc line. - short circuit lvds_detect() if have a stored edid Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_connectors.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 729207a1e83e..5b6067aa08bd 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -400,7 +400,6 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec
400 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 400 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
401 struct drm_encoder *encoder = radeon_best_single_encoder(connector); 401 struct drm_encoder *encoder = radeon_best_single_encoder(connector);
402 enum drm_connector_status ret = connector_status_disconnected; 402 enum drm_connector_status ret = connector_status_disconnected;
403 bool dret;
404 403
405 if (encoder) { 404 if (encoder) {
406 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 405 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -413,12 +412,17 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec
413 } 412 }
414 413
415 /* check for edid as well */ 414 /* check for edid as well */
416 if (radeon_connector->ddc_bus) { 415 if (radeon_connector->edid)
417 radeon_i2c_do_lock(radeon_connector, 1); 416 ret = connector_status_connected;
418 dret = radeon_ddc_probe(radeon_connector); 417 else {
419 radeon_i2c_do_lock(radeon_connector, 0); 418 if (radeon_connector->ddc_bus) {
420 if (dret) 419 radeon_i2c_do_lock(radeon_connector, 1);
421 ret = connector_status_connected; 420 radeon_connector->edid = drm_get_edid(&radeon_connector->base,
421 &radeon_connector->ddc_bus->adapter);
422 radeon_i2c_do_lock(radeon_connector, 0);
423 if (radeon_connector->edid)
424 ret = connector_status_connected;
425 }
422 } 426 }
423 /* check acpi lid status ??? */ 427 /* check acpi lid status ??? */
424 428
@@ -432,6 +436,8 @@ static void radeon_connector_destroy(struct drm_connector *connector)
432 436
433 if (radeon_connector->ddc_bus) 437 if (radeon_connector->ddc_bus)
434 radeon_i2c_destroy(radeon_connector->ddc_bus); 438 radeon_i2c_destroy(radeon_connector->ddc_bus);
439 if (radeon_connector->edid)
440 kfree(radeon_connector->edid);
435 kfree(radeon_connector->con_priv); 441 kfree(radeon_connector->con_priv);
436 drm_sysfs_connector_remove(connector); 442 drm_sysfs_connector_remove(connector);
437 drm_connector_cleanup(connector); 443 drm_connector_cleanup(connector);
@@ -519,9 +525,32 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
519 radeon_i2c_do_lock(radeon_connector, 1); 525 radeon_i2c_do_lock(radeon_connector, 1);
520 dret = radeon_ddc_probe(radeon_connector); 526 dret = radeon_ddc_probe(radeon_connector);
521 radeon_i2c_do_lock(radeon_connector, 0); 527 radeon_i2c_do_lock(radeon_connector, 0);
522 if (dret) 528 if (dret) {
523 ret = connector_status_connected; 529 if (radeon_connector->edid) {
524 else { 530 kfree(radeon_connector->edid);
531 radeon_connector->edid = NULL;
532 }
533 radeon_i2c_do_lock(radeon_connector, 1);
534 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
535 radeon_i2c_do_lock(radeon_connector, 0);
536
537 if (!radeon_connector->edid) {
538 DRM_ERROR("DDC responded but not EDID found for %s\n",
539 drm_get_connector_name(connector));
540 } else {
541 radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
542
543 /* some oems have boards with separate digital and analog connectors
544 * with a shared ddc line (often vga + hdmi)
545 */
546 if (radeon_connector->use_digital && radeon_connector->shared_ddc) {
547 kfree(radeon_connector->edid);
548 radeon_connector->edid = NULL;
549 ret = connector_status_disconnected;
550 } else
551 ret = connector_status_connected;
552 }
553 } else {
525 if (radeon_connector->dac_load_detect) { 554 if (radeon_connector->dac_load_detect) {
526 encoder_funcs = encoder->helper_private; 555 encoder_funcs = encoder->helper_private;
527 ret = encoder_funcs->detect(encoder, connector); 556 ret = encoder_funcs->detect(encoder, connector);
@@ -649,6 +678,10 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
649 dret = radeon_ddc_probe(radeon_connector); 678 dret = radeon_ddc_probe(radeon_connector);
650 radeon_i2c_do_lock(radeon_connector, 0); 679 radeon_i2c_do_lock(radeon_connector, 0);
651 if (dret) { 680 if (dret) {
681 if (radeon_connector->edid) {
682 kfree(radeon_connector->edid);
683 radeon_connector->edid = NULL;
684 }
652 radeon_i2c_do_lock(radeon_connector, 1); 685 radeon_i2c_do_lock(radeon_connector, 1);
653 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); 686 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
654 radeon_i2c_do_lock(radeon_connector, 0); 687 radeon_i2c_do_lock(radeon_connector, 0);
@@ -659,10 +692,15 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
659 } else { 692 } else {
660 radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); 693 radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
661 694
662 /* if this isn't a digital monitor 695 /* some oems have boards with separate digital and analog connectors
663 then we need to make sure we don't have any 696 * with a shared ddc line (often vga + hdmi)
664 TV conflicts */ 697 */
665 ret = connector_status_connected; 698 if ((!radeon_connector->use_digital) && radeon_connector->shared_ddc) {
699 kfree(radeon_connector->edid);
700 radeon_connector->edid = NULL;
701 ret = connector_status_disconnected;
702 } else
703 ret = connector_status_connected;
666 } 704 }
667 } 705 }
668 706
@@ -787,6 +825,7 @@ radeon_add_atom_connector(struct drm_device *dev,
787 struct radeon_connector *radeon_connector; 825 struct radeon_connector *radeon_connector;
788 struct radeon_connector_atom_dig *radeon_dig_connector; 826 struct radeon_connector_atom_dig *radeon_dig_connector;
789 uint32_t subpixel_order = SubPixelNone; 827 uint32_t subpixel_order = SubPixelNone;
828 bool shared_ddc = false;
790 int ret; 829 int ret;
791 830
792 /* fixme - tv/cv/din */ 831 /* fixme - tv/cv/din */
@@ -800,6 +839,13 @@ radeon_add_atom_connector(struct drm_device *dev,
800 radeon_connector->devices |= supported_device; 839 radeon_connector->devices |= supported_device;
801 return; 840 return;
802 } 841 }
842 if (radeon_connector->ddc_bus && i2c_bus->valid) {
843 if (memcmp(&radeon_connector->ddc_bus->rec, i2c_bus,
844 sizeof(struct radeon_i2c_bus_rec)) == 0) {
845 radeon_connector->shared_ddc = true;
846 shared_ddc = true;
847 }
848 }
803 } 849 }
804 850
805 radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); 851 radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
@@ -810,6 +856,7 @@ radeon_add_atom_connector(struct drm_device *dev,
810 856
811 radeon_connector->connector_id = connector_id; 857 radeon_connector->connector_id = connector_id;
812 radeon_connector->devices = supported_device; 858 radeon_connector->devices = supported_device;
859 radeon_connector->shared_ddc = shared_ddc;
813 switch (connector_type) { 860 switch (connector_type) {
814 case DRM_MODE_CONNECTOR_VGA: 861 case DRM_MODE_CONNECTOR_VGA:
815 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 862 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);