2. R-Car平台概述

好,我们直接进入正题。这一章我打算把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的提供者。

驱动加载时,主要做这几件事:

  1. 解析设备树:找到DU节点,获取寄存器地址、中断号、时钟。
  2. 初始化CRTC:注册一个或多个CRTC(每个CRTC对应一个显示通道)。
  3. 初始化Plane:每个CRTC下面挂多个硬件图层(通常是1个主层+1~3个叠加层)。
  4. 建立连接:通过设备树中的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的显示链路画的,你可以看到数据是怎么从应用程序一路流到屏幕的。

R-Car 显示驱动框架数据流 用户空间 (Weston/Xorg) DRM Core / KMS DU 驱动 CRTC + Plane VSPM 驱动 DMA + 格式转换 DU 硬件 (显示控制器) VSPM 硬件 (DMA引擎) 像素数据流 Encoder / Connector 屏幕 说明: VSPM负责从DDR搬运数据给DU DU只负责生成时序和图层合成

从这张图你可以看到,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组合是它特有的。理解了这个框架,后面讲具体移植步骤时,你就能知道每一步是在填哪个坑。