intel_extreme: expand bios scan for panel a bit, might help ticket #17451
This commit is contained in:
@@ -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 "
|
||||||
|
|||||||
Reference in New Issue
Block a user