3. KMS 对象模型:CRTC、Encoder、Connector、Plane、Bridge 的概念与拓扑关系

KMS(Kernel Mode Setting)是 DRM 驱动中负责显示模式配置与画面输出的核心子系统。要理解 KMS 的工作方式,必须首先掌握其对象模型——即构成显示管线的五个基本对象:CRTC、Encoder、Connector、Plane 和 Bridge。这些对象通过明确的拓扑关系连接在一起,形成从帧缓冲区到显示设备的完整数据通路。

3.1 五大核心对象概述

下表列出了 KMS 对象模型中每个核心对象的职责、内核数据结构以及典型实例:

对象 内核结构体 核心职责 典型实例
CRTC struct drm_crtc 管理显示时序、扫描输出、VBlank 中断、色彩转换矩阵 SoC 内置显示控制器、GPU 显示管道
Encoder struct drm_encoder 将像素数据编码为特定接口信号(如 HDMI、LVDS、eDP) IT66121 HDMI 发送器、ANX7625 DP 桥片
Connector struct drm_connector 代表物理连接器,检测热插拔、读取 EDID、报告物理状态 HDMI Type-A、DisplayPort、VGA、eDP 面板接口
Plane struct drm_plane 管理帧缓冲区与显示层的合成(叠加、缩放、裁剪) 主平面(Primary)、光标平面(Cursor)、叠加平面(Overlay)
Bridge struct drm_bridge 插入在 Encoder 与 Connector 之间的中间处理单元 MIPI DSI 转 eDP 桥片、色彩转换芯片、信号调理器
关键理解:CRTC 是显示管线的“心脏”,负责生成时序;Plane 是“内容源”,提供像素数据;Encoder 和 Bridge 负责“信号转换”;Connector 是“物理出口”。这五个对象必须按正确拓扑连接,才能完成一次完整的显示输出。

3.2 对象拓扑关系

KMS 对象之间的连接关系遵循严格的单向数据流。下图展示了从帧缓冲区到显示设备的完整拓扑结构:

KMS 对象拓扑关系图 KMS 对象拓扑关系图 帧缓冲区 (FB) Plane(主/光标/叠加) 帧缓冲区绑定 · 缩放 · 裁剪 · 合成 CRTC(显示控制器) 时序生成 · VBlank 中断 · 色彩管理 · 扫描输出 Encoder(编码器) Bridge(桥片,可选) Connector(连接器) 说明: Bridge 为可选节点,当 Encoder 与 Connector 之间需要信号转换时插入。
拓扑规则:
  • 一个 CRTC 可以连接多个 Plane(通常至少一个主平面 + 一个光标平面)。
  • 一个 CRTC 连接一个 Encoder,但一个 Encoder 可以被多个 CRTC 共享(取决于硬件)。
  • 一个 Encoder 连接一个 Connector,中间可插入零个或多个 Bridge。
  • 一个 Connector 只能连接一个 Encoder/Bridge,但一个物理连接器可能对应多个虚拟 Connector(如 DP MST)。

3.3 Plane:显示层的核心

Plane 是 KMS 对象模型中与帧缓冲区直接交互的组件。每个 Plane 对应一个独立的显示层,支持不同的像素格式和合成方式。

3.3.1 Plane 的类型

类型 内核常量 典型用途 数量限制
主平面 (Primary) DRM_PLANE_TYPE_PRIMARY 显示主内容,通常为全屏帧缓冲区 每个 CRTC 至少 1 个
光标平面 (Cursor) DRM_PLANE_TYPE_CURSOR 硬件鼠标光标,支持快速移动和热更新 每个 CRTC 最多 1 个
叠加平面 (Overlay) DRM_PLANE_TYPE_OVERLAY 视频叠加、UI 层、画中画 取决于硬件能力

3.3.2 Plane 的关键属性

  • 帧缓冲区绑定:每个 Plane 在某一时刻只能绑定一个 struct drm_framebuffer,但可以通过 drm_atomic_set_fb_for_plane() 原子切换。
  • 源裁剪与目标缩放:Plane 支持 src_x/src_y/src_w/src_h(源裁剪)和 crtc_x/crtc_y/crtc_w/crtc_h(目标位置与缩放)。
  • 像素格式:通过 drm_plane_create_format_modifiers() 声明支持的格式列表,如 ARGB8888、NV12、YUV420 等。
  • 色彩属性:支持 COLOR_ENCODING 和 COLOR_RANGE 属性,用于 YUV 到 RGB 的转换控制。
开发提示:在实现 Plane 驱动时,务必通过 drm_universal_plane_init() 正确初始化类型,并在 atomic_check 回调中验证源裁剪和目标缩放是否在硬件限制范围内。错误的 Plane 配置会导致画面撕裂或显示异常。

3.4 CRTC:显示时序与 VBlank 的掌控者

CRTC(Cathode Ray Tube Controller,历史名称沿用)是 KMS 对象模型中负责生成显示时序的核心对象。它控制着每一帧的扫描过程,并产生 VBlank 中断信号。

3.4.1 CRTC 的核心职责

  1. 模式设置:通过 drm_display_mode 结构体配置分辨率、刷新率、行场同步参数。
  2. VBlank 管理:在垂直消隐期触发中断,用于帧同步、统计帧率、驱动色彩校准。
  3. 色彩管理:支持 drm_crtc_enable_color_mgmt() 注册 degamma、CTM(色彩变换矩阵)、gamma 校正。
  4. 扫描输出:从绑定的 Plane 中读取像素数据,按时序输出到 Encoder。

3.4.2 CRTC 与 VBlank 的关系

