「只能亮一块」钉死了。今天走最熟的那根线:HDMI。其它显示口先关掉。

现象:板子 HDMI 口插了显示器,显示器灯亮、提示无信号;或者有 logo 没有桌面;或者桌面跑在 HDMI 上,旁边那块 LVDS/MIPI 玻璃只剩背光。

原因几乎总是同一类:设备树把不该亮的口也 okay 了,或者该亮的 HDMI 四件套没齐,或者你改了 dts 却没刷 resource 分区。HDMI 是真热插拔:没插线,status 就是 disconnectedsimple-panel 永远报 connected。把两路一起 okay,撒谎的那路会把诚实的 HDMI 挤出主显示,或者反过来。 

分辨率跟显示器 EDID 走,不要在板级写死 1024×600。

device/board/rk/rk3568_evb/kernel/rk3568-evb-linux.dts

现象:插着 HDMI 线,status 是 disconnected

hdc shell "ls /sys/class/drm/"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"

原因

线插到 USB Host 不是 HDMI 母座;显示器输入源没切;插头没插紧;&hdmi okay 但 &hdmi_in_vp0 / &route_hdmi 仍 disabled,VOP 没把 VP 接到 HDMI。

代码

&hdmi { status = "okay"; };
&hdmi_in_vp0 { status = "okay"; };
&hdmi_in_vp1 { status = "disabled"; };
&route_hdmi {
    status = "okay";
    connect = <&vp0_out_hdmi>;
};

VP0 出 HDMI。connect 写成 vp1_out_hdmi 却打开 in_vp0,扫描在一边、连接器在另一边,黑屏。

hdc shell "cat /proc/partitions"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/enabled"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/modes"
hdc shell "mount -t debugfs none /sys/kernel/debug 2>/dev/null"
hdc shell "cat /sys/kernel/debug/dri/0/summary"

期望 connectedmodes 里有显示器给的模式(常见 1920x1080)。拔线再读,必须变成 disconnected。不变,你看的不是真 HDMI。


现象:HDMI 有桌面,旁边 MIPI/LVDS 只有背光

原因

composer 同一时刻只喂一路。你为了先看 HDMI 把 &hdmi 打开,测完忘了关。Linux Weston 可以双 output,开源鸿蒙不行。

代码:开 HDMI 时其余全关

&hdmi { status = "okay"; };
&hdmi_in_vp0 { status = "okay"; };
&route_hdmi { connect = <&vp0_out_hdmi>; status = "okay"; };

&video_phy0 { status = "disabled"; };
&lvds { status = "disabled"; };
&lvds_in_vp2 { status = "disabled"; };
&route_lvds { status = "disabled"; };
&lvds_panel { status = "disabled"; };

&rgb { status = "disabled"; };
&rgb_in_vp2 { status = "disabled"; };
&route_rgb { status = "disabled"; };
&tft_lcd_panel { status = "disabled"; };

&edp { status = "disabled"; };
&edp_in_vp0 { status = "disabled"; };
&edp_panel { status = "disabled"; };

&dsi1 { status = "disabled"; };
&dsi1_in_vp0 { status = "disabled"; };
&dsi1_in_vp1 { status = "disabled"; };
&route_dsi1 { status = "disabled"; };
&dsi0 { status = "disabled"; };
&dsi0_panel { compatible = "simple-panel-dsi-disabled"; };

DSI panel 节点不能删。HDF of_find_compatible_node 不一定跳过 status=disabled,抓错之后 panelManager 空,/dev/dri/card0 可能不建。

刷 resource p4 + boot_linux p5,路径 /dev/block/。SD 启动也写 mmcblk0p4

hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk1p4 bs=4M conv=fsync"
hdc shell "dd if=/data/boot_linux.img of=/dev/block/mmcblk1p5 bs=4M conv=fsync"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk0p4 bs=4M conv=fsync"

现象:黑屏,串口有字

