3、CRTC基础概念:CRTC的作用、CRTC与显示管线的映射关系、CRTC的初始化流程

3.1 CRTC的核心作用

CRTC(Cathode Ray Tube Controller,阴极射线管控制器)是显示子系统的核心时序引擎。在SA8155平台的DPU(Display Processing Unit)架构中,CRTC负责将软件层的抽象显示请求转换为硬件可执行的扫描输出时序。其核心职责可归纳为以下四点:

  • 时序生成:根据VESA/CEA标准或自定义模式,生成垂直同步(VSYNC)、水平同步(HSYNC)、数据使能(DE)和像素时钟(PCLK)信号。
  • 帧缓冲区扫描:从内存中指定的帧缓冲区地址按行读取像素数据,并送入下游的DPU处理管线。
  • 中断管理:在帧起始(SOF)、帧结束(EOF)、行结束(LINE)等关键事件点向CPU触发中断,驱动垂直同步(V-Sync)和缓冲区翻转机制。
  • 电源状态控制:管理显示管线的时钟门控和电源域,支持DPU进入低功耗状态。
关键概念:在SA8155的DRM(Direct Rendering Manager)框架中,CRTC是drm_crtc结构体的具体实现。每个CRTC实例对应一个独立的显示输出通道,负责驱动一个物理显示接口(如DP、DSI、HDMI)。

3.2 CRTC与显示管线的映射关系

SA8155的显示管线采用“分层-合成-输出”的流水线架构。CRTC位于管线的中间层,连接上游的Plane(图层)和下游的Encoder(编码器)/Connector(连接器)。下图展示了CRTC在显示管线中的核心位置:

SA8155 显示管线:CRTC 映射关系 Plane 0 (主屏) drm_plane Plane 1 (光标) drm_plane Plane 2 (视频) drm_plane CRTC drm_crtc 时序引擎 + 合成 DPU CRTC 实例 Encoder drm_encoder Connector drm_connector 说明: 一个 CRTC 可以绑定多个 Plane(图层叠加),但只能连接一个 Encoder-Connector 对。 SA8155 最多支持 3 个 CRTC 实例,分别对应主屏、副屏和 DP 输出。

CRTC与显示管线的映射遵循以下规则:

组件 DRM对象 与CRTC的关系 SA8155实例数
Plane(图层) drm_plane CRTC从绑定的Plane列表中读取像素源,进行硬件合成 每个CRTC最多4个Plane
Encoder(编码器) drm_encoder CRTC将合成后的像素流推送给Encoder进行协议编码 每个CRTC绑定1个Encoder
Connector(连接器) drm_connector 通过Encoder间接关联,代表物理显示接口 每个Encoder绑定1个Connector
DPU硬件块 msm_dpu_crtc CRTC的硬件后端,包含Mixer(合成器)和时序发生器 与CRTC 1:1对应
开发提示:在SA8155的DPU驱动中,CRTC的硬件后端由dpu_crtc结构体描述。该结构体包含dpu_hw_mixer(硬件合成器)和dpu_hw_ctl(控制寄存器)两个关键子模块。CRTC的初始化本质上是为这两个硬件模块分配资源并建立映射。

3.3 CRTC的初始化流程

CRTC的初始化在SA8155显示驱动中分为三个阶段:硬件探测阶段、DRM对象创建阶段和模式配置阶段。完整的初始化流程如下图所示:

CRTC 初始化流程(SA8155 DPU) 阶段一:硬件探测与资源枚举 dpu_probe() 读取DTB硬件配置 dpu_hw_catalog_init() 枚举Mixer/CTL资源 dpu_rm_init() 资源管理器初始化 阶段二:DRM CRTC 对象创建 msm_drm_init() 调用drm_mode_config_init dpu_crtc_init() 分配drm_crtc + dpu_crtc drm_crtc_init() 注册到DRM核心 阶段三:模式配置与时钟绑定 dpu_crtc_atomic_check() 验证模式有效性 dpu_crtc_setup_mixer() 绑定硬件Mixer资源 dpu_crtc_enable() 使能时钟 + 启动时序 关键时序点: CRTC初始化完成后,驱动会调用 drm_crtc_vblank_on() 开启垂直同步中断。 时钟配置在 dpu_crtc_enable() 中通过 clk_set_rate() 设置像素时钟频率。 如果时钟频率与显示模式不匹配,CRTC将无法输出有效时序。

