3. EDID基础

EDID(Extended Display Identification Data,扩展显示标识数据)是显示器、电视机、投影仪等显示设备向视频源(GPU、机顶盒、播放器)宣告自身能力与偏好的标准数据结构。在HDMI系统中,EDID通过DDC通道(基于I2C,地址0x50)传输,是CEC、HDCP、音频回传等功能正常工作的前提。理解EDID的结构、版本差异、数据块组织方式以及校验和算法,是进行自定义EDID、修复显示异常、实现多设备兼容性管理的核心基础。本章将从二进制结构出发,逐层拆解EDID的组成,并给出可落地的校验与修改方法。

EDID 128字节结构总览(Base Block + Extension Block) Base Block(128字节)— 必备 Header (0-7) 00 FF FF FF FF FF FF 00 Vendor/Product (8-17) 厂商ID、产品代码、序列号 Version (18-19) 1.3 / 1.4 / 2.0 Basic Display (20-24) 视频输入类型、水平/垂直尺寸、Gamma Chromaticity (25-34) RGB/YCbCr色度坐标 Established Timings (35-37) 720x400, 640x480, 800x600等标准时序 Standard Timings (38-53) 8组厂商自定义时序 Detailed Timings (54-125) 4个18字节描述符(时序/显示器名称/范围限制) Extension Count (126) 后续扩展块数量(0-255) Checksum (127) 使前127字节总和 + 校验和 = 0 (mod 256) Extension Block(128字节/块) CEA-861 (0x02) 音频格式、VSDB、HDMI 1.4/2.0 4K@60Hz、HDR、3D支持 VTB-EXT (0x10) 视频时序块扩展 DisplayID (0x70) DisplayID 2.0扩展 其他扩展类型 LS-EXT, DI-EXT, 厂商自定义 指向扩展块 校验和算法 sum(0..126) + checksum ≡ 0 checksum = (256 - sum) & 0xFF DDC通道 I2C地址 0x50,从偏移0开始 每次读取128字节

上图展示了EDID的整体结构。Base Block是每个显示设备必须提供的,而Extension Block则根据设备功能(如HDMI音频、4K支持、HDR)按需添加。下面我们将深入解析每个部分的细节。

3.1 EDID的核心结构:从Header到Checksum

EDID的Base Block固定为128字节,从I2C偏移0x00开始读取。其结构布局遵循VESA E-EDID标准,每个字段都有明确的字节偏移和位定义。理解这些偏移是解析和修改EDID的第一步。

3.1.1 关键字段解析

字节偏移字段名长度说明
0-7Header8字节固定值 00 FF FF FF FF FF FF 00,用于识别EDID起始
8-9Manufacturer ID2字节PNP ID,3个ASCII字符压缩为16位
10-11Product Code2字节厂商自定义产品编号
12-15Serial Number4字节32位序列号,可为零
16Week of Manufacture1字节生产周,0表示未知
17Year of Manufacture1字节生产年份 = 值 + 1990
18EDID Version1字节主版本号,通常为1
19EDID Revision1字节次版本号,3/4/5等
20Video Input Definition1字节信号类型(数字/模拟)、位深、接口类型
21Horizontal Screen Size1字节屏幕宽度(cm),0表示未知
22Vertical Screen Size1字节屏幕高度(cm)
23Gamma1字节Gamma值 = (值+100)/100,0xFF表示2.2
24Features1字节支持DPMS、色域、sRGB等特性
25-34Chromaticity10字节红绿蓝白点的色度坐标
35-37Established Timings3字节标准时序位图(VGA、XGA等)
38-53Standard Timings16字节8组2字节的厂商时序定义
54-125Detailed Timing Descriptors72字节4个18字节描述符,可定义时序、名称、范围
126Extension Count1字节后续扩展块数量
127Checksum1字节校验和,使前127字节总和+校验和=0 (mod 256)

在解析时,需要特别注意字节序。EDID中的多字节字段(如产品代码、序列号)采用小端序(Little-Endian)存储。例如,产品代码0x1234在字节10存储为0x34,字节11存储为0x12。

实战要点:当使用I2C读取EDID时,建议一次性读取256字节(Base Block + 第一个Extension Block),避免多次I2C事务带来的时序问题。读取后先验证Header和Checksum,再解析具体字段。

