Repairing broken EDID of monitor
Introduction
Recently I tried out a HDMI stick at my monitor. It’s the same monitor, I repaired back then in Repairing Hyundai W240D monitor. After I was finished with the HDMI stick I reconnected my laptop again, but - uh oh: The resolution was not recognized anymore.
I was presented with an ugly 640x480 resolution. The first things like plugging the monitor in again or switching it off and on again didn’t help. I could select between 640x480, 800x600 and 1024x768. And the monitor was recognized as “unnamed monitor”.
So, looking at the logs - maybe I see some error. And I got lucky: The kernel logged the following line:
kernel: EDID block 0 (tag 0x00) checksum is invalid, remainder is 66
That’s strange. Seems like the monitor doesn’t identify itself anymore. Searching the interwebs brought me to a wonderful page, which exactly explains, what I need to do: https://wiki.debian.org/RepairEDID.
The following is a step-by-step description of what I did to get it working again. In case, it happens again, I hopefully remember that this issue can be fixed.
The commands
Reading the EDID EEPROM
First step is to read out the EDID EEPROM. We use two kernel modules to get access to this:
$ modprobe i2c-dev
$ modprobe eeprom
Then we can search for EDID EEPROMs. These have the property, that they are at address 0x0050
on the i2c bus:
$ ls -al /sys/bus/i2c/devices/*-0050/eeprom
-r--r--r-- 1 root root 256 26. Nov 12:09 /sys/bus/i2c/devices/6-0050/eeprom
-r--r--r-- 1 root root 256 26. Nov 12:09 /sys/bus/i2c/devices/7-0050/eeprom
These are the two EEPROMs I have. Both are 256 bytes big.
One is for the internal laptop display, the other is the broken monitor.
We can verify the contents of this EEPROMs by using parse-edid
:
$ apt install read-edid
$ cat /sys/bus/i2c/devices/6-0050/eeprom|parse-edid
Checksum Correct
Section "Monitor"
Identifier ""
ModelName ""
VendorName "SHP"
# Monitor Manufactured week 50 of 2014
# EDID version 1.4
# Digital Display
DisplaySize 290 170
Gamma 2.20
Option "DPMS" "false"
Modeline "Mode 0" -hsync -vsync
EndSection
$ cat /sys/bus/i2c/devices/7-0050/eeprom|parse-edid
WARNING: Checksum failed
Trying to continue...
Section "Monitor"
Identifier "W240D DVI"
ModelName "W240D DVI"
VendorName "HIT"
# Monitor Manufactured week 30 of 2007
# EDID version 1.3
# Digital Display
DisplaySize 520 320
Gamma 2.20
Option "DPMS" "false"
Horizsync 30-83
VertRefresh 59-76
# Maximum pixel clock is 180MHz
#Not giving standard mode: 1920x1200, 60Hz
#Not giving standard mode: 1600x1200, 60Hz
#Not giving standard mode: 1680x1050, 60Hz
#Not giving standard mode: 1280x1024, 60Hz
#Extension block found. Parsing...
Modeline "Mode 11" -hsync -vsync
Modeline "Mode 0" +hsync -vsync
Modeline "Mode 1" +hsync +vsync
Modeline "Mode 2" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
Modeline "Mode 3" 74.250 1920 2448 2492 2640 1080 1082 1089 1125 +hsync +vsync interlace
Modeline "Mode 4" 74.250 1280 1720 1760 1980 720 725 730 750 +hsync +vsync
Modeline "Mode 5" 27.000 720 732 796 864 576 581 586 625 -hsync -vsync
Modeline "Mode 6" 74.250 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace
Modeline "Mode 7" 74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync
Modeline "Mode 8" 27.027 720 736 798 858 480 489 495 525 -hsync -vsync
Modeline "Mode 9" 27.027 720 736 798 858 480 489 495 525 -hsync -vsync
Modeline "Mode 10" 25.200 640 656 752 800 480 490 492 525 -hsync -vsync
Modeline "Mode 12" +hsync +vsync interlace
Modeline "Mode 13" +hsync +vsync
Modeline "Mode 14" -hsync -vsync
Option "PreferredMode" "Mode 11"
EndSection
The second one is the problematic one, as indicated by “WARNING: Checksum failed”. But most data seems still to be there, so not too bad. The EEPROM is still there and didn’t loose all the data.
A hexdump and the difference
Let’s have a look at the hexdump:
$ cat /sys/bus/i2c/devices/7-0050/eeprom|hd
00000000 00 ff ff ff ff ff ff 00 21 34 03 7d 43 41 32 01 |........!4.}CA2.|
00000010 1e 11 01 03 80 34 20 78 0a ef 95 a3 54 4c 9b 26 |.....4 x....TL.&|
00000020 00 50 54 ad cf 00 d1 00 a9 40 b3 00 81 80 01 01 |.PT......@......|
00000030 01 01 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20 |......(<..p.#@0 |
00000040 36 00 08 40 21 00 00 1a 48 3f 40 30 62 b0 32 40 |6..@!...H?@0b.2@|
00000050 40 c0 13 00 08 40 21 00 00 1e 00 00 00 fd 00 3b |@....@!........;|
00000060 4c 1e 53 12 00 0a 20 20 20 20 20 20 00 00 00 fc |L.S... ....|
00000070 00 57 32 34 30 44 20 44 56 49 0a 20 20 20 01 33 |.W240D DVI. .3|
00000080 02 03 1c 71 49 90 14 13 12 05 04 03 02 01 23 09 |...qI.........#.|
00000090 07 07 83 01 00 00 65 03 0c 00 10 00 8c 0a d0 90 |......e.........|
000000a0 20 40 31 20 0c 40 55 00 13 8e 21 00 00 18 01 1d | @1 .@U...!.....|
000000b0 80 18 71 1c 16 20 58 2c 25 00 c4 8e 21 00 00 9e |..q.. X,%...!...|
000000c0 01 1d 00 72 51 d0 1e 20 6e 28 55 00 c4 8e 21 00 |...rQ.. n(U...!.|
000000d0 00 1e 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 c4 8e |...... .-..>....|
000000e0 21 00 00 18 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 |!....... .-..>..|
000000f0 13 8e 21 00 00 18 00 00 00 00 00 00 00 00 00 c4 |..!.............|
These are the 256 bytes of the EEPROM for which the checksum is not correct.
Luckily, I also backed up the EDID data when I repaired the monitor the last time. This backup is in the form of a blog post, see Repairing Hyundai W240D monitor. Now, taking the correct EEPROM content at that time:
and
cat /sys/class/drm/card0/card0-DP-1/edid | hd
:00000000 00 ff ff ff ff ff ff 00 21 34 03 7d 43 41 32 01 |........!4.}CA2.| 00000010 1e 11 01 03 80 34 20 78 0a ef 95 a3 54 4c 9b 26 |.....4 x....TL.&| 00000020 0f 50 54 ad cf 00 d1 00 a9 40 b3 00 81 80 01 01 |.PT......@......| 00000030 01 01 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20 |......(<..p.#@0 | 00000040 36 00 08 40 21 00 00 1a 48 3f 40 30 62 b0 32 40 |6..@!...H?@0b.2@| 00000050 40 c0 13 00 08 40 21 00 00 1e 00 00 00 fd 00 3b |@....@!........;| 00000060 4c 1e 53 12 00 0a 20 20 20 20 20 20 00 00 00 fc |L.S... ....| 00000070 00 57 32 34 30 44 20 44 56 49 0a 20 20 20 01 33 |.W240D DVI. .3| 00000080 02 03 1c 71 49 90 14 13 12 05 04 03 02 01 23 09 |...qI.........#.| 00000090 07 07 83 01 00 00 65 03 0c 00 10 00 8c 0a d0 90 |......e.........| 000000a0 20 40 31 20 0c 40 55 00 13 8e 21 00 00 18 01 1d | @1 .@U...!.....| 000000b0 80 18 71 1c 16 20 58 2c 25 00 c4 8e 21 00 00 9e |..q.. X,%...!...| 000000c0 01 1d 00 72 51 d0 1e 20 6e 28 55 00 c4 8e 21 00 |...rQ.. n(U...!.| 000000d0 00 1e 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 c4 8e |...... .-..>....| 000000e0 21 00 00 18 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 |!....... .-..>..| 000000f0 13 8e 21 00 00 18 00 00 00 00 00 00 00 00 00 c4 |..!.............|
Can you spot the difference? It’s actually only one single byte, that’s bad: it’s at offset 0x20
: The bad
one has 0x00
but it should be 0x0f
. No idea, what cause this change…
Writing to the EEPROM
First step: Let’s backup the current state of the EEPROM in case we mess up, it will be handy:
$ cat /sys/bus/i2c/devices/7-0050/eeprom > hyundai-monitor-bad-edid.bin
Next step: We will use the i2c utils to write to it. So, let’s first use this tool to dump the content, so that we are sure, we have the correct EEPROM… In the docs I read, there are many warnings about writing to the wrong EEPROM - e.g. the DIMMs also have a EEPROM which store the timing data. If you accidentally write to the wrong EEPROM and write to the DIMMs of your laptop, you practically have bricked your laptop. So, better to be sure.
It should be i2c bus number 7 and address 0x50:
$ i2cdump 7 0x50
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-7, address 0x50, mode byte
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 ff ff ff ff ff ff 00 21 34 03 7d 43 41 32 01 ........!4?}CA2?
10: 1e 11 01 03 80 34 20 78 0a ef 95 a3 54 4c 9b 26 ?????4 x????TL?&
20: 00 50 54 ad cf 00 d1 00 a9 40 b3 00 81 80 01 01 .PT??.?.?@?.????
30: 01 01 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20 ??????(<??p?#@0
40: 36 00 08 40 21 00 00 1a 48 3f 40 30 62 b0 32 40 6.?@!..?H?@0b?2@
50: 40 c0 13 00 08 40 21 00 00 1e 00 00 00 fd 00 3b @??.?@!..?...?.;
60: 4c 1e 53 12 00 0a 20 20 20 20 20 20 00 00 00 fc L?S?.? ...?
70: 00 57 32 34 30 44 20 44 56 49 0a 20 20 20 01 33 .W240D DVI? ?3
80: 02 03 1c 71 49 90 14 13 12 05 04 03 02 01 23 09 ???qI?????????#?
90: 07 07 83 01 00 00 65 03 0c 00 10 00 8c 0a d0 90 ????..e??.?.????
a0: 20 40 31 20 0c 40 55 00 13 8e 21 00 00 18 01 1d @1 ?@U.??!..???
b0: 80 18 71 1c 16 20 58 2c 25 00 c4 8e 21 00 00 9e ??q?? X,%.??!..?
c0: 01 1d 00 72 51 d0 1e 20 6e 28 55 00 c4 8e 21 00 ??.rQ?? n(U.??!.
d0: 00 1e 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 c4 8e .????? ?-??>?.??
e0: 21 00 00 18 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 !..????? ?-??>?.
f0: 13 8e 21 00 00 18 00 00 00 00 00 00 00 00 00 c4 ??!..?.........?
So, we see the same data. And at offset 0x20
there is still the wrong byte 0x00
.
Now let’s fix it:
$ i2cset -y 7 0x50 0x20 0x0F
This sets the byte at offset 0x20 to 0x0F for the EEPROM on bus 7 and address 0x50.
Dump it again, to verify it worked:
$ i2cdump 7 0x50
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-7, address 0x50, mode byte
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 ff ff ff ff ff ff 00 21 34 03 7d 43 41 32 01 ........!4?}CA2?
10: 1e 11 01 03 80 34 20 78 0a ef 95 a3 54 4c 9b 26 ?????4 x????TL?&
20: 0f 50 54 ad cf 00 d1 00 a9 40 b3 00 81 80 01 01 ?PT??.?.?@?.????
30: 01 01 01 01 01 01 28 3c 80 a0 70 b0 23 40 30 20 ??????(<??p?#@0
40: 36 00 08 40 21 00 00 1a 48 3f 40 30 62 b0 32 40 6.?@!..?H?@0b?2@
50: 40 c0 13 00 08 40 21 00 00 1e 00 00 00 fd 00 3b @??.?@!..?...?.;
60: 4c 1e 53 12 00 0a 20 20 20 20 20 20 00 00 00 fc L?S?.? ...?
70: 00 57 32 34 30 44 20 44 56 49 0a 20 20 20 01 33 .W240D DVI? ?3
80: 02 03 1c 71 49 90 14 13 12 05 04 03 02 01 23 09 ???qI?????????#?
90: 07 07 83 01 00 00 65 03 0c 00 10 00 8c 0a d0 90 ????..e??.?.????
a0: 20 40 31 20 0c 40 55 00 13 8e 21 00 00 18 01 1d @1 ?@U.??!..???
b0: 80 18 71 1c 16 20 58 2c 25 00 c4 8e 21 00 00 9e ??q?? X,%.??!..?
c0: 01 1d 00 72 51 d0 1e 20 6e 28 55 00 c4 8e 21 00 ??.rQ?? n(U.??!.
d0: 00 1e 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 c4 8e .????? ?-??>?.??
e0: 21 00 00 18 8c 0a d0 8a 20 e0 2d 10 10 3e 96 00 !..????? ?-??>?.
Looks good! Now we have again “0x0f” at offset “0x20”.
If we now parse the EDID data again:
$ cat /sys/bus/i2c/devices/7-0050/eeprom|parse-edid
Checksum Correct
Section "Monitor"
Identifier "W240D DVI"
ModelName "W240D DVI"
VendorName "HIT"
# Monitor Manufactured week 30 of 2007
# EDID version 1.3
# Digital Display
DisplaySize 520 320
Gamma 2.20
Option "DPMS" "false"
Horizsync 30-83
VertRefresh 59-76
# Maximum pixel clock is 180MHz
#Not giving standard mode: 1920x1200, 60Hz
#Not giving standard mode: 1600x1200, 60Hz
#Not giving standard mode: 1680x1050, 60Hz
#Not giving standard mode: 1280x1024, 60Hz
#Extension block found. Parsing...
Modeline "Mode 11" -hsync -vsync
Modeline "Mode 0" +hsync -vsync
Modeline "Mode 1" +hsync +vsync
Modeline "Mode 2" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
Modeline "Mode 3" 74.250 1920 2448 2492 2640 1080 1082 1089 1125 +hsync +vsync interlace
Modeline "Mode 4" 74.250 1280 1720 1760 1980 720 725 730 750 +hsync +vsync
Modeline "Mode 5" 27.000 720 732 796 864 576 581 586 625 -hsync -vsync
Modeline "Mode 6" 74.250 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace
Modeline "Mode 7" 74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync
Modeline "Mode 8" 27.027 720 736 798 858 480 489 495 525 -hsync -vsync
Modeline "Mode 9" 27.027 720 736 798 858 480 489 495 525 -hsync -vsync
Modeline "Mode 10" 25.200 640 656 752 800 480 490 492 525 -hsync -vsync
Modeline "Mode 12" +hsync +vsync interlace
Modeline "Mode 13" +hsync +vsync
Modeline "Mode 14" -hsync -vsync
Option "PreferredMode" "Mode 11"
EndSection
Now we get again “Checksum Correct”.
Testing
Ok, next step: Replug display cable. Then something unexpected happend: The monitor didn’t display anything at all. In the OSD (on screen display) menu, it said the resolution was “1921x1200”, which doesn’t work of course.
I simply chose the option “recall” in the OSD, which I think is kind of a reset to factory defaults. And voila - the monitor works again.
Cleanup
Since writing to i2c devices can be dangerous, it’s better to unload the i2c-dev module again afterwards:
$ modprobe -r i2c-dev
$ modprobe -r eeprom
Further thoughts
According to the specification in wikipedia of Extended Display Identification Data the wrong byte at offset 0x20 is part of the chromatic values. This means, that this broken EDID was probably an accident, as why would the HDMI stick change this? I’ve read, that sometimes these EEPROMs can be messed up, when the monitor is started or plugged in or out. So it’s just bad luck.
The original source was this EDID Repair which mentions another project: EDID Inserter. This sounds like an interesting project. In the office, I also use a KVM switch and sometimes it takes time until the monitor shows an image. Sometimes the monitor is not detected at all. This might be an explanation: When the KVM switch changes the display, it might disconnect also the DDC (Display Data Channel) which transports the EDID. And this inserter tries to solve the problem by connecting a fixed EEPROM directly so that the graphics card also sees a monitor connected and doesn’t switch the video mode.
Today, there seem to be commercial solutions available, just search for “EDID Emulator”. I would need such a thing for Display Port (not HDMI), but that’s maybe not so easy, as the i2c lines are maybe not directly exposed, see DDC over Display Port.
There are maybe other solutions possible - at least for linux. Search for “Linux Bypass EDID” or https://www.kernel.org/doc/Documentation/EDID/HOWTO.txt and look at this very old question How can I make Linux behave better when EDID is unavailable?.
Maybe it’s worth a try?
Comments
No comments yet.Leave a comment
Your email address will not be published. Required fields are marked *. All comments are held for moderation to avoid spam and abuse.