, 2 min read
Patching Faulty EDID Information
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.
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).
// This program was written by Gordian Edenhofer on 04-May-2014
// It is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
// Simple EDID Manipulation Tool
// Usage: semt [Inputfile] [X-Resolution] [Y-Resolution] [Outputfile] [Options]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
int i, c, x_res, y_res, checksum = 0, debug=0;
unsigned char edid[128];
FILE *fp;
while ((c = getopt(argc,argv,"dvh")) != -1) {
// ...
}
if (argc-optind != 4) {
printf("%s: is meant to be used with the following arguments [Inputfile] [X-Resolution] [Y-Resolution] [Outputfile]\n",argv[0]);
return 1;
}
if ((fp = fopen(argv[optind],"r")) == NULL) { ... }
if (fread( edid, 1, 128, fp ) != 128) { ... }
if (fclose(fp) != 0) { ... }
x_res = atoi(argv[optind+1]);
y_res = atoi(argv[optind+2]);
// Dumping X-Resolution to EDID
edid[56] = x_res%256;
edid[58] = (x_res/256)*16;
edid[74] = x_res%256;
edid[76] = (x_res/256)*16;
// Dumping Y-Resolution to EDID
edid[59] = y_res%256;
edid[61] = (y_res/256)*16;
edid[77] = y_res%256;
edid[79] = (y_res/256)*16;
y_res = atoi(argv[optind+2]);
// Dumping X-Resolution to EDID
edid[56] = x_res%256;
edid[58] = (x_res/256)*16;
edid[74] = x_res%256;
edid[76] = (x_res/256)*16;
// Dumping Y-Resolution to EDID
edid[59] = y_res%256;
edid[61] = (y_res/256)*16;
edid[77] = y_res%256;
edid[79] = (y_res/256)*16;
// Calculating and writing the checksum
for (i=0; i<=126; ++i)
checksum += edid[i];
checksum %= 256;
edid[127] = (256-checksum)%256;
if ((fp = fopen(argv[optind+3],"w")) == NULL) { ... }
if (fwrite(edid,1,128,fp) != 128) { ... }
if (fclose(fp) != 0) { ... }
return 0;
}
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/.