2. 显示驱动框架:Linux DRM框架介绍、MSM DRM驱动架构、SA8155显示驱动代码结构

2.1 Linux DRM框架概述

DRM(Direct Rendering Manager)是Linux内核中负责图形显示与渲染管理的标准框架。它向上提供统一的用户空间接口(通过/dev/dri/card0设备节点),向下抽象GPU、Display Controller、Encoder、Connector等硬件单元。

核心设计理念: DRM将显示管线拆解为若干个可组合的抽象对象,驱动开发者只需实现对应的回调函数,框架自动完成状态管理、原子提交、事件通知等复杂逻辑。

2.1.1 DRM核心对象模型

对象 角色 对应硬件 关键操作
CRTC 显示控制器,负责扫描输出与时序生成 DPU硬件管线(Mixer + PingPong + P010) mode_set、atomic_flush、enable/disable
Plane 图层叠加单元,支持多个图层混合 DPU SSPP(Source Surface Processor Pipe) update_plane、disable_plane、atomic_check
Encoder 编码器,将CRTC输出的像素流转换为物理接口信号 DPU INTF(Interface)模块 mode_fixup、atomic_mode_set
Connector 物理连接器,检测显示器热插拔与EDID信息 HDMI、DP、DSI物理接口 detect、get_modes、atomic_get_property
Bridge 桥接芯片,用于信号转换(如DP转HDMI) 外部显示桥片 pre_enable、enable、disable
开发提示: 在SA8155平台上,CRTC与DPU硬件管线是1:1映射关系。一个CRTC对应一个DPU硬件实例,包含完整的Mixer → PingPong → INTF数据通路。

2.1.2 DRM原子提交(Atomic Commit)

DRM原子提交是SA8155显示驱动开发中必须掌握的核心机制。它保证多个显示对象的状态更新在同一个VBlank周期内同步生效,避免撕裂(Tearing)和闪烁。

  • 非原子模式(Legacy): 每个对象单独提交,无法保证时序同步,已逐步淘汰。
  • 原子模式(Atomic): 驱动实现atomic_check和atomic_flush回调,用户空间通过DRM_IOCTL_MODE_ATOMIC一次性提交完整状态。
  • 状态对象: drm_crtc_state、drm_plane_state、drm_connector_state,驱动可在其中携带私有硬件状态。
// 原子提交流程(用户空间侧)
struct drm_mode_atomic atomic = {0};
atomic.flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
atomic.count_objs = 3;  // CRTC + Plane + Connector
atomic.objs_ptr = (uint64_t)objs;
atomic.count_props_ptr = (uint64_t)count_props;
atomic.props_ptr = (uint64_t)props;
atomic.values_ptr = (uint64_t)values;

int ret = drmIoctl(fd, DRM_IOCTL_MODE_ATOMIC, &atomic);
if (ret) {
    // 原子提交失败,整个状态回滚
    handle_atomic_fail();
}

2.2 MSM DRM驱动架构

MSM DRM是Qualcomm平台在Linux内核中的显示驱动实现,位于drivers/gpu/drm/msm/目录。它同时管理Adreno GPU和DPU显示控制器,SA8155使用的正是MSM DRM框架。

MSM DRM 驱动架构分层图 用户空间 SurfaceFlinger / Wayland / Weston / drm-app DRM核心框架 (drm_core) drm_atomic_state / drm_crtc / drm_plane / drm_encoder / drm_connector MSM DRM 驱动 (msm_drv) msm_kms / msm_drm_private / msm_gem / msm_fence DPU 显示驱动 (dpu_kms) dpu_crtc / dpu_plane / dpu_encoder dpu_hw_ctl / dpu_hw_intf / dpu_hw_sspp Adreno GPU 驱动 (adreno) a6xx_gpu / adreno_gpu / adreno_iommu msm_gem_submit / msm_ringbuffer 硬件抽象层 (HAL / IOMMU / Clock / Regulator) dpu_hw_catalog / dpu_hw_mdss / dpu_hw_util / clk_bulk / regulator_bulk

2.2.1 MSM DRM关键数据结构

数据结构 作用 所属模块
msm_drm_private MSM DRM全局私有数据,管理KMS实例、GEM对象、Fence上下文 msm_drv
msm_kms KMS(Kernel Mode Setting)抽象接口,提供enable_vblank、prepare_commit等回调 msm_kms
dpu_kms DPU子驱动的主结构体,包含硬件目录、时钟、中断、IRQ域 dpu_kms
dpu_crtc DPU CRTC实现,管理Mixer、PingPong、CTL硬件块 dpu_crtc
dpu_hw_ctl 硬件控制块抽象,负责启动/停止显示管线、触发刷新 dpu_hw_ctl

