2、显示驱动框架解析:Linux DRM/KMS框架简介、R-Car DU驱动模块分析、VSPM驱动角色与职责
好,我们直接进入正题。这一章我打算把R-Car显示驱动的骨架给你拆开来看。说白了,就是三件事:Linux标准框架长什么样、R-Car的DU模块怎么挂上去、VSPM这个“幕后管家”到底在忙什么。
我个人习惯,接手一个新平台的显示驱动,第一件事不是看代码,而是先搞清楚“谁管谁”。R-Car的显示链路其实很清晰,但如果你不了解DRM/KMS的基本套路,很容易在设备树和驱动 probe 阶段就绕晕了。
2.1 Linux DRM/KMS框架:显示驱动的“操作系统”
DRM(Direct Rendering Manager)和KMS(Kernel Mode Setting)是Linux图形栈的基石。你想想看,如果没有一个统一框架,每个SoC厂商都自己搞一套ioctl,那上层应用(比如Weston、Xorg)得疯掉。
DRM/KMS把显示硬件抽象成几个核心对象:
| 核心对象 | 对应硬件概念 | 我的理解 |
|---|---|---|
| CRTC | 显示控制器(DU的通道) | 负责生成时序,扫出画面 |
| Encoder | 信号编码器(如LVDS、HDMI) | 把像素数据转成物理信号 |
| Connector | 物理接口(如HDMI座子) | 用户能插拔的东西 |
| Plane | 硬件图层(DU的图层) | 叠加、缩放、alpha混合 |
| Framebuffer | 显存中的画面数据 | 就是一块内存,存像素 |
嗯,这里要注意:DRM/KMS框架本身不关心你的硬件具体怎么实现,它只定义了一套“契约”。你的驱动只要实现了这些回调函数,用户空间就能用标准的modeset API来控制显示。
关键点:在R-Car平台上,DU驱动就是CRTC和Plane的实现者。Encoder和Connector通常由外部的HDMI桥芯片或LVDS收发器驱动来提供。DU只管把数据发出去,至于发到哪个接口,那是设备树里连接关系的事。
2.2 R-Car DU驱动模块:显示引擎的核心
DU(Display Unit)是R-Car SoC内部的显示输出模块。我做过H3和M3的移植,DU的寄存器布局基本一致,但通道数量和图层能力有差异。
DU驱动在DRM框架中扮演什么角色?说白了,它就是CRTC和Primary Plane的提供者。
驱动加载时,主要做这几件事:
- 解析设备树:找到DU节点,获取寄存器地址、中断号、时钟。
- 初始化CRTC:注册一个或多个CRTC(每个CRTC对应一个显示通道)。
- 初始化Plane:每个CRTC下面挂多个硬件图层(通常是1个主层+1~3个叠加层)。
- 建立连接:通过设备树中的remote-endpoint,找到对应的Encoder。
我曾经在移植R-Car M3N时踩过一个坑:设备树里DU的端口连接写错了,导致CRTC和Encoder对不上号,modeset时内核直接panic。后来我养成了一个习惯——先读设备树,再读驱动。
避坑指南:DU驱动中有一个关键结构体 rcar_du_device,它管理着所有通道和图层。如果你要加一个新的显示输出(比如第二路HDMI),一定要检查这个结构体里的 num_crtcs 和 num_planes 是否配对了。我曾经因为少配了一个plane,导致双屏显示时第二个屏幕只有背景色。
2.3 VSPM驱动角色与职责:看不见的“搬运工”
VSPM(Video Signal Processor Manager)是R-Car平台特有的模块。很多刚接触R-Car的工程师会问:DU不是已经能输出画面了吗?为什么还要VSPM?
原因很简单:DU本身没有足够的内存带宽来直接读取大分辨率帧缓冲。VSPM充当了一个DMA引擎,负责从内存中抓取数据,做必要的格式转换、裁剪、缩放,然后喂给DU。
VSPM的职责可以总结为:
- DMA传输:从系统内存(DDR)搬运像素数据到DU的FIFO。
- 格式转换:比如把NV12转成ARGB8888,或者做YUV到RGB的转换。
- 裁剪与缩放:支持硬件级别的画面裁剪和缩放,减轻CPU/GPU负担。
- 写回(Writeback):支持将DU输出的画面写回内存,用于截图或合成。
在驱动层面,VSPM通常作为一个独立的platform driver存在。它通过DRM的dma_buf机制与DU共享帧缓冲。你想想看,如果没有VSPM,DU直接去读DDR,那总线压力会非常大,尤其是在4K分辨率下。
注意:VSPM的初始化顺序很重要。VSPM必须在DU之前完成probe,因为DU在初始化CRTC时需要知道VSPM提供的DMA通道。如果顺序反了,DU会找不到VSPM,导致显示黑屏。我遇到过这种情况,查了两天才发现是initcall顺序的问题。
2.4 整体框架关系图
下面这张图是我根据R-Car H3的显示链路画的,你可以看到数据是怎么从应用程序一路流到屏幕的。
从这张图你可以看到,VSPM和DU是协作关系,不是替代关系。VSPM负责“喂”,DU负责“吐”。两者缺一不可。
2.5 驱动初始化流程对比
我把DU和VSPM的初始化流程放在一起对比,这样你更容易看出它们的依赖关系:
| 步骤 | VSPM驱动 | DU驱动 |
|---|---|---|
| 1 | probe:获取VSPM硬件资源 | probe:获取DU硬件资源 |
| 2 | 注册DMA引擎到dmaengine框架 | 解析设备树端口连接 |
| 3 | 初始化VSPM内部管道(rpf/wpf) | 调用dmaengine API获取VSPM通道 |
| 4 | 暴露dmaengine slave接口 | 注册DRM CRTC和Plane |
| 5 | 等待DU调用 | 绑定Encoder/Connector |
经验之谈:如果你在移植时发现DU probe成功但modeset失败,八成是VSPM的dmaengine通道没有正确映射。检查设备树中DU节点的 vsps 属性,它指定了每个CRTC对应哪个VSPM实例。我曾经把H3的DU0配成了VSPD1,结果画面全是花屏——因为VSPD1的带宽不够支撑4K输出。
好了,这一章的内容就是这些。DRM/KMS框架是标准化的,但R-Car的DU和VSPM组合是它特有的。理解了这个框架,后面讲具体移植步骤时,你就能知道每一步是在填哪个坑。