4. CRTC核心数据结构:struct drm_crtc、struct drm_crtc_funcs、struct drm_crtc_state

在KMS(Kernel Mode Setting)框架中,CRTC(Cathode Ray Tube Controller)是显示管线的核心调度与时序控制单元。它负责从Framebuffer读取像素数据,按照设定的时序参数生成行/场同步信号,并将数据流送往Encoder。理解CRTC的三个核心数据结构——struct drm_crtc、struct drm_crtc_funcs和struct drm_crtc_state——是掌握CRTC初始配置与状态管理的前提。

核心要点:CRTC在KMS中扮演“显示控制器”角色,其数据结构设计遵循DRM的“对象-函数-状态”三元组模式,即一个对象(drm_crtc)绑定一组操作函数(drm_crtc_funcs)和一个可变状态(drm_crtc_state)。

4.1 struct drm_crtc:CRTC对象结构体

struct drm_crtc是CRTC在内核中的核心对象,继承自drm_mode_object。它描述了CRTC的硬件属性、当前配置、绑定关系以及状态指针。在SA8155平台上,每个显示接口(如DP、DSI、HDMI)通常对应一个独立的CRTC实例。

成员变量 类型 说明
dev struct drm_device * 指向所属DRM设备的指针
port struct device_node * 设备树中对应的端口节点,用于解析硬件连接
funcs const struct drm_crtc_funcs * CRTC操作函数表,驱动必须实现
state struct drm_crtc_state * 指向当前CRTC状态的指针(原子模式设置核心)
primary struct drm_plane * 主图层(Primary Plane),通常用于显示主帧缓冲
cursor struct drm_plane * 光标图层(Cursor Plane),可选
enabled bool CRTC是否已启用(非原子模式使用,原子模式通过state判断)
mode struct drm_display_mode 当前设置的显示模式(非原子模式使用)
base struct drm_mode_object DRM模式对象基类,提供ID和属性管理
SA8155实践提示:在SA8155的MDSS(Mobile Display Subsystem)中,每个CRTC对应一个硬件显示控制器(如DPU的Mixer)。初始化时,需要通过drm_crtc_init_with_planes()将CRTC与Primary Plane和Cursor Plane绑定。
// CRTC初始化示例(SA8155 DPU驱动简化版)
struct drm_crtc *crtc;
int ret;

crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
if (!crtc)
    return -ENOMEM;

// 绑定主图层和光标图层,并注册CRTC
ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, cursor_plane,
                                &msm_crtc_funcs, "primary_crtc");
if (ret) {
    kfree(crtc);
    return ret;
}

// 设置CRTC端口(用于设备树解析)
crtc->port = of_graph_get_port_by_id(dev->dev->of_node, 0);

4.2 struct drm_crtc_funcs:CRTC操作函数表

struct drm_crtc_funcs定义了驱动需要实现的CRTC操作回调。这些回调是KMS框架与硬件交互的接口,涵盖了CRTC的使能、模式设置、原子状态管理、属性控制等核心功能。

关键设计:在原子模式设置(Atomic Mode Setting)中,atomic_check和atomic_flush(或atomic_begin/atomic_end)是驱动必须实现的两个核心回调,它们分别负责状态验证和硬件提交。
回调函数 作用 原子模式要求
set_config 设置CRTC的显示模式(非原子模式入口) 可选(原子模式通过atomic_check替代)
destroy 销毁CRTC对象,释放资源 必须实现
page_flip 页面翻转,用于实现VBlank同步的缓冲区切换 必须实现(或通过atomic_flush实现)
set_property 设置CRTC属性(非原子模式) 可选(原子模式通过atomic_set_property替代)
atomic_duplicate_state 复制CRTC状态,用于原子事务的状态快照 必须实现
atomic_destroy_state 销毁CRTC状态 必须实现
atomic_set_property 原子模式下设置CRTC属性 推荐实现(用于自定义属性)
atomic_get_property 原子模式下获取CRTC属性 推荐实现
enable_vblank 使能VBlank中断 必须实现(用于页面翻转和性能监测)
disable_vblank 禁用VBlank中断 必须实现
// SA8155 CRTC函数表定义示例
static const struct drm_crtc_funcs msm_crtc_funcs = {
    .set_config       = drm_atomic_helper_set_config,
    .destroy          = msm_crtc_destroy,
    .page_flip        = drm_atomic_helper_page_flip,
    .atomic_duplicate_state = msm_crtc_duplicate_state,
    .atomic_destroy_state   = msm_crtc_destroy_state,
    .atomic_set_property    = msm_crtc_atomic_set_property,
    .atomic_get_property    = msm_crtc_atomic_get_property,
    .enable_vblank    = msm_crtc_enable_vblank,
    .disable_vblank   = msm_crtc_disable_vblank,
};
常见错误:在实现atomic_duplicate_state时,必须调用__drm_atomic_helper_crtc_duplicate_state()来复制公共状态字段,否则会导致状态丢失或内存泄漏。同样,atomic_destroy_state中应调用__drm_atomic_helper_crtc_destroy_state()。

4.3 struct drm_crtc_state:CRTC原子状态

struct drm_crtc_state是原子模式设置的核心数据结构,它保存了CRTC在某一时刻的完整配置快照。KMS框架通过状态比较(drm_atomic_crtc_needs_modeset())来判断是否需要重新配置硬件。

