3. DRM 核心概念:CRTC、Encoder、Connector、Plane、FB、Vblank

DRM (Direct Rendering Manager) 是 Linux 内核中负责显示输出的核心框架。在瑞芯微平台驱动开发中,理解 DRM 的六大核心对象是编写显示驱动的基石。本章将逐一剖析这些对象的功能、协作关系以及在 RK 平台上的典型实现。

学习提示: 本章概念是后续编写 RK 显示驱动 Probe 函数和 Atomic Commit 流程的基础。建议结合 RK 芯片手册的显示控制器章节进行对照学习。

3.1 六大核心对象概览

DRM 框架将显示输出链路抽象为一条“数据管道”:从内存中的图像数据开始,经过图形处理、格式转换、时序生成,最终输出到物理显示设备。下表总结了每个核心对象在管道中的角色:

对象 全称 核心职责 瑞芯微平台对应硬件
CRTC Cathode Ray Tube Controller 生成显示时序、扫描控制、帧切换 VOP (Video Output Processor)
Encoder Encoder 将 CRTC 输出的并行信号编码为外部接口协议 HDMI TX、DP PHY、MIPI DSI
Connector Connector 物理连接器检测、EDID 读取、热插拔管理 HDMI Connector、DP Connector
Plane Plane 图像层管理、Alpha 混合、缩放、旋转 VOP 的 Win0/Win1/Win2 图层
FB Framebuffer 物理内存中的像素数据缓冲区 DDR 中的 DMA Buffer
Vblank Vertical Blanking Interval 帧消隐期中断与同步信号 VOP 的帧中断

3.2 核心对象详解

3.2.1 CRTC — 显示控制核心

CRTC 是显示管道的“大脑”,负责生成像素时钟、行同步、场同步等时序信号,并控制帧缓冲区的切换。在瑞芯微平台上,CRTC 对应 VOP (Video Output Processor) 模块。

CRTC 的主要功能包括:

  • 时序生成: 根据 Modeline 参数生成 HFP、HBP、VFP、VBP 等时序。
  • 帧切换: 在 Vblank 期间安全切换 Framebuffer 地址,防止画面撕裂。
  • Gamma 校正: 对输出像素进行颜色查找表 (LUT) 映射。
  • 电源管理: 控制 VOP 模块的时钟门控与电源域。
RK 平台关键结构体: struct rockchip_crtc_state 扩展了 DRM 原生的 struct drm_crtc_state,用于保存 VOP 特有的输出模式、图层配置和时钟参数。

3.2.2 Encoder — 信号编码器

Encoder 负责将 CRTC 输出的并行 RGB/YCbCr 信号转换为特定显示接口的串行协议。RK 平台常见的 Encoder 类型包括:

  • HDMI Encoder: 将并行数据编码为 TMDS 差分信号,支持音频嵌入。
  • DP Encoder: 将数据打包为 DisplayPort 微包,支持更高带宽。
  • MIPI DSI Encoder: 将数据转换为 DSI 协议包,用于连接 MIPI 屏幕。
  • LVDS Encoder: 将并行数据转换为 LVDS 差分对,用于工控屏。

Encoder 与 CRTC 之间通过 drm_encoder.crtc 指针建立连接。在 RK 驱动中,通常使用 dw_hdmi 或 analogix_dp 等桥接驱动来实现 Encoder 功能。

3.2.3 Connector — 物理连接器

Connector 代表物理显示接口,负责检测设备连接状态、读取显示器 EDID 数据以及提供物理属性(如最大分辨率、接口类型)。

Connector 的核心操作:

  • 热插拔检测: 通过 GPIO 中断或 I2C 检测显示器插入/拔出。
  • EDID 读取: 通过 DDC 通道读取显示器支持的时序列表。
  • 状态上报: 将连接状态和显示模式上报给 DRM 核心。
开发陷阱: 在 RK3399 上,HDMI Connector 的热插拔检测 (HPD) 引脚必须正确配置 GPIO 中断,否则系统无法感知显示器插入,导致无输出。

3.2.4 Plane — 显示图层

Plane 是 DRM 中负责图像合成的基本单元。每个 Plane 对应一个独立的显示层,支持独立的 Framebuffer、位置、大小、Alpha 值和像素格式。RK VOP 通常提供 3 个硬件图层:

  • Win0: 主图层,支持 RGB 和 YUV 格式,支持缩放。
  • Win1: 辅助图层,支持 RGB 格式,支持 Alpha 混合。
  • Win2: 光标层,支持 ARGB 格式,通常用于鼠标指针。

Plane 的类型:

类型 用途 典型限制
DRM_PLANE_TYPE_PRIMARY 主显示层,必须存在 通常绑定 CRTC,不可移动
DRM_PLANE_TYPE_OVERLAY 叠加层,用于画中画、字幕 数量有限,受硬件图层数限制
DRM_PLANE_TYPE_CURSOR 硬件光标层 尺寸小(通常 64x64),格式受限

3.2.5 FB — 帧缓冲区