3.2 EDID版本演进:1.3、1.4与2.0的差异

EDID标准经历了多个版本迭代,每个版本在保持向后兼容的同时,增加了新的能力描述。版本号存储在字节18(主版本)和字节19(次版本)中。

3.2.1 版本对比表

特性EDID 1.3EDID 1.4EDID 2.0
发布时间1997年2002年2016年(DisplayID 2.0)
最大分辨率支持UXGA (1600x1200)WUXGA (1920x1200)8K@60Hz及以上
色彩深度6-bit/8-bit8-bit/10-bit/12-bit10-bit/12-bit/16-bit
扩展块类型CEA-861BCEA-861D/E/FDisplayID 2.0
HDR支持不支持通过CEA-861F VSDB支持原生HDR元数据
音频支持仅LPCMLPCM + 压缩音频LPCM + 压缩 + 对象音频
3D支持不支持通过CEA-861D支持原生3D描述
接口类型VGA/DVIHDMI 1.4HDMI 2.1/DisplayPort

EDID 1.4是目前最广泛使用的版本,它通过CEA-861扩展块实现了对HDMI 1.4特性的完整描述。EDID 2.0实际上与DisplayID 2.0标准融合,采用全新的数据块结构,不再使用传统的128字节Base Block格式,而是使用更灵活的Tiled DisplayID块。

兼容性风险:当自定义EDID时,如果目标设备只支持EDID 1.3,而写入的EDID包含1.4特有的扩展块(如CEA-861F),可能导致设备无法正确解析。建议在修改前先确认源设备的EDID版本支持范围。

3.3 Base Block与Extension Block的协作机制

Base Block提供了显示设备的基本信息,而Extension Block则承载了HDMI特有的功能描述。在HDMI系统中,最重要的扩展块是CEA-861系列(Tag 0x02)。

3.3.1 CEA-861扩展块结构

CEA-861扩展块同样为128字节,其内部结构如下:

  1. Tag (1字节):固定为0x02,标识这是CEA扩展块。
  2. Revision (1字节):CEA-861版本号(如3表示861C,4表示861D)。
  3. DTD Offset (1字节):指向Detailed Timing Descriptor的偏移量。
  4. Data Blocks (可变长度):包含音频数据块、视频数据块、VSDB(Vendor Specific Data Block)等。
  5. Detailed Timing Descriptors (18字节×N):额外的时序描述符。
  6. Checksum (1字节):与Base Block相同的校验算法。

在HDMI 1.4及以后版本中,VSDB是关键的扩展块,它包含了HDMI特有的能力声明:

VSDB结构示例(HDMI 1.4):
- Vendor ID (3字节): 0x000C03 (HDMI LLC)
- Physical Address (2字节): 设备物理地址
- Flags (1字节): 支持CEC、HDCP等
- Max TMDS Clock (1字节): 最大TMDS时钟(MHz/5)
- 可选字段: 3D、4K支持、HDR等
解析技巧:在解析CEA扩展块时,先读取DTD Offset,该值指向第一个DTD的起始位置。从DTD Offset到扩展块末尾(偏移127)之间的区域,如果剩余空间≥18字节,则包含DTD;否则为填充数据(0x00)。

3.4 校验和计算:原理与实现

EDID的校验和机制简单但关键,它确保数据在传输过程中未被损坏。每个128字节块(Base Block和每个Extension Block)都有独立的校验和。

3.4.1 校验算法

校验和的计算方法如下:

  1. 将当前块的前127个字节(偏移0-126)的值累加。
  2. 对256取模(即取低8位)。
  3. 校验和字节 = (256 - 累加和) & 0xFF。

验证时,将前127字节与校验和字节相加,结果对256取模应为0。

// C语言实现示例
unsigned char calculate_checksum(unsigned char *edid_block) {
    unsigned char sum = 0;
    for (int i = 0; i < 127; i++) {
        sum += edid_block[i];
    }
    return (unsigned char)(0x100 - sum);
}

// 验证函数
int verify_checksum(unsigned char *edid_block) {
    unsigned char sum = 0;
    for (int i = 0; i < 128; i++) {
        sum += edid_block[i];
    }
    return (sum == 0);
}

