RK3588 HDMI转DVI黑屏问题排查与解决

前言

最近在调试 RK3588 平台的显示输出时遇到个头疼的问题:用 HDMI 转 DVI 转接器连显示器,冷启动就黑屏,但拔掉 HDMI 线重新插上就好了。HDMI 直连显示器完全没问题。折腾了好几天,试了各种方案,最后发现居然只要改一行设备树就搞定了。记录一下排查过程,希望能帮到遇到类似问题的朋友。

问题现象

  • 硬件环境: RK3588 开发板,HDMI0 和 HDMI1 两个输出口
  • 问题表现 :
    • HDMI 转 DVI 转接器连接显示器,冷启动黑屏
    • 拔掉 HDMI 线重新插上,显示正常
    • HDMI 直连显示器,一切正常
  • 影响范围: HDMI0 和 HDMI1 都有这个问题

排查过程

第一步:抓日志分析

先看启动日志,发现 HPD (热插拔检测) 信号是正常的:

复制代码
[    0.xxx] rockchip-hdmi fde80000.hdmi: HDMI0: HPD detected

但是 EDID 读取有问题,经常读不到或者读取失败。这就奇怪了,HPD 都检测到了,为啥 EDID 读不出来?

第二步:对比 HDMI 直连和 DVI 转接器

用示波器测了一下时序,发现问题了:

  • HDMI 直连: HPD 信号和 I2C (DDC) 几乎同时就绪,300ms 内搞定
  • DVI 转接器: HPD 信号 300ms 就来了,但 I2C 总线要 1-2 秒才稳定

这就是问题所在!系统启动时检测显示器,HPD 有信号就去读 EDID,但这时候 DVI 转接器的 I2C 还没初始化好,读不到 EDID,系统就认为没显示器。

第三步:尝试驱动层修改(弯路)

一开始想在驱动里加延时重试机制,试了好几个方案:

  1. HPD 多次检测 : 改 dw_hdmi_rk3588_read_hpd() 函数,循环检测 10 次,每次间隔 100ms

    • 结果:没用,HPD 本来就是好的
  2. 延迟 reprobe: 启动 1 秒后再触发一次热插拔事件,强制重新读 EDID

    • 结果:有点效果,但不稳定
  3. 强制路由: 强制 HDMI0 只能用 vp0,防止系统乱选

    • 结果:治标不治本

折腾了好几天,驱动改得乱七八糟,问题还是时好时坏。

第四步:回到设备树(正解)

冷静下来重新看了一遍设备树配置,发现了关键点:

父设备树 (rk3588-nvr-demo.dtsi):

复制代码
&route_hdmi0 {
    status = "okay";
    force-output;  // 注意这个属性
    connect = <&vp2_out_hdmi0>;
};

子设备树 (rk3588-nvr-demo-v10-android-a5.dts):

复制代码
&route_hdmi0 {
    status = "okay";
    connect = <&vp0_out_hdmi0>;
    /delete-property/ force-output;  // 把父设备树的 force-output 删了
    /delete-node/ force_timing;
};

看到 /delete-property/ force-output 这行,突然想起来,force-output 是干啥的?

翻了一下 rockchip_drm_logo.c 的代码:

复制代码
if (force_output)
    connector->force = DRM_FORCE_ON;

if (connector->force) {
    if (connector->force == DRM_FORCE_ON ||
        connector->force == DRM_FORCE_ON_DIGITAL)
        connector->status = connector_status_connected;  // 强制标记为已连接
    ...
}

原来 force-output 会强制把 connector 标记为已连接状态,跳过 HPD 检测!这不就是我们需要的吗?

而且看代码,启动完成后会自动清除这个标记:

复制代码
list_for_each_entry_safe(set, tmp, &mode_set_list, head) {
    if (set->force_output)
        set->sub_dev->connector->force = DRM_FORCE_UNSPECIFIED;  // 恢复正常
    ...
}

也就是说,force-output 只在启动时生效,启动完成后会自动恢复,不影响热插拔!

解决方案

只需要删除设备树中的一行代码!

修改文件

android/kernel-5.10/arch/arm64/boot/dts/rockchip/rk3588-nvr-demo-v10-android-a5.dts

修改前

复制代码
&route_hdmi0 {
    status = "okay";
    connect = <&vp0_out_hdmi0>;
    /delete-property/ force-output;  // 删掉这行
    /delete-node/ force_timing;
};

&route_hdmi1 {
    status = "disabled";
    connect = <&vp1_out_hdmi1>;
    /delete-property/ force-output;  // 删掉这行
    /delete-node/ force_timing;
};

