转自:https://blog.csdn.net/dearsq/article/details/52354593
调试流程
设置 dts 中的参数 并 配置管脚
背光部分
LCD 初始化序列 cmds
打开 config
检查电压
调试顺序
1 背光有没有亮
2 开机 以及 从休眠状态唤醒 都没有显示内容
3 我碰到的 cmds 问题
问题集锦
我调试中碰到的问题
其他一些杂散的需要确认的内容
参数为 8 字节16字节 传输会异常错可以正常传输
显示偏移图像位置偏差
白屏
屏在进出睡眠或者显示过程中白屏
花屏
屏幕闪烁
屏幕抖动
屏幕闪动
唤醒闪屏问题
屏幕唤醒显示灰色底面
水波纹
调节对比度
确认有没有 framebuffer 输出
图像颜色不正常
感谢
调试流程
1. 设置 dts 中的参数 并 配置管脚
仿造平台的其他 lcd-*-mipi.dtsi 编写 lcd-xxx-mipi.dtsi 后 需要在 主 dts 文件中包含这个 dtsi
#include “lcd-xxx-mipi.dtsi“
1
先看屏的手册
里面的关键信息有 分辨率(540×960) 接口(2条lanes)
## MIPI Host配置
disp_mipi_init: mipi_dsi_init{
compatible = "rockchip,mipi_dsi_init";
/* 是否要在 dtsi 中初始化 1 0 */
rockchip,screen_init = <1>;
/* 要几条数据 lane ,根据原理图和 mipi 规格书*/
rockchip,dsi_lane = <2>;
/* ddr clk 一条 lane 的传输速率 Mbits/s */
/* 100 + H_total×V_total×fps×3(一个rgb为3字节)×8(8bits)/lanes */
/* 这里的 total 指的是 sync + front + back + active */
/* 比如 H_total = Hsync + HFP(hfront-proch) + HBP(hback-porch) + Hactive */
rockchip,dsi_hs_clk = <1000>;
/* 单mipi 还是双 mipi*/
rockchip,mipi_dsi_num = <1>;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
看原理图,完成管脚的配置
可以看到,我这里只用到了 LCD_RST,没有用到 LCD_EN (是 VCC_LCD),说明是默认使能的,也没有 LCD_CS
所以进行如下配置
## 屏电源控制配置
disp_mipi_power_ctr: mipi_power_ctr {
compatible = "rockchip,mipi_power_ctr";
mipi_lcd_rst:mipi_lcd_rst{
compatible = "rockchip,lcd_rst";
rockchip,gpios = <&gpio2 GPIO_B7 GPIO_ACTIVE_LOW>;
rockchip,delay = <100>;
};
/*
// 配置 lcd_en GPIO 哪一路 ,有可能没有 LCD_EN 那么就是 VCC 常供电
mipi_lcd_en:mipi_lcd_en {
compatible = "rockchip,lcd_en";
rockchip,gpios = <&gpio0 GPIO_C1 GPIO_ACTIVE_HIGH>;
rockchip,delay = <100>;
};
*/
//还可能有片选 cs
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
根据屏的规格书 完成 timings 配置
垂直方向的信息:
重要的参数有 垂直同步信号 VFP VBP VS 对应填充到屏参中的 Vfront-proch Vback-proch Vsync-len
同样
水平方向的信息:
要注意的是, HS HBP HFP 虽然最小值是 5,但是不能设置的这么低
因为后面还有两条要求,HBLK = HS + HBP + HFP >= 24 且 HS + HBP > 19
所以最初设置 HS = HBP = HFP = 10
// lcd-xxx-mipi.dtsi 中的 屏参
disp_timings: display-timings {
native-mode = <&timing0>;
compatible = "rockchip,display-timings";
timing0: timing0 {
screen-type = <SCREEN_MIPI>; //单mipi SCREEN_MIPI 双mipi SCREEN_DUAL_MIPI
lvds-format = <LVDS_8BIT_2>; //不用配置
out-face = <OUT_P888>; //屏的接线格式
//配置颜色,可为OUT_P888(24位)、OUT_P666(18位)或者OUT_P565(16位)
clock-frequency = <120000000>; //dclk频率,看规格书,或者 H×V×fps
hactive = <540>; //水平有效像素
vactive = <960>; //垂直有效像素
hback-porch = <80>; //水平同步信号
hfront-porch = <81>; //水平同步信号
vback-porch = <21>;
vfront-porch = <21>;
hsync-len = <10>; //水平同步信号
vsync-len = <3>;
hsync-active = <0>; //hync 极性控制 置 1 反转极性
vsync-active = <0>;
de-active = <0>; //DEN 极性控制
pixelclk-active = <0>; //dclk 极性控制
swap-rb = <0>; //设 1 反转颜色
swap-rg = <0>;
swap-gb = <0>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2. 背光部分
在 rk3288-tb_8846.dts 中还需要打开 mipi 相关的通道 并 配置背光相关的信息。
首先根据这颗背光 IC 的 datasheet
我们了解到 EN 拉高时背光使能,拉低时背光禁能; FB 接受反馈信号,动态控制背光亮度
我们知道这颗背光芯片有两种调光方式
一是 EN 输入 PWM 信号进行调光
二是 EN 使能后,通过 FB 获得反馈信号进行调光。
根据我们的原理图
BL_EN 是普通的 GPIO ,LCDC_BL 是支持 PWM 输出的管脚,所以得知我们硬件采用的是第二种调光方式
backlight {
compatible = "pwm-backlight";
pwms = <&pwm0 0 25000>; //在这里配置采用的是 pwm0 还是 pwm1
brightness-levels = <255 254 253 252 251 250 249 248 247 246 245 244 243 242 241 240
239 238 237 236 235 234 233 232 231 230 229 228 227 226 225 224 223 222 221 220
219 218 217 216 215 214 213 212 211 210 209 208 207 206 205 204 203 202 201 200
199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180
179 178 177 176 175 174 173 172 171 170 169 168 167 166 165 164 163 162 161 160
159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144 143 142 141 140
139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120
119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100
99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70
69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40
39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10
9 8 7 6 5 4 3 2 1 0>;
default-brightness-level = <200>;
enable-gpios = <&gpio7 GPIO_A2 GPIO_ACTIVE_HIGH>; //BL_EN 背光使能管脚
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
3. LCD 初始化序列 cmds
最后如果有初始化序列的,打开之前的 screen-init = < 1 > ,并且填充初始化序列
## 屏初始化序列
disp_mipi_init_cmds: screen-on-cmds {
compatible = "rockchip,screen-on-cmds";
/*rockchip,cmd_debug = <1>;
rockchip,on-cmds1 { //指的是一条初始化命令
compatible = "rockchip,on-cmds";
rockchip,cmd_type = <LPDT>; //命令是在 low power(LPDT)还是 high speed(HSDT)下发送
rockchip,dsi_id = <2>; //选择通过哪个mipi发送 0==》单mipi0 1==》mipi1 2==》双mipi0+1
rockchip,cmd = <0x05 0x01>; //初始化命令
//第一个字节 DSI 数据类型; 第二个字节为 LCD 的 CMD; 后面为指令内容
rockchip,cmd_delay = <0>;
};
*/
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
值得一讲的是 cmd,一般屏厂或者FAE都会给出初始化序列。
比如这里我拿到的是 MTK 平台的 LCD 初始化代码:
data_array[0]=0x00043902;
data_array[1]=0x8983FFB9;
dsi_set_cmdq(&data_array, 2, 1);
MDELAY(10);
1
2
3
4
分析得知
array[0] 中 04 代表要传输的字节数,3902 代表传输的是长包数据
//MTK平台 3900 代表不传值 3905 表示传一个数据 3902 表示传多个数据
array[1] 中的参数全部为传输的参数,而且正确的传参数据为 B9 FF 83 89
所以移植到 RK 平台就是:
rockchip,on-cmds1 {
compatible = "rockchip,on-cmds";
rockchip,cmd_type = <LPDT>;
rockchip,dsi_id = <0>;
rockchip,cmd = <0x39 0xB9 0xFF 0x83 0x89>;
//0x39 为 DSI 数据类型、 0xB9 为LCD CMD、后面为参数
rockchip,cmd_delay = <10>;
}
1
2
3
4
5
6
7
8
我们根据 这块 lcd 的 规格书,也能够验证结果初始化命令参数的正确性:
DSI 协议中 ,0x29 和 0x39 区别:在 Mipi 协议中,它俩都表示 长包(Long Packet)数据类型。
但是 Mipi DSI 的 Spec 中写着两者的区别 0x29 属于 Generic long write ,0x39 属于 DCS long write。
DCS 系的读写命令,可带参数,常用于 LCD 初始化参数命令。
Generic 系读写命令,是协议规范外的命令,通常是一些 IC 定制的,只要确保主机和外设同意这些数据格式即可,通常和 DCS 通用。
另外值得一说的是大部分初始化代码的最后一般都是 exit_sleep 和 display_on。
rockchip,on-cmds15 {
compatible = "rockchip,on-cmds";
rockchip,cmd_type = <LPDT>;
rockchip,dsi_id = <0>;
rockchip,cmd = <0x05 dcs_exit_sleep_mode>;
rockchip,cmd_delay = <120>;
};
rockchip,on-cmds16 {
compatible = "rockchip,on-cmds";
rockchip,cmd_type = <LPDT>;
rockchip,dsi_id = <0>;
rockchip,cmd = <0x05 dcs_set_display_on>;
rockchip,cmd_delay = <100>;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
这里 dcs_exit_sleep_mode dcs_set_display_on 在 drivers/video/rockchip/transmitter/mipi_dsi.h 中有定义
#define dcs_set_display_on 0x29
#define dcs_exit_sleep_mode 0x11
1
2
所以表示的 0x05 0x11 表示的含义为,短包传输 发送 exit_sleep_mode 命令
这两个命令后的延时*相当重要*!!务必确认好。
4. 打开 config
根据 RK 手册中的要求
make menuconfig
打开三个宏
这里也可以顺手把 LVDS 的相关代码给关掉
5. 检查电压
先不要接上屏,编译完代码烧录后开机。
检查原理图上各个供电管脚的电压(DVDD、IOVDD 是否为 3.3V,VDD_LCDA 是否为 5-10V,VDD_LCDK 是否为 0V),确认电压正常后,关机,上屏,结合 开机log 看能否正常开机。
6. 调试顺序
6.1 背光有没有亮
背光没亮的话确认一下接上屏的时候,量一量 VDD_LCDA 的电压为多少(串联电路大概能到 20V+)
没有就去检查背光电路供电电压和 backlight 相关的配置
6.2 开机 以及 从休眠状态唤醒 都没有显示内容
之所以这样说是因为可能存在 休眠唤醒 能显示,但 开机 无法显示的情况
如果两种情况都没有显示,那么很有可能是 cmds 或者 timing 仍然有问题
1. 用示波器量波形看 DCLKP 的频率为多少,是否为 clock-frequency 中设置的(可能实际的会略低一点)
2. 量 RST 是否有一个 低-高 的变化,没有则是 rst 设置的触发方式可能反了
3. 在 RST 高低高后会开始传输数据,量 lanes 是否有数据输出。抓取数据需要专门的仪器,我们用示波器大致看看有没有数据输出就够了。
我在调试的时候就发现 lane 一直为低电平,没有数据传输,然后采取量 RST 发现唤醒屏后待到屏幕快灭了 RST 才会被拉高。跟代码发现 RK 平台的实现是
!你设置的触发电平
你设置的触发电平
1
2
但是我设置的触发电平是 低电平有效 ACTIVE_LOW
即
!ACTIVE_LOW
ACTIVE_LOW
1
2
即先高再低,所以是错的,改为 ACTIVE_HIGH 后正常。
但是虽然填的是 ACTIVE_HIGH ,但是应该还是属于低电平有效的,这里是 RK 平台 driver 的实现有问题。
修改后 lane 有数据传递了。
但是有数据传递仍然怎么样都没有显示。
这时候有极大可能是 cmds 有问题。
下面着重讲一下我 cmds 碰到的问题。
6.3 我碰到的 cmds 问题
我当时拿到 MTK 平台参数的时候,有的参数超过了 32个字节(有个有36个字节,有个有39个字节),完成 dtsi 中 cmds 编写后
烧录,板子跑飞,空指针异常。
发现传递 这个超长 参数的时候有内存溢出情况。
于是跟代码发现 dcs_cmd.cmds 的大小为 int cmds[32],所以擅自想当然的将包拆成了 39 = 28+11,还将其中的延时设置为 0 。
这样当然是不行的。但是一切都是基于这个拆了包的 cmds 来调,走了不少弯路。
后来一切的其他参数都确定没问题了。
于是去联系原厂的工程师,说平台参数大小有限制,咨询拆包是否可行。他们说建议修改 cmds[32] 改成了 cmds[400] 。
修改后发现屏幕终于点亮了。
终于点亮了。
点亮了。
问题集锦
RK 手册中已经有相当一部分很有参考价值的了。
这里的一部分是自己碰到的,有的是查资料时候收集到觉得很有意义的,都放这里了。
1. 我调试中碰到的问题
在点亮屏后刚开始有开机 logo 闪烁,向右偏移了近半个屏幕的长度,等问题。
重新确认 clock-frequence 后发现少打了一个 0 。
修改后解决了 闪烁,大偏移 的问题。
最初偏移还是有点大,如下图。
稍微降低 hs_clk ,由 504 降低到 496 解决。
垂直方向会显示多一点内容,如下图。
调整 VFP 后解决,将 VFP 增大为 15 。
下面会有黑边,如下图。
稍微增大 VBP 后解决,将 VBP 增大为 15。
开机 android 最左边会被裁剪一部分,如下图。
增大 HBP 后解决,将 HBP 由 10 增加到 30。
至此屏幕已完美显示。
2. 其他一些杂散的需要确认的内容
是否有framebuffer輸出,要是改動了display這塊的clk很有可能沒有buffer輸出的,可以通過cat /dev/graphyics/fb0查看有沒有輸出字符。(我是通过google 插件 vysor 直接连接开发板看有没有内容显示,windows 平台也可以用 total control 软件来看)
3. 参数为 8 字节、16字节 传输会异常?错,可以正常传输。
看到一篇文章中说,数据 cmds 为 8 字节 和 16 字节 的时候,写命令和数据的函数要注意变化。
然后在调试的时候发现 如果 参数为这两种情况的时候, 传输模式会自动由 LP 模式 变成 HS 模式。但这只是个意外。
跟踪代码后发现,其实是可以正常传输的,我这只是个意外而已:
http://blog.csdn.net/dearsq/article/details/52369879
4. 显示偏移、图像位置偏差
timing 中的参数设置有误。优先确认。
看着图像调节前扫、回扫进行左右上下移动
5. 白屏
随机出现白屏有可能是静电问题,把LCD拿到头发上擦几下,如果很容易出现白屏那肯定就是静电问题了。另外一个在有Backend IC的情况下,也有可能bypass没处理好。
結束開機logo至android動畫出現之間出現閃屏或者閃白光的情況。原因:在這個時間點kernel會會對屏再次初始化,我們可以軟件上屏蔽第一次初始化動作從而解决。
6. 屏在进出睡眠或者显示过程中白屏
喚醒屏幕閃白光問題,說白了是背光早亮了,很有可能是下序列mdelay太久,改小點就沒有這個問題了。根本原因屏幕初始化序列下慢了。
sleep out(0x11)和 display on(0x29)之间需要 mdelay(120ms)左右。
7. 花屏
说明 lcd 初始化成功,但是没有 rgb 刷过来。
timing 中的参数设置有误。优先确认 pclk。
花屏 还可能是总线速度有问题。
开机就花屏最简单的解决方式是,在 Init 结束的地方加一个刷黑屏的功能。也可以在睡眠函数里加延时函数。
8. 屏幕闪烁
pclk 有问题
在最开始的时候,我的 pclk 漏了一个 0 ,为之前的 1/10 此时就有图像闪烁问题。
proch 有问题
在调试完后,我尝试将 proch 增加到极限,发现会出现图像闪烁的问题。
9. 屏幕抖动
测时序,延时不足
10. 屏幕闪动
通过调节电压来稳定,一般调节的电压为VRL、VRH、VDV和VCM
11. 唤醒闪屏问题
这是由於每次重新RST下序列過程delay久了導致,适當減少delay時間
12. 屏幕唤醒显示灰色底面
寄存器没有使能外部升压电路
13. 水波纹
通常都是rgb interface polarity導致,需要調整pclk hsync vsync de極性使之符合平台極性
14. 调节对比度
VRL、VRH、VDV和VCM,这些电压也可以用来调节亮暗(对比度)
也可以通过调节Gamma值来实现,要调节的对象为 PRP、PRN、VRP、VRN 等
15. 确认有没有 framebuffer 输出
要是改动了display这块的clk很有可能没有buffer输出的,可以通过cat /dev/graphyics/fb0 查看有没有输出字符
如果有说明是 mipi 还没有调通,如果没有说明是 fb 有问题
16. 图像颜色不正常
可能时钟型号极性反了
可能 VCOM 调节不正常
进行 GAMMA 校正
感谢
这段时间基本上把有些 Mipi 移植和 RK 平台 LCD 移植的文章看遍了。以下文章很有帮助。本文的问题集锦部分有一部分是将以下文章中的内容搜罗过来的:
android lcd調試 高通平台lcd調試深入分析總結(mipi和rgb接口)
firefly rk3288 的 wiki 百科
Mipi DSI 协议介绍
Mipi 调试经验
最后,得感谢这段时间师兄 Baker 和 Nick 的指点。
还有网上两位 RK 刘哥和“llg”和“勇气” 的指点。
收益颇丰。谢谢谢谢!
另外 刘哥 llg 提出了一种方法:不起 android ,直接写 framebuffer 。这样对像素点的直接操作会比对图片的操作更加直观。
暂时还不了解是什么意思,准备今晚下班了去了解一下。
也顺便帮刘哥打个广告:刘哥的站点: http://www.laoliu-soft.net/
[版权声明]本文地址:http://blog.csdn.net/dearsq/article/details/52354593
欢迎转载,转载请著名出处和作者 Younix~谢谢~
————————————————
版权声明:本文为CSDN博主「Younix脏羊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dearsq/java/article/details/52354593