aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-12-08 22:13:06 -0500
committerDave Airlie <airlied@redhat.com>2010-12-20 22:31:00 -0500
commitc324acd5032f516b8188da99d2ce05cf8d1294d6 (patch)
treef39637387eafcd91b3a82e303e6a6452be0a8911
parent7a868e18a4907dc8f1f05d99bcb9fd3fa8881ee4 (diff)
drm/radeon/kms: parse the extended LCD info block
This block may contain various additional LCD info such as physical size and a stored EDID. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c53
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
4 files changed, 67 insertions, 5 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 35c5ff09040d..d6c611eee204 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1515,6 +1515,59 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
1515 else 1515 else
1516 lvds->linkb = false; 1516 lvds->linkb = false;
1517 1517
1518 /* parse the lcd record table */
1519 if (lvds_info->info.usModePatchTableOffset) {
1520 ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
1521 ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
1522 bool bad_record = false;
1523 u8 *record = (u8 *)(mode_info->atom_context->bios +
1524 data_offset +
1525 lvds_info->info.usModePatchTableOffset);
1526 while (*record != ATOM_RECORD_END_TYPE) {
1527 switch (*record) {
1528 case LCD_MODE_PATCH_RECORD_MODE_TYPE:
1529 record += sizeof(ATOM_PATCH_RECORD_MODE);
1530 break;
1531 case LCD_RTS_RECORD_TYPE:
1532 record += sizeof(ATOM_LCD_RTS_RECORD);
1533 break;
1534 case LCD_CAP_RECORD_TYPE:
1535 record += sizeof(ATOM_LCD_MODE_CONTROL_CAP);
1536 break;
1537 case LCD_FAKE_EDID_PATCH_RECORD_TYPE:
1538 fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
1539 if (fake_edid_record->ucFakeEDIDLength) {
1540 struct edid *edid;
1541 int edid_size =
1542 max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
1543 edid = kmalloc(edid_size, GFP_KERNEL);
1544 if (edid) {
1545 memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
1546 fake_edid_record->ucFakeEDIDLength);
1547
1548 if (drm_edid_is_valid(edid))
1549 rdev->mode_info.bios_hardcoded_edid = edid;
1550 else
1551 kfree(edid);
1552 }
1553 }
1554 record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
1555 break;
1556 case LCD_PANEL_RESOLUTION_RECORD_TYPE:
1557 panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
1558 lvds->native_mode.width_mm = panel_res_record->usHSize;
1559 lvds->native_mode.height_mm = panel_res_record->usVSize;
1560 record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
1561 break;
1562 default:
1563 DRM_ERROR("Bad LCD record %d\n", *record);
1564 bad_record = true;
1565 break;
1566 }
1567 if (bad_record)
1568 break;
1569 }
1570 }
1518 } 1571 }
1519 return lvds; 1572 return lvds;
1520} 1573}
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 3bddea5b5295..111a844c1ecb 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -471,8 +471,9 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
471 return true; 471 return true;
472} 472}
473 473
474/* this is used for atom LCDs as well */
474struct edid * 475struct edid *
475radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) 476radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
476{ 477{
477 if (rdev->mode_info.bios_hardcoded_edid) 478 if (rdev->mode_info.bios_hardcoded_edid)
478 return rdev->mode_info.bios_hardcoded_edid; 479 return rdev->mode_info.bios_hardcoded_edid;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 7b17e639ab32..acebbc76c2f9 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -679,9 +679,17 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
679 if (!radeon_connector->edid) { 679 if (!radeon_connector->edid) {
680 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); 680 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
681 } 681 }
682 /* some servers provide a hardcoded edid in rom for KVMs */ 682
683 if (!radeon_connector->edid) 683 if (!radeon_connector->edid) {
684 radeon_connector->edid = radeon_combios_get_hardcoded_edid(rdev); 684 if (rdev->is_atom_bios) {
685 /* some laptops provide a hardcoded edid in rom for LCDs */
686 if (((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_LVDS) ||
687 (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)))
688 radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
689 } else
690 /* some servers provide a hardcoded edid in rom for KVMs */
691 radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev);
692 }
685 if (radeon_connector->edid) { 693 if (radeon_connector->edid) {
686 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); 694 drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
687 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); 695 ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index f406f02bf14e..fd185f783a31 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -566,7 +566,7 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
566 566
567extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); 567extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
568extern struct edid * 568extern struct edid *
569radeon_combios_get_hardcoded_edid(struct radeon_device *rdev); 569radeon_bios_get_hardcoded_edid(struct radeon_device *rdev);
570extern bool radeon_atom_get_clock_info(struct drm_device *dev); 570extern bool radeon_atom_get_clock_info(struct drm_device *dev);
571extern bool radeon_combios_get_clock_info(struct drm_device *dev); 571extern bool radeon_combios_get_clock_info(struct drm_device *dev);
572extern struct radeon_encoder_atom_dig * 572extern struct radeon_encoder_atom_dig *