1. DRM 驱动概述

1.1 DRM 框架发展历史

DRM(Direct Rendering Manager)最初诞生于 XFree86 时代,目的是解决多个 X Server 进程同时访问显卡时的资源竞争问题。2003 年,DRM 被合入 Linux 主线内核 2.5 系列,成为内核图形子系统的基础组件。早期的 DRM 仅提供基本的 GPU 命令提交和内存管理,显示输出仍由用户态的 X Server 控制。

2012 年,Linux 内核 3.8 引入了 KMS(Kernel Mode Setting),将显示模式设置、帧缓冲管理和输出链路控制从用户态移入内核。这一变革彻底改变了嵌入式显示驱动的开发方式:开发者不再需要为每个 SoC 编写复杂的用户态显示库,而是通过统一的 DRM/KMS 接口完成显示链路配置。

2014 年之后,DRM 框架逐步引入 GEM(Graphics Execution Manager)作为标准内存管理方案,替代了早期的 TTM(Translation Table Manager)。GEM 提供了 Buffer Object、Dumb Buffer、Prime(DMA-BUF 共享)等机制,成为嵌入式平台显示内存管理的事实标准。

关键里程碑:
  • 2003 — DRM 合入主线,提供 GPU 命令提交基础
  • 2012 — KMS 引入,显示模式设置内核化
  • 2014 — GEM 成为主流内存管理方案
  • 2016 — Atomic KMS 合入,支持无撕裂提交
  • 2018+ — Bridge/Encoder 抽象完善,适配 MIPI DSI/HDMI/DP
DRM 框架发展时间线 2003 DRM 合入主线 2012 KMS 引入 2014 GEM 成为主流 2016 Atomic KMS 2018+ Bridge/Encoder 抽象

1.2 核心组件:DRM / KMS / GEM

DRM 框架由三个核心子系统构成,各自承担不同的职责。理解这三者的分工是进行驱动移植和显示链路调试的前提。

组件 全称 核心职责 关键数据结构
DRM Direct Rendering Manager GPU 命令提交、上下文管理、文件操作接口 drm_device, drm_file, drm_driver
KMS Kernel Mode Setting 显示模式设置、输出链路管理、帧缓冲控制 drm_crtc, drm_encoder, drm_connector, drm_plane
GEM Graphics Execution Manager 显存分配、Buffer Object 管理、DMA-BUF 共享 drm_gem_object, drm_gem_cma_object
嵌入式开发提示: 在嵌入式 Linux 中,大多数 SoC 使用 CMA(Contiguous Memory Allocator)分配连续物理内存作为显示缓冲区。GEM 的 CMA 辅助实现 drm_gem_cma_helper 是移植时最常用的内存管理方案,无需复杂的 GPU MMU 支持。
DRM 框架三层架构 用户态应用 / libdrm / Mesa / Wayland open("/dev/dri/card0") → ioctl → DRM 文件操作接口 DRM 核心层 (drm_core) drm_driver → drm_device → drm_file → ioctl 分发 KMS 显示管理 CRTC / Encoder / Connector / Plane GEM 内存管理 Buffer Object / Dumb / Prime / CMA SoC 显示硬件 / GPU / Display Controller

1.3 DRM 在嵌入式 Linux 中的地位

在嵌入式 Linux 领域,DRM/KMS 已经取代了传统的 FBDEV(Frame Buffer Device)和 V4L2 输出接口,成为显示子系统的事实标准。几乎所有主流嵌入式 SoC 平台(i.MX、Rockchip、Allwinner、Qualcomm、Mediatek、STM32MP)都使用 DRM 驱动作为显示输出方案。

DRM 在嵌入式系统中的核心优势体现在以下几个方面:

  • 统一接口 — 应用层通过标准 DRM ioctl 操作显示,无需关心底层 SoC 差异
  • 零拷贝显示 — GEM/Prime 支持 DMA-BUF 共享,视频解码器输出可直接送显
  • 多图层合成 — KMS Plane 支持硬件图层叠加,无需 GPU 参与即可实现 UI 合成
  • 无撕裂更新 — Atomic KMS 保证帧切换在 VBlank 期间完成,消除撕裂
  • 设备树驱动 — 显示链路拓扑通过设备树描述,驱动移植只需修改 dts
常见误区: 很多开发者认为 DRM 只适用于桌面 GPU。实际上,DRM 框架对嵌入式 SoC 的 Display Controller 支持非常成熟。嵌入式 DRM 驱动通常不涉及 GPU 命令提交,只实现 KMS 显示输出和 GEM CMA 内存管理,代码量远小于桌面 GPU 驱动。
DRM 在嵌入式 Linux 显示栈中的位置 应用层:QT / LVGL / Flutter / Wayland Compositor libdrm (用户态封装层) DRM/KMS 内核驱动 (drm_driver + kms + gem) SoC Display Controller 硬件 MIPI DSI / LVDS / HDMI / eDP / RGB 接口

1.4 DRM 驱动移植的核心挑战

在嵌入式平台上移植 DRM 驱动,开发者通常面临以下关键问题:

挑战 典型场景 解决方案
设备树显示链路描述 MIPI DSI 桥接芯片 + 触摸屏组合 正确配置 ports、remote-endpoint、panel 节点
Encoder/Bridge 适配 HDMI 转换芯片(如 LT8619、SIL9022) 实现 drm_bridge_funcs 回调,配置 I2C 初始化序列
时序与分辨率配置 非标 LCD 屏(800×480、1024×600) 在 panel 节点中填写 display-timings 子节点
时钟与复位依赖 DSI 控制器需要 PLL 时钟和 GPIO 复位 设备树中声明 clocks、resets、pinctrl 属性
DMA-BUF 共享 视频解码器直接输出到显示缓冲区 使用 GEM Prime 导出 dma-buf fd,通过 drm_mode_set_plane 送显