在嵌入式 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 连接路径,这些概念就不会再模糊。
愿你真正掌握显示系统架构,在屏幕背后做图像输出的操控者。
920

被折叠的 条评论
为什么被折叠?



