From: "Antonino A. Daplas" Check first if EDID block came from a broken display before fixing. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton --- 25-akpm/drivers/video/fbmon.c | 69 ++++++++++++++++++++++++++++-------------- 1 files changed, 46 insertions(+), 23 deletions(-) diff -puN drivers/video/fbmon.c~fbdev-cleanup-broken-edid-fixup-code drivers/video/fbmon.c --- 25/drivers/video/fbmon.c~fbdev-cleanup-broken-edid-fixup-code Thu Jan 13 15:40:47 2005 +++ 25-akpm/drivers/video/fbmon.c Thu Jan 13 15:40:47 2005 @@ -89,11 +89,12 @@ static void copy_string(unsigned char *c while (i-- && (*--s == 0x20)) *s = 0; } -static void fix_edid(unsigned char *edid) +static int check_edid(unsigned char *edid) { unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4]; unsigned char *b; - u32 model, i; + u32 model; + int i, fix = 0, ret = 0; manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@'; manufacturer[1] = ((block[0] & 0x03) << 3) + @@ -105,36 +106,57 @@ static void fix_edid(unsigned char *edid for (i = 0; i < ARRAY_SIZE(brokendb); i++) { if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && brokendb[i].model == model) { - printk("fbmon: The EDID Block of " "Manufacturer: %s Model: 0x%x is known to " "be broken,\n", manufacturer, model); - switch (brokendb[i].fix) { - case FBMON_FIX_HEADER: - printk("fbmon: trying a header " - "reconstruct\n"); - memcpy(edid, edid_v1_header, 8); - break; - case FBMON_FIX_INPUT: - printk("fbmon: trying to fix input type\n"); - b = edid + EDID_STRUCT_DISPLAY; - /* Only if display is GTF capable will - the input type be reset to analog */ - if (b[4] & 0x01) { - b[0] &= ~0x80; - edid[127] += 0x80; - } - } + fix = brokendb[i].fix; + break; + } + } + + switch (fix) { + case FBMON_FIX_HEADER: + for (i = 0; i < 8; i++) { + if (edid[i] != edid_v1_header[i]) + ret = fix; } + break; + case FBMON_FIX_INPUT: + b = edid + EDID_STRUCT_DISPLAY; + /* Only if display is GTF capable will + the input type be reset to analog */ + if (b[4] & 0x01 && b[0] & 0x80) + ret = fix; + break; + } + + return ret; +} + +static void fix_edid(unsigned char *edid, int fix) +{ + unsigned char *b; + + switch (fix) { + case FBMON_FIX_HEADER: + printk("fbmon: trying a header reconstruct\n"); + memcpy(edid, edid_v1_header, 8); + break; + case FBMON_FIX_INPUT: + printk("fbmon: trying to fix input type\n"); + b = edid + EDID_STRUCT_DISPLAY; + b[0] &= ~0x80; + edid[127] += 0x80; } } static int edid_checksum(unsigned char *edid) { unsigned char i, csum = 0, all_null = 0; - int err = 0; + int err = 0, fix = check_edid(edid); - fix_edid(edid); + if (fix) + fix_edid(edid, fix); for (i = 0; i < EDID_LENGTH; i++) { csum += edid[i]; @@ -151,9 +173,10 @@ static int edid_checksum(unsigned char * static int edid_check_header(unsigned char *edid) { - int i, err = 1; + int i, err = 1, fix = check_edid(edid); - fix_edid(edid); + if (fix) + fix_edid(edid, fix); for (i = 0; i < 8; i++) { if (edid[i] != edid_v1_header[i]) _