4. 设备树配置实战:瑞芯微显示控制器设备树节点解析、时钟与复位配置、接口绑定(HDMI/DP/MIPI)

设备树(Device Tree)是瑞芯微平台显示驱动开发的基石。DRM/KMS 驱动在初始化阶段通过解析设备树节点获取硬件资源(寄存器基址、中断号、时钟、复位信号)以及显示接口的物理连接信息。本章将深入解析 RK3588/RK3568 等主流芯片的显示控制器设备树节点结构,并逐一拆解时钟与复位配置、HDMI/DP/MIPI 接口绑定的标准写法。

4.1 显示控制器设备树节点结构

瑞芯微平台通常包含多个显示控制器(VOP / VPU),每个控制器对应一个独立的设备树节点。以 RK3588 为例,其 VOP(Video Output Processor)节点位于 soc 总线下,核心属性如下表所示:

属性名 类型 说明 典型值(RK3588 VOP)
compatible string 驱动匹配字符串 "rockchip,rk3588-vop"
reg u64 数组 寄存器地址与长度 <0x0 0xfdd90000 0x0 0x6000>
interrupts u32 数组 中断号与触发类型 <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>
clocks phandle 数组 时钟句柄列表 <&cru ACLK_VOP>, <&cru HCLK_VOP>
clock-names string 数组 时钟名称 "aclk", "hclk"
resets phandle 数组 复位信号句柄 <&cru SRST_VOP_A>, <&cru SRST_VOP_H>
reset-names string 数组 复位名称 "axi", "ahb"
iommus phandle IOMMU 绑定 <&vop_mmu>
ports 子节点 显示输出端口绑定 见 4.3 节
关键点: compatible 字符串必须与内核驱动中 of_device_id 表严格匹配,否则驱动无法 probe。RK3588 的 VOP 驱动匹配字符串为 "rockchip,rk3588-vop",而 RK3568 为 "rockchip,rk3568-vop"。

以下是一个完整的 RK3588 VOP 设备树节点示例:

vop: vop@fdd90000 {
    compatible = "rockchip,rk3588-vop";
    reg = <0x0 0xfdd90000 0x0 0x6000>,
          <0x0 0xfdd91000 0x0 0x1000>;
    reg-names = "vop", "gamma-lut";
    interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru ACLK_VOP>,
             <&cru HCLK_VOP>,
             <&cru DCLK_VOP0>;
    clock-names = "aclk", "hclk", "dclk";
    resets = <&cru SRST_VOP_A>,
             <&cru SRST_VOP_H>;
    reset-names = "axi", "ahb";
    iommus = <&vop_mmu>;
    power-domains = <&power RK3588_PD_VOP>;
    status = "disabled";

    vop_out: ports {
        #address-cells = <1>;
        #size-cells = <0>;

        vop_out_edp: endpoint@0 {
            reg = <0>;
            remote-endpoint = <&edp_in_vop>;
        };

        vop_out_dp: endpoint@1 {
            reg = <1>;
            remote-endpoint = <&dp_in_vop>;
        };
    };
};

4.2 时钟与复位配置

显示控制器的时钟与复位配置直接影响驱动初始化和显示时序的稳定性。瑞芯微平台使用 CRU(Clock and Reset Unit)统一管理时钟与复位信号。

4.2.1 时钟配置规范

VOP 节点通常需要以下三类时钟:

  • aclk:AXI 总线时钟,用于 VOP 与内存控制器之间的数据搬运,频率通常为 400MHz~600MHz。
  • hclk:AHB 总线时钟,用于 VOP 寄存器访问,频率通常为 100MHz~200MHz。
  • dclk:像素时钟(Display Clock),用于生成 VOP 内部像素流水线时序,频率取决于输出分辨率(如 4K@60 需要 594MHz)。
调试建议: 如果驱动 probe 失败,首先检查 clk_get_rate 返回值。使用 cat /sys/kernel/debug/clk/clk_summary | grep vop 可以查看 VOP 相关时钟的当前频率和开启状态。

时钟配置的常见错误及解决方案:

