ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

RK3568多屏独立旋转配置:DSI竖屏与HDMI横屏实践

RK3568多屏独立旋转配置:DSI竖屏与HDMI横屏实践 前阵子调一块RK3568开发板的多屏显示板载MIPI DSI接口的竖屏电容触摸屏另外通过HDMI接了一台普通横屏显示器。需求本身不复杂小屏跑竖屏界面外接大屏输出横屏内容两个屏幕各自转各自的互不影响。结果我在设备树里把DSI面板的时序改成720x1280竖屏之后HDMI外接出来的画面也跟着变成了竖的两边还一起画面撕裂折腾到半夜才把原理捋顺。这篇文章就是把这段排查过程整理成一份可复现的教程RK3568平台上DSI屏和HDMI屏的独立旋转配置到底该在哪一层做每一步怎么验证。内容基于RK3568平台和Linux内核的DRM/KMS显示框架原理部分对其他带多显示接口的瑞芯微平台同样适用。1. 旋转到底发生在哪一层为什么改panel时序会把HDMI带歪1.1 一条显示链路里发生的事在DRM/KMS的视角下RK3568的显示链路大致是VOP生成画面经过内部的VPVideo Port输出接到各接口控制器DSI、HDMI、DP等最后送到屏幕。DRM框架把这条链路抽象成几个角色CRTC对应VOP里的VP负责生成像素时序Connector对应DSI、HDMI这类物理输出接口Plane对应VOP里的图层画面内容最终要填入PlaneEncoder连接CRTC和Connector的中间环节负责把并行像素转成接口协议。旋转rotation在DRM里是Plane的属性不是Connector的属性。也就是说内核支持的旋转是对画面图层做旋转而不是对某个物理接口做旋转。理论上修改一个Plane的rotation不应该影响另一个物理接口的输出。那为什么我改DSI面板时序HDMI会被带歪问题就出在旋转和时序被混为一谈了。1.2 panel时序是物理方向图层旋转才是显示方向设备树panel节点里的display-timings描述的是面板本身的物理时序。hactive和vactive就是面板的固有分辨率。如果面板物理规格就是720x1280竖屏把这段时序写对DSI输出就是竖屏——这是天生就是竖的。如果面板物理是1280x720横屏你想让它竖着显示就需要靠Plane的rotation属性或者上层合成器如Weston的transform来做旋转——这是后天转出来的。问题恰恰出在这两层容易混淆。我在设备树里直接改display-timings后DSI的竖屏时序是生效了但由于BSP默认的route配置里DSI和HDMI都绑在同一个VP上HDMI输出复用了同一个CRTC的时钟和模式解析逻辑导致HDMI那边也跟着用竖屏时序去驱动横屏显示器画面自然就不正常了。更隐蔽的情况是有些BSP的中间层代码在probe时发现panel宽高比是竖屏后会偷偷把整个CRTC的旋转基准改了结果所有挂在这个CRTC下的输出全被带着旋转。这种问题在单屏场景下看不出来一上多屏就暴露。1.3 为什么RK3568能独立旋转两个VP带来的自由度RK3568有两个VOP每个VOP内部又有多个VP。DSI和HDMI如果各自挂到不同的VP上两路的时序、时钟、Plane资源就完全独立。硬件上完全具备DSI转90度、HDMI不转的条件。反过来如果两路强行挤在同一个VP下又没有做特殊的克隆clone处理那就必然出现改一路、带偏另一路的后果。所以RK3568多屏独立旋转配置的第一步不是写旋转参数而是先确认两路输出的VP分配是不是已经分开。这个结论也解释了一个常见误区有人以为多屏显示只要在应用层把两个窗口放好就行但实际上底层的VP/CRTC分配不对应用层怎么旋转都是白搭。2. 上线前的摸底确认设备树、驱动和DRM显示资源的现状动手改配置之前先花十分钟确认三件事设备树里DSI和HDMI的route是怎么写的、内核认了几个Plane、每个Plane的rotation支持哪些值。这三件事确认完后面基本不会走弯路。2.1 在设备树里找到DSI和HDMI的routeBSP源码路径一般在arch/arm64/boot/dts/rockchip/下的板级dts里。搜索一下grep -n dsi0\|dsi1\|route_dsi\|hdmi\|route_hdmi arch/arm64/boot/dts/rockchip/rk3568-evb.dts重点看route节点的connect字段它决定这个接口最终绑定到哪个VProute_dsi0 { status okay; connect vp0; }; route_hdmi { status okay; connect vp0; };这种两个都绑vp0的写法想让两路独立旋转就是给自己挖坑。后面第3章会说具体怎么拆开。2.2 用modetest摸清Plane的rotation能力在开发板串口或ssh终端里执行modetest -M rockchip -p modetest -M rockchip -c-p会打印所有Plane及其属性重点看每个Plane的rotation属性支持哪些值。不同内核版本、不同BSP的打印差异很大有的打印成枚举enums: 0Rotate 0, 1Rotate 90, 2Rotate 180, 3Rotate 270设置时就按0/1/2/3写有的打印成bitmaskvalues: Rotate 00x1, Rotate 900x2, Rotate 1800x4, Rotate 2700x8那就要按bit位写90度对应2。别硬背固定值一切以modetest打印为准。还要确认rotation能力是在Primary Plane上还是在CURSOR Plane上。RK3568的BSP里通常主Plane支持旋转Cursor不一定支持驱动不支持时设置会直接报错或静默忽略。2.3 记录两路默认状态避免改完回不去modetest -c能看到Connector的连接状态HDMI有没有插线、EDID有没有读出来、DSI panel是否ready。改配置之前把dmesg | grep -i vop\|dsi\|hdmi的结果保存一份。设备树改错可能导致HDMI直接不probe有个基线日志对照会好排查很多。还有一个容易被忽略的点确认当前软件跑的是扩展模式extend还是克隆模式clone。如果两屏做的是克隆它们共享同一个CRTC天然无法独立旋转要独立旋转显示策略必须是扩展模式或者每个输出走各自的CRTC。3. 设备树里固定方向DSI竖屏、HDMI横屏各走各的如果产品形态固定比如小屏永远竖屏、大屏永远横屏最省心、最稳定的做法是在设备树里把两路的物理方向和VP分配一次定死。这步做对了进入系统以后不需要额外旋转也不存在两个屏幕互相抢资源的问题。3.1 DSI面板的display-timings按竖屏写先把DSI的panel时序改成720x1280竖屏dsi0 { status okay; panel0 { compatible simple-panel-dsi; reg 0; enable-gpios gpio3 RK_PC4 GPIO_ACTIVE_HIGH; reset-gpios gpio3 RK_PC5 GPIO_ACTIVE_LOW; backlight backlight; display-timings { native-mode timing0; timing0: timing0 { clock-frequency 60000000; hactive 720; vactive 1280; hback-porch 60; hfront-porch 60; hsync-len 20; vback-porch 15; vfront-porch 15; vsync-len 5; hsync-active 0; vsync-active 0; de-active 0; pixelclk-active 0; }; }; }; };这里的hactive和vactive就是物理方向的关键。porch、clock-frequency这类参数必须从面板手册里查每个型号都不一样不要照抄示例值。写错porch最常见的现象是画面偏、闪甚至完全点不亮。3.2 把HDMI的route拆到另一个VP接着改route。关键点是确保两路不再挤同一个VProute_dsi0 { status okay; connect vp0; }; route_hdmi { status okay; connect vp1; };VP怎么分配不是随便定的。RK3568的VOP0和VOP1能接的输出接口有硬件限制某个接口只能绑到特定VP具体要看芯片手册和BSP默认dtsi里的注释。如果绑错很可能出现HDMI完全没有信号或者probe直接失败。改完重新编译dtb烧录后重启。3.3 重启后怎么快速验证方向重启之后先看日志dmesg | grep -i vop\|dsi\|hdmi重点看两路分别挂在哪个VP上有没有报资源冲突。然后分别给两个屏幕显示同一张带方向标识的测试图确认DSI是竖的、HDMI是横的。这里有一个产品形态的判断如果面板物理规格已经是竖屏720x1280那第3.1节这种改法就对了如果面板物理是横屏1280x720只是想让UI以竖屏呈现那就不要改display-timings而应该在用户空间的合成器里做旋转。设备树里强行改timing会把显示驱动对面板的认知搞歪后续触摸映射、休眠唤醒都会跟着出问题。有部分BSP的VOP驱动实现了对rotation属性的解析可以在route或plane节点加rotation 90试试但我实际用的几个内核版本并不吃这个属性所以更推荐在用户空间用Weston的transform去固化方向。4. 运行时独立旋转modetest、xrandr、Weston三种打法设备树方案适合出厂就定死的产品。如果产品需要在设置里允许用户切换横竖屏或者你只是临时调试就得靠这一章的运行时方案。4.1 最底层modetest直接改Plane rotation先用modetest查出Connector ID和Primary Plane IDmodetest -M rockchip -c modetest -M rockchip -p假设DSI对应的Connector ID是100Primary Plane ID是98要把它旋转90度按modetest枚举值写modetest -M rockchip -w 98:rotation:1或者按bitmask写modetest -M rockchip -w 98:rotation:2到底用哪个值看modetest -p输出里rotation属性旁边写的enums或者values。我见过同是RK3568的平台不同内核版本打印的枚举规则就不一样照搬网上的命令没有意义。注意modetest -w改的是单个Plane。如果你的UI有多个图层需要把主图层对应的Plane也一起改。另外旋转会明显增加VOP带宽占用改完如果画面花掉说明VP带宽或内存带宽不够处理方法在第6章展开。4.2 桌面环境xrandr一条命令的事如果系统跑的是X server DRM后端xrandr --output DSI-1 --rotate left xrandr --output DSI-1 --rotate right xrandr --output DSI-1 --rotate inverted xrandr --output DSI-1 --rotate normalxrandr --rotate背后走的也是Plane rotation属性但X server会自己处理多图层开发者不用关心具体是哪个Plane。前提是X server起来之后才生效适合交互调试不适合做开机即用的产品配置。4.3 产品化配置Weston的transform嵌入式Linux现在很多用Wayland/Weston。Weston的配置文件通常在/etc/xdg/weston/weston.ini或启动参数里指定。给DSI这一路加旋转[output] nameDSI-1 mode720x1280 transformrotate-90name对应modetest -c看到的Connector名字不要想当然写成DSI-1先用modetest -c确认。transform可选normal、rotate-90、rotate-180、rotate-270、flipped等。Weston的transform会让合成器在输出前完成旋转相当于对整个输出画面统一做变换比单独改Plane更省心而且触摸事件映射Weston也会自动跟着转。产品上我一般优先用这种方式固化方向。三种方式的适用场景对比如下方式生效层级适用场景注意点modetest -wDRM Plane调试验证多Plane要分别设置重启失效xrandr --rotateX server桌面交互调试依赖X server不适合无桌面产品weston.ini transformWayland合成器产品交付固化需要确认Connector name和触摸联动5. 屏幕转了触摸没跟上双屏坐标映射的独立处理旋转配置最容易翻车的还不是显示是触摸。屏幕转了90度触摸坐标如果不跟着转换UI上的按钮就永远点不对。这个问题的本质是触摸屏上报的是传感器物理坐标和设备树里panel的原生方向一致旋转显示方向只是把画面转过去了触摸控制器并不会自动知道。5.1 触摸坐标系为什么和显示坐标系脱节从用户角度看本来左上角的按钮显示旋转后跑到右上角了但触摸的物理坐标还认为那里是左上角。于是点上去没有反应反而点别处触发了按钮。处理这个问题的思路有两种一是在输入校准层做坐标变换二是在设备树/驱动层把触摸坐标系的轴和面板原生方向对齐。具体用哪种取决于你的触摸驱
返回列表