RK3576 开机黑屏只有背光?从 dmesg 到 DTS 的显示排查实战

电子说

1.4w人已加入

描述

适用场景:拿到 RK3576 板子,系统跑起来了,UART 能敲命令,但屏幕不亮 —— 要么黑漆漆一片,要么只有背光没内容,要么副屏死活不出来。

先搞清显示链路有几段

RK3576 的显示链路从上到下分四段,哪段断了都会黑屏

SurfaceFlinger / Android 应用层 → 图层没送过来,屏幕空转

HWComposer (HWC) → Plane 分错了,图层堆不上去

DRM/KMS (CRTC + Encoder + Connector) → 模式没设对,显示器不认

VOP2 / VOPL (硬件合成 + 时序) → 时钟没开、MMU 报错、寄存器没配

排查的第一件事:先确认问题是硬件没输出,还是软件层把画面吞了。

 

# DRM 整体状态——所有 CRTC、Plane、Connector 一目了然cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/state# 正常:每个 CRTC 有 enable=1,connector 有 connected 状态# 异常:全是 disabled,或者 connector 显示 disconnected# 内核 dmesg 先扫一遍dmesg | grep -iE "vop|drm|hdmi|edp|dsi"

 

如果state 显示 enabled 但屏幕不亮,问题在物理层(HDMI/eDP PHY)。如果 state 本身就是 disabled,往下走。

第一步:dmesg 先过一遍

显示初始化失败,dmesg 一定会留痕迹。重点关注这三类日志:

VOP2 (Main VOP) 初始化

 

#  正常[    1.224567] rockchip-vop2 fdd90000.vop: Adding to iommu group 0[    1.224600] rockchip-vop2 fdd90000.vop: [drm:vop2_bind] vop2 bind success, vps:3#  时钟没拿到[    1.224567] rockchip-vop2 fdd90000.vop: failed to get aclk_vop[    1.224568] rockchip-vop2 fdd90000.vop: vop2_bind failed: -ENOENT#  寄存器资源被占[    1.224567] rockchip-vop2 fdd90000.vop: failed to get regs[    1.224568] rockchip-vop2 fdd90000.vop: vop2_bind failed: -EBUSY

 

VOPL (Lite VOP) 初始化

 

#  正常[    1.225000] rockchip-vop fdd80000.vop: Adding to iommu group 0#  电源域或时钟没就绪[    1.225000] rockchip-vop fdd80000.vop: failed to get hclk_vop[    1.225001] rockchip-vop fdd80000.vop: vop_bind failed: -EPROBE_DEFER

 

DRM component bind — 最关键的一步

VOP 是 DRM 的一个 component,所有 component 必须全部就绪,DRM 主驱动才会完成绑定:

 

#  正常:所有 component 都 bound 上了[    1.230000] rockchip-drm display-subsystem: bound fdd90000.vop (ops vop2_component_ops)[    1.230100] rockchip-drm display-subsystem: bound fdd80000.vop (ops vop_component_ops)[    1.230200] rockchip-drm display-subsystem: bound fdd60000.hdmi (ops dw_hdmi_rockchip_ops)[    1.235000] rockchip-drm display-subsystem: [drm] fb0: rockchipdrmfb frame buffer device#  超时,component 没到齐[    5.000000] rockchip-drm display-subsystem: failed to bind all components[    5.000100] rockchip-drm display-subsystem: [drm] *ERROR* failed to load rockchip drm driver.#  其中一个 component bind 失败[    1.230000] rockchip-drm display-subsystem: failed to bind fdd80000.vop: -ENODEV

 

逐行解读

① Adding to iommu group 0 → VOP 已加入 IOMMU 组。如果这行都没有,说明设备根本就没 probe—— 去 DTS 里看 status 是不是 "okay"。

② failed to get xxx → 时钟或寄存器缺失。最常见的坑是 DTS 的 clock-names 写错了:

 

cat /sys/kernel/debug/clk/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSclk_summary | grep vop# 正常:aclk_vop、hclk_vop、dclk_vp0 的 enable count 应该 >= 1# 异常:missing 某些时钟,或 enable count 全是 0

 

