在嵌入式 Linux 系统中,HDMI 是最常见的显示输出方式之一。在 NXP i.MX8M Plus 平台中,HDMI 显示通路既涉及硬件电路(PHY、ESD、DDC 等)也涉及内核 DRM 子系统的多级抽象(Plane、CRTC、Encoder、Connector)。
本文将从底层硬件、设备树配置、DRM 架构三个维度,一步步讲透 HDMI 显示系统在 Linux 中是如何连接、注册与驱动的。
一、HDMI 显示系统的物理组成
从硬件层面看,HDMI 接口不仅仅是几根差分线,还包括以下模块:
模块 | 功能 | 原理图中体现 |
---|---|---|
HDMI PHY | 将像素数据转换成 TMDS 信号(HDMI传输协议) | hdmiphy 芯片 |
ESD 防护器件 | 防静电浪涌、保护 PHY 芯片 | PCMF2HDMI2S ,差分信号前端 |
Level Shifter | DDC (I2C)、HPD 电平转换 | PCA9306 等器件 |
HDMI CEC | 支持远程控制协议的 GPIO 电路 | NX3008 开关电路 |
HDMI Connector | TYPE A 或 TYPE D 标准接口 | J17 连接器 |
此外,DDC I2C 通道用于读取显示器的 EDID 信息(分辨率能力等),HPD(Hot Plug Detect)用于检测是否插入显示器。
二、Linux 内核中的显示通路架构(DRM/KMS)
Linux 使用 DRM (Direct Rendering Manager) + KMS (Kernel Mode Setting) 构建显示子系统。
一条完整的显示路径由以下模块构成:
Plane → CRTC → Encoder → Connector
模块 | 功能 | 示例(NXP i.MX8MP) |
---|---|---|
Plane | 像素源,例如 framebuffer | LCDIF 输出层 |
CRTC | 定时控制器,生成同步信号 | lcdif1/lcdif3 |
Encoder | 将 RGB/YUV 转换为 HDMI/MIPI 信号 | HDMI 编码器 |
Connector | 具体的显示输出接口 | HDMI TYPE-A 接口 |
DRM 会根据设备树中的 port
和 endpoint
自动识别连接关系并建立显示拓扑。
三、设备树中的 HDMI 配置详解
在 i.MX8MP 平台上,HDMI 相关设备树配置如下:
hdmi: hdmi@32fd8000 {
compatible = "fsl,imx8mp-hdmi";
reg = <0x32fd8000 0x7eff>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&hdmi_blk_ctrl IMX8MP_HDMIBLK_PD_HDMI_TX>;
clocks = <&clk IMX8MP_CLK_HDMI_APB>,
<&clk IMX8MP_CLK_HDMI_24M>,
<&hdmiphy 0>;
clock-names = "iahb", "isfr", "pix";
status = "okay";
port {
hdmi_from_lcdif3: endpoint {
remote-endpoint = <&lcdif3_to_hdmi>;
};
};
};
同时,lcdif3
控制器(Plane/CRTC)也需要在设备树中声明与 HDMI 相连:
&lcdif3 {
status = "okay";
port@3 {
lcdif3_to_hdmi: endpoint {
remote-endpoint = <&hdmi_from_lcdif3>;
};
};
};
通过 remote-endpoint
,完成了 LCDIF3 (CRTC)
→ HDMI (Connector)
的连线。
四、HDMI 是如何作为 DRM Connector 被注册的?
当系统启动时,Linux DRM 框架会扫描所有 port
和 endpoint
节点,建立图形设备拓扑。
在 HDMI 驱动中,通常调用如下代码将其注册为 drm_connector
:
struct drm_connector *connector;
connector = devm_kzalloc(...);
drm_connector_init(dev, connector, &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
这就完成了 HDMI 作为一个类型为 HDMI-A
的显示输出接口的注册。
一旦连接建立,KMS 将负责:
- 读取 EDID:通过 DDC 获取显示支持的分辨率
- 设置 mode:CRTC + encoder 配合调整时序
- 处理热插拔:HPD 管脚绑定的中断控制器响应
五、调试建议
-
使用
modetest
查看 DRM 拓扑与支持的分辨率:modetest -M imx-drm
-
检查 EDID 读取是否正常:
cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode
-
若屏幕无显示,检查:
hdmi
,hdmiphy
节点是否开启(status = "okay"
)- 是否存在
panel
或bridge
未正确初始化 - 是否有 HPD 中断(GPIO trace)
六、总结:DRM 架构下 HDMI 的连接机制全流程
步骤 | 描述 |
---|---|
1 | 硬件上 HDMI PHY、ESD、DDC 电路完整连接 |
2 | DTS 中描述 CRTC → HDMI 的连接关系 |
3 | 驱动层通过 drm_connector_init 注册 HDMI 接口 |
4 | DRM 框架自动解析 endpoint 构建拓扑 |
5 | 用户态通过 modetest/xrandr 进行控制 |
七、延伸学习建议
- 深入阅读:Linux Kernel
drivers/gpu/drm/imx/*hdmi*
驱动实现 - 理解 HDMI 协议(TMDS、DDC、CEC)的基础电气特性
- 将 HDMI 更换为 MIPI DSI 或 eDP 时,识别 pipeline 变化点
你只需亲手调通一个 HDMI 显示通路,理解一次完整的 CRTC → Encoder → HDMI 连接路径,这些概念就不会再模糊。
愿你真正掌握显示系统架构,在屏幕背后做图像输出的操控者。