DRM显示子系统:显示管线的拼接方式
对象拆清楚之后,下一步就是:这些对象是怎么连成一条真实显示链路的?
1. 从输入到输出,不是一根线,而是一串对象关系
一条完整链路通常会长这样:
这里有三个点值得注意。
第一,多个 plane 可以汇到同一个 CRTC。
这代表一帧画面往往是“多图层输入 -> 一次统一输出”。
第二,encoder 后面不一定只有一个 bridge。
外部链路稍微复杂一点时,中间可能串好几个 bridge。
第三,connector 不一定意味着“外接显示器插口”。
对固定内屏来说,它依然可以是用户态看到的输出对象,只是背后接的是一个固定 panel。
2. SoC 显示驱动中的 component 框架
很多 SoC 的显示子系统不是一个 monolithic 驱动,而是分散成多个 platform driver:
- 显示控制器自己一个驱动;
- DSI / HDMI / DP 主机控制器各自一个驱动;
- bridge 芯片又是单独驱动;
- panel 再单独一个驱动。
这些东西物理上属于一条链,软件上却不是同一个模块。component 框架的价值就在这里:
它允许“主设备”等待一组子组件都准备好,再把整条链路组装起来。
所以在 SoC DRM 驱动里经常会看到这样一种节奏:
- master 先创建
drm_device和mode_config; - 各子模块各自 probe;
- 所有组件就绪后统一 bind;
- bind 阶段把 plane、crtc、encoder、connector、bridge 串起来。
这一步解决的是“驱动组织方式”的问题。
3. OF graph 解决的是“谁和谁相连”的问题
驱动组织好了,还需要知道链路关系本身。这个时候经常会用到设备树里的 OF graph。
它的核心元素并不多:
port:某个设备的一个输入或输出端口;endpoint:这个端口上的具体连接点;remote-endpoint:它连到对端哪个 endpoint。
可以把 OF graph 理解成一张连线图,DRM 沿着这张图把输出路径找出来。
4. Bridge 链的递归拼接
Bridge 之所以好用,一个关键原因是它天生支持链式组合。
最常见的过程是:
- encoder 确定自己后面接的第一个 bridge;
- 第一个 bridge 在 attach 时,再去找自己后面的下一个 bridge 或 panel;
- 这个过程一直递归下去,直到链路末端。
如果末端是 panel,常见做法是把 panel 包成 bridge,或者通过 bridge helper 把 panel 挂进链路。这样整条输出路径在框架眼里就统一成了一串 bridge/connector/panel 的组合。
注意:bridge 的 attach 不是“上电”,而是“把链关系建立起来”。
5. Connector 的用户态视角
很多内核对象名词很适合从硬件视角去理解,connector 则相反,它更适合从用户态视角去理解。
用户态关心的是:
- 这个输出端现在是否 connected;
- 它支持哪些 mode;
- 我能不能往这个口上设一个 1920x1080@60 的模式;
- 它有没有热插拔事件。
这些信息最终都应该落在 connector 这一层暴露出去。
所以如果写驱动时脑子里只想着 panel、bridge、DSI host,很容易把 connector 的位置写得模糊。需要注意:connector 是给用户态看的输出对象。

浙公网安备 33010602011771号