背景

研发一个机型的过程中出了点意料之外的问题。在关机状态下,进行电源适配器(DC)连续插拔测试时,在特定操作下会有概率性出现花屏现象,而且花屏现象不一致不统一。

现象如下图所示。图中无关紧要的位置打了马赛克,bug的问题现象是屏幕显示的内容花了。虽然都是关机充电界面花屏,但是花的内容款式有几种不同的。

Failed Rate:每7-8次出现1次;测试未发现与特定屏型号、特定屏单体、特定主板单体有关。与特定操作和场景强相关。

步骤:设备处于关机状态下 → 接入DC电源 →设备因关机充电而自动开机 → 显示开机logo → 显示充电动画 → 如果发现充电动画正常,则立刻拔出DC,然后尽快马上再次插入,再次循环;如果花屏,则问题复现。

平台:CPU  →  mipi  →  IT6151  →  eDP  →  TCON→ SOURCE IC → LCD

异常分析

软件出图分析:动画无异常、软件出图无特殊逻辑

分析显示问题的时候,第一步可以先看看我们从CPU出来的画面本身是否正常的。一般花屏可以通过截图和投屏、录屏来确认图源的正常情况,但是我们是在关机充电画面,Android尚未启动,故无法进行这类操作。

从现象上看,出问题的时候开机logo不花,充电动画花了。一般来说,花屏和屏的上下电时序、波形质量有关系,通常喜欢在亮屏就花。但是碰到的问题是亮屏的时候并不花,而是一段时间后才花,看来不能直接去找时序的锅。

因此结合关机充电这个场景,不排除是充电动画解析和显示的异常,包括充电动画对屏和背光的操作有时序异常。因此首先在问题出现后借助串口日志分析动画和屏操作日志。

此外,该机型有引入MTK AAL功能、上层PQ功能,因此SoC端的CABC功能或PQ模式可能有影响,也进行分析。

AAL功能和PQ功能是芯片厂商提供的调节画质的接口。

Action小结结论
动画日志分析正常关机充电动画部分没有异常,软件出图没有明显异常,电信号操作没有差异
开关、背光日志分析正常
正常、异常日志对比;
新、老版本日志对比;
与drvier only版本对比;
没有差异
PQ影响确认PQ服务在该阶段不会生效
AAL影响AAL没有源码,但根据文档确认在关机充电阶段不会生效。
此外,软件关闭ALL编译开关后,问题仍能复现

做实验缩小范围:发现问题不在屏端、TCON端

前面的实验表面CPU出来的画面应该没有问题,而且花屏的时候每次花的内容基本不相同,和正常显示的内容看着也不相干,因此向更底层的方向去分析。

Action小结结论
同主板同软件搭配A型屏复现花屏问题和屏、TCON无关
同主板同软件搭配B型屏复现
硬件飞线,将TCON Core 1V8接开关,在问题复现后,手动开关该开关,等价重启TCON复现后拨动、拨回开关,现象还在
屏单体问题分析测试资源不够、时间紧张,未测结合上面的结论(和屏无关),因此和屏单体也无关

6151信号稳定性、电源稳定性和软件逻辑分析:无异常(除eDP和MIPI信号无法分析)

6151是mipi to eDP芯片,CPU出来的画面发送给它,它处理后再发送给屏幕

前面步骤分析认为CPU出图、TCON均没有异常,因此围绕6151进行分析。

保障6151稳定运行的两个条件是:

  1. 软件下的配置正确
  2. 时序正确且各电信号稳定

梳理6151几个关键监测点,准备挂示波器和逻辑分析仪:

  1. 6151可以通过MIPI DSI下发指令、切换模式
  2. 6151可以通过I2C下发指令、切换模式
  3. 关键电信号包括几个GPIO、LDO、VDD(1V2、1V8、3V3、eDP使能、RST)的时序及波形