错误现象 可能原因 解决方案
驱动 probe 返回 -EPROBE_DEFER 时钟 phandle 指向的 CRU 节点未就绪 检查 clocks 属性中的 phandle 是否正确,确保 CRU 节点 status = "okay"
显示无输出,dmesg 显示 "failed to enable dclk" dclk 频率设置超出 PLL 范围 在 CRU 节点中配置合适的 assigned-clock-rates
屏幕闪烁或撕裂 aclk 频率不足,无法满足带宽需求 提高 aclk 频率或降低显示分辨率

4.2.2 复位配置规范

复位信号用于在驱动初始化时确保 VOP 内部逻辑处于已知状态。瑞芯微平台通常提供两个复位信号:

  • axi:复位 AXI 总线接口逻辑。
  • ahb:复位 AHB 总线接口逻辑。

驱动中复位操作的典型流程:

/* 驱动 probe 中的复位处理 */
struct reset_control *axi_rst, *ahb_rst;

axi_rst = devm_reset_control_get_exclusive(dev, "axi");
ahb_rst = devm_reset_control_get_exclusive(dev, "ahb");

/* 先释放复位,再进入工作状态 */
reset_control_deassert(axi_rst);
reset_control_deassert(ahb_rst);
注意: 复位信号必须在时钟使能之后操作。如果先释放复位再使能时钟,可能导致 VOP 内部状态机进入不可预测状态。正确的顺序是:使能时钟 → 释放复位 → 初始化寄存器。

4.3 接口绑定:HDMI / DP / MIPI

瑞芯微显示控制器的输出接口通过 ports 子节点与外部显示接口控制器(HDMI、DP、MIPI DSI)绑定。这种绑定使用 remote-endpoint 属性建立 VOP 与接口控制器之间的数据通路。

4.3.1 接口绑定架构

以下 SVG 图展示了 VOP 与三种显示接口控制器的绑定关系:

瑞芯微 VOP 显示接口绑定架构 VOP 控制器 vop@fdd90000 ports 子节点 endpoint@0 eDP 输出 endpoint@1 DP 输出 endpoint@2 HDMI 输出 eDP 控制器 edp@fdec0000 DP 控制器 dp@fde60000 HDMI 控制器 hdmi@fde80000 remote-endpoint 属性建立 VOP 与接口控制器之间的数据通路,DRM 驱动通过解析 ports 子节点自动创建连接

4.3.2 HDMI 接口绑定

HDMI 接口绑定需要 VOP 的 endpoint 与 HDMI 控制器的 input endpoint 建立连接。以下是一个完整的 HDMI 绑定示例:

/* VOP 节点中的 HDMI endpoint */
vop_out_hdmi: endpoint@2 {
    reg = <2>;
    remote-endpoint = <&hdmi_in_vop>;
};

/* HDMI 控制器节点 */
hdmi: hdmi@fde80000 {
    compatible = "rockchip,rk3588-hdmi";
    reg = <0x0 0xfde80000 0x0 0x20000>;
    interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru PCLK_HDMI0>,
             <&cru HCLK_HDMI0>,
             <&cru HDMITX0_REF>;
    clock-names = "pclk", "hclk", "ref";
    pinctrl-names = "default";
    pinctrl-0 = <&hdmitx0_hpd &hdmitx0_scl &hdmitx0_sda>;
    status = "disabled";

    ports {
        #address-cells = <1>;
        #size-cells = <0>;

        hdmi_in: port@0 {
            reg = <0>;
            #address-cells = <1>;
            #size-cells = <0>;

            hdmi_in_vop: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&vop_out_hdmi>;
            };
        };

        hdmi_out: port@1 {
            reg = <1>;
            #address-cells = <1>;
            #size-cells = <0>;

            hdmi_out_con: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&hdmi_con_in>;
            };
        };
    };
};

4.3.3 DP 接口绑定

DP 接口绑定与 HDMI 类似,但 DP 控制器通常需要额外的 data-lanes 属性来配置链路数量:

/* VOP 节点中的 DP endpoint */
vop_out_dp: endpoint@1 {
    reg = <1>;
    remote-endpoint = <&dp_in_vop>;
};

