一、插上 DP 线,发生了什么
显示器插 DP 线,秒亮。同一台换根长线,闪三四下才亮。换根更差的线,黑屏。
这背后是 DisplayPort 协议栈的初始化流程——Link Training(链路训练)。它发生在 Hot Plug 之后、第一帧画面之前,决定 GPU 和显示器能不能对上话。大部分 DP 黑屏、闪屏、降速问题,根源都在这个过程里。
二、为什么需要训练——没有时钟线
HDMI(TMDS 模式)传视频,数据差分对之外还有一根独立时钟。接收端直接用这个时钟采样数据。
DP 没有独立时钟。接收端必须从数据流里自己恢复时钟(CDR,Clock Data Recovery)。问题是数据流经过线缆后,高频衰减、码间干扰、反射叠加,信号已经不是发送端灌进去的样子了。
GPU 不知道线缆是什么货色——多长?什么材质?连接器接触好不好?所以不能预设参数,只能原地训练:发已知图案 → 接收端给反馈 → 调整参数 → 循环到双方满意。
三、全局流程:从 HPD 到第一帧画面

三个角色:
- Source(GPU):发起训练、发训练图案、调整参数
- Sink(显示器/面板):检测信号质量,通过 DPCD 寄存器反馈
- AUX Channel:1 Mbps 半双工差分通道,所有协商走这里
四、Phase 1: Clock Recovery
目标:让 Sink 的 CDR 锁定发送端的比特时钟。时钟对不上,后面全没法做。
TPS1(Training Pattern 1)
TPS1 是一段不加扰的固定比特序列,边沿密度极高,给 CDR 的 PLL 提供尽可能多的相位调整机会。不加扰是为了最大化边沿密度——加扰会随机化边沿分布,降低 CDR 锁定效率。
实际波形内容:TPS1 = 不断重复的 D10.2 符号(8b/10b 编码)。
D10.2 的 10-bit 编码:
RD- : 0101010101 ← 每 bit 翻转一次
RD+ : 1010101010 ← 每 bit 翻转一次
D10.2 是 8b/10b 编码中边沿密度最高的符号——每个 bit 都跟上一个 bit 不同。对于 CDR 来说,这是最理想的条件:每个 UI(单位间隔)都提供一次相位比较机会。
在示波器上看,TPS1 就是 1.62 / 2.7 / 5.4 / 8.1 GHz 的方波——频率等于 Link Rate 的一半(NRZ 编码下,0101... 的基频 = bit rate / 2)。这就是为什么 CR 锁得快:PLL 只需要锁一个单频信号。
AUX 交互流程——逐寄存器拆解
下面是 CR 阶段一轮完整的 AUX 事务序列。这是 Source(GPU 驱动)里最核心的一段状态机代码。
Step 1 —— 写速率和 Lane 数
Source 通过 AUX Native Write,一次事务写入两个寄存器:
AUX WRITE:
→ 00100h (LINK_BW_SET) = 1Eh // HBR3, 8.1 Gbps/lane
→ 00101h (LANE_COUNT_SET) = 84h // 4 Lane + Enhanced Framing
速率按 Sink 的 DPCD MAX_LINK_RATE(00001h)和 GPU 的驱动策略取交集。高质量线缆用 HBR3(1Eh),差线缆回退到 HBR2(14h)甚至 HBR(0Ah)。
Step 2 —— 进入 TPS1,写初始 Drive 参数
AUX WRITE:
→ 00102h (TRAINING_PATTERN_SET) = 01h // 切换到 TPS1
→ 00103h (TRAINING_LANE0_SET) = 00h // Swing Level 0, Pre-emph 0
→ 00104h (TRAINING_LANE1_SET) = 00h
→ 00105h (TRAINING_LANE2_SET) = 00h
→ 00106h (TRAINING_LANE3_SET) = 00h
初始值永远是 00h(最低 Swing + 零 Pre-emphasis)——在保证信号能锁的前提下最小化功耗。VESA 规范要求 Source 在写 TRAINING_PATTERN_SET 的同时或之前,必须写完所有 TRAINING_LANEx_SET。这是一个原子性要求:Sink 看到 TRAINING_PATTERN_SET 非零值时,会立刻用当前的 TRAINING_LANEx_SET 参数开始评估信号。
Step 3 —— 等待 CDR 锁定
Source 从写完 TRAINING_PATTERN_SET 起,在 Main Link 上持续发送 TPS1 图案。至少等待 100 μs(或 TRAINING_AUX_RD_INTERVAL 寄存器指定的更长时间),再读状态。
Step 4 —— 读取状态,检测 CR_DONE
AUX READ:
← 00202h (LANE0_1_STATUS)
← 00203h (LANE2_3_STATUS)
← 00206h (ADJUST_REQUEST_LANE0_1)
← 00207h (ADJUST_REQUEST_LANE2_3)
Source 检查 00202h 和 00203h 中每条 Lane 的 Bit[0](L0 CR_DONE)、Bit[4](L1 CR_DONE):
LANE0_1_STATUS = 11h → Lane 0 CR_DONE=1, Lane 1 CR_DONE=1 ✓
LANE2_3_STATUS = 11h → Lane 2 CR_DONE=1, Lane 3 CR_DONE=1 ✓
全 Lane CR_DONE = 1 → CR 通过,进入 Phase 2。
任一条 CR_DONE = 0 → Source 进入 Step 5;与此同时,Sink 端在内部评估接收到的 TPS1 信号质量,根据 CDR 锁相环的相位误差幅度,决定需要 Source 把 Voltage Swing 和 Pre-emphasis 调到哪个 Level,并把对应的值写入自身 DPCD 的 ADJUST_REQUEST_LANE0_1(00206h)和 ADJUST_REQUEST_LANE2_3(00207h),等着 Source 下一次 AUX Read 来取。
Step 5 —— 看 ADJUST_REQUEST,调整后重试
Source 读 00206h/00207h,解析每条未锁 Lane 的调整建议:
ADJUST_REQUEST_LANE0_1 = 0202h
→ Lane 0: VOLTAGE_SWING=10b (Level 2), PRE-EMPHASIS=00b (Level 0)
→ Lane 1: VOLTAGE_SWING=10b (Level 2), PRE-EMPHASIS=00b (Level 0)
Source 按建议更新 TRAINING_LANEx_SET,重写:
AUX WRITE:
→ 00103h = 02h // Lane 0: Swing Level 2
→ 00104h = 02h // Lane 1: Swing Level 2
→ 00105h = 02h // Lane 2: Swing Level 2
→ 00106h = 02h // Lane 3: Swing Level 2
不需要重写 00102h——Sink 仍在 TPS1 模式,它只是等着读新的 TRAINING_LANEx_SET 值然后评估信号。写完后 Source 再等 100 μs,回到 Step 4 重新读状态。
CR 阶段的循环与降级
DP 2.0 规范(Section 3.5.1.2.2, Page 744)为 CR 阶段定义了三个精确的退出条件,任一满足即触发降速:
条件 #1 —— 驱动已经最大:Source 已经把 Voltage Swing + Pre-emphasis 调到最高等级(发送器物理极限),但 Sink 仍不置 CR_DONE。
条件 #2 —— 同一个 ADJ_REQ 连续 5 次不锁:Sink 连续 5 次 AUX Read 都返回相同的 ADJUST_REQUEST 值,但 CR_DONE 仍为 0。这说明 Sink 已经找不到更好的参数了——当前驱动设置无论怎么调,CDR 都锁不上。
条件 #3 —— 累计 10 次 AUX Read 仍不锁:从 CR 阶段开始算起,Source 一共读了 10 次 LANEx_CR_DONE + ADJUST_REQUEST,但 CR_DONE 始终不全。这是一个兜底上限,防止训练无限循环。
注意:条件 #2 和 #3 中的"5 次""10 次"是 Source 端(GPU 驱动)内部的软件计数器,Source 自己计数 AUX Read 次数,达到阈值后触发降速。这两个阈值由规范定义但不由任何 DPCD 寄存器记录,Sink 不知道当前重试到第几次了。
这三个条件在规范里的原文流程图(Figure 3-12)中清晰标记为 #1、#2、#3。