此外,在eDP驱动中初始化完成后dump寄存器,在进入充电界面时再次dump,排查意外没发现的SoC对6151的配置、6151寄存器变化、或6151自己跑飞了。

Action小结结论
1V2、1V8、3V3使能、eDP使能、RST的时序、波形(从开机到花屏发生)未见异常关键电信号的时序和质量正常
review软件配置正确未见异常软件配置符合要求,不涉及屏参
开机logo后(屏亮起后)6151 I2C监测,有一次意料之外的Write和Read没有挂逻辑分析仪,不能直接简单从示波器看到通信内容,不能排除软件这次通信是否让6151发生了变化,致使花屏没有对6151有重新初始化、切换模式、修改参数等操作
i2c通信没有影响花屏,也不影响概率
出新软件,移除掉这个I2C通信
(分析驱动,发现6151驱动确实有个i2c读写,但是这个是状态dump,可以直接去掉不影响功能)
示波器体现,i2c通信已经去除
花屏现象仍然能保持复现
且少量手工验证下,复现概率没有变化
6151寄存器dump
(改动量较大,需要在关机动画那里进行dump。接下来问题有更明确的进展,没来得及做这个实验)
//
是否通过MIPI DSI向6151发出指令软件排查没有走过MIPI DSI通道
无仪器分析
如果存在该情况,则问题不应该是概率性的

坑:回顾问题分析过程,这里有个漏掉的信号(V3P3A)没有分析到(而是只量取了使能)。因为这个信号,我们有惯性思维,会认为它是稳定常开的,因此没有量它的波形。

我们分析到后面才发现是这个信号有异常掉0,它导致了花屏

花屏伴随着L-Sensor 通信异常;发现前级电源有短暂异常掉电;L-Sensor 通信异常导致前级掉电

截止目前我们并没有发现什么太异常的东西,没有线索去指引分析。但是在串口日志中发现一个奇怪的现象,花屏的时候,都伴随着光感传感器I2C通信异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[2024-05-16 10:13:58]  [    4.362148] <5>.(5)[1:swapper/0]i2c_dump_info: -----------------------
[2024-05-16 10:13:58] [ 4.362969] <5>.(5)[1:swapper/0]i2c i2c-1: last transfer info:
[2024-05-16 10:13:58] [ 4.363699] <5>.(5)[1:swapper/0]i2c i2c-1: [00] [ 4.343075] SLAVE_ADDR=86,INTR_STAT=2,CONTROL=28,FIFO_STAT=1101,DEBUGSTAT=300, tmo=500
[2024-05-16 10:13:58] [ 4.365236] <5>.(5)[1:swapper/0]i2c i2c-1: [01] [ 3.710385] SLAVE_ADDR=48,INTR_STAT=2,CONTROL=28,FIFO_STAT=1210,DEBUGSTAT=300, tmo=500
[2024-05-16 10:13:58] [ 4.366781] <5>.(5)[1:swapper/0]i2c i2c-1: [02] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.368221] <5>.(5)[1:swapper/0]i2c i2c-1: [03] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.369661] <5>.(5)[1:swapper/0]i2c i2c-1: [04] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.371108] <5>.(5)[1:swapper/0]i2c i2c-1: [05] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.372549] <5>.(5)[1:swapper/0]i2c i2c-1: [06] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.373989] <5>.(5)[1:swapper/0]i2c i2c-1: [07] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.375436] <5>.(5)[1:swapper/0]i2c i2c-1: [08] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.376877] <5>.(5)[1:swapper/0]i2c i2c-1: [09] [ 0.000000] SLAVE_ADDR=0,INTR_STAT=0,CONTROL=0,FIFO_STAT=0,DEBUGSTAT=0, tmo=0
[2024-05-16 10:13:58] [ 4.378323] <5>.(5)[1:swapper/0]i2c i2c-1: addr:0x43,ACK error
[2024-05-16 10:13:58] [ 4.379064] <5>.(5)[1:swapper/0][ALS] gt4421_i2c_read_reg 162 : read reg send res = -121

