自制工业控制系统:显示子系统深入——EDID、模式协商、显存与品牌信息的获取
Contents
起因
显卡实战篇(《从GOP帧缓冲接管显示输出》)解决的是"接管帧缓冲自己画像素",但顺着往下还有一串问题躲不掉:高分辨率是靠什么实现的?系统怎么"自动适配"显示器?显示器支持哪些模式从哪查?显卡的显存容量、品牌型号从哪读?——“从哪查"这问的标准答案是 EDID,1994 年 VESA 定的规矩:让显示器在 DDC 线上自报家门,交出 128 字节的"我能干什么”(后来扩到 256 字节 E-EDID)。动机很朴素:VGA 时代显示器是哑巴,刷新率给高了轻则黑屏重则伤机器,显卡只能瞎猜。这篇把这些信息问题逐个落到可操作的层面——涉及三块东西:EDID、模式协商、PCI 配置空间。
一、先分清三个角色
“显示"这件事是三方接力,各自约束一环:
- GPU 渲染核心:把像素算出来写进显存(我们的系统里它闲着,像素我们自己写帧缓冲)
- 显示引擎(Display Engine):按固定时序逐行扫描帧缓冲,把像素流编码成 HDMI/DP/VGA 信号发出去
- 显示器:解码信号点亮面板
所以"这台机器支持什么分辨率"从来不是单方面的事,而是三方约束的交集:显示引擎能产生的时序 × 连接线的带宽上限 × 显示器面板能吃的模式。高分辨率的本质:更高的像素时钟 + 更大的显存占用——1920×1080@32bpp 一帧约 8MB,4K 是 33MB,显存(或集显情况下划出的内存)够不够是硬约束。线缆带宽是另一道闸:HDMI 1.4 的 10.2Gbps 撑到 4K30,4K60 要 HDMI 2.0 的 18Gbps——线不够格,时序参数再对也出不了画。
二、“一个显示模式"到底是什么
所谓模式,不是"宽×高"这么简单,是一组扫描时序参数:像素时钟频率 + 水平/垂直的有效像素数、消隐期(blanking)、同步脉冲位置——显示引擎拿这组参数编排扫描节拍。以 1080p60 为例:像素时钟 148.5MHz,每行有效 1920 像素外加消隐共 2200,每帧行数外加消隐共 1125 行,2200×1125×60Hz ≈ 148.5MHz。切换分辨率 = 重写显示引擎的这组时序寄存器。理解了这一点,“显示模式"就从玄学变成了寄存器值。
三、EDID:显示器的身份证
显示器怎么告诉主机"我是谁、我支持什么”?答案是一块叫 EDID 的只读数据,存在显示器内部的 EEPROM 里,通过DDC 通道(Display Data Channel)访问——本质就是一根 I²C 总线,VGA/HDMI 里捎带的 SCL/SDA 两根线,DisplayPort 则走 AUX 通道,器件地址 0x50。主机"自动适配显示器”,第一步就是通过 DDC 把这 128 字节读出来。
EDID 1.x 布局(128 字节):
| 偏移 | 字段 | 说明 |
|---|---|---|
| 0x00 | 头 | 00 FF FF FF FF FF FF 00 |
| 0x08 | 厂商 ID | 3 个 5 位压缩的大写字母(如 SAM = 三星),16 位大端 |
| 0x0A | 产品码 | 16 位,厂商自定型号编号 |
| 0x0C | 序列号 + 0x10 制造周/年 | 出厂身份 |
| 0x12 | EDID 版本 | 1.3/1.4 |
| 0x14 | 视频输入定义 | 数字(HDMI/DP)/模拟(VGA)位标记 |
| 0x15 | 最大尺寸 | 厘米,对角线兜底信息 |
| 0x23 | 建立时序位图 | 位标记:640×480@60/72/75/85 等 VGA 经典模式支持与否 |
| 0x25 | 标准时序 | 8 组 2 字节编码 |
| 0x36 起 | 详细时序描述符(DTD)×4 | 每个 18 字节——重头戏 |
| 0x7E | 扩展块数 | E-EDID 最多 256 字节 |
| 0x7F | 校验和 | 前 128 字节累加 ≡ 0(mod 256),验证读数完好 |
DTD(18 字节)才是模式清单的核心:像素时钟(2 字节,单位 10kHz)、水平有效/消隐、垂直有效/消隐、同步宽度和偏移、物理尺寸(mm)……第一个 DTD 惯例是显示器的原生模式(preferred timing)——面板的物理分辨率,点对点最清晰。所谓"自动适配"的技术真相:读 EDID → 取首选 DTD → 换算成显示引擎的时序寄存器值。
读回的 128 字节先过两道验证再信:
|
|
厂商 ID 的编码是每字母 5 位(1=A……26=Z),两个字节装三个字母——SAM 三星、DEL 戴尔、AOC 冠捷,现场一眼认出面板是谁家的。校验和不过的 EDID 常见于劣质转接线,别硬解,按 1024×768 安全模式兜底。
四、自动适配在我们系统里是怎么发生的
分层看这段流程归谁做:
- 固件已经做了一遍:UEFI 的 DXE 阶段,GOP 驱动读 EDID、协商模式、初始化显示引擎——所以移交清单里的帧缓冲五元组,就是"协商已完成"的结果。我们的"开机选原生分辨率然后写死"策略之所以成立,是因为脏活累活固件干完了
QueryMode枚举的是固件准备好的模式清单(gop.mode.max_mode个,逐个QueryMode(i)看 info),典型内容是原生模式 + 几个 VESA 安全降级模式——注意这是协商后的可用清单,不是显示器全部能力。全能力要看 EDID 原文- 什么时候需要自己下场:固件清单满足不了(比如固件只给了 1024×768 但面板是 1080p)、或者要多屏/热插拔——那就得自己走一遍"DDC 读 EDID → 解析 DTD → 编显示引擎时序寄存器”。最后一步要查 Intel 显示引擎的寄存器文档(Intel 有公开的显示编程文档可查),这属于后续扩展项:工控单屏固定场景,基础篇吃固件现成饭,够用且稳
QEMU 实验路径:-device VGA,edid=on 生成虚拟 EDID,-device VGA,xres=1920,yres=1080 直接指定模式,配合我们内核把 EDID 头和厂商 ID 打到串口,验读数正确。
五、显存怎么查
两条路径,按显卡形态分:
- Intel 集显:没有独立显存,是共享系统内存(UMA)——固件开机从物理内存里"偷"一块 stolen memory 划给显示用,
frame_buffer_base指向的就是它。这块的踪迹在移交的内存映射里是保留类型描述符,不在可用内存之列(显卡篇第三节的排除清单就是为它准备的)——所以集显平台问"显存多大"其实问错了对象,要问的是帧缓冲需求:pitch × height × 4,1080p 约 8MB,stolen memory 一般 32MB 以上,绰绰有余 - 独显(以后扩展用):显存映射在 BAR 里,容量 = PCIe 篇"写全 1 探测"读回的 BAR 尺寸——那套 BAR 探测代码在显示这就是显存容量探测代码,一块砖两处用
六、品牌型号信息:PCI 配置空间的认亲
显卡的品牌、型号、修订,全部写在 PCIe 配置空间里,枚举篇的偏移表直接查:
| 偏移 | 字段 | 说明 |
|---|---|---|
| 0x00 | Vendor ID | 0x8086 = Intel,0x10DE = NVIDIA,0x1002/0x1022 = AMD |
| 0x02 | Device ID | 具体型号编号,对照厂商设备表查名字 |
| 0x08 | Revision + Class Code | 类码 0x03 显示控制器,子类 0x00 VGA 兼容 / 0x02 显示其它 |
| 0x40 | 子系统厂商/设备 ID | 整卡厂(OEM)信息 |
配合 EDID 里的显示器厂商 ID(SAM 三星、DEL 戴尔、AOC……),整条显示链的"户口本"都能打印到工控系统的硬件信息页:显卡 vendor/device + 显示器厂商/产品码/原生模式 + EDID 物理尺寸——现场排障第一步"知道自己插的是啥"就有了。
七、汇总一张表
| 你想知道 | 去哪查 | 我们的系统怎么拿 |
|---|---|---|
| 当前分辨率/帧缓冲 | GOP ModeInfo | 移交清单五元组(固件已协商) |
| 显示器支持的全部模式 | EDID 的 DTD 列表 | DDC/AUX 读 0x50 器件(需要时自己实现,QEMU 可验) |
| 显示器原生模式 | EDID 首选 DTD | 同上 |
| 显示器厂商/型号 | EDID 0x08-0x0B | 同上 |
| 显存容量 | 集显=UMA(内存映射);独显=BAR 尺寸 | 内存映射 / PCIe 枚举现成代码 |
| 显卡品牌型号 | PCI 配置空间 0x00/0x02/0x40 | PCIe 枚举清单直接认亲 |
| 切换分辨率 | 显示引擎时序寄存器重编程 | 基础篇不做(固定原生模式),扩展项 |
总结
显示子系统的情报体系三层:EDID 是显示器的自述(128 字节、DDC 通道 0x50 器件、DTD 列表是模式清单、首个 DTD 即原生模式,读回先验头和校验和);模式协商是三方交集的取舍(固件已替我们完成,GOP 清单是协商结果不是全部能力);身份信息在 PCI 配置空间(显卡)和 EDID 头(显示器)。显存这件事,集显平台是 UMA + stolen memory,问帧缓冲够不够就行;独显平台就是 BAR 尺寸,枚举代码直接复用。到这里,显示这条线从"能画像素"到"知道自己为什么能画"就完整了。
参考链接
- OSDev Wiki: EDID——128 字节布局与 DTD 解析
- E-EDID 标准(VESA)——权威定义出处
- 本系列显卡篇:Intel集成显卡实战——从GOP帧缓冲接管显示输出、PCIe 篇:ECAM配置空间、BAR探测与MSI配置
- 本系列第一篇:自制工业控制系统:从UEFI到内核
Author 软件开发大郭
LastMod 2026-09-11