2020/10/15

外付けディスプレイの色が変なのを直す

MacBook Air mid 2011につないだディスプレイが画像のBeforeのように色が変になったのを、元のEDIDをHDMI用のEDIDでオーバーライドすることで、Afterのように直した。ハードウェアを変更するのではなくあくまでソフト的に。

LCD before and after EDID modification







環境及び使用したソフトなど

  • MacBook Air mid 2011
  • macOS 10.13.6
  • 外付けディスプレイ: Raspberry Pi HDMI IPS Touch Screen LCD (10.1 inch) (Seeed studio)
  • Mini DisplayPort-HDMI変換アダプタ: AD-MDPHDMIWH (ELECOM)
  • HDMIケーブル: DH-HD14SS20BK (ELECOM)
  • 接続方法: MacBook Air ー mini DP-HDMI変換ケーブル ー HDMIケーブル ー 外付けディスプレイ
  • ソフト: ターミナル、Xcode

適宜sudoを使う(以下sudoなしで書いている)のと、必要なタイミングでSIPを無効化して作業した。


方法

まず、/System/Library/Displays/Contents/Resourcesに行き、ディスプレイのEDIDオーバーライド用のファイルがあるOverridesディレクトリを次のコマンドでバックアップする。

cp -R Overfides Overrides.bak


次に、現在のEDIDの値を取得

ioreg -lw0 | grep Display

として、自分の場合はAppleBacklightDisplayではないほうが外部ディスプレイの情報である。

それは、

"IOClass" = "AppleDisplay"

"DisplayProductID" = 837

"IODisplayPrefsKey" = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/IGPU@2/AppleIntelFramebuffer@1/display0/AppleDisplay-30e4-345"

"DisplayVendorID" = 12516

"IODisplayEDID" = <00ffffffffffff0030e44503000000000015010490160e7802e887965a559528225155000000010101010101010101010101010101014c1d00ec5020183040305700d9880000001b1612008050201630ffffffffffffffff001b000000fe00433347524e803130315758310a0000000000004132a80000000001010a2020009a>

である。

ここで、ディスプレイのEDIDオーバーライド用のファイルがある/System/Library/Displays/Contents/Resources/Overridesに、DisplayVendorID-30e4 (30e4はIODisplayPrefsKeyに由来)というディレクトリを作成し、その中にDisplayProductID-345.plist (345はIODisplayPrefsKeyに由来)というファイルを作成する。その中身は以下。(いくつかの文言は先ほど表示した値を参考に書く)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>DisplayProductName</key>
  <string>Display (EDID override)</string>
  <key>IODisplayEDID</key>
  <data>
</data>
  <key>DisplayVendorID</key>
  <integer>12516</integer>
  <key>DisplayProductID</key>
  <integer>837</integer>
</dict>
</plist>

ここで、DisplayProductID-345.plistをXcodeで開き、IODisplayEDIDに、先ほど表示したIODisplayEDID(前後は<と>で囲む)を書き込む。直接書き換えられない場合は、別の場所で同じ内容のファイルを作成して、あとでcpコマンドでコピーして上書きする。


ここで、XcodeでIODisplayEDIDの20 Byte目の値を書き換えたい。具体的には、<00ffffffffffff0030e44503000000000015010490...>の途中(ここでは...の前)の90(Digital input, Color Bit Depth: 6, Video interface: undefined)をHDMI用の設定: 

Digital input

Color Bit depth: 8

Video interface: HDMIa

にしたい。これは英語版のwikipediaのDEIDの解説によると、

Bit 7: 1

Bit 6-4: 010

Bit 3-0: 0010

で、10100010ということになる。これの16進数表示はa2で、問題の「90」の部分をこのa2で置き換え、上書き保存する(実はDigital input以外undefinedの80でもいけた)。次に、DisplayProductID-345.plistというファイル名の拡張子を除去しDisplayProductID-345という名前に直す。そして、ディスプレイをつなぎ直すと、、、

乱れていたのが直った!めでたしめでたし。


その他

一応直ったものの、何の値が本当にいいのかはよくわからない。実はa5(DP用)でも問題なかったし、接続方法を考えると、本当はDPがいいのかHDMIがいいのか、、、?。とにかく今回はColor Bit Depthを8かundefinedにすることが重要だったようだ。


おまけ

cmd + "brightness up"でDetect Displaysができる。いちいちSystem PreferencesのDisplayでoptionを押しながら右下のDetect Displaysボタンを押さなくてすむ。しかもSystem Preferencesが開けないロック画面でも実行はできる(でも画面は映らないかも)。ちなみにoption + "brightness up"でSystem PreferencesのDisplaysを開ける。