aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2011-03-23 04:10:10 -0400
committerDave Airlie <airlied@redhat.com>2011-03-24 06:24:32 -0400
commitfafcf94e2b5732d1e13b440291c53115d2b172e9 (patch)
tree349e6eccfdd57b619aa8e7acca5468a689f03f58 /drivers/gpu
parent2d370f502ac872dc9b4cd05f9922b260e2874ec1 (diff)
drm/radeon/kms: fix hardcoded EDID handling
On some servers there is a hardcoded EDID provided in the vbios so that the driver will always see a display connected even if something like a KVM prevents traditional means like DDC or load detection from working properly. Also most server boards with DVI are not actually DVI, but DVO connected to a virtual KVM service processor. If we fail to detect a monitor via DDC or load detection and a hardcoded EDID is available, use it. Additionally, when using the hardcoded EDID, use a copy of it rather than the actual one stored in the driver as the detect() and get_modes() functions may free it if DDC is successful. This fixes the virtual KVM on several internal servers. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c21
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c30
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
3 files changed, 45 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index cf7c8d5b4ec2..cf602e2d0718 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -448,7 +448,7 @@ static uint16_t combios_get_table_offset(struct drm_device *dev,
448 448
449bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) 449bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
450{ 450{
451 int edid_info; 451 int edid_info, size;
452 struct edid *edid; 452 struct edid *edid;
453 unsigned char *raw; 453 unsigned char *raw;
454 edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE); 454 edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
@@ -456,11 +456,12 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
456 return false; 456 return false;
457 457
458 raw = rdev->bios + edid_info; 458 raw = rdev->bios + edid_info;
459 edid = kmalloc(EDID_LENGTH * (raw[0x7e] + 1), GFP_KERNEL); 459 size = EDID_LENGTH * (raw[0x7e] + 1);
460 edid = kmalloc(size, GFP_KERNEL);
460 if (edid == NULL) 461 if (edid == NULL)
461 return false; 462 return false;
462 463
463 memcpy((unsigned char *)edid, raw, EDID_LENGTH * (raw[0x7e] + 1)); 464 memcpy((unsigned char *)edid, raw, size);
464 465
465 if (!drm_edid_is_valid(edid)) { 466 if (!drm_edid_is_valid(edid)) {
466 kfree(edid); 467 kfree(edid);
@@ -468,6 +469,7 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
468 } 469 }
469 470
470 rdev->mode_info.bios_hardcoded_edid = edid; 471 rdev->mode_info.bios_hardcoded_edid = edid;
472 rdev->mode_info.bios_hardcoded_edid_size = size;
471 return true; 473 return true;
472} 474}
473 475
@@ -475,8 +477,17 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
475struct edid * 477struct edid *
476radeon_bios_get_hardcoded_edid(struct radeon_device *rdev) 478radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
477{ 479{
478 if (rdev->mode_info.bios_hardcoded_edid) 480 struct edid *edid;
479 return rdev->mode_info.bios_hardcoded_edid; 481
482 if (rdev->mode_info.bios_hardcoded_edid) {
483 edid = kmalloc(rdev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
484 if (edid) {
485 memcpy((unsigned char *)edid,
486 (unsigned char *)rdev->mode_info.bios_hardcoded_edid,
487 rdev->mode_info.bios_hardcoded_edid_size);
488 return edid;
489 }
490 }
480 return NULL; 491 return NULL;
481} 492}
482 493
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 3f3c9aac46cc..a1866738a657 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -629,6 +629,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector,
629static enum drm_connector_status 629static enum drm_connector_status
630radeon_vga_detect(struct drm_connector *connector, bool force) 630radeon_vga_detect(struct drm_connector *connector, bool force)
631{ 631{
632 struct drm_device *dev = connector->dev;
633 struct radeon_device *rdev = dev->dev_private;
632 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 634 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
633 struct drm_encoder *encoder; 635 struct drm_encoder *encoder;
634 struct drm_encoder_helper_funcs *encoder_funcs; 636 struct drm_encoder_helper_funcs *encoder_funcs;
@@ -679,6 +681,17 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
679 681
680 if (ret == connector_status_connected) 682 if (ret == connector_status_connected)
681 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); 683 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
684
685 /* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
686 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
687 * by other means, assume the CRT is connected and use that EDID.
688 */
689 if ((!rdev->is_atom_bios) &&
690 (ret == connector_status_disconnected) &&
691 rdev->mode_info.bios_hardcoded_edid_size) {
692 ret = connector_status_connected;
693 }
694
682 radeon_connector_update_scratch_regs(connector, ret); 695 radeon_connector_update_scratch_regs(connector, ret);
683 return ret; 696 return ret;
684} 697}
@@ -790,6 +803,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector)
790static enum drm_connector_status 803static enum drm_connector_status
791radeon_dvi_detect(struct drm_connector *connector, bool force) 804radeon_dvi_detect(struct drm_connector *connector, bool force)
792{ 805{
806 struct drm_device *dev = connector->dev;
807 struct radeon_device *rdev = dev->dev_private;
793 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 808 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
794 struct drm_encoder *encoder = NULL; 809 struct drm_encoder *encoder = NULL;
795 struct drm_encoder_helper_funcs *encoder_funcs; 810 struct drm_encoder_helper_funcs *encoder_funcs;
@@ -829,8 +844,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
829 * you don't really know what's connected to which port as both are digital. 844 * you don't really know what's connected to which port as both are digital.
830 */ 845 */
831 if (radeon_connector->shared_ddc && (ret == connector_status_connected)) { 846 if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
832 struct drm_device *dev = connector->dev;
833 struct radeon_device *rdev = dev->dev_private;
834 struct drm_connector *list_connector; 847 struct drm_connector *list_connector;
835 struct radeon_connector *list_radeon_connector; 848 struct radeon_connector *list_radeon_connector;
836 list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) { 849 list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
@@ -895,6 +908,19 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
895 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); 908 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
896 } 909 }
897 910
911 /* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
912 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
913 * by other means, assume the DFP is connected and use that EDID. In most
914 * cases the DVI port is actually a virtual KVM port connected to the service
915 * processor.
916 */
917 if ((!rdev->is_atom_bios) &&
918 (ret == connector_status_disconnected) &&
919 rdev->mode_info.bios_hardcoded_edid_size) {
920 radeon_connector->use_digital = true;
921 ret = connector_status_connected;
922 }
923
898out: 924out:
899 /* updated in get modes as well since we need to know if it's analog or digital */ 925 /* updated in get modes as well since we need to know if it's analog or digital */
900 radeon_connector_update_scratch_regs(connector, ret); 926 radeon_connector_update_scratch_regs(connector, ret);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 5067d18d0009..1ae6846de827 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -239,6 +239,7 @@ struct radeon_mode_info {
239 struct drm_property *underscan_vborder_property; 239 struct drm_property *underscan_vborder_property;
240 /* hardcoded DFP edid from BIOS */ 240 /* hardcoded DFP edid from BIOS */
241 struct edid *bios_hardcoded_edid; 241 struct edid *bios_hardcoded_edid;
242 int bios_hardcoded_edid_size;
242 243
243 /* pointer to fbdev info structure */ 244 /* pointer to fbdev info structure */
244 struct radeon_fbdev *rfbdev; 245 struct radeon_fbdev *rfbdev;