3. SA8155 DPU驱动架构:DPU驱动在DRM框架中的位置、msm_dpu驱动模块、dpu_kms核心结构体
SA8155的显示子系统基于高通骁龙平台的Display Processing Unit (DPU) 硬件模块。在Linux内核中,DPU驱动被封装为msm_dpu驱动模块,并作为DRM/KMS框架的一个具体实现。理解DPU驱动在DRM框架中的位置、模块组成以及核心结构体dpu_kms,是进行DPU中断配置与显示时序开发的基础。
架构定位提示: DRM框架提供设备无关的显示抽象层,而msm_dpu驱动则负责将SA8155的DPU硬件能力映射到DRM的KMS接口上。所有显示时序、中断、图层合成等底层操作,最终都通过
dpu_kms结构体进行管理。
3.1 DPU驱动在DRM框架中的位置
在DRM框架中,msm_dpu驱动位于DRM Core与硬件抽象层之间。它向上通过struct drm_driver和struct drm_mode_config_funcs注册到DRM核心,向下直接操作DPU硬件寄存器。
下图展示了DPU驱动在DRM软件栈中的层级关系:
从图中可以看出,msm_dpu驱动模块是连接DRM核心与DPU硬件的桥梁。它实现了DRM框架定义的struct drm_mode_config_funcs回调,包括fb_create、output_poll_changed等,并管理着dpu_kms这一核心结构体。
3.2 msm_dpu驱动模块
msm_dpu驱动模块是SA8155显示驱动的核心实现。它由多个子模块组成,每个子模块对应DRM框架中的一个组件。下表列出了主要子模块及其职责:
| 子模块文件 | 对应DRM组件 | 核心职责 |
|---|---|---|
dpu_kms.c |
DRM设备 (struct drm_device) | 初始化/销毁DPU KMS实例,管理全局资源,注册中断处理 |
dpu_encoder.c |
DRM编码器 (struct drm_encoder) | 管理显示时序输出,控制物理接口(DSI/DP/eDP),处理VSYNC中断 |
dpu_crtc.c |
DRM CRTC (struct drm_crtc) | 管理显示流水线,协调图层合成,处理帧完成中断 |
dpu_plane.c |
DRM平面 (struct drm_plane) | 管理硬件图层(VIG/DMA),处理图层属性更新,支持缩放/旋转 |
dpu_hw_intf.c |
硬件接口层 | 封装DPU硬件接口寄存器操作,包括时序生成器、中断控制器 |
模块依赖关系:
dpu_kms作为顶层管理者,在初始化时会依次创建dpu_encoder、dpu_crtc和dpu_plane实例。这些子模块通过dpu_kms提供的dpu_hw_intf接口访问硬件寄存器,实现显示时序配置与中断控制。
msm_dpu驱动模块的初始化流程如下:
- 平台驱动探测: 内核调用
dpu_kms_probe(),匹配设备树节点,获取MMIO基地址和中断号。 - DRM设备注册: 调用
drm_dev_alloc()分配struct drm_device,并将dpu_kms结构体关联到drm_device->dev_private。 - 模式配置初始化: 设置
drm_mode_config的min_width、max_width、funcs等参数。 - 子模块创建: 依次创建
dpu_encoder、dpu_crtc、dpu_plane,并注册到DRM框架。 - 中断注册: 通过
devm_request_irq()注册DPU中断处理函数,包括VSYNC、帧完成、错误中断等。 - DRM设备注册: 调用
drm_dev_register(),使设备对用户空间可见。
3.3 dpu_kms核心结构体
dpu_kms是msm_dpu驱动中最重要的数据结构,它封装了整个DPU显示子系统的状态和控制信息。该结构体定义在drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h中。
以下是dpu_kms结构体的核心字段及其作用:
struct dpu_kms {
struct drm_device *dev; // 关联的DRM设备
struct platform_device *pdev; // 平台设备指针
void __iomem *mmio; // DPU寄存器MMIO基地址
unsigned long mmio_size; // MMIO区域大小
struct dpu_hw_catalog *catalog; // 硬件能力描述表
struct dpu_rm *rm; // 资源管理器
struct dpu_irq_controller irq_ctrl; // 中断控制器
struct dpu_encoder *encoders[DPU_MAX_ENCODERS]; // 编码器数组
struct dpu_crtc *crtcs[DPU_MAX_CRTCS]; // CRTC数组
struct dpu_plane *planes[DPU_MAX_PLANES]; // 平面数组
struct clk *core_clk; // DPU核心时钟
struct clk *vsync_clk; // VSYNC时钟
struct clk *axi_clk; // AXI总线时钟
struct regulator *vdd; // DPU电源域
bool has_danger_ctrl; // 是否支持危险控制
bool has_idle_pc; // 是否支持空闲电源管理
};
下表对关键字段进行详细说明:
| 字段 | 类型 | 说明 |
|---|---|---|
mmio |
void __iomem * |
DPU硬件寄存器的虚拟地址基址,所有寄存器读写操作都通过此指针进行 |
catalog |
struct dpu_hw_catalog * |
描述SA8155 DPU硬件能力,包括支持的最大分辨率、图层数、混色器数量等 |
rm |
struct dpu_rm * |
资源管理器,负责分配和回收硬件资源(如混色器、接口、图层管道) |
irq_ctrl |
struct dpu_irq_controller |
中断控制器,管理DPU所有中断的注册、使能、处理和清理 |
encoders |
struct dpu_encoder *[] |
编码器数组,每个编码器对应一个物理显示接口(如DSI0、DSI1、DP) |
core_clk |
struct clk * |
DPU核心时钟,控制显示处理单元的运行频率,直接影响显示时序 |
下图展示了dpu_kms结构体与各子模块之间的关系:
开发注意事项: 在编写DPU中断处理函数时,必须通过
dpu_kms->irq_ctrl来注册和注销中断,而不是直接调用request_irq。因为dpu_irq_controller封装了中断的共享处理逻辑,确保多个子模块(如encoder和crtc)可以安全地共享同一个硬件中断线。