1. HDMI音频概述:接口标准演进、数据包结构与I2S的关系

各位同学,咱们今天聊聊HDMI音频。说实话,我刚开始接触HDMI音频时,也觉得这东西挺玄乎的——明明就是一根线,怎么就能把视频和音频一起传过去?后来做了几个项目,踩了不少坑,才慢慢摸清楚这里面的门道。

1.1 HDMI接口标准的演进

HDMI从2002年诞生到现在,已经走过了二十多年。我最早接触的是HDMI 1.3版本,那时候还在做DVD播放器。嗯,咱们先看看各个版本的变化:

版本 发布时间 音频相关特性
HDMI 1.0 2002年 支持8通道LPCM,192kHz/24bit
HDMI 1.3 2006年 增加Dolby TrueHD、DTS-HD MA无损格式
HDMI 2.0 2013年 支持32通道音频,1536kHz采样率
HDMI 2.1 2017年 eARC增强音频回传,支持Dolby Atmos

你可能会问,为什么音频通道数从8路涨到32路?说白了,家庭影院系统越来越复杂了。我记得2015年做一个高端AV接收机项目,客户要求支持11.2声道,那时候HDMI 2.0刚出来,我们团队还专门研究了一下怎么把这么多通道塞进一个数据流里。

核心要点:HDMI音频能力的提升,本质上是在带宽和协议层面不断"挤空间"。每次版本升级,音频通道数、采样率、位深都在涨。

1.2 HDMI音频数据包结构

HDMI传输音频,靠的是TMDS通道里的数据岛(Data Island)。说白了,视频信号占用了大部分带宽,音频数据就插在视频消隐期里传输。我刚开始做驱动时,总觉得这个设计很巧妙——不用额外布线,一根线搞定所有。

音频数据包的结构是这样的:

Audio Sample Packet (ASP) 格式:
┌─────────────────────────────────┐
│  Packet Header (4 bytes)        │
│  - Data Byte Count              │
│  - Packet Type (0x02 for audio) │
├─────────────────────────────────┤
│  Subpacket 0 (4 bytes)          │
│  - Channel Status               │
│  - Sample Data (2 bytes)        │
├─────────────────────────────────┤
│  Subpacket 1 (4 bytes)          │
│  - Channel Status               │
│  - Sample Data (2 bytes)        │
├─────────────────────────────────┤
│  ...更多Subpacket...            │
└─────────────────────────────────┘

每个音频数据包最多携带4个样本(每个样本可以是16、20或24位)。我建议你重点关注Packet Header里的Data Byte Count字段——这个值如果算错了,音频就会断断续续。我曾经在一个项目中,因为把这个值写死了,导致48kHz采样率下正常,但切换到96kHz就出问题。排查了两天才发现是这里的问题。

实战技巧:调试HDMI音频时,先用逻辑分析仪抓一下Data Island的波形。看看Packet Type是不是0x02,Data Byte Count对不对。这招帮我解决过至少5个音频无声的bug。

1.3 I2S与HDMI的关系

I2S是飞利浦在1986年定义的音频总线标准。你想想看,HDMI要传输音频,但SoC内部处理音频用的还是I2S。所以这两者之间需要一个"翻译官"——HDMI发送器(Transmitter)。

典型的音频链路是这样的:

SoC/I2S Master
    │
    ├─ I2S_BCLK (位时钟)
    ├─ I2S_LRCK (左右声道时钟)  
    ├─ I2S_SDIN (串行数据)
    └─ I2S_MCLK (主时钟,可选)
        │
        ▼
    HDMI Transmitter (如Silicon Image SiI9134)
        │
        ├─ 将I2S数据打包成Audio Sample Packet
        ├─ 插入到TMDS数据流中
        └─ 通过HDMI线缆发送
            │
            ▼
        HDMI Receiver (如ADV7611)
            │
            ├─ 解析Audio Sample Packet
            └─ 恢复出I2S信号给DAC或SoC

这里有个关键点:I2S的位时钟(BCLK)和HDMI的TMDS时钟是异步的。我建议你在驱动里处理好时钟域同步问题,否则会出现"噼啪"的爆音。我记得第一次做HDMI音频驱动时,没注意这个细节,结果播放音乐时每隔几秒就"咔"一声,被测试同事吐槽了好久。

避坑指南:我曾经遇到过一个案例——I2S的MCLK没有提供给HDMI Transmitter,导致音频采样率识别错误。HDMI规范里,MCLK不是必须的,但很多Transmitter芯片需要它来做时钟恢复。所以,建议你尽量把MCLK接上,省得后面出问题。

1.4 音频数据格式的映射关系

I2S传过来的数据,到了HDMI这边要做一些格式转换。咱们看看最常见的几种情况:

I2S格式 HDMI打包方式 注意事项
16位左对齐 直接映射到16位样本 简单,但动态范围有限
24位右对齐 需要做位对齐处理 注意LSB/MSB位置
32位I2S 取高24位或高16位 取决于接收端能力
TDM多通道 拆分成多个Audio Sample Packet 通道映射要仔细

我个人习惯在驱动初始化时,先读取HDMI Transmitter的EDID信息,看看接收端支持什么格式。然后根据这个信息来配置I2S的格式。这样做的好处是——兼容性好,不会出现"有声音但格式不对"的尴尬情况。

总结一下:HDMI音频的核心就是——I2S负责"生产"音频数据,HDMI负责"打包运输"。驱动工程师要做的就是确保这两边的格式、时钟、通道映射都对得上。嗯,说起来简单,做起来嘛...咱们后面几章慢慢聊。

好了,这一章先到这里。下一章咱们会深入HDMI音频驱动的初始化流程,包括EDID解析和音频格式协商。到时候我会分享一个实际项目中的调试案例,保证让你少走弯路。