当前位置: 首页 > news >正文

RK3576 HDMI 引脚复用与驱动深度分析

记录一次将 HDMI CEC/SCL/SDA 引脚释放为 GPIO 的实战过程,涉及 Rockchip 平台、Synopsys DW HDMI IP 驱动、设备树 pinctrl 覆盖,以及 TMDS/FRL/DDC/EDID 等概念的梳理。

一、问题背景

硬件设计将 `GPIO4_C0`(SoC 的 `hdmi_tx_cec_m0` 引脚)用作 RK628 芯片的 reset 脚。内核启动时出现 GPIO 争抢错误:

[ 2.658605] rockchip-pinctrl pinctrl: pin gpio4-16 already requested by 27da0000.hdmi;

cannot claim for 2-0050

[ 2.658636] rockchip-pinctrl pinctrl: pin-144 (2-0050) status -22

[ 2.658647] rockchip-pinctrl pinctrl: could not request pin 144 (gpio4-16) from group

rk628-reset on device rockchip-pinctrl

根因:** SoC 的 HDMI 驱动通过 pinctrl 占用了 GPIO4_C0(CEC 功能),rk628 驱动尝试将其用作 reset GPIO 时报 `-EBUSY`。此外硬件还希望将 DDC 引脚(GPIO4_C2、GPIO4_C3)也释放出来做普通 I2C。

二、HDMI 四根引脚详解

RK3576 的 HDMI TX 通过 `hdmi_txm0_pins` pinctrl 组复用以下引脚(均在 GPIO4 bank):

| 引脚 | 编号 | Function | 协议角色 | 能否去掉 |

|---|---|---|---|---|

| GPIO4_C0 | pin-144 | `hdmi_tx_cec_m0` | CEC(消费电子控制) | ✅ 可以 |

| GPIO4_C1 | pin-145 | `hdmi_tx_hpdin_m0` | HPD(热插拔检测) | ❌ 建议保留 |

| GPIO4_C2 | pin-146 | `hdmi_tx_scl` | DDC SCL(EDID I2C 时钟) | ✅ 可以 |

| GPIO4_C3 | pin-147 | `hdmi_tx_sda` | DDC SDA(EDID I2C 数据) | ✅ 可以 |

2.1 CEC — Consumer Electronics Control

CEC 是 HDMI 协议中的**可选**功能,用于电视、机顶盒、功放等设备间的联动控制(如:打开电视时自动打开功放)。

在 Linux 驱动中:

// dw-hdmi-qp.c:4742 if (of_property_read_bool(np, "cec-enable")) { hdmi->cec_enable = true; irq = platform_get_irq(pdev, 1); // 拿 CEC 中断 };

// 不写 cec-enable → hdmi->cec_enable 保持 false

// → dw_hdmi_qp_register_cec() 直接 return 0,不注册设备

结论:没有 `cec-enable` 属性时,CEC 功能完全静默——不注册平台设备、不申请中断、不占用任何软件资源。去掉 pinctrl 中的 CEC 引脚不会导致任何错误。

2.2 HPD — Hot Plug Detect

HPD 是 HDMI PHY 用来判断"对端是否插入了显示器"的**唯一硬件信号**。他的工作方式不是 GPIO 输入,而是通过 pinctrl 将引脚的电平路由到 HDMI IP 内部的 IOC GRF 寄存器:

// dw_hdmi-rockchip.c:4400 dw_hdmi_rk3576_read_hpd() { regmap_read(hdmi->regmap, RK3576_IOC_HDMITX_HPD_STATUS, &val); if (val & RK3576_HDMITX_LEVEL_INT) return connector_status_connected; // 读到高电平 → 认为有设备 else return connector_status_disconnected; // 读到低电平 → 认为无设备 }

HPD 在整个 HDMI 管线中的作用:

- **DRM connector detect:** 决定是否上报"已连接"

- **FRL 训练状态机:** 训练过程中每 500μs 轮询一次,HPD 为低则退出

- **DDC 读写操作:** 每次 I2C 传输前检查 HPD,确保设备还在

如果 HPD 一直为低:

- DRM 框架认为没有显示器 → 不启动视频管线 → **黑屏**

- 可通过 `force-output` DT 属性绕过 DRM 层检查

- 但 FRL 模式和 DDC 操作中仍会直接读 HPD 寄存器

建议:在 GPIO4_C1 上加一个 10KΩ 上拉电阻到 3.3V,让 PHY 读到持续高电平。一毛钱成本,零软件副作用。

2.3 DDC / SCL+SDA — Display Data Channel

DDC 是 HDMI 标准规定的一个 I2C 总线,用来读显示器的 EDID(Extended Display Identification Data)。EDID 是一个 128/256 字节的数据块,描述了显示器支持的分辨率、刷新率、色彩空间、音频格式等能力。

需要注意的是,HDMI 的 DDC 不是用 SoC 的通用 I2C 控制器,而是 **HDMI IP 内部的专用 I2C 控制器**。驱动通过操作 HDMI 寄存器来读写 EDID:

