1. 程式人生 > >Mipi LCD 通用移植除錯流程

Mipi LCD 通用移植除錯流程

前言

其實之前有寫過一篇關於 =RK3288 平臺 LCD 除錯流程的部落格 。不過是 RK3288 Android5.1 平臺的。
雖然實際上 Mipi 部分程式碼實在是大同小異。但是距上次那篇文章到現在也已經不知不覺整整一年了,這一年 Mipi LCD 確實也調了不少。
索性再次重新梳理一下,也許會有別樣的收穫吧。
沒有看過那篇文章的同學也不需要再看了,這篇文章會更加全面的描述和分析除錯流程。
這次文章以 RM72014 這顆 Driver IC 為例,從 RK Mipi LCD 程式碼分析 到 屏的公式計算 再到實踐中的問題都會涉及,除錯為主,分析為輔,比較冗長,大家可以挑選自己需要的部分來看。
隨著我碰到的情況更多,本文也將不斷更新。
也歡迎大家留言分享交流自己碰到的情況和解決方案。

一、扣出屏 datasheet 中的關鍵資訊

首先我們要找屏廠索取詳細版的屏的規格書,扣出其中的關鍵資訊。
屏 Spec 的目錄大概如下:

其中我們最需要關注的是
General Specification
Power on/off sequence
上電下電時序
Timing 屏參

1. General Specification

提煉出來關鍵資訊是
Hactive = 800 ,水平解析度
Vactive = 1280 ,垂直解析度
Lanes = 4 ,Mipi data 訊號線通道數

2. Power on/off sequence

這個在屏點不亮的時候需要首先確認,這個我們後面會說。
我們在調屏的時候可以先把這個截圖儲存到自己的筆記中,就不需要每次都去翻 datasheet 了。

3. Timing

關鍵資訊提煉出來:
Hactive = 800
HFP = 24
HBP = 132
Hsync = 4

Vactive = 1280
VFP = 8
VBP = 8
VSync = 4

Pixel Clock Frequency(Pclk)= 74.88MHZ

這裡我們詳細說一下各個引數的含義,這個對我們後續調屏會非常有幫助。
更加詳細全面的參見 NXP 的一份資料:graphics.lcd.technologies.pdf

說白了核心思想就是下面這張圖:

Horizontal 代表水平方向,HBP 行同步訊號後肩 、HFP 行同步訊號前肩,單位是 clocks,什麼 clock ?pclk (pixel clock frequence),畫素時鐘頻率,也就是我們在 dts 中填充的 clock-frequence 這個引數。
Vertical 代表垂直方向,VBP 幀同步訊號後肩、VFPP 幀同步訊號前肩,單位是 lines。

另外根據以上的資訊,我們還能計算出 Mipi Dsi Clock 。
DCLK = 100 + H_total×V_total × fps × 3 × 8 / lanes_nums
total 這裡指的是 sync + front + back + active
比如 H_total = Hsync + HFP(hfront-proch) + HBP(hback-porch) + Hactive
fps 指的是幀率,一般我們按照 60 幀來計算
3 × 8 代表一個 RGB 為 3 個位元組,每個位元組 8 bit
lanes 代表 mipi data 通道數

所以對於我這個屏
DCLK
= 100Mbps + H_Total × V_Total x fps x 3 x 8 / lanes_nums
= 100 + ( 800 + 21 + 132 + 4 ) x ( 1280 + 8 + 8 + 4 ) x 60 幀 x 3 位元組 x 8 bit / 4 lanes
= 100Mbps + 449Mbps = 549 Mbps

二、根據屏參 和 硬體設計填寫 dts

RK LCD 這部分的去耦合性已經做的很好了。
我們僅僅只需要填寫 dts ,驅動會自動解析 dts ,
管腳控制部分會自動申請分配操縱 GPIO,屏初始化程式碼(init cmds)和屏參(timing)將被自動封裝成 mipi dsi 命令進行傳送。

2.1 建立屏的 dtsi 檔案

