4. 显示驱动初始化日志分析:drm驱动加载顺序、pci probe日志、i2c/ddc通道探测日志、edid读取日志
显示驱动的初始化过程是故障排查的第一道关卡。当系统启动时,内核通过 PCI 子系统发现显卡设备,然后由 DRM (Direct Rendering Manager) 框架按特定顺序加载驱动模块、探测硬件资源、初始化 I2C/DDC 通道,并最终读取显示器的 EDID 数据。任何一个环节失败,都会导致“黑屏”、“无显示”或“分辨率异常”。本节将深入解析这些关键步骤的日志特征与排查方法。
核心原则: 显示驱动的初始化顺序是“自上而下、依赖先行”的。如果前一步(如 PCI probe)失败,后续的 EDID 读取日志将根本不会出现。排查时应从最早的错误日志开始,逐层向下分析。
4.1 DRM 驱动加载顺序与日志特征
DRM 子系统采用模块化设计,加载顺序通常为:DRM 核心层 → GPU 特定驱动 → 显示控制器驱动 → 输出接口驱动 (HDMI/DP/eDP)。在 dmesg 中,可以通过以下日志模式识别加载顺序:
| 加载阶段 | 典型 dmesg 日志 | 说明 |
|---|---|---|
| DRM 核心初始化 | [drm] Initialized drm 1.1.0 20060810 |
DRM 框架加载成功 |
| GPU 驱动绑定 | [drm] amdgpu: psp v11.0.0 initialized |
特定 GPU 驱动开始初始化 |
| 显示控制器初始化 | [drm] Display Core v3.2.0 initialized |
DC (Display Core) 初始化完成 |
| 输出接口注册 | [drm] Adding connector for HDMI-A-1 |
物理输出接口被注册到 DRM 框架 |
排查技巧: 使用
dmesg | grep -i "drm" 过滤所有 DRM 相关日志。如果看不到“Initialized drm”行,说明 DRM 核心模块未加载,应检查内核配置或模块黑名单。
4.2 PCI Probe 日志分析
PCI Probe 是 GPU 驱动与硬件建立通信的第一步。驱动通过 pci_probe() 函数读取设备的 Vendor ID、Device ID、Subsystem ID 等信息,并分配 MMIO 和 IRQ 资源。常见的 dmesg 日志格式如下:
[ 2.345678] pci 0000:01:00.0: [1002:67df] type 00 class 0x030000
[ 2.345679] pci 0000:01:00.0: reg 0x10: [mem 0xe0000000-0xefffffff 64bit pref]
[ 2.345680] pci 0000:01:00.0: reg 0x18: [mem 0xf0000000-0xf07fffff 64bit pref]
[ 2.345681] pci 0000:01:00.0: reg 0x20: [io 0x3000-0x30ff]
[ 2.345682] pci 0000:01:00.0: BAR 0: assigned [mem 0xe0000000-0xefffffff 64bit pref]
[ 2.345683] pci 0000:01:00.0: BAR 2: assigned [mem 0xf0000000-0xf07fffff 64bit pref]
[ 2.345684] pci 0000:01:00.0: BAR 5: assigned [io 0x3000-0x30ff]
常见故障模式:
- BAR 分配失败: 日志中出现
BAR 0: can't allocate [mem ...],通常由 BIOS 设置或 IOMMU 问题导致。 - IRQ 冲突:
irq 16: nobody cared或genirq: Flags mismatch,表明中断号被其他设备占用。 - 设备未找到:
pci 0000:01:00.0: [Firmware Bug]: Invalid VPD,可能表示 PCIe 链路不稳定或设备损坏。
关键字段解析:
- [1002:67df]:Vendor ID (1002 = AMD) : Device ID (67df = Polaris 架构)。
- class 0x030000:PCI 类代码,0x03 表示显示控制器,0x00 表示 VGA 兼容。
- reg 0x10/0x18/0x20:BAR (Base Address Register) 编号,对应不同的 MMIO 或 IO 空间。
- 64bit pref:64 位预取内存空间,用于高性能显存访问。
4.3 I2C/DDC 通道探测日志
I2C/DDC 通道是显卡与显示器之间通信的物理链路,用于读取 EDID 和执行显示控制。DRM 驱动在初始化时会枚举所有可能的 I2C 适配器,并尝试与显示器握手。典型的 dmesg 日志如下:
[ 3.456789] [drm] DDC: 0x50 on I2C adapter 0 (i915 gmbus [0])
[ 3.456790] [drm] DDC: 0x50 on I2C adapter 1 (i915 gmbus [1])
[ 3.456791] [drm] DDC: 0x50 on I2C adapter 2 (i915 gmbus [2])
[ 3.456792] [drm] DDC: 0x50 on I2C adapter 3 (i915 gmbus [3])
[ 3.456793] [drm] DDC: 0x50 on I2C adapter 4 (i915 gmbus [4])
解读: 每个 I2C 适配器对应一个物理输出接口(HDMI、DP、eDP 等)。
0x50 是 EDID 数据在 DDC 通道上的标准 I2C 地址。如果某个接口的 DDC 日志缺失,说明该接口的 I2C 总线未被正确初始化。
故障排查对照表:
| 日志现象 | 可能原因 | 排查方向 |
|---|---|---|
| DDC 适配器数量少于物理接口数 | GPIO 复用配置错误、硬件焊接不良 | 检查设备树或 ACPI 表 |
| DDC 通信超时 | 显示器未上电、线缆损坏、I2C 电平不匹配 | 更换线缆/显示器测试 |
| I2C 总线被锁定 | 驱动 bug 或硬件死锁 | 使用 i2cget 工具手动探测 |
4.4 EDID 读取日志分析
EDID (Extended Display Identification Data) 是显示器向显卡提供的“身份证”,包含分辨率、刷新率、色彩深度等关键参数。EDID 读取成功与否直接决定显示器能否正常工作。dmesg 中典型的 EDID 日志如下:
[ 4.567890] [drm] Got EDID for HDMI-A-1: 2560x1440 60Hz 8bpc
[ 4.567891] [drm] EDID block 0 checksum: 0x4a (valid)
[ 4.567892] [drm] EDID block 1 checksum: 0x8b (valid)
[ 4.567893] [drm] HDMI-A-1: EDID has 2 extension blocks
EDID 读取失败典型日志:
[drm] HDMI-A-1: No EDID found— 未检测到显示器或 DDC 通信失败。[drm] EDID block 0 checksum: 0x00 (invalid)— 数据损坏,校验和错误。[drm] HDMI-A-1: EDID is invalid— 读取到的 EDID 数据格式错误。[drm] Failed to get EDID for HDMI-A-1: -5— I2C 传输错误(-5 = EIO)。
EDID 数据块结构:
| 块编号 | 大小 | 内容 | 校验方式 |
|---|---|---|---|
| Block 0 | 128 字节 | 基础显示参数(分辨率、时序、厂商信息) | Checksum (字节 127) |
| Block 1 | 128 字节 | 扩展数据(色域、音频、3D 支持等) | Checksum (字节 255) |
| Block 2+ | 128 字节/块 | CTA-861 扩展块(HDR、动态元数据等) | Checksum (每块末尾) |
高级排查: 使用
edid-decode 工具可以解析原始 EDID 数据。首先通过 cat /sys/class/drm/card0-HDMI-A-1/edid > edid.bin 导出 EDID,然后运行 edid-decode edid.bin 查看详细内容。如果 EDID 校验失败,可以尝试强制指定分辨率:video=HDMI-A-1:2560x1440@60 作为内核启动参数。
4.5 综合排查流程
当显示驱动初始化失败时,建议按照以下步骤进行系统化排查:
- 检查 PCI 层: 使用
lspci -vnn | grep VGA确认显卡是否被系统识别。如果 lspci 中无显示,检查硬件连接或 BIOS 设置。 - 过滤 DRM 日志:
dmesg | grep -E "drm|pci|i2c|edid"收集所有相关日志,按时间戳排序。 - 确认驱动加载: 查找
[drm] Initialized和bound to driver关键字,确认驱动成功绑定。 - 验证 I2C/DDC: 检查 DDC 适配器数量是否与物理接口数一致,使用
i2cdetect -l列出所有 I2C 总线。 - 分析 EDID: 如果 EDID 读取失败,尝试使用
edid-decode分析原始数据,或强制指定分辨率作为临时方案。 - 查看内核错误: 使用
dmesg --level=err,warn过滤错误和警告级别日志,重点关注BUG、ERROR、FAILED等关键字。
实战案例: 某系统在 dmesg 中看到
[drm] Failed to get EDID for HDMI-A-1: -5,同时 i2cdetect -y 0 显示地址 0x50 为 "UU"(表示被驱动占用但无响应)。最终排查发现 HDMI 线缆的 DDC 引脚断裂,更换线缆后 EDID 读取正常。