三种黑不要混:

  1. [drm] Initialized 从不出现 → 内核 DRM 没起来,查四件套。
  2. 有 Initialized、有 logo、无桌面 → RenderService / SystemUI / 电源超时。hidumper -s RenderService,约 22 秒后黑用 wakeup。
  3. HDMI disconnected → 回到第一节。

failed to init overlay plane 经常是红鲱鱼。modes 为空是 EDID 没读到,换线、直插、显示器开到明确 HDMI 源。不要在 dts 里编假 timing。

hdc shell "dmesg | grep -iE 'drm|hdmi|edid|vop'"
hdc shell "ls /dev/dri/"
hdc shell "pidof render_service"

不要在 DTS 里写死 1024×600

LVDS 那块玻璃没有 EDID,时序必须写在 dts 里。HDMI 显示器有 EDID,写死是在剥夺它。

错误示范:

&hdmi {
    status = "okay";
    /* 不要这样做 */
    rockchip,default-mode = <1024 600>;
};

hdmi_panel: hdmi-fake-panel {
    compatible = "simple-panel";
    display-timings {
        native-mode = <&hdmi_timing0>;
        hdmi_timing0: timing0 {
            clock-frequency = <51200000>;
            hactive = <1024>;
            vactive = <600>;
        };
    };
};

第二段尤其坏:你给 HDMI 造了一个 simple-panel。HDMI 连接器立刻染上 LVDS 那种「永远 connected」的病,热插拔失效,拔线仍 connected,EDID 被忽略。桌面分辨率锁在 1024×600,1080p 显示器四周黑边,或者直接不认。

正确的 HDMI 就是四行 status 加一个 connect。分辨率出现在:

hdc shell "cat /sys/class/drm/card0-HDMI-A-1/modes"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/enabled"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"

modes 里常见:

1920x1080
1280x720
1024x768

哪一档被选中,看 debugfs summary 里 VP0 的 mode。插不同显示器,这个列表会变。变了,说明 EDID 通路是通的。列表永远只有 1024x600,回头查 dts 是不是被写死,或者 DDC 没出来、驱动在用一份兜底模式。

DDC 是一组 I2C。显示器不给 EDID(线太差、插座虚接、显示器还没上电),连接器可能 connected 但 modes 空。HPD 高、DDC 失败,表现就是有 connected、没模式、黑屏。换线、换口、让显示器先亮再插,比改 dts 快。

官方连线图从 SoC 到插座经过 PHY、HPD、DDC。RK3568 的 HDMI 控制器把这三样包在 &hdmi 节点里,板级 dts 通常只改 status 和接到哪个 Video Port。你要是在板级再抄一份时钟,就是在和显示器的 EDID 抢权。


真正生效的还是 resource 里那份 dtb

你从 LVDS 切到 HDMI,只刷了 p5,U-Boot 仍加载 p4 的 rk-kernel.dtb,板上继续出 LVDS 时序。HDMI 线插着,summary 仍是 LVDS-1clk 51200。你会以为 HDMI 驱动坏了。

生效的 DTB 是 resource 分区 p4 的 rk-kernel.dtb,不是 boot_linux 里的 toybrick.dtb。改 &hdmi 必须刷 p4。稳妥起见 p5 也刷,内核和 dtb 成套。

SD 是 mmcblk1,eMMC 是 mmcblk0/dev/block/by-name/resource 永远指 eMMC。U-Boot 常从 eMMC 取 resource。从 SD 启动也要刷 mmcblk0p4

dd 必须写 /dev/block/mmcblkXpY

hdc shell "cat /proc/partitions"
hdc shell "ls -l /dev/block/mmcblk0p4 /dev/block/mmcblk1p4 /dev/block/mmcblk0p5 /dev/block/mmcblk1p5"

hdc file send resource.img /data/resource.img
hdc file send boot_linux.img /data/boot_linux.img
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk1p4 bs=4M conv=fsync"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk0p4 bs=4M conv=fsync"
hdc shell "dd if=/data/boot_linux.img of=/dev/block/mmcblk1p5 bs=4M conv=fsync"

