1. i.MX显示子系统全景

在i.MX平台上做DRM/KMS开发,第一件容易踩坑的事,是把"显示控制器"当成一个统一的东西。实际上,i.MX历代SoC的显示子系统由多个职责不同的硬件模块拼装而成:有的负责把像素按时序推出去,有的负责图层合成,有的负责把图像缩放、旋转、格式转换,还有的专门做显示内容的读取与重排。DRM/KMS只是Linux内核里的一套软件抽象,它把这些硬件能力包装成CRTC、Plane、Encoder、Connector等对象,但软件抽象与硬件拓扑并不是一一对应的。理解这一点,才能判断某个功能到底该由哪个模块承担、驱动里该走哪条通路。

一、显示子系统的三类角色

把i.MX显示相关的硬件按职责分成三类,思路会清晰很多。

第一类是显示控制器(Display Controller),它直接产生并行RGB或MIPI DSI等时序信号,决定分辨率、刷新率、消隐区、像素时钟。i.MX6系列的eLCDIF、i.MX7ULP的LCDIF、i.MX8M系列的LCDIFv3都属于这一类。它们通常支持一到两个图层,能直接扫描framebuffer输出,结构简单、延迟低,适合单图层或简单叠加的场景。

第二类是显示处理单元(Display Processing Unit),代表是i.MX8QM/8QXP上的DPU和i.MX8M Plus上的DCSS。它们不再是"一个控制器",而是由多个可编程的显示引擎(Display Engine)、提取单元(Extraction Unit)、混合单元(Blend Unit)、定时发生器(Timing Generator)组成的合成流水线。DPU可以同时驱动多路显示,每路支持多个图层,图层之间做alpha混合、色彩空间转换、位置缩放。DCSS则更偏向单路高分辨率输出,内部有Fetch Unit、Layer Blend、Display Engine等模块。这类硬件的DRM驱动通常把每个Display Engine映射成一个CRTC,把每个图层映射成一个Plane。

第三类是图像处理与显示辅助模块,包括PXP、PRG、DPR。PXP(Pixel Pipeline)是i.MX6/7上常见的2D加速器,能做缩放、旋转、色彩空间转换、alpha混合,常被用来把摄像头或GPU的输出加工后送给LCDIF。PRG(Prefetch Resolve Gasket)和DPR(Display Prefetch Resolve)是i.MX8M系列里配合LCDIFv3/DCSS使用的预取与重排模块,它们把分散在内存中的、非连续的图层数据预取并重排成显示控制器能高效读取的连续流,解决高分辨率、多图层下的带宽和延迟问题。

i.MX 显示子系统硬件拓扑与数据通路 内存 / 数据源 Framebuffer (DRM GEM) Camera / VPU 输出 GPU 渲染结果 PXP 缩放 / 旋转 / CSC Alpha 混合 格式转换 PRG / DPR 预取 Prefetch 地址重排 Resolve 带宽优化 LCDIF / LCDIFv3 单/双图层扫描 并行 RGB / MIPI DSI 像素时钟 / 时序生成 i.MX6 / 7 / 8M DPU 多 Display Engine 多图层 Blend Unit 多路显示输出 i.MX8QM / 8QXP DCSS Fetch Unit Layer Blend Display Engine i.MX8M Plus 显示输出接口 并行 RGB · MIPI DSI · LVDS · HDMI · DisplayPort DRM/KMS CRTC ← 控制器 Plane ← 图层 Encoder ← 接口 Connector ← 面板 图例 数据源 图像处理 预取重排

二、数据通路怎么走

以i.MX8M Plus为例,一条典型的高分辨率显示通路是:应用通过DRM把多个图层提交到内核,GEM对象驻留在DDR中;DCSS的Fetch Unit从内存读取图层数据,如果图层是压缩或非连续的,PRG/DPR会先做预取和地址重排,把数据整理成DCSS能连续读取的格式;DCSS内部完成图层混合、色彩空间转换,再由Display Engine产生时序,通过MIPI DSI或HDMI输出到面板。这条通路里,DRM的Plane对应DCSS的图层,CRTC对应Display Engine,Encoder对应DSI/HDMI控制器,Connector对应面板。

而在i.MX6上,通路更短:应用提交framebuffer,eLCDIF直接扫描输出。如果要做缩放或旋转,就得先把数据交给PXP处理,PXP输出到另一块framebuffer,再让LCDIF扫描。这就是为什么在i.MX6上做视频播放时,常常看到"PXP + LCDIF"的组合,而不是让LCDIF自己缩放——LCDIF本身不具备缩放能力。

i.MX8QM/8QXP的DPU则更接近现代显示处理器:它内部有多个Display Engine,每个Engine可以独立驱动一路显示,每路支持多个图层,图层可以在Blend Unit里做alpha混合和位置调整。DPU还支持通过DPR/PRG做预取,但DPU的图层管理比DCSS更复杂,驱动里的Plane数量也更多。

三、DRM/KMS在i.MX上的定位与边界

DRM/KMS是软件层,它不改变硬件能力,只负责把硬件能力暴露给用户空间。在i.MX上,KMS驱动要做的事包括:枚举显示控制器和接口、创建CRTC/Plane/Encoder/Connector、管理framebuffer和GEM对象、处理原子提交(atomic commit)、配置时序和格式。但KMS不能做硬件不支持的事。比如,如果LCDIF只有两个图层,KMS就不能凭空变出第三个硬件图层;如果DCSS不支持某种像素格式,KMS提交时就会返回-EINVAL。

边界还体现在内存带宽和延迟上。高分辨率多图层场景下,如果PRG/DPR没有正确配置,DCSS可能因为读取不及时而underflow,表现为屏幕闪烁或花屏。这时问题不在DRM的原子提交逻辑,而在硬件预取通路。理解这一点,排障时就不会只盯着DRM驱动看。

在i.MX8M Plus上,DCSS的Fetch Unit和PRG/DPR是紧耦合的。如果设备树里没有正确描述PRG/DPR的寄存器区域和中断,DCSS驱动可能仍然能probe,但高负载下会出现显示异常。建议在板级调试时,先用modetest验证单图层输出,再逐步叠加图层,观察是否触发underflow。

四、实际开发中的判断依据

拿到一块i.MX板子,先确认三件事:SoC型号决定显示控制器类型(LCDIF/DPU/DCSS),设备树决定哪些显示通路被使能,DRM驱动决定KMS对象怎么映射。比如,i.MX8M Plus的DCSS在设备树里通常有display-subsystem节点,下面挂dcss、prg、dpr等子节点;而i.MX6的LCDIF则是一个简单的lcdif节点。

调试时,可以用modetest -M imx-dcss或modetest -M imx-drm查看当前KMS对象。如果Plane数量与预期不符,先查设备树里图层是否被禁用,再查驱动是否支持该图层的格式。如果显示异常,先确认时序参数(mode)是否正确,再确认内存带宽是否足够。这些判断都建立在"硬件拓扑决定软件能力"这个前提上。

总结来说,i.MX显示子系统不是单一控制器,而是由显示控制器、显示处理单元、图像处理与预取模块共同组成的流水线。DRM/KMS是这条流水线的软件抽象层,它把硬件能力映射成CRTC、Plane、Encoder、Connector,但映射关系取决于具体SoC和驱动实现。理解硬件拓扑,才能正确使用DRM/KMS,也才能在显示异常时快速定位是软件配置问题还是硬件通路问题。