仿造平臺的其他 lcd-*-mipi.dtsi 編寫 lcd-xxx-mipi.dtsi 後 需要在 主 dts 檔案中包含這個 dtsi。

&rk_screen {
  /* 8inch LCD Mipi */
  #include <dt-bindings/display/screen-timing/lcd-mipi-rm72014.dtsi>
};

根據前面我們獲取到的屏參資訊開始編寫 dtsi

2.1.1 Mipi Host

//MIPI Host配置
disp_mipi_init: mipi_dsi_init{
        compatible = "rockchip,mipi_dsi_init";

        /* 是否要在 dtsi 中初始化 1 是 0 否 */
        rockchip,screen_init    = <1>;

        /* 要幾條資料 lane*/
        rockchip,dsi_lane       = <4>;

        /* ddr clk 一條 lane 的傳輸速率 Mbits/s */
        /* 前面我們已經算得為 549 */
        rockchip,dsi_hs_clk     = <549>;

        /* 單mipi 還是雙 mipi*/
        rockchip,mipi_dsi_num   = <1>;
};

2.1.2 Timing

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 = <74488000>;   //dclk頻率,看規格書,或者 H×V×fps
            hactive = <800>;                 //水平有效畫素
            vactive = <1280>;                //垂直有效畫素
            hback-porch = <132>;              //水平同步訊號 後肩
            hfront-porch = <24>;              //水平同步訊號 前肩
            vback-porch = <8>;
            vfront-porch = <8>;            
            hsync-len = <4>;                //水平同步訊號
            vsync-len = <4>;
            hsync-active = <0>;              //hync 極性控制 置 1 反轉極性
            vsync-active = <0>;
            de-active = <0>;                 //DEN 極性控制
            pixelclk-active = <0>;           //dclk 極性控制
            swap-rb = <0>;                   //設 1 反轉顏色 red 和 blue
            swap-rg = <0>;
            swap-gb = <0>;
    };
};

2.1.3 init cmds

屏場給的初始化時序往往不會是 RK 平臺的。我們可能需要自己轉換一下。
不過一般也很好理解,我們分別分析兩組平臺的例子:

展訊平臺
GP_COMMAD_PA(02);SPI_WriteData(0x53);SPI_WriteData(0x24);
GP_COMMAD_PA(03);SPI_WriteData(0xf0);SPI_WriteData(0x5a);SPI_WriteData(0x5a); Delay_ms(30);
GP_COMMAD_PA(01);SPI_WriteData(0x11); Delay_ms(100);
GP_COMMAD_PA(01);SPI_WriteData(0x29); Delay_ms(30);
GP_COMMAD_PA(04);SPI_WriteData(0xc3);SPI_WriteData(0x40);SPI_WriteData(0x00);SPI_WriteData(0x28);
GP_COMMAD_PA(02);SPI_WriteData(0x50);SPI_WriteData(0x77);
GP_COMMAD_PA(02);SPI_WriteData(0xe1);SPI_WriteData(0x66);
GP_COMMAD_PA(02);SPI_WriteData(0xdc);SPI_WriteData(0x67);
GP_COMMAD_PA(02);SPI_WriteData(0xd3);SPI_WriteData(0xc8);
GP_COMMAD_PA(02);SPI_WriteData(0x50);SPI_WriteData(0x00);
GP_COMMAD_PA(02);SPI_WriteData(0xf0);SPI_WriteData(0x5a);
GP_COMMAD_PA(02);SPI_WriteData(0xf5);SPI_WriteData(0x80);
Delay(120);