写完看返回。records in/out 之后必须是块设备上的写入。若 ls -l /dev/mmcblk1p4 显示普通文件而不是 brw,你已经踩进假成功。删掉那个文件,改路径重来。

板上:

hdc shell "cat /proc/device-tree/lvds-panel/status; echo"
hdc shell "find /proc/device-tree -iname '*hdmi*'"
hdc shell "cat /proc/device-tree/hdmi@fe0a0000/status; echo"

lvds-panel 期望 disabled。HDMI 控制器期望 okay。对不上,就是刷错分区或刷错介质,别去拧显示器菜单。

board 目录经常不在内核 DEPS 里。改 dts 之后删 checkpoint,让 build_kernel.sh 把 rk3568-evb-linux.dts 拷进内核树,编 dtb,打 resource。

rm -rf out/kernel/checkpoint
rm -f out/kernel/src_tmp/linux-5.10/resource.img
rm -f out/rk3568_evb/packages/phone/images/resource.img
./build.sh --product-name rk3568_evb --ccache

只换显示、system / vendor 已经能进桌面时,刷 resource + boot_linux 就够。vendor 缺 GPU 库那是另一张镜像的事;缺的话桌面同样没有,render_service 退 255。

编完在主机确认 dtb:

find out/kernel -name '*rk3568-evb*.dtb' -o -name 'rk-kernel.dtb' | head
dtc -I dtb -O dts -o /tmp/now.dts 那份.dtb
grep -n 'hdmi\|lvds\|simple-panel-dsi' /tmp/now.dts | head -40

&hdmi 合并后的节点 status 是 okay,lvds-panel 是 disabled,DSI panel 的 compatible 带 disabled 这个后缀。三件都在,再刷。缺一件,编的是旧树或 dts 没被拷进去。


线、口、输入源:软件全对时的黑屏

软件栈查完仍是黑的,按硬件从近到远排。

USB Host 口和 HDMI 口长得不像,但操作台上线多了会插错。Host 口给 U 盘、USB 相机、USB 网卡。HDMI 插座在板边,对的是显示器或电视机。插到 Host,HPD 不会跳,status 停在 disconnected。这不是驱动。

插头没插紧。HDMI 靠里面那排弹片,松一下 HPD 就掉。status 在 connected / disconnected 之间抖,modes 时有时无。按住再读一次 sysfs。抖就换线。

显示器输入源。很多屏后面有 HDMI1 / HDMI2 / DP / 自动。停在自动以外的错误源,板子已经 connected,人眼仍是「无信号」。把菜单切到对应那一个 HDMI。这一条不进 dmesg。

显示器还没从待机醒。HPD 有的屏在待机时仍拉高,有的不拉。你看到 disconnected,先按显示器电源。

分辨率超出显示器能力。EDID 若被读残,驱动可能选一档屏不认的 mode。modes 里只留 1920x1080 试:用一根短线、一台 1080p 屏做对照。不要在 dts 里写死兜底时序,先把 DDC 修好。

拔掉线能变成 disconnected,还有一个诊断用途。你怀疑当前主显示是不是 HDMI:拔线,summary 里 VP0 应该停,status 变 disconnected。若拔线之后 status 仍是 connected,你看的那个 card0-HDMI-A-1 不是真 HDMI,或者 dtb 根本不是你以为的那份。


内核没起来,也会被说成「HDMI 黑屏」

DDR 识别错、loader 版本和颗粒不匹配,U-Boot 停在内存训练,或者内核没出 [drm] Initialized。屏上可能有 U-Boot 的字,也可能全黑。你在 dts 里改 HDMI 没有意义。

串口必须开着。波特率 1500000 8N1。没看到内核的 Linux version,不要谈显示。没看到 [drm] Initialized rockchip,不要谈 HDMI 连接器。