3.4.2 校验和修改流程

当修改EDID中的任何字节后,必须重新计算校验和,否则设备会拒绝加载该EDID。修改流程如下:

  1. 定位需要修改的字节偏移。
  2. 修改目标字节值。
  3. 重新计算该块(Base或Extension)的校验和。
  4. 更新校验和字节(偏移127)。
  5. 如果修改了Extension Count(偏移126),还需检查后续扩展块是否完整。
常见错误:许多初学者在修改EDID后忘记更新校验和,导致显示器黑屏或系统无法识别。建议在修改后使用工具(如AW EDID Editor)自动重新计算校验和。

3.5 实战案例:自定义EDID修复4K显示问题

下面通过一个实际案例,展示如何通过修改EDID解决4K@60Hz显示异常的问题。

3.5.1 问题背景

某用户使用HDMI 2.0线缆连接4K电视和显卡,但系统只能输出4K@30Hz,无法选择60Hz刷新率。初步判断是电视的EDID未正确声明HDMI 2.0能力。

3.5.2 分析过程

使用I2C读取电视的EDID,关键数据如下:

Base Block:
- Version: 1.4
- Extension Count: 2

CEA-861 Extension Block (第一个):
- Tag: 0x02
- Revision: 3 (CEA-861C)
- VSDB Vendor ID: 0x000C03
- Max TMDS Clock: 0x22 (170MHz,仅支持HDMI 1.4)
- 无4K@60Hz时序描述

问题定位:Max TMDS Clock字段值为0x22,对应170MHz,而4K@60Hz需要至少600MHz的TMDS时钟。此外,CEA-861C版本不支持4K时序描述。

3.5.3 修改方案

需要将CEA扩展块升级到861F,并添加4K@60Hz时序。具体操作:

  1. 将CEA Revision从3改为6(对应861F)。
  2. 将Max TMDS Clock改为0x78(600MHz/5=120,即0x78)。
  3. 在DTD区域添加4K@60Hz时序描述符(3840x2160@60Hz,Pixel Clock 594MHz)。
  4. 添加VSDB中的SCDC(Status and Control Data Channel)支持标志。
  5. 重新计算所有修改块的校验和。
修改后的VSDB关键字节:
- Max TMDS Clock: 0x78 (600MHz)
- SCDC Present: 1 (bit 7 of Flags)
- 4K@60Hz DTD: 像素时钟 594MHz,H: 3840, V: 2160

3.5.4 结果与复盘

修改后,系统成功识别4K@60Hz选项,画面正常输出。但需要注意:

  • 此修改仅适用于支持HDMI 2.0的显卡和线缆。
  • 如果电视硬件本身不支持HDMI 2.0,修改EDID可能导致无信号。
  • 建议在修改前备份原始EDID,以便恢复。
经验总结:EDID修改是解决显示兼容性问题的有力工具,但必须基于硬件实际能力。在自定义EDID时,始终遵循"最小修改"原则,只改动必要的字段,并确保校验和正确。

3.6 常见误区与调试建议

在EDID解析和自定义过程中,以下误区需要特别注意:

  • 误区1:忽略字节序。多字节字段(如产品代码)使用小端序,直接按大端序解析会导致错误。
  • 误区2:混淆EDID版本与CEA版本。EDID 1.4可以搭配不同版本的CEA扩展块(861C/D/E/F),两者独立。
  • 误区3:修改后不验证。修改EDID后,应使用工具(如Windows的"显示设置"或Linux的edid-decode)验证解析结果。
  • 误区4:忽略扩展块数量。修改Extension Count后,必须确保后续扩展块完整且校验和正确。

调试EDID问题时,推荐使用以下工具链:

  1. 读取EDID:Linux下使用i2cdump -y 0 0x50,Windows下使用"显示器的EDID查看器"。
  2. 解析EDID:使用edid-decode工具,可输出完整的字段解析。
  3. 修改EDID:使用AW EDID Editor或自定义脚本,修改后自动计算校验和。
  4. 验证修改:重新读取EDID,使用edid-decode确认修改生效。
专业建议:在批量部署自定义EDID前,建议在至少3种不同型号的显卡/显示器组合上测试,确保兼容性。同时,记录每次修改的版本号和变更内容,便于回溯。