修改后

复制代码
&route_hdmi0 {
    status = "okay";
    connect = <&vp0_out_hdmi0>;
    /delete-node/ force_timing;
};

&route_hdmi1 {
    status = "disabled";
    connect = <&vp1_out_hdmi1>;
    /delete-node/ force_timing;
};

就这么简单,把 /delete-property/ force-output; 这行删掉,让子设备树继承父设备树的 force-output 属性。

编译测试

复制代码
cd android/kernel-5.10
make ARCH=arm64 rockchip_defconfig
make ARCH=arm64 dtbs -j8

烧录测试,完美解决!

原理说明

为什么有效?

  1. 启动阶段:

    • force-output 属性生效
    • 系统强制将 HDMI 标记为"已连接"
    • 不管 EDID 读没读到,都会初始化显示输出
    • DVI 转接器的 I2C 慢慢初始化,系统会等它
  2. 启动完成后:

    • DRM 框架自动清除 force-output 标记
    • 恢复正常的 HPD 检测机制
    • 热插拔功能完全正常

为什么之前删掉了 force-output?

看了一下 git 历史,之前删掉 force-output 是为了支持多屏输出,避免启动时强制激活所有输出。但这样就导致 DVI 转接器的时序问题暴露出来了。

其实 force-output 只在启动时生效,启动完成后会自动清除,并不影响多屏切换。所以保留它是没问题的。

测试结果

  • ✅ HDMI0 + DVI 转接器:冷启动正常
  • ✅ HDMI1 + DVI 转接器:冷启动正常(通过 dpms 启用后)
  • ✅ HDMI0 直连:正常
  • ✅ HDMI1 直连:正常
  • ✅ 热插拔:完全正常
  • ✅ 多屏切换:正常

经验总结

  1. 遇到显示问题,先看设备树

    • 很多显示相关的配置都在设备树里
    • 驱动层的修改往往治标不治本
  2. 理解硬件时序差异

    • HDMI 和 DVI 虽然兼容,但时序特性不同
    • DVI 转接器的 I2C 初始化比 HPD 慢很多
  3. 善用现有机制

    • force-output 就是为了解决这类问题设计的
    • 不要一上来就改驱动,先看看有没有现成的配置项
  4. 测试要全面

    • 不仅要测 DVI 转接器,还要测 HDMI 直连
    • 不仅要测冷启动,还要测热插拔
    • 不仅要测单屏,还要测多屏切换

参考资料

  • Rockchip DRM 驱动文档
  • Linux DRM 子系统文档
  • RK3588 TRM (Technical Reference Manual)

写在最后

这个问题前前后后折腾了好几天,改了一堆驱动代码,最后发现只要删一行设备树就搞定了。有时候问题的解决方案往往比想象中简单,关键是要理解底层原理,找对方向。

希望这篇文章能帮到遇到类似问题的朋友。如果有疑问或者更好的解决方案,欢迎在评论区交流!


环境信息:

  • 平台: RK3588
  • 内核: Linux 5.10
  • Android 版本: Android 12
  • 问题芯片: HDMI 转 DVI 转接器

关键字: RK3588, HDMI, DVI, 黑屏, force-output, 设备树, DTS

相关推荐
松涛和鸣9 小时前
75、 IMX6ULL LM75温度传感器I2C驱动开发
java·linux·数据库·驱动开发·python
济61712 小时前
I.MX6U 开发板网络环境搭建---- TFTP 环境搭建-- Ubuntu20.04
linux·网络·驱动开发
松涛和鸣1 天前
74、IMX6ULL按键驱动开发:Platform总线+中断顶底半部+阻塞式读取
linux·服务器·网络·数据库·驱动开发
The️1 天前
Linux驱动开发之Makefile
linux·驱动开发·mcu·ubuntu
嵌入式-老费1 天前
Linux Camera驱动开发(IPCam Soc驱动开发特点)
驱动开发
dump linux1 天前
设备树子系统与驱动开发入门
linux·驱动开发·嵌入式硬件
探路者继续奋斗1 天前
IDD意图驱动开发之系统规格说明书
驱动开发·规格说明书·意图驱动开发·idd·ai开发模式
hexie6666661 天前
嵌入式Linux 优化开机启动时间
linux·驱动开发
chenchen000000001 天前
国产显示芯势力新篇章:内置DDR+四核A35!MY-SSD2351-MINI开发板深度评测
驱动开发·嵌入式硬件