深入eDP协议栈:从PSR SDP发送到Main Link开关,一次搞懂屏幕自刷新的完整信令流程
深入eDP协议栈:从PSR SDP发送到Main Link开关,一次搞懂屏幕自刷新的完整信令流程
在显示技术的演进中,嵌入式DisplayPort(eDP)协议因其高效能和低功耗特性,已成为移动设备和高端显示器的首选接口。其中,面板自刷新(PSR)功能通过智能管理主链路状态,可显著降低系统功耗——这对需要长续航的笔记本电脑和便携设备尤为重要。本文将拆解PSR全流程的信令交互,结合寄存器操作和时序控制,为显示驱动开发者提供可直接落地的实现方案。
1. PSR技术基础与硬件准备
PSR的核心思想是在帧内容不变时关闭主链路传输,由显示面板本地缓存维持图像输出。要实现这一功能,需要显示控制器(Source)和面板(Sink)双方的协同工作。硬件层面需确认以下关键点:
- eDP版本支持:检查DPCD 0000h寄存器的PSR_SUPPORT字段(bit 31)
- 面板能力验证:通过DPCD 070h确认SINK_PSR_CAPS
- 帧缓存配置:确保FB足够存储至少一帧未压缩图像(DPCD 071h的Y_SIZE/LINE_BYTES)
注意:某些面板要求PSR进入前完成完整的链路训练(Link Training),这需要检查DPCD 0200h的TRAINING_AUX_RD_INTERVAL
典型初始化流程如下:
// 检查PSR支持 uint32_t dpcd_caps = read_dpcd(ADDR_DPCD_REV); if (!(dpcd_caps & DPCD_PSR_SUPPORT)) { printk("PSR not supported by sink device\n"); return -ENOTSUPP; } // 配置帧缓冲区参数 write_dpcd(ADDR_PSR_Y_SIZE, y_resolution); write_dpcd(ADDR_PSR_LINE_BYTES, bytes_per_line);2. PSR进入流程的信令时序
2.1 垂直消隐期与SDP发送
PSR进入流程始于垂直消隐期(VBlank)内的Secondary Data Packet(SDP)发送。此时序选择基于两个考量:
- 避免干扰有效像素传输
- 为面板预留足够的建立时间(PSR_SETUP_TIME)
关键寄存器操作包括:
| 寄存器地址 | 操作位 | 功能描述 |
|---|---|---|
| DPCD 600h | Bit 0 | 置1触发PSR进入序列 |
| DPCD 601h | Bit 7:0 | 配置PSR进入延迟(VSYNC到SDP的间隔) |
def send_psr_enter(): # 在VBlank开始后延迟配置的时钟周期 wait_vblank() delay(psr_setup_time) # 构造并发送PSR SDP包 sdp_packet = build_sdp(type=PSR_ENTER, payload=[0x00, 0x1E, 0x00, 0x00]) aux_ch_write(SDP_PACKET_REG, sdp_packet)2.2 Main Link关闭决策
发送SDP后,Source需根据以下因素决定是否关闭Main Link:
- 帧内容稳定性:通过CRC校验确认连续3帧无变化
- 功耗策略:根据DPCD 00603h的PSR_MAIN_LINK_CTL字段
- 面板响应时间:参考DPCD 070h的PSR_EXIT_TO_ACTIVE_TIME
关闭主链路的典型操作为:
void disable_main_link(void) { // 停止视频流传输 write_reg(VIDEO_ENABLE_REG, 0x00); // 关闭PHY层供电 write_reg(PHY_POWER_CTL, POWER_DOWN); // 记录链路状态 g_link_state = LINK_OFF; }3. PSR运行期间的维持机制
3.1 面板自刷新维持
进入PSR状态后,面板依靠本地帧缓存维持显示,此时Source需:
- 持续监控AUX通道的HPD信号
- 定期发送Idle Pattern(每500ms)
- 处理可能的远程帧更新请求
维持阶段的关键参数:
| 参数 | 寄存器地址 | 典型值 |
|---|---|---|
| Idle Pattern间隔 | DPCD 0604h | 0x1F4 (500ms) |
| 帧更新超时 | DPCD 0605h | 0x3E8 (1000ms) |
3.2 低功耗状态管理
在深度PSR模式下(PSR2),可进一步降低系统功耗:
- 内存自刷新:通过DPCD 0607h配置DRAM刷新率
- 时钟门控:关闭不必要的显示控制器时钟域
- 电压调节:根据DPCD 0608h设置IO电压等级
提示:PSR2的深度休眠可能增加唤醒延迟,需在功耗和响应速度间权衡
4. PSR退出流程与链路恢复
4.1 唤醒事件处理
以下事件会触发PSR退出:
- 内容更新:帧缓冲区差异超过阈值(DPCD 0609h)
- 用户交互:检测到输入设备活动
- 超时事件:达到DPCD 0605h配置的超时值
唤醒序列的第一步是通过AUX通道发送PSR_EXIT SDP:
def handle_wake_event(): # 发送PSR退出SDP exit_sdp = build_sdp(type=PSR_EXIT) aux_ch_write(SDP_PACKET_REG, exit_sdp) # 启动主链路供电 power_up_phy() # 等待面板响应 timeout = read_dpcd(ADDR_PSR_EXIT_TIMEOUT) wait_panel_ready(timeout)4.2 链路训练与状态同步
PSR退出后的关键步骤是链路恢复:
- 快速链路训练:使用DPCD 0200h存储的参数
- 状态验证:检查DPCD 0600h的PSR_STATUS
- 帧同步:等待下一个VBlank开始视频流
典型训练代码如下:
int retrain_link(void) { // 应用预存的训练参数 apply_saved_training(); // 执行快速CR/CE训练 if (train_cr_ce() != SUCCESS) { // 失败时回退到全训练 full_link_training(); } // 验证链路状态 uint8_t status = read_dpcd(ADDR_PSR_STATUS); return (status & PSR_ACTIVE) ? 0 : -EIO; }5. 调试技巧与常见问题
5.1 时序问题排查
PSR实现中最常见的三类时序问题:
- SDP发送过早:导致面板错过进入指令
- 解决方案:增加DPCD 601h的延迟值
- 唤醒响应超时:面板未及时退出PSR
- 检查:DPCD 070h的PSR_EXIT_TO_ACTIVE_TIME
- 链路训练失败:退出后无法恢复视频
- 对策:保存训练参数到DPCD 0200h
5.2 寄存器调试技巧
推荐使用以下寄存器监控PSR状态:
# 监控PSR状态机 regwatch 0x600 0x1 # PSR控制状态 regwatch 0x601 0xFF # 进入延迟 regwatch 0x603 0x3 # Main Link控制5.3 实际案例:某4K面板的PSR2实现
在某款4K分辨率面板的调试中,发现PSR退出后出现图像撕裂。根本原因是:
- 面板要求的PSR_EXIT_TO_ACTIVE_TIME为16ms
- 驱动默认配置8ms超时
- 导致链路训练开始时面板未就绪
修正方案:
- write_dpcd(ADDR_PSR_EXIT_TIMEOUT, 0x08); + write_dpcd(ADDR_PSR_EXIT_TIMEOUT, 0x20); // 32ms容限