GP_COMMAD_PA 表示 dsi packets 的個數
SPI_WriteData 介面用來寫資料
Delay_ms 表示延時 xx 毫秒
所以
GP_COMMAD_PA(02);SPI_WriteData(0x53);SPI_WriteData(0x24);
表示給屏 0x53 指令,有一個指令引數,為 0x24
GP_COMMAD_PA(03);SPI_WriteData(0xf0);SPI_WriteData(0x5a);SPI_WriteData(0x5a); Delay_ms(30);
表示給屏 0xf0 指令,有兩個指令引數 0x5a 和 0x5a ,並且延時 30ms
GP_COMMAD_PA(01);SPI_WriteData(0x11); Delay_ms(100);
表示給屏 0x11 指令,沒有指令引數,並且延時 100ms
GP_COMMAD_PA(01);SPI_WriteData(0x29); Delay_ms(30);
表示給屏 0x29 指令,沒有指令引數,並且延時 30ms

後面同理。

細心的同學發現了我這裡強調了指令引數的個數。
因為這涉及到了 dsi 協議中 dsi 傳輸的資料型別。
根據 《MIPI-DSI-specification-v1-1.pdf》49 頁我們可以看到,有如下這些資料型別。

我們只需要關注 0x05 ,0x15,0x39,他們分別對應的 dsi 引數型別是 無參指令(Short No parameters)、單引數指令(Short 1 parameter)、多引數指令(Long Command Packets)。

MTK 平臺
data_array[0]=0x00043902;
data_array[1]=0x8983FFB9; 
dsi_set_cmdq(&data_array, 2, 1); 
MDELAY(10);

分析得知
array[0] 中 04 代表要傳輸的位元組數,3902 代表傳輸的是多參指令
//MTK平臺 3900 代表無參 3905 表示單參 3902 表示多參
array1 中的引數全部為傳輸的引數,而且正確的傳引數據是倒著的 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 命令、後面為引數
                            rockchip,cmd_delay = <10>;
}
* Mipi DSI 協議中 Generic 和 DCS 的區別*

另外,值得一提的是。在上面 Mipi 的 Spec 中,大家可以看到 0x29 和 0x39 都可以表示多參,0x03 和 0x05 都可以表示無參,0x13 和 0x15 都可以表示單參。但他們不是沒有區別的。

DSI 協議中 ,0x29 和 0x39 區別:在 Mipi 協議中,它倆都表示 長包(Long Packet)資料型別。
但是 Mipi DSI 的 Spec 中寫著兩者的區別 0x29 屬於 Generic long write ,0x39 屬於 DCS long write。
DCS 系的讀寫命令,可帶引數,常用於 LCD 初始化引數命令。
Generic 系讀寫命令,是協議規範外的命令,通常是一些 IC 定製的,只要確保主機和外設同意這些資料格式即可,通常和 DCS 通用。

RK 平臺

上述兩個例子舉完了。我們繼續寫 RK 平臺 RM72014 的 inital cmds:

對應的 inital cmds

 disp_mipi_init_cmds: screen-on-cmds {
    rockchip,cmd_debug = <0>;
    compatible = "rockchip,screen-on-cmds";
    rockchip,on-cmds1 {
        compatible = "rockchip,on-cmds";
        rockchip,cmd_type = <LPDT>;
        rockchip,dsi_id = <2>;
        rockchip,cmd = <0x15 0x53 0x24>;
        rockchip,cmd_delay = <0>;
    };

    rockchip,on-cmds2 {
        compatible = "rockchip,on-cmds";
        rockchip,cmd_type = <LPDT>;
        rockchip,dsi_id = <2>;
        rockchip,cmd = <0x39 0xf0 0x5a 0x5a>;
        rockchip,cmd_delay = <30>;
    };

    rockchip,on-cmds3 {
        compatible = "rockchip,on-cmds";
        rockchip,cmd_type = <LPDT>;
        rockchip,dsi_id = <2>;
        rockchip,cmd = <0x05 0x11>;
        rockchip,cmd_delay = <100>;
    };

  rockchip,on-cmds4 {
        compatible = "rockchip,on-cmds";
        rockchip,cmd_type = <LPDT>;
        rockchip,dsi_id = <2>;
        rockchip,cmd = <0x05 0x29>;
        rockchip,cmd_delay = <30>;
    };

//... 

  rockchip,on-cmds11 {
        compatible = "rockchip,on-cmds";
        rockchip,cmd_type = <LPDT>;
        rockchip,dsi_id = <2>;
        rockchip,cmd = <0x15 0xf0 0x5a>;
        rockchip,cmd_delay = <0>;
    };

  rockchip,on-cmds12 {
        compatible = "rockchip,on-cmds";
        rockchip,cmd_type = <LPDT>;
        rockchip,dsi_id = <2>;
        rockchip,cmd = <0x15 0xf5 0x80>;
        rockchip,cmd_delay = <120>;
    };

cmd_type 表示 dsi 傳輸型別,分為 HSDT 高速(Video 模式) 和 LPDT 低速(command 模式)
dsi_id 表示通過哪一組 mipi 傳送。0 表示第一組 Mipi ,2 表示兩組同時發。1 表示第二組 Mipi,但是一般不會出現只用第二組的情況,所以不會是 1 。

2.2 硬體管腳 GPIO 配置

有兩種方式控制屏相關的 GPIO,一種是在屏 dtsi 中配置,一種是交由 vop 進行控制。

前者的例子如下,比如可以在 dtsi 中完成電源控制配置


 ## 屏電源控制配置
disp_mipi_power_ctr: mipi_power_ctr {
        compatible = "rockchip,mipi_power_ctr";
        mipi_lcd_rst:mipi_lcd_rst{
                compatible = "rockchip,lcd_rst";
                rockchip,gpios = <&gpio4 GPIO_D6 GPIO_ACTIVE_HIGH>;
                rockchip,delay = <10>;
        };

        // 配置 lcd_en GPIO 哪一路 ,有可能沒有 LCD_EN 那麼就是 VCC 常供電
        mipi_lcd_en:mipi_lcd_en {
                compatible = "rockchip,lcd_en";
                rockchip,gpios = <&gpio1 GPIO_B5 GPIO_ACTIVE_HIGH>;
                rockchip,delay = <10>;
        };

        //還可能有片選 cs
};

也可以交由 vop 控制,比如這樣:

&vopl_rk_fb {
    status = "okay";
  rockchip,prop = <PRMRY>;
  assigned-clocks = <&cru DCLK_VOP1_DIV>;
  assigned-clock-parents = <&cru PLL_CPLL>;
    power_ctr: power_ctr {
        rockchip,debug = <0>;
        lcd_en: lcd-en {
            rockchip,power_type = <GPIO>;
            gpios = <&gpio1 GPIO_B5 GPIO_ACTIVE_HIGH>;
            rockchip,delay = <10>;
        };
        lcd_rst: lcd-rst {
            rockchip,power_type = <GPIO>;
            gpios = <&gpio4 GPIO_D6 GPIO_ACTIVE_HIGH>;
            rockchip,delay = <10>;
        };
    };
};

GPIO_A / B C 的定義在 kernel/arch/arm64/boot/dts/include/dt-binding/pinctl/rk.h 中
delay 需要根據上面的時序圖進行設定,一般 10ms 可以適配大部分的螢幕了。
這裡的 rockchip,gpios 我們根據硬體進行配置:

        rockchip,gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;  // GPIO4_D6
  • 1

        rockchip,gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; //GPIO1_B5
  • 1

三、背光 Backlight

背光常用的有三種情況:
一是 常開。
二是 背光 IC 使能後,輸入 PWM 訊號調光。
三是 背光 IC 使能後,通過 FB 獲得反饋自動進行調光。

比如我曾用到一顆 背光 IC 是這樣的:

enter description here

enter description here

我們瞭解到 EN 拉高時背光使能,拉低時背光禁能; FB 接受反饋訊號,動態控制背光亮度。

根據相關的原理圖

enter description here
enter description here

BL_EN 是普通的 GPIO ,LCDC_BL 是支援 PWM 輸出的管腳,所以得知我們硬體採用的是第二種調光方式

完成 dts 中 backlight 相關的配置

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 背光使能管腳
    };

四、確認驅動程式碼和 vop/lcdc 通道開啟

make menuconfig 確認一下三個巨集開啟