3.4 初始化流程关键代码解析

在SA8155的DPU驱动中,CRTC初始化的核心函数位于drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c。以下是dpu_crtc_init()的简化实现:

struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane)
{
    struct dpu_crtc *dpu_crtc;
    struct drm_crtc *crtc;
    int ret;

    // 1. 分配 dpu_crtc 结构体(包含硬件上下文)
    dpu_crtc = devm_kzalloc(dev->dev, sizeof(*dpu_crtc), GFP_KERNEL);
    if (!dpu_crtc)
        return ERR_PTR(-ENOMEM);

    crtc = &dpu_crtc->base;

    // 2. 调用 DRM 核心初始化
    ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
                                    &dpu_crtc_funcs, NULL);
    if (ret) {
        dev_err(dev->dev, "drm_crtc_init failed: %d\n", ret);
        return ERR_PTR(ret);
    }

    // 3. 初始化硬件资源列表(Mixer、CTL)
    INIT_LIST_HEAD(&dpu_crtc->mixers);
    INIT_LIST_HEAD(&dpu_crtc->ctl_events);

    // 4. 注册 Vblank 处理函数
    drm_crtc_vblank_reset(crtc);

    // 5. 设置 CRTC 属性(色彩空间、缩放模式等)
    dpu_crtc_init_properties(dpu_crtc);

    return crtc;
}
EXPORT_SYMBOL(dpu_crtc_init);
常见陷阱:在SA8155平台中,CRTC初始化失败通常由以下原因导致:
  • 时钟未就绪:dpu_crtc_enable()中调用clk_prepare_enable()失败,通常是因为DTB中时钟节点配置错误。
  • Mixer资源冲突:多个CRTC尝试绑定同一个硬件Mixer,导致dpu_rm_get_mixer()返回NULL。
  • 中断号错误:CRTC的Vblank中断号与硬件不一致,导致request_irq()失败。

3.5 CRTC与DPU时钟的绑定关系

CRTC的时序输出直接依赖DPU时钟域。在SA8155中,每个CRTC实例关联以下时钟:

时钟名称 时钟源 作用 典型频率范围
dpu_core_clk DPU核心PLL DPU内部逻辑时钟,驱动Mixer和CTL模块 200 MHz – 600 MHz
dpu_core_clk_src 系统PLL0 核心时钟的源时钟,用于分频生成dpu_core_clk 500 MHz – 1.2 GHz
dpu_pclk DPU像素PLL 像素时钟,直接决定CRTC的输出分辨率 25 MHz – 594 MHz
dpu_ahb_clk 系统总线时钟 AHB总线接口时钟,用于寄存器访问 37.5 MHz – 150 MHz

时钟配置的典型调用链如下:

// 在 dpu_crtc_enable() 中
static void dpu_crtc_enable(struct drm_crtc *crtc)
{
    struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
    struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);

    // 1. 根据显示模式计算像素时钟
    unsigned long pclk_rate = cstate->mode.clock * 1000; // kHz -> Hz

    // 2. 设置像素时钟频率
    clk_set_rate(dpu_crtc->pclk, pclk_rate);

    // 3. 使能核心时钟
    clk_prepare_enable(dpu_crtc->core_clk);

    // 4. 启动硬件时序发生器
    dpu_hw_ctl_start(dpu_crtc->hw_ctl);
}
调试技巧:在CRTC初始化阶段,可以通过/sys/kernel/debug/dri/0/crtc-0/clk节点查看当前CRTC的时钟频率。如果显示异常,首先检查dpu_pclk是否与mode.clock一致。使用cat /sys/kernel/debug/clk/dpu_pclk/clk_rate可以获取硬件实际设置的频率。

3.6 本章小结

  • CRTC是显示管线的时序核心,负责生成VSYNC/HSYNC/DE信号并驱动帧缓冲区扫描。
  • 在SA8155的DRM框架中,CRTC位于Plane和Encoder之间,通过drm_crtc结构体与硬件DPU块映射。
  • CRTC初始化分为硬件探测、DRM对象创建和模式配置三个阶段,每个阶段都有对应的回调函数。
  • 时钟配置是CRTC初始化的关键步骤,dpu_pclk必须与显示模式的像素时钟精确匹配。
  • 调试CRTC问题时,优先检查时钟频率、Mixer资源分配和中断注册状态。