HDMI问题处理

最近遇到一个问题,在使用多屏拓展时,在拔插HDMI屏,报错 invalid ELD data byte 13,后发现linux低版本都存在类似问题,做此记录。该问题表示内核在解析 ELD 数据时发现异常(常见于 DP 转 HDMI 的转接头或显示器 EDID 不规范)

EDID介绍

EDID(Extended Display Identification Data,扩展显示标识数据)是由 VESA 协会制定的一套标准数据格式,用来告知主机一些信号源

EDID 数据结构
字段 示例 说明
制造商 & 产品名 DELL U2723QE 品牌与型号
序列号 & 生产日期 CN12345678 追溯与质保
支持的分辨率 1920×1080@60Hz, 3840×2160@30Hz 决定了能否点亮 4K
刷新率范围 24-75 Hz 变频/游戏模式依据
色彩空间 & 位深 RGB444 8bit, YCbCr422 12bit HDR必需
音频能力 LPCM 2-8ch, AC3, DTS 决定能否出声
首选时序 2560×1440@144Hz 最佳分辨率

插上线缆后,显示器会把 HPD(Hot-Plug Detect,19 号引脚)拉到 +5 V,通知源端。源端通过 DDC(Display Data Channel,本质就是 I²C)发起读取。一般EDID是二进制文件,由显示器厂家提供。

解决与规避方案

在一些老版本内核(CentOS 7.9 默认 3.10 内核 + 较旧的 Mesa 驱动)中,DP/HDMI 热插拔经常触发 Bug,尤其是带音频通道的 DP → HDMI 转换。Xorg/桌面环境重新走了 DRM/KMS 热插拔流程,导致另一个 HDMI 屏幕也被重置。可以升级系统的话,最好是升级系统,附带升级最新内核。如果不行,可以尝试以下方法。

  • 临时解决方法
    如果并不需要音频,可以先屏蔽 HDMI/DP 音频
    1
    2
    3
    4
    echo "options snd_hda_codec_hdmi enable=0" | sudo tee /etc/modprobe.d/disable-hdmi-audio.conf
    sudo dracut -f
    reboot

    但大多数情况下,显示器的视频信号也会收到影响,可能得需要通过xrandr 重新配置输出才可以恢复。实在无奈,只能配置一个xrandr脚本,不定时检测屏幕。比如HDMI端口名称为HDMI-0,DP端口名称为DP-0DP-5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/bin/bash

HDMI_OUT="HDMI-0"
DP_PORTS=("DP-0" "DP-1" "DP-2" "DP-3" "DP-4" "DP-5")

# 保存初始状态
declare -A last_status
for dp in "${DP_PORTS[@]}"; do
status=$(xrandr | grep "^$dp " | awk '{print $2}')
last_status[$dp]=$status
done

while true; do
sleep 2
for dp in "${DP_PORTS[@]}"; do
status=$(xrandr | grep "^$dp " | awk '{print $2}')
if [[ "$status" != "${last_status[$dp]}" ]]; then
# 检测到DP端口状态变化
last_status[$dp]=$status
# 恢复 HDMI-0
xrandr --output "$HDMI_OUT" --auto --primary

# 如果 DP-1 连接了,就放在 HDMI-0 的右边
if xrandr | grep "^DP-1 connected" >/dev/null; then
xrandr --output DP-1 --auto --right-of "$HDMI_OUT"
fi
fi
done
done

把脚本命名成monitor-fix.sh,可以执行,在后台运行

1
2
chmod +x ~/bin/monitor-fix.sh
nohup ~/bin/monitor-fix.sh &

也可以做成开机自启动服务,例如创建/etc/systemd/user/multi-user.target.wants/monitor-fix.service

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Auto fix HDMI-0 screen when disabled
After=graphical.target

[Service]
ExecStart=%h/bin/monitor-fix.sh
Restart=always
Environment=DISPLAY=:0
Environment=XAUTHORITY=%h/.Xauthority

[Install]
WantedBy=multi-user.target

脚本需要放在用户/home/用户名/bin/目录下,并设置执行权限。