/dev/dri/card0 不出现,和 HDMI 插头无关。回到四件套、HDF 有没有误抓 DSI panel、vendor 里有没有把 DRM 编进内核。CONFIG_DRM_ROCKCHIPCONFIG_DRM_DW_HDMI 这类开关若被关掉,连接器节点写得再漂亮也不会有 card0-HDMI-A-1。那是内核配置,不是 dts status。新编的 Image 里要能 grep -a 到 HDMI 相关字符串,再刷。

CEC 脚、HPD 脚若被别的节点占用,表现为永远 disconnected。先确认 HDMI 节点活着,再去对 pinctrl:

hdc shell "cat /sys/class/drm/card0/device/uevent"
hdc shell "ls /sys/class/drm/"

uevent 里能看到 DRM 驱动名,card0-HDMI-A-1 必须出现。没有这个连接器,是 &hdmi 没 probe,不是显示器的事。


电源超时:桌面起来过,然后黑

HDMI 显示器自带背光,不会踩 LVDS 那种 37 秒 regulator cleanup。它会踩电源管理。

首启 SystemUI、Launcher、一堆 hap 在装,没人碰鼠标。SuspendController 的 timeout 源走到,发 display off,DRM blank。串口有:

KeventFbNotifierFn: blank=4
receive display off event
DevmgrServicePowerStateChange: suspend

hdc 还活着,pidof render_service 还有号。这不是 HDMI 没配好。

hdc shell "power-shell wakeup"

屏醒了,显示栈没问题。真正读的配置在 /system/etc/power_config/power_suspend.json。往 vendor 放一份盖不住。显示总论把这一层归在「卡 logo 的变种」。HDMI 上它更像「亮过又灭」。

不要为此去改 &hdmi 的 status。那是给连接器的,不是给空白计时器的。


验收命令,从 partitions 开始

hdc shell "cat /proc/partitions"
hdc shell "mount | grep ' on / '"
hdc shell "ls -l /dev/block/mmcblk0p4 /dev/block/mmcblk1p4"
hdc shell "ls -l /dev/block/by-name/resource /dev/block/by-name/boot_linux"

hdc shell "dmesg | grep -iE '\\[drm\\] Initialized|dw-hdmi|rockchip-drm|hdmi'"
hdc shell "ls -l /dev/dri/"
hdc shell "cat /sys/class/drm/card0/device/uevent"

hdc shell "ls /sys/class/drm/"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/enabled"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/modes"

hdc shell "mount -t debugfs none /sys/kernel/debug"
hdc shell "cat /sys/kernel/debug/dri/0/summary"

hdc shell "cat /proc/device-tree/lvds-panel/status; echo"
hdc shell "find /proc/device-tree -iname '*hdmi*'"

hdc shell "pidof render_service composer_host"
hdc shell "hidumper -s RenderService | head -80"

插上显示器之后,合格大致是:

card0-HDMI-A-1/status    connected
card0-HDMI-A-1/enabled   enabled
card0-HDMI-A-1/modes     至少一行,常见 1920x1080
summary                  VP0 ACTIVE,connector HDMI-A-1
lvds-panel/status        disabled

enabled 是 disabled 但 status 是 connected,说明连接器在、没被选成主显示。回头查还有没有 simple-panel 抢在前面,或者 composer 没起来。

status 是 disconnected,先动手:换口、换线、开显示器、确认不是 Host 口。再读 dts 的 &hdmi。最后才怀疑 HPD 脚被占用。

分辨率不要用尺子去量是不是 1024×600。HDMI 这篇通过的标志是「跟这台显示器的 EDID 一致」,不是「跟 LVDS 玻璃一致」。


和 LVDS 对打,才能记住 HDMI 的脾气

同一块板,同一份内核,换 dts 开关就能在两种连接器之间切。建议真的切一次。

切到 HDMI:四件套打开 VP0,LVDS / RGB / DSI / eDP 全关,DSI panel 改 compatible。刷 p4 和 p5,eMMC 的 p4 也刷。插显示器。读 statusmodes、summary。拔线,status 必须变成 disconnected。

