近日,我们顺利完成了某头部金融终端平板与 OpenHarmony 的适配事情。此款平板能够通过拓展的办法连接各种外设,例如 HDMI 显示器。经由数月的努力,我们成功实现了这一新形态的适配,充分展现了酷派在开源鸿蒙领域所具备的创新能力,同时也为开源鸿蒙生态系统注入了专业运用。
本文基于的软硬件信息如下:
RK3588 OpenHarmony 4.0 + Linux 5.10

将着重先容eDP + DP转HDMI双显的适配过程。
RK3588 显示架构
在先容适配之前,让我们先来理解下RK3588的显示子系统,RK3588采取VOP 2.0设计,硬件架构如下图:
从上图可以看到,全体显示通路的末了端包含了由RGA,GPU和VPU组成的图形显示加速模块用来进⾏图像的⽣成和处理,个中RGA对图像进⾏缩放,旋转,合成等 2D 处理,GPU完成渲染,VPU进行高效视频解码,处理后的数据放到DDR中,然后由VOP(视频输出处理器)读取,根据运用须要进行相应处理后输出到对应的显⽰接口(如HDMI/DP等), 末了送到显⽰器或屏幕上。
VOP 2.0架构下只存在一个 VOP, 但是有多个独立的VP口,如上图有三路VP,可以实现三屏异显。而RK3588有四路VP,两个DP掌握器,如下图所示,只有VP0/1/2路可以输出到DP0/1。
平板显示连接
平板显示由两部分组成:一个是内置eDP屏,另一个是DP通过拓展连接到HDMI显示器,DP转接HDMI输出示意图如下:
本文紧张讲解的便是这种双屏显示场景的适配,底版本eDP单显输出正常。
双屏适配
DTS 配置
DP配置有两种模式:一个是type-c模式(DP Alt mode),另一个是非type-c模式(DP legacy mode)。我们这里适配的是DP legacy mode,利用的是第二个DP,在DTS里是dp1,使能配置如下:
&dp1 { status = "okay"; ......};
配置vp1连接dp1显示接口:
&vp1 { vp1_out_dp1: endpoint@3 { reg = <3>; remote-endpoint = <&dp1_in_vp1>; }; ......}
连接通路配置是dp1_in_vp1:
dp1_in_vp1: endpoint@1 { reg = <1>; remote-endpoint = <&vp1_out_dp1>; status = "okay";};
配置完成查看VOP状态,如下图VP1连接DP-2(也便是DTS的dp1), VP2连接eDP显示:
Linux 驱动移植
底版本内核DRM驱动有如下图红框处问题:
需移植三方驱动,在移植开始前,先理解下全体DRM的显示通路:
这里crtc是显示掌握器,对应VOP的video port,encoder/bridge卖力显示输出转换,终极通过connector送到显示屏幕上。
在对显示通路有了一个基本的认识后我们来移植DRM驱动,还包含一份phy,代码位于:
drivers/gpu/drm/rockchip/drivers/gpu/drm/bridge/analogix/drivers/gpu/drm/bridge/synopsys/drivers/phy/rockchip/
移植完成后有如下图红框处log表示DP连接成功:
也可以通过sys节点确认:
cat /sys/class/drm/card0-DP-2/statusconnected
此时HDMI仍未点亮,按照老例,我们利用modetest测试如下图表示内核驱动正常:
OH 屏幕管理
我们利用 hello_composer 来测试框架层是否正常。hello_composer 的测试内容很广泛,详细包括硬件显示接口后端、垂直同步系统、屏幕管理、输出管理等等。这个测试程序涵盖了从获取屏幕信息、创建图层、申请缓冲区、绘制内容、合成图层到终极显示的全体过程,因此它的正常运行能够验证全体图形显示管线的基本功能完全性。
经测试,hello_composer 可以正常事情。解释图形显示系统的核心功能链路是正常的。从底层硬件抽象到上层合成和显示,紧张模块都在正常事情。
但是还是涌现了两个屏幕都无法精确显示内容的情形。由于单个屏幕可以正常显示,问题发生在连接第二块屏幕之后,因此我们疑惑是 Render Service 中的多屏多窗口管理中的问题。
根据官方文档,Display Manager Server 紧张卖力 Display 管理,供应 Display 信息、屏幕截图、屏幕亮灭和亮度处理掌握,并处理 Display 与 Screen 映射关系。
在剖析屏幕初始化代码时,我们把稳到一个非常征象:系统能够获取到默认屏幕的screen id(值为2),但在abstractDisplayMap_中却找不到与之对应的项。解释屏幕初始化流程可能有点问题。
通过仔细研究代码,我们创造abstractDisplayMap_的更新紧张发生在BindAloneScreenLocked函数中,该函数常日由OnAbstractScreenConnect触发。然而,根据 hilog,OnAbstractScreenConnect彷佛只为后来添加的DP显示器调用了一次,而内置eDP屏幕则根本没有初始化。
eDP 屏幕未初始化导致了未能成功创建 default group。而正常情形下,初始化顺序该当是 eDP屏幕首先创建group,等后续 DP显示器添加时,会查找默认屏幕(eDP)对应的group。然而,当这个顺序颠倒时,DP显示器先创建group,之后eDP屏幕初始化时,就找不到与之对应的group,因此初始化失落败。这个顺序的颠倒阐明了为什么abstractDisplayMap_中短缺内置屏幕的信息。
RSScreen -> RSScreenManager -> HdiBackend -> HdiDevice -> HdiDeviceImpl -> DisplayComposerVdiImpl -> HdiSession -> DrmDisplay -> DrmDevice
通过研究屏幕信息从 DrmDevice 通报到 RSScreen 中的过程,我们深入探究了颠倒的缘故原由。终极创造可能和屏幕信息存储所利用的数据构造有关,C++ 供应的 unordered_map 只记录映射关系,并不担保顺序。在跨模块通报时,window manager 彷佛缺点的利用了屏幕信息,并把第一个遍历到的屏幕作为了默认屏幕。
终极,我们考虑了以下几个方向办理问题,实现了双屏同显。
•重新评估和调度屏幕初始化的顺序,确保eDP屏幕总是首先初始化。•在DP显示器初始化时,增加检讨机制,确保默认屏幕(eDP)已经精确初始化。•在关键点添加同步机制,确保屏幕和group的创建保持精确的顺序。
支持 DP 热插拔
我们以上所做的双屏适配事情并不包含热插拔内容,重新插拔会导致显示器无法正常事情。首先可以通过 hidumper 查看 rosen 管理的屏幕,确认 rosen 是否收到了热插拔屏幕的旗子暗记。
hdc shell hidumper -s RenderService -a screen
结果显示 rosen 并未管理新插入的 DP 屏幕。因此问题可能涌如今 HAL 层,Display 没有精确处理内核上报的热插拔事宜。
通过剖析代码,我们追踪了热插拔事宜的处理流程:
1.HdiNetLinkMonitor::MonitorThread 监听netlink2.ParseUeventMessage 解析吸收到的uevent3.HdiSession::HandleHotplug 处理热插拔事宜4.DrmDevice::HandleHotplug 在DRM设备层面处理热插拔5.DrmConnector::HandleHotplug 在连接器层面处理热插拔
uevent是Linux内核用于向用户空间报告设备状态变革的机制。当设备状态发生变革时,内核会天生uevent。这些通过netlink套接字通报给用户空间程序。Netlink是一种用于内核和用户空间进程间通信的分外套接字家族。
在剖析过程中,我创造了一个关键问题:Display HDF 只能处理 HDMI 热插拔事宜事宜,无法处理 DP 事宜。详细来说,ParseUeventMessage函数仅仅解析为"STATE=HDMI=0"(或"STATE=HDMI=1")的 uevent 事宜。这些字符串被写去世在代码中,导致系统无法精确识别和处理DP热插拔事宜。
此外,我们还创造了另一个影响系统稳定性的问题。在HdiNetLinkMonitor::MonitorThread函数中,如果没能成功从uevent中解析出DP状态,线程就会直接退出。这使得频繁热插拔测试中屏幕表现得极其不稳定。
在未来的事情中,我们可以考虑进一步优化热插拔处理流程,例如实现更繁芜的重试机制,或者支持多种多样的显示协议,如 VGA,eDP 等,使 OpenHarmony 更健壮。
结 语
在本次双显适配事情中,我们成功办理一系列问题,不仅包括底版本内核驱动存在的毛病,还有框架层不支持的显示接口以及热插拔场景等,这都有力地证明了我们在系统适配领域的能力。未来,我们会不断的探索和研讨,积极参与开源鸿蒙生态培植,通过实际行动推动硬件生态的发展。
[参考文档]
Rockchip3588 Linux SDK Docs
作者:TJ/LC
来源-微信公众年夜众号:酷派技能团队
出处:https://mp.weixin.qq.com/s/8cq-tFAkIj8aWDBnJFuQHw