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,最后绑定并初始化”。具体来说:
- 各子模块驱动(如
dw_hdmi-imx.c)在 probe 中调用component_add(),把自己注册为一个 component,并提供ops(bind/unbind)。 - 核心驱动
imx-drm-drv.c在 probe 中调用component_match_add()构建匹配表,然后调用component_master_add_with_match()注册 master。 - 当所有 component 都注册完成后,component 框架调用 master 的
bind回调,即imx_drm_bind()。 - 在
imx_drm_bind()中,驱动创建 DRM 设备、初始化 CRTC/Encoder/Connector,并调用各 component 的bind回调,把子模块接入显示管线。 - 最后调用
drm_dev_register()注册 DRM 设备,用户空间即可通过/dev/dri/card0访问。
这个流程的核心是“延迟绑定”:只有当所有依赖的显示子模块都就绪后,DRM 设备才会真正注册。如果某个子模块(如 HDMI)没有在设备树中使能或驱动未加载,master 的 bind 就不会触发,/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 显示问题时,快速定位是配置缺失、设备树错误,还是驱动绑定失败,从而缩小排查范围。