再切回 LVDS:按 LVDS 那篇把 1024×600、JEIDA、video_phy0lvds_in_vp2route_lvds 打开,把 &hdmi 四件套关掉。刷同一对分区。U-Boot 应打出 type: LVDS0 for VP2。此时插不插 HDMI 线都不该再出现 HDMI-A-1 被选中。你可以插着线,card0-HDMI-A-1 若还在,status 即使 connected,summary 的 ACTIVE 也必须是 LVDS-1。若 HDMI 又把桌面抢走,就是 &hdmi 没关干净。

这两次切换用的是同一根原则。HDMI 贡献的额外一课是:只有它能用拔线证明自己。LVDS 不能。谁先学会信 HPD,谁就少信 simple-panel 的 connected。

窗口取向:显示器是 1920×1080 横的,窗口服务若仍按竖屏 720×1280 申请,桌面会在 HDMI 上竖着占一块。那是窗口取向,不是 HDMI 时序。触摸跟主显示走。外接 HDMI 常常配 USB 鼠标,键鼠插 Host 口,HDMI 线插 HDMI 口。


现场一条最短路径

显示器、HDMI 线、板子、串口、hdc,五样都在桌上。dts 已按本文打开 HDMI、关掉其余。

先串口。上电看到 Linux version,看到 [drm] Initialized。看不到,停,不要拧显示器。

再 hdc。cat /proc/partitions。确认这次启动介质。把 resource、boot_linux 按 /dev/block/ 写到 p4、p5,eMMC 的 p4 也写。reboot。

起来后读 card0-HDMI-A-1/status。disconnected:换口换线换输入源,再读。connected:读 modes,读 summary。VP0 上是 HDMI-A-1,桌面就该在这台显示器上。

桌面不在,pidof render_service 为空:去查 so 和 hilog,不是 HDMI。pid 在、屏黑:power-shell wakeup。醒了就是超时。不醒,summary 是否其实在扫 LVDS-1——回到四选一。

这条路径里没有「调 HDMI 时序」这一步。需要时序的是 LVDS、RGB、MIPI、eDP 那些没有 EDID 或不信任 EDID 的口。


现象对照

现象原因先做什么
card0-HDMI-A-1 不存在&hdmi disabled 或 DRM 没起来ls drm;dmesg
disconnected,线插着HPD/线/源/route 没齐换线换口;查四件套
connected,modes 空EDID 失败换线、先开显示器再插
HDMI 有桌面,MIPI 只背光两路 okay关 HDMI 再测 MIPI
connected 但 enabled=disabled主显示不是 HDMIsummary;关 simple-panel
改 dts 无效没刷 p4;dd 路径错resource + /dev/block/
有 logo 无桌面RS/SystemUI/电源hidumper;wakeup
画面 1024×600 居中小块dts 写死了 LVDS 时序删 panel timing,跟 EDID

拔线实验是 HDMI 独有的教具。status 必须跟着插头走。LVDS-1、DPI-1 做不到这件事,它们永远 connected。所以这一路既是投屏口,也是用来验证「你刷进去的 dtb 是不是真 HDMI 那份」的探针。

hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"
# 拔线,再读一次,必须变成 disconnected
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/edid" | xxd | head
hdc shell "cat /sys/kernel/debug/dri/0/summary"
hdc shell "find /proc/device-tree -iname '*hdmi*' | head"

edid 全零:DDC 没通,换线、去掉转接头。summary 的 ACTIVE 在 LVDS-1:dts 里 HDMI 可能 okay 了,主显示仍被 simple-panel 抢走,回到四选一那一组 disabled。/proc/device-tree 里 hdmi 仍是 disabled:p4 没刷上,或刷到了 SD 的 p4、U-Boot 读的是 eMMC。