VBlank 是 CRTC 驱动中最重要的中断事件之一。下图展示了 CRTC 扫描时序与 VBlank 窗口的关系:

CRTC 扫描时序与 VBlank 窗口 CRTC 扫描时序与 VBlank 窗口 VBlank 窗口(垂直消隐期) 下一帧扫描开始 帧开始 帧结束 VBlank 期间可安全更新帧缓冲区、执行色彩校准、统计帧率,不会产生撕裂。
常见陷阱:不要在 VBlank 回调中执行耗时操作(如内存分配、互斥锁等待)。VBlank 中断处理必须快速返回,否则会导致帧率抖动或系统响应延迟。建议使用工作队列或 threaded IRQ 处理非紧急任务。

3.5 Encoder 与 Bridge:信号转换链路

Encoder 和 Bridge 共同构成了从 CRTC 到 Connector 的信号转换链路。Encoder 通常负责协议级别的编码,而 Bridge 则处理更细粒度的信号调理。

3.5.1 Encoder 的类型

Encoder 类型 输出接口 典型驱动
DRM_MODE_ENCODER_DAC 模拟 VGA i915、radeon
DRM_MODE_ENCODER_TMDS HDMI / DVI dw-hdmi、tda998x
DRM_MODE_ENCODER_LVDS LVDS 面板 imx-ldb、tilcdc
DRM_MODE_ENCODER_DP DisplayPort analogix_dp、cdns-dp
DRM_MODE_ENCODER_DSI MIPI DSI sun6i-mipi-dsi、dw-mipi-dsi

3.5.2 Bridge 的链式处理

Bridge 是 DRM 子系统中相对较新的抽象,用于处理 Encoder 与 Connector 之间的中间处理步骤。典型的 Bridge 处理流程包括:

  1. 信号格式转换:如 MIPI DSI 转 eDP、RGB 并行转 LVDS。
  2. 色彩空间转换:如 BT.601 转 BT.709、YUV 转 RGB。
  3. 信号调理:如预加重、摆幅调整、去抖动。
  4. 电源管理:桥片的上电/下电序列控制。
Bridge 驱动开发要点:
  • 使用 drm_bridge_add() 注册桥片,通过 drm_bridge_attach() 连接到 Encoder。
  • 实现 struct drm_bridge_funcs 中的 mode_set、enable、disable 回调。
  • 如果桥片支持色彩处理,可以在 atomic_check 中验证色彩属性。
  • 多个 Bridge 可以链式连接,形成处理流水线。

3.6 Connector:物理世界的接口

Connector 是 KMS 对象模型中唯一与物理世界直接交互的对象。它负责检测显示设备的连接状态、读取 EDID 信息、报告物理属性。

3.6.1 Connector 的状态机

Connector 的状态通过 drm_connector_status 枚举表示:

状态 含义 典型触发条件
connector_status_connected 显示设备已连接 热插拔检测 (HPD) 引脚拉高
connector_status_disconnected 显示设备未连接 HPD 引脚拉低、EDID 读取失败
connector_status_unknown 无法确定状态 硬件不支持热插拔检测

3.6.2 EDID 与显示能力

Connector 通过 drm_get_edid() 读取显示设备的 EDID(Extended Display Identification Data),获取以下信息:

  • 支持的分辨率与刷新率:包含标准时序和详细时序描述。
  • 物理尺寸:屏幕的对角线尺寸(厘米)。
  • 色彩特性:色域、伽马值、色彩深度。
  • 接口类型:HDMI、DP、DVI 等。
调试技巧:使用 cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode 可以查看 EDID 的详细内容。如果 Connector 状态异常,首先检查 EDID 读取是否成功。

3.7 对象拓扑的完整示例

以下是一个典型的嵌入式设备 KMS 对象拓扑示例,展示了从帧缓冲区到 eDP 面板的完整链路:

// 伪代码:KMS 对象拓扑初始化
struct drm_device *dev;
struct drm_crtc *crtc;
struct drm_plane *primary, *cursor;
struct drm_encoder *encoder;
struct drm_bridge *bridge;
struct drm_connector *connector;

// 1. 创建 Plane
primary = drm_universal_plane_init(dev, ... , DRM_PLANE_TYPE_PRIMARY, ...);
cursor  = drm_universal_plane_init(dev, ... , DRM_PLANE_TYPE_CURSOR, ...);

// 2. 创建 CRTC,绑定 Plane
crtc = drm_crtc_init_with_planes(dev, ... , primary, cursor, ...);
drm_crtc_enable_color_mgmt(crtc, degamma_lut_size, has_ctm, gamma_lut_size);

// 3. 创建 Encoder
encoder = drm_encoder_init(dev, ... , DRM_MODE_ENCODER_DP, ...);

// 4. 创建 Bridge 并连接到 Encoder
bridge = devm_drm_bridge_add(dev, ...);
drm_bridge_attach(encoder, bridge, NULL, 0);

// 5. 创建 Connector,连接到 Bridge
connector = drm_connector_init(dev, ... , DRM_MODE_CONNECTOR_eDP, ...);
drm_connector_attach_encoder(connector, encoder);  // 或通过 Bridge 连接

// 6. 建立 CRTC 到 Encoder 的链接
drm_mode_config_reset(dev);
拓扑验证:在驱动加载后,可以通过 drm_client_modeset_probe() 或用户空间的 modetest 工具验证对象拓扑是否正确。使用 find . -name "*.ko" | xargs modprobe 加载驱动后,执行 modetest -M <driver_name> 查看对象列表。

3.8 本章小结