DisplayPort
前言
本文主要介绍 Rockchip 平台 DP 接口的使用与调试方法。
产品版本
芯片名称 | 内核版本 |
---|---|
RK3576 | LINUX Kernel 6.1 |
RK3588 | LINUX Kernel 5.10/6.1 |
读者对象
本文档(本指南)主要适用于以下工程师:
技术支持工程师
软件开发工程师
1. Rockchip 平台 DisplayPort 简介
1.1 功能特性
Rochchip RK3576 和 RK3588 DP 接口功能参数如下表格:
功能 | RK3576 | RK3588 |
---|---|---|
Version | 1.4a | 1.4a |
SST | Support | Support |
MST | Support | Not support |
DSC | Not support | Not support |
Max resolution | 4K@120Hz | 8K@30Hz |
Main-Link lanes | 1/2/4 lanes | 1/2/4 lanes |
Main-Link rate | 8.1/5.4/2.7/1.62 Gbps/lane | 8.1/5.4/2.7/1.62 Gbps/lane |
AUX_CH | 1M | 1M |
Color Format | RGB/YUV444/YUV422/YUV420 | RGB/YUV444/YUV422/YUV420 |
Color Depth | 8/10 bit(6bit just for RGB) | 8/10 bit(6bit just for RGB) |
Display Split Mode | Support | Support |
HDCP | HDCP2.2/HDCP1.3 | HDCP2.2/HDCP1.3 |
Type-C support | DP Alternate Mode | DP Alternate Mode |
I2S | Support | Support |
SPDIF | Support | Support |
HDR | Support | Support |
RK3576 只有一个物理 DP 接口,但在 MST 模式下内部能接受3 路显示数据流(为区分物理接口,用Stream-0, Stream-1, Stream-2 表示)。每路的最大输出能力如下:
DP Stream Channel | max width | max height | max pixel clock |
---|---|---|---|
Stream-0 | 4096 | 2160 | 1188MHz |
Stream-1 | 2560 | 1440 | 300MHz |
Stream-2 | 1920 | 1080 | 150MHz |
1.2 DP 与 VOP 连接关系
RK3576 的 VOP 有三个 Video Port, 一个 DP 控制器。在 MST 模式下,DP 控制器支持从 VOP 最多接收3 路的显示数据流。Stream-0/1/2 均可接收来自 Video Port0/1/2的显示数据。其中, 当工作在 SST 模式下时,只能使用 DP 控制器中的 Stream-0。 工作在 MST 模式下时, Stream-0/1/2都可以使用。
RK3588 的 VOP 有四个 Video Port, 两个 DP 控制器,其中只有 Video Port 0/1/2 可以输出到 DP0/1, 如下图。
如 RK3588 两个 DP 接口不支持 MST 模式,并且内部只能接收一路显示数据 Stream-0。对于这种不支持 MST 的平台,默认 Video Port 输出输出到 DP 接口的 Stream-0。
1.3 DP 输出
根据应用场景的不同,可以设计不同的 DP 输出方式:Type-C 接口输出、DP 标准接口输出、通过其他转接芯片转接输出。
RK3576 在 MST 模式下,最多可以接 3 台显示器,可以通过 MST 显示器通过菊花链的方式串联,如下:
通过菊花链连接的显示器,只有最后一台显示器可以接 SST 显示器,其他的需要 MST 显示器。
另一种方式,可以通过 MST HUB 进行连接,如下:
通过 MST HUB 连接时, DP 显示器可以是 SST 显示器,也可以是 MST 显示器。
1.4 代码路径
U-Boot 驱动代码:
drivers/video/drm/dw-dp.c
drivers/phy/phy-rockchip-usbdp.c
Kernel 驱动代码:
drivers/gpu/drm/rockchip/dw-dp.c
drivers/phy/rockchip/phy-rockchip-usbdp.c
RK3576 参考 DTS 配置:
arch/arm64/boot/dts/rockchip/rk3576-evb1.dtsi
arch/arm64/boot/dts/rockchip/rk3576-test2.dtsi
RK3588 参考 DTS 配置:
arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi
arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi
arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi
arch/arm64/boot/dts/rockchip/rk3588-nvr-demo.dtsi
1.5 驱动加载
通过下面的log,判断驱动加载是否完成:
RK3576:
[1.991964] rockchip-drm display-subsystem: bound 27e40000.dp (ops 0xffffffc0094a1570) //DP 驱动加载完成
RK3588:
[2.472282] rockchip-drm display-subsystem: bound fde50000.dp (ops dw_dp_component_ops) //DP0 驱动加载完成
[2.472319] rockchip-drm display-subsystem: bound fde60000.dp (ops dw_dp_component_ops) //DP1 驱动加载完成
2. 功能配置
对于 DP 接口,支持 MST 和 不支持 MST 的平台 DTS 节点的基础配置存在差异。
不支持 MST 的平台,如 RK3588, 一个 DP 控制器只支持一路 DP 输出, 只需定义一个 ports 子节点描述这路 DP 可以支持的显示通路即可,DP 节点描述如下:
dp0: dp@fde50000 {
compatible = "rockchip,rk3588-dp";
...
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
dp0_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_dp0>;
status = "disabled";
};
dp0_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_dp0>;
status = "disabled";
};
dp0_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_dp0>;
status = "disabled";
};
};
...
};
};
对于支持 MST的平台,如 RK3576,一个 DP 控制器要支持 3 路显示数据流输出,一个 ports 节点无法描述多个 DP 通道的显示通路,需要通过多个子节点描述, 配置如下:
dp: dp@27e40000 {
compatible = "rockchip,rk3576-dp";
...
dp0: dp0 {
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
dp0_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_dp0>;
status = "disabled";
};
dp0_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_dp0>;
status = "disabled";
};
dp0_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_dp0>;
status = "disabled";
};
};
};
};
dp1: dp1 {
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
dp1_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_dp1>;
status = "disabled";
};
dp1_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_dp1>;
status = "disabled";
};
dp1_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_dp1>;
status = "disabled";
};
};
};
};
dp2: dp2 {
status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
dp2_in_vp0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vp0_out_dp2>;
status = "disabled";
};
dp2_in_vp1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vp1_out_dp2>;
status = "disabled";
};
dp2_in_vp2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vp2_out_dp2>;
status = "disabled";
};
};
};
};
};
上述的 dp0/1/2 子节点,分别描述 DP 控制器中 Stream-0/1/2 可以支持的显示通路。
对比 DTS 的配置,支持 MST 的平台上多了一层 DP 通道的子节点。
2.1 使能 DP
DP 和 USB3.0 共用 PHY,PHY lane 的配置根据接口的不同有两种方式,Type-C 模式和非 Type-C 模式。
2.1.1 DP Alt Mode(Type-C)
根据 DisplayPort Alt Mode 协议,通过 PD (Power Delivery) 的状态机和显示器进行通信,进行 lane 的映射和 HPD 信息的传递。通过 PD 协议进入 DP Mode 并通过 attention 指令传递 HPD 信息的流程主要如下图所示。
不支持 MST 的平台,如 RK3588, 配置如下:
&dp0 {
status = "okay";
};
&dp0_in_vp2 {
status = "okay";
};
在上面的配置中,使能了 DP0 接口,并把 DP0 绑定到 VOP 的 Video Port2,这只是一种参考配置,实际使用过程中,可以根据实际的需求,使能 DP0 或 DP1, 并把 DP0 或 DP1 绑定到期望的 Video Port(0/1/2) 上。
支持 MST 的平台,如 RK3576, 配置如下:
&dp {
status = "okay";
};
&dp0 {
status = "okay";
};
&dp0_in_vp2 {
status = "okay";
};
可以看到,支持 MST 的平台,需要使能 DP 设备节点,要开启的 DP Stream 通道,以及该通道要绑定的 VOP 上的 Video Port。上述的配置中,即使了 DP 接口的 Stream-0,并把 Stream-0 绑定到 VOP 的Video Port2。
需要注意的是,支持 MST 的平台,因为 SST 模式下一定要使用 DP Steam-0, 所以 dp0 节点是一定要使能的。dp1 和 dp2 根据使用情况进行配置。
PHY 配置如下,支持 MST 和 不支持 MST 的平台无差异,参考如下 RK3588 usbdp phy0 的配置:
&usbdp_phy0 {
status = "okay";
orientation-switch;
/* DP related config */
svid = <0xff01>;
sbu1-dc-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>;
sbu2-dc-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
/* DP related config */
port {
#address-cells = <1>;
#size-cells = <0>;
usbdp_phy0_orientation_switch: endpoint@0 {
reg = <0>;
remote-endpoint = <&usbc0_orien_sw>;
};
/* DP related config */
usbdp_phy0_dp_altmode_mux: endpoint@1 {
reg = <1>;
remote-endpoint = <&dp_altmode_mux>;
};
/* DP related config */
};
};
sbu1-dc-gpios 和 sbu2-dc-gpios :
Type-C 的 SBU1 和 SBU2 引脚是和 DP 的 AUX_CH 复用的,在 Type-C 正插时, AUX_CH_P 复用SBU1,AUX_CH_N 复用 SUB2。在 Type-C 反插时,AUX_CH_P 复用 SBU2, AUX_CH_N 复用 SBU1。 根据 DP 协议要求,AUX_CH_P 需要配置为下拉状态,AUX_CH_N 需要配置成上拉状态。Type-C 不同的插入状态(正插和反插) AUX_CH_N 和 AUX_CH_P 的复用配置是不一样的,在 RK 方案上,是通过两个GPIO 来分别控制 SBU1 和 SBU2 的上下拉状态,即 dts 中的 sbu1-dc-gpios 和 sbu2-dc -gpios。因此,在配置 PHY 时,需要配置 sbu1-dc-gpios 和 sbu2-dc-gpios (实际配置这两个 GPIO 的时候要参照硬件设计的原理图,例如下图的 TYPEC0_SBU1_DC 和 TYPEC0_SBU2_DC), PHY 驱动会根据当前的Type-C 正反插状态去调整 GPIO 输出的电平。
svid :
对 DP 来说是固定值 0xff01。
Type-C 接口需要通过 Type-C 的 CC 检测和 PD 协商来配置 lane 和 HPD 的状态, 所以还需要配置 PD芯片:
&i2c2 {
status = "okay";
usbc0: fusb302@22 {
compatible = "fcs,fusb302";
reg = <0x22>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PB4 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&usbc0_int>;
vbus-supply = <&vbus5v0_typec>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
usbc0_role_sw: endpoint@0 {
remote-endpoint = <&dwc3_0_role_switch>;
};
};
};
usb_con: connector {
compatible = "usb-c-connector";
label = "USB-C";
data-role = "dual";
power-role = "dual";
try-power-role = "sink";
op-sink-microwatt = <1000000>;
sink-pdos =
<PDO_FIXED(5000, 1000, PDO_FIXED_USB_COMM)>;
source-pdos =
<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
/* DP related config */
altmodes {
#address-cells = <1>;
#size-cells = <0>;
altmode@0 {
reg = <0>;
svid = <0xff01>;
vdo = <0xffffffff>;
};
};
/* DP related config */
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
usbc0_orien_sw: endpoint {
remote-endpoint = <&usbdp_phy0_orientation_switch>;
};
};
/* DP related config */
port@1 {
reg = <1>;
dp_altmode_mux: endpoint {
remote-endpoint = <&usbdp_phy0_dp_altmode_mux>;
};
};
/* DP related config */
};
};
};
};
altmode@0 节点中, svid 固定配置为 0xff01, vdo 固定配置为 0xffffffff。
Note: 当前支持的 PD 芯片为 fusb302, hub311。fusb302 对应的驱动为/drivers/usb/typec/tcpm/fusb302.c, hub311 对应的驱动为/drivers/usb/typec/tcpm/tcpci_husb311.c。
2.1.2 DP Legacy Mode
非 Type-C 接口输出,无论是 DP 接口,还是通过其他的转接芯片输出,配置流程基本一致,并且都需要配置 HPD Pin。 在实际分配 IO 引脚的时候,可以使用DP_HPD 专用引脚, 这种情况按 IOMUX 进行配置,还可以使用普通的 GPIO 进行检测。
对于不支持 MST 的平台,如 RK3588, 使用 DP_HPD Pin 的时候配置如下:
&dp1 {
pinctrl-0 = <&dp1m2_pins>;
pinctrl-names = "default";
status = "okay";
};
&dp1_in_vp2 {
status = "okay";
};
使用普通 GPIO 作 HPD 检测的时候配置如下:
&dp1 {
pinctrl-names = "default";
pinctrl-0 = <&dp1_hpd>;
hpd-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
status = "okay";
};
&dp1_in_vp2 {
status = "okay";
};
&pinctrl {
dp {
dp1_hpd: dp1-hpd {
rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
};
对于支持 MST 的平台,比如RK3576, 使用 DP_HPD Pin 的时候配置如下:
&dp {
pinctrl-0 = <&dp1m2_pins>;
pinctrl-names = "default";
status = "okay";
};
&dp0 {
status = "okay";
};
&dp0_in_vp2 {
status = "okay";
};
使用普通 GPIO 作 HPD 检测的时候配置如下:
&dp {
pinctrl-names = "default";
pinctrl-0 = <&dp_hpd>;
hpd-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
status = "okay";
};
&dp0 {
status = "okay";
};
&dp0_in_vp2 {
status = "okay";
};
&pinctrl {
dp {
dp_hpd: dp-hpd {
rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
};
上述支持 MST 平台和 不支持 MST 平台的配置中,HPD 的配置是属于整个 DP 接口的配置,均配置在设备节点下。
DP 和 USB 3.0 共用 PHY,当 DP 为 非 Type-C 接口输出时,就需要指定 lane 配置给 DP 使用以及对应的 lane 序号,这部分内容在 DTS 中指定。对于 DP PHY lane 的配置,可以配置成 2 lane 模式或 4 lane 模式。
PHY lane 接口的物理编号如下图所示:
对于 DP 配置 4 lane, dtsi 配置属性如下:
rockchip,dp-lane-mux = <x x x x>;
对于 DP 配置 2 lane, dtsi 配置属性如下:
rockchip,dp-lane-mux = <x x>;
其中,索引为 DP 的 lane, 值为 PHY 的 lane。 无论 2 lane 还是 4 lane 配置,硬件设计时一般使用如下的 OPTION1 或 OPTION2 两种中的一种。
对于 DP 4 lane 的 OPTION1 映射关系如下:
其中 DP lane 为 DP 的 lane 的序号。 dts 的配置如下:
&usbdp_phy1 {
rockchip,dp-lane-mux = <0 1 2 3>;
status = "okay";
};
对于 DP 4 lane 的 OPTION2 映射关系如下:
其中 DP lane 为 DP 的 lane 的序号。 dts 的配置如下:
&usbdp_phy1 {
rockchip,dp-lane-mux = <2 3 0 1>;
status = "okay";
};