做RK3568方案的朋友应该都遇到过这种需求设备上挂了一块MIPI DSI竖屏比如720x1280用来做交互面板旁边又接了一台HDMI显示器做横向大屏展示。麻烦的是两块屏往往共用一个显示子系统改竖屏的时候一不小心就把HDMI也带歪了或者反过来HDMI配置一改DSI整屏花掉。我先后在好几款基于RK3568的板卡上踩过这套多屏显示的坑最后把手上的方案稳定成了“DSI竖屏、HDMI横屏、互不干扰”的状态。这篇文章把这套独立旋转配置的完整思路和实操过程记录下来包括设备树怎么写、DRM旋转和面板旋转的区别、U-Boot启动Logo怎么同步以及最容易被忽略的触摸坐标问题。适合正在做广告机、闸机、自助终端、收银双屏设备的工程师参考也适合第一次接触RK3568多屏显示、看设备树看得一头雾水的新手。1. 为什么多屏独立旋转会被当成“麻烦事”1.1 双屏终端里藏着什么样的需求从实际项目看RK3568做双屏设备非常常见尤其是商显和工业终端领域。典型形态是一块MIPI DSI接口的竖屏做操作面板操作界面竖着排布另一块HDMI接口的标准显示器做内容展示画面必须保持横向。两个屏幕各干各的谁都不能将就对方。这里有个容易被忽略的点旋转需求不只是“显示画面转90度”这么简单。用户期望的是——开机Logo方向正确、内核日志控制台方向正确、桌面界面方向正确、触摸坐标方向正确而且这些动作只影响DSI这条链路HDMI全程不参与任何旋转。只要其中一个环节没对齐交付给客户的产品就会被判定为“没做完”。很多开发者拿到板子第一件事改设备树把整个显示链路方向的属性翻了个遍结果是DSI竖了HDMI也跟着竖了或者LED背光正常但画面只显示一半。这些问题背后不全是粗心更多是对“旋转到底发生在哪一层”没有完整认知。1.2 旋转的本质前后端方向的匹配问题把旋转拆开看本质上是三个方向需要对齐面板固有方向、显示控制器扫描方向、应用层绘制方向。面板固有方向指的是屏本身出厂时默认从哪个边开始扫描这个方向由模组厂商定义一般写在规格书里。显示控制器扫描方向由VOPVideo Output Processor控制RC和RK系列平台上VOP输出时可以对每一条通路做变换。应用层绘制方向则是UI最终呈现给用户的画面方向由桌面系统或合成器决定。当一个屏幕出现“画面倒着、UI方向对不上触摸”这类情况时绝大多数是因为这三个方向没有解耦有人直接给整个显示子系统加了一刀切的旋转。而RK3568之所以能做独立旋转是因为它的显示子系统天然支持“按通路隔离配置”每个VPVideo Port视频端口独立工作VOP2里每个VP又能单独绑定不同的输出接口。只要理解了这条链路再回头看各种旋转配置就能明白哪些属性影响全局、哪些属性只影响单块屏也就不会再被设备树里的几十个节点带偏。2. RK3568显示栈拆解VOP2、VP和连接器是怎么协作的2.1 VOP2 与 VP谁在负责画面输出RK3568内部的核心显示模块是VOP2Video Output Processor 2它负责从内存里取帧、做缩放与旋转处理、最后把画面送往外设接口。VOP2内部有多个VP也就是视频输出通路。每个VP可以理解成一个独立的显示通道有自己的一套平面Plane、缩放器和时序生成逻辑。RK3568上常见的VP数量是3个VP0、VP1、VP2具体多少个由芯片版本和内核配置决定。每个VP可以独立选择要接到哪个外部接口上比如VP0接DSI0、VP1接HDMI、VP2接eDP或LVDS。正因为VP之间物理隔离DP、HDMI、DSI、eDP这些接口才能在同一个系统里同时工作而不互相打架。这也就是多屏旋转能够“独立”的硬件基础旋转是发生在每个VP对应的处理链路里的而不是整个显示子系统统一切一刀。只要在设备树里把VP和显示接口的对应关系绑对独立旋转就有了底层保障。2.2 DSI和HDMI在RK3568上各自走哪条链路在RK3568的设备树里你通常会看到类似route_dsi0、route_hdmi这样的节点它们就是显示路由节点职责是把某个VP和具体接口连接起来。DSI接口通过MIPI DSI协议把视频信号送给LCD模组HDMI则通过HDMI PHY把信号输出给标准显示器。DSI和HDMI的数据格式、时钟策略完全不一样。DSI屏幕通常要求固定的单通道参数竖屏的720x128060Hz与横屏的1920x108060Hz在像素时钟、MIPI带宽上差异很大HDMI则遵循标准时序支持分辨率协商和热插拔检测。这意味着“旋转配置”不能只关心画面方向还得考虑分辨率、刷新率、带宽这些约束条件。我在实际项目中画过这样一张链路表VP0绑定DSI0连接MIPI竖屏默认720x1280VP1绑定HDMI连接普通显示器默认1920x1080。两个VP各自拥有独立的显示时序所以在显示控制这一层它们天然是解耦的。而大多数配置错误恰恰出在“没有显式指定VP绑定关系”导致内核把多个接口自动分配到同一个VP上旋转一个屏幕另一个也跟着变了。2.3 旋转能设在哪几层连接器、平面还是合成器这是整篇教程最关键的概念先把这个理清楚后面配置时才知道该动哪里。连接器层Connector面板的方向属性drm_panel_orientation属于连接器层代表“这块屏幕在物理上应该怎么摆放”。如果硬件上规定面板默认是竖屏那么连接器旋转和触摸坐标联动就发生在这一层。平面层PlaneDRM框架里平面Plane是真正被显示控制器用来扫描内存内容的单元。平面层支持旋转时意味着可以在扫描时直接把帧内容旋转后再显示出来对应DRM属性里的rotation。合成器层Compositor也就是应用层Wayland/Weston、Android SurfaceFlinger或者LiteOS/裸机UI栈都会在最终合成时做旋转。这一层的旋转对内核透明通常不改变显示时序只改变界面绘制方向。很多方案只改了其中一层比如设备树里加了个旋转属性但UI合成器还在按照横屏布局或者SurfaceFlinger设置了旋转但内核连接器方向没变导致触摸坐标错位。真正稳定可靠的独立旋转配置必须明确哪个屏幕走哪一层进行旋转并在最终效果上保持一致。3. 方案选型旋转到底应该由谁来执行3.1 内核级旋转在设备树里改panel的rotation如果你希望开机Logo、内核启动文字、控制台输出都跟着旋转那就必须在内核级完成。在DRM的panel-simple框架下面板设备的设备树节点里可以声明rotation属性用来描述面板相对于显示控制器的默认扫描方向。RK系列内核经常还会看到rockchip,rotate、rockchip,rotate-90、rockchip,rotate-180这类厂商扩展属性具体认哪个由内核里实际的panel驱动决定。内核级旋转的优点是“一劳永逸”整个显示栈从上到下都感知到这块屏是旋转过的FB控制台、开机Logo、DRM应用都会以旋转后的方向工作UI层不需要额外改任何代码。缺点也很明显它是静态的一旦编译进设备树想再切成横屏必须改动重启。3.2 应用级旋转DRM Plane 与合成器一侧的路由应用级旋转指的是通过DRM的plane属性或合成器旋转实现动态翻转。比如Weston里的输出旋转、Android里的取消自动旋转、或者直接调用modetest给plane设置rotation属性。这种方式的场景价值在于同一块屏幕可能某些界面需要竖屏操作某些场景需要横屏展示。通过合成器切换不用修改内核运行时就能旋转。同时如果内核里的面板链接器方向设置正确应用级旋转可以只旋转内容不改变触摸坐标的基准方向两者配合起来比一刀切内核属性要灵活得多。不过应用级旋转也有局限启动Logo和FB控制台不受它控制在这之前画面方向依然由内核和U-Boot决定。另外如果合成器不支持旋转或依赖GPU去转性能开销会明显放大对RK3568这类定位中端的SoC来说能走硬件旋转尽量走硬件。3.3 我的选择固定方向用内核动态切换用应用但两者必须分开结合多种RK3568项目的经验我的方案是DSI竖屏作为固定交互屏方向恒定直接在内核级加旋转保证开机到后台全链路方向一致HDMI横屏作为内容展示屏方向本身就是横的走默认配置不需要旋转由VP绑定关系实现链路隔离。这样做的理由有三个。第一交互屏对“开机方向”非常敏感不可能让客户每次冷启动都看到一屏横着的Logo等系统起来后才变竖第二HDMI长期接横向显示器不参与任何旋转逻辑避免在HDMI链路上引入多余变换减少带宽和延迟开销第三两块屏分别占用独立VP互不共享扫描链路改一块就不会影响另一块。4. 实操设备树配置DSI与HDMI独立旋转4.1 第一步确认当前显示拓扑与VP绑定情况配置前先别急着改先弄清楚现在板子上的实际拓扑。最直接的办法是在RK3568开发板上进入系统后跑一遍modetestmodetest -M rockchip -p从输出里能看到连接器列表和当前模式重点看几个信息有没有DSI连接器它是connected还是disconnected有没有HDMI连接器对应的mode列表是哪些encoder和CRTC的绑定关系尤其要看DSI和HDMI分别被安排到了哪个CRTC/VP上。我的一台设备上输出大致是这个形态Connectors: id encoder status name size (mm) modes encoders 13 12 connected DSI-1 69x122 ... 12 16 15 connected HDMI-A-1 698x392 ... 15看到名字能对上你外接的两块屏就算关系明确。如果这里DSI和HDMI都接到了同一个CRTC上说明VP绑定没有设好后面改旋转大概率会互相影响这是整个配置过程中最重要的排查点。4.2 第二步改动设备树把DSI和HDMI绑定到不同VP确认拓扑之后接下来修改设备树。以RK3568比较典型的SDK为例打开你的设备树主文件重点关注dsi0、route_dsi0、hdmi、route_hdmi这几个节点。下面是一个参考写法dsi0 { status okay; panel0 { compatible your_lcd_vendor,720x1280; reg 0; rockchip,rotate 90; // 厂商内核常用扩展属性按需配置 // 如果在你内核对应的panel驱动里认标准rotation属性 // 也可以写成 rotation 90; 具体以驱动源码为准 backlight backlight_lcd; power-supply vcc3v3_lcd; reset-gpios gpio3 RK_PD1 GPIO_ACTIVE_LOW; port { panel_in_dsi0: endpoint { remote-endpoint dsi0_out_panel; }; }; }; }; route_dsi0 { status okay; connect vp0; // 确保DSI走VP0 }; hdmi { status okay; }; route_hdmi { status okay; connect vp1; // 确保HDMI走VP1与DSI隔离 };这里最核心的就是connect vp0和connect vp1。这样写的意图很明确让DSI和HDMI分别占据独立VP内核在计算显示通路时就不会把两个接口挤到一个VP上。接着在DSI面板节点里加上旋转属性由于旋转作用于DSI对应的panel/connector而HDMI走的是另一条VP链路所以HDMI天然不受影响。需要特别留意的是RK各个SDK版本的属性名并不完全一致。有的5.10内核分支里标准panel驱动用rotation有的RK定制内核则读取rockchip,rotate。动手前先确认驱动源码里到底用的哪个字段名不然属性写了不生效还容易以为自己配置错了。最快的方法是在内核目录里搜一下rockchip,rotate和rotation的of_property读取位置grep -rn rockchip,rotate drivers/gpu/drm/rockchip/ grep -rn rotation drivers/gpu/drm/panel/4.3 第三步确认内核配置项重新编译dtb与boot镜像设备树改完后还需要确认内核打开了对应的DRM显示驱动。RK3568的显示相关配置一般在CONFIG_DRM_ROCKCHIP、CONFIG_DRM_DW_HDMI、CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI这些开关下面。你可以在板子的内核menuconfig里搜一搜确保没有把MIPI DSI或HDMI的编解码驱动漏掉。配置完毕后编译通常只需要重编内核并生成新的boot.img不需要每次都在文件系统上折腾make ARCHarm64 rk3568_defconfig make ARCHarm64 dtbs make ARCHarm64 boot.img烧录后先确认系统一启动DSI屏就是竖的HDMI屏保持横的再做后面的事。这里有一个小技巧烧录后先别急着接DSI屏单独接HDMI看是否正常先确认基础显示链路没被我改坏再同时接两块屏验证隔离效果。这样可以快速区分“配置把HDMI带偏了”和“HDMI本身硬件异常”两种情况。4.4 第四步同步U-Boot避免开机Logo方向不一致这一步是很多项目最容易漏的地方。如果系统启动后Kernel起来之前有一段时间显示的是U-Boot Logo你会发现内核配置好的竖屏方向只在内核起来后生效开机Logo依然横着。原因在于U-Boot阶段也有自己的一套显示初始化逻辑和面板参数它不读Kernel的完整设备树只读U-Boot阶段需要的那些节点。所以设备树里DSI屏幕的旋转配置必须同步改到U-Boot的dts里。RK平台的U-Boot源码目录里通常会放一套专门给U-Boot用的dts路径和Kernel的不一样需要找到对应板卡的rk3568-evb.dts这类文件同样给panel节点加上旋转字段并重新编译U-Boot镜像烧录。同步之后冷启动全程看到的Logo方向才会一致。4.5 第五步触摸坐标联动调整屏幕物理方向变了触摸坐标基准必须跟着变否则“竖屏显示、横屏触摸”会让你怀疑设备坏了。RK3568方案里触摸屏用的比较多的GT9xx系列设备树里就有坐标变换相关属性。比如触控芯片节点里常见的i2c4 { gt9xx14 { compatible goodix,gt911; reg 0x14; touchscreen-inverted-x 0; touchscreen-inverted-y 0; touchscreen-swapped-x-y 0; }; };如果屏幕旋转了90度那touchscreen-swapped-x-y通常要变成1可能还要调整inverted方向。至于具体哪几个组合取决于面板旋转方向与触控IC扫描方向的相对关系。最靠谱的办法是烧录后逐个组合测试在调试阶段不要一次同时改多个字段改一次测一次确定好方向后再固化到设备树里。如果用的是Android系统还要注意SurfaceFlinger侧的显示方向。有些方案里设备树已经旋转了面板但系统界面仍按横屏布局绘制这多数是在framework层旋转了最终合成画面与内核旋转叠加造成二次旋转。调试思路是先在内核层确认最终看板画面方向正确再调整系统层的persist.sys.display.rotation之类的配置让它和内核方向保持一致。5. 常见问题与排查技巧实录5.1 问题速查表为了方便快速定位我把碰过的问题整理成了下面这张速查表。现象最可能的原因定位方式处理建议改完DSI后HDMI跟着旋转VP绑定冲突两个接口被分配到同一个VP检查route节点里的connect属性用modetest确认CRTC把DSI和HDMI分别绑定到VP0和VP1之类的独立VP开机Logo方向不对只改了Kernel dts没同步U-Boot dts观察Logo阶段与内核阶段的差异同步修改U-Boot dts后重编U-Boot镜像fbcon控制台方向与桌面不一致内核面板旋转和fbcon旋转配置冲突检查内核cmdline里的fbcon参数统一使用同一套旋转语义别同时刻意混用两种机制触摸点击位置错乱只在显示层旋转没同步触摸坐标变换用触摸屏坐标自测工具画圆、点角改设备树inverted/swapped字段逐项验证竖屏分辨率跑不满/出花屏MIPI DSI带宽或像素时钟配置不足dmesg看mipi dsi初始化日志测数据率根据面板规格重新计算lane数和clock必要时调整lane-rate系统起来后DSI黑屏panel节点rotation属性没被驱动识别搜索内核驱动里对应的属性名确认内核分支用的字段名改为实际支持的写法5.2 典型问题一DSI一旋转HDMI也跟着歪这个问题基本可以断定是两个显示通路的路由没有隔离干净。RK3568的显示子系统里多个接口到底哪几个共用同一个VP并不完全靠“猜”而是看设备树里route节点到底怎么connect的。如果route_dsi0和route_hdmi都指向同一个VP那么内核把DSI的扫描方向旋转变换一应用HDMI作为同一个VP上的另一个输出自然跟着歪。这种情况下不要局限于Panel驱动先回去检查设备树。把两个route的connect分别指向不同VP后再执行前面说的modetest确认CRTC编号才能从根本解决。5.3 典型问题二MIPI DSI带宽不够旋转后花屏旋转本身不增加带宽需求但它往往会暴露之前被掩盖的时序问题。一个720x1280的24bit RGB屏跑60Hz按像素时钟估算有效像素时钟约为 720 x 1280 x 60 ≈ 55.3MHz加上行场消隐后实际像素时钟通常在 70~90MHz 左右MIPI DSI的链路带宽按 4-lane计算最低每lane速率约为 pixel_clock x 24 / 4算出来的每一lane数据率如果在DSI接口的合理范围内常见1Gbps左右那大概率是时序配置问题。但如果硬件只用了2-lane并且每lane速率被顶到非常高面板就会在刷新时出现随机条纹或整条花屏。旋转后花屏的本质不是“转坏了”而是原来横屏分辨率下还算“富裕”的带宽在竖屏大尺寸扫描或时序切换后变成临界状态。遇到这类问题我一般先把旋转去掉恢复横屏确认画面稳定再重新引入旋转并逐帧监测dmesg。不要一上来就怀疑旋转代码MIPI物理层和clock配置才是首要排查对象。6. 工程细节里的小提醒这章再分享几个实际项目中容易踩到的工程细节虽然不是“大问题”但处理不好非常耽误时间。板级调试的时候不要图省事只改Kernel设备树U-Boot、内核和触摸驱动这三处必须当成一个整体来管理。任何一处方向配置不一致最终用户看到的就是开机方向变来变去。我在多个项目中总结出的经验是先确定面板物理方向再统一写入三份配置最后用同一份烧录包做整机验证绝不挨个单独试。设备树里的旋转属性最好在内核源码里确认驱动读取位置后使用。不同内核分支对属性的支持并不统一RK官方的SDK跟主干Linux在显示驱动上存在分化使用rockchip,rotate还是标准rotation取决于实际使用的内核版本。搜索驱动源码里of_property读取的是哪个字段比在论坛里东问西问高效得多。画面方向验证时建议做“全屏色块方向判断”组合验证。开机后先显示一个带方向信息的画面比如左上角明确标注“TOP”字样的测试图确认物理方向再用手写笔写几个大字确认触摸坐标方向和旋转状态一致最后切换HDMI内容确认DSI的旋转没有对另一块屏幕造成任何影响。三步走完基本可以判定配置正确。在联调时如果发现HDMI热插拔后DSI画面闪烁别急着怀疑旋转配置。这种情况通常是两个VP共用的系统内存带宽或者时钟域出现了竞争优先检查内存调度和DCLK配置RGBA/RGB格式换算也值得确认。旋转和这些带宽问题常常只是“同时出现”而不是“因果关系”。做多屏独立旋转的核心思路其实不复杂利用RK3568多VP的物理隔离把DSI和HDMI分别绑定到不同VP上再在需要旋转的那条链路上单独配置方向属性并保证U-Boot、内核、触摸坐标全链路一致。这套方法论不局限于DSI和HDMI换成eDP加DSI、LVDS加HDMI同样适用区别只是换一组route节点和panel驱动。下次遇到类似需求可以先在modetest里确认拓扑再“绑定VP—配置rotation—同步触摸—验证方向”四步走问题基本能控制住。