软件逻辑上光感传感器与显示无关,排查发现光感传感器与6151不在同一路I2C,但是会共用前级电源(V3P3A)。因此两者之间可能有关联,先来看看这个i2c通信失败和花屏有没有关联。

电路图如下,LCM电源会使用V3P3A这路电。它和光感传感器是共用的电源。

Action小结结论
日志看花屏现象伴有L-Sensor的I2C通信异常花屏和L-Sensor可能不是巧合,有相关性,要证明是否因果关系,需要用示波器确认时间点L-Sensor通信失败,相关或因果地,使V3P3A短暂掉到底
V3P3A会给屏供电,供电的异常有导致花屏的重大嫌疑
示波器抓取V3P3A波形、I2C波形
(V3P3A电源来自VPA_PMU,给屏、TP、L-Sensor使用)
1. 花屏发生时,L-Sensor有三次连续i2c通信(Write,无ACK)后,V3P3A短暂掉电
2. 摄像头录像确认,花屏是紧接着随后发生的
3. 异常掉电波形见下图
查阅L-Sensor驱动,确定会通过Regulator关闭前级电源V3P3A驱动代码如下展示L-Sensor通信失败,会通过regulator关闭V3P3A的输出
拔掉光感后进行实验花屏现象从概率性发生,变成必现花屏现象与光感通信异常情况强相关
保持光感装好,软件关闭光感驱动花屏现象不再复现

波形图如下所示,可以看到电源有短暂的异常掉到0。

由于这一路电源是PMIC输出的,驱动能力和稳定性都较强,而且每次复现的时候波形都是一致的,因此基本认定异常波形应该是来源于软件的异常逻辑。

既然花屏的时候伴随着光感传感器的通信异常问题,那么直接定位到对应驱动代码的位置,如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
......

exit_create_attr_failed:
exit_sensor_obj_attach_fail:
exit_misc_device_register_failed:
misc_deregister(&gt4421_device);
exit_init_failed:
kfree(obj);
gt4421_obj = NULL;
if(regulator_disable(rgb_3v3)){
APS_ERR("gt4421 disable regulator failed.");
}
exit:
gt4421_i2c_client = NULL;
APS_ERR("%s: err = %d\n", __func__, err);
gt4421_init_flag = -1;
return err;

......

这段代码是光感传感器初始化(probe)过程中,碰到i2c通信失败,即没有与传感器正常通信的情况下,走的失败逻辑。其中的关键代码是regulator_disable(rgb_3v3),它通过regulator接口关闭了3.3V的电源供电,因此造成了供电电源的异常波形。

由于这一路电源同时给屏供电,因此这一异常的电源波形使屏端的逻辑出现异常,进一步导致了花屏现象的发生。

L-Sensor概率性通信异常根因:SDA/SCL台阶问题

从前面的分析可以确定,我们发现了事故的直接原因。即光感传感器初始化失败,其驱动代码关闭了前级电源,致使屏的电源异常,导致花屏。

问题的“概率性”来源。实际上花屏不是“概率性”的,只要是V3P3A掉电了,必定会花屏。而“概率性”的来源是L-Sensor概率性的通信异常。因此问题转向为分析光感传感器概率性通信异常的原因。

L-Sensor本身比较简单,其电信号总共只有使能、i2c两根线,加起来3个信号。

Action小结结论
示波器量取RGB_PWR_EN未见异常光感传感器概率性通信异常不是因为它自己的供电有问题
i2c影响(驱动能力)检查该路i2c已经配置CPU内部上拉,且L-Sensor本身具备内部上拉与i2c干扰无关,与同一路i2c上的重力传感器无关,i2c链路未见异常
i2c影响(其他client)该路i2c还插着g-sensor,贴在板上无法拿下,软件关闭驱动后复测,可复现花屏
i2c影响(波形)示波器体现,波形健康
示波器量取SDA波形SDA进入工作状态前,有0.7V台阶,自CPU IO reset后就存在i2c开始工作前有异常电平,有较大嫌疑(异常波形放在“异常根因”小结展示)
示波器量取SCL波形SCL进入工作状态前,有0.7V台阶,自CPU IO reset后就存在
临时措施,将台阶压下去i2c启用前,将SDA、SCL的电放掉,让台阶下来异常电平压下去后,i2c不再复现异常通信的情况,花屏不再复现