Framebuffer (FB) 是 DRM 中表示物理内存中图像数据的对象。它封装了像素数据的物理地址、格式、步长和尺寸信息。FB 通过 drm_framebuffer 结构体管理,其生命周期由 DRM 核心的引用计数控制。

FB 的关键属性:

  • 像素格式: DRM_FORMAT_XRGB8888、DRM_FORMAT_NV12 等。
  • pitches: 每行像素的字节数(步长)。
  • offsets: 各颜色分量的偏移地址(用于 YUV 格式)。
  • modifier: 内存布局修饰符(如 DRM_FORMAT_MOD_LINEAR、AFBC)。
RK 平台优化: 瑞芯微 VOP 支持 AFBC (Arm Frame Buffer Compression) 压缩格式,可显著降低内存带宽。驱动中需通过 drm_fb_cma_get_gem_obj 获取 DMA-BUF 并配置 VOP 的 AFBC 解码器。

3.2.6 Vblank — 垂直消隐期

Vblank 是 CRTC 在完成一帧扫描后、开始下一帧扫描前的短暂间隔。在此期间更新 Framebuffer 地址或 Plane 属性可以避免画面撕裂 (Tearing)。

Vblank 在驱动中的典型用途:

  • 帧同步: 用户态程序通过 DRM_IOCTL_WAIT_VBLANK 等待 Vblank 事件。
  • Page Flip: 在 Vblank 中断中安全切换 FB 地址。
  • 统计 FPS: 通过 Vblank 中断计数计算刷新率。

RK 平台 Vblank 中断处理流程:

// 在 VOP 驱动中注册 Vblank 中断处理函数
static irqreturn_t vop_isr(int irq, void *dev_id)
{
    struct vop *vop = dev_id;
    uint32_t intr_status;

    intr_status = vop_readl(vop, VOP_INTR_STATUS);
    if (intr_status & FS_INTR) {
        // 通知 DRM 核心 Vblank 事件发生
        drm_crtc_handle_vblank(&vop->crtc);
        // 处理 Page Flip 回调
        if (vop->pending_flip)
            vop_flip_done(vop);
    }
    return IRQ_HANDLED;
}

3.3 核心对象协作关系

下图展示了 DRM 核心对象在显示输出管道中的完整协作流程:

DRM 核心对象协作关系图 用户空间 (App) Framebuffer (FB) Plane (图层) CRTC (VOP) Encoder Connector Vblank 中断 数据流向说明 1. App 创建 FB 2. Plane 关联 FB 3. CRTC 扫描 Plane 4. Encoder 编码输出

3.4 对象注册与绑定流程

在 RK 平台驱动初始化时,需要按照特定顺序注册这些 DRM 对象。典型的 Probe 函数流程如下:

  1. 分配 CRTC: 调用 drm_crtc_init_with_planes() 注册 VOP 为 CRTC。
  2. 注册 Plane: 调用 drm_universal_plane_init() 注册 Win0/Win1/Win2 图层。
  3. 注册 Encoder: 调用 drm_encoder_init() 注册 HDMI/DP/MIPI 编码器。
  4. 注册 Connector: 调用 drm_connector_init() 注册物理连接器,并绑定 drm_connector_funcs 回调。
  5. 建立连接: 通过 drm_mode_connector_attach_encoder() 将 Connector 绑定到 Encoder。
  6. 注册 Vblank 处理: 调用 drm_vblank_init() 初始化 Vblank 支持,并注册中断处理函数。
RK 特有流程: 在 rockchip_drm_bind() 函数中,会先通过 component_bind_all() 绑定所有 VOP 子节点,然后按上述顺序完成 DRM 对象的注册。这种设计利用了 Linux 组件框架来管理 VOP 内部的多个硬件模块。

3.5 Atomic 模式下的对象交互

现代 DRM 驱动(包括 RK 平台)使用 Atomic 模式 管理显示状态更新。在 Atomic 模式下,所有对象的状态变更被收集到一个 drm_atomic_state 事务中,然后一次性提交。关键交互点包括:

  • CRTC 状态检查: atomic_check 回调验证时序和时钟可行性。
  • Plane 状态更新: atomic_update 回调配置 VOP 图层寄存器。
  • FB 引用管理: Atomic 框架自动处理 FB 的引用计数,确保在 Vblank 完成前 FB 不会被释放。
  • Vblank 同步: drm_atomic_helper_commit 在 Vblank 期间执行硬件寄存器更新。

下表总结了 Atomic 模式下各对象的回调函数:

对象 Atomic Check 回调 Atomic Commit 回调
CRTC crtc_helper->atomic_check crtc_helper->atomic_flush
Plane plane_helper->atomic_check plane_helper->atomic_update
Encoder encoder_helper->atomic_check encoder_helper->atomic_mode_set
Connector connector_helper->atomic_check connector_helper->atomic_commit
实战要点: 在 RK 平台调试时,可通过 cat /sys/kernel/debug/dri/0/state 查看当前 Atomic 状态树,确认 CRTC、Plane、Connector 的绑定关系是否正确。