不要给 HDMI 造一颗 simple-panel。不要把 1024×600 写进 HDMI 节点。契约是四件套、别人全关、HPD 真的连上、EDID 能读、resource 里的 dtb 是新的。 | 拔线仍 connected | 造了 simple-panel,或看错连接器 | 不要给 HDMI 加 fake panel | | [drm] Initialized 没有 | 内核没起来,或 DRM 没编进 | 串口从 U-Boot 读起 | | render_service 退 255 | vendor 缺 mali / composer so | 产品 config,与 HDMI 无关 | | Cluster plane init failed | 能出桌面的旧包是否也有 | 红鲱鱼 |

「另一路 simple-panel 仍 okay」值得单独再写一次为什么。HDMI 自己不会永远 connected。它被抢走,是因为列表里站着一个更早注册、永远 connected 的 LVDS-1 或 DPI-1 或 DSI-1。你在 HDMI 连接器上看一切正常:插上 connected,拔掉 disconnected。桌面却不来。summary 会出卖真相:ACTIVE 的 VP 挂的不是 HDMI-A-1。

修法不是给 HDMI 提高优先级。开源鸿蒙的 composer 没有「我更喜欢 HDMI」这种旋钮。修法是把撒谎的那路 disabled,让列表里只剩 HDMI。四选一在 HDMI 这篇里不是口号,是让热插拔的诚实生效。


现象:改了 dts,HDMI 还是不出

&hdmi 已经 okay,LVDS 已经 disabled。重启以后 /proc/device-tree 里 LVDS 还是 okay。

原因

生效的 DTB 在 resource 分区 p4 的 rk-kernel.dtb。U-Boot 取出这份树再启动内核。boot_linux 那个 ext2 里也有一份 dtb,名字常叫 toybrick.dtb,你刷 p5 换的是它,U-Boot 不读。

/dev/block/by-name/resource 永远指向 eMMC,也就是 mmcblk0p4。从 SD 启动只刷 mmcblk1p4,U-Boot 仍可能从 eMMC 取旧 resource。SD 启动也要刷 mmcblk0p4

dd 写成 /dev/mmcblk1p4。这个路径常常不是块设备,工具在 /dev 下新建普通文件,exit 0。分区里的旧图纹丝不动。必须 /dev/block/mmcblkXpY

内核 GN 不盯 board 目录。改了 rk3568-evb-linux.dts,ninja 认为内核没变,out/ 里躺着昨天的 resource.img

代码

rm -rf out/kernel/checkpoint
rm -f out/rk3568_evb/packages/phone/images/resource.img
./build.sh --product-name rk3568_evb --ccache

hdc shell "cat /proc/partitions"
hdc shell "ls -l /dev/block/mmcblk0p4 /dev/block/mmcblk1p4"
hdc file send resource.img /data/resource.img
hdc file send boot_linux.img /data/boot_linux.img
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk1p4 bs=4M conv=fsync"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk0p4 bs=4M conv=fsync"
hdc shell "dd if=/data/boot_linux.img of=/dev/block/mmcblk1p5 bs=4M conv=fsync"

主机确认:

dtc -I dtb -O dts -o /tmp/now.dts rk-kernel.dtb
grep -n 'hdmi\|lvds-panel\|simple-panel-dsi' /tmp/now.dts | head -40

&hdmi 合并后 okay,lvds-panel disabled,DSI panel 的 compatible 带 disabled 后缀。三件都在,再刷。

板上:

hdc shell "cat /proc/device-tree/lvds-panel/status; echo"
hdc shell "find /proc/device-tree -iname '*hdmi*' | head"

lvds-panel 仍是 okay,新树没生效,不要拧显示器。


现象:modes 是空的,status 却是 connected

控制器认为插上了,EDID 没读到。没有可用模式,composer 没法选分辨率。屏上「无信号」,和 disconnected 看起来一样,sysfs 不一样。

原因

DDC 是一组 I2C,走 HDMI 插座里那对 DDC 脚。线太长、转接头只接了 TMDS 没接 DDC、显示器还没上电,都会让 EDID 读空。HPD 可以先跳变,DDC 后失败。