到这里,问题不再复现了,我们从找到花屏的直接诱因,并顺藤摸瓜到找到了根本的原因。

异常根因

在最前面先展示一下异常波形,如下图。

其中,紫色、蓝色线分别代表L-Sensor(光感传感器)的i2c的SDA和SCL两根线。图上有相应标注,特别说明的,这个图是导入了解决措施后抓取的。在图的左半部分有标记出来的“异常的台阶”,它就是异常的电平。中部标记的“放电,压下台阶”是导入了措施后。未导入前的异常情况下,这个台阶没有放电过程,一直有不小的台阶存在。

SDA和SCL一高一低,原因是示波器选取的0基准线的位置的差异,实际上它们电平相等

首先来解释一下在解决措施导入前,L-Sensor会概率性通信失败的原因。

我们通过示波器看到,L-Sensor i2c线上有一些抬起来的电平(台阶)。由于这个台阶不算小,而且这一型号的L-Sensor本身器件设计、制造上带来的电气特性,使得台阶(即i2c线路上的电压),顺着i2c线及L-Sensor芯片内部的电路,对其灌入电流。灌入的电流相当于对芯片进行了半残废的供电,可能会导致其处于半工作状态。

但由于不是正常的正确的供电,因此内部逻辑可能紊乱,就像程序引用空指针一样行为是未定义的,会出现概率性的通信异常。

当然,平时i2c正常工作都是拉高的,这个时候为什么不怕灌电流呢?因为在正常情况下,L-Sensor是有正常电源供电的,i2c上的电流灌不进来,或者是L-Sensor已经正常启动了,不再像灌电流那样跑飞了

至于i2c为什么会出现台阶,分析下电路图可以发现,i2c的两根线是从CPU的引脚上出来的,CPU初始化后,引脚处于悬空态,因此有台阶电平出来。

1
2
flowchart LR
开机 --> GPIO初始化 --> i2c线所在引脚悬空 --> 产生电平台阶 --> 对光感传感器灌电 --> 光感传感器i2c概率性通信异常

开机过程中,L-Sensor的驱动会尝试与L-Sensor进行i2c通信。当通信失败时,驱动代码逻辑将V3P3A下电了,影响了屏的电源稳定性,导致花屏。

1
2
flowchart LR
光感传感器i2c概率性通信异常 --> regulator_disable --> 屏的电源有异常掉电 --> 屏工作异常 --> 花屏

解决方案

对于L-Sensor而言,其器件特性决定了无法耐受住i2c上小台阶(0.7V作用)的灌电,使得L-Sensor ic处于半工作半死、没正常运行的阶段。

从SDA/SCL漏进去的电让内部ic错乱了,使得L-Sensor不再正常工作、不能正常启动。换句话说,即使器件没有上电,i2c漏进去的电使得器件实际上不是完全没电的,接下来的启动时序实际上不一定满足要求。

因此,解决这个问题很简单,要么让这个台阶不出现,要么出现后让它消失。

L-Sensor的电路图如下。

查看电路和规格书有如下几个重要的信息,用于决策我们的解决方案。

  • L-Sensor有一个电源,用于供电。它是常开的,很前级的电,影响很大,不能想着用它来放电;且它内部连接是PMIC的一个LDO,用于放电可能有其他异常————不能切断漏电路径,也不能用于放电。