成员变量 类型 说明
crtc struct drm_crtc * 指向所属CRTC的指针
enable bool CRTC是否启用(原子模式替代drm_crtc.enabled)
active bool CRTC是否处于激活状态(与power管理相关)
mode struct drm_display_mode 当前请求的显示模式
adjusted_mode struct drm_display_mode 硬件调整后的模式(考虑时钟限制、边界调整等)
mode_changed bool 模式是否发生变化(由框架自动计算)
active_changed bool 激活状态是否发生变化
connectors_changed bool 连接的Connector是否发生变化
plane_mask u32 位掩码,标识哪些Plane绑定到此CRTC
event struct drm_pending_vblank_event * 页面翻转事件,用于用户空间同步
state struct drm_atomic_state * 指向所属原子事务状态的指针
// CRTC状态复制函数示例(SA8155扩展状态)
struct msm_crtc_state {
    struct drm_crtc_state base;  // 必须作为第一个成员
    // SA8155私有扩展字段
    u32 interface_type;          // 接口类型:DP/DSI/HDMI
    u32 mixer_id;                // DPU Mixer硬件ID
    bool dual_pipe;              // 是否启用双管道模式
};

struct drm_crtc_state *msm_crtc_duplicate_state(struct drm_crtc *crtc)
{
    struct msm_crtc_state *state;

    state = kmalloc(sizeof(*state), GFP_KERNEL);
    if (!state)
        return NULL;

    // 复制公共状态字段
    __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);

    // 复制私有字段
    state->interface_type = to_msm_crtc_state(crtc->state)->interface_type;
    state->mixer_id = to_msm_crtc_state(crtc->state)->mixer_id;
    state->dual_pipe = to_msm_crtc_state(crtc->state)->dual_pipe;

    return &state->base;
}

4.4 数据结构关系图

下图展示了CRTC三个核心数据结构之间的关联,以及它们与KMS框架中其他组件(Plane、Connector、Encoder)的关系。

CRTC核心数据结构关系图 CRTC核心数据结构关系图 struct drm_crtc CRTC对象:硬件控制器抽象 struct drm_crtc_funcs 操作函数表:回调接口 struct drm_crtc_state 原子状态:配置快照 funcs指针 state指针 struct drm_plane 图层(Primary/Cursor) struct drm_encoder 编码器(数据流输出) struct drm_connector 连接器(物理接口) primary/cursor encoder绑定 connector绑定 说明: 1. drm_crtc 通过 funcs 指针调用硬件操作,通过 state 指针管理当前配置。 2. 原子模式设置中,所有配置修改通过 drm_crtc_state 进行,提交时由 atomic_check 验证。

4.5 原子状态管理流程

在原子模式设置中,CRTC的状态管理遵循“复制-修改-验证-提交”的流程。驱动通过drm_atomic_state事务来协调CRTC、Plane和Connector的状态变更。

  1. 状态复制:调用atomic_duplicate_state创建当前状态的快照。
  2. 属性修改:通过atomic_set_property修改状态中的特定字段(如mode、enable)。
  3. 原子检查:框架调用drm_atomic_check_only,触发各个对象的atomic_check回调,验证状态组合的合法性。
  4. 硬件提交:通过drm_atomic_commit提交状态,框架调用atomic_flush(或atomic_begin/atomic_end)将配置写入硬件寄存器。
  5. 状态替换:提交成功后,框架将crtc->state指针指向新状态,旧状态被销毁。
// 原子模式设置中CRTC状态检查示例
static int msm_crtc_atomic_check(struct drm_crtc *crtc,
                                 struct drm_crtc_state *state)
{
    struct msm_crtc_state *msm_state = to_msm_crtc_state(state);
    struct drm_display_mode *mode = &state->adjusted_mode;
    int ret;

    // 1. 检查模式时序是否在硬件支持范围内
    ret = msm_dpu_mode_valid(crtc, mode);
    if (ret)
        return ret;

    // 2. 检查接口类型与Mixer的兼容性
    if (msm_state->interface_type == INTERFACE_DP &&
        msm_state->mixer_id > MAX_DP_MIXER_ID)
        return -EINVAL;

    // 3. 检查Plane掩码是否有效
    if (hweight32(state->plane_mask) > MAX_PLANES_PER_CRTC)
        return -EINVAL;

    return 0;
}
调试技巧:在SA8155开发中,可以通过drm_atomic_crtc_needs_modeset(state)判断当前状态变更是否需要重新配置硬件时序。如果返回true,驱动必须在atomic_flush中执行完整的CRTC关闭-配置-重新使能序列。

4.6 关键差异对比

对比维度 drm_crtc drm_crtc_funcs drm_crtc_state
角色 CRTC对象实例 操作接口定义 配置状态容器
生命周期 驱动加载时创建,卸载时销毁 静态常量,全局共享 每次原子提交创建,提交后销毁
可变性 部分字段可变(如state指针) 不可变(const) 可变(通过原子事务修改)
存储位置 堆分配(kzalloc) 代码段(.rodata) 堆分配(kmalloc)
核心作用 表示硬件CRTC 提供硬件操作方法 保存原子配置快照
总结:在SA8155显示驱动开发中,struct drm_crtc是CRTC的“身份证”,struct drm_crtc_funcs是CRTC的“操作手册”,struct drm_crtc_state是CRTC的“状态快照”。三者协同工作,构成了KMS框架中CRTC管理的基础。驱动开发者的核心任务就是正确实现这三个结构体,并确保它们之间的数据流和状态转换符合原子模式设置的规范。