首页 / 资讯中心 / 文章详情

MIPI-DSI显示接口解析:从差分信号到设备树,点亮屏幕不再难

MIPI-DSI显示接口解析:从差分信号到设备树,点亮屏幕不再难 ★ FEATURED ARTICLE
我第一次点亮一块MIPI-DSI屏时信心来自一份改了无数遍的设备树配置结果上电之后背光先亮了屏幕却一片白。拿着示波器到处戳最后才发现根本不是初始化序列的问题而是数据lane的极性接反了。从那以后我养成了一个习惯遇到屏幕没点亮先问物理链路再问驱动代码。这篇文章要聊的就是整个过程里大家最常打交道的MIPI-DSI基础包括这个硬件接口为什么长这样、数据在路上到底怎么跑、以及像T113i这类平台点屏时设备树和驱动里的参数究竟从哪来。内容不追求把规范背完只解决“手里有块DSI屏想把它点亮”这件事。适合刚接触嵌入式显示、正在为一块屏头大的开发者也适合想回头把基础补扎实的工程师。1. 为什么“点亮屏幕”这件事绕不开MIPI-DSI1.1 从RGB并行屏到串行DSI接口路线图的更替早几年做嵌入式屏幕大部分SoC接LCD用的是并行RGB接口。一片不带控制器的TFT屏需要PCLK、HSYNC、VSYNC、DE再加上R、G、B每通道6bit或8bit的数据线林林总总二十多根信号。线一多PCB走线就难受连接器也越做越粗。频率稍微高一点整排信号线之间的串扰就能把波形搅得没法看更别提驱动强度、等长控制这些麻烦事。MIPI-DSIDisplay Serial Interface就是在这种背景下顶替上来的。它把并行数据收敛成一组高速差分信号物理上只保留1对时钟线和最多4对数据线承载的数据量反而远超老式并行接口。现在的手机屏、平板屏、工控屏、车载仪表屏几乎都把DSI当标准输入口。对做系统集成的人来说点亮屏幕绕不开这个接口那就意味着不能只把它当成一段可复制的驱动代码得当成一个硬件接口去理解。1.2 差分信号为什么能供得上高速显示数据很多从并行接口转过来的人会问同一个问题就那么几根线扛得住每秒几个Gbit的图像数据吗核心答案在差分传输。每对差分线里的两条线发送端分别输出幅度相同、极性相反的信号接收端只关心两条线之间的差值。外界过来的共模干扰会同时叠加在两条线上相减之后正好抵消再配合接收端的差分放大器有用信号可以完整恢复。这和网线、USB、SATA是同一套底子只是速率和协议细节不同。打个比方并行RGB像一群人并排喊口号声音越大越整齐DSI则是两个人互为镜像地说话周围噪声再多只要两人之间的差值稳定信息就丢不了。代价也有。差分传输要求布线尽量等长、阻抗匹配通常按100欧姆差分阻抗设计连接器质量和ESD保护同样影响信号质量。很多点屏翻车现场回头查根因其实是PCB那几对线没画好而不是软件配错。1.3 写驱动前得先有协议分层意识MIPI-DSI名义上叫“接口”实际上是一个完整的协议族。工作起来可以粗略分成三层最底下的D-PHY物理层负责电平、同步和差分传输中间协议层负责把图像数据和命令打包成一个个包最上层是命令集常见的DCSDisplay Command Set就在这一层。屏厂给的初始化序列、SoC驱动里的lane配置、设备树里的timing参数分别打在对应层上。有了分层意识排查问题会快很多。屏幕白屏可能是物理层没起来时钟没输出、lane接错也可能是链路层包没发对初始化序列被截断还可能是应用层命令没执行寄存器地址写错。三层对应三种完全不同的排查手段后面文章会按这条思路展开。2. 从“几条线在干活”看物理层时钟通道与数据通道的协同2.1 LP/HS双模平时慢悠悠发数据时飙车D-PHY标准规定一条DSI链路由1个时钟lane和1到4个数据lane组成每个lane是一对差分线。物理层最大的特点是具备两种工作状态LP低功耗状态和HS高速状态。LP状态信号摆幅接近0到1.2V速率低主要用于控制信息和握手HS状态摆幅只有200mV左右一个数据lane的速率可以到几百Mbps甚至更高真正的图像数据全在HS状态传输。链路并不是上电之后一直高速跑而是先由LP状态切换进HS状态完成同步后爆发式传数据传完再退回LP。这个过程对使用者是透明的但调试波形时会看到两种状态交替出现这一点后面讲示波器排查时还会用到。2.2 时钟lane的DDR工作方式DSI的时钟lane就是一对差分时钟。与并行接口不同的是数据lane不是只在单个时钟沿采样而是上升沿、下降沿都采样也就是DDR双边沿工作。举个例子若时钟频率是225MHz每根数据lane每秒能传输约450Mbit。为什么DSI时钟经常标到几百MHz原因就在这——单lane靠双边沿四个lane再并行总吞吐量等于时钟频率乘lane数再乘2。很多工程师第一次看到DSI时钟频率几百MHz会发怵换算成实际数据量其实只是刚好匹配屏幕需求。这个机制还解释了lane数量、时钟频率和分辨率为什么总是绑在一起。屏厂规格书上写“DSI 4 lane, 900Mbps/lane”翻译过来就是时钟链路要跑在450MHz四对数据线同时以900Mbps速率送数。2.3 屏幕分辨率怎么决定lane数量和时钟频率实际拿一块常见屏算一遍理解会扎实很多。假设面板是1920x1080、24bit RGB、60Hz刷新率。先算像素时钟1920乘1080乘60约124.4MHz这是纯active区的理论值。实际像素时钟要包含消隐区很多屏会用到148.5MHz这类数值。按148.5MHz、每像素24bit算总带宽是148.5乘24约3.56Gbps。如果链路只有2个数据lane每个lane要承担约1.78GbpsD-PHY常见速率下会比较紧张换成4个数据lane每个lane只需要约890Mbps此时时钟频率约445MHz处于很舒服的区间。这也是为什么中低分辨率屏常见2 lane1080p以上的屏普遍要4 lane。画板子之前先做这个简单乘法能在选型阶段躲开一堆“屏幕点不亮”的隐患。3. DSI链路怎么说话包结构、传输模式与命令集3.1 短包和长包DSI传输的基本单元MIPI-DSI协议层把数据组织成包所有命令和图像数据都放在包里。短包固定4字节第1字节是数据类型DI中间2字节是数据或参数最后1字节是ECC校验。短包适合发短命令比如Sleep Out、Display On。长包则由4字节包头、可变长度有效载荷和2字节CRC校验组成。包头里有数据类型和载荷长度载荷就是真正要写入屏幕的寄存器序列或者图像数据。Video Mode下一行行的像素数据也以长包形式传输。很多驱动代码里初始化序列看起来是“一长串二进制”其实就是把多个长短包连在一起只不过包类型字段一眼看上去像寄存器地址特别容易混淆。3.2 容易混淆的DCS命令与包类型这个点必须单独拎出来说。屏厂给的配置里常能看到这样的序列0x39 0x00 0x01 0x02 0xA0 0x15 0xB0 0x10不少人的第一反应是“0x39是寄存器地址”其实不对。0x39在MIPI-DSI语法里是数据类型DI表示这是一个DCS Long Write包0x15表示DCS Short Write带1个参数0x23表示Generic Short Write带2个参数。包类型后面跟的才是真正的DCS命令和参数。常见DCS命令包括0x11是Sleep Out0x29是Display On0x28是Display Off0x2C是Memory Write0x05是Sleep In。顺带说一个更容易绕晕的点DCS命令集里也有一条0x05Sleep In和包类型0x05是两个概念。看初始化序列时要结合上下文——固定位置上的首字节是包类型后面的字节才是命令本身。真正动手配初始化序列时按“包类型、命令、参数”的结构去理解而不是把整串二进制当成连续的寄存器地址表。这个认知错误会让人反复核对寄存器清单却始终查不出问题在哪。下面用表格列一下常见包类型数据类型含义典型用途0x05DCS Short Write无参数发送0x11、0x29这类无参命令0x15DCS Short Write1参数发送0xB0 0x100x23Generic Short Write2参数发送两个字节的厂商短参数0x29Generic Long Write发送厂商专用长数据0x39DCS Long Write发送较长寄存器序列3.3 Video Mode与Command Mode持续刷新与按需刷新DSI链路有两种工作模式理解它们的差别能解释很多“屏为什么这样点”的设计决策。Command Mode命令模式下屏幕内部带有帧缓冲RAM主机只需要把整帧或局部更新数据写成命令发过去屏幕自己负责持续刷新显示。这类屏适合做低功耗可穿戴设备局部刷新也省电缺点是面板成本高主机还要管理刷新节奏。Video Mode视频模式下屏幕不依赖自己的RAM主机必须按固定时序持续不断把像素数据传过去行为接近老式RGB接口。几乎所有用DSI的常规TFT屏都是Video Mode。这也是设备树里HFP、HBP、VSA、VFP、VBP这些时序参数一直存在的原因——DSI链路虽然只有几根线时序行为上仍然模拟了并行接口的消隐概念。很多人会想既然已经是串行链路了为什么还要保留消隐参数答案在于面板内部驱动IC需要这些时间去完成扫描、电荷共享和换行不是链路足够快就能省掉。3.4 时序参数HFP/VSA这些值到底是写给谁看的设备树或SoC显示驱动里常看到这样一组参数hactive、vactive、hfront-porch、hback-porch、hsync-len、vfront-porch、vback-porch、vsync-len。这些值不是拍脑袋写的直接来自屏幕规格书里的Timing Characteristics表。像素时钟决定一行像素多快送完HFP等消隐参数规定扫描完一行后要留多少空闲。在DSI Video Mode下消隐期内链路上不需要传像素主机可以插进一些短包或保持链路空闲。参数抄错常见表现就是图像左右偏移、顶部色带、刷新时抖动甚至直接黑屏。所以把屏点亮本质上是把规格书参数原封不动搬进设备树再配好lane数和时钟。别自作聪明“优化”这些值屏厂给的数字大都是经过量产验证的。4. t113i平台点屏的驱动侧基本盘参数从哪来到哪去4.1 T113i的显示链路U-Boot先亮屏内核再接管用T113i这类全志平台做产品点屏过程比单纯在Linux内核里配一个panel复杂一点因为通常存在两个阶段U-Boot阶段和Kernel阶段。U-Boot阶段BootROM加载U-Boot后显示驱动会根据设备树初始化TCON和DSI控制器把boot logo显示出来用户上电后能立刻看到画面。到了Kernel阶段内核显示驱动会重新初始化硬件和面板。理论上两边共用同一个设备树但因为U-Boot的显示框架和内核显示框架是两套代码某些参数的解释并不完全一致。实际开发中我遇到过“U-Boot下能显示logo内核起来后屏幕黑掉”的情况。逐项对比日志后发现是U-Boot和内核里的DSI时钟计算方式不同导致kernel侧实际lane rate偏低。定位的关键是让两个阶段使用同一份panel参数升级SDK时同步更新两边的显示驱动版本。Tina Linux SDK里这两部分的panel配置通常都能在设备树对应节点中找到。4.2 屏厂规格书翻译成设备树timing实际配设备树我一般先在规格书里找到Timing表然后逐项对应。下面这是一个示意节点数值不来自任何具体屏真实项目必须改成屏厂确认过的参数dsi { status okay; >// 从屏厂文档翻译而来的初始化片段 mipi_dsi_dcs_write(dsi, 0x11, NULL, 0); // Sleep Out msleep(120); mipi_dsi_dcs_write_buffer(dsi, (const u8[]){0xB0, 0x10}, 2); // 厂商寄存器 mipi_dsi_dcs_write_buffer(dsi, (const u8[]){0xB4, 0x01, 0x02, 0x03}, 4);这里最值得提醒的是初始化序列的发送时机必须符合面板状态机。比如有些屏必须先Sleep Out等若干毫秒再发显示设置有的序列第一条要先把寄存器页切到指定页后面命令才有效。把整段数组一股脑发出去、中间没有任何延时很容易导致后面寄存器写失败。更隐蔽的坑是某些寄存器只能在Display Off状态下修改Display On之后再写就没反应所以序列开头的Sleep In、Display Off往往是起点顺序不能靠感觉调整。4.4 从像素时钟到lane rate驱动内部的换算关系除了设备树里的timingDSI控制器还需要知道链路时钟跑多快这个值通常由像素时钟和lane数换算。常用的关系是total_pixel_clock pixel_clock × (1 blanking_ratio) lane_rate total_pixel_clock × bits_per_pixel / lane_count byte_clock lane_rate / 8在T113i这类平台TCON输出的像素时钟已经包含消隐驱动会根据分辨率、porch和lane数反算DSI时钟。还有一个容易忽略的变量hblank变长会导致数据传输时间更紧lane rate也要跟着调整。所以改porch参数时不要只改设备树里的时序还要确认DSI时钟是否同步更新否则容易出现“参数看起来合理但屏幕闪”的现象。5. 点亮失败的排查链从电压、复位到波形一步步缩小范围5.1 先排除“屏根本没上电”电压与复位的三类坑屏幕点不亮我强烈建议先别急着上示波器看高速波形先从直流信号查起。第一步用万用表量屏供电电压主电源VDD、IOVCC、背光电压是否正常纹波是否过大。嵌入式环境里最常见的是背光用boost升压负载一重电压就跌落造成屏幕一亮就灭或间歇闪。第二步查Reset时序。很多面板要求VDD稳定后等几毫秒再把RESET拉高或拉低保持一段有效时间。如果SoC启动时GPIO状态没控制好RESET被拉错极性整块屏就不工作。第三步查GPIO复用问题。带屏板子上reset脚和enable脚经常与调试口或其他外设共用引脚U-Boot或内核里某个驱动先把它复用成了别的功能导致面板驱动拉不动电平。这三类问题用万用表和示波器DC档就能定位不需要一开始就深入协议。5.2 再看时钟有没有起来示波器测差分波形要点电压和复位都正常屏还是不亮就要上示波器看DSI链路了。DSI在LP状态的电平只有0到1.2VHS状态差分摆幅更是只有200mV左右所以示波器带宽建议500MHz以上最好用差分探头去测DP/DN。测量重点有两个时钟lane有没有周期性波形、数据lane在初始化阶段有没有明显的HS包爆发。如果时钟lane完全静止问题多半在TCON或DSI控制器没使能如果时钟有但数据lane毫无动作可能是面板没有正确进入接收状态驱动认为链路还没建立。另一个实用技巧是打开示波器的色阶或余辉模式观察HS眼图。看到眼图闭合、上升沿太缓可以在驱动里试着降低lane rate看能否改善。这个变量能帮你区分是硬件信号质量问题还是软件配置问题。5.3 最后查链路握手lane映射、极性翻转与readback验证到这一步时钟正常、数据也有活动屏仍黑着就得怀疑lane映射和极性了。PCB布线为了走线方便经常会把某一对数据线的DP/DN反接或把几个数据lane顺序打乱。部分SoC的DSI控制器允许在驱动里直接配置lane映射和极性不需要改板子。全志平台的设备树里通常有lane-number、lane-polarity这类配置项。排查时可以把极性翻转组合挨个试一遍看哪个组合能让画面正常。如果平台不支持任意映射只能改板那就要按规格书的lane order重新设计。有条件的话用DSI控制器的回读能力做最后确认会很有用。很多屏支持读寄存器比如读Panel ID或error flag。驱动里发一条读命令如果能读到非全0xFF的值至少证明命令通路是通的。这也能解释为什么一开始就要确认屏幕是否支持readback它能把“命令到底有没有发进去”从猜测变成实测。5.4 常见错误对照表下面这个表格是我调试过程中比较高频的现象汇总现象可能原因优先排查手段背光亮、屏全白初始化序列未生效或时序错误查RESET时序、初始化序列是否完整发送背光不亮背光电路或电源问题万用表量背光升压输出显示花屏/条纹像素时钟偏高、porch错误降低lane rate试跑核对timing表图像左右偏移HFP/HBP填错对照规格书逐项校准顶部色带VSA/VFP与规格书不符先查垂直消隐参数上电闪一下再灭电源时序或欠压示波器抓VDD在RESET前后的波形仅U-Boot亮、内核不亮两阶段驱动配置不一致对比U-Boot与Kernel的DSI时钟设定排查时不要跳步。先处理供电和复位再看时钟和lane最后才动初始化序列这条链路基本能覆盖九成以上的“屏幕点不亮”问题。6. 写在接口演进的边上DSI为何今天依然是主流6.1 DSI与eDP的路线之争聊MIPI-DSI绕不开另一个叫eDP的竞争对手。eDP在笔记本、一体机这类大屏场景里占据绝对主力带宽更高、支持大屏、扩展功能完善。MIPI-DSI则在手机、平板、工控、车载这些中小尺寸屏上继续称王。两者本质都是串行差分显示接口选择哪条路线更多是生态和成本问题不是单纯的技术优劣问题。做嵌入式设备往往在DSI体系内就能解决全部需求也正因如此把DSI吃透的性价比非常高。6.2 新面板功能背后还是这条老链路这几年屏厂推出了很多新能力可变刷新率、局部刷新、低功耗模式、双DSI接口拼超高分辨率等。细看就会发现大部分新能力仍然建立在Video Mode与Command Mode的既有框架之上链路底层的D-PHY和包格式并没有被推翻。昨天刚上手的屏可能是双DSI拼接的4K屏但基础包结构和时钟同步逻辑还是那套老东西。我这几年点的屏越多越觉得把基础接口吃透比追新概念更有用。每次遇到点不亮的屏回头查的还是那几对差分线、包类型和时序参数。先把这些基础变成直觉再花哨的屏幕拿到手里顶多折腾半天也就能亮起来了。
阅读完成 · 觉得有帮助?
咨询建站