2.3 SA8155显示驱动代码结构

SA8155的显示驱动代码位于drivers/gpu/drm/msm/disp/dpu1/目录,这是整个课程最常打交道的代码区域。下面列出核心文件及其职责:

SA8155 DPU1 驱动代码结构 dpu1/ dpu_kms.c / dpu_kms.h dpu_crtc.c / dpu_crtc.h dpu_plane.c / dpu_plane.h dpu_encoder.c / dpu_encoder.h dpu_connector.c / dpu_connector.h dpu_hw_catalog.c / .h dpu_hw_ctl.c dpu_hw_sspp.c dpu_hw_intf.c dpu_hw_pingpong.c dpu_power.c / dpu_power.h dpu_core_irq.c / dpu_core_irq.h dpu_hw_util.c / dpu_hw_mdss.h 📁 关键路径:dpu_crtc.c → dpu_hw_ctl.c → dpu_hw_intf.c → dpu_power.c 时钟配置入口在 dpu_power.c,通过 clk_bulk API 操作 DPU 时钟域

2.3.1 核心文件功能速查表

文件名 功能描述 课程关注度
dpu_kms.c DPU KMS初始化、模式设置入口、全局资源管理 ⭐⭐⭐
dpu_crtc.c CRTC实现,包含dpu_crtc_atomic_flush、dpu_crtc_vblank_cb等核心回调 ⭐⭐⭐⭐⭐
dpu_plane.c 图层管理,SSPP硬件配置、源裁剪、缩放、格式转换 ⭐⭐⭐⭐
dpu_encoder.c 编码器实现,管理INTF接口、帧完成中断、传输模式 ⭐⭐⭐
dpu_hw_ctl.c 硬件控制块,负责显示管线启动/停止、刷新触发、安全模式 ⭐⭐⭐⭐
dpu_hw_intf.c 接口硬件抽象,配置时序参数、分辨率、像素时钟 ⭐⭐⭐⭐
dpu_power.c 电源与时钟管理,时钟频率配置、使能/禁能、带宽投票 ⭐⭐⭐⭐⭐
dpu_hw_catalog.c 硬件目录,定义SA8155支持的DPU硬件块列表与能力 ⭐⭐

2.3.2 代码调用链路示例:CRTC使能流程

当用户空间通过DRM原子提交使能CRTC时,驱动内部会经历以下调用链:

  1. dpu_crtc_atomic_enable() → 设置CRTC状态为启用,启动VBlank定时器
  2. dpu_crtc_setup_mixer() → 配置Mixer与PingPong硬件块
  3. dpu_encoder_prepare() → 准备编码器,配置INTF接口参数
  4. dpu_power_clk_enable() → 使能DPU时钟域,设置时钟频率
  5. dpu_hw_ctl_start() → 启动硬件控制块,开始扫描输出
// dpu_crtc_atomic_enable 简化代码片段
static void dpu_crtc_atomic_enable(struct drm_crtc *crtc,
                                   struct drm_crtc_state *old_state)
{
    struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
    struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(dpu_crtc);

    // 1. 使能时钟
    dpu_power_clk_enable(&dpu_kms->power, DPU_CLK_AHB);
    dpu_power_clk_set_rate(&dpu_kms->power, DPU_CLK_CORE, dpu_crtc->cur_mode->clock * 1000);

    // 2. 配置Mixer
    dpu_crtc_setup_mixer(dpu_crtc, crtc->state);

    // 3. 启动硬件控制块
    dpu_hw_ctl_start(dpu_crtc->hw_ctl, DPU_CTL_MODE_VIDEO);

    // 4. 使能VBlank
    drm_crtc_vblank_on(crtc);
}
⚠️ 时钟配置陷阱: SA8155的DPU时钟域包含多个时钟源(core_clk、ahb_clk、axi_clk、vsync_clk等),dpu_power_clk_set_rate()必须在时钟使能之后调用,且频率值必须与硬件目录中定义的频率表匹配,否则会导致显示黑屏或时序异常。

2.4 本章小结

  • DRM框架 提供了CRTC、Plane、Encoder、Connector四大抽象对象,原子提交机制是SA8155显示驱动的核心交互方式。
  • MSM DRM架构 分为用户空间 → DRM核心 → MSM驱动 → DPU/Adreno子驱动 → 硬件抽象层五层,每层职责清晰。
  • SA8155代码结构 集中在dpu1/目录,dpu_crtc.c和dpu_power.c是时钟配置实践中最常修改的文件。
  • 下一章将深入DPU硬件管线,详细拆解Mixer、PingPong、INTF、SSPP等硬件模块的工作原理与寄存器配置。