如何理解 EDID 详细时序表中的字段?
EDID 的 Detailed Timing Descriptor(DTD)描述完整的显示时序。表中带“2”的字段保存前面数值的高位;sync offset 用于确定同步脉冲的位置;border 描述可寻址图像周围的边框区域。
原表有一处错误:标准 DTD 的 00h 和 01h 合起来保存 pixel clock,并非分别保存水平频率和垂直频率。
先认清 18 字节结构
以下偏移均相对于单个 DTD 的起点:
| 偏移 | 含义 |
|---|---|
00h–01h | 16 位小端 pixel clock,单位为 10 kHz |
02h–04h | 水平可寻址像素数和水平 blanking,两个 12 位数 |
05h–07h | 垂直可寻址行数和垂直 blanking,两个 12 位数 |
08h–0Bh | 水平、垂直同步偏移和同步脉宽,包含分散存储的高位 |
0Ch–0Eh | 图像物理尺寸字段,通常以 mm 表示,不是像素分辨率 |
0Fh | 左、右每侧的 horizontal border,单位为 pixels |
10h | 上、下每侧的 vertical border,单位为 lines |
11h | interlace、stereo、同步形式等标志 |
如果前两个字节合起来为零,该项就不是有效的像素时序 DTD,应按相应的其他描述符格式解析。字段布局可参照 VESA E-EDID 规范第 3.10 节。
“active time 2”为什么存在?
一个字节只能表示 0–255,放不下常见的分辨率数值。因此,DTD 将水平可寻址像素数拆成低 8 位和高 4 位;水平 blanking 也采用相同方式,并共用一个高位字节。
例如,水平像素数为 1920,即 0x780:02h 保存 0x80,04h 的高半字节保存 0x7。垂直方向同理。这些字段没有定义第二套分辨率。
下面是 C 语言字段解包片段,需包含 <stdint.h>。假设 d 指向至少 18 字节的数据,且已确认它是时序描述符:
uint32_t pixel_clock_hz =
((uint32_t)d[0] | ((uint32_t)d[1] << 8)) * 10000u;
uint32_t hactive = d[2] | ((d[4] & 0xF0u) << 4);
uint32_t hblank = d[3] | ((d[4] & 0x0Fu) << 8);
uint32_t vactive = d[5] | ((d[7] & 0xF0u) << 4);
uint32_t vblank = d[6] | ((d[7] & 0x0Fu) << 8);
uint32_t hsync_offset = d[8] | ((d[11] & 0xC0u) << 2);
uint32_t hsync_width = d[9] | ((d[11] & 0x30u) << 4);
uint32_t vsync_offset = (d[10] >> 4)
| ((d[11] & 0x0Cu) << 2);
uint32_t vsync_width = (d[10] & 0x0Fu)
| ((d[11] & 0x03u) << 4);
其中 hactive、vactive 对应可寻址图像尺寸。上述位拼接方式也可以在 Linux DRM 的 DTD 解析实现中核对。
sync offset 和同步脉宽有什么区别?
在 border 为零的情况下,一行的时序可以表示为:
可寻址图像 → front porch → sync pulse → back porch → 下一行
sync offset 表示从图像结束到同步脉冲开始的间隔,此时等于 front porch;sync pulse width 表示同步脉冲持续多久。水平量以像素时钟周期计数,垂直量以行计数。
blanking 的总长度无法单独确定同步脉冲在其中的位置。显卡控制器还需要 offset 和 width,才能确定同步开始和结束的位置。对于无边框模式,可以计算:
hsync_start = hactive + hsync_offset
hsync_end = hsync_start + hsync_width
htotal = hactive + hblank
vsync_start = vactive + vsync_offset
vsync_end = vsync_start + vsync_width
vtotal = vactive + vblank
这些关系与 Linux DRM 构造显示模式的方式一致。但具体硬件寄存器可能采用不同的计数约定,不能直接把数值原样写入。
border 为什么需要单独记录?
border 是视频信号中的边框区域,位于可寻址图像与 blanking 之间。它不是显示器外壳,也不是窗口边框。
例如,horizontal border 为 8,表示左、右各有 8 个像素时钟周期的边框区域,不表示应用程序的可寻址宽度增加了 16 像素。
非零 border 会影响图像边界与同步位置的关系。旧式 Sync Offset 定义包含右侧或底部 border,所以只有 border 为零时,才能直接把它等同于 front porch。遇到非零值时,应结合对应 EDID 定义及控制器的边框处理方式解释。相关区别见 VESA 规范第 3.12 节及附录 D-5。
在操作系统中应该如何使用?
先校验 EDID 的头部、长度、版本和块校验和,再识别时序描述符并解包字段。校验和通过只说明数据满足这一项检查,仍需检查各个时序数值是否合理。
对于逐行扫描且 border 为零的模式,刷新率可以由总时序计算:
horizontal_frequency_hz = pixel_clock_hz / htotal
refresh_rate_hz = pixel_clock_hz / (htotal * vtotal)
例如,假设 pixel clock 为 148.5 MHz,水平总计数为 2200,垂直总计数为 1125,则刷新率为 148500000 / (2200 × 1125) = 60 Hz。这只是计算示例,不代表题目中的显示器参数。interlaced 模式需要另外处理场、帧及半行关系。
读取首选模式时还要区分 preferred 与 native:在 EDID 1.4 中,第一个详细时序描述符给出 preferred timing,但首选模式是否包含面板 native pixel format,需要结合相应特性位判断,不能把所有 EDID 版本一概处理。相关规则见 VESA 规范第 3.6.4 和 3.10.1 节。
DTD 提供显示模式参数。要输出该模式,仍需通过显卡驱动或固件的模式设置接口完成配置,并确认显卡和连接链路支持该时序。
备注:内容仅供参考。
