Acer H243HをDVIで接続すると認識しない。VGA接続とHDMI接続では正常に動作するが、DVIで接続するとsyslogに以下のエラーが出る。

Jan  5 23:48:32 haramaki kernel: [97894.621687] amdgpu 0000:01:00.0: DVI-D-1: EDID is invalid:
Jan  5 23:48:32 haramaki kernel: [97894.621694]         [00] BAD  00 ff ff ff ff ff ff 00 ff ff ff ff ff ff ff ff
Jan  5 23:48:32 haramaki kernel: [97894.621696]         [00] BAD  2b 13 01 03 80 35 1d 78 ea 60 85 a6 56 4a 9c 25
Jan  5 23:48:32 haramaki kernel: [97894.621697]         [00] BAD  12 50 54 af cf 00 81 80 71 4f 95 00 95 0f a9 40
Jan  5 23:48:32 haramaki kernel: [97894.621698]         [00] BAD  b3 00 01 01 01 01 1a 36 80 a0 70 38 1f 40 30 20
Jan  5 23:48:32 haramaki kernel: [97894.621699]         [00] BAD  35 00 13 2a 21 00 00 1a 00 00 00 fc 00 48 32 34
Jan  5 23:48:32 haramaki kernel: [97894.621700]         [00] BAD  33 48 0a 20 20 20 20 20 20 20 00 00 00 fd 00 38
Jan  5 23:48:32 haramaki kernel: [97894.621701]         [00] BAD  4c 1f 53 12 00 0a 20 20 20 20 20 20 00 00 00 ff
Jan  5 23:48:32 haramaki kernel: [97894.621702]         [00] BAD  00 4c 45 57 30 43 30 31 34 34 30 31 31 0a 00 33

どうやらEDIDが壊れているようだ。

LinuxからモニターのEDID ROMを読み書きするには

モニターには EDID(利用可能な解像度・リフレッシュレート・メーカー名・型番などの情報)が格納されたROMが搭載されており、PCとVESA Display Data Channel(I2Cベースのバス)で接続されている。

このROMはLinuxからI2Cデバイスとして認識されているので、I2Cバス操作用のツールでROMを読み書きすることができる。

DVIのEDID ROMが繋っているバスを探す

rootでi2cdetect -l を実行し、バスの一覧を出す

# i2cdetect -l
i2c-3	i2c       	AMDGPU DM i2c hw bus 2          	I2C adapter
i2c-1	i2c       	dmdc                            	I2C adapter
i2c-2	i2c       	AMDGPU DM i2c hw bus 1          	I2C adapter
i2c-0	i2c       	AMDGPU DM i2c hw bus 0          	I2C adapter

出力からバス0,2,3がGPUのものであることが分かるが、どのポートのものであるかまでは分からないので総当たりでダンプする。 rootでi2cdump (バス番号) 0x50 を実行するとEDIDをダンプできる。

# echo Y | i2cdump 0 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-0, address 0x50, mode byte
Continue? [Y/n] 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
80: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX

# echo Y | i2cdump 2 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-2, address 0x50, mode byte
Continue? [Y/n] 
     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 2a 59 00 28 00 00 00 00    ........*Y.(....
10: 19 19 01 03 80 3e 22 78 ea 1e c5 ae 4f 34 b1 26    ?????>"x????O4?&
20: 0e 50 54 af cf 00 d1 00 d1 c0 b3 00 a9 c0 95 00    ?PT??.?.???.???.
30: 81 81 81 00 71 40 04 74 00 30 f2 70 5a 80 30 20    ???.q@?t.0?pZ?0 
40: 36 00 70 fe 31 00 00 1a 56 5e 00 a0 a0 a0 29 50    6.p?1..?V^.???)P
50: 30 20 36 00 70 fe 31 00 00 1a 00 00 00 fd 00 1e    0 6.p?1..?...?.?
60: a0 17 50 19 00 0a 20 20 20 20 20 20 00 00 00 fc    ??P?.?      ...?
70: 00 55 48 44 20 48 44 4d 49 0a 20 20 20 20 01 63    .UHD HDMI?    ?c
80: 02 03 43 f3 58 61 90 05 04 60 65 66 03 02 07 16    ??C?Xa???`ef????
90: 01 1f 12 13 14 20 15 11 06 5d 5e 5f 62 23 09 07    ????? ???]^_b#??
a0: 07 83 01 00 00 e3 05 03 01 e2 0f 71 6e 03 0c 00    ???..??????qn??.
b0: 10 00 38 3d 20 00 80 01 02 03 04 67 d8 5d c4 01    ?.8= .?????g?]??
c0: 78 c0 00 02 3a 80 18 71 38 2d 40 58 2c 45 00 13    x?.?:??q8-@X,E.?
d0: 2b 21 00 00 1a 02 3a 80 d0 72 38 2d 40 30 20 45    +!..??:??r8-@0 E
e0: 00 06 44 21 00 00 1a 01 1d 80 18 71 1c 16 20 58    .?D!..?????q?? X
f0: 2c 25 00 06 44 21 00 00 9e 00 00 00 00 00 00 a0    ,%.?D!..?......?

# echo Y | i2cdump 3 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-3, address 0x50, mode byte
Continue? [Y/n] 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
10:  2b 13 01 03 80 35 1d 78 ea 60 85 a6 56 4a 9c 25   +....5.x.`..VJ.%
20:  12 50 54 af cf 00 81 80 71 4f 95 00 95 0f a9 40   .PT.....qO.....@
30:  b3 00 01 01 01 01 1a 36 80 a0 70 38 1f 40 30 20   .......6..p8.@0 
40:  35 00 13 2a 21 00 00 1a 00 00 00 fc 00 48 32 34   5..*!........H24
50:  33 48 0a 20 20 20 20 20 20 20 00 00 00 fd 00 38   3H.       .....8
60:  4c 1f 53 12 00 0a 20 20 20 20 20 20 00 00 00 ff   L.S...      ....
70:  00 4c 45 57 30 43 30 31 34 34 30 31 31 0a 00 33   .LEW0C0144011..3
80:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
90:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
a0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
b0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
c0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
d0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
e0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
f0:  ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................

EDIDの内容から、このカードではバス番号2がHDMIのバスで、バス番号3がDVIポートのバスであることがわかる。

正常なEDIDを吸い出す

モニタを正常なポート(HDMI)で接続し、正常なEDIDを吸い出す

# echo Y | i2cdump 2 0x50 > edid-h243h-hdmi.txt
$ vim edid-h243h-hdmi.txt
(マクロで余計なデータを取り除いてhex dumpに変換)
$ xxd -r -p < edid-h243h-hdmi.txt > edid-h243h-hdmi.bin

DVIポートのEDIDの修復

モニタをDVIで接続し、正常なEDIDを書き込む

$ cat <<'EOS' >edidwrite.py
#!/usr/bin/python3
import sys
import os

with open(sys.argv[2], "rb") as f:
    edid = f.read()

for i, byt in enumerate(edid):
    os.system("echo Y | i2cset %d 0x50 0x%02x 0x%02x b" % (int(sys.argv[1]), i, byt))
    os.system("sleep 0.1")
EOS
$ sudo python3 edidwrite.py 3 edid-h243h-hdmi.bin
正常に認識されるようになった 正常に認識されるようになった

おまけ

EDIDをいじるとこういうこともできる

💰FlexScan💰 になったH243H 💰FlexScan💰 になったH243H