/* DP 控制器节点 */
dp: dp@fde60000 {
    compatible = "rockchip,rk3588-dp";
    reg = <0x0 0xfde60000 0x0 0x4000>;
    interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru PCLK_DP0>,
             <&cru HCLK_DP0>;
    clock-names = "pclk", "hclk";
    status = "disabled";

    ports {
        #address-cells = <1>;
        #size-cells = <0>;

        dp_in: port@0 {
            reg = <0>;
            #address-cells = <1>;
            #size-cells = <0>;

            dp_in_vop: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&vop_out_dp>;
                /* 可选:配置数据通道数 */
                data-lanes = <0 1 2 3>;
            };
        };
    };
};

4.3.4 MIPI DSI 接口绑定

MIPI DSI 接口绑定需要额外配置 DPHY 和 DSI 控制器的连接。瑞芯微平台通常使用 rockchip,mipi-dsi 驱动:

/* VOP 节点中的 MIPI DSI endpoint */
vop_out_mipi: endpoint@3 {
    reg = <3>;
    remote-endpoint = <&dsi_in_vop>;
};

/* MIPI DSI 控制器节点 */
dsi: dsi@fde20000 {
    compatible = "rockchip,rk3588-mipi-dsi2";
    reg = <0x0 0xfde20000 0x0 0x10000>;
    interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru PCLK_DSI0>,
             <&cru HCLK_DSI0>;
    clock-names = "pclk", "hclk";
    phys = <&dsi_dphy0>;
    phy-names = "dphy";
    status = "disabled";

    ports {
        #address-cells = <1>;
        #size-cells = <0>;

        dsi_in: port@0 {
            reg = <0>;
            #address-cells = <1>;
            #size-cells = <0>;

            dsi_in_vop: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&vop_out_mipi>;
            };
        };

        dsi_out: port@1 {
            reg = <1>;
            #address-cells = <1>;
            #size-cells = <0>;

            dsi_out_panel: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&panel_in_dsi>;
            };
        };
    };
};

/* DPHY 节点 */
dsi_dphy0: phy@fde21000 {
    compatible = "rockchip,rk3588-mipi-dphy";
    reg = <0x0 0xfde21000 0x0 0x1000>;
    clocks = <&cru PCLK_DSI0>;
    clock-names = "pclk";
    #phy-cells = <0>;
    status = "disabled";
};

4.4 接口绑定对比与选择

下表总结了三种显示接口在设备树绑定中的关键差异:

特性 HDMI DP MIPI DSI
最大分辨率 4K@60 (HDMI 2.0) / 8K@60 (HDMI 2.1) 4K@120 / 8K@60 (DP 1.4) 4K@60 (DSI 2.0)
是否需要 DPHY 否(内置 TMDS) 否(内置 AUX/LT) 是(必须绑定 phys 属性)
数据通道配置 无 data-lanes 可选 data-lanes 必选(1~4 通道)
热插拔检测 通过 HPD GPIO 通过 AUX 通道 通常不支持热插拔
典型应用场景 电视、显示器 电脑显示器、扩展坞 嵌入式屏幕、平板

4.5 常见问题与调试方法

实战经验: 在瑞芯微平台调试显示接口绑定时,以下三个步骤可以解决 90% 的问题:
  1. 检查 remote-endpoint 的 phandle 是否双向匹配(VOP 指向接口控制器,接口控制器指向 VOP)。
  2. 使用 cat /sys/kernel/debug/dri/0/state 查看 DRM 连接状态,确认 encoder 和 connector 是否已创建。
  3. 检查时钟频率:cat /sys/kernel/debug/clk/clk_summary | grep -E "vop|hdmi|dp|dsi"。

以下是一个典型的调试流程 SVG 图:

显示接口绑定调试流程 步骤 1 检查设备树语法 步骤 2 验证 remote-endpoint 步骤 3 检查时钟/复位 步骤 4a:检查 dmesg 错误 dmesg | grep -E "vop|hdmi|dp" 步骤 4b:检查 DRM 状态 cat /sys/kernel/debug/dri/0/state 问题定位与修复

4.6 本章小结

设备树配置是瑞芯微显示驱动开发的基础环节。本章详细解析了 VOP 节点的核心属性、时钟与复位的配置规范,以及 HDMI/DP/MIPI 三种显示接口的绑定方法。掌握这些内容后,开发者可以独立完成瑞芯微平台显示控制器的设备树配置,并为后续的 DRM 驱动开发奠定硬件描述基础。