diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-12-08 22:13:06 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-12-20 22:31:00 -0500 |
commit | c324acd5032f516b8188da99d2ce05cf8d1294d6 (patch) | |
tree | f39637387eafcd91b3a82e303e6a6452be0a8911 | |
parent | 7a868e18a4907dc8f1f05d99bcb9fd3fa8881ee4 (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.c | 53 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 2 |
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 */ | ||
474 | struct edid * | 475 | struct edid * |
475 | radeon_combios_get_hardcoded_edid(struct radeon_device *rdev) | 476 | radeon_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 | ||
567 | extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); | 567 | extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); |
568 | extern struct edid * | 568 | extern struct edid * |
569 | radeon_combios_get_hardcoded_edid(struct radeon_device *rdev); | 569 | radeon_bios_get_hardcoded_edid(struct radeon_device *rdev); |
570 | extern bool radeon_atom_get_clock_info(struct drm_device *dev); | 570 | extern bool radeon_atom_get_clock_info(struct drm_device *dev); |
571 | extern bool radeon_combios_get_clock_info(struct drm_device *dev); | 571 | extern bool radeon_combios_get_clock_info(struct drm_device *dev); |
572 | extern struct radeon_encoder_atom_dig * | 572 | extern struct radeon_encoder_atom_dig * |