2. DRM框架基础:核心概念与对象模型
DRM (Direct Rendering Manager) 是 Linux 内核中负责图形显示和渲染管理的核心框架。在 SA8155 平台显示子系统调试中,理解 DRM 的对象模型与设备注册流程是定位链路问题的前提。本章从四个核心抽象对象入手,逐步拆解 DRM 的层次结构。
2.1 四大核心概念
DRM 将显示硬件抽象为 CRTC、Encoder、Connector、Plane 四种对象,它们共同构成一条完整的显示链路。
| 对象 | 职责 | 硬件对应 | 关键属性 |
|---|---|---|---|
| CRTC | 扫描输出控制,生成时序信号 | Display Controller (DPU/DSI) | 分辨率、刷新率、VBLANK、Gamma |
| Encoder | 像素数据编码/转换 | MDP/DPU 内部编码模块 | 编码类型 (RGB/YPbPr)、桥接 |
| Connector | 物理接口与显示器探测 | HDMI/DP/DSI 物理接口 | EDID、热插拔、连接状态 |
| Plane | 图层叠加与合成 | 硬件图层 (Overlay/Blender) | Z-order、Alpha、裁剪、格式 |
调试要点: 在 SA8155 上,CRTC 通常对应 DPU (Display Processing Unit) 的 Mixer 实例;Plane 对应 DPU 的 SSPP (Source Surface Processor Pipe)。链路不通时,优先检查 Connector 的
status 和 Encoder 的 possible_crtcs 掩码。
2.2 DRM 对象模型
DRM 采用 通用对象模型 (GEM-like) 管理所有显示资源。每个核心对象都继承自 drm_mode_object,通过 id 和 type 唯一标识。
2.2.1 对象继承层次
struct drm_mode_object {
uint32_t id; // 全局唯一 ID
uint32_t type; // DRM_MODE_OBJECT_CRTC / ENCODER / CONNECTOR / PLANE
struct drm_object_properties *properties;
};
struct drm_crtc {
struct drm_mode_object base;
struct drm_plane *primary; // 主图层
struct drm_plane *cursor; // 光标图层
struct drm_display_mode mode;
// ... 硬件相关字段
};
struct drm_encoder {
struct drm_mode_object base;
uint32_t possible_crtcs; // 位掩码,标识可绑定的 CRTC
uint32_t possible_clones; // 位掩码,标识可克隆的 Encoder
};
struct drm_connector {
struct drm_mode_object base;
struct drm_encoder *encoder; // 当前绑定的 Encoder
enum drm_connector_status status; // connected / disconnected
struct edid *edid;
};
struct drm_plane {
struct drm_mode_object base;
uint32_t possible_crtcs;
uint32_t format_count;
uint32_t *formats; // 支持的像素格式列表
};
关键字段解读:
possible_crtcs:位掩码,bit i 表示该对象可以绑定到第 i 个 CRTC。调试时若链路不通,常因掩码未正确配置。possible_clones:仅 Encoder 使用,表示哪些 Encoder 可以同时输出相同画面(克隆模式)。status:Connector 的物理连接状态,通过drm_helper_hpd_irq_event()热插拔更新。
2.2.2 对象属性 (Properties)
DRM 通过 属性 (Property) 机制暴露可配置参数,用户态通过 drmModeObjectSetProperty() 或 Atomic API 修改。常见属性包括:
| 属性名 | 所属对象 | 类型 | 说明 |
|---|---|---|---|
CRTC_ID |
Plane / Connector | Object | 绑定到的 CRTC ID |
MODE_ID |
CRTC | Blob | 显示模式 (分辨率/刷新率) |
ACTIVE |
CRTC | Boolean | CRTC 是否启用 |
FB_ID |
Plane | Object | 当前帧缓冲 ID |
SRC_X/Y/W/H |
Plane | Range | 源裁剪区域 (16.16 定点) |
CRTC_X/Y/W/H |
Plane | Range | 目标显示位置 |
zpos |
Plane | Range | 图层 Z 序 (0 为底层) |
alpha |
Plane | Range | 全局透明度 (0~65535) |
2.3 DRM 设备注册流程
DRM 设备注册是显示驱动初始化的核心步骤,分为 框架层 和 驱动层 两个阶段。以下以 SA8155 的 msm_drm 驱动为例,展示完整流程。
2.3.1 注册流程步骤
- 分配 DRM 设备:
drm_dev_alloc()分配struct drm_device,设置driver回调。 - 加载驱动:
devm_drm_dev_register()或drm_dev_register(),触发bind()回调。 - 创建核心对象:在
bind()中依次创建 CRTC、Encoder、Connector、Plane,并注册到 DRM 核心。 - 配置链路:通过
drm_mode_config_reset()初始化默认状态,设置possible_crtcs等掩码。 - 注册设备节点:创建
/dev/dri/card0字符设备,用户态可通过drmModeGetResources()枚举对象。 - 启用热插拔:注册
drm_connector的poll或中断处理,检测显示器连接状态。
2.3.2 关键代码路径
// SA8155 msm_drm 驱动 bind 回调简化示例
static int msm_drm_bind(struct device *dev)
{
struct drm_device *ddev;
int ret;
// 1. 分配 DRM 设备
ddev = drm_dev_alloc(&msm_driver, dev);
if (IS_ERR(ddev))
return PTR_ERR(ddev);
// 2. 初始化模式配置
ddev->mode_config.min_width = 0;
ddev->mode_config.max_width = 4096;
ddev->mode_config.funcs = &msm_mode_config_funcs;
// 3. 创建 CRTC (DPU Mixer)
ret = msm_dpu_crtc_init(ddev, crtc, ...);
// 4. 创建 Encoder (DPU INTF)
ret = msm_dpu_encoder_init(ddev, encoder, ...);
// 5. 创建 Connector (DSI/DP)
ret = msm_dsi_connector_init(ddev, connector, ...);
// 6. 创建 Plane (SSPP)
ret = msm_dpu_plane_init(ddev, plane, ...);
// 7. 注册 DRM 设备
ret = drm_dev_register(ddev, 0);
if (ret)
goto err;
// 8. 启用热插拔轮询
drm_kms_helper_poll_init(ddev);
return 0;
err:
drm_dev_put(ddev);
return ret;
}
常见注册失败原因:
- possible_crtcs 未设置:Encoder 或 Plane 的
possible_crtcs为 0,导致链路无法绑定。 - Connector 状态异常:物理接口未初始化或 EDID 读取失败,导致
status为connector_status_disconnected。 - 资源冲突:多个 CRTC 竞争同一硬件 Mixer,或 Plane 数量超过硬件限制。
- 中断未注册:VBLANK 或热插拔中断缺失,导致 Atomic Commit 无法完成。
2.4 本章小结
- CRTC/Encoder/Connector/Plane 是 DRM 的四大核心抽象,分别对应显示链路中的时序生成、编码、物理接口和图层叠加。
- 对象模型 基于
drm_mode_object统一管理,通过id和properties实现用户态配置。 - 设备注册流程 从
drm_dev_alloc()到drm_dev_register(),核心在于bind()回调中创建并链接四个核心对象。 - SA8155 平台中,DPU 驱动扩展了
dpu_crtc、dpu_encoder等结构,调试时重点关注possible_crtcs和status字段。