// dw-hdmi-qp.c — DDC 读 EDID 流程 dw_hdmi_connector_get_modes() → edid = drm_get_edid(connector, hdmi->ddc); // hdmi->ddc 是内部注册的 i2c_adapter → drm_add_edid_modes(connector, edid); // 把 EDID 里的分辨率加进 mode list ```

没有 DDC 时,驱动有兜底逻辑:

} else { hdmi->hdmi_data.sink_is_hdmi = true; ret = rockchip_drm_add_modes_noedid(connector); // 加标准分辨率(1080p、720p 等) dev_info(hdmi->dev, "failed to get edid\n"); }

结论:去掉 DDC 不会报错,驱动会用标准分辨率兜底。如果你的面板是固定分辨率,这是完全可接受的权衡。

三、TMDS vs FRL:两代 HDMI 传输协议

3.1 概念

| | TMDS | FRL |

|---|---|---|

| 全称 | Transition Minimized Differential Signaling | Fixed Rate Link |

| 引入版本 | HDMI 1.0 ~ 2.0 | HDMI 2.1 |

| 最大带宽 | 18 Gbps | 48 Gbps |

| 支持的典型分辨率 | 4K@60Hz、1440p@144Hz | 8K@60Hz、4K@120Hz |

| 链路建立 | 无需协商,直接驱动 | 需要源端和显示端握手训练 |

| 类比 | 国道:通车就是通车 | 高速公路:上之前要先取卡 |

3.2 模式选择逻辑

// dw_hdmi-rockchip.c:1112 if (!max_frl_rate || (tmdsclk < HDMI20_MAX_RATE && mode.clock < HDMI20_MAX_RATE)) { hdmi->link_cfg.frl_mode = false; // → TMDS } else { hdmi->link_cfg.frl_mode = true; // → FRL }

FRL 需要**同时满足**:

1. `max_frl_rate != 0` — 显示器通过 EDID 声明支持 FRL(需要 DDC)

2. 像素时钟 ≥ 600MHz — 高分辨率/高刷新率场景

多数嵌入式场景走 TMDS。** 低分辨率面板 + 无 DDC → 100% TMDS。

FRL 训练状态机在 `dw-hdmi-qp.c` 中由 `dw_hdmi_qp_flt_work()` 驱动,入口条件:

// dw-hdmi-qp.c:3813 if (link_cfg && link_cfg->frl_mode) queue_work(hdmi->workqueue, &hdmi->flt_work); // 只在 FRL 模式下触发

TMDS 模式下,`dw_hdmi_qp_is_disabled()` 永远不会被调用,HPD 检查仅限于 DRM connector detect 层。

四、驱动架构

arch/arm64/boot/dts/rockchip/ ├── rk3576.dtsi ← HDMI 节点定义(reg、中断、时钟、pinctrl-0) ├── rk3576-pinctrl.dtsi ← hdmi_txm0_pins、hdmi_tx_scl、hdmi_tx_sda 等 pinctrl 组 └── x1013.dts ← 你的板级 DTS,在这里覆盖/添加属性 drivers/gpu/drm/ ├── bridge/synopsys/ │ ├── dw-hdmi-qp.c ← Synopsys DW HDMI QP 通用核心 │ ├── dw-hdmi-qp-cec.c ← CEC 子模块(平台设备) │ └── dw-hdmi-qp-hdcp.c ← HDCP 子模块 └── rockchip/ └── dw_hdmi-rockchip.c ← Rockchip 胶水层(GRF、时钟、pinctrl) drivers/misc/rk628/ ├── rk628.c ← rk628 主驱动(HDMI in → DSI out) └── rk628_hdmitx.c ← rk628 自带 HDMI TX

分层设计:** Synopsys 提供通用的 HDMI IP 核心驱动,Rockchip 写一层"胶水代码"处理 SoC 特有的寄存器、时钟、中断映射。同样的 `dw-hdmi-qp.c` 也在全志、ST、NXP 的平台上使用。

五、实际修改方案

5.1 新增不含 CEC 的 pinctrl 组

&pinctrl { /* ... rk628 pinctrl ... */ hdmi_tx_nocrc { hdmi_txm0_nocrc: hdmi-txm0-nocrc { rockchip,pins = /* hdmi_tx_hpdin_m0 — 只保留 HPD,去掉 CEC */ <4 RK_PC1 9 &pcfg_pull_none>; }; }; };

原来的 `hdmi_txm0_pins` 捆绑了 CEC 和 HPD 两根脚,但我们只需要 HPD。新建一个只含 HPD 的组,彻底解耦。

5.2 覆盖 HDMI 节点的 pinctrl

&hdmi { status = "okay"; enable-gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_HIGH>; /* * 覆盖 rk3576.dtsi 中的 pinctrl-0: * - hdmi_txm0_pins(CEC + HPD)→ hdmi_txm0_nocrc(只 HPD) * - 去掉 hdmi_tx_scl + hdmi_tx_sda(不需要 DDC/EDID) * * 释放的引脚: * GPIO4_C0 → rk628 reset * GPIO4_C2 + GPIO4_C3 → GPIO / 软件 I2C */ pinctrl-names = "default"; pinctrl-0 = <&hdmi_txm0_nocrc>; };

```

5.3 硬件

GPIO4_C1 上拉 10KΩ 到 3.3V,保证 HPD 读到高电平。

5.4 验证

# 启动后检查 HDMI 日志 dmesg | grep -E "hdmi|rk628|tmds|cec"

# 期望输出(无报错):

# dw hdmi qp use tmds mode

# rk628 probe 成功(不再有 gpio4-16 冲突)

```

六、关键结论

1. **CEC 可选:** 没有 `cec-enable` 属性时驱动完全跳过,去掉引脚无副作用。

2. **DDC 可选:** 不去读 EDID 时驱动用兜底分辨率,去掉 SCL/SDA 不报错。

3. **HPD 建议保留:** PHY 层需要它判断设备状态。可通过硬件上拉或 `force-output` DT 属性处理。

4. **低分辨率 = TMDS:** FRL 只在超高清场景下开启,你的场景全程 TMDS,FRL 相关代码不会执行。

5. **pinctrl 组名对驱动透明:** 驱动通过 `devm_pinctrl_get()` 拿整个设备的 pinctrl,只按 `pinctrl-names`(如 "default"、"idle")匹配状态,不知道组的名字。改 DT 即可,C 代码一行不动。

6. **Synopsys IP 分层:** Rockchip 的 HDMI 核心来自 Synopsys DesignWare,Rockchip 只负责 SoC 特有的胶水层。CEC、DDC、EDID、音频 N/CTS 等协议逻辑是通用代码。

八.RK628F奇怪问题

如果想使用hdmi中的ddc复用做普通i2c的时候记得把rk628f的hdmi的ddc的电阻拆掉,不然会干扰到edid部分导致芯片锁hdmi信号的流程

http://www.jsqmd.com/news/1114049/

相关文章:

  • 本地多模态模型选型实战:Qwen与Gemma中文OCR与长上下文对比
  • ChatGPT精准输出JSON与Markdown的7步黄金法则:从乱码到可解析,5分钟实现零错误结构化响应
  • 适配科研实验与高端制造,各类难熔金属合金的熔炼与球化制粉体系
  • 民航多航站楼多分支组网存在哪些核心网络痛点?
  • 【ChatGPT代码审查实战指南】:20年资深工程师亲授5大高危漏洞自动识别模式,错过再等一年
  • AI驱动的激励机制压力测试工具:用自然语言发现规则漏洞
  • 为什么你的Few-shot提示总在测试集崩塌?揭秘LLM上下文感知阈值与样本排序的3层神经机制
  • DDrawCompat:3步解决Windows 10/11老游戏兼容性难题的终极方案
  • 终极网盘下载加速秘籍:八大平台直链下载助手完全指南
  • skill过多时,如何保证agent的命中率
  • OpenPLC Editor实战指南:5分钟掌握开源工业自动化编程
  • 国产代码大模型实战对比:GLM-5.1与DeepSeek-V4-Pro真实项目硬刚
  • 传输层的拥塞控制
  • Photon光影包终极指南:5个简单步骤让Minecraft画面焕然一新
  • Milvus、Pinecone 与 FAISS 向量数据库选型与实战指南
  • Android逆向调试入门:破解三大反调试机制实战指南
  • Grok是语言模型,不是视频模型:澄清多模态技术基本概念
  • 2026春招AI抢人大战:小白程序员如何抓住大模型红利,速收藏!
  • 【ChatGPT编程提效黄金法则】:20年资深工程师亲授7大不可外传的代码生成实战技巧
  • Prometheus 5-Rocky Linux 9用Prometheus 3.12.0 + Alertmanager 0.33.0 邮件告警(Mysql)
  • 3分钟快速上手:B站缓存视频转换神器m4s-converter完全指南
  • Java系统抗量子密码迁移实战:三步实现PQC算法集成与兼容性架构
  • 如何用Photon光影包打造电影级Minecraft体验:新手终极指南
  • 全栈实战笔记:Vue 部署的底层逻辑,打通 publicPath 与 Nginx 的任督二脉
  • 【小白也能轻松玩转龙虾】虾壳云一键部署保姆级步骤,打造专属 OpenClaw v2.7.9 自动助理(附最新安装包)
  • AI 驱动钓鱼攻击蔓延态势与全域协同防御体系研究
  • ClaudeCode使用非官方API的配置
  • BepInEx游戏模组框架:3分钟掌握跨平台插件安装与高效管理
  • WorkBuddy微盛课堂#1|1分钟让AI生成5张公众号封面图,并直接导入
  • 简单粗暴地理解js原型链--js面向对象编程