EDID 数据结构详解:从头部到校验和

EDID 这块数据块,说白了就是显示器的身份证。128 字节,一个字节都不能多,一个字节也不能少。我做调试这些年,至少有一半的“黑屏”问题,最后都查到是 EDID 结构被写乱了。今天咱们就把它的五脏六腑拆开看看。

先给你一张总览图,心里有个谱。

EDID 数据结构总览 EDID 数据结构(128 字节) 头部(0x00 - 0x07):8 字节固定标识 00 FF FF FF FF FF FF 00 厂商 ID(8-9)+ 产品代码(10-11) 序列号(12-15) 版本号(18) 基本参数块(20-24):最大尺寸、Gamma、特性 色度坐标(25-34) 标准时序(35-37)/ 详细时序(38-53) 剩余块(54-125) 扩展块数量(126) 校验和(127) 说明: • 基础 EDID 共 128 字节,若含扩展块(如 HDMI、DisplayID)则总长 256/512 字节。 • 前 128 字节结构固定,其中前 8 字节头是读取成功的“第一道门”。 • 版本号(0x12)决定后续解析规则:EDID 1.3 / 1.4 字段布局不同。 • 校验和(0x7F)保证数据完整性,我见过大量“花屏”是校验出错。

2.1 EDID 头部——第一道门槛

头部一共 8 个字节,从偏移 0x00 到 0x07。标准值是:00 FF FF FF FF FF FF 00。你想想看,显示器上电后,显卡通过 I²C 读到的第一个字节必须是 0x00,接着六个 0xFF,最后一个 0x00。哪怕错一个,显卡就会认为这个显示器“不合法”,直接不输出画面。

我常用的检查手法:用逻辑分析仪抓 I²C 波形,如果 EDID 的前两个字节不是 00 FF,基本就是地址或上拉电阻出了问题。有一次客户反馈“DP 转 HDMI 没信号”,我一查,是转接芯片把 EDID 头部的 0xFF 写成了 0xFE,差了 1 个 bit,画面全黑。

2.2 版本号——别把 1.3 和 1.4 搞混

偏移 0x12 是版本号,0x13 是修订号。常见版本:

版本修订EDID 规格主要变化
0103EDID 1.3最早广泛使用的版本,VT.B 时序块固定
0104EDID 1.4支持更多色深度、3D 格式、扩展块数量增至 4
0200EDID 2.0极少见,DisplayID 已经替代

我在项目里遇到过一台老投影仪,EDID 版本写的是 01 01(版本 1 修订 1),这根本不在标准中。显卡读到这里直接解析失败,输出 640×480 的“保底分辨率”。

注意:EDID 1.3 和 1.4 在详细时序描述块(第 38~53 字节)的格式有差异。1.4 允许“虚拟控制”和“内容类型”字段。如果你按 1.3 解析 1.4,可能会误判最大带宽。

2.3 基本参数——显示器的“体检报告”

偏移 20~24 字节,包含:

  • 视频输入类型(0x14):数字/模拟、同步极性等。我习惯看 bit 7——为 1 是数字接口,为 0 是模拟 VGA。很多 HDMI 转 VGA 线把这里写错,导致显卡以为信号是模拟的。
  • 最大水平尺寸(0x15)和最大垂直尺寸(0x16):单位 cm。我曾碰到一个显示器把这两个字节填反了,Windows 识别成“便携式设备”。
  • Gamma(0x17):8 位小数表示,默认 2.2。注意有些老屏幕写 0x00 表示“不提供”。
  • 特性(0x18):包括 DPMS 支持、色度类型等。

举个例子,如果你想判断显示器是否支持“sRGB”,就看特性字节的 bit 1。

2.4 扩展块——隐藏的“彩蛋”

偏移 0x7E(126 字节)表示后续扩展块的数量。一个扩展块也是 128 字节。常见扩展块类型:

  • CEA-861 扩展:HDMI 的必备扩展,包含音视频格式、3D、YCbCr 支持。
  • DisplayID 扩展:使用 DisplayID 格式,用于超高清或拼接屏。
  • VTB-EXT:额外的详细时序块。

嗯,这里要注意:扩展块的数量不是固定的。有些便宜转换器可能只写 0x00(无扩展),但你还想用它输出 4K @ 60Hz?想都别想。

我曾经调试一台 8K 电视,EDID 头部没问题,但是显卡死活不输出 4K 以上分辨率。用 EDID 分析工具一看,扩展块数量是 0x00,但显示器明明支持 HDMI 2.1。最后发现是线缆 EEPROM 写保护,导致扩展块没被复制出来。

2.5 校验和——最后一道防线

第 128 字节(偏移 0x7F)是校验和。计算方式:

// 将前 127 个字节相加,加上校验和,结果 mod 256 必须为 0
uint8_t checksum = 0;
for (int i = 0; i < 128; i++) {
    checksum += edid[i];
}
// 最终 checksum == 0x00 才正确

简单说,就是整个 128 字节的和模 256 等于 0。如果校验和不对,显卡会丢弃整个 EDID。我遇到过最坑的一次:一个 HDMI 切换器在传输过程中丢失了一个 bit,校验和从 0x55 变成 0x54。显示器是好的,但切换器输出黑屏。后来我在切换器输入端增加了重试机制,这才稳定。

调试建议:在嵌入式系统中读取 EDID 后,先校验校验和。不等显卡报错,自己就能发现数据损坏。我曾把这个逻辑加在 bootloader 里,从源头上过滤掉一半的“黑屏”问题。

小结一下

EDID 的数据结构其实不难,但每段都牵扯到具体的物理和逻辑配置。头部是门,版本号是门牌,基本参数是房子结构,扩展块是阁楼,校验和是门锁。哪个环节断了,画面就出不来。

你想想看,如果你在调试时发现读到的 EDID 前 8 字节是对的,版本号也是 1.4,但分辨率就是上不去——那就重点查扩展块和校验和。逻辑分析仪一挂,数据字节挨个对,通常半小时内能定位到问题。