HDMI
芯片名称与内核版本
- 芯片名称:RK322X/RK3328/RK3368/RK3399/RK3288/RK3528/RK356X/RK3588
- 内核版本:LINUX kernel 6.1/5.10/4.19/4.4
前言
本文主要介绍 Rockchip 平台基于 DRM 显示框架的 HDMI 的使用与调试方法。
概述
产品版本
- RK3288
- RK3368
- RK322X
- RK3328
- RK3399
- RK3528
- RK356X
- RK3588
- RK3576
读者对象
- 技术支持工程师
- 软件开发工程师
1. Rockchip 平台 HDMI 简介
Rockchip 各平台的 HDMI 功能如下:
功能 | RK3288 | RK3368 | RK322X | RK3328 | RK3399 | RK3528 | RK356X | RK3588 | RK3576 |
---|---|---|---|---|---|---|---|---|---|
最大输出分辨率 | 3840x2160p60 | 4096x2160p60 | 4096x2160p60 | 4096x2160p60 | 4096x2160p60 | 4096x2160p60 | 4096x2160p60 | 7680x4320p60 | 4096x2160p120 |
隔行模式 | N | N | Y | Y | Y | Y | Y | Y | Y |
支持的颜色格式 | RGB, YCbCr444, YCbCr422, YCbCr420 (仅 RK3288W 支持 YCbCr420) | RGB, YCbCr444, YCbCr422, YCbCr420 | RGB, YCbCr444, YCbCr422, YCbCr420 | RGB, YCbCr444, YCbCr422, YCbCr420 | RGB, YCbCr444, YCbCr420 | RGB, YCbCr444, YCbCr422, YCbCr420 | RGB, YCbCr444, YCbCr422, YCbCr420 | RGB, YCbCr444, YCbCr422, YCbCr420 | RGB, YCbCr444, YCbCr422, YCbCr420 |
是否支持 10bit 色深 | Y | N | Y | Y | Y | Y | Y | Y | Y |
支持 HDMI 协议版本 | HDMI 2.0 | HDMI 2.0 | HDMI 2.0 | HDMI 2.0 | HDMI 2.0 | HDMI 2.0 | HDMI 2.0 | HDMI 2.1 | HDMI 2.1 |
DRM: DRM 全称是 Direct Rendering Manager 是 DRI ( Direct Rendering Infrastructure ) 框架的一个 组件。LINUX 4.4 及其以后的内核采用 DRM 框架, HDMI 驱动的路径为:
kernel/drivers/gpu/drm/rockchip/dw_hdmi-Rockchip.c
kernel/drivers/gpu/drm/rockchip/inno_hdmi.c
kernel/drivers/gpu/drm/bridge/synopsys/
2. DRM 框架 HDMI 介绍
2.1 HDMI 软件功能配置
2.1.1 使能 HDMI
打开 HDMI 需要添加:
&hdmi {
status = "okay";
};
2.1.2 绑定 VOP
在 Rockchip 的各个平台中,各种显示接口(HDMI、DP、CVBS 等)输出的图像数据来自 VOP:
如果平台存在两个 VOP(RK3288、RK3399):VOPB(支持 4K)、VOPL(只支持 2K),两个 VOP 可以分别与两个显示接口绑定(一个显示接口只能和一个 VOP 绑定),且可以相互交换:
- 当 DTS 中显示设备节点打开时,显示接口对应 VOPB 和 VOPL 的 ports 都会打开,所以需要关闭用不到的那个 VOP 对应的 port。
例如,HDMI 绑定到 VOPB 需要添加:
&hdmi_in_vopl {
status = "disabled";
};
反之,若绑定到 VOPL 则添加:
&hdmi_in_vopb {
status = "disabled";
};
如果平台只有一个 VOP,则不需要该步骤。
VOP2 及其后版本,一个平台不再有多个 VOP。取而代之的是只有一个 VOP,而 VOP 中有多个 VP(Video Port)输出。
-
RK356X VOP 与 HDMI 的通路:
- HDMI 可以绑定在 VP0 或 VP1 上,建议绑定 VP0 可以支持 4K 输出:
&hdmi_in_vp0 {
status = "okay";
};
&hdmi_in_vp1 {
status = "disabled";
};
- HDMI 可以绑定在 VP0 或 VP1 上,建议绑定 VP0 可以支持 4K 输出:
-
RK3588 VOP 与 HDMI 的通路:
- RK3588 有两个 HDMITX,两者在性能上完全相同,分别可以绑定在 VP0/1/2。
- 如果最高只需要输出 4K 分辨率,建议 HDMI0/1 分别绑定在 VP0/1:
&hdmi0_in_vp0 {
status = "okay";
};
&hdmi0_in_vp1 {
status = "disabled";
};
&hdmi0_in_vp2 {
status = "disabled";
};
&hdmi1_in_vp1 {
status = "okay";
};
&hdmi1_in_vp0 {
status = "disabled";
};
&hdmi1_in_vp2 {
status = "disabled";
};
-
RK3588 平台如果需要输出 8K 分辨率,必须占用 VP0 和 VP1 两个 port 进行拼接。在 DTS 中,必须将输出 8K 的 HDMI 绑定在 VP0 上,以 HDMI0 为例:
&hdmi0_in_vp0 {
status = "okay";
};
&hdmi0_in_vp1 {
status = "disabled";
};
&hdmi0_in_vp2 {
status = "disabled";
};同时,还需要将 VOP ACLK 设置为 800M,详见 3.1.4。
-
RK3588 HDMI 与 eDP 共用 COMBPHY,以 HDMI0 和 eDP0 为例,DTS 中
hdptxphy_hdmi0
为 HDMI PHY 节点,hdptxphy0
为 eDP PHY 节点:hdptxphy0: phy@fed60000 {
compatible = "rockchip,rk3588-hdptx-phy";
reg = <0x0 0xfed60000 0x0 0x2000>;
clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>;
clock-names = "ref", "apb";
resets = <&cru SRST_P_HDPTX0>, <&cru SRST_HDPTX0_INIT>,
<&cru SRST_HDPTX0_CMN>, <&cru SRST_HDPTX0_LANE>;
reset-names = "apb", "init", "cmn", "lane";
rockchip,grf = <&hdptxphy0_grf>;
#phy-cells = <0>;
status = "disabled";
};
hdptxphy_hdmi0: hdmiphy@fed60000 {
compatible = "rockchip,rk3588-hdptx-phy-hdmi";
reg = <0x0 0xfed60000 0x0 0x2000>;
clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>;
clock-names = "ref", "apb";
clock-output-names = "clk_hdmiphy_pixel0";
#clock-cells = <0>;
resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>,
<&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>,
<&cru SRST_HDPTX0_LANE>, <&cru SRST_HDPTX0_ROPLL>,
<&cru SRST_HDPTX0_LCPLL>;
reset-names = "phy", "apb", "init", "cmn", "lane", "ropll",
"lcpll";
rockchip,grf = <&hdptxphy0_grf>;
#phy-cells = <0>;
status = "disabled";
};
所以当使用 HDMI 的时候必须关闭对应的 eDP 和 eDP PHY。以 HDMI0 为例:
&hdmi0 {
status = "okay";
};
&hdptxphy_hdmi0 {
status = "okay";
};
&edp0 {
status = "disabled";
};
&hdptxphy0 {
status = "disabled";
};
2.1.3 打开开机 logo
如果 U-Boot logo 未开启,那么 kernel 阶段也无法显示开机 logo,只能等到系统启动后才能看到应用显示的图像。在 DTS 中将 route_hdmi
使能即可打开 U-Boot logo 支持:
&route_hdmi {
status = "okay";
};
在双 VOP 的平台,需要注意代码中的 connect
指定的 VOP 必须与 HDMI 绑定的 VOP 一致(详见 3.1.2),否则可能出现花屏等问题。
route_hdmi: route-hdmi {
status = "disabled";
logo,uboot = "logo.bmp";
logo,kernel = "logo_kernel.bmp";
logo,mode = "center";
charge_logo,mode = "center";
connect = <&vopb_out_hdmi>;
};
2.1.4 VOP dclk 绑定 PLL
HDMI 绑定的 VOP/VP dclk,需要指定对应的 PLL 作为时钟源。在 RK 的平台中,RK322X/RK3328/RK3528 HDMI 都与固定的 VOP/VP 绑定,且固定使用 HDMI PHY PLL 作为 dclk 时钟源,无需配置。
2.1.4.1 RK3288 绑定 PLL
RK3288 VOPB/VOPL dclk 可以挂载到 GPLL/CPLL。由于这两个 PLL 都不能小数分频,所以 RK3288 的 HDMI 只能输出 594M 整数分频的标准分辨率(如 4K60/1080P60/720P60)。举例 VOPB dclk 挂载到 GPLL,VOPL dclk 挂载到 CPLL 如下:
&vopb {
assigned-clocks = <&cru DCLK_VOP0>;
assigned-clock-parents = <&cru PLL_GPLL>;
};
&vopl {
assigned-clocks = <&cru DCLK_VOP1>;
assigned-clock-parents = <&cru PLL_CPLL>;
};
2.1.4.2 RK3399 绑定 PLL
RK3399 的 HDMI 所绑定的 VOP dclk 需要挂载到 VPLL 上,若是双显则需要将另一个 VOP dclk 挂到 CPLL,这样可以分出任意频率的 dclk,实现双显任意分辨率的支持。如当 HDMI 绑定到 VOPB 时配置:
&vopb {
assigned-clocks = <&cru DCLK_VOP0_DIV>;
assigned-clock-parents = <&cru PLL_VPLL>;
};
&vopl {
assigned-clocks = <&cru DCLK_VOP1_DIV>;
assigned-clock-parents = <&cru PLL_CPLL>;
};
当 HDMI 绑定到 VOPL 时配置:
&vopb {
assigned-clocks = <&cru DCLK_VOP0_DIV>;
assigned-clock-parents = <&cru PLL_CPLL>;
};
&vopl {
assigned-clocks = <&cru DCLK_VOP1_DIV>;
assigned-clock-parents = <&cru PLL_VPLL>;
};
2.1.4.3 RK356X 绑定 PLL
RK356X HDMI 所绑定的 VP dclk 必须需要挂载到 HPLL 上,举例 VP0 dclk:
&vop {
assigned-clocks = <&cru DCLK_VOP0>;
assigned-clock-parents = <&pmucru PLL_HPLL>;
};
2.1.4.4 RK3588/RK3576 绑定 PLL
RK3588 如果需要输出 4K60 以上的分辨率,需要将 VOP ACLK 设置为 800MHz:
&vop {
assigned-clocks = <&cru ACLK_VOP>;
assigned-clock-rates = <800000000>;
status = "okay";
};
RK3588 HDMI 0/1 可以绑定 VP 0/1/2,详见 2.1.2。这三个 VP dclk 都可以挂载到 GPLL/HDMI0 PHY PLL/HDMI 1 PHY PLL/V0PLL。
具体的分配策略和相关限制可以参考《Rockchip_Developer_Guide_DRM_Display_Driver_CN.pdf》中的 10.11 章节。
RK3588/RK3576 如果要支持非标准分辨率,需要指定 PHY PLL 作为 VOP dclk 时钟源。
RK3588 DTS 配置如下:
&display_subsystem {
clocks = <&hdptxphy_hdmi_clk0>, <&hdptxphy_hdmi_clk1>;
clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll";
};
&hdptxphy_hdmi_clk0 {
status = "okay";
};
&hdptxphy_hdmi_clk1 {
status = "okay";
};
RK3576 DTS 配置如下:
&display_subsystem {
clocks = <&hdptxphy_hdmi>;
clock-names = "hdmi0_phy_pll";
};