错误修法是在 dts 里给 HDMI 编一套 1024×600 的 display-timings,甚至造一颗 simple-panel 挂上去。那是 LVDS 的做法。HDMI 会跟真实显示器打架:热插拔失效,拔线仍 connected,1080p 屏四周黑边。

代码

hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/modes"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/edid" | xxd | head
hdc shell "dmesg | grep -iE 'edid|hdmi|ddc'"

edid 全零或读失败,先换线、直插不走转接、显示器开到明确的 HDMI 源。短线、1080p 屏做对照。读到一串非零,modes 就该出现 1920x1080 一类。

不要写:

/* 错误示范 */
hdmi_fake: hdmi-fake-panel {
    compatible = "simple-panel";
    display-timings {
        native-mode = <&hdmi_timing0>;
        hdmi_timing0: timing0 {
            clock-frequency = <51200000>;
            hactive = <1024>;
            vactive = <600>;
        };
    };
};

正确的 HDMI 就是控制器 + in_vp + route。分辨率出现在 modes 文件里,随显示器变。永远只有 1024x600,回头查 dts 是不是被写死。


现象:画面是 1024×600 小块,四周黑

modes 能把两件事分开。列表里只有 1024x600:dts 写死了,或 EDID 失败后走了兜底。列表里有 1920x1080,summary 也是 1920x1080,画面仍是竖条:窗口取向,不是 HDMI。

删掉 HDMI 上任何 display-timings、任何 simple-panel。让 EDID 说话。窗口取向在板级显示策略里写成横屏。那不是 &hdmi 的字段,别在 porch 上找竖条。

外接 HDMI 常用 USB 键鼠,插 Host 口,不是 OTG。OTG 一插,板子角色会变,hdc 掉、画面也像「没了」。触摸跟主显示走。不要 HDMI 出桌面、LVDS 玻璃还当第二块触摸板——composer 不会克隆。


现象:亮过桌面,二三十秒后黑

HDMI 显示器自带背光,不会踩 LVDS 那种 37 秒 regulator cleanup。它会踩电源管理。首启在装 hap,没人点,SuspendController 的 timeout 源走到,DRM blank。

KeventFbNotifierFn: blank=4
receive display off event
hdc shell "power-shell wakeup"
hdc shell "pidof render_service"

屏醒了,显示栈没问题。真正读的配置在 /system/etc/power_config/power_suspend.json。往 vendor 放一份盖不住。不要为此去改 &hdmi 的 status。

render_service 退 255 是另一件事。查 vendor 的 mali / composer so。板级 config.json 没声明 rockchip_products 一类部件,so 编出来了也不会打进 vendor.img。刷一百次 p4 也补不回来,要重打 vendor。

failed to init overlay plane Cluster0-win0 在能出桌面和黑屏的日志里都出现过,当红鲱鱼。

串口没有 Linux version,是 loader / DDR,不是 HDMI。波特率 1500000 8N1。停在内存训练、停在 Cannot find partition,先把启动做完。


从 LVDS 切到 HDMI,一次做完

打开 device/board/rk/rk3568_evb/kernel/rk3568-evb-linux.dts,按本文打开 HDMI 四件套,关掉 LVDS / RGB / DSI / eDP,DSI compatible 改名,video_phy0 disabled。删 checkpoint,重打 resource 和 boot_linux。

hdc shell "cat /proc/partitions"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk1p4 bs=4M conv=fsync"
hdc shell "dd if=/data/boot_linux.img of=/dev/block/mmcblk1p5 bs=4M conv=fsync"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk0p4 bs=4M conv=fsync"
hdc shell reboot

串口看到 Linux version,看到 [drm] Initialized。插上显示器:

hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/modes"
hdc shell "mount -t debugfs none /sys/kernel/debug 2>/dev/null"
hdc shell "cat /sys/kernel/debug/dri/0/summary"
hdc shell "cat /proc/device-tree/lvds-panel/status; echo"

