Dell S3225QSのDDC/CI通信が失敗する問題の解決とコマンドラインからの入力切替(Linux / Mac)

Arch LinuxベースのOmarchyで、Dell S3225QS(4Kモニター)をHDMI接続した際に、ddcutilでDDC/CI通信がcommunication failedとなる問題に遭遇した。本記事では、原因の切り分けから解決、ddcutilを使ったモニターの入力切替、さらにmacOSで同じことをする方法までを記録する。

環境

  • OS: Arch Linux(Omarchy)
  • カーネル: 6.18.7-arch1-1
  • GPU: AMD Phoenix1(APU) / ドライバ: amdgpu
  • モニター: Dell S3225QS(HDMI接続)
  • ddcutil: 2.2.5

症状

ddcutil detectを実行すると、HDMI接続のDell S3225QSで「DDC communication failed」が発生した。

1
2
3
4
5
6
Invalid display
   I2C bus:  /dev/i2c-1
      DRM_connector:           card1-HDMI-A-2
      ...
   DDC communication failed
   Failure detail: getvcp of feature x10 returned Error_Info[DDCRC_RETRIES in ddc_write_read_with_retry, causes: DDCRC_DDC_DATA(10)]

エラーの内容はDDCRC_DDC_DATAが10回リトライしてすべて失敗、というもの。

一方で、同じマシンにDisplayPort接続していた別のモニター(JAPANNEXT)では正常にDDC/CIが動作していた。

確認したこと

環境面に問題はなかった

ddcutil environmentで確認したところ、以下はすべて正常だった。

  • i2c-devモジュールがロード済み
  • /dev/i2c-*デバイスが存在し、権限も問題なし(i2cグループ、RW権限)
  • amdgpuドライバが正しく認識されている

モニター側の設定も問題なかった

Dell S3225QSのOSDメニューでDDC/CIは「有効」に設定されていた。

I2Cレベルでは応答していた

ddcutil detect --verboseの出力を見ると、I2Cレベルではモニターは応答している。

1
I2C address 0x37 (DDC) responsive: true

つまり、I2Cの物理層は問題なく、DDC/CIプロトコルレベルでデータのやり取りに失敗している状態だった。

原因

amdgpuドライバ + HDMI接続の環境では、ユーザースペースからI2Cバスを直接叩くDDC/CI通信がタイミングの問題で失敗することがある。

ddcutil 2.xでは、I2Cバスを直接操作する方法と、カーネルのDRM(Direct Rendering Manager)コネクタAPI経由で通信する方法の2つが選べる。DRM経由の場合、amdgpuドライバが通信を仲介するため、タイミングの問題が回避される。

解決方法

バス番号を明示して通信する

Dell S3225QSはI2Cバス1(/dev/i2c-1)に接続されていたので、--busオプションでバスを明示指定することでDDC/CI通信が成功した。

1
ddcutil detect --bus 1
1
2
3
4
5
6
7
8
9
Display 1
   I2C bus:  /dev/i2c-1
   DRM_connector:           card1-HDMI-A-2
   EDID synopsis:
      Mfg id:               DEL - Dell Inc.
      Model:                DELL S3225QS
      Product code:         53673  (0xd1a9)
      Serial number:        J33WR44
   VCP version:         2.1

ddcutilでモニターの入力を切り替える

DDC/CI通信が正常に動作するようになったので、ddcutilを使ってモニターの入力ソースをコマンドラインから切り替えられる。

対応している入力ソースを確認する

ddcutil capabilitiesでモニターがサポートしているVCP機能を確認できる。Feature 60(Input Source)の項目を見る。

1
ddcutil capabilities --bus 1 | grep -A 10 "Feature: 60"
1
2
3
4
5
Feature: 60 (Input Source)
   Values:
      0f: DisplayPort-1
      11: HDMI-1
      12: HDMI-2

Dell S3225QSでは、3つの入力ソースが利用可能だった。

現在の入力ソースを確認する

1
ddcutil getvcp 60 --bus 1
1
VCP code 0x60 (Input Source): HDMI-1 (sl=0x11)

入力を切り替える

ddcutil setvcpで入力ソースを変更できる。

1
2
3
4
5
6
7
8
# HDMI-1に切り替え
ddcutil setvcp 60 0x11 --bus 1