降级路线:
条件触发(#1 或 #2 或 #3)
↓
降速率:HBR3 → HBR2 → HBR → RBR(回到 Step 1,重新开始整个 CR)
↓ 最低速率仍不行
减 Lane 数:4 → 2 → 1(只保留已 CR_DONE 的 Lane,其余禁用)
每一步降级都意味着从头(Step 1)重新来:重写 LINK_BW_SET(速率变了)或 LANE_COUNT_SET(Lane 数变了),重写 00h 的 TRAINING_LANEx_SET,重发 TPS1,重等 100 μs。
CR 调整优先级
调整 Drive(Voltage Swing ↑, Pre-emphasis ↑)
↓ 不行
降 Link Rate(8.1 → 5.4 → 2.7 → 1.62 Gbps)
↓ 不行
减 Lane Count(4 → 2 → 1)
逻辑:先加大驱动(多费电),不行再降速(牺牲带宽),最后减通道(牺牲更多带宽)。
Voltage Swing 与 Pre-emphasis
VESA 定义了各 4 个 Level(0-3)。Source 通过 TRAINING_LANEx_SET 的 Bit[1:0](Swing)和 Bit[4:3](Pre-emphasis)设置,Sink 通过 ADJUST_REQUEST 反馈需要的 Level。位域编码见第六节。
规范(Table 3-2)对 Swing 和 Pre-emphasis 的组合有限制:并非所有 Level 组合都合法。比如 HBR3/HBR2 下 Swing Level 3 只允许搭配 Pre-emphasis Level 0,Swing Level 2 不允许搭配 Pre-emphasis Level 2/3。具体以规范 Table 3-2 的矩阵为准。发送器必须至少支持 Level 0-2,Level 3 可选。V_diff_pp 上限 1.38 V(Table 3-39)。
Pre-emphasis 定义(Section 3.1.5.2):20 × log10(VDIFF-PRE / VDIFF),即信号跳变后第一个 bit 的幅度与后续稳态 bit 幅度之比。
五、Phase 2: Channel EQ + Symbol Lock + Inter-lane Alignment
时钟锁了,但信号质量可能还不够。Phase 2 三个并行的目标:
Channel Equalization:补偿线缆的高频损耗。线缆是低通滤波器——8.1 Gbps 经过几米后高频衰减严重,1 和 0 的边界模糊(码间干扰)。均衡器反向放大高频分量。
Symbol Lock:找到 8b/10b 编码的符号边界。比特锁了,但 10 个比特哪个是头还不知道——接收端靠 K28.5 逗号码做符号对齐。
Inter-lane Alignment:多 Lane 场景下各 Lane 到达时间不一致。DP 规范要求 Source 在相邻 Lane 间故意插入 2 个 Link Symbol 的偏移(inter-lane skew),接收端在训练阶段完成去偏移。
TPS2 / TPS3 / TPS4
| Pattern | 用途 | 加扰? | 场景 |
|---|---|---|---|
| TPS2 | 信道均衡 | 否 | RBR / HBR / HBR2 |
| TPS3 | 均衡(含中继器) | 否 | 链路有 LTTPR |
| TPS4 | 信道均衡 | 是 | HBR3(8.1 Gbps) |
TPS4 加扰是因为 HBR3 的速率下,不加扰的固定图案会产生集中的频谱尖峰,干扰 Wi-Fi 和蜂窝天线。加了扰的 TPS4 看起来像随机噪声。
训练图案的实际内容——Source 到底在发什么符号
以上几种训练图案不是随机的比特流,而是 VESA 规范明确定义的 8b/10b 符号序列(TPS4 例外,额外加扰)。下表来自 DP 2.0 规范的 Table 3-11。
TPS2 —— 10 符号循环序列(不加扰)
K28.5- , D11.6 , K28.5+ , D11.6 , D10.2 , D10.2 , D10.2 , D10.2 , D10.2 , D10.2
10 个符号组成一个循环,反复发送。解读每个符号的角色:
| 符号 | 8b/10b 编码(10-bit) | 作用 |
|---|---|---|
| K28.5- | 0011111010 | 逗号码——Sink 用它找符号边界(Symbol Lock),因为 0011111 这个 7-bit 序列在正常数据中永不出现 |
| K28.5+ | 1100000101 | 同上(Running Disparity 为正时的编码) |
| D11.6 | 含中频分量 | 给均衡器提供中频参考——不同于 TPS1 的纯高频,D11.6 有更丰富的频谱分量 |
| D10.2 | 0101010101 或 1010101010 | 纯高频分量,延续 CR 阶段的边沿密度,确保时钟不丢 |
TPS2 的设计思路:逗号码做对齐,高频 + 中频混合做均衡。K28.5 出现在序列开头,Sink 扫描这个特定比特序列就能找到符号边界。
TPS3 —— 42 符号长序列(不加扰,含 LTTPR 支持)
K28.5- , K28.5+ , K28.5- , K28.5+ , ← 4 个逗号码(给中继器做对齐)
D10.2- , D10.2- , ... (×12) , ← 12 个 D10.2(高频)
K28.5- , K28.5+ , ← 中间再插逗号码
D30.3- , D30.3+ , D30.3- , D30.3+ , ← 16 对 D30.3(低频)
... (×16 对)
TPS3 比 TPS2 多两样东西:
- 开头的 4 个连续 K28.5:给中间经过的 LTTPR(有源中继器)也做符号对齐
- D30.3 长序列:D30.3 含有更丰富的低频分量,均衡器能从中提取线缆的低频响应,补全频率覆盖
TPS4 —— 252 个 10-bit 符号,含加扰(HBR3 专用)
TPS4 的序列结构与 CP2520 Pattern 3 相同(DP 物理层一致性测试规范):
K28.0- , K28.5- , K28.5+ , K28.0- , ← 4 个控制符号开头
再加 248 个 00h 数据 → 经加扰器 → 8b/10b 编码 → 发送
TPS4 的核心区别在于加扰。Source 先取 248 个 0x00 字节,通过 DP 的 16-bit 并行加扰器(多项式 G(x) = x^16 + x^5 + x^4 + x^3 + 1)生成伪随机序列,再做 8b/10b 编码发送。
加扰后的 TPS4 频谱接近白噪声——没有 TPS2 那种集中在 D10.2 频率上的尖峰。这对 HBR3(8.1 Gbps)至关重要,因为不加扰的固定图案会在 4.05 GHz 附近产生强烈 EMI 辐射。
四种图案的频谱特性对比
四种图案本质上是不同频率分量的组合,Sink 从中提取线缆在不同频段的衰减信息:
| 图案 | 频率分量 | 频谱形状 | 用途 |
|---|---|---|---|
| TPS1 | 纯高频:D10.2 逐 bit 翻转,频率 = bit rate ÷ 2(HBR3 下 4.05 GHz 方波) | 单根线 | CDR 锁相——PLL 只需要追一个频率 |
| TPS2 | 高频 + 中频:D10.2(4.05 GHz)+ D11.6(中频分量)+ K28.5(低频逗号码) | 几根离散线 | EQ 均衡——覆盖高频和中频,均衡器可以算出线缆的滚降曲线 |
| TPS3 | 高频 + 中频 + 低频:TPS2 的基础 + D30.3 长序列(大量低频分量) | 覆盖面更宽 | EQ 均衡 + 中继器对齐——低频分量让均衡器看到线缆的全频段响应 |
| TPS4 | 全频段噪声:248 字节 00h 经加扰后频谱平坦,接近白噪声 | 铺满 | EQ 均衡 + 过 EMI 认证——没有集中尖峰,不会干扰 Wi-Fi/蜂窝 |
关键理解:均衡器之所以能工作,是因为它知道 Source 发了什么符号。收到了 → 比较实际波形和理想波形 → 差值就是线缆的频率响应 → 反向放大高频 = 均衡。TPS1 只有一个频率,所以只能锁时钟;TPS2/TPS3 有多个频率,均衡器才能建立完整的补偿曲线。TPS4 加扰后频谱铺满整个带宽,均衡器能看到线缆在所有频率上的衰减——代价是必须知道加扰器的初始种子值才能做"已知序列"比较。
AUX 交互流程——逐寄存器拆解
Phase 2 比 CR 多了两个检查维度:均衡完成 + 符号锁定 + Lane 间对齐。一个 Lane 必须同时满足 CR_DONE=1、CH_EQ_DONE=1、SYMBOL_LOCKED=1,才算完成。
Step 1 —— 进入 EQ 阶段
Source 继承 CR 阶段最终收敛的 Swing/Pre-emphasis 值,切换训练图案:
AUX WRITE:
→ 00102h (TRAINING_PATTERN_SET) = 02h // TPS2(HBR2 及以下)
如果 HBR3 → = 07h // TPS4(加扰)
注意:不重写 TRAINING_LANEx_SET——沿用 CR 最后的值。速率和 Lane 数也不变。
Source 同步在 Main Link 上切换训练图案。TPS2 和 TPS4 都包含更复杂的序列,允许 Sink 内部调整 CTLE(连续时间线性均衡器)增益和 DFE(判决反馈均衡器)抽头系数。
Step 2 —— 等待均衡收敛
Sink 内部的均衡器是自适应电路。TPS2/TPS4 图案包含了足够丰富的频率分量,均衡器在接收图案的过程中逐步收敛到最优系数。
Step 3 —— 读取 EQ 状态,三合一判断
AUX READ:
← 00202h (LANE0_1_STATUS)
← 00203h (LANE2_3_STATUS)
← 00204h (LANE_ALIGN_STATUS_UPDATED)
← 00206h (ADJUST_REQUEST_LANE0_1)
← 00207h (ADJUST_REQUEST_LANE2_3)
对每条 Lane 做三个检查:
以 Lane 0 为例(00202h):
Bit 0: CR_DONE = 1 ✓ // CR 不能丢!
Bit 1: CHANNEL_EQ_DONE = 1 ✓
Bit 2: SYMBOL_LOCKED = 1 ✓
00204h Bit[0] = 1 表示所有 Lane 已完成 Inter-lane Alignment。
注意:CR_DONE 在 Phase 2 中必须保持为 1。如果某 Lane 的 CR_DONE 在 EQ 阶段清零,说明在均衡过程中时钟锁丢了——这时 Source 应回到 Phase 1 重新做 CR。
Step 4 —— 不全过,调整 Drive 重试
任一条 Lane 三个位不全为 1 → Source 读 ADJUST_REQUEST,Sink 端也在同步动作:它的自适应均衡器(CTLE + DFE)持续分析 TPS2/TPS4 中不同频率分量的衰减,计算出需要多大的 Pre-emphasis 才能补偿线缆的高频损耗,把这个需求写入 00206h/00207h。Source 读取后更新 TRAINING_LANEx_SET 写回给 Sink。
调整逻辑与 CR 一致,但 EQ 阶段 Sink 可能单独调整 Pre-emphasis(均衡阶段对预加重更敏感):
ADJUST_REQUEST_LANE0_1 = 0808h
→ Lane 0: VOLTAGE_SWING=00b (不动), PRE-EMPHASIS=10b (Level 2)
→ Lane 1: VOLTAGE_SWING=00b (不动), PRE-EMPHASIS=10b (Level 2)
Source 更新:
AUX WRITE → 00103h = 08h (Swing 0, Pre-emph 2)
EQ 阶段有明确的 maximum loop counter = 5。这是 DP 规范(Section 3.5.1.2.3, Page 748)明确规定的:EQ 最多重试 5 轮。第 6 轮(loop counter > 5)仍未通过 → 降速或降 Lane 数,回到 CR 重新训练。

注意:这个 Loop Counter 同样是 Source 端内部的软件计数器,由 GPU 驱动维护,不写入任何 DPCD 寄存器。规范只定义了"最多 5 轮"的行为要求,具体怎么计由 Source 实现决定。
EQ 阶段的完整状态流转
进入 EQ(继承 CR 参数)
│
▼
写 TRAINING_PATTERN_SET = 02h/07h
│
▼
等 ≥ 100 μs → 读 00202h/00203h
│
├─ 全 Lane 三合一 ✓ → 读 00204h
│ │
│ ├─ ALIGN_DONE = 1 → EQ 通过!
│ └─ ALIGN_DONE = 0 → 再等一轮
│
└─ 不全过 → 读 ADJUST_REQUEST → 更新 TRAINING_LANEx_SET
│
├─ Loop < 5 → 回 Step 2
└─ Loop = 5 → 降速/降 Lane → 回到 CR 重来
Loop Counter 为 Source 端软件变量,不存于 DPCD。
完成后
AUX WRITE:
→ 00102h (TRAINING_PATTERN_SET) = 00h // Normal Active
链路进入正常工作模式。GPU 开始发视频流(含 MSA 包,Mvid/Nvid 用于 Sink 恢复像素时钟),显示器出画面。
六、DPCD 寄存器速查
Training 的本质是 Source 和 Sink 通过 DPCD 寄存器完成的一轮轮"写→等→读→调"循环。下面逐个拆解每个寄存器的作用和位域布局。
6.1 Source 写入的寄存器(控制端)
LINK_BW_SET(00100h)—— 写死链路速率
Source 一次写入,整个 Training 过程中不再改(除非降速重训)。
| 值 | 速率 | 每 Lane 带宽 |
|---|---|---|
| 06h | RBR(Reduced Bit Rate) | 1.62 Gbps |
| 0Ah | HBR(High Bit Rate) | 2.7 Gbps |
| 14h | HBR2 | 5.4 Gbps |
| 1Eh | HBR3 | 8.1 Gbps |
LANE_COUNT_SET(00101h)—— 启用几条 Lane
| Bit | 含义 |
|---|---|
| 4:0 | LANE_COUNT:1/2/4(DP 不支持 3 Lane) |
| 7 | ENHANCED_FRAME_EN:1 = 开启 Enhanced Framing |
TRAINING_PATTERN_SET(00102h)—— 切换训练阶段
| Bit | 含义 |
|---|---|
| 1:0 | TRAINING_PATTERN_SELECT:00=Normal, 01=TPS1, 10=TPS2, 11=TPS3 |
| 2 | RECOVERED_CLOCK_OUT_EN |
| 3 | SCRAMBLING_DISABLE(置 0 则加扰) |
TPS4 的写法特殊:写 07h(即 Bit[3:0]=0111),低 2 位为 11 选 TPS3,Bit[2]=1 表示启用 scrambling。
TRAINING_LANEx_SET(00103h-00106h)—— 每 Lane 的物理层参数
这是 Source 执行 Sink 建议的"动作寄存器",按 Lane 独立配置:
| Bit | 字段 | 含义 |
|---|---|---|
| 1:0 | VOLTAGE_SWING_SET | 电压摆幅:00=Level 0(最小), 01=Level 1, 10=Level 2, 11=Level 3(最大) |
| 4:3 | PRE-EMPHASIS_SET | 预加重:00=Level 0(关闭), 01=Level 1, 10=Level 2, 11=Level 3(最大) |
| 5 | MAX_SWING_REACHED | Source 置 1 告知 Sink"摆幅已经最大,没法再大了" |
| 6 | MAX_PRE-EMPHASIS_REACHED | Source 置 1 告知 Sink"预加重已经最大" |
地址分配:00103h = Lane 0,00104h = Lane 1,00105h = Lane 2,00106h = Lane 3。
Training 开始时写 00h(Swing Level 0, Pre-emphasis Level 0)——最低功耗起步。
TRAINING_AUX_RD_INTERVAL(0000Eh)—— Source 该多久读一次状态
Sink 通过此寄存器告诉 Source"我多久能准备好一次新的状态更新":
| 值 | 含义 |
|---|---|
| 00h | 默认 100 μs |
| 01h | 4 ms |
| 02h | 8 ms |
| 03h | 16 ms |
| 04h | 32 ms |
Source 在写 TRAINING_PATTERN_SET 之后至少等 100 μs(或该寄存器指定值),再读状态寄存器。
6.2 Source 读取的寄存器(状态端)
LANE0_1_STATUS(00202h)—— Lane 0/1 训练状态
| Bit | Lane 0 | Lane 1 | 含义 |
|---|---|---|---|
| 0 | CR_DONE | — | Lane 0 时钟恢复完成 |
| 1 | CHANNEL_EQ_DONE | — | Lane 0 信道均衡完成 |
| 2 | SYMBOL_LOCKED | — | Lane 0 符号锁定完成 |
| 4 | — | CR_DONE | Lane 1 时钟恢复完成 |
| 5 | — | CHANNEL_EQ_DONE | Lane 1 信道均衡完成 |
| 6 | — | SYMBOL_LOCKED | Lane 1 符号锁定完成 |
LANE2_3_STATUS(00203h)—— Lane 2/3 训练状态
位域布局与 00202h 完全一致,Bit[0:2] 对应 Lane 2,Bit[4:6] 对应 Lane 3。
注意:CR 阶段只看 CR_DONE;EQ 阶段三个位全看(CR_DONE 必须保持为 1,否则 CR 已丢)。
LANE_ALIGN_STATUS_UPDATED(00204h)
| Bit | 含义 |
|---|---|
| 0 | INTERLANE_ALIGN_DONE:1 = 所有 Lane 已完成去偏移 |
ADJUST_REQUEST_LANE0_1(00206h)—— Sink 的"指挥棒"
| Bit | Lane 0 | Lane 1 | 含义 |
|---|---|---|---|
| 1:0 | VOLTAGE_SWING | — | 00=不动, 01=Level 1, 10=Level 2, 11=Level 3 |
| 3:2 | PRE-EMPHASIS | — | 00=不动, 01=Level 1, 10=Level 2, 11=Level 3 |
| 5:4 | — | VOLTAGE_SWING | 同上 |
| 7:6 | — | PRE-EMPHASIS | 同上 |
关键规则:ADJUST_REQUEST 的值是绝对值而非相对增量。Source 读到 0202h(Lane 0 Swing Level 2, Lane 1 Swing Level 2),就往 TRAINING_LANE0_SET 写 02h、TRAINING_LANE1_SET 写 02h。
ADJUST_REQUEST_LANE2_3(00207h)
布局与 00206h 完全对称,对应 Lane 2/3。
LINK_STATUS_UPDATED(00200h / 00204h Bit[0])
训练成功后的运行时监控寄存器。当 Sink 检测到链路失效时,会清除对应 DONE 位并置 LINK_STATUS_UPDATED = 1,同时通过 IRQ HPD 通知 Source。
6.3 Sink 是怎么"指挥"的
Sink 内部有一定自主权:它说了"需要 Level 2 的 Swing",Source 必须照做,但 Sink 也可以在 ADJUST_REQUEST 里持续回 00h(“当前参数没问题”)——这意味着即使某些 DONE 位还没置 1,Sink 也认为问题不在驱动电平上,而在于需要更多时间或降速处理。
Sink 回 00h → "当前参数 OK,别动"
Sink 回 02h → "Swing 调到 Level 2"
Sink 回 22h → "Swing 调到 Level 2,Pre-emphasis 也调到 Level 2"
Sink 回 82h → "Lane 1 调到 Swing Level 2,Lane 0 不动"
七、完整训练过程:从 AUX 事务看全过程
下面是把前面所有寄存器拼起来,一次成功的 HBR3 4-Lane 训练在 AUX 总线上的完整对话(省略 EDID 读取等前置步骤)。
7.1 AUX 事务轨迹(正常训练)
Round 0: 配置阶段
AUX WRITE 00100h = 1Eh // LINK_BW_SET → HBR3
AUX WRITE 00101h = 84h // LANE_COUNT_SET → 4 Lane + Enhanced
AUX WRITE 00102h = 01h // TRAINING_PATTERN_SET → TPS1
AUX WRITE 00103h = 00h // Lane 0: Swing 0, Pre-emph 0
AUX WRITE 00104h = 00h // Lane 1: Swing 0, Pre-emph 0
AUX WRITE 00105h = 00h // Lane 2: Swing 0, Pre-emph 0
AUX WRITE 00106h = 00h // Lane 3: Swing 0, Pre-emph 0
[等 ≥ 100 μs]
Round 1: CR 第 1 次检查
AUX READ 00202h → 11h // L0/1 CR_DONE
AUX READ 00203h → 11h // L2/3 CR_DONE
AUX READ 00206h → 0202h // ADJ: L0/1 need Swing Level 2
AUX READ 00207h → 0202h // ADJ: L2/3 need Swing Level 2
→ CR 不全过 → 调整
AUX WRITE 00103h = 02h // Lane 0: Swing 2
AUX WRITE 00104h = 02h // Lane 1: Swing 2
AUX WRITE 00105h = 02h // Lane 2: Swing 2
AUX WRITE 00106h = 02h // Lane 3: Swing 2
[等 ≥ 100 μs]
Round 2: CR 第 2 次检查
AUX READ 00202h → 11h // L0/1 CR_DONE ✓
AUX READ 00203h → 11h // L2/3 CR_DONE ✓
AUX READ 00206h → 0000h // ADJ: 全 OK
AUX READ 00207h → 0000h // ADJ: 全 OK
→ CR 全部通过!进入 EQ
Round 3: EQ 第 1 轮(loop=1)
AUX WRITE 00102h = 07h // TRAINING_PATTERN_SET → TPS4
[等 ≥ 100 μs]
AUX READ 00202h → 77h // L0/1: CR=1, EQ=1, SYM=1 ✓ (0111 0111)
AUX READ 00203h → 77h // L2/3: CR=1, EQ=1, SYM=1 ✓
AUX READ 00204h → 01h // ALIGN_DONE ✓
→ EQ 全部通过!
完成:
AUX WRITE 00102h = 00h // Normal Active
→ 链路就绪,开始传视频!
解读一下关键返回值:
11h=0001 0001:Lane 0 CR_DONE=1, Lane 1 CR_DONE=1(Bit[0] 和 Bit[4])77h=0111 0111:Lane 0 三个 DONE 位全 1, Lane 1 三个 DONE 位全 10202h= Lane 0 Swing Level 2, Lane 1 Swing Level 20000h= “当前参数 OK,别动”
八、Link Maintenance:训练完不等于没事了
Link Training 成功只说明当前时刻状态好。链路运行中可能出三种问题:
| 失效 | 原因 |
|---|---|
| 时钟失锁 | 线缆抖动、温度漂移 |
| 符号锁丢失 | 突发误码破坏了 K 码检测 |
| Lane 间对齐丢失 | 某 Lane 短暂失锁 |
流程:Sink 检测到失效 → 清除对应 DONE 位 + 置 LINK_STATUS_UPDATED(00200h Bit[0] = 1)→ 拉 IRQ HPD(低脉冲 0.5-1ms)→ Source 在 100ms 内读 DPCD 00200h-00205h → 重新执行完整 Link Training → 若失败,降速重试。
Link Maintenance 的寄存器读取序列:
IRQ HPD 触发
│
▼
Source 读 00200h (SINK_COUNT / LINK_STATUS_UPDATED)
│ Bit[0]=1 → 确认是链路状态变化
▼
Source 读 00202h (LANE0_1_STATUS)
Source 读 00203h (LANE2_3_STATUS)
Source 读 00204h (LANE_ALIGN_STATUS_UPDATED)
│ 看谁丢了 DONE 位
▼
Source 写 00102h = 01h (TPS1) → 重新 Link Training
期望用原参数快速恢复,若失败则按正常流程降级
IRQ HPD 说白了就是 Sink 对 Source 说"出事了,你来看"。Source 得自己去 DPCD 里搞清楚哪个 Lane、哪个阶段的问题。
九、DP 2.0 / UHBR 的变化
DP 2.0 引入了 128b/132b 编码和 UHBR 速率(10 / 13.5 / 20 Gbps/lane)。Link Training 的 CR + EQ 框架不变,但:
- 训练图案为 32-bit Symbol 结构重新定义,不再用 TPS1-4
- UHBR20 的高频衰减极严重,EQ 训练精度要求远高于 HBR3
- LTTPR(有源中继器)在 UHBR 链路几乎成了标配
- UHBR 模式强制 DSC,训练前需额外协商
框架完全一样,细节换了一套参数。理解了 DP 1.4 的 Training,DP 2.0 基本就是同一张流程图换数字。
十、常见问题排查——分角色视角
同一个黑屏,Source 开发者看到的和 Sink 开发者看到的完全不同。下面按角色拆开讲。
10.1 Source 端(GPU / 驱动开发者)
Source 是训练的发起方,能主动读写 DPCD,排查的起点是"我的 AUX 事务有没有正常完成",是否能从 DPCD 看到 Sink 端的 Training 反馈。
Training 根本不启动:先确认 HPD 电平是否 > 2V,再抓 AUX 总线看 00100h(LINK_BW_SET)是否有写入。没写入 → AUX 不通(查差分对正负、终端 100Ω)。有写入但无后续状态读 → 驱动状态机未正确调用。
CR 阶段反复失败:读 00202h/00203h 逐 Lane 查 CR_DONE。同步看 00206h/00207h 的 ADJUST_REQUEST:如果一直回 00h 但 CR_DONE 不置 1 → Sink 内部 CDR 问题(参考时钟、PLL 配置);如果 ADJ_REQ 逐步增大 → 线缆衰减严重,Sink 在请求更强的驱动;如果 LINK_BW_SET 反复从 1Eh→14h→0Ah→06h → GPU 在不断降速重训。条件 #2(连续 5 次同 ADJ_REQ)或 #3(累计 10 次)触发 → 降速或降 Lane。
EQ 阶段失败:某 Lane CR_DONE 在 EQ 中清零 → 时钟丢了,回 CR;全 Lane 三 DONE 位都是 1 但 00204h Bit[0]=0 → Inter-lane 对齐超时,Lane 间 skew 超出 Sink 去偏移范围。Loop Counter 到 5 → 先降 Lane 再降速。
Link Maintenance 频繁触发:查 IRQ HPD → 00200h Bit[0]=1 → 看 00202h/00203h 谁丢了位。检查该 Lane 的眼图、抖动、连接器触点。
降速:读 00100h,如果从 1Eh 变成了 0Ah → Training 在 HBR3 失败降到了 HBR。检查线缆是否满足对应速率的损耗要求。
10.2 Sink 端(显示器 / 面板开发者)
Sink 是被动方,排查的起点是"Source 有没有来碰我的 DPCD",以及当每一次 Training 尝试失败时,有没有给出正确的 ADJUST_REQUEST 反馈,Training 成功时有没有正常把标志位拉高。
Source 根本没来:确认 HPD 是否正确拉高(> 2V)。量 AUX_P/AUX_N 差分对上有无 1 Mbps 曼彻斯特编码信号。没有 → Source 端问题;有 → 检查 Sink 的 AUX PHY 是否正确回应。
AUX 通但反复训练失败:确认 MAX_LINK_RATE(00001h)和 MAX_LANE_COUNT(00002h)返回值不为 00h。确认 TPS1 到达后 CDR 锁定检测逻辑是否正确,ADJUST_REQUEST 值是否合理(应随 Source 调大 Swing 逐步归零)。如果一直回 00h 但 CR_DONE 不置 1 → CDR 评估逻辑有 bug。EQ 阶段检查 CTLE 增益和 DFE tap 系数是否在 TPS2/TPS4 下正确收敛,K28.5 逗号码检测阈值是否合理。
CR_DONE 置不了:查 CDR PLL 参考时钟频率、PLL 倍频系数、锁相环带宽配置(规范 Table 3-47)。用示波器在 Sink 输入端测 TP3_EQ 眼图。可能软件逻辑有 bug——实际上锁了但没写 DPCD。
EQ_DONE / SYMBOL_LOCKED 置不了:均衡器是否在处理 TPS2 的各频率分量,CTLE 增益是否足够。Inter-lane 对齐失败 → Lane 间 skew 超出 Sink 去偏移范围,Sink 去偏移 FIFO 深度是否足够。
ADJUST_REQUEST 策略:CDR 快锁了但差一点 → 小幅度加 Swing(Level 1/2);相位误差很大 → 加 Swing Level 3;幅度够但高频衰减严重 → 保持 Swing,加 Pre-emphasis;信号已经很好了 → 回 00h,等 CDR 自锁。
十一、总结
Link Training 的设计思路:没有独立时钟,电缆特性未知,Source 和 Sink 通过 AUX 协商 + Main Link 训练图案 + DPCD 状态反馈,自动找到最佳物理层参数。
排 DP 黑屏问题,记住这条线:先看 HPD 有没有,再抓 AUX 读没读,按照AUX Log和DPCD寄存器的内容,逐步定位是卡在什么阶段?CR没过还是EQ不过?还是通道对不齐?有没有symbol error等等,逐步定位问题的原因。
关注公众号:FPGAer Zone,回复关键字:“DP”,自动获取DP标准协议文档。
1054

被折叠的 条评论
为什么被折叠?



