2. KMS基础概念
KMS(Kernel Mode Setting)把显示输出拆解为一组职责清晰的内核对象。理解这些对象以及它们之间的数据流,是后续排查黑屏、花屏、分辨率异常、热插拔失效等问题的前提。可以把 KMS 想象成一条“像素生产线”:Framebuffer 提供原料,Plane 负责图层合成,CRTC 负责时序扫描,Encoder 负责信号编码,Connector 负责物理输出,Bridge 负责链路转换。
一、核心对象与职责
KMS 中每个对象都对应内核里的一个结构体,并通过 DRM 的 object ID 暴露给用户空间。它们不是孤立的,而是通过 atomic 状态机协同工作。
- Framebuffer(FB):一块显存缓冲区的抽象,描述像素格式、宽高、pitch、offset 以及底层 GEM 对象。它是“要显示什么”的数据来源。
- Plane:图层抽象,负责把某个 Framebuffer 按裁剪、缩放、旋转、混合等属性叠加到 CRTC 上。常见类型有 Primary、Overlay、Cursor。
- CRTC:显示控制器,负责从 Plane 取像素并按像素时钟、行场时序扫描输出。它决定“什么时候、以什么时序”输出。
- Encoder:把 CRTC 输出的并行像素信号转换为具体接口信号,如 HDMI TMDS、DP 链路、DSI 串行信号。它决定“以什么电气形式”输出。
- Connector:物理连接器抽象,如 HDMI-A-1、DP-1、eDP-1。它管理连接状态、EDID、支持的显示模式,并负责热插拔检测。
- Bridge:当 SoC 输出与 Connector 之间需要电平转换、协议转换或复用芯片时使用,例如 MIPI DSI 转 HDMI、DP 转 eDP、LVDS 转 eDP。
一句话记忆:Framebuffer 是“画什么”,Plane 是“怎么叠”,CRTC 是“按什么时序扫”,Encoder 是“编成什么信号”,Connector 是“从哪个口出去”,Bridge 是“中间怎么转”。
二、数据流与对象关系
从用户空间提交一次 atomic commit 开始,数据流大致如下:应用或合成器把渲染结果写入 GEM 缓冲区,创建或复用 Framebuffer;然后通过 atomic 属性把 FB 绑定到某个 Plane,把 Plane 绑定到 CRTC,把 CRTC 绑定到 Encoder,Encoder 再关联到 Connector。内核在 commit 时校验拓扑和模式是否合法,最后在 vblank 时机把新状态生效。
下面这张图展示了 KMS 核心对象之间的连接关系与像素/控制数据流。注意 Bridge 位于 Encoder 与 Connector 之间,是链路转换的关键节点。
三、关键属性与调试入口
排查 KMS 问题时,最常用的手段是查看对象拓扑和当前状态。modetest 可以列出所有对象及其连接关系,debugfs 则能查看更底层的状态。
# 列出所有 KMS 对象及连接关系
modetest -M rockchip -c
# 查看 connector 状态、EDID、支持模式
modetest -M rockchip -c -p
# 查看 CRTC 当前模式与 Plane 绑定
cat /sys/kernel/debug/dri/0/state
# 查看 connector 热插拔与 EDID 信息
cat /sys/class/drm/card0-HDMI-A-1/status
cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode
下表总结了各核心对象在故障排查中最值得关注的属性。
| 对象 | 关键属性 | 常见故障现象 | 排查入口 |
|---|---|---|---|
| Framebuffer | format、width、height、pitch、modifier | 花屏、颜色错乱、偏移 | modetest -p、drm_info |
| Plane | type、crtc_id、fb_id、src/dst、zpos | 图层不显示、叠加顺序错误 | debugfs state、modetest -p |
| CRTC | mode、active、plane_mask | 无扫描输出、时序异常 | debugfs state、modetest -c |
| Encoder | encoder_type、possible_crtcs | 接口无信号、链路训练失败 | dmesg、modetest -e |
| Connector | status、edid、modes、dpms | 热插拔无效、分辨率不对 | /sys/class/drm、modetest -c |
| Bridge | bridge_type、of_node、timings | 转换芯片无输出、时序不匹配 | dmesg、debugfs、设备树 |
四、典型场景:HDMI 无输出的排查路径
假设一块板子 HDMI 接显示器无画面。按照 KMS 数据流从后往前排查,可以快速缩小范围。
- 先看 Connector 状态:
cat /sys/class/drm/card0-HDMI-A-1/status。如果是 disconnected,说明 HPD 检测或 EDID 读取有问题,优先查硬件连接和 HPD 中断。 - 如果 status 是 connected,但 modes 为空,说明 EDID 解析失败,检查 DDC 通道和 EDID 数据。
- 如果 Connector 正常,查看 CRTC 是否 active、mode 是否设置成功。若 CRTC 未激活,检查 atomic commit 是否被拒绝。
- 如果 CRTC 正常,检查 Encoder 是否绑定到正确的 CRTC,以及 Bridge 是否成功 probe。
- 最后检查 Framebuffer 和 Plane 是否绑定正确,格式是否被硬件支持。
调试技巧:在 dmesg 中搜索 drm、connector、bridge 关键字,往往能直接看到链路训练失败、EDID 校验失败或 bridge probe 失败的原因。
五、常见误区与复盘
- 误区一:把 Connector 当成“接口本身”。 Connector 是内核抽象,真正驱动信号的是 Encoder 和 Bridge。HDMI 无输出不一定是 Connector 问题。
- 误区二:忽略 Bridge 的时序约束。 Bridge 芯片通常对输入时序、像素时钟范围有要求,SoC 输出的 mode 必须落在 Bridge 支持范围内。
- 误区三:只看 CRTC 不看 Plane。 黑屏但 CRTC active,很可能是 Plane 没有绑定 FB,或者 zpos 被其他图层遮挡。
- 误区四:热插拔后不重新读取 EDID。 某些显示器切换输入源后 EDID 会变化,必须重新触发 modeset。
复盘建议:每次排查 KMS 问题,先画出当前系统的对象拓扑图,标注每个对象的 ID 和状态,再对照数据流逐段验证。这样比盲目改代码或换线更高效。
掌握 CRTC、Encoder、Connector、Plane、Framebuffer、Bridge 六个核心对象及其数据流,就建立了 KMS 调试的“地图”。后续无论是分析 atomic commit 失败、调试多屏显示,还是排查 Bridge 链路问题,都可以沿着这条数据流逐段定位。