3. i.MX DRM驱动源码结构

i.MX 的 DRM 显示驱动位于内核源码 drivers/gpu/drm/imx/ 目录下,它并不是一个单一文件驱动,而是由“平台设备驱动 + component 框架 + 多个显示子模块”共同组成的复合结构。理解这个目录的组织方式,是后续阅读代码、定位问题、添加新显示接口(如 LVDS、MIPI DSI、HDMI)的基础。

一、目录组织:按显示子模块拆分

在典型的 i.MX8 内核(如 NXP 官方 linux-imx 5.15/6.1 分支)中,drivers/gpu/drm/imx/ 大致包含以下内容:

  • imx-drm-core.c / imx-drm-core.h:整个 i.MX DRM 驱动的核心,负责注册 DRM 设备、创建 CRTC/Encoder/Connector、管理 component master。
  • imx-drm-drv.c:platform_driver 入口,负责 probe、匹配设备树、启动 component 匹配流程。
  • ipuv3-crtc.c、ipuv3-plane.c:基于 IPUv3 显示控制器的 CRTC 与 Plane 实现。
  • dw_hdmi-imx.c:HDMI 输出,封装 Synopsys DesignWare HDMI 控制器。
  • imx-ldb.c:LVDS Display Bridge,负责 LVDS 通道输出。
  • imx-parallel-display.c:并行 RGB 接口输出。
  • imx-mipi-dsi.c(部分版本位于 drivers/gpu/drm/imx/dcss/ 或独立目录):MIPI DSI 输出。
  • dcss/:i.MX8MQ 的 Display Controller SubSystem 驱动,是另一套独立的显示管线。

可以看到,i.MX DRM 驱动采用“一个 master + 多个 component”的目录划分方式:核心文件负责聚合,各子模块文件负责具体显示通路。这种划分直接对应 component 框架的绑定模型。

二、Kconfig 与 Makefile:编译开关与模块组织

在 drivers/gpu/drm/imx/Kconfig 中,通常会看到类似配置项:

config DRM_IMX
    tristate "Freescale i.MX DRM support"
    depends on DRM && (ARCH_MXC || COMPILE_TEST)
    select DRM_KMS_HELPER
    select VIDEOMODE_HELPERS

config DRM_IMX_HDMI
    bool "Enable HDMI support on i.MX"
    depends on DRM_IMX
    select DRM_DW_HDMI

config DRM_IMX_LDB
    bool "Enable LVDS Display Bridge on i.MX"
    depends on DRM_IMX

config DRM_IMX_PARALLEL_DISPLAY
    bool "Enable parallel display support on i.MX"
    depends on DRM_IMX

对应的 Makefile 则把这些配置项映射到目标文件:

obj-$(CONFIG_DRM_IMX) += imx-drm.o
imx-drm-y := imx-drm-core.o imx-drm-drv.o ipuv3-crtc.o ipuv3-plane.o

obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o
obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += imx-parallel-display.o

这里的关键点是:imx-drm.o 是一个由多个 .o 链接而成的复合对象,它承载了 DRM master 与 IPU CRTC/Plane;而 HDMI、LDB、parallel display 等作为独立模块,通过 component 框架挂接到 master 上。因此,Kconfig 中的 bool 与 tristate 选择,会直接影响最终生成的模块集合和绑定关系。

三、设备树匹配:compatible 与 of_device_id

i.MX DRM 的 platform_driver 通过 of_device_id 表与设备树节点匹配。核心驱动通常匹配顶层显示控制器节点,例如:

static const struct of_device_id imx_drm_dt_ids[] = {
    { .compatible = "fsl,imx8mq-display-subsystem", },
    { .compatible = "fsl,imx6q-ipu", },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);

而各子模块(HDMI、LDB、DSI)也各自定义自己的 of_device_id,例如 LDB 匹配 "fsl,imx6q-ldb"、"fsl,imx8mq-ldb"。设备树中,这些节点通常作为顶层显示控制器节点的子节点或通过 ports/endpoint 描述连接关系。驱动 probe 时,component 框架会依据设备树中的 ports 拓扑,把 master 与各 component 按顺序绑定。

四、platform_driver 与 component 框架的绑定流程

i.MX DRM 的绑定流程可以概括为“先注册 component,再匹配 master,最后绑定并初始化”。具体来说:

  1. 各子模块驱动(如 dw_hdmi-imx.c)在 probe 中调用 component_add(),把自己注册为一个 component,并提供 ops(bind/unbind)。
  2. 核心驱动 imx-drm-drv.c 在 probe 中调用 component_match_add() 构建匹配表,然后调用 component_master_add_with_match() 注册 master。
  3. 当所有 component 都注册完成后,component 框架调用 master 的 bind 回调,即 imx_drm_bind()。
  4. 在 imx_drm_bind() 中,驱动创建 DRM 设备、初始化 CRTC/Encoder/Connector,并调用各 component 的 bind 回调,把子模块接入显示管线。
  5. 最后调用 drm_dev_register() 注册 DRM 设备,用户空间即可通过 /dev/dri/card0 访问。

这个流程的核心是“延迟绑定”:只有当所有依赖的显示子模块都就绪后,DRM 设备才会真正注册。如果某个子模块(如 HDMI)没有在设备树中使能或驱动未加载,master 的 bind 就不会触发,/dev/dri/card0 也不会出现。这是排查“显示不亮”问题时非常重要的判断依据。

i.MX DRM 源码结构与 component 绑定流程 drivers/gpu/drm/imx/ imx-drm-core.c DRM master / CRTC / Encoder imx-drm-drv.c platform_driver / component master ipuv3-crtc.c / ipuv3-plane.c IPUv3 CRTC 与 Plane dw_hdmi-imx.c HDMI component imx-ldb.c LVDS Display Bridge component imx-parallel-display.c 并行 RGB component dcss/ i.MX8MQ 独立显示子系统 Kconfig / Makefile CONFIG_DRM_IMX CONFIG_DRM_IMX_HDMI CONFIG_DRM_IMX_LDB CONFIG_DRM_IMX_PARALLEL component 绑定流程 ① 子模块 probe component_add() 注册 component ② 核心驱动 probe component_master_add_with_match() ③ 等待所有 component 就绪 匹配设备树 ports/endpoint 拓扑 ④ master bind 回调 imx_drm_bind() 创建 DRM 设备 ⑤ 各 component bind HDMI / LDB / DSI 接入管线 ⑥ drm_dev_register() 生成 /dev/dri/card0

五、实际排查中的判断依据

当显示不亮时,可以按以下顺序检查:

  • 确认 CONFIG_DRM_IMX 及对应子模块配置已使能,zcat /proc/config.gz | grep DRM_IMX 可快速查看。
  • 检查设备树中显示控制器节点与子节点是否 status = "okay",以及 ports 连接是否正确。
  • 查看内核日志中是否有 imx-drm 相关 probe 信息,以及 component 是否全部匹配成功。
  • 若 /dev/dri/card0 不存在,通常说明 master bind 未触发,应优先排查某个 component 是否缺失或 probe 失败。

理解目录组织、Kconfig/Makefile 的映射关系、设备树匹配方式以及 component 绑定流程,能够帮助你在面对 i.MX 显示问题时,快速定位是配置缺失、设备树错误,还是驱动绑定失败,从而缩小排查范围。