intel_extreme: expand bios scan for panel a bit, might help ticket #17451

This commit is contained in:
Rudolf Cornelissen
2021-12-11 12:21:42 +00:00
parent 84c9ff3ee5
commit d2e4af7873
@@ -19,9 +19,6 @@
#endif #endif
static const off_t kVbtPointer = 0x1A;
struct vbt_header { struct vbt_header {
uint8 signature[20]; uint8 signature[20];
uint16 version; uint16 version;
@@ -115,7 +112,7 @@ static struct vbios {
PROM-programmed timings info when compensation mode is off on your machine. PROM-programmed timings info when compensation mode is off on your machine.
*/ */
static bool static bool
get_bios(void) get_bios(int* vbtOffset)
{ {
static const uint64_t kVBIOSAddress = 0xc0000; static const uint64_t kVBIOSAddress = 0xc0000;
static const int kVBIOSSize = 64 * 1024; static const int kVBIOSSize = 64 * 1024;
@@ -133,14 +130,22 @@ get_bios(void)
TRACE((DEVICE_NAME ": mapping VBIOS: 0x%" B_PRIx64 " -> %p\n", TRACE((DEVICE_NAME ": mapping VBIOS: 0x%" B_PRIx64 " -> %p\n",
kVBIOSAddress, vbios.memory)); kVBIOSAddress, vbios.memory));
int vbtOffset = vbios.ReadWord(kVbtPointer); // scan BIOS for VBT signature
if ((vbtOffset + (int)sizeof(vbt_header)) >= kVBIOSSize) { *vbtOffset = kVBIOSSize;
TRACE((DEVICE_NAME": bad VBT offset : 0x%x\n", vbtOffset)); for (uint32 i = 0; i + 4 < kVBIOSSize; i += 4) {
if (memcmp(vbios.memory + i, "$VBT", 4) == 0) {
*vbtOffset = i;
continue;
}
}
if ((*vbtOffset + (int)sizeof(vbt_header)) >= kVBIOSSize) {
TRACE((DEVICE_NAME": bad VBT offset : 0x%x\n", *vbtOffset));
delete_area(vbios.area); delete_area(vbios.area);
return false; return false;
} }
struct vbt_header* vbt = (struct vbt_header*)(vbios.memory + vbtOffset); struct vbt_header* vbt = (struct vbt_header*)(vbios.memory + *vbtOffset);
if (memcmp(vbt->signature, "$VBT", 4) != 0) { if (memcmp(vbt->signature, "$VBT", 4) != 0) {
TRACE((DEVICE_NAME": bad VBT signature: %20s\n", vbt->signature)); TRACE((DEVICE_NAME": bad VBT signature: %20s\n", vbt->signature));
delete_area(vbios.area); delete_area(vbios.area);
@@ -182,10 +187,10 @@ sanitize_panel_timing(display_timing& timing)
bool bool
get_lvds_mode_from_bios(display_timing* panelTiming) get_lvds_mode_from_bios(display_timing* panelTiming)
{ {
if (!get_bios()) int vbtOffset = 0;
if (!get_bios(&vbtOffset))
return false; return false;
int vbtOffset = vbios.ReadWord(kVbtPointer);
struct vbt_header* vbt = (struct vbt_header*)(vbios.memory + vbtOffset); struct vbt_header* vbt = (struct vbt_header*)(vbios.memory + vbtOffset);
int bdbOffset = vbtOffset + vbt->bdb_offset; int bdbOffset = vbtOffset + vbt->bdb_offset;
@@ -194,6 +199,8 @@ get_lvds_mode_from_bios(display_timing* panelTiming)
TRACE((DEVICE_NAME": bad BDB signature\n")); TRACE((DEVICE_NAME": bad BDB signature\n"));
delete_area(vbios.area); delete_area(vbios.area);
} }
TRACE((DEVICE_NAME ": VBT signature \"%.*s\", BDB version %d\n",
(int)sizeof(vbt->signature), vbt->signature, bdb->version));
int blockSize; int blockSize;
int panelType = -1; int panelType = -1;
@@ -205,7 +212,7 @@ get_lvds_mode_from_bios(display_timing* panelTiming)
int id = vbios.memory[start]; int id = vbios.memory[start];
blockSize = vbios.ReadWord(start + 1) + 3; blockSize = vbios.ReadWord(start + 1) + 3;
switch (id) { switch (id) {
case 40: // FIXME magic numbers case 40: // Item BDB_LVDS_OPTIONS
{ {
struct lvds_bdb1 *lvds1; struct lvds_bdb1 *lvds1;
lvds1 = (struct lvds_bdb1 *)(vbios.memory + start); lvds1 = (struct lvds_bdb1 *)(vbios.memory + start);
@@ -213,7 +220,7 @@ get_lvds_mode_from_bios(display_timing* panelTiming)
TRACE((DEVICE_NAME ": panel type: %d\n", panelType)); TRACE((DEVICE_NAME ": panel type: %d\n", panelType));
break; break;
} }
case 41: case 41: // Item BDB_LVDS_LFP_DATA_PTRS
{ {
// First make sure we found block 40 and the panel type // First make sure we found block 40 and the panel type
if (panelType == -1) if (panelType == -1)
@@ -226,20 +233,9 @@ get_lvds_mode_from_bios(display_timing* panelTiming)
lvds2_lfp_info = (struct lvds_bdb2_lfp_info *) lvds2_lfp_info = (struct lvds_bdb2_lfp_info *)
(vbios.memory + bdbOffset (vbios.memory + bdbOffset
+ lvds2->panels[panelType].lfp_info_offset); + lvds2->panels[panelType].lfp_info_offset);
/* check terminator */ /* Show terminator: Check not done in drm i915 driver: Assuming chk not valid. */
if (lvds2_lfp_info->terminator != 0xffff) { TRACE((DEVICE_NAME ": LFP info terminator %x\n", lvds2_lfp_info->terminator));
TRACE((DEVICE_NAME ": Incorrect LFP info terminator %x\n",
lvds2_lfp_info->terminator));
#if 0
// FIXME the terminator is not present on my SandyBridge
// laptop, but the video mode is still correct. Maybe the
// format of the block has changed accross versions. We
// could check the size of the block to detect different
// layouts.
delete_area(vbios.area);
return false;
#endif
}
uint8_t* timing_data = vbios.memory + bdbOffset uint8_t* timing_data = vbios.memory + bdbOffset
+ lvds2->panels[panelType].lfp_edid_dtd_offset; + lvds2->panels[panelType].lfp_edid_dtd_offset;
TRACE((DEVICE_NAME ": found LFP of size %d x %d " TRACE((DEVICE_NAME ": found LFP of size %d x %d "