enter description here

dts 中確認

//   RK3399 平臺
    &mipi0_rk_fb {
      status = "disabled";
    };

// RK3288 平臺
    &dsi_host {
      status = "disabled";
    };

五、除錯流程

一般按照上面的順序,編譯,燒錄後。
幸運的話,屏就可以點亮(有東西顯示)了。

但是這個世界對長的帥的人就是如此不公平。
至少我從來沒有一次就直接點亮過。

下面我們開始進入除錯階段。

5.1 檢查電壓

檢查原理圖上各個供電管腳的電壓
VCC 、VCC IO 是否正常。
VCC IO 是給 GPIO 供電用,比如 RST。有的屏會相容 3.3V 和 1.8 V 的 IO 電平,但是大部分不會。
VCC_LCDA 、VCC_LCDK 電壓是否滿足要求。

確認電壓正常後,關機,上屏,結合 開機 Log 看屏部分是否正常初始化。

5.2 背光是否正常

背光沒亮的話確認一下接上屏的時候,量一量 VDD_LCDA 的電壓為多少(串聯電路大概能到 20V+)
沒有就去檢查背光電路供電電壓和 backlight 相關的配置(比如背光功能使能的 GPIO 有沒有控制到、PWM通道是否配置正確)。

5.3 framebuffer 是否有資料產生

3368/3399 的命令為

echo bmp > sys/class/graphics/fb0/dump_buf 
或者
echo bin > sys/class/graphics/fb0/dump_buf

312x 的命令為

cat /dev/graphics/fb0 > /data/fb0.yuv

將生成的檔案 adb pull 出來後可以通過圖片檢視軟體,譬如 7YUV 讀取輸出的 bmp 檔案或者 bin 檔案。
如果有軟體能正常顯示畫面,說明是 mipi 的問題。
如果軟體不能正常顯示畫面,說明 fb 刷下來的資料有問題

5.4 列印 Mipi LCD 相關 Log 資訊

開啟 Mipi DBG 的介面

driver/video/rockchip/transmitter/rk32_mipi_dsi.c 中的:
    #define MIPI_DBG(x...) printk(KERN_INFO x)

driver/video/rockchip/screen/lcd_mipi.c 中的:
    #define MIPI_SCREEN_DBG(x...) printk(KERN_ERR x)

看看 log 中是否有異常。

譬如
probe 函式是否正常;
是否有呼叫到 rk32_dsi_enable() 函式,該函式為 lcdc 呼叫 mipi 的入口函式;
初始化 mipi 的過程中是否有報錯等等

電源控制部分對應的操作函式:driver/video/rockchip/screen/lcd_mipi.c 的
rk_mipi_screen_pwr_enable(),rk_mipi_screen_pwr_disable()。

