上周同事扔给我一块MIPI DSI接口的LCD,说在全志T527的板子上点不亮,让我帮忙看一眼。拿到样机和屏之后我没有急着上电,而是先翻开原理图把屏的连接脚位过了一遍。这一查还真查出了问题——复位脚在硬件上被直接拉到了低电平,等于一直按着不让屏启动,跟设备树里配的极性完全是两码事。这种问题如果一上来就闷头改驱动,大概率会白白浪费大半天。
这个系列写到前面第10篇,一直在记录BSP调试里比较典型的坑。今天这篇算第11篇,专门聊聊在全志T527上调MIPI DSI的点屏思路、设备树配置和排障链路。如果你是做BSP或者驱动开发,手里正好有类似的板子要调屏,这篇内容应该能帮你少走几步弯路。
1. MIPI DSI点屏,先搞懂SoC和屏之间谁说了算
1.1 显示链路的三段式结构
全志T527这颗SoC的显示输出链路并不是“CPU管脚直接连屏幕”,中间隔着三段:第一段是Display Engine,也就是大家常说的DE,负责把framebuffer读出来做格式转换、缩放、图层叠加;第二段是TCON-LCD,负责产生像素时钟、同步信号以及控制时序;第三段才是MIPI DSI controller,把TCON送来的并行数据打包成D-PHY的串行差分信号,经过匹配电路送到屏端。很多时候点不亮,根子不在代码,而在这三段之间某一段的连接或配置根本没有生效。
我拿到一块新屏时,第一件事是找一个已经点亮的板子或者文档,确认它用的是video mode还是command mode。T527的DSI controller两种都支持,但绝大多数消费类屏幕用的是video mode——也就是说TCON持续输出图像数据,屏端自己把信号刷新到面板上。如果配置成了command mode,又没写初始化命令,屏幕多半就是一片黑,甚至背光亮着却是白屏。
另一个容易忽略的点:TCON-LCD这层其实还分成了TCON-LCD0和TCON-LCD1,同一个DSI控制器究竟挂在哪个TCON下面,取决于芯片内部的显示通路设计。在全志T527上,严格按SDK里的示例来就行,不要在dts里随意把DSI0挂到另一个TCON上,我曾经在别的平台踩过类似坑,模块本身不报错,但从根上链路就没走通。
1.2 屏参决定配置顺序
屏幕规格书里标着一大堆参数,分辨率、像素格式、刷新率、扫描方向、MIPI lane数、每lane速率、HSYNC/VSYNC极性等等。真正决定你第一步怎么配的是三个:lane数、像素格式、刷新率。其他参数像porch、active width,大部分情况下可以参考屏驱IC的默认配置,但lane数和像素格式一旦错,后面所有东西都错。
举个例子,一块常见的720x1280 60Hz面板通常走4 lane,RGB888,DSI速率约400~500Mbps/lane。你在dts里如果配成了2 lane,实际带宽不够,画面上会出横纹、撕裂甚至完全黑屏。反过来,本来2 lane的屏被配成4 lane,屏端不一定报错,但驱动可能因为接收到多余的时钟而出现花屏或者锁不住信号。所以改任何配置前,先拿尺子数一下排线上有几对差分线,再对照屏端IC型号查一下实际lane数。
1.3 上下电时序不是玄学
做BSP久了你会发现,屏幕点不亮的问题里,“上电时序”出现的频率高得吓人。MIPI DSI屏幕虽然看起来只有一组VCC、一组IO、一组背光,但屏里的Driver IC其实分模块工作:VSP、VSN、VCL、VDD等供电来源经常不是同一路。绝大多数屏的规格书会画一张Power On/Off Timing状态图,至少要满足VCC先上,接着IO电压和复位信号,复位拉低一段时间再拉高,然后等t1、t2延时之后再发初始化命令。
我见过最典型的翻车:dts里的reset-gpios和enable-gpios都配了,但顺序反了。正常做法是板载电源先稳定,然后释放复位,最后再打开背光。如果背光先亮了,屏还没启动,那看起来就是“亮着背光但全黑”。还有一种情况,复位GPIO用GPIO_ACTIVE_HIGH配置,实际上屏是低电平复位,结果屏一直没退出复位状态。这类问题用万用表量GPIO电平都查不出来,因为电平看起来是对的,但极性和时序不对。
2. 全志T527设备树配置:从显示引擎到panel节点
2.1 dts里从DE到DSI的节点骨架
全志T527的SDK里,显示相关的设备树节点一般已经写好了大框架,我们需要补的通常只是DSI controller下面的panel子节点和对应的port连接。一个比较完整的panel示例大致是下面这样:
&disp { status = "okay"; }; &tcon_lcd0 { status = "okay"; clock-frequency = <66000000>; }; &dsi0 { status = "okay"; #address-cells = <1>; #size-cells = <0>; panel@0 { compatible = "simple-panel"; reg = <0>; reset-gpios = <&pio PA10 GPIO_ACTIVE_LOW>; enable-gpios = <&pio PA11 GPIO_ACTIVE_HIGH>; backlight = <&backlight>; status = "okay"; port { panel_in: endpoint { remote-endpoint = <&dsi0_out>; }; }; }; ports { #address-cells = <1>; #size-cells = <0>; port@1 { reg = <1>; dsi0_out: endpoint { remote-endpoint = <&panel_in>; }; }; }; };注意几个细节。首先是reg = <0>,这个要跟panel驱动的预期一致。其次是port连接,全志的display driver通过port来找DSI和panel的关系,如果你只写了panel节点但没挂endpoint,driver可能报no endpoint直接跳过。第三,status节点别省,有些模组在默认dts里是disabled状态,不加"okay"永远不会被probe。
2.2 panel节点里哪些属性必须有
我通常在panel节点里只放“和硬件强相关”的属性,像颜色格式、时序这类能写进驱动里的东西就不重复放,避免两处不一致。必须检查的是:reset-gpios、enable-gpios、backlight引用、DSI lane数量和MIPI速率。
reset和enable引脚的极性,一定要回到原理图去确认。GPIO_ACTIVE_LOW表示低电平生效,配置为高电平时引脚默认保持低。很多屏的reset是低有效,所以reset-gpios应配成GPIO_ACTIVE_LOW;enable有时是“高有效使能”,但有些屏的STBY电平又是另一个说法。不要照着参考设计抄,全志的参考板用的屏和你手上的屏大概率不是一个型号,对应GPIO定义可能正好相反。
backlight节点的绑定也容易出问题。如果屏自带背光控制,你可以直接给panel节点加backlight = <&backlight>让driver去管理pwm。这里要留意backlight节点里的brightness-levels数组和default-brightness-level,很多时候全黑不是屏没醒,是背光输出被设成了0。
2.3 MIPI速率和像素时钟怎么推算
很多刚接触MIPI DSI的工程师不理解为什么要单独配clock-frequency或者DSI速率。这里有个简化公式可以帮忙理清思路:
像素时钟 ≈ 分辨率H × 分辨率V × 帧率 × blank系数
比如720×1280 @60Hz,blank系数按1.2估算,大约是:
720 × 1280 × 60 × 1.2 ≈ 66.4 MHz
RGB888一个像素占24bit,线速率需要:
66.4M × 24 ÷ 4lane ≈ 398Mbps/lane
考虑到MIPI D-PHY每一包还要带包头、包尾和HS前导码,实际选型一般留15%左右余量,所以450~500Mbps/lane是比较稳妥的选择。如果你的屏规格书明确写了推荐DSI clock为500Mbps,那就按规格书来,不要自己拍脑袋,否则图像容易出现时钟饥饿导致的闪屏。
另外注意:TCON-LCD的时钟不一定等于MIPI速率。TCON负责产生像素时钟,DSI负责把像素打包,两者之间有分频关系,很多SoC里DSI clock是TCON clock的倍频。改dts时不要只改一个,建议把TCON和DSI两个频率绑定在一起看。调试时如果花屏,可以先试着成对地往上往下调,观察画面变化。
3. 第一轮点亮,我常做的自检清单
3.1 背光和屏供电别用万用表“目测”
点屏之前,我基本都会先测三路电压:屏的VCC、背光的LED电压、PHY的供电。全志T527的DSI PHY一般有独立的AVCC或LDO供电域,如果在dts里漏配了PHY电源,现象很迷惑——驱动初始化正常,但DPHY输出波形很弱,或者干脆没输出。
一个实操习惯:用示波器靠DC档看电压稳定度,再用AC档看纹波。MIPI DSI屏对电压纹波比较敏感,纹波超过50mV有时会在某些亮度下出现细条纹。这个在共享电源时会特别明显,比如背光升压电路和屏的VCC在同一个DC-DC输出后面,背光负载一变化,屏就闪一下。
如果电压纹波有问题,优先加LC滤波或者在dts里把背光驱动的PWM频率调高一点,把音频频段的干扰避开。别一上来就怀疑驱动。
3.2 复位和使能信号,建议用GPIO控制而非硬接
很多参考板图省事,把屏的复位脚直接接到SoC的GPIO上,通过设备树控制。这样做有个前提:确保这个GPIO在uboot阶段不被别的驱动复用了。我遇到过pinmux冲突——同一根脚同时被其他驱动和reset驱动占用,导致复位信号毛刺不断,屏幕时而亮时而黑。
在自检阶段,我会优先确认三件事:上电后GPIO电平是否达到预期,复位拉低再拉高的整个时间是否满足屏规格书(通常是大于等于1ms或者10ms),以及背光是否在reset释放后才开启。这些逻辑可以先用用户态的gpioset手动操作一遍,确认时序正常之后再去改驱动。注意T527的新SDK里直接用libgpiod操作GPIO会更方便,不要还在sysfs里用gpio号硬猜。
3.3 示波器探头放哪里才看得出来
很多时候点不亮,驱动日志全正常,这时候就要上示波器了。MIPI DSI是差分信号,测量时钟lane时务必用差分探头,没有差分探头的话至少要接两个单端探头做A-B相减。测点选在连接器附近的测试点,或者排线座焊盘上。
正常HS传输时,时钟lane能看到一串连续的正弦波/方波,频率和配置的DSI速率对应。数据lane只在有数据时才出现数据突发,平时保持LP-00状态。如果你看到数据lane上一直在发东西,大概率是video mode正常把数据流发出来了;如果数据lane什么也没有,只有初始化时的LP脉冲,那问题更可能在TCON侧,没有数据喂给DSI。
4. 最常见的三种“点不亮”现象与完整排查链路
4.1 背光亮、LCD无画面
这是出现频率最高的一类。背光亮说明背光通路正常,但屏端没有收到有效图像数据。
我的排查顺序是固定的。先看内核日志里DSI初始化和panel probe是否成功,有没有no panel、timeout之类的报错。再看初始化序列有没有发送成功。很多屏在开机时必须先收到sleep out和display on命令,否则就算TCON持续输出图像,屏端也处于睡眠模式,表现为纯白或者全黑。
再深入一层,查初始化命令的发送时机。如果panel节点里的初始化码是通过LP模式一包一包发出去的,而TCON已经提前开始HS持续发像素了,屏可能一直不能进入正常显示模式。这时就要检查video mode的hsync/vsync参数,包括命令发送间隔是不是太短、初始化命令有没有在正确的时间点发送。最简单粗暴的方法:手动在驱动里加一条ssleep(100)在发display on之前,往往就能看出命令时序有没有问题。
4.2 花屏、横条纹、颜色错乱
花屏的原因可以分成三类:数据lane没对齐、DSI速率/TCON频率不匹配、以及电压纹波干扰。我习惯先做一个快速分类:
| 故障表现 | 可能原因 | 优先排查方向 |
|---|---|---|
| 横向平移、颜色错位、镜像 | lane mapping错误 | 检查DSI物理lane映射 |
| 整体斜切、雪花、重影 | 速率不匹配 | 成对调整DSI rate和TCON clock |
| 特定亮度下细条纹闪烁 | 电源纹波 | 示波器测VCC和AVCC纹波 |
数据lane没对齐时,画面会出现典型的“横向平移/镜像错乱”,因为屏把RGB三色通道收到的bit流解错了。这时候要检查SoC的lane mapping配置。全志T527的DSI controller允许把物理lane映射到任意逻辑lane,SDK里一般有个表,屏端FPC排线上LANE0接的是哪个PHY lane,必须和dts里的映射一致。
速率不匹配则更好识别——画面通常是整体斜切、蒙蒙的雪花或者左右移动的重影。这可以通过逐档调整DSI速率来排除。我在调屏时习惯把MIPI速率一次上下调整25%,观察三次画面变化,基本能锁定是速率还是时序。还有一种伪装成花屏的纹波问题,前面提过,如果只出现在某些亮度、某些刷新率下,优先测电源波形而不是去调屏参。
4.3 开机概率性不亮,重启或休眠唤醒后失效
概率性问题最考验耐心。常见原因是上下电时序残留电压。比如reset信号拉高后,屏端VCC还没完全爬升到阈值,或者屏内Driver IC因为某次异常断电没有完全复位,导致下次开机时内部状态机跑飞。
我一般用两个手段去复现:一是连续重启50次,每次间隔5秒,手动记录不亮概率;二是在休眠唤醒循环里跑一天,抓唤醒后的dmesg和GPIO状态。接下来重点检查复位引脚在重启瞬间是否出现了毛刺——有些SoC的GPIO在系统reboot时没有默认状态,如果bootloader里没有先把reset拉低,屏可能带着残影状态启动。
另外,电源路径上如果有大电容,掉电之后VCC残留时间会很长。BSP设备树里电源的ramp-delay或者power-on-delay没设够,就会产生概率性问题。全志T527的PMIC配置中,可以把VCC掉电延时调低一点点,让下一次上电前电压彻底归零。
5. 利用内核日志和debugfs把问题“定量”定位
5.1 dmesg里只要看这几条
驱动开发基本都会习惯性刷dmesg,但信息太杂反而看不出问题。我通常会grep几个关键词:dsi、lcd、panel、drm、tcon。正常点亮时,日志里应该能看到类似下面的行:
[ 2.241] mipi-dsi dsi0: DSI host registered [ 2.250] panel-simple panel@0: DSI panel probed [ 2.258] mipi-dsi dsi0: video mode config: 4 lanes, 500 Mbps per lane [ 2.266] mipi-dsi dsi0: sent 34 bytes init sequence [ 2.274] mipi-dsi dsi0: enter hs mode如果始终没有出现panel probed,那问题基本在设备树端口连接或者panel compatible没有匹配。如果出现probed但没有后续的enter hs mode,那就是初始化命令或TCON启动阶段被卡住了,这时候再去查videomode参数。注意timeout这个单词,MIPI DSI在等待ack或等待TE信号时容易超时,不要忽略,先解决超时再去管图像。
5.2 用debugfs强制驱动显示链路
很多全志SDK里能调的东西比命令行多得多。板子上电后先挂上debugfs:
mount -t debugfs none /sys/kernel/debug ls /sys/kernel/debug/driDRM子系统的state文件可以查看当前每个connector是否connected、每个plane是否有framebuffer。重点看connector的status是不是connected,crtc的active是不是1。如果active=0,说明用户层/应用没有真正开一个显示会话,问题根本不是MIPI,而是显示framebuffer没有接上。这种情况在嵌入式BSP里很常见——屏幕本身已经点亮,但因为init没有启动GUI进程,看起来像黑屏。
全志在新平台可能还会保留/sys/class/disp之类的节点,T527的新SDK里路径可能不同,但原理一样:找一个能读当前显示模式、layer状态、clock状态的节点,逐项检查。
5.3 眼图和信号质量怎么看
如果到了HS信号质量层面,说明驱动链路基本通了,剩下的是硬件或阻抗匹配问题。此时示波器上观察到的时钟lane眼图应该清晰张开。四根数据lane的摆幅差异不应超过50mV,差分信号过冲最好控制在10%以内。
遇到信号质量差,几步处理:缩短FPC长度、检查连接器焊接、确认差分走线有没有跨分割,以及在dts里微调HS_Trail和HS_Exit这些D-PHY时间参数。全志的DSI驱动里一般留了lane_drive或者phy_timing的调节入口,这不是常规需求,但遇到眼图闭合时可以试着按手册把摆幅提高一档。
另一个容易被忽略的是匹配电阻。很多模组的MIPI差分对已经内置了匹配电阻,如果外围又加了一组100欧并联电阻,信号摆幅会被拉低,屏幕在常温下看着还行,一热就花屏。
6. 调试过程中的几个个人实用习惯
6.1 永远保存一份“最小可点屏配置”
调试进入稳定期后,我会把“屏规格书关键参数 + dts片段 + 验证log”整理成一个md文件放到板卡项目的doc目录下,而不是只存在U盘某个不知名txt里。下次再拿到同型号屏,直接搜型号就能找到之前调通的配置,省去大量重复劳动。
如果同时调好几块不同分辨率的屏,我会在dts里把panel子节点做成两到三个别名,通过uboot传参选择,千万别每次改完硬编码就发布。全志T527这类平台,板子量产之后屏供应商可能换批次,保留可切换配置能救后面的产线同事。
6.2 把“电源波形”作为默认怀疑对象
调MIPI DSI久了你会发现,很多疑难杂症最后都会归到“电源纹波”或者“掉电残留”上。排查效率上,我建议每次点不亮都先花五分钟测一下屏VCC、PHY AVCC、背光供电这三个地方,拿示波器抓一下上电瞬间波形。看起来多花五分钟,但能直接排除掉一大类坑。
尤其要注意背光driver在工作时产生的开关噪声,如果噪声耦合到了MIPI差分线上,高速信号解调时会毛刺加剧,表现为固定角度的彩色横条。这种情况我遇到过两次,最后都是靠背光电源和MIPI走线拉开距离解决的。
6.3 省时间的求助方式
如果上述步骤都做完还没解决,需要找FAE或原厂支持时,我一般直接发三样东西:设备树panel节点、完整dmesg、示波器关键波形截图。这三样是最能定位问题的“证据链”。别只发一句“屏幕不亮”,那基本等于让大家陪你盲猜,来回五六轮都解决不了。
我还在自己笔记本里保存了一份“屏参清单模板”,包括分辨率、lane数、每lane速率、porch、初始化命令、复位时序要求、上下电顺序等字段。模板填完顺手发给屏厂FAE,对方一看就知道你是个懂行的,沟通效率完全不一样。
6.4 调完一块屏之后我会额外做哪些验证
屏幕点亮只是第一步,要真正算“调完”,我还会做三件事。第一是连续重启100次,确认没有概率性黑屏;第二是在背光不同亮度下跑白、黑、灰、RGB纯色Pattern,重点看低亮度下有没有条纹,高亮度下有没有过冲;第三是跑一轮休眠唤醒压力测试,确认进出休眠时画面恢复无残留、无闪烁。
全志T527这类平台的量产板经常有温漂问题,所以我还习惯在-20℃和60℃环境下各回测一次。如果只能在常温环境调,至少要把DSI速率留足余量,不要刚好卡在带宽临界值上。很多“夏天没问题、冬天花屏”的事故,追根到底就是当初速率调得太贴近极限。
到这里,全志T527的MIPI DSI调试思路基本就完整了。这次这块屏最终是复位极性搞反导致的“背光亮无画面”,改了一行dts就解决了。整个过程看起来简单,但正因为前面把电源、时钟、初始化、HS时序都过了一遍,才能快速收网。