DRM/KMS 架构:显示驱动的骨架

做显示驱动,绕不开 DRM/KMS。说白了,DRM(Direct Rendering Manager)是内核里管理显示和图形的那一套框架。KMS(Kernel Mode Setting)是它的一部分,专门负责设置显示模式——分辨率、刷新率、颜色深度这些。

我刚开始接触时,觉得这东西很抽象。后来调过几块 HDMI 芯片,才明白它其实就是把显示链路拆成了几个标准零件。你只要把这些零件拼好,驱动就通了。

核心概念速览

DRM/KMS 定义了四个基本对象:CRTC、Encoder、Connector、Plane。它们的关系,我画了张图,你先看一眼:

DRM/KMS 核心对象关系图 DRM/KMS 核心对象关系图 说明:数据从 Framebuffer 出发,经过 Plane → CRTC → Encoder → Connector,最终到达显示器。 每个箭头代表一个内核对象之间的绑定关系。 Framebuffer Plane CRTC Encoder Connector

逐个拆解: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() 数量不足、格式不支持