就是这路电和屏共用的,被异常放掉了,出了花屏问题

  • SCL1直接接CPU I2C1,在RGB_3V3上拉没有使能的情况下,显然SCL和SDA的台阶就是SCL1自己导致的————台阶是CPU输出的
  • 漏电路径看————SCL1可以放电下掉台阶
  • 漏电路径看————RGB_3V3可以放电下掉台阶,但是有电阻,且属于CPU的两个GPIO之间有电流灌入流出

因此可以看到决策我们处理这个台阶的关键结论如下:

  1. 台阶是CPU i2c引脚自己输出出来的,它可以想办法不输出出来,或者出来后卸掉
  2. 漏电通路上,开关漏电路径的VIO18_PMU动不得,因此通过切断传输路径的方式来切断漏电的方案不可行

因此我们尝试再CPU引脚即SDA/SCL两根线上想办法。查看规格和代码配置有一个可行方案——把CPU引脚配置成下拉或输出0————这样可以避免输出台阶,并且就算输出了台阶也可以经CPU内部电路把台阶卸掉。

SCL1内部支持下拉,本事是SCL驱动能力较强————可以灌入电流(请硬件确认过),用SCL1来放电可以达成目标。

因此改法就很清晰了:借助dws将引脚配置为下拉,将台阶电放掉,在i2c使用之前,再切换到i2c模式,接入上拉。(实际上台阶无法完全去掉,因为CPU一旦完成初始化,这个引脚就是悬空的(芯片级默认模式),就会有台阶。CPU初始化完成后一段时间才跑到软件逻辑去下拉放电)

修改如下,只需要把对应引脚拉下去即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
              <gpio84>
<eint_mode>false</eint_mode>
- <def_mode>1</def_mode>
+ <def_mode>0</def_mode>
<inpull_en>true</inpull_en>
<inpull_selhigh>true</inpull_selhigh>
- <def_dir>IN</def_dir>
+ <def_dir>OUT</def_dir>
<out_high>false</out_high>
- <varName0>GPIO_I2C1_SCA_PIN</varName0>
<smt>false</smt>
<ies>true</ies>
</gpio84>

这个修改导入后,量取波形(前面展示过修改后的波形图)。可以看到i2c线的台阶会有一小段拉下来,这个操作可以把i2c线上的电拉下来,把灌入L-Sersor的电放干净,使光感传感器处于正常的状态。

经过压测后问题能成功修复,再也没有复现到L-Sensor i2c通信异常和花屏异常了。

优化措施:Regulator失效了?

熟悉驱动的朋友,应该能看到一个不合理的地方。通常情况下,一些公共使用的资源,在共用这些资源的模块之间,会以特定的协作方式来控制资源的开关,防止互相干扰。比如一个智能指针,会在一个对象的引用计数降低到0的时候再回收它。

对于驱动来说,对共用电源的控制一般采用regulator。当regulator的引用计数降低到0后才真正关闭电源。

那么,在L-Sensor驱动和屏驱动均规范使用了regulator的情况下,为何屏还在用的电,仍然被L-Sensor regulator_disable关掉了呢?

经过分析,添加日志后发现,屏驱动的初始化居然在传感器后面,传感器先初始化,然后才是屏初始化。

用一个表格来说明这个逻辑,以及它是怎么触发花屏问题的。

这个问题中共用的电源来自于PMIC,下表用PMIC输出来表示这个电源,1表示打开,0表示关闭

开机过程顺序 跑的逻辑 PMIC输出状态 Regulator计数 备注
PMIC初始化 根据代码配置,将PMIC输出为高电平 1 0 此时对使用该电的设备供电(屏和L-Sensor)
初始化L-Sensor 进入L-Sensor驱动,regulator +1 1 1 PMIC本来就输出高电平,这里+1后仍然出高电平,供电正常
L-Sensor通信失败 L-Sensor做异常释放逻辑,将regulator计数-1 0 0 Regulator计数掉为0,触发关闭电源的逻辑,使PMIC输出0
初始化屏 进入屏驱动,regulator +1 1 1 regulator不为0,打开PMIC供电

regulator正确使用,供电也正常,逻辑没问题,为什么花屏了呢?

