PAYATHON 2026

如何理解 EDID 详细时序表中的字段?

数据小许

EDID 的 Detailed Timing Descriptor(DTD)描述完整的显示时序。表中带“2”的字段保存前面数值的高位;sync offset 用于确定同步脉冲的位置;border 描述可寻址图像周围的边框区域。

原表有一处错误:标准 DTD 的 00h 和 01h 合起来保存 pixel clock,并非分别保存水平频率和垂直频率。

先认清 18 字节结构

以下偏移均相对于单个 DTD 的起点:

偏移含义
00h–01h16 位小端 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
11hinterlace、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 提供显示模式参数。要输出该模式,仍需通过显卡驱动或固件的模式设置接口完成配置,并确认显卡和连接链路支持该时序。

备注:内容仅供参考。