summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_combios.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2011-03-23 08:10:10 +0000
committerDave Airlie <airlied@redhat.com>2011-03-24 20:24:32 +1000
commitfafcf94e2b5732d1e13b440291c53115d2b172e9 (patch)
tree349e6eccfdd57b619aa8e7acca5468a689f03f58 /drivers/gpu/drm/radeon/radeon_combios.c
parent2d370f502ac872dc9b4cd05f9922b260e2874ec1 (diff)
downloadblackbird-op-linux-fafcf94e2b5732d1e13b440291c53115d2b172e9.tar.gz
blackbird-op-linux-fafcf94e2b5732d1e13b440291c53115d2b172e9.zip
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/drm/radeon/radeon_combios.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c21
1 files changed, 16 insertions, 5 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,
bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
{
- int edid_info;
+ int edid_info, size;
struct edid *edid;
unsigned char *raw;
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)
return false;
raw = rdev->bios + edid_info;
- edid = kmalloc(EDID_LENGTH * (raw[0x7e] + 1), GFP_KERNEL);
+ size = EDID_LENGTH * (raw[0x7e] + 1);
+ edid = kmalloc(size, GFP_KERNEL);
if (edid == NULL)
return false;
- memcpy((unsigned char *)edid, raw, EDID_LENGTH * (raw[0x7e] + 1));
+ memcpy((unsigned char *)edid, raw, size);
if (!drm_edid_is_valid(edid)) {
kfree(edid);
@@ -468,6 +469,7 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
}
rdev->mode_info.bios_hardcoded_edid = edid;
+ rdev->mode_info.bios_hardcoded_edid_size = size;
return true;
}
@@ -475,8 +477,17 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
struct edid *
radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
{
- if (rdev->mode_info.bios_hardcoded_edid)
- return rdev->mode_info.bios_hardcoded_edid;
+ struct edid *edid;
+
+ if (rdev->mode_info.bios_hardcoded_edid) {
+ edid = kmalloc(rdev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
+ if (edid) {
+ memcpy((unsigned char *)edid,
+ (unsigned char *)rdev->mode_info.bios_hardcoded_edid,
+ rdev->mode_info.bios_hardcoded_edid_size);
+ return edid;
+ }
+ }
return NULL;
}
OpenPOWER on IntegriCloud