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 掩码。
DRM 核心对象关系图 Plane 图层 / SSPP CRTC 时序 / Mixer Encoder 编码 / 桥接 Connector 物理接口 绑定 possible_crtcs possible_clones 说明: 一个 CRTC 可绑定多个 Plane(图层叠加);一个 Encoder 可连接多个 Connector(克隆模式)。 SA8155 典型链路:Plane(SSPP) → CRTC(Mixer) → Encoder(DPU_INTF) → Connector(DSI/DP)。

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)
DRM 对象模型继承层次 drm_mode_object drm_plane drm_crtc drm_encoder drm_connector 对象模型核心机制: 1. 每个对象通过 drm_mode_object.id 唯一标识,用户态通过 ID 访问。 2. 属性 (Property) 以链表挂载在 drm_object_properties 上,支持 Atomic 批量更新。 3. SA8155 的 DPU 驱动在 drm_crtc 中扩展了 dpu_crtc_state,包含 Mixer 配置。

2.3 DRM 设备注册流程

DRM 设备注册是显示驱动初始化的核心步骤,分为 框架层 和 驱动层 两个阶段。以下以 SA8155 的 msm_drm 驱动为例,展示完整流程。

2.3.1 注册流程步骤

  1. 分配 DRM 设备:drm_dev_alloc() 分配 struct drm_device,设置 driver 回调。
  2. 加载驱动:devm_drm_dev_register() 或 drm_dev_register(),触发 bind() 回调。
  3. 创建核心对象:在 bind() 中依次创建 CRTC、Encoder、Connector、Plane,并注册到 DRM 核心。
  4. 配置链路:通过 drm_mode_config_reset() 初始化默认状态,设置 possible_crtcs 等掩码。
  5. 注册设备节点:创建 /dev/dri/card0 字符设备,用户态可通过 drmModeGetResources() 枚举对象。
  6. 启用热插拔:注册 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 无法完成。
DRM 设备注册流程 (SA8155 msm_drm) drm_dev_alloc() msm_drm_bind() 创建 CRTC (Mixer) 创建 Encoder (INTF) 创建 Connector 创建 Plane (SSPP) drm_dev_register() drm_kms_helper_poll_init() /dev/dri/card0 就绪 注册完成后,用户态可通过 libdrm 调用 drmModeGetResources() 枚举所有 CRTC/Encoder/Connector/Plane 对象。 调试时使用 cat /sys/kernel/debug/dri/0/state 查看当前对象状态。

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 字段。