4、显示时序与时钟:Pixel Clock计算、显示时序参数、RK时钟树配置

显示驱动里,时序和时钟是绕不开的硬骨头。我刚开始接触这块时,总觉得不就是让屏幕亮起来嘛,至于搞这么复杂?后来被一块MIPI屏折腾了三天,才发现时序不对,屏幕就是死活不亮。嗯,今天咱们就把这块彻底讲透。

4.1 显示时序到底是个啥?

说白了,显示时序就是告诉屏幕:什么时候该扫哪一行,什么时候该换下一行,什么时候该从头再来。你想想看,屏幕上的像素点是一个个刷新的,总得有个规矩吧?

我习惯把显示时序拆成三个维度:

  • 行时序(Horizontal Timing):从左到右扫完一行
  • 帧时序(Vertical Timing):从上到下扫完一帧
  • 像素时钟(Pixel Clock):决定每个像素点刷新的速度

每个维度里,又包含几个关键参数:

参数 含义 常见坑点
HBP (Horizontal Back Porch) 行同步后的消隐区 太小会导致图像左移
HFP (Horizontal Front Porch) 行同步前的消隐区 太小会导致图像右移
HSYNC 行同步脉冲宽度 不同屏幕要求差异很大
VBP / VFP / VSYNC 垂直方向对应参数 影响图像上下偏移
⚠️ 我曾经踩过的坑: 有个项目用了块非标屏,规格书里HBP写的是88个像素时钟周期,我按常规设了48,结果图像整体左移了大概20个像素。查了两天才发现是消隐区没配对。所以拿到新屏,第一件事就是对着规格书把每个参数核对一遍。

4.2 Pixel Clock怎么算?

Pixel Clock,也叫点时钟,是显示时序的“心跳”。它决定了每秒能刷多少个像素点。

计算公式其实很简单:

Pixel Clock = (H_Total) × (V_Total) × Refresh_Rate

其中:

  • H_Total = H_Active + HBP + HFP + HSYNC
  • V_Total = V_Active + VBP + VFP + VSYNC

举个例子,一块1080p的屏,60Hz刷新率:

H_Active = 1920
HBP = 148, HFP = 88, HSYNC = 44
H_Total = 1920 + 148 + 88 + 44 = 2200

V_Active = 1080
VBP = 36, VFP = 4, VSYNC = 5
V_Total = 1080 + 36 + 4 + 5 = 1125

Pixel Clock = 2200 × 1125 × 60 = 148.5 MHz
💡 我个人习惯: 算出来的Pixel Clock最好留5%~10%的余量。比如算出来148.5MHz,我会先试试能不能跑到155MHz。万一后面要调刷新率或者加特效,不至于重新配时钟树。

4.3 RK时钟树配置实战

瑞芯微的时钟树,说白了就是一条链路:从PLL出来,经过分频、选通,最终送到各个显示模块。我画了个简化的流程:

PLL (比如24MHz晶振倍频) 
  → 分频器 (得到目标频率) 
    → 时钟门控 (开关控制) 
      → VOP (Video Output Processor) 
        → DSI/HDMI/eDP 等接口

在RK平台上,配置时钟树主要操作这几个寄存器:

  • CRU (Clock & Reset Unit):核心时钟管理单元
  • VOP_DCLK:显示像素时钟
  • ACLK / HCLK:总线时钟,影响DMA传输速度

我拿RK3568举个例子,配置一个1080p@60的MIPI屏:

// 1. 先配PLL,得到合适的VCO频率
// 比如用24MHz晶振,倍频到594MHz
// 2. 分频得到Pixel Clock
// 594MHz / 4 = 148.5MHz
// 3. 配置VOP时钟源选择
writel(CLK_SEL_VOP0_DCLK_SRC_PLL, &cru->clksel_con[XX]);
// 4. 设置分频系数
writel(DIV_VOP0_DCLK(4), &cru->clksel_con[XX]);
// 5. 使能时钟
writel(CLK_EN_VOP0_DCLK, &cru->clk_en);

🔑 关键点: 时钟树配置的顺序很重要。我建议先配PLL,再配分频,最后使能时钟。如果顺序反了,可能会产生毛刺,导致屏幕闪一下或者直接黑屏。

4.4 避坑指南:我遇到过的时钟问题

做显示驱动这些年,时钟这块我栽过不少跟头。挑几个典型的说说:

  1. 时钟频率不够:有次用了一块4K屏,算出来Pixel Clock要594MHz。结果RK3399的VOP最高只能跑到500MHz。最后只能降分辨率或者降刷新率。
  2. 时钟抖动太大:MIPI DSI对时钟抖动很敏感。我遇到过屏幕偶尔闪一下,查了半天发现是PLL配置的环路带宽不对,导致时钟抖动超标。
  3. 时钟域同步问题:VOP和DSI是两个时钟域,中间需要做异步FIFO。有次FIFO深度设小了,高分辨率下直接溢出,图像撕裂。
⚠️ 我曾经犯过的错: 有个项目为了省功耗,把ACLK降到了200MHz。结果发现DMA传输跟不上,屏幕刷新到一半就卡住了。后来才明白,总线时钟不能只看显示需求,还得考虑内存带宽。ACLK至少要保证DMA能在1帧时间内把数据搬完。

4.5 调试技巧:怎么验证时序对不对?

配完时钟和时序,怎么知道对不对?我一般用这几招:

  • 看示波器:直接量HSYNC和VSYNC的波形,看频率对不对,占空比是否稳定
  • 读寄存器:RK平台有CLK_DUMP功能,可以打印出当前时钟树的状态
  • 跑测试图:用彩条、网格图,看图像有没有偏移、撕裂、闪烁

嗯,说到测试图,我习惯在驱动里内置一个纯色填充函数。调试时先让屏幕显示纯红、纯绿、纯蓝,确认颜色没问题了,再上复杂图像。这样能快速定位问题是出在时序上还是数据通路上。

最后说一句,显示时序和时钟配置,说白了就是“算清楚、配准确、验证透”。别嫌麻烦,这块搞定了,后面调图像质量、调性能就顺风顺水了。