Clock 部分在 drivers/video/rockchip/transmitter/rk32_mipi_dsi.c 可以新增如下列印

 256 static int rk312x_mipi_dsi_phy_set_gotp(struct dsi *dsi, u32 offset, int n)
 257 {
 258     u32 val = 0, temp = 0, Tlpx = 0;
 259     u32 ddr_clk = dsi->phy.ddr_clk;
 260     u32 Ttxbyte_clk = dsi->phy.Ttxbyte_clk;
 261     u32 Tsys_clk = dsi->phy.Tsys_clk;
 262     u32 Ttxclkesc = dsi->phy.Ttxclkesc;
 263     printk("%s : ddr_clk %d\n", __func__, ddr_clk);

1123 static int rk32_mipi_dsi_enable_hs_clk(void *arg, u32 enable)
1124 {
1125     struct dsi *dsi = arg;
1126     printk("rk32_mipi_dsi_enable_hs_clk,enable=%d\n",enable);
1127     rk32_dsi_set_bits(dsi, enable, phy_txrequestclkhs);
1128     return 0;
1129 }

dts 中也有一些 Debug 的開關可以開啟以協助分析問題。RK 手冊中會有更加詳細的描述,這裡不贅述了。

5.5 上電時序是否正常

根據前面我們從 datasheet 中扣出來的上電時序圖

確認上電時序是否正常,VCC、RST、MIPI 順序是否正常。
1. VCC 使能有沒有起作用。
2. RST 是否有一個 低-高 的變化,沒有則是 rst 設定的觸發方式可能反了
3. 在 RST 變高後會開始傳輸資料,量 lanes 是否有資料輸出。抓取資料需要一定規格的示波器和差分探頭,我們用普通的示波器大致看看有沒有資料輸出就夠了。

如果到這篇文章中的所有辦法都用完了還沒有點亮,只能來這裡重新測 data 和 clk 波形是否正常。
如果也正常,那就需要確認 mipi phy 是否把初始化命令正確傳送出來。用差分探頭在單端模式下抓 mipi phy 的 lane0N 和 lane0P。
命令也是正常的,屏依舊還沒有點亮,只能進一步分析 mipi 協議了。

5.6 clock 是否正常

用示波器量波形看 DCLK 的頻率為多少,是否為 dsi_hs_clk 中設定的(可能實際的會略低一點)。
實際的 DCLK 是否滿足屏的要求。

5.7 可以顯示了但是 花屏/閃屏/抖動 等

見後面的問題集錦

5.8 進一步分析 Mipi 協議

屏參、上電時序、clock 啥都確定是對的了。竟然還是無法點亮螢幕。
最後只能分析協議。
這是網友 @nice 碰到的問題。
最後發現是 LP00 的時間不對,RK 平臺預設是 85ms,但是屏要求是 15ms。修改後正常。
參考文章:http://blog.csdn.net/g_salamander/article/details/9163455
我就不重複造輪子了。上面這篇文章寫的非常好。等什麼時候我有更深的感悟了也寫一篇包含自己體會的 Mipi 協議分析部落格好了。

六、問題集錦

RK 的官方文件中描述了不少問題,我這邊就不再贅述了。
以下是我碰到的一些問題的解決辦法,還有一些從網上搜到的發揮了作用的解決辦法,一併都附在這裡了。

6.1 RST 復位不正常

我們 RST 是低電平有效,所以我想當然的將 RST 設定為
ACTIVE_LOW。

我在除錯的時候發現 lane 一直為低電平,沒有資料傳輸,然後採取量 RST 發現喚醒屏後待到螢幕快滅了 RST 才會被拉高。跟程式碼發現 RK 平臺的實現是

!你設定的觸發電平
你設定的觸發電平

我設定的觸發電平是 低電平有效 ACTIVE_LOW

!ACTIVE_LOW
ACTIVE_LOW

即先高再低。
所以是錯的,改為 ACTIVE_HIGH 後正常。

但是雖然填的是 ACTIVE_HIGH ,但是根據驅動應該還是屬於低電平有效的,這裡是 RK 平臺 driver 的實現有問題。
修改後 lane 有資料傳遞了。

6.2 有資料傳輸,但是 cmds 有問題

cmds 有的引數超過了 32個位元組(有個有36個位元組,有個有39個位元組),完成 dtsi 中 cmds 編寫後
燒錄,板子跑飛,空指標異常。
發現傳遞 這個超長 引數的時候有記憶體溢位情況。
於是跟程式碼發現 dcs_cmd.cmds 的資料型別為 int cmds[32],所以擅自想當然的將包拆成了 39 = 28+11,還將其中的延時設定為 0 。
這樣當然是不行的。但是一切都是基於這個拆了包的 cmds 來調,走了不少彎路。

於是去聯絡原廠的工程師,說平臺引數大小有限制,諮詢拆包是否可行。
他們說可以直接修改 cmds 陣列大小,將 cmds[32] 改成了 cmds[400] 。

這個問題在 RK 後來的 kernel 中被更新了。

所以有時候碰到問題需要確認一下 kernel 是不是最新的,也許會有意想不到的效果。

6.3 開機 Logo 閃爍,且水平方向向右偏移壓縮了半個螢幕

在點亮屏後剛開始有開機 logo 閃爍,向右偏移了近半個螢幕的長度。
重新確認 clock-frequence 後發現少打了一個 0 。
修改後解決了 閃爍,大偏移 的問題。

6.4 偏移巨大

如下面這張圖,偏移的特別多,可能是 dclk 有問題,修改 dsi_hs_clk 由 504 降到 496 解決。

enter description here

比如下面這張圖,也是偏移的很多,將 dclk 增加解決。

6.5 偏移一點點

如下圖,一般修改 HBP、HFP、VBP、VFP 即可。

enter description here

6.6 水平方向似乎被裁剪(偏移)

如下圖,實際是 HBP 的問題。
增大 HBP 後解決,將 HBP 由 10 增加到 30。

enter description here

6.7 正常開機可以點亮,休眠喚醒無法點亮。

dclk 有問題。
用示波器去測究竟 dclk 出來的是多少。
比如我設定的 470 開機啟動可以點亮,休眠喚醒無法點亮。
用示波器一測,竟然才 200 Mbps,修改到 584 後(實際出來為 450) 休眠喚醒才也可以點亮。

6.8 白屏(偶爾)

白屏有可能是靜電問題,把 LCD 拿到頭髮上擦幾下,如果很容易出現白屏那肯定就是靜電問題了。
另外一個在有Backend IC的情況下,也有可能bypass沒處理好。

6.9 白屏(開機 Logo 到 Android 動畫之間)

結束開機logo至Android動畫出現之間出現閃屏或者閃白光的情況。
原因:在這個時間點kernel會會對屏再次初始化,我們可以軟體上遮蔽第一次初始化動作從而解決。

6.10 白屏(進入睡眠 suspend / 開始顯示 resume 時)

喚醒螢幕閃白光問題,說白了是背光早亮了,很有可能是下序列mdelay太久,改小點就沒有這個問題了。根本原因螢幕初始化序列下慢了。
sleep out(0x11)和 display on(0x29)之間需要 mdelay(120ms)左右。

6.11 花屏

LCD 初始化成功,但是 RGB 沒有刷過來。
優先確認 timing 中的 pclk,另外還有可能是匯流排速度有問題。

開機花屏最簡單的解決方式是,在 Init 結束的地方加一個刷黑屏的功能。也可以在睡眠函式里加延時函式。

6.12 閃爍(快速,大量)

  1. pclk 有問題
    在最開始的時候,我的 pclk 漏了一個 0 ,為之前的 1/10 此時就有影象閃爍問題。
  2. proch 有問題
    在除錯完後,我嘗試將 proch 增加到極限,發現會出現影象閃爍的問題。

6.13 閃爍(偶爾)

通過調節電壓來穩定,一般調節的電壓為VRL、VRH、VDV和VCM

6.14 閃爍(喚醒 resume 時)

RST 後下載初始化時序時間過長,適當減少 delay 時間可以解決。

6.15 抖動

測時序,延時不足

6.16 灰屏(喚醒時)

暫存器沒有使能外部升壓電路

6.17 水波紋

通常都是rgb interface polarity導致,需要調整pclk hsync vsync de極性使之符合平臺極性

6.18 調節對比度

VRL、VRH、VDV和VCM,這些電壓也可以用來調節亮暗(對比度)
也可以通過調節Gamma值來實現,要調節的物件為 PRP、PRN、VRP、VRN 等

6.19 影象顏色不正常

可能時鐘型號極性反了
可能 VCOM 調節不正常
進行 GAMMA 校正

6.20 明暗色過渡部分,出現不停閃動的亮點

pixel clock 極性,由上升沿取樣改為下降沿取樣即可。

最後,我上面說的都是廢話。
最好的資料就是 RK 官方的TRM 、屏的 Spec 和 Mipi DSI 協議規格書。
LCD 這邊的變數太多了,一萬個工程師可以碰到一萬種屏不顯示的情況。
網上搜再多資料也沒有抓波、抓上電時序,對照官方手冊確認 來的實在。