DP Link Training 深度解析:从时钟恢复到链路就绪的全过程

一、插上 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.201010101011010101010纯高频分量,延续 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 多两样东西:

  1. 开头的 4 个连续 K28.5:给中间经过的 LTTPR(有源中继器)也做符号对齐
  2. 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 带宽
06hRBR(Reduced Bit Rate)1.62 Gbps
0AhHBR(High Bit Rate)2.7 Gbps
14hHBR25.4 Gbps
1EhHBR38.1 Gbps
LANE_COUNT_SET(00101h)—— 启用几条 Lane
Bit含义
4:0LANE_COUNT:1/2/4(DP 不支持 3 Lane)
7ENHANCED_FRAME_EN:1 = 开启 Enhanced Framing
TRAINING_PATTERN_SET(00102h)—— 切换训练阶段
Bit含义
1:0TRAINING_PATTERN_SELECT:00=Normal, 01=TPS1, 10=TPS2, 11=TPS3
2RECOVERED_CLOCK_OUT_EN
3SCRAMBLING_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:0VOLTAGE_SWING_SET电压摆幅:00=Level 0(最小), 01=Level 1, 10=Level 2, 11=Level 3(最大)
4:3PRE-EMPHASIS_SET预加重:00=Level 0(关闭), 01=Level 1, 10=Level 2, 11=Level 3(最大)
5MAX_SWING_REACHEDSource 置 1 告知 Sink"摆幅已经最大,没法再大了"
6MAX_PRE-EMPHASIS_REACHEDSource 置 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
01h4 ms
02h8 ms
03h16 ms
04h32 ms

Source 在写 TRAINING_PATTERN_SET 之后至少等 100 μs(或该寄存器指定值),再读状态寄存器。

6.2 Source 读取的寄存器(状态端)

LANE0_1_STATUS(00202h)—— Lane 0/1 训练状态
BitLane 0Lane 1含义
0CR_DONELane 0 时钟恢复完成
1CHANNEL_EQ_DONELane 0 信道均衡完成
2SYMBOL_LOCKEDLane 0 符号锁定完成
4CR_DONELane 1 时钟恢复完成
5CHANNEL_EQ_DONELane 1 信道均衡完成
6SYMBOL_LOCKEDLane 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含义
0INTERLANE_ALIGN_DONE:1 = 所有 Lane 已完成去偏移
ADJUST_REQUEST_LANE0_1(00206h)—— Sink 的"指挥棒"
BitLane 0Lane 1含义
1:0VOLTAGE_SWING00=不动, 01=Level 1, 10=Level 2, 11=Level 3
3:2PRE-EMPHASIS00=不动, 01=Level 1, 10=Level 2, 11=Level 3
5:4VOLTAGE_SWING同上
7:6PRE-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 位全 1
  • 0202h = Lane 0 Swing Level 2, Lane 1 Swing Level 2
  • 0000h = “当前参数 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标准协议文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值