新闻详情

新闻详情

首页 / 资讯中心 / 详情

RK3568多路显示移植实战:OpenHarmony双屏异显与设备树配置指南

发布时间:2026/9/11 4:58:06来源:尧图网络
RK3568多路显示移植实战:OpenHarmony双屏异显与设备树配置指南
做 RK3568 多路显示移植这件事是我最近在 OpenHarmony 系统适配里最折腾、也最有收获的一块。RK3568 这颗芯片的显示能力其实很强原生就支持 HDMI、eDP、LVDS、MIPI DSI 多路输出但真正要在 OpenHarmony 上把两路屏幕同时点亮、再让每路屏幕显示各自的内容中间涉及的内核配置、设备树路由、时序参数、用户态显示栈适配每一环都有坑等着你。这篇文章就围绕“RK3568 多路显示移植”这个主题把我实际项目中走过的流程、改过的配置、踩过的坑完整捋一遍给准备在 RK3568/3566 上做多屏方案的兄弟们一份能直接抄作业的参考。我不打算只贴一段设备树就完事而是把整个移植过程中最关键的设计思路和排查方法讲明白。你要知道多路显示移植最怕的不是“不会配”而是“配置错了不知道从哪查起”。所以这篇文章会先从硬件基础和显示链路讲起再逐步展开内核配置、设备树实操、双屏异显方案最后用一整章的篇幅整理现场调试时最常遇到的问题和排查技巧确保你在实际项目中遇到类似情况时能快速定位。1. 在这次移植里我到底在做什么1.1 别被“多路显示”四个字带偏很多朋友一听到“多路显示”第一反应就是“接两块屏幕嘛一块 HDMI 一块 MIPI都点亮不就完了”。真要做起来你会发现事情远没有这么简单。多路显示不只是物理上接两块屏而是要在系统层面同时驱动两套完整的显示链路前端是图形渲染出来的帧中端要经过显示控制器VOP合成、缩放、叠加后端要通过不同的物理接口HDMI、LVDS、MIPI DSI 等把信号送到各自的屏幕上整个过程还要保证帧率同步、分辨率匹配、时序正确。在 OpenHarmony 标准系统的体系里显示栈的底层层基本是复用 Linux 内核的 DRM/KMS 框架。Rockchip 的 DRM 驱动负责把 VOP 和各个显示接口抽象成 DRM 设备OpenHarmony 的 HDFHardware Driver Foundation显示模块再通过 libdrm 和内核对接。所以做多路显示移植核心工作其实集中在两块一是确保内核里的 DRM 驱动和各个显示接口驱动能正常 probe二是把设备树里“显示接口 - VOP 通道 - 物理面板”这三者的路由关系配清楚。这个理解太重要了因为它决定了你排查问题的方向。如果第二路屏幕不亮你先怀疑的是 HDMI 驱动有没有起来、设备树 route 节点有没有配对而不是跑去应用层找显示接口 API 的问题。移植的系统层面没打通应用层写得再花哨都没用。1.2 RK3568 的显示资源盘点动手之前一定要先盘点手里的硬件资源知道自己有什么、能用什么才能决定后面怎么配置。RK3568 集成了两个显示控制器 VOP习惯上叫 VOP0 和 VOP1。VOP0 能力更强支持 4K60 输出VOP1 最高支持 2K60部分场景 4K30。每个 VOP 内部又有多个视频层plane用于 UI 层、视频层、光标层的叠加和合成这个和 PC 显卡的 overlay 概念类似。RK3568 上可以拿来输出画面的物理接口包括HDMI 2.0、eDP 1.3、双通道 LVDS、MIPI DSI有四组 D-PHY通常接一组或两组、RGB 并口。它并不是所有接口都能同时自由组合。LVDS 和 MIPI DSI 之间存在引脚复用关系RGB 接口也和部分 LVDS 引脚有复用真正能“同时点亮”的组合往往是固定的那几种比如“HDMI MIPI DSI”、“HDMI LVDS”、“eDP MIPI DSI”。这就要求你在选型阶段就把屏幕接口定下来别等画完板子再发现这也不能接那也不能接。从 OpenHarmony 适配的角度看还有一个必须注意的资源约束每个显示接口在设备树里要显式绑定到某个 VOP 的 video portvp0、vp1、vp2、vp3而这个绑定一旦冲突驱动会直接拒绝初始化。RK3568 的 VOP 通道数量是够用的但接口和通道之间的交叉使能需要你手动规划清楚不能两个 route 节点都抢同一个 vp。1.3 为什么基于 DRM 来做而不是自己写驱动这个问题我评估了很久。Rockchip 在老内核里有一套自己的 framebuffer 显示框架很多旧项目直接基于那个改。但在 OpenHarmony 标准系统上用户态的 HDF 显示模块、图形栈Graphic 2D、Rosen 窗口系统对接的是标准的 DRM/KMS 接口如果你自己另起炉灶写一套显示驱动意味着上层所有组件都要跟着改工作量会成倍上涨。所以常规做法就是走 Rockchip 官方内核的 DRM 路线OpenHarmony 用户态通过 HDF display 模块访问 /dev/dri/card0 来完成画面提交和显示。这样做的好处是生态成熟DRM 的 modetest、dmesg 调试信息、/sys/class/drm 下的状态节点都能直接拿来用上层接口也标准后续升级内核版本、替换显示面板时不需要动用户态代码。基于这个前提本文后面的所有配置都以 Rockchip 5.10 内核 DRM 框架为基线展开这也是目前 RK3568 上跑 OpenHarmony 标准系统的主流组合。2. 动手前三件事内核开关、设备树框架、显示通路2.1 内核里要保证能开的显示开关有些项目拿到的 SDK 默认内核配置只打开了 HDMI你直接加一个 MIPI DSI 的设备树节点进去驱动根本没有编译自然也就没有反应。所以第一步是把内核配置过一遍确保 DRM 框架和你要用的接口驱动都编译进去了。我以 Rockchip 5.10 内核为例列一下多路显示移植时最常用到的几个配置项配置项说明建议CONFIG_DRM_ROCKCHIPRockchip DRM 总开关VOP、MMU 都依赖它必选CONFIG_DRM_ROCKCHIP_DW_HDMI经 Synopsys DW-HDMI 控制器输出的 HDMI 驱动用 HDMI 就开CONFIG_DRM_ROCKCHIP_ANALOGIX_DPAnalogix DP/eDP 驱动用 eDP 就开CONFIG_DRM_ROCKCHIP_LVDSLVDS 输出驱动用 LVDS 就开CONFIG_DRM_ROCKCHIP_DW_MIPI_DSIMIPI DSI 控制器驱动用 MIPI 屏就开CONFIG_DRM_PANEL_SIMPLE通用 panel 驱动适配 simple-panel 节点强烈建议开CONFIG_BACKLIGHT_PWM / CONFIG_PWM_ROCKCHIPPWM 背光控制屏幕要调亮度就开内核对配置的依赖关系很严格比如 DRM_ROCKCHIP_DW_HDMI 必须依赖 DRM_ROCKCHIPMIPI DSI 驱动还依赖 DRM_MIPI_DSI 基础框架。我在实际编译时踩过最典型的坑就是单独勾了某个接口驱动但它的依赖项没开编译报错后整块功能直接缺失后续排查方向都偏了。建议你把内核配置界面里的显示相关项整体展开把所有 Rockchip 显示驱动都检查一遍确保不遗漏。2.2 设备树里那条看不见的“数据通路”RK3568 的显示设备树逻辑上可以理解成一条水管系统VOP 是水泵显示接口是水龙头panel 是你手上的杯子。设备树要做的事情就是把“水泵”的出水口通过哪根管子接到哪个“水龙头”上告诉系统这颗电路板实际是怎么设计的。具体到节点层级一个典型的 DRM 显示设备树结构包含这样几层display_subsystem整个显示子系统的容器状态要 ok里面引用了 VOP 和各个显示接口节点。vop/vopb_mmuVOP 控制器及对应的 IOMMU 节点status 都设为 ok。vp0/vp1/vp2/vp3VOP 的显示端口每个 vp 可以绑定一个显示接口配置里还包括 plane 的分配。route_hdmi/route_lvds/route_mipi_dsi路由节点真正决定“哪个接口从哪个 vp 取数据”的地方这个节点的 connect 属性是最关键的一个。具体接口节点hdmi、dsi0、dsi1、lvds负责各自接口的寄存器配置、引脚复用、电源控制。panel 节点挂在接口节点下面描述屏幕的物理参数、供电引脚、背光控制、时序。这里我要强调一下 vp 和 plane 的分配关系。在 Rockchip 设备树里rockchip,plane-mask 决定这个 vp 能使用哪几个 planerockchip,primary-plane 决定默认的主 planerockchip,cluster-plane 决定哪个是 cluster 层通常用于视频层。如果两个 vp 的 plane-mask 配重了会出现莫名其妙的分屏、抖动、显示内容串扰。一个稳妥的分配方式是vp0 用 plane 0 和 2vp1 用 plane 1 和 3这样资源完全隔离。2.3 面板时序参数计算真没你想的那么简单面板时序是整个设备树里最容易被抄错、也最影响显示效果的部分。很多 LCD 屏的 datasheet 里会直接给你一组参数hactive、vactive、hfront-porch、hsync-len、hback-porch、vfront-porch、vsync-len、vback-porch这些是硬性参数照着填就行。麻烦的是 clock-frequency像素时钟有些 datasheet 给的是确切值有些只给你推荐刷新率需要你自己算。计算像素时钟有一个很实用的估算公式像素时钟 (hactive hfront-porch hsync-len hback-porch) x (vactive vfront-porch vsync-len vback-porch) x 刷新率比如 1280x800 的屏幕默认刷新率 60Hz典型的水平总像素是 14081280 40 48 40垂直总像素是 845800 13 3 29乘上 60Hz 后大约是 71.4MHz所以很多面板的 datasheet 上直接标 70MHz 就是这个原因。如果你填的像素时钟比实际要求低太多屏幕会明显刷新率不足、画面闪烁填高了可能出现花屏。这个参数宁可先从小的试起一步步往上加我的习惯是先按 datasheet 推荐值填然后用 modetest 验证刷新率再微调。如果你手头连 datasheet 都没有那就要靠板厂或者屏厂提供支持硬猜时序参数在嵌入式项目里基本是死路。我曾经在某个项目里因为屏厂给错了 hback-porch导致画面整体向右偏了三分之一屏这个方向排查起来极其痛苦后面会专门讲这个案例。3. 一路到多路的设备树实操与双屏配置3.1 单路 HDMI 点亮的完整参考配置先把最简单的一路 HDMI 配置跑通这是后续多路显示的地基。下面的设备树片段是我在一个 RK3568 项目里验证过的配置你直接对照你的硬件修改 pinctrl 和电源节点就行。display_subsystem { status okay; }; vopb { status okay; }; vopb_mmu { status okay; }; vp0 { rockchip,plane-mask (1 0) | (1 2); rockchip,primary-plane 0; rockchip,cluster-plane 2; }; hdmi { status okay; pinctrl-names default; pinctrl-0 hdmim0_tx0_cec hdmim0_tx0_scl hdmim0_tx0_sda hdmitx0_hpd; }; route_hdmi { status okay; connect vp0; };这套配置里最核心的就是 route_hdmi 节点里的 connect 属性它把 HDMI 接口接到了 vp0 上。如果你只有一个 HDMI 输出这样配完以后系统起来HDMI 显示器应该能直接点亮。不过要注意很多 RK3568 开发板的 HDMI 的 HPD 引脚和 CEC 引脚不是固定不变的可能分成 hdmim0、hdmim1 这两个复用组具体用哪一组要看原理图。我之前就吃过这个亏pinctrl 配错了导致 HDMI 始终检测不到外接显示器一度以为是驱动没编译进去。3.2 叠加第二路MIPI DSI/LVDS 的接入细节HDMI 单独点亮之后再开始叠加第二路。如果第二路是 MIPI DSI 屏需要在 dsi0或 dsi1节点下挂一个 panel 子节点并且把 route_mipi_dsi 指向另一个 vp比如 vp1。dsi0 { status okay; #address-cells 1; #size-cells 0; panel0 { compatible simple-panel; reg 0; backlight backlight; enable-gpios gpio0 RK_PB5 GPIO_ACTIVE_HIGH; reset-gpios gpio0 RK_PB6 GPIO_ACTIVE_LOW; pinctrl-names default; pinctrl-0 lcd_panel_enable; display-timings { native-mode timing0; timing0: timing0 { clock-frequency 70000000; hactive 1280; vactive 800; hback-porch 40; hfront-porch 40; hsync-len 48; vback-porch 29; vfront-porch 13; vsync-len 3; hsync-active 0; vsync-active 0; de-active 0; pixelclk-active 0; }; }; }; }; dsi0_in_vp1 { status okay; }; route_mipi_dsi { status okay; connect vp1; };这里有两个容易忽略的点。第一panel 节点的 enable-gpios 和 reset-gpios 必须和你实际硬件原理图一致特别是电平极性搞反了屏可能一直锁在复位状态背光亮了、画面死活不出来。第二dsi0_in_vp1 这个节点是接口和 vp 之间的连接节点它的 status 必须设为 ok否则即使 route_mipi_dsi 配了 connect vp1数据通路也没打通。我记得在 Rockchip 的某些内核版本里这个中间节点如果忘了开会出现 dmesg 里 DSI 接口已经 probe 成功、但 vp 上一直报“no connector”的错误排查起来非常迷惑。LVDS 屏的配置思路和 MIPI DSI 类似只是把 dsi0 节点替换成 lvds 节点panel 时序参数改为 LVDS 屏对应的参数同时注意 LVDS 是单通道还是双通道。双通道 LVDS 的配置里需要额外指定>
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

mise bootstrap packages brew untap 命令完全指南:从配置中移除 Homebrew Tap 2026/9/11 5:34:11

mise bootstrap packages brew untap 命令完全指南:从配置中移除 Homebrew Tap

mise bootstrap packages brew untap 命令完全指南:从配置中移除 Homebrew Tap 【免费下载链接】mise dev tools, env vars, task runner 项目地址: https://gitcode.com/GitHub_Trending/mi/mise 本指南围绕 mise 的 mise bootstrap packages brew untap 命…

阅读更多 →
基于原生NodeJS的Agent Memory实现与优化实践 2026/9/11 5:34:11

基于原生NodeJS的Agent Memory实现与优化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AI辅助遗留Java重构:安全迭代实战指南 2026/9/11 5:34:11

AI辅助遗留Java重构:安全迭代实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
2026国产实时计算平台选型指南:从Flink到湖仓管控全链路解析 2026/9/11 5:34:11

2026国产实时计算平台选型指南:从Flink到湖仓管控全链路解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Abaqus刚体建模:解析与离散刚体的选择与应用 2026/9/11 5:34:11

Abaqus刚体建模:解析与离散刚体的选择与应用

1. 解析刚体与离散刚体的基础概念在Abaqus有限元分析中,刚体(Rigid Body)是一种特殊的部件类型,它不会发生任何变形。刚体在仿真过程中保持形状不变,只有平移和旋转自由度。Abaqus提供了两种主要的刚体建模方式&#x…

阅读更多 →
pmap 命令详解:用 SerenityOS 的 pmap 剖析进程虚拟内存映射 2026/9/11 5:31:10

pmap 命令详解:用 SerenityOS 的 pmap 剖析进程虚拟内存映射

pmap 命令详解:用 SerenityOS 的 pmap 剖析进程虚拟内存映射 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 pmap 是 SerenityOS 提供的一个命令行实用工具&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