③ failed to bind all components → 5 秒超时。DRM 主驱动最多等 5 秒让所有 component 就绪。有任何一个 component 返回 -EPROBE_DEFER,超时后就报这个。

 

# 看哪些 component 没 bound 上dmesg | grep "component"

 

④ fb0: rockchipdrmfb frame buffer device → 这行出现说明 DRM 初始化基本完成。如果没有这行,显示子系统根本没启动成功。

第二步:VP 路由配错了

dmesg 没有报错,VOP 初始化看着正常,但屏幕还是不亮。这种情况八成是 VP 路由配错了

RK3576 有三个 VP(Video Port),各有各的能力约束:

VP 最大分辨率 DCLK 上限 能接谁
VP0 4096x4096 1.2 GHz HDMI/DP/eDP(主屏,功能最全)
VP1 2560x2560 300 MHz eDP/DP/MIPI DSI
VP2 1920x1920 150 MHz RGB/BT1120(纯基础功能)

路由定义在 SoC DTSI (rk3576.dtsi) 的 display-subsystem 节点里:

 

display_subsystem: display-subsystem {    ports = <&vop_out>, <&vopl_out>;    route {        route_hdmi: route-hdmi {            status = "disabled";            connect = <&vp0_out_hdmi>;    // HDMI 默认连 VP0        };        route_edp: route-edp {            status = "disabled";            connect = <&vp1_out_edp>;     // eDP 默认连 VP1        };        route_dsi: route-dsi {            status = "disabled";            connect = <&vp1_out_dsi>;     // MIPI DSI 也连 VP1        };        route_rgb: route-rgb {            status = "disabled";            connect = <&vp2_out_rgb>;     // RGB 连 VP2        };    };};

 

 

// 真正的路由在 board DTS 中开启。比如 HDMI 主输出 + eDP 副屏:&route_hdmi {    status = "okay";    connect = <&vp0_out_hdmi>; // VP0 → HDMI};&route_edp {    status = "okay";    connect = <&vp1_out_edp>;  // VP1 → eDP};

 

最容易出错的三种情况:

① 开了 route 但没开对应的显示接口:route_hdmi 配了 okay,但 &hdmi 节点还是status = "disabled"。驱动不会报错,它只是跳过初始化。

 

cat /sys/firmware/devicetree/base/hdmi@27da0000/status# 应该输出: okay

 

② VP 能力不够:VP2 最大只支持 1920x1920。如果 route 把 VP2 连到 4K 屏:

 

[    1.235000] rockchip-vop2 fdd90000.vop: failed to set mode 3840x2160 on vp2[    1.235001] rockchip-vop2 fdd90000.vop: vp2 max output is 1920x1920

 

③ 两个 route 同时连到同一个 VP:没有竞争逻辑,只有一个生效。双屏必须分别连 VP0 和 VP1。

确认当前路由

 

# 看 CRTC 与 Connector 的绑定关系cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/state# 重点关注:# CRTC-0 (VP0) → connector 是 HDMI-A-1 → VP0 驱动 HDMI# CRTC-1 (VP1) → connector 是 eDP-1 → VP1 驱动 eDP# 看 connector 连接状态cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/connectors# 正常:connector HDMI-A-1 (connected)# 异常:connector HDMI-A-1 (disconnected)

 

第三步:各层调试方法

dmesg 和路由都检查过了,还是黑屏?逐层往下透。

DRM 层

 

# CRTC 具体状态cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/crtc-0/state# 关键字段:#   enable=1#   active=1#   mode: 1920x1080@60#   plane_mask=0x1# 如果 enable=0 → CRTC 没使能# 所有 Plane 列表cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/planes# Framebuffercat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/framebuffers# 正常:fb:1, format:XR24, 1920x1080, size:8294400

 

HWC 层

 

# HWC dumpdumpsys hwcomposer# 关注:#   Display: 0 → 主屏#   Display: 1 → 副屏#   Plane assignment → 每个 CRTC 分到了哪些 plane# 如果 dumpsys hwcomposer 输出为空 → HWC 服务没起来ps -A | grep hwc# 正常:hwcomposer.rockchip 或 android.hardware.graphics.composer

 

RK3576 的 Plane 分配策略定义在 drmhwc3576.cpp 的assignPlaneByHWC():

端口组合 VP0 VP1 VP2
单 VP0 All Cluster + Esmart0/2 - -
单 VP1 - All Cluster + Esmart1/3 -
VP0+VP1 Cluster+Esmart0/2 Esmart1/3 -
三屏全开 Cluster0+Esmart0 Cluster1+Esmart1 Esmart2/3

关键约束:VP2 不能接 Cluster 类 Plane,只能接 Esmart。如果 HWC 把 Cluster 分给了 VP2,VP2 的屏幕就是空白。

SurfaceFlinger 层

 

# SF 全局信息dumpsys SurfaceFlinger# 只看显示设备dumpsys SurfaceFlinger --displays# 正常:至少有一个 display,connected=true# 如果只有一个 display 但你有两个屏 → 副屏没被 SF 识别

 

寄存器层

 

# RK3576 VOP2 基地址 0xfdd90000# 读 VOP 版本寄存器# 正常:0x97650050(VOP_VERSION_RK3576)# 读 VP0 使能状态# bit 0: VP0 enable(1=使能)# bit 8: VP0 standby(1=待机)

 

IOMMU —— 隐蔽的黑屏原因

VOP 通过 IOMMU 读 framebuffer。IOMMU 出问题会导致 page fault:

 

dmesg | grep -E "iommu|mmu|page fault"# 错误示例:# rk_iommu fdd97e00.iommu: page fault at 0x00000000# rk_iommu fdd97e00.iommu: read from VP0, irq:0x000001

 

IOMMU page fault 的原因:

•Gralloc 分配的 buffer 没正确映射到 IOMMU 地址空间

•buffer 被释放了但 VOP 还在读

•VOP MMU 节点被 disable 了

 

cat /sys/firmware/devicetree/base/iommu@fdd97e00/status# 应该输出: okay

 

实战案例

案例一:HDMI 只有背光没有画面

现象:上电后背光亮了,一直黑屏。UART 能登录,系统正常运行,但没有任何显示。

排查过程

 

# dmesg 看驱动状态dmesg | grep -iE "vop|drm|hdmi"# 输出:# rockchip-vop2 fdd90000.vop: vop2 bind success# rockchip-drm display-subsystem: bound fdd90000.vop# rockchip-drm display-subsystem: bound fdd60000.hdmi# rockchip-drm display-subsystem: fb0: rockchipdrmfb# → 驱动初始化正常# DRM connector 状态cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/connectors# HDMI-A-1 (connected) → 连接正常# CRTC 状态cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/crtc-0/state# enable=1, mode: 0x0 ← mode 是 0!没设有效分辨率

 

根因:&hdmi 节点没配pinctrl-0。HDMI 的 I2C 引脚(DDC)没有被配置,读不到显示器的 EDID。没有 EDID,VOP 不知道输出什么分辨率。

 

# 验证cat /sys/class/drm/card0-HDMI-A-1/edid | hexdump -C# 输出为空 → 确实读不到 EDIDcat /sys/firmware/devicetree/base/hdmi@fdd60000/pinctrl-0# 输出为空 → pinctrl 没配

 

修复:补齐 pinctrl:

 

&hdmi {    pinctrl-0 = <&hdmim0_tx0_cec &hdmim1_tx1_hpd                 &hdmim1_tx0_sda &hdmim1_tx0_scl>;    pinctrl-names = "default";    status = "okay";};

 

重启后:

 

# EDID 正常读取cat /sys/class/drm/card0-HDMI-A-1/edid | hexdump -C# mode 正常了cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/crtc-0/state | grep mode# mode: 1920x1080@60

 

案例二:eDP 屏分辨率不对,内容偏移

现象:eDP 副屏有显示,但分辨率只有 1024x768(屏是 1920x1080),内容偏移半个屏。

排查过程

 

# CRTC 状态cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/crtc-1/state | grep mode# mode: 1024x768@60# 查 EDIDcat /sys/class/drm/card0-eDP-1/edid | hexdump -C# 有数据,但 timing 是 1024x768# 看 dmesg 中 eDP 协商过程dmesg | grep -i "panel|edp"# panel-simple edp-panel: panel has no eDP EDID, using fixed-mode# panel-simple edp-panel: size 1024x768

 

根因:DTS 中 eDP 配的是 panel-simple,靠 DTS 里的 display-timings 固定时序。但 DTS 写的是参考设计的分辨率,不是实际屏的。

修复:两个方案选一个。

方案 A(修正 DTS timing):

 

&edp_panel {    width-mm = <256>;    height-mm = <144>;    display-timings {        timing0 {            clock-frequency = <148500000>;            hactive = <1920>;            vactive = <1080>;            hfront-porch = <88>;            hsync-len = <44>;            hback-porch = <148>;            vfront-porch = <4>;            vsync-len = <5>;            vback-porch = <36>;        };    };};

 

方案 B(改用 panel-edp,支持 EDID 自动识别,换屏不用改 DTS):

 

// 去掉固定 display-timings,让 eDP 控制器自己读 EDID// 前提是你的 eDP 屏支持 EDID(大部分都支持)

 

案例三:双屏异显,副屏死活不出来

现象:主屏 HDMI 正常,eDP 副屏背光亮但不显示。dumpsys SurfaceFlinger --displays 只看得到一个屏。

排查过程

 

dumpsys SurfaceFlinger --displays# Display 0: HDMI-A-1 (connected)# → 只有主屏cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/connectors# HDMI-A-1 (connected)# eDP-1 (connected)# → DRM 层识别到了,但 SF 没收到通知cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/crtc-1/state | grep plane_mask# plane_mask=0x0 ← VP1 没分到任何 plane!

 

根因:VP1 的 rockchip,plane-mask 在 DTS 中没配或配成了 0。没有 plane mask,HWC 不知道 VP1 能用哪些硬件管线。

修复:在 DTS 中给每个 VP 配 plane mask:

 

&vop {    vp0: vp0 {        rockchip,plane-mask = <(ROCKCHIP_VOP2_CLUSTER0 |                                ROCKCHIP_VOP2_ESMART0 |                                ROCKCHIP_VOP2_ESMART2)>;        rockchip,primary-plane = ;    };    vp1: vp1 {        rockchip,plane-mask = <(ROCKCHIP_VOP2_CLUSTER1 |                                ROCKCHIP_VOP2_ESMART1 |                                ROCKCHIP_VOP2_ESMART3)>;        rockchip,primary-plane = ;    };};

 

plane-mask 决定了 VP 能用哪些管线。不配的话默认为 0,HWC 分不到 plane,屏幕出不来。

修复后验证:

 

dumpsys SurfaceFlinger --displays# Display 0: HDMI-A-1 (connected)# Display 1: eDP-1 (connected) ← 出来了

 

调试命令收藏

目标 命令 正常输出示例
DRM 全状态 cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/state CRTC enabled, connector connected
CRTC 状态 cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/crtc-0/state mode:1920x1080 enable=1
Connector 列表 cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/connectors HDMI-A-1 (connected)
Framebuffer cat /sys/kernel/debug/dri/ 2>/dev/null # 需开启 CONFIG_DEBUG_FS0/framebuffers fb:1 format:XR24 1920x1080
EDID 读取 cat /sys/class/drm/card0-HDMI-A-1/edid | hexdump -C 非空数据
SurfaceFlinger dumpsys SurfaceFlinger --displays Display 0/1 connected
HWC dump dumpsys hwcomposer Plane assignment 信息
时钟状态 cat /sys/kernel/debug/clk/ 2>/dev/null # 需开启 CONFIG_DEBUG_FSclk_summary | grep vop enable count >= 1
DTS 状态 cat /sys/firmware/devicetree/base/vop@fdd90000/status okay
IOMMU 错误 dmesg | grep -E "iommu|page fault" 无输出(没错误就是最好)

常规排查流程

rk3576


审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐
  • 热点推荐
  • rk3576

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分