Patching Faulty EDID Information

· klm's blog


Original post is here: eklausmeier.goip.de

Some computer monitors either do not provide correct EDID, or no EDID at all. An example monitor is LG E2340T. In this case you can provide a hand-crafted EDID file in xorg.conf. For setting the correct screen resolution in the EDID file you can either use a hex-editor, or use below short C program.

[more_WP_Tag] The C program reads a "half-way" working EDID file and changes resolution to the required values. It does this by modifying the bytes at positions (56, 58, 59, 61) and (74, 76, 77, 79).

 1// This program was written by Gordian Edenhofer on 04-May-2014
 2// It is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
 3// Simple EDID Manipulation Tool
 4// Usage: semt [Inputfile] [X-Resolution] [Y-Resolution] [Outputfile] [Options]
 5
 6#include <stdio.h>
 7#include <stdlib.h>
 8#include <unistd.h>
 9
10int main (int argc, char *argv[]) {
11        int i, c, x_res, y_res, checksum = 0, debug=0;
12        unsigned char edid[128];
13        FILE *fp;
14
15        while ((c = getopt(argc,argv,"dvh")) != -1) {
16                // ...
17        }
18
19        if (argc-optind != 4) {
20                printf("%s: is meant to be used with the following arguments [Inputfile] [X-Resolution] [Y-Resolution] [Outputfile]\n",argv[0]);
21                return 1;
22        }
23
24        if ((fp = fopen(argv[optind],"r")) == NULL) { ... }
25        if (fread( edid, 1, 128, fp ) != 128) { ... }
26        if (fclose(fp) != 0) { ... }
27
28        x_res = atoi(argv[optind+1]);
29        y_res = atoi(argv[optind+2]);
30
31        // Dumping X-Resolution to EDID
32        edid[56] = x_res%256;
33        edid[58] = (x_res/256)*16;
34        edid[74] = x_res%256;
35        edid[76] = (x_res/256)*16;
36
37        // Dumping Y-Resolution to EDID
38        edid[59] = y_res%256;
39        edid[61] = (y_res/256)*16;
40        edid[77] = y_res%256;
41        edid[79] = (y_res/256)*16;
42        y_res = atoi(argv[optind+2]);
43
44        // Dumping X-Resolution to EDID
45        edid[56] = x_res%256;
46        edid[58] = (x_res/256)*16;
47        edid[74] = x_res%256;
48        edid[76] = (x_res/256)*16;
49
50        // Dumping Y-Resolution to EDID
51        edid[59] = y_res%256;
52        edid[61] = (y_res/256)*16;
53        edid[77] = y_res%256;
54        edid[79] = (y_res/256)*16;
55
56        // Calculating and writing the checksum
57        for (i=0; i<=126; ++i)
58                checksum += edid[i];
59        checksum %= 256;
60        edid[127] = (256-checksum)%256;
61
62        if ((fp = fopen(argv[optind+3],"w")) == NULL) { ... }
63        if (fwrite(edid,1,128,fp) != 128) { ... }
64        if (fclose(fp) != 0) { ... }
65
66        return 0;
67}

The complete source code for semt.c is in GitHub. An example EDID file is in edid.bin.

The difficulty was to come up with the correct bytes to change. The program parse-edid in read-edid was a very helpful guide here. parse-edid is contained in Debian package read-edid.

Using the modified EDID in xorg.conf goes like this:

Section "Screen"
        Identifier     "Screen0"
        Device         "Device0"
        Monitor        "Monitor0"
        DefaultDepth    24
        Option         "CustomEDID" "CRT-1:/etc/X11/LG2.bin"
#       Option         "UseEdid" "False"
        Option         "TwinView" "0"
        Option         "metamodes" "1920x1080 +0+0"

        SubSection     "Display"
                Depth       24
        EndSubSection
EndSection


Section "Device"
        Identifier      "Device0"
#       Option  "NoLogo"        "True"
EndSection

Use either CRT-0 or CRT-1 depending on which connector of the graphic card the monitor is plugged on.

More on EDID and fixing stuff in xorg.conf: Workaround buggy HDMI audio with EDID modification. EDID standard is here: EDID standard.

Added 12-Jul-2015: There is an AUR package for semt: aur.archlinux.org/packages/semt/.