# HDMI-2に切り替え
ddcutil setvcp 60 0x12 --bus 1

# DisplayPort-1に切り替え
ddcutil setvcp 60 0x0f --bus 1

エイリアスを設定して使いやすくする

頻繁に切り替えるなら、シェルのエイリアスを設定しておくと便利だ。

1
2
3
4
5
# ~/.bashrc や ~/.zshrc に追加
alias dell-hdmi1='ddcutil setvcp 60 0x11 --bus 1'
alias dell-hdmi2='ddcutil setvcp 60 0x12 --bus 1'
alias dell-dp='ddcutil setvcp 60 0x0f --bus 1'
alias dell-input='ddcutil getvcp 60 --bus 1'

これで、ターミナルからdell-hdmi2と打つだけでモニターの入力をHDMI-2に切り替えられる。物理ボタンでOSDを操作する必要がなくなり、KVMスイッチ的な運用やスクリプトによる自動切替も可能になる。

macOSで同じことをする

ddcutilはLinux専用のため、macOSでは別のツールを使う。

m1ddc(Apple Silicon Mac向け)

Apple Silicon Macならm1ddcが使える。

1
brew install m1ddc

VCPコードの値はddcutilと同じだが、16進数ではなく10進数で指定する点に注意。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 現在の入力を確認
m1ddc get input

# 入力を切り替え
m1ddc set input 17    # HDMI-1 (0x11 = 17)
m1ddc set input 18    # HDMI-2 (0x12 = 18)
m1ddc set input 15    # DisplayPort-1 (0x0f = 15)

# 輝度の取得・設定もできる
m1ddc get luminance
m1ddc set luminance 50

ddcctl(Intel Mac向け)

Intel Macの場合はddcctlを使う。

1
brew install ddcctl
1
ddcctl -d 1 -i 17    # ディスプレイ1の入力をHDMI-1に

BetterDisplay(GUI)

GUIで操作したいならBetterDisplayが便利だ。DDC/CI経由の入力切替や輝度調整がメニューバーからできる。

1
brew install --cask betterdisplay

macOSでのエイリアス(m1ddc)

1
2
3
4
5
# ~/.bashrc や ~/.zshrc に追加
alias dell-hdmi1='m1ddc set input 17'
alias dell-hdmi2='m1ddc set input 18'
alias dell-dp='m1ddc set input 15'
alias dell-input='m1ddc get input'

Linux / Mac共用のdotfilesを使っている場合

OS判定で切り替えれば、同じdotfilesをLinuxとMacで共有できる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Dell S3225QS 入力切替
if [[ "$(uname)" == "Darwin" ]]; then
  alias dell-hdmi1='m1ddc set input 17'
  alias dell-hdmi2='m1ddc set input 18'
  alias dell-dp='m1ddc set input 15'
  alias dell-input='m1ddc get input'
else
  alias dell-hdmi1='ddcutil setvcp 60 0x11 --bus 1'
  alias dell-hdmi2='ddcutil setvcp 60 0x12 --bus 1'
  alias dell-dp='ddcutil setvcp 60 0x0f --bus 1'
  alias dell-input='ddcutil getvcp 60 --bus 1'
fi

macOSでDDC/CIが動かない場合

USB-C→HDMI変換アダプタ経由で接続している場合、DDCラインが通っていないアダプタが多い。その場合はDDC対応を謳っているアダプタ(CalDigitやBelkinなど)を使う必要がある。

まとめ

  • amdgpu + HDMI接続の環境では、ddcutilのDDC/CI通信がDDCRC_DDC_DATAエラーで失敗することがある
  • ddcutil environmentで環境面に問題がなく、モニター側のDDC/CI設定も有効なのに通信が失敗する場合は、--busオプションでI2Cバスを明示指定すると通信が成功する場合がある
  • DDC/CIが動作すれば、VCPコード60(Input Source)でモニターの入力切替がコマンドラインから可能になる
  • macOSではm1ddc(Apple Silicon)やddcctl(Intel)で同様の操作ができる
  • エイリアスやOS判定を使えば、Linux / Mac共通のdotfilesで運用できる

同じ構成で悩んでいる人の参考になれば幸いだ。

カテゴリ

comments powered by Disqus