3. RK3399 显示控制器 (VOP) 设备树节点:vopb 与 vopl 的差异、时钟配置、端口与端点绑定

RK3399 集成了两个独立的显示控制器——VOPB (Video Output Processor Big) 和 VOPL (Video Output Processor Little)。在设备树中,这两个节点分别对应 vopb 和 vopl,它们共享部分硬件资源,但在输出能力、时钟域和绑定方式上存在关键差异。理解这些差异是正确配置显示链路的基础。

3.1 VOPB 与 VOPL 的硬件差异

VOPB 是高性能显示控制器,支持更高的分辨率、更多的图层和更丰富的输出格式;VOPL 则面向低功耗场景,通常用于副屏或简单界面输出。下表列出了两者的核心差异:

特性 VOPB (vopb) VOPL (vopl)
最大输出分辨率 4096x2160 (4K) 1920x1080 (1080p)
硬件图层数 4 个 Win0~Win3 2 个 Win0~Win1
支持输出接口 DP、HDMI、MIPI DSI、eDP MIPI DSI、RGB、LVDS
AFBC 支持 支持 (帧缓冲压缩) 不支持
HDR 处理 支持 HDR10 不支持
时钟域 ACLK_VOPB / HCLK_VOPB ACLK_VOPL / HCLK_VOPL
典型用途 主屏 (HDMI/DP) 副屏 (DSI/LVDS)
选型建议: 在双屏显示场景中,通常将 VOPB 分配给高分辨率主屏(如 HDMI 4K),VOPL 分配给低分辨率副屏(如 MIPI DSI 1080p)。如果只使用单屏,优先使用 VOPB 以获得最佳性能。

3.2 时钟配置详解

每个 VOP 节点需要配置两组时钟:AXI 总线时钟 (ACLK) 和 AHB 总线时钟 (HCLK),以及可选的 DCLK (像素时钟)。时钟名称和索引必须与 SoC 的时钟树定义一致。

以下是一个典型的 VOPB 时钟配置片段:

vopb: vop@ff900000 {
    compatible = "rockchip,rk3399-vop-big";
    reg = <0x0 0xff900000 0x0 0x3efc>;
    interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru ACLK_VOPB>,
             <&cru HCLK_VOPB>,
             <&cru DCLK_VOPB>;
    clock-names = "aclk_vopb",
                  "hclk_vopb",
                  "dclk_vopb";
    power-domains = <&power RK3399_PD_VOPB>;
    resets = <&cru SRST_ACLK_VOPB>,
             <&cru SRST_HCLK_VOPB>;
    reset-names = "axi", "ahb";
    status = "disabled";
};

时钟配置的关键点:

  • ACLK:VOP 内部 AXI 总线时钟,用于图层 DMA 传输,频率通常为 400~600 MHz。
  • HCLK:AHB 总线时钟,用于寄存器访问,频率通常为 100~150 MHz。
  • DCLK:像素时钟,由 CRU (Clock & Reset Unit) 根据显示时序动态调整,频率等于像素时钟频率。
  • clock-names:必须与驱动中 devm_clk_get() 使用的名称完全匹配。
常见错误: 如果 DCLK 未正确配置或时钟频率超出 VOP 支持范围,会导致屏幕无显示或显示撕裂。调试时可通过 cat /sys/kernel/debug/clk/clk_summary | grep vop 检查时钟是否已使能。

3.3 端口 (port) 与端点 (endpoint) 绑定

RK3399 的显示链路采用 OF Graph 绑定方式,通过 port 和 endpoint 描述 VOP 与外部显示接口控制器(如 HDMI、DP、DSI)之间的连接关系。每个 VOP 节点包含一个或多个 port,每个 port 包含一个 endpoint,指向下游显示接口控制器的输入端口。

下图展示了 VOPB 和 VOPL 与外部接口的典型绑定拓扑:

RK3399 VOP 端口与端点绑定拓扑 VOPB port@0 (HDMI/DP) port@1 (MIPI DSI) VOPL port@0 (MIPI DSI) port@1 (RGB/LVDS) HDMI 控制器 ports:port@in MIPI DSI0 ports:port@in MIPI DSI1 ports:port@in endpoint@0 endpoint@1 endpoint@0 说明: 每个 VOP 的 port 对应一个输出接口,endpoint 指向下游控制器的 port@in。实际绑定由设备树中的 remote-endpoint 属性完成。

设备树中绑定的具体实现如下:

/* VOPB 节点内部 */
&vopb {
    status = "okay";

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

        vopb_out_hdmi: endpoint@0 {
            reg = <0>;
            remote-endpoint = <&hdmi_in_vopb>;
        };
    };

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

        vopb_out_dsi0: endpoint@0 {
            reg = <0>;
            remote-endpoint = <&dsi0_in_vopb>;
        };
    };
};

/* HDMI 控制器节点内部 */
&hdmi {
    status = "okay";

    ports {
        port@0 {
            reg = <0>;

            hdmi_in_vopb: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&vopb_out_hdmi>;
            };
        };
    };
};

3.4 绑定规则与调试要点

在配置端口与端点绑定时,需要遵循以下规则:

  1. 一对一绑定:每个 VOP 的 endpoint 只能连接到一个下游控制器的 endpoint,反之亦然。
  2. 端口编号对应接口类型:port@0 通常对应第一个输出接口,port@1 对应第二个。具体映射关系由 SoC 设计决定,需查阅 TRM。
  3. remote-endpoint 必须成对出现:VOP 的 endpoint 和下游控制器的 endpoint 必须互相引用,否则 OF Graph 解析失败。
  4. status 属性:未使用的 VOP 或接口应设置为 status = "disabled",避免驱动尝试初始化不存在的硬件链路。
调试命令: 使用 cat /sys/kernel/debug/dri/0/summary 可以查看当前 VOP 的绑定状态、图层配置和时钟频率。如果显示 "No connector" 或 "No encoder",说明端口绑定未正确建立。

3.5 双屏显示配置示例

以下是一个实际的双屏配置场景:VOPB 驱动 HDMI 4K 主屏,VOPL 驱动 MIPI DSI 1080p 副屏。设备树中需要同时使能两个 VOP 节点,并分别绑定到对应的输出接口。

/* 主屏:VOPB -> HDMI */
&vopb {
    status = "okay";
    assigned-clocks = <&cru DCLK_VOPB>;
    assigned-clock-rates = <594000000>;  /* 4K@60Hz 像素时钟 */
};

&hdmi {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&hdmi_cec>;
};

/* 副屏:VOPL -> MIPI DSI0 */
&vopl {
    status = "okay";
    assigned-clocks = <&cru DCLK_VOPL>;
    assigned-clock-rates = <148500000>;  /* 1080p@60Hz 像素时钟 */
};

&dsi0 {
    status = "okay";
    rockchip,lane-rate = <500>;
    panel@0 {
        compatible = "boe,tv080wum-nl0";
        reg = <0>;
        enable-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
    };
};

在驱动层面,VOP 的绑定关系决定了 framebuffer 的分配策略:

  • VOPB 通常绑定 /dev/dri/card0,作为主显示设备。
  • VOPL 绑定 /dev/dri/card1,作为副显示设备。
  • 用户空间可通过 DRM_IOCTL_MODE_GETCONNECTOR 查询每个 VOP 绑定的输出接口。
性能提示: 双屏显示时,两个 VOP 共享 DDR 带宽。如果同时播放 4K 视频和 1080p 动画,建议在 VOPB 上启用 AFBC 压缩以减少带宽占用,避免画面卡顿。