原因在于第一步PMIC就已经是输出高电平,开始对L-Sensor和屏供电了。对于屏而言,过早的供电,不仅使屏芯片已经处于工作状态,后面的异常掉电的波形不仅不是让它重启,反而是让它变得紊乱、异常。此外,屏的初始化有时序要求,在屏驱动初始化时,本来上电时序是设计好的,谁曾想驱动逻辑想要控制的电源实际上早在L-Sensor初始化时就上好了电呢?

换句话说,就是屏不一定想要这么早上电,而且上完电后就稳稳地给我电,中间突然来一下掉到零这叫什么?

显而易见的,在屏驱动运行前,屏就已经上电了,这个时候开机亮屏都是正常的,可谓歪打正着,给屏的供电是意料之外的但是却一脸懵逼的。

因此看上去很离谱的“光感传感器通信异常居然能导致我花屏???”是有合理解释的。

我们能看到这个模块初始化顺序不仅导致功能强大的Regulator失去了其作用,而且在体验上,用户觉得开机速度快不快很大程度上就是开机亮屏快不快,居然先给我在屏初始化之前去初始化了传感器这个用户无感的模块。

最后,这个问题也很好处理,我们调整屏的初始化到前面即可。一般调节初始化阶段(initcall)会有效果。但是由于Linux各模块启动顺序有很大牵扯关联,这么改是有风险的。因此我们通过调节模块链接顺序即可实现在同一个initcall阶段内去调节模块的初始化顺序(调节链接顺序即可)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
diff --git a/drivers/misc/mediatek/Makefile b/drivers/misc/mediatek/Makefile
index b8e611a48b1f..1544f7159cbe 100755
--- a/drivers/misc/mediatek/Makefile
+++ b/drivers/misc/mediatek/Makefile
@@ -84,7 +84,6 @@ obj-$(CONFIG_MTK_AUXADC) += auxadc/
obj-$(CONFIG_MTK_GPT_SCHEME_SUPPORT) += partition/
obj-$(CONFIG_MTK_PWM) += pwm/
obj-$(CONFIG_MTK_IRTX_PWM_SUPPORT) += irtx/
-obj-$(CONFIG_MTK_SENSORS_1_0) += sensors-1.0/
obj-$(CONFIG_MTK_TINYSYS_SCP_SUPPORT) += scp/
obj-$(CONFIG_MTK_HIFIXDSP_SUPPORT) += hifi_dsp/
obj-$(CONFIG_MTK_HIFIXDSP_SUPPORT) += hifidsp_audio_ipi/
@@ -123,6 +122,7 @@ obj-$(CONFIG_MTK_CMDQ) += mdp/
obj-$(CONFIG_MTK_SMI_EXT) += smi/
obj-$(CONFIG_MTK_LCM) += lcm/
obj-$(CONFIG_MTK_LCM) += ext_disp/
+obj-$(CONFIG_MTK_SENSORS_1_0) += sensors-1.0/
obj-$(CONFIG_MTK_HDMI_SUPPORT) += hdmi/
obj-$(CONFIG_MTK_FB) += video/
obj-$(CONFIG_MTK_DYNAMIC_FPS_FRAMEWORK_SUPPORT) += dfrc/

为什么其他项目没有这个问题

  1. 电路设计差异

其他项目的板子,i2c SCL/SDA那里不使用mos fet,而使用专门的转接芯片。区别是,mos管会被一定的电压打开(本案说的小台阶就是这个“一定的电压”),而转接芯片不会。

一句话说,mos fet会因小台阶而导通,使电漏过去。

  1. L-Sensor差异

本案涉及的L-Sensor是1.8V的器件,且其内部电路设计和工艺制程会受到SDA/SCL的灌电影响,处于不正常的工作状态和不正常的上电时序。

  1. CPU IO配置

在开机过程中IO没有配置下拉,会使SDA/SCL存在台阶,产生了灌电流