status=connected,modes 非空,summary 的 VP0 是 HDMI-A-1,lvds-panel 是 disabled。拔线:status=disconnected。这四条齐了,内核侧过关。

桌面不在,走 RenderService / 签名 / 超时,不是时序。

再切回 LVDS:按 LVDS 那篇把 1024×600、JEIDA、video_phy0lvds_in_vp2route_lvds 打开,把 &hdmi 四件套关掉。刷同一对分区。U-Boot 应打出 type: LVDS0 for VP2。此时插着 HDMI 线,summary 的 ACTIVE 必须是 LVDS-1。若 HDMI 又把桌面抢走,就是 &hdmi 没关干净。

两次切换用的是同一根原则。HDMI 贡献的额外一课:只有它能用拔线证明自己。


验收命令,从 partitions 开始

hdc shell "cat /proc/partitions"
hdc shell "mount | grep ' on / '"
hdc shell "ls -l /dev/block/mmcblk0p4 /dev/block/mmcblk1p4"
hdc shell "ls -l /dev/block/by-name/resource /dev/block/by-name/boot_linux"

hdc shell "dmesg | grep -iE '\\[drm\\] Initialized|dw-hdmi|rockchip-drm|hdmi'"
hdc shell "ls -l /dev/dri/"
hdc shell "cat /sys/class/drm/card0/device/uevent"

hdc shell "ls /sys/class/drm/"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/status"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/enabled"
hdc shell "cat /sys/class/drm/card0-HDMI-A-1/modes"

hdc shell "mount -t debugfs none /sys/kernel/debug"
hdc shell "cat /sys/kernel/debug/dri/0/summary"

hdc shell "pidof render_service composer_host"
hdc shell "hidumper -s RenderService | head -80"
hdc shell "power-shell wakeup"

合格大致是:

card0-HDMI-A-1/status    connected
card0-HDMI-A-1/enabled   enabled
card0-HDMI-A-1/modes     至少一行,常见 1920x1080
summary                  VP0 ACTIVE,connector HDMI-A-1
lvds-panel/status        disabled
拔线后 status            disconnected

分辨率不要用尺子去量是不是 1024×600。HDMI 通过的标志是「跟这台显示器的 EDID 一致」,不是「跟 LVDS 玻璃一致」。

HDMI 这一路没有 DCS 初始化,没有 JEIDA 总线格式,没有 51.2 MHz 写死。契约是:四件套 okay、别人 disabled、HPD 真的连上、EDID 能读、resource 里的 dtb 是新的。玻璃屏那几路把契约换成 simple-panel 和时序表。LVDS 那篇会把 51.2 MHz 钉死。对照着看,HDMI 为什么不写 timing 会更清楚:LVDS 没 EDID,不写就没模式;HDMI 有 EDID,写了就是在抢权。


DDC 是一组 I2C,不是神秘寄存器

HDMI 插座里除了 TMDS,还有一对脚跑 I2C,就是 DDC。显示器把 EDID 放在地址 0x50。驱动读到一串二进制,解析出 modes

线只接了影像没接 DDC(劣质转接头常见),HPD 可以高,status 是 connected,modes 是空。看起来像驱动坏了,其实是显示器没机会开口。

hdc shell "cat /sys/class/drm/card0-HDMI-A-1/edid" | xxd | head -8
hdc shell "dmesg | grep -iE 'edid|ddc|i2c'"

edid 开头常见 00 ff ff ff ff ff ff 00,这是 EDID 头。全零或读失败,换线、去掉转接头、显示器先亮再插。不要在 dts 里补一份假 timing 去「救」它。那是 LVDS 的契约,HDMI 会跟真实 1080p 打架。

插不同显示器,modes 列表应当变。变了,DDC 通。永远只有 1024x600,回头查 dts 是不是被写死。


系列第 17 篇 · 芯片:瑞芯微 RK3568 · OpenHarmony 4.1(API 11) · Linux 5.10

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