DRM/KMS 架构:显示驱动的骨架
做显示驱动,绕不开 DRM/KMS。说白了,DRM(Direct Rendering Manager)是内核里管理显示和图形的那一套框架。KMS(Kernel Mode Setting)是它的一部分,专门负责设置显示模式——分辨率、刷新率、颜色深度这些。
我刚开始接触时,觉得这东西很抽象。后来调过几块 HDMI 芯片,才明白它其实就是把显示链路拆成了几个标准零件。你只要把这些零件拼好,驱动就通了。
核心概念速览
DRM/KMS 定义了四个基本对象:CRTC、Encoder、Connector、Plane。它们的关系,我画了张图,你先看一眼:
逐个拆解:CRTC、Encoder、Connector、Plane
CRTC — 显示控制器
CRTC 是显示管线的核心。它负责从内存里读像素数据,生成时序信号(行同步、场同步、像素时钟)。你可以把它理解成「画布的大脑」——它决定什么时候扫哪一行、什么时候换帧。
我遇到过一个问题:某款 SoC 的 CRTC 只支持 60Hz 刷新率,但客户要求 50Hz。折腾了半天,发现是 CRTC 的时钟分频器有硬件限制。最后只能改 PLL 配置才搞定。
关键点:每个 CRTC 同一时刻只能驱动一个显示输出。双屏扩展需要两个 CRTC。
Encoder — 编码器
Encoder 把 CRTC 输出的并行 RGB 数据转换成某种串行接口信号。比如 HDMI Encoder 会把数据编码成 TMDS 差分信号。LVDS、eDP、MIPI DSI 也都有自己的 Encoder。
说白了,Encoder 就是「翻译官」。CRTC 说「我要发红色 8 位」,Encoder 就把它变成 HDMI 能懂的格式。
| Encoder 类型 | 输出接口 | 常见场景 |
|---|---|---|
| TMDS | HDMI / DVI | 电视、显示器 |
| LVDS | LVDS 差分对 | 笔记本屏幕 |
| eDP | Embedded DisplayPort | 平板、高端笔记本 |
| MIPI DSI | MIPI D-PHY | 手机、嵌入式设备 |
Connector — 物理连接器
Connector 代表物理接口。HDMI 插座、VGA 座子、DP 口,都是 Connector。它负责检测有没有设备插入(通过 HPD 引脚),以及读取显示器的 EDID 数据。
我记得有一次调试,HDMI 插上没反应。查了半天,发现是 Connector 的 HPD GPIO 配置错了,中断没触发。改完设备树就好了。
小技巧:调试时可以用 cat /sys/class/drm/card0-HDMI-A-1/status 查看连接状态。如果显示 connected 但没画面,多半是 EDID 解析失败。
Plane — 图层
Plane 是 DRM 里比较新的概念。它代表一个独立的显示图层。每个 Plane 可以有自己的 Framebuffer、位置、大小、透明度。CRTC 会把多个 Plane 叠加后输出。
举个例子:视频播放器用 Overlay Plane 显示视频,用 Primary Plane 显示 UI。这样视频缩放和 UI 刷新互不干扰。
- Primary Plane:主图层,必须存在。通常用于桌面背景。
- Overlay Plane:叠加层,可选。用于视频、硬件光标。
- Cursor Plane:光标层,专用硬件光标。
它们怎么连起来的?
驱动初始化时,需要把 CRTC、Encoder、Connector、Plane 绑定成一条显示管线。绑定关系通过 drm_mode_config 结构体管理。
// 伪代码:绑定 CRTC 和 Encoder
encoder->possible_crtcs = 1 << drm_crtc_index(crtc);
// 绑定 Encoder 和 Connector
connector->encoder_ids[0] = encoder->base.id;
connector->encoder = encoder;
// 绑定 Plane 到 CRTC
plane->possible_crtcs = 1 << drm_crtc_index(crtc);
用户空间通过 drmModeSetCrtc() 设置显示模式。内核收到后,会按管线顺序配置每个硬件模块。
避坑指南
我曾经踩过的坑:
- Encoder 和 Connector 不匹配:HDMI Encoder 绑了 DVI Connector,导致音频无法传输。因为 DVI 不支持音频。
- Plane 数量不够:某平台只有 1 个 Overlay Plane,但上层应用开了 2 个视频窗口。结果第二个窗口黑屏。
- CRTC 时钟范围:有些 CRTC 的像素时钟上限是 165MHz,超过这个值 HDMI 1080p@60 都出不来。查 datasheet 很重要。
一张表总结
| 对象 | 职责 | 用户空间接口 | 常见问题 |
|---|---|---|---|
| CRTC | 时序生成、帧缓冲扫描 | drmModeSetCrtc() | 时钟范围、刷新率限制 |
| Encoder | 数据编码、信号转换 | drmModeGetEncoder() | 编码格式不匹配 |
| Connector | 物理接口、热插拔、EDID | drmModeGetConnector() | HPD 中断、EDID 损坏 |
| Plane | 图层叠加、缩放、透明度 | drmModeSetPlane() | 数量不足、格式不支持 |