Tina Linux LCD調(diào)試指南
1 概述
編寫目的 本文檔將介紹sunxi 平臺Display Engine 模塊中LCD 的調(diào)試方法。
LCD 調(diào)試方法,調(diào)試手段。
LCD 驅(qū)動編寫。
lcd0 節(jié)點下各個屬性的解釋。
典型LCD 接口配置。
適用范圍:sunxi 平臺DE1.0/DE2.0 中LCD 屏幕參數(shù)設置。
2 相關術(shù)語介紹
?
表2-1: LCD 相關術(shù)語
?
術(shù)語 | 解釋說明 |
---|---|
SUNXI | Allwinner 一系列SoC 硬件平臺 |
LCD | Liquid Crystal Display, 液晶顯示器 |
MIPI | Mobile Industry Processor Interface |
DSI | Display Serial Interface,顯示串行接口 |
I8080 | Intel 8080LCD 接口 |
RGB | 這里指一種LCD 接口,該接口發(fā)送不經(jīng)過任何編碼的RGB 分量 |
LVDS | Low-Voltage Differential Signaling 一種LCD 接口,低壓和差分傳輸是其特點 |
3 IC 規(guī)格
LCD 接口相關規(guī)格:
支持雙顯,異顯。也就是顯示內(nèi)容可以不一樣,顯示分辨率可以不一樣,屏接口也可以不一樣。
支持MIPI-DSI 接口, 數(shù)量一個。最大支持1920x1200@60 分辨率,滿足寬高不要超過2048,像素時鐘不超過180MHz 都支持。
支持RGB 接口,數(shù)量2 個。其中主顯支持并行RGB666,副顯并行支持RGB888, 并行RGB 接口最大支持1920x1200@60 分辨率,滿足寬高不要超過2048,像
素時鐘不超過180MHz 都支持?;蛘邇蓚€串行RGB 接口,串行RGB 的最高分辨率最大不超過800*480@60
支持兩個dual-link LVDS 接口, 最大支持1920x1200@60 分辨率,滿足寬高不要超過2048,像素時鐘不超過180MHz 都支持?;蛘? 個single-link LVDS 接
口,分辨率最高支持1366*768@60。
兩個I8080 接口。分辨率最高支持800*480@60。
LVDS 接口支持信號同顯。每兩個single link LVDS 接口必須連接到完全一樣的LVDS 接口的屏上,將完全一樣的數(shù)據(jù)發(fā)送到這兩個屏上,做到信號一樣。所以
理論上,T509 能做到4顯,其中前2 個和后2 個分辨率可以不一樣,2 個之間的分辨率必須一樣,且必須連接一樣的LCD 屏。
說明
在多顯的場景下,以上接口可以自由搭配,除了MIPI-DSI 必須用在主顯上。
技巧
一個dual link LVDS 接口共20 條線,它可以拆分成兩個single link 的LVDS 接口,假設為lvds0 和lvds1,選擇一個single link 的時候做顯示的時候,必須選擇lvds0。
4 模塊介紹
4.1 添加屏驅(qū)動步驟
對于linux4.9 及以下版本總共需要修改三處地方(即下列前三項),對于linux5.4 則需要修改四處地方,具體可參考屏驅(qū)動源碼位置。
? linux 源碼倉庫。
? uboot 源碼倉庫。在uboot 中也有顯示和屏驅(qū)動,目的是顯示logo。
? 板級dts 配置倉庫。目的是通過board.dts 來配置一些通用的LCD 配置參數(shù)。對于linux4.9,該配置同時對內(nèi)核及uboot 生效,對于linux-5.4,請參照下條。
? 對于linux5.4,還需額外配置uboot 專用板級dts 配置倉庫。
確保全志顯示框架的內(nèi)核配置有使能,查看menuconfig 配置說明。
前期準備以下資料和信息:
? 屏手冊。主要是描述屏基本信息和電氣特性等,向屏廠索要。
? Driver IC 手冊。主要是描述屏IC 的詳細信息。這里主要是對各個命令進行詳解,對我們進行初始化定制有用,向屏廠索要。
? 屏時序信息。請向屏廠索要。請看屏時序參數(shù)說明以了解更多信息。
? 屏初始化代碼。,請向屏廠索要。一般情況下DSI 和I8080 屏等都需要初始化命令對屏進行初始化。
? 萬用表。調(diào)屏避免不了測量相關電壓。
動手添加屏驅(qū)動之前,先了解屏驅(qū)動,請看屏驅(qū)動分解。
通過第3 步的資料,定位該屏的類型,然后選擇一個已有同樣類型的屏驅(qū)動作為模板進行屏驅(qū)動添加或者直接在上面修改。
修改屏驅(qū)動目錄下的panel.c和panel.h。在全局結(jié)構(gòu)體變量panel_array中新增剛才添加strcut_lcd_panel的變量指針。panel.h中新增strcut lcd_panel的聲
明。
修改Makefile。在lcd 屏驅(qū)動目錄的上一級的Makefile 文件中的disp-objs中新增剛才添加屏驅(qū)動.o。
修改board.dts 中的lcd0??梢钥碦GB 接口,MIPI-DSI 接口,I8080 接口和LVDS 接口,里面有介紹各種接口典型配置。硬件參數(shù)說明,這一章有所有l(wèi)cd0 節(jié)
點下可配置屬性詳細解釋。
編譯uboot,kernel,打包燒寫。注意不同SDK,編譯方式有所不同,部分SDK 默認不編譯uboot。
調(diào)試。通過調(diào)試方法我們可以初步定位問題,還有FAQ,對調(diào)屏也有幫助。
4.2 屏驅(qū)動說明
4.2.1 屏驅(qū)動源碼位置
linux 3.4 版本內(nèi)核:
linux3-4/drivers/video/sunxi/disp2/disp/lcd/
linux 3.10 版本內(nèi)核:
linux3-10/drivers/video/sunxi/disp2/disp/lcd/
linux 4.9 版本及其以上內(nèi)核:
linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/
uboot-2014:
brandy/u-boot-2014.07/drivers/video/sunxi/disp2/disp/lcd
uboot-2018:
brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/disp2/disp/lcd
板級配置,其中“芯片型號” 比如R818,和“板子名稱” 比如demo,請根據(jù)實際替換。
device/config/chips/芯片型號/configs/板子名稱/board.dts
針對linux5.4 時使用的uboot 板級配置:
device/config/chips/芯片型號/configs/板子名稱/uboot-board.dts
針對linux5.4 時使用的kernel 板級配置:
device/config/chips/芯片型號/configs/板子名稱/linux-5.4/board.dts
4.2.2 menuconfig 配置說明
LCD 相關代碼包含在disp 驅(qū)動模塊中,進入內(nèi)核根目錄,執(zhí)行make ARCH=arm menuconfig或者make ARCH=arm64 menuconfig(64bit 平臺) 進入配置主界
面。并按以下步驟操作:
DE1.0 對應平臺:R6(linux-3.10)、R16(linux-3.4)。
DE2.0 對應平臺:除R6 和R16 之外的。
?
圖4-1: DE1.0 menuconfig 配置圖
?
?
圖4-2: DE2.0 menuconfig 配置圖
?
以R40 為例,具體配置目錄為:Device Drivers->Graphics support->Support for frame buffer devices->Video Support for sunxi -> DISP Driver Support(sunxi-disp2)。
4.2.3 屏驅(qū)動分解
在屏驅(qū)動源碼位置中,主要分為四類文件
panel.c和panel.h,當用戶添加新屏驅(qū)動時,是需要修改這兩個文件的,需要將屏結(jié)構(gòu)體變量添加到全局結(jié)構(gòu)體變量panel_array中。
lcd_source.c和lcd_source.h,這兩個文件實現(xiàn)的是給屏驅(qū)動使用的函數(shù)接口,比如電源開關,gpio,dsi 讀寫接口等,用戶不需要修改只需要用。
屏驅(qū)動。除了上面提到的源文件外,其它的一般一個c 文件和一個h 文件就代表一個屏驅(qū)動。
在屏驅(qū)動源碼位置的上一級,有用戶需要修改的Makefile 文件。
我們可以打開drivers/video/fbdev/sunxi/disp2/disp/lcd/default_panel.c作為屏驅(qū)動的例子,在該文件的最后
struct __lcd_panel default_panel = {
/* panel driver name, must mach the lcd_drv_name in board.dts */
.name = "default_lcd",
.func = {
.cfg_panel_info = LCD_cfg_panel_info,
.cfg_open_flow = LCD_open_flow,
.cfg_close_flow = LCD_close_flow,
}
,
};
該全局變量default_panel的成員name與lcd_driver_name必須一致,這個關系到驅(qū)動能否找到指定的文件。
接下來是func成員的初始化,這里最主要實現(xiàn)三個回調(diào)函數(shù)。LCD_cfg_panel_info,LCD_open_flow和LCD_close_flow。
開關屏流程即屏上下電流程,屏手冊或者driver IC 手冊中里面的Power on Sequence 和Power off Sequence。
開關屏的操作流程如下圖所示。
其中,LCD_open_flow 和LCD_close_flow 稱為開關屏流程函數(shù), 方框中的函數(shù), 如LCD_power_on,稱為開關屏步驟函數(shù)。
不需要進行初始化操作的LCD 屏,比如lvds 屏,RGB 屏等,LCD_panel_init 及LCD_panel_exit這函數(shù)可以為空。
?
圖4-3: LCD 開關屏流程
?
函數(shù):LCD_open_flow
功能:LCD_open_flow 函數(shù)只會系統(tǒng)初始化的時候調(diào)用一次,執(zhí)行每個LCD_OPEN_FUNC即是把對應的開屏步驟函數(shù)進行注冊,先注冊先執(zhí)行,但并沒有立刻執(zhí)
行該開屏步驟函數(shù)。
原型:
static s32 LCD_open_flow(u32 sel)
函數(shù)常用內(nèi)容為:
static __s32 LCD_open_flow(__u32 sel)
{
LCD_OPEN_FUNC(sel, LCD_power_on,10);
LCD_OPEN_FUNC(sel, LCD_panel_init, 50);
LCD_OPEN_FUNC(sel, sunxi_lcd_tcon_enable, 100);
LCD_OPEN_FUNC(sel, LCD_bl_open, 0);
return 0;
}
如上,調(diào)用四次LCD_OPEN_FUNC 注冊了四個回調(diào)函數(shù),對應了四個開屏流程, 先注冊先執(zhí)行。實際上注冊多少個函數(shù)是用戶自己的自由,只要合理即可。
LCD_power_on 即打開LCD 電源,再延遲10ms;這個步驟一般用于打開LCD 相關電源和相關管腳比如復位腳。這里一般是使用電源控制函數(shù)說明和管腳控制
函數(shù)說明進行操作。
LCD_panel_init 即初始化屏,再延遲50ms;不需要初始化的屏,可省掉此步驟,這個函數(shù)一般用于發(fā)送初始化命令給屏進行屏初始化。如果是DSI 屏看DSI 相
關函數(shù)說明,如果是I8080 屏用I8080 接口函數(shù)說明,如果是其它情況比如i2c 或者spi 可以看使用iic/spi 串行接口初始化,也可以用GPIO 來進行模擬。
sunxi_lcd_tcon_enable 打開TCON,再延遲100ms;這一步是固定的,表示開始發(fā)送圖像信號。
LCD_bl_open 打開背光,再延遲0ms。前面三步搞定之后才開背光,這樣不會看到閃爍。這里一般使用的函數(shù)請看背光控制函數(shù)說明。
如下圖,這是屏手冊中典型的上電時序圖,我們編寫屏驅(qū)動的時候,也要注意,該延時就得延時。
?
圖4-4: power on
?
函數(shù):LCD_OPEN_FUNC
功能:注冊開屏步驟函數(shù)到開屏流程中,記住這里是注冊不是執(zhí)行!
原型:
void LCD_OPEN_FUNC(__u32 sel, LCD_FUNC func, __u32 delay)
參數(shù)說明:
func 是一個函數(shù)指針,其類型是:void (*LCD_FUNC) (__u32 sel),用戶自己定義的函數(shù)必須也要用統(tǒng)一的形式。比如:
void user_defined_func(__u32 sel)
{
//do something
}
delay 是執(zhí)行該步驟后,再延遲的時間,時間單位是毫秒。
LCD_OPEN_FUNC 的第二個參數(shù)是前后兩個步驟的延時長度,單位ms,注意這里的數(shù)值請按照屏手冊規(guī)定去填,亂填可能導致屏初始化異常或者開關屏時間過
長,影響用戶體驗。
與LCD_open_flow 對應的是LCD_close_flow 是,用于注冊關屏函數(shù),使用LCD_CLOSE_FUNC進行函數(shù)注冊,先注冊先執(zhí)行,這里只是注冊回調(diào)函數(shù)不是立刻執(zhí)
行。
static s32 LCD_close_flow(u32 sel)
{
/* close lcd backlight, and delay 0ms */
LCD_CLOSE_FUNC(sel, LCD_bl_close, 0);
/* close lcd controller, and delay 0ms */
LCD_CLOSE_FUNC(sel, sunxi_lcd_tcon_disable, 50);
/* open lcd power, than delay 200ms */
LCD_CLOSE_FUNC(sel, LCD_panel_exit, 100);
/* close lcd power, and delay 500ms */
LCD_CLOSE_FUNC(sel, LCD_power_off, 0);
return 0;
}
先關閉背光,這樣整個關屏過程,用戶不會看到閃爍的過程。
關閉TCON,也就是停止發(fā)送數(shù)據(jù),這是必要的。再延遲50ms。
執(zhí)行關屏代碼,再延遲200ms(不需要初始化的屏,可省掉此步驟)。
最后關閉電源,再延遲0ms。
如下圖是典型關屏時序圖。
?
圖4-5: power off
?
函數(shù):LCD_cfg_panel_info
功能:配置的TCON 擴展參數(shù),比如gamma 功能和顏色映射功能。
原型:
static void LCD_cfg_panel_info(__panel_extend_para_t * info)
TCON 的擴展參數(shù)只能在屏文件中配置,參數(shù)的定義見顯示效果相關參數(shù)。
需要gamma 校正,或色彩映射,在board.dts 中將相應模塊的enable 參數(shù)置1,lcd_gamma_en,lcd_cmap_en,并且填充3 個系數(shù)表,lcd_gamma_tbl,
lcd_cmap_tbl,如下所示代碼部分。注意的是:gamma,模板提供了18 段拐點值,然后再插值出所有的值(255 個)。如果覺得還不細,可以往相應表格里添加
子項。cmap_tbl 的大小是固定了,不能減小或增加表的大小。
最終生成的gamma 表項是由rgb 三個gamma 值組成的,各占8bit,目前提供的模板中,三個gamma 值是相同的。
static void LCD_cfg_panel_info(struct panel_extend_para *info)
{
u32 i = 0, j = 0;
u32 items;
u8 lcd_gamma_tbl[][2] = {
/* {input value, corrected value} */
{0, 0},
{15, 15},
{30, 30},
{45, 45},
{60, 60},
{75, 75},
{90, 90},
{105, 105},
{120, 120},
{135, 135},
{150, 150},
{165, 165},
{180, 180},
{195, 195},
{210, 210},
{225, 225},
{240, 240},
{255, 255},
};
u32 lcd_cmap_tbl[2][3][4] = {
{
{LCD_CMAP_G0, LCD_CMAP_B1, LCD_CMAP_G2, LCD_CMAP_B3},
{LCD_CMAP_B0, LCD_CMAP_R1, LCD_CMAP_B2, LCD_CMAP_R3},
{LCD_CMAP_R0, LCD_CMAP_G1, LCD_CMAP_R2, LCD_CMAP_G3},
},
{
{LCD_CMAP_B3, LCD_CMAP_G2, LCD_CMAP_B1, LCD_CMAP_G0},
{LCD_CMAP_R3, LCD_CMAP_B2, LCD_CMAP_R1, LCD_CMAP_B0},
{LCD_CMAP_G3, LCD_CMAP_R2, LCD_CMAP_G1, LCD_CMAP_R0},
},
};
items = sizeof(lcd_gamma_tbl) / 2;
for (i = 0; i < items - 1; i++) {
u32 num = lcd_gamma_tbl[i + 1][0] - lcd_gamma_tbl[i][0];
for (j = 0; j < num; j++) {
u32 value = 0;
value =
lcd_gamma_tbl[i][1] +
((lcd_gamma_tbl[i + 1][1] -
lcd_gamma_tbl[i][1]) * j) / num;
info->lcd_gamma_tbl[lcd_gamma_tbl[i][0] + j] =
(value << 16) + (value << 8) + value;
}
}
info->lcd_gamma_tbl[255] =
(lcd_gamma_tbl[items - 1][1] << 16) +
(lcd_gamma_tbl[items - 1][1] << 8) + lcd_gamma_tbl[items - 1][1];
memcpy(info->lcd_cmap_tbl, lcd_cmap_tbl, sizeof(lcd_cmap_tbl));
}
4.2.4 延時函數(shù)說明
函數(shù):sunxi_lcd_delay_ms / sunxi_lcd_delay_us
功能:延時函數(shù),分別是毫秒級別/微秒級別的延時。
原型:s32 sunxi_lcd_delay_ms(u32 ms) / s32 sunxi_lcd_delay_us(u32 us)
4.2.5 圖像數(shù)據(jù)使能函數(shù)說明
函數(shù):sunxi_lcd_tcon_enable / sunxi_lcd_tcon_disable
功能:打開LCD 控制器,開始刷新LCD 顯示。關閉LCD 控制器,停止刷新數(shù)據(jù)。
原型:void sunxi_lcd_tcon_enable(u32 screen_id)
void sunxi_lcd_tcon_disable(u32 screen_id)
4.2.6 背光控制函數(shù)說明
函數(shù):sunxi_lcd_backlight_enable / sunxi_lcd_backlight_disable
功能:打開/關閉背光,操作的是board.dts 中l(wèi)cd_bl 配置的gpio。見lcd_bl_en。
原型:void sunxi_lcd_backlight_enable(u32 screen_id)
void sunxi_lcd_backlight_disable(u32 screen_id)
函數(shù):sunxi_lcd_pwm_enable / sunxi_lcd_pwm_disable
功能:打開/關閉pwm 控制器,打開時pwm 將往外輸出pwm 波形。對應的是lcd_pwm_ch所對應的那一路pwm。
原型:s32 sunxi_lcd_pwm_enable(u32 screen_id)
s32 sunxi_lcd_pwm_disable(u32 screen_id)
4.2.7 電源控制函數(shù)說明
函數(shù):sunxi_lcd_power_enable / sunxi_lcd_power_disable
功能:打開/關閉Lcd 電源,操作的是board.dts 中的lcd_power/lcd_power1/lcd_power2(pwr_id 標識電源索引)。
原型:void sunxi_lcd_power_enable(u32 screen_id, u32 pwr_id)
void sunxi_lcd_power_disable(u32 screen_id, u32 pwr_id)
pwr_id = 0:對應于board.dts 中的lcd_power。
pwr_id = 1:對應于board.dts 中的lcd_power1。
pwr_id = 2:對應于board.dts 中的lcd_power2。
pwr_id = 3:對應于board.dts 中的lcd_power3。
函數(shù):sunxi_lcd_pin_cfg
功能:配置lcd 的io。
原型:s32 sunxi_lcd_pin_cfg(u32 screen_id, u32 bon)
說明:配置lcd 的data/clk 等pin,對應board.dts 中的lcdd0-lcdd23/lcddclk/lcdde/lcdhsync/lcdvsync。
由于dsi 是專用pin, 所以dsi 接口屏不需要在board.dts 中配置這組pin,但同樣會在此函數(shù)接口中打開與關閉對應的pin。
Bon: 1: 為開,0:為配置成disable 狀態(tài)。
4.2.8 DSI 相關函數(shù)說明
MIPI DSI 屏,大部分需要初始化,使用的是DSI-D0 通道的LP 模式進行初始化。提供的接口函數(shù)說明如下:
函數(shù):sunxi_lcd_dsi_clk_enable / sunxi_lcd_dsi_clk_disble
功能:僅限dsi 接口屏使用,使能/關閉dsi 輸出的高速時鐘clk 信號,必須在初始化的時候調(diào)用。
原型:s32 sunxi_lcd_dsi_clk_enable(u32 scree_id)
s32 sunxi_lcd_dsi_clk_disable(u32 scree_id)
函數(shù):sunxi_lcd_dsi_dcs_wr
功能:對屏的dcs 寫操作。
原型:s32 sunxi_lcd_dsi_dcs_wr(u32 sel,u8 cmd,u8* para_p,__u32 para_num)
參數(shù)說明:
? cmd:dcs 寫命令內(nèi)容。
? para_p:dcs 寫命令的參數(shù)起始地址。
? para_num:dcs 寫命令的參數(shù)個數(shù),單位為byte。
函數(shù):sunxi_lcd_dsi_dcs_wr_2para
功能:對屏的dcs 寫操作,該命令帶有兩個參數(shù)。
原型:s32 sunxi_lcd_dsi_dcs_wr_2para(u32 sel,u8 cmd,u8 para1,__u8 para2)
參數(shù)說明:
? cmd:dcs 寫命令內(nèi)容。
? para1:dcs 寫命令的第一個參數(shù)內(nèi)容。
? para2:dcs 寫命令的第二個參數(shù)內(nèi)容。
sunxi_dsi_dcs_wr_0para,sunxi_dsi_dcs_wr_1para,sunxi_dsi_dcs_wr_3para,sunxi_dsi_dcs_wr_4para,
sunxi_dsi_dcs_wr_5para定義與dsi_dcs_wr_2para類似,差別就是參數(shù)數(shù)量。
函數(shù):sunxi_lcd_dsi_dcs_read
功能:dsi 讀操作。
原型:s32 sunxi_lcd_dsi_dcs_read(u32 sel, u8 cmd, u8 result, u32 num_p)
參數(shù)說明:
? sel, 顯示id。
? cmd, 要讀取的寄存器。
? result,用于存放讀取接口的數(shù)組,用戶必須自行保證其有足夠空間保存讀取的接口。
? num_p,指針用于存放讀取字節(jié)數(shù),用戶必須保證其非空指針。
4.2.9 I8080 接口函數(shù)說明
顯示驅(qū)動提供5 個接口函數(shù)可供使用。如下:
函數(shù):sunxi_lcd_cpu_write
功能:設定CPU 屏的指定寄存器為指定的值。
原型:void sunxi_lcd_cpu_write(u32 sel, u32 index, __u32 data)
函數(shù)內(nèi)容為:
Void sunxi_lcd_cpu_write(__u32 sel, __u32 index, __u32 data) { sunxi_lcd_cpu_write_index(sel, index); sunxi_lcd_cpu_wirte_data(sel, data); }
實現(xiàn)了8080 總線上的兩個寫操作。
sunxi_lcd_cpu_write_index 實現(xiàn)第一個寫操作,這時PIN 腳RS(A1)為低電平,總線數(shù)據(jù)上的數(shù)據(jù)內(nèi)容為參數(shù)index 的值。
Sunxi_lcd_cpu_wirte_data 實現(xiàn)第二個寫操作,這時PIN 腳RS(A1)為高電平,總線數(shù)據(jù)上的數(shù)據(jù)內(nèi)容為參數(shù)data 的值。
函數(shù):sunxi_lcd_cpu_write_index
功能:設定CPU 屏為指定寄存器。
原型:
void sunxi_lcd_cpu_write_index(__u32 sel,__u32 index)
具體說明見sunxi_lcd_cpu_write。
函數(shù):sunxi_lcd_cpu_write_data
功能:設定CPU 屏寄存器的值為指定的值。
原型:
void Sunxi_lcd_cpu_write_data(__u32 sel, __u32 data);
函數(shù): tcon0_cpu_rd_24b_data
功能:讀操作。
原型:
s32 tcon0_cpu_rd_24b_data(u32 sel, u32 index, u32 *data, u32 size)
參數(shù)說明:
? sel:顯示id。
? index: 要讀取的寄存器。
? data:用于存放讀取接口的數(shù)組指針,用戶必須保證其有足夠空間存放數(shù)據(jù)。
? size:要讀取的字節(jié)數(shù)。
4.2.10 管腳控制函數(shù)說明
函數(shù):sunxi_lcd_gpio_set_value
功能:LCD_GPIO PIN 腳上輸出高電平或低電平。
原型:s32 sunxi_lcd_gpio_set_value(u32 screen_id, u32 io_index, u32 value)
參數(shù)說明:
? io_index = 0:對應于board.dts 中的lcd_gpio_0。
? io_index = 1:對應于board.dts 中的lcd_gpio_1。
? io_index = 2:對應于board.dts 中的lcd_gpio_2。
? io_index = 3:對應于board.dts 中的lcd_gpio_3。
? value = 0:對應IO 輸出低電平。
? Value = 1:對應IO 輸出高電平。
只用于該GPIO 定義為輸出的情形。
函數(shù):sunxi_lcd_gpio_set_direction
功能:設置LCD_GPIO PIN 腳為輸入或輸出模式。
原型:
s32 sunxi_lcd_gpio_set_direction(u32 screen_id, u32 io_index, u32 direction);
參數(shù)說明:
? io_index = 0:對應于board.dts 中的lcd_gpio_0。
? io_index = 1:對應于board.dts 中的lcd_gpio_1。
? io_index = 2:對應于board.dts 中的lcd_gpio_2。
? io_index = 3:對應于board.dts 中的lcd_gpio_3。
? direction = 0:對應IO 設置為輸入。
? direction = 1:對應IO 設置為輸出。
一部分屏需要進行初始化操作,在開屏步驟函數(shù)中,對應于LCD_panel_init 函數(shù),提供了幾種方式對屏的初始化。
對于DSI 屏,是通過DSI-D0 通道進行初始化。對于CPU 屏,是通過8080 總線的方式,使用的是LCDIO(PD,PH)進行初始化。這種初始化方式,其總線的引腳位
置定義與CPU 屏一致。
以下這些接口在屏驅(qū)動分解中提到路徑的lcd_source.c 和lcd_source.h 中定義和實現(xiàn)。
4.2.11 使用iic/spi 串行接口初始化
需要在屏驅(qū)動中注冊iic/spi 設備對串行接口的訪問。
使用硬件spi 對屏或者轉(zhuǎn)接IC 進行初始化,如下代碼片段。
首先調(diào)用spi_init 函數(shù)對spi 硬件進行初始化,spi_init 函數(shù)可以分為幾個步驟,第一獲取master;根據(jù)實際的硬件連接,選擇spi(代碼中選擇了spi1),如果這一
步返回錯誤說spi 沒有配置好,找spi 驅(qū)動負責人。第二步設置spi device,這里包括最大速度,spi 傳輸模式,以及每個字包含的比特數(shù)。最后調(diào)用spi_setup 完成
master 和device 的關聯(lián)。
comm_out 是一個spi 傳輸?shù)睦?,核心就是spi_sync_transfer 函數(shù)。
static int spi_init(void) { int ret = -1; struct spi_master *master; master = spi_busnum_to_master(1); if (!master) { lcd_fb_wrn("fail to get mastern"); goto OUT } spi_device = spi_alloc_device(master); if (!spi_device) { lcd_fb_wrn("fail to get spi devicen"); goto OUT; } spi_device->bits_per_word = 8; spi_device->max_speed_hz = 60000000; /*50MHz*/ spi_device->mode = SPI_MODE_0; ret = spi_setup(spi_device); if (ret) { lcd_fb_wrn("Faile to setup spin"); goto FREE; } lcd_fb_inf("Init spi1:bits_per_word:%d max_speed_hz:%d mode:%dn", spi_device->bits_per_word, spi_device->max_speed_hz, spi_device->mode); ret = 0; goto OUT; FREE: spi_master_put(master); kfree(spi_device); spi_device = NULL; OUT: return ret; } static int comm_out(unsigned int sel, unsigned char cmd) { struct spi_transfer t; if (!spi_device) return -1; DC(sel, 0); memset(&t, 0, sizeof(struct spi_transfer)); t.tx_buf = &cmd; t.len = 1; t.bits_per_word = 8; t.speed_hz = 24000000; return spi_sync_transfer(spi_device, &t, 1); }
使用硬件i2c 對LCD& 轉(zhuǎn)接IC 進行初始化,初始化i2c 硬件的核心函數(shù)是i2c_add_driver,而你要做的是初始化好其參數(shù)struct i2c_driver。
it66121_id 包含設備名字以及i2c 總線索引(i2c0,i2c1…)。
it66121_i2c_probe 能進到這個函數(shù),你就可以開始使用i2c 了。代碼段里面僅僅將后面需要的參數(shù)cilent 賦值給一個全局指針變量。
it66121_match,這是dts 的match table,由于你是給disp2 加驅(qū)動,所以這里的match table 就是disp2 的match table,這個table 關系到能否使用i2c,注意不
要填錯。 tv_i2c_detect 函數(shù),這里是非常關鍵的,這個函數(shù)早于probe 函數(shù)被調(diào)用,只有成功被調(diào)用后才能開始使用i2c,其中strlcpy 的調(diào)用意味著成功。
normal_i2c 是從設備地址列表,填寫的LCD 或者轉(zhuǎn)接IC 的從設備地址以及i2c 索引。
以probe 函數(shù)是否被調(diào)用來決定你是否可以開始使用I2C。
用i2c_smbus_write_byte_data 或者i2c_smbus_read_byte_data 來讀寫可以滿足大部分場景。
#define IT66121_SLAVE_ADDR 0x4c #define IT66121_I2C_ID 0 static const struct i2c_device_id it66121_id[] = { { "IT66121", IT66121_I2C_ID }, { /* END OF LIST */ } }; MODULE_DEVICE_TABLE(i2c, it66121_id); static int it66121_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { this_client = client; return 0; } static const struct of_device_id it66121_match[] = { {.compatible = "allwinner,sun8iw10p1-disp",}, {.compatible = "allwinner,sun50i-disp",}, {.compatible = "allwinner,sunxi-disp",}, {}, }; static int tv_i2c_detect(struct i2c_client *client, struct i2c_board_info *info) { const char *type_name = "IT66121"; if (IT66121_I2C_ID == client->adapter->nr) { strlcpy(info->type, type_name, 20); } else pr_warn("%s:%d wrong i2c id:%d, expect id is :%dn", __func__, __LINE__, client->adapter->nr, IT66121_I2C_ID); return 0; } static unsigned short normal_i2c[] = {IT66121_SLAVE_ADDR, I2C_CLIENT_END}; static struct i2c_driver it66121_i2c_driver = { .class = I2C_CLASS_HWMON, .id_table = it66121_id, .probe = it66121_i2c_probe, .remove = it66121_i2c_remove, .driver = { .owner = THIS_MODULE, .name = "IT66121", .of_match_table = it66121_match, }, .detect = tv_i2c_detect, .address_list = normal_i2c, }; static void LCD_panel_init(u32 sel) { int ret = -1; ret = i2c_add_driver(&it66121_i2c_driver); if (ret) { pr_warn("Add it66121_i2c_driver fail!n"); return; } //start init chip with i2c } void it6612_twi_write_byte(it6612_reg_set* reg) { u8 rdata = 0; u8 tmp = 0; rdata = i2c_smbus_read_byte_data(this_client, reg->offset); tmp = (rdata & (~reg->mask))|(reg->mask?->value); i2c_smbus_write_byte_data(this_client, reg->offset, tmp); }
4.2.12 U-boot 屏驅(qū)動注意事項
U-boot 編寫屏驅(qū)動的步驟和內(nèi)核是一樣的,代碼路徑文件組織方式都是一樣的,這里要講的是需要注意的事項。
1.為了加快U-boot 的顯示速度,開屏的幾個函數(shù)之間采取異步調(diào)用的方式,原理是利用timer中斷,定時調(diào)用開屏函數(shù),所以這種情況下bootGUI 框架加載完畢并
不意味著開屏完成,而是當你見到LCD open finish的打印的時候。
建議:為了盡量利用異步調(diào)用的優(yōu)點,請把需要的延時盡量在注冊回調(diào)的時候指定,比如下面延時10ms 就是利用timer 異步來進行回調(diào)的,這10ms 時間,uboot
就可以做其它事情,以達到異步調(diào)用的目的。
LCD_OPEN_FUNC(sel, LCD_power_on,10);
2.sunxi_lcd_power_enable 函數(shù)和sunxi_lcd_pin_cfg 不能在LCD_power_on之外調(diào)用,否則uboot 會異常。
嚴格講,只能在用LCD_OPEN_FUNC注冊的回調(diào)第一個函數(shù)里面調(diào)用。
4.3 RGB 接口
4.3.1 概述
下面介紹全志平臺的RGB 以及配置示例,至于lcd0 下面每個屬性的詳解細節(jié)請看硬件參數(shù)說明。
RGB 接口在全志平臺又稱HV 接口(Horizontal 同步和Vertical 同步)。
對于RGB 屏的初始化:
有些LCD 屏支持高級的功能比如gamma,像素格式的設置等,但是RGB 協(xié)議本身不支持圖像數(shù)據(jù)之外的傳輸,所以無法通過RGB 管腳進行對LCD 屏進行配置,
所以拿到一款RGB 接口屏,要么不需要初始化命令,要么這個屏會提供額外的管腳給SoC 來進行配置,比如SPI 和I2C等。
4.3.2 RGB 接口管腳
?
圖4-6: RGB 管腳
?
上面這些腳具體到SoC 哪根管腳以及第幾個功能(管腳復用功能)請參考pin mux 表格,管腳復用功能的名字一般以“LCDX_” 開頭,其中X 是數(shù)字。
其中數(shù)據(jù)腳的數(shù)量不一定是24 根。RGB 又細分幾種接口,通過設置lcd_hv_if來選擇。
?
表4-1: RGB 接口分類
?
位寬 | 時鐘周期 | 數(shù)顏色數(shù)量和格式 |
---|---|---|
24 bits | 1 cycle | 16.7M colors, RGB888 |
18 bits | 1 cycle | 262K colors, RGB666 |
16 bits | 1 cycle | 65K colors, RGB565 |
6 bits | 3 cycles | 262K colors, RGB666 |
6 bits | 3 cycles | 65K colors, RGB565 |
說明
時鐘周期數(shù)的意思:是一個像素需要用多少個時鐘周期發(fā)送完畢的意思。
當時鐘周期為1 時,我們稱這種RGB 接口為并行接口,其它的情況則是串行接口,更為普遍的原則就是只要需要多個時鐘周期才能發(fā)送完一個像素的接口都是串行
接口。
如何判斷是否支持24bit 的位寬,最簡單的方式就是在pinmux 表格中數(shù)一數(shù)數(shù)據(jù)腳的數(shù)量,如果有24 根則支持24bit,如果只有18 根則支持18bit。
硬件連接
對于并行RGB 的接口,當位寬小于24 時,硬件連接應該選擇連接每個分量中的高位而放棄低位,這樣做的原因是損失較少的顏色數(shù)量。
對于串行RGB 接口,硬件連接可參考RGB 和I8080 管腳配置示意圖中sync RGB 那幾列。
RGB 接口有兩種同步方式,根據(jù)經(jīng)驗來說盡量使用第二種方式,硬件上請保證連接好DE 腳。
Hsync+Vsync
DE(Data Enable)
4.3.3 并行RGB 接口配置示例
當我們配置并行RGB 接口時,在配置里面并不需要區(qū)分是24 位,18 位和16 位,最大位寬是哪種是參考pin mux 表格,如果LCD 屏本身支持的位寬比SoC 支持的
位寬少,當然只能選擇少的一方。
因為不需要初始化,RGB 接口極少出現(xiàn)問題,重點關注lcd 的timing 的合理性,也就是lcd_ht,lcd_hspw,lcd_hbp,lcd_vt,lcd_vspw和lcd_vbp這個屬性的合理
性。
下面是典型并行RGB 接口board.dts 配置示例,其中用空行把配置分成幾個部分
第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏驅(qū)動來初始化,這里是default_lcd,是針對不需要初始化設置的
RGB 屏
第二部分決定下面的配置是一個并行RGB 的配置。
第三部分決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。
第四部分決定了背光(pwm 和lcd_bl_en)。請看背光相關參數(shù)。
第五部分是顯示效果部分的配置,如果非24 位的RGB,那么一般情況下需要設置lcd_frm。
第六部分就是電源和管腳配置。是用RGB666 還是RGB888,需要根據(jù)實際pinmux 表來決定,如果該芯片只有18 根rgb 數(shù)據(jù)則只能rgb18。請看電源和管腳
參數(shù)。
&lcd0 { /* part 1 */ lcd_used = <1>; lcd_driver_name = "default_lcd"; /* part 2 */ lcd_if = <0>; lcd_hv_if = <0>; /* part 3 */ lcd_width = <150>; lcd_height = <94>; lcd_x = <800>; lcd_y = <480>; lcd_dclk_freq = <33>; lcd_hbp = <46>; lcd_ht = <1055>; lcd_hspw = <0>; lcd_vbp = <23>; lcd_vt = <525>; lcd_vspw = <0>; /* part 4 */ lcd_backlight = <50>; lcd_pwm_used = <1>; lcd_pwm_ch = <8>; lcd_pwm_freq = <10000>; lcd_pwm_pol = <1>; lcd_bl_en = <&pio PD 27 1 0 3 1>; lcd_bright_curve_en = <0>; /* part 5 */ lcd_frm = <0>; lcd_io_phase = <0x0000>; lcd_gamma_en = <0>; lcd_cmap_en = <0>; lcd_hv_clk_phase = <0>; lcd_hv_sync_polarity= <0>; /* part 6 */ lcd_power = "vcc-lcd"; lcd_pin_power = "vcc-pd"; pinctrl-0 = <&rgb24_pins_a>; pinctrl-1 = <&rgb24_pins_b>; };
4.3.4 串行RGB 接口的典型配置
串行RGB 是相對于并行RGB 來說,而并不是說它只用一根線來發(fā)數(shù)據(jù),只要通過多個時鐘周期才能把一個像素的數(shù)據(jù)發(fā)完,那么這樣的RGB 接口就是串行RGB。
同樣與并行RGB 接口一樣,配置中并不需要也無法體現(xiàn)具體是哪種串行RGB 接口,需要做的就是把硬件連接對。
下面是典型串行RGB 接口board.dts 配置示例,它只有8 根數(shù)據(jù)腳,其中用空行把配置分成幾個部分
第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏驅(qū)動來初始化。
第二分部決定下面的配置是一個串行RGB 的配置。
第三部分決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。
技巧 這里需要注意的是,對于該接口,SoC 總共需要三個周期才能發(fā)完一個pixel,所以我們配置時序的時候,需要滿足lcd_dclk_freq3=lcd_htlcd_vt60,或者
lcd_dclk_freq=lcd_ht3lcd_vt60要么3 倍lcd_ht要么3倍lcd_dclk_freq。
第四部分決定了背光。就是pwm 和lcd_bl_en。請看背光相關參數(shù)
第五部分是顯示效果方面的設置。
第六部分管腳和電源的定義。請看電源和管腳參數(shù)。
說明
下面實例的lcd driver IC 是stv7789v,是需要初始化,初始化的接口協(xié)議是SPI,所以這多了幾根spi 管腳配置,驅(qū)動里面用gpio 模擬spi 協(xié)議,所以這里都是配置
gpio 功能。
&lcd0 { /* part 1 */ lcd_used = <1>; lcd_driver_name = "st7789v"; /* part 2 */ lcd_if = <0>; lcd_hv_if = <8>; /* part 3 */ lcd_x = <240>; lcd_y = <320>; lcd_width = <108>; lcd_height = <64>; lcd_dclk_freq = <19>; lcd_hbp = <120>; ;10 + 20 + 10 + 240*3 = 760 real set 1000 lcd_ht = <850>; lcd_hspw = <2>; lcd_vbp = <13>; lcd_vt = <373>; lcd_vspw = <2>; /* part 4 */ lcd_backlight = <50>; lcd_pwm_used = <1>; lcd_pwm_ch = <8>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_bl_en = <&pio PB 1 1 0 3 1>; lcd_bright_curve_en = <1>; /* part 5 */ lcd_frm = <1>; lcd_hv_clk_phase = <0>; lcd_hv_sync_polarity= <0>; lcd_hv_srgb_seq = <0>; lcd_io_phase = <0x0000>; lcd_gamma_en = <0>; lcd_cmap_en = <0>; lcd_rb_swap = <0>; /* part 6 */ lcd_power = "vcc-lcd"; lcd_pin_power = "vcc-pd"; /*reset */ lcd_gpio_0 = <&pio PD 9 1 0 3 1>; /* cs */ lcd_gpio_1 = <&pio PD 10 1 0 3 0>; /*sda */ lcd_gpio_2 = <&pio PD 13 1 0 3 0>; /*sck */ lcd_gpio_3 = <&pio PD 12 1 0 3 0>; pinctrl-0 = <&rgb8_pins_a>; pinctrl-1 = <&rgb8_pins_b>; };
4.4 MIPI-DSI 接口
4.4.1 概述
MIPI-DSI,即Mobile Industry Processor Interface Display Serial Interface,移動通信行業(yè)處理器接口顯示串行接口。
對于用戶來說,需要了解:
Command mode,類似MPU 接口,需要IC 內(nèi)部有GRAM 來緩沖。
Video mode。類似RGB 接口,沒有GRAM,需要不停往panel 刷數(shù)據(jù)。其中video mode又分為三個子mode。
? Non-burst mode with sync pulses
? Non Burst mode with sync Events
? Burst mode。簡單理解就是有效數(shù)據(jù)比率更高,傳輸效率更高。
lane 的意思是指一對差分管腳。
4.4.2 MIPI-DSI 的管腳
MIPI-DSI 的管腳是在大部分IC 中是專用,在board.dtsi 里面不需要配置,只要硬件上連接好就行。
但是有一部分IC 的DSI 管腳不是專用的,與其它功能的腳復用,這個時候就需要配置好pinctrl-0和pinctrl-1。
mipi-dsi 的管腳是差分的,分為兩種管腳,一種是時鐘管腳,另外一種是數(shù)據(jù)管腳,數(shù)據(jù)管腳的數(shù)量是可變的,數(shù)量的單位是lane,每一條lane 實際包含兩條線。
一般來說LCD 屏說明書里面的說的lane 的數(shù)量是指數(shù)據(jù)管腳的數(shù)量不包括時鐘管腳。比如說某4 lane MIPI-DSI 屏就總共有(4+1)*2根腳。
4.4.3 MIPI-DSI 的電源
一般都有一路電源供給MIPI-DSI 這個模塊,你可以理解為管腳電,也可以理解成模塊電,不同IC 這路電的電壓要求可能不同,一旦確定IC 型號之后,這路電的電
壓就不變,如果擅自改變此路電的電壓可能導致模塊異常。
?
圖4-7: pinmux
?
4.4.4 判斷是否支持某款MIPI-DSI 屏
1.分辨率限制。有l(wèi)ane 的速度限制,我們可以得到最大分辨率的限制,計算公式如下,只要lane_speed 不超過上面IC 規(guī)格規(guī)定的速度,那么理論上是支持的,
請查看IC 規(guī)格。
lane_speed=lcd_vt * lcd_ht * fps * bit_per_pixel / lane_num / 1e9
? 單位:Gbps。
? fps: 期望刷新率,通過屏手冊可知道,一般是60。請看lcd_dclk_freq。
? bit_per_pixel: 每個像素包含的比特數(shù)量,一般是24 或者18,通過lcd_dsi_format來設置。
? lane_num:lane 數(shù)量,通過lcd_dsi_lane來設置。
? 1e9:1000000000 的科學計數(shù)寫法。
選擇分辨率的同時需要考慮系統(tǒng)帶寬,DE 能力,所以即使接口方面支持這個分辨率,對于整個系統(tǒng)來說不一定支持,比如說硬件為了節(jié)省成本選擇了一款速
度很慢的DDR 內(nèi)存然后同時又想選擇高分辨率的屏幕,很明顯這是不現(xiàn)實的。
lane 數(shù)量限制。絕大部分全志科技IC 最大支持4 lane 的MIPI-DSI,如果你看到該款屏超過4 lane 就肯定不支持了。少數(shù)IC 最大支持8 lane,應該選擇該款
IC。
MIPI-DSI 標準不兼容。請查看IC 規(guī)格。
4.4.5 計算MIPI-DSI 時鐘lane 頻率
使用示波器測量MIPI-DSI 的時鐘信號,確定其頻率是否滿足屏的需求。
首先,我們由給定的像素時鐘和lane 數(shù)量,可以計算出理論CLK 信號的頻率,如下公式:
Freq_dsi_clk = (Dclk * colordepth * 3 / lane ) / 2
Freq_dsi_clk:我們要測量的dsi 時鐘腳的頻率。單位MHz。
Dclk:像素時鐘。由lcd_htlcd_vtfps/1e6公式算出來。
Colordepth:顏色深度,一般是8 或者6。
乘以3 表示RGB 分量3 個。
Lane:dsi 的lane 數(shù)量。
除以2:是因為dsi 時鐘是雙沿采樣。
4.4.6 MIPI-DSI Video mode 屏配置示例
絕大多數(shù)MIPI-DSI 屏的配置都是用video mode。
下面是典型MIPI-DSI video mode 的board.dts 配置示例,其中用空行把配置分成幾個部分
第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏驅(qū)動來初始化。
第二部分,決定該配置是dsi 接口,而且dsi 接口使用的是video mode。
第三部分,決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。
第四部分,背光相關的設置。請看背光相關參數(shù)。
第五部分,dsi 接口的詳細設置。
第六部分,顯示效果相關的設置。
第七部分,管腳和電源設置。請看電源和管腳參數(shù)。
&lcd0 { /* part 1 */ lcd_used = <1>; lcd_driver_name = "k101im2qa04"; /* part 2 */ lcd_if = <4>; lcd_dsi_if = <0>; /* part 3 */ lcd_x = <800>; lcd_y = <1280>; lcd_width = <135>; lcd_height = <216>; lcd_dclk_freq = <68>; lcd_hbp = <36>; lcd_ht = <854>; lcd_hspw = <18>; lcd_vbp = <12>; lcd_vt = <1320>; lcd_vspw = <4>; /* part 4 */ lcd_backlight = <50>; lcd_pwm_used = <1>; lcd_pwm_ch = <0>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_bl_en = <&pio PB 8 1 0 3 1>; lcd_bright_curve_en = <0>; /* part 5 */ lcd_dsi_lane = <4>; lcd_dsi_format = <0>; lcd_dsi_te = <0>; /* part 6 */ lcd_frm = <0>; lcd_gamma_en = <0>; lcd_cmap_en = <0>; /* part 7 */ lcd_pin_power = "dcdc1"; lcd_pin_power1 = "eldo3"; lcd_power = "dc1sw"; lcd_gpio_0 = <&pio PD 22 1 0 3 1>; pinctrl-0 = <&dsi4lane_pins_a>; pinctrl-1 = <&dsi4lane_pins_b>; };
4.4.7 MIPI-DSI 超高分辨率屏配置示例
根據(jù)分辨率的高低通常分為幾種模式來配置。1080p 分辨率及其以下:只需要設置lcd_dsi_if 來控制就行。Command mode 一般是低分辨率屏,而video mode
和burst mode 則是用于高分辨率的。如果分辨率達到2k,則需要額外的設置。
分辨率達到2k 以上的屏,實際上需要多達8 條數(shù)據(jù)lane 才能正常顯示,其中四條lane 發(fā)送一副圖像中的奇像素,另外一副圖像發(fā)送偶像素。
說明
注意只有部分IC 支持超高分辨率,具體查看芯片規(guī)格中的MIPI-DSI 部分
下面是MIPI-DSI 高分辨超高分辨率(大于2k)board.dts 配置示例,其中用空行把配置分成幾個部分
第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏驅(qū)動來初始化。
第二部分,決定該配置是dsi 接口,而且dsi 接口使用的是video mode。
第三部分,決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。
第四部分,背光相關的設置,請看背光相關參數(shù)。
第五部分,dsi 接口的詳細設置。
說明 lcd_dsi_lane 依舊設置成4 條lane 的原因,是因為這個是設置一個dsi 的lane 數(shù)量,這個屏要用兩個dsi。加起來就是8 條lane。
此時lcd_tcon_mode, lcd_dsi_port_num 和lcd_tcon_en_odd_even_div 三個選項需要特別設置,點擊查看具體含義,如果是1080p 及其以下分辨率的屏(只用
4lane 或者以下的),那么這三個配置默認0 即可。
第六部分,顯示效果部分的設置。
第七部分,是管腳和電源的配置。請根據(jù)電路圖來配置。請看電源和管腳參數(shù)。
&lcd0 { /* part 1 */ lcd_used = <1>; lcd_driver_name = "lq101r1sx03"; /* part 2 */ lcd_if = <4>; lcd_dsi_if = <0>; /* part 3 */ lcd_x = <2560>; lcd_y = <1600>; lcd_width = <216>; lcd_height = <135>; lcd_dclk_freq = <268>; lcd_hbp = <80>; lcd_ht = <2720>; lcd_hspw = <32>; lcd_vbp = <37>; lcd_vt = <1646>; lcd_vspw = <6>; /* part 4 */ lcd_backlight = <50>; lcd_pwm_used = <1>; lcd_pwm_ch = <0>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_bl_en = <&pio PH 10 1 0 3 1>; /* part 5 */ lcd_dsi_lane = <4>; lcd_dsi_format = <0>; lcd_dsi_te = <0>; lcd_dsi_port_num = <1>; lcd_tcon_mode = <4>; lcd_tcon_en_odd_even_div = <1>; /* part 6 */ lcd_frm = <0>; lcd_io_phase = <0x0000>; lcd_gamma_en = <0>; lcd_bright_curve_en = <0>; lcd_cmap_en = <0>; /* part 7 */ lcd_power = "vcc18-lcd"; lcd_power1 = "vcc33-lcd"; lcd_pin_power = "vcc-pd"; lcd_gpio_0 = <&pio PH 11 1 0 3 1>; lcd_gpio_1 = <&pio PH 12 1 0 3 1>; };
4.4.8 MIPI-DSI Command mode 屏配置示例
Command mode 下的DSI 屏類似與I8080 接口,屏內(nèi)部帶RAM 用于緩沖和圖像處理,這種情況一般都需要用屏的te 腳來觸發(fā)vsync 中斷,所以與其它類型的DSI
屏不同的是,這里需要設置lcd_vsync 腳,屏的te 腳就連到lcd_vsync 上,并且lcd_dsi_te 設置成1。
te 腳的設置非常關鍵,一般來說如果屏有te 腳,則必須連上,否則在顯示動態(tài)畫面的時候會畫面會撕裂,而且軟件無法解決,直接造成最終硬件無法量產(chǎn)的結(jié)
果。
這里只列舉出與MIPI-DSI video mode 不同的關鍵之處,其它參考上一小節(jié)。
第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏驅(qū)動來初始化。
第二部分,決定該配置是dsi 接口,而且lcd_dsi_if設置成1 表明command mode。
第三部分,決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。
第四部分,背光相關的設置。請看背光相關參數(shù)。
第五部分,dsi 接口的詳細設置。lcd_dsi_te,這里設置為1 表示使能te 觸發(fā)。
第六部分,顯示效果相關的設置。
第七部分,管腳和電源設置。lcd_vsync,這里是te 腳,硬件上需要將這根腳連接到屏的te腳,軟件上需要將其設置為vsync 功能。請看電源和管腳參數(shù)。
&lcd0 { /* part 1 */ lcd_used = <1>; lcd_driver_name = "h245qbn02"; /* part 2 */ lcd_if = <4>; lcd_dsi_if = <1>; /* part 3 */ lcd_x = <240>; lcd_y = <432>; lcd_width = <52>; lcd_height = <52>; lcd_dclk_freq = <18>; lcd_hbp = <96>; lcd_ht = <480>; lcd_hspw = <2>; lcd_vbp = <21>; lcd_vt = <514>; lcd_vspw = <2>; /* part 4 */ lcd_backlight = <100>; lcd_pwm_used = <1>; lcd_pwm_ch = <0>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_bright_curve_en = <0>; lcd_bl_en = <&pio PB 3 1 0 3 1>; /* part 5 */ lcd_dsi_lane = <1>; lcd_dsi_format = <0>; lcd_dsi_te = <1>; lcd_frm = <0>; lcd_io_phase = <0x0000>; lcd_gamma_en = <0>; lcd_cmap_en = <0>; /* part 7 */ lcd_power = "axp233_dc1sw" lcd_power1 = "axp233_eldo1" lcd_gpio_0 = <&pio PB 2 1 0 3 0>; lcd_vsync = <&pio PD 21 2 0 3 0>; };
4.4.9 MIPI-DSI VR 雙屏配置示例
實際場景是兩個物理屏,每個屏是1080p,每個屏都是4 條lane,要求的是兩個屏各自顯示一幀圖像的左右一半,由于寬高比和橫豎屏以及DE 處理能力的因素,
一個DE+ 一個tcon+ 兩個DSI 已經(jīng)無法滿足,必須用兩個tcon 各自驅(qū)動一個dsi,但是兩路顯示必須要同步,這就需要用到兩個tcon 的同步模式。
LCD0 標記為slave tcon,它由master tcon 來驅(qū)動(設置lcd_tcon_mode)。
LCD1 標記為master tcon,并且負責兩個屏的所有電源,背光,管腳的開關。
把管腳,電源等都放到LCD1 開,LCD0 先開,對應模塊寄存器都初始化,但是電源不開,然后開LCD1,LCD1 使能就會觸發(fā)LCD0 一起發(fā)數(shù)據(jù)。這樣做到同時
亮滅。
說明
注意:僅有極少IC 支持該模式
&lcd0 { lcd_used = <1>; lcd_driver_name = "lpm025m475a"; ;lcd_bl_0_percent = <0>; ;lcd_bl_40_percent = <23>; ;lcd_bl_100_percent = <100>; lcd_backlight = <50>; lcd_if = <4>; lcd_x = <1080>; lcd_y = <1920>; lcd_width = <31>; lcd_height = <56>; lcd_dclk_freq = <141>; lcd_pwm_used = <0>; lcd_pwm_ch = <0>; lcd_pwm_freq = <20000>; lcd_pwm_pol = <0>; lcd_pwm_max_limit = <255>; lcd_hbp = <100>; lcd_ht = <1212>; lcd_hspw = <5>; lcd_vbp = <8>; lcd_vt = <1936>; lcd_vspw = <2>; lcd_dsi_if = <0>; lcd_dsi_lane = <4>; lcd_dsi_format = <0>; lcd_dsi_te = <0>; lcd_dsi_eotp = <0>; lcd_frm = <0>; lcd_io_phase = <0x0000>; lcd_hv_clk_phase = <0>; lcd_hv_sync_polarity= <0>; lcd_gamma_en = <0>; lcd_bright_curve_en = <0>; lcd_cmap_en = <0>; lcd_dsi_port_num = <0>; lcd_tcon_mode = <3>; lcd_slave_stop_pos = <0>; lcd_sync_pixel_num = <0>; lcd_sync_line_num = <0>; }; &lcd1 { lcd_used = <1>; lcd_driver_name = "lpm025m475a"; ;lcd_bl_0_percent = <0>; ;lcd_bl_40_percent = <23>; ;lcd_bl_100_percent = <100>; lcd_backlight = <50>; lcd_if = <4>; lcd_x = <1080>; lcd_y = <1920>; lcd_width = <31>; lcd_height = <56>; lcd_dclk_freq = <141>; lcd_pwm_used = <1>; lcd_pwm_ch = <0>; lcd_pwm_freq = <20000>; lcd_pwm_pol = <0>; lcd_pwm_max_limit = <255>; lcd_hbp = <100>; lcd_ht = <1212>; lcd_hspw = <5>; lcd_vbp = <8>; lcd_vt = <1936>; lcd_vspw = <2>; lcd_dsi_if = <0>; lcd_dsi_lane = <4>; lcd_dsi_format = <0>; lcd_dsi_te = <0>; lcd_dsi_eotp = <0>; lcd_frm = <0>; lcd_io_phase = <0x0000>; lcd_hv_clk_phase = <0>; lcd_hv_sync_polarity= <0>; lcd_gamma_en = <0>; lcd_bright_curve_en = <0>; lcd_cmap_en = <0>; lcd_dsi_port_num = <0>; lcd_tcon_mode = <1>; lcd_tcon_slave_num = <0>; lcd_slave_stop_pos = <0>; lcd_sync_pixel_num = <0>; lcd_sync_line_num = <0>; lcd_bl_en = <&pio PH 10 1 0 3 1>; lcd_power = "vcc-dsi"; lcd_power1 = "vcc18-lcd"; lcd_power2 = "vcc33-lcd"; lcd_gpio_0 = <&pio PH 8 1 0 3 1>; lcd_gpio_1 = <&pio PH 11 1 0 3 1>; lcd_gpio_2 = <&pio PH 12 1 0 3 1>; lcd_pin_power = "vcc-ph" };
4.5 I8080 接口
4.5.1 概述
Intel 8080 接口屏(又稱MCU 接口) 很老的協(xié)議,一般用在分辨率很小的屏上。
信號線:
? CS 片選信號,決定該芯片是否工作。
? RS 寄存器選擇信號,低表示選擇index 或者status 寄存器,高表示選擇控制寄存器。實際場景中一般接SoC 的LCD_DE 腳(數(shù)據(jù)使能腳)。
? /WR (低表示寫數(shù)據(jù)) 數(shù)據(jù)命令區(qū)分信號,也就是寫時鐘信號,一般接SoC 的LCD_CLK 腳。
? /RD (低表示讀數(shù)據(jù))數(shù)據(jù)讀信號,也就是讀時鐘信號,一般接SoC 的LCD_HSYNC 腳。
? RESET 復位LCD(用固定命令系列0 1 0 來復位)。
? Data 雙向傳輸?shù)臄?shù)據(jù)總線。
I8080 根據(jù)的數(shù)據(jù)位寬接口有8/9/16/18,連哪些腳參考,即使位寬一樣,連的管腳也不一樣,還要考慮的因素是rgb 格式。
RGB565,總共有65K 這么多種顏色。
RGB666,總共有262K 那么多種顏色。
9bit 固定為262K。
從屏手冊得知:數(shù)據(jù)位寬,顏色數(shù)量之和,參考RGB 和I8080 管腳配置示意圖,進行硬件連接。
4.5.2 I8080 接口屏典型配置示例
下面是典型是一個RGB565 的,位寬為8 位的I8080 接口的屏的board.dts 配置示例
1.第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏驅(qū)動來初始化。
2.第二部分,決定該配置是I8080 接口,而且是8bit/2cycle 格式RGB565。
技巧 為什么叫做8bit/2cycle RGB565 呢,首先它的格式是RGB565,也就是一個像素是16bit,然后它是8bit 的位寬,就需要兩個時鐘周期才能發(fā)完一個像素,所以才
叫2 cycle。
第三部分,決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。這里比較特殊的是設置像素時鐘要滿足以下公式:lcd_dclk_freq2>=lcd_htlcd_vt*fps,或者lcd_dclk_freq=lcd_ht 2lcd_vt*60, 也就是要么雙倍lcd_ht要么雙倍lcd_dclk_freq。
第四部分,背光相關的設置。請看背光相關參數(shù)。
第五部分,cpu 接口的詳細設置。這里使能了lcd_cpu_te和lcd_cpu_mode,意思是使用te觸發(fā)和規(guī)定了觸發(fā)間隔。這是非常關鍵的設置。
第六部分,顯示效果相關的設置。這里使能了lcd_frm也是比較關鍵的設置,詳細意思點擊查看。
第七部分,管腳和電源設置。這里為了用te 觸發(fā),同樣需要設置lcd_vsync,該腳功能定義已經(jīng)包括在pinctrl-0 中。這里自定義了一組管腳。參考RGB 和
I8080 管腳配置示意圖,通過確定I8080 的位寬,像素格式(顏色數(shù)量),在表中確定需要連接哪些管腳。請看電源和管腳參數(shù)。
&pio { I8080_8bit_pins_a: I8080_8bit@0 { allwinner,pins = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,pname = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,function = "I8080_8bit"; allwinner,muxsel = <2>; allwinner,drive = <3>; allwinner,pull = <0>; }; I8080_8bit_pins_b: I8080_8bit@1 { allwinner,pins = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,pname = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,function = "I8080_8bit_suspend"; allwinner,muxsel = <7>; allwinner,drive = <3>; allwinner,pull = <0>; }; }; &lcd0 { /* part 1 */ lcd_used = <1>; lcd_driver_name = "s2003t46g"; /* part 2 */ lcd_if = <1>; lcd_cpu_if = <14>; /* part 3 */ lcd_x = <240>; lcd_y = <320>; lcd_width = <108>; lcd_height = <64>; lcd_dclk_freq = <16>; lcd_hbp = <20>; lcd_ht = <298>; lcd_hspw = <10>; lcd_vbp = <8>; lcd_vt = <336>; lcd_vspw = <4>; /* part 4 */ lcd_pwm_used = <1>; lcd_pwm_ch = <8>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_bright_curve_en = <1>; /* part 5 */ lcd_cpu_mode = <1>; lcd_cpu_te = <1>; /* part 6 */ lcd_frm = <1>; lcd_gamma_en = <0>; lcd_cmap_en = <0>; lcd_rb_swap = <0>; /* part 7 */ lcd_power = "vcc-lcd"; lcd_pin_power = "vcc-pd"; ;reset pin lcd_gpio_0 = <&pio PD 9 1 0 3 1>; ;cs pin lcd_gpio_1 = <&pio PD 10 1 0 3 0>; pinctrl-0 = <&I8080_8bit_pins_a>; pinctrl-1 = <&I8080_8bit_pins_a>; };
4.6 LVDS 接口
4.6.1 概述
LVDS 即Low Voltage Differential Signaling 是一種低壓差分信號接口。
4.6.2 LVDS Single link 典型配置
LVDS 接口,lcd0 對應的lvds 管腳和lcd1 對應的lvds 管腳是固定而且不一樣。
由于lvds 協(xié)議不具備傳輸數(shù)據(jù)之外的能力,一般屏端不需要任何初始化,只需要初始化SoC 端即可。所以這里的lcd_driver_name 依舊是”default_lcd”,當然你可
以為初始化的啟動延時做專門的優(yōu)化。
下面是典型是single link lvds 屏的board.dts 配置示例,其中用空行把配置分成幾個部分
第一部分,決定該配置是否使用,以及使用哪個屏驅(qū)動,lcd_driver_name 決定了用哪個屏 驅(qū)動來初始化。
第二部分,決定該配置是lvds 接口,而且是single link。 技巧 如果Dual Link 的屏,那么除了要改lcd_lvds_if 為1 之外,管腳方面還要把lcd1 的管腳一起搬到下面去,也就是總共需要配置PD0 到PD9,和配置PD10 到
PD19 總共二十根腳為lvds 管腳功能(功能3)。當然屏的timing 也是要根據(jù)屏來改的。
第三部分,決定了SoC 中的LCD 模塊發(fā)送時序,請查看屏時序參數(shù)說明。
第四部分,背光相關的設置。請看背光相關參數(shù)。
第五部分,lvds 接口的詳細設置。
第六部分,顯示效果相關的設置。
第七部分,管腳和電源設置。請看電源和管腳參數(shù)。
&lcd0 { /* part 1 */ lcd_used = 1 lcd_driver_name = "default_lcd"; /* part 2 */ lcd_if = 3 lcd_lvds_if = 0 /* part 3 */ lcd_x = 1280 lcd_y = 800 lcd_width = 150 lcd_height = 94 lcd_dclk_freq = 70 lcd_hbp = 20 lcd_ht = 1418 lcd_hspw = 10 lcd_vbp = 10 lcd_vt = 814 lcd_vspw = 5 /* part 4 */ lcd_pwm_used = 1 lcd_pwm_ch = 0 lcd_pwm_freq = 50000 lcd_pwm_pol = 0 lcd_pwm_max_limit = 255 lcd_backlight = 50 lcd_bright_curve_en = 0 lcd_bl_en = <&pio PD 21 1 0 3 1>; /* part 5 */ lcd_lvds_colordepth = 1 lcd_lvds_mode = 0 /* part 6 */ lcd_frm = 1 lcd_hv_clk_phase = 0 lcd_hv_sync_polarity= 0 lcd_gamma_en = 0 lcd_cmap_en = 0 /* part 7 */ lcd_power = "vcc-lcd" pinctrl-0 = <&lvds0_pins_a>; pinctrl-1 = <&lvds0_pins_b>; };
4.6.3 LVDS dual link 典型配置
如果Dual Link 的屏:
lcd_lvds_if設置為1(場景1)或者2(場景2)。
管腳配置方面,也從4 data lane 變成8 data lane,包括clk lane 總共20 根管腳。
場景1,物理上連接一個屏,8 data lane,SoC 向每4 條lane 傳輸一半的像素,奇數(shù)像素或者偶數(shù)像素。
&lcd1 { lcd_used = <1>; lcd_driver_name = "bp101wx1"; lcd_backlight = <50>; lcd_if = <3>; lcd_x = <2560>; lcd_y = <800>; lcd_width = <150>; lcd_height = <94>; lcd_dclk_freq = <138>; lcd_pwm_used = <0>; lcd_pwm_ch = <2>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_hbp = <40>; lcd_ht = <2836>; lcd_hspw = <20>; lcd_vbp = <10>; lcd_vt = <814>; lcd_vspw = <5>; lcd_lvds_if = <1>; lcd_lvds_colordepth = <0>; lcd_lvds_mode = <0>; lcd_frm = <0>; lcd_hv_clk_phase = <0>; lcd_hv_sync_polarity= <0>; lcd_gamma_en = <0>; lcd_bright_curve_en = <0>; lcd_cmap_en = <0>; lcd_fsync_en = <0>; lcd_fsync_act_time = <1000>; lcd_fsync_dis_time = <1000>; lcd_fsync_pol = <0>; deu_mode = <0>; lcdgamma4iep = <22>; smart_color = <90>; lcd_bl_en = <&pio PJ 27 1 0 3 1>; lcd_gpio_0 = <&pio PI 1 1 0 3 1>; lcd_pin_power = "bldo5"; lcd_power = "dc1sw"; pinctrl-0 = <&lcd1_lvds2link_pins_a>; pinctrl-1 = <&lcd1_lvds2link_pins_b>; };
場景2(部分IC 支持),物理上連接兩個屏,每個屏各自4 條lane,兩個屏是一樣型號,分辨率和timing 一樣,這時候部分IC 支持將全部像素發(fā)到每個屏上,實現(xiàn)
雙顯(信號上的雙顯),注意這時候lcd timing 是一個屏的timing, lcd_lvds_if 為2。
lcd1: lcd1@01c0c001 { lcd_used = <1>; lcd_driver_name = "bp101wx1"; lcd_backlight = <50>; lcd_if = <3>; lcd_x = <1280>; lcd_y = <800>; lcd_width = <150>; lcd_height = <94>; lcd_dclk_freq = <70>; lcd_pwm_used = <0>; lcd_pwm_ch = <2>; lcd_pwm_freq = <50000>; lcd_pwm_pol = <1>; lcd_pwm_max_limit = <255>; lcd_hbp = <20>; lcd_ht = <1418>; lcd_hspw = <10>; lcd_vbp = <10>; lcd_vt = <814>; lcd_vspw = <5>; lcd_lvds_if = <2>; lcd_lvds_colordepth = <0>; lcd_lvds_mode = <0>; lcd_frm = <0>; lcd_hv_clk_phase = <0>; lcd_hv_sync_polarity= <0>; lcd_gamma_en = <0>; lcd_bright_curve_en = <0>; lcd_cmap_en = <0>; lcd_fsync_en = <0>; lcd_fsync_act_time = <1000>; lcd_fsync_dis_time = <1000>; lcd_fsync_pol = <0>; deu_mode = <0>; lcdgamma4iep = <22>; smart_color = <90>; lcd_bl_en = <&pio PJ 27 1 0 3 1>; lcd_gpio_0 = <&pio PI 1 1 0 3 1>; lcd_pin_power = "bldo5"; lcd_power = "dc1sw"; pinctrl-0 = <&lcd1_lvds2link_pins_a>; pinctrl-1 = <&lcd1_lvds2link_pins_a>; };
4.7 RGB 和I8080 管腳配置示意圖
?
圖4-8: pinmux
?
4.8 從sys_config.fex 到board.dtsi 的遷移注意事項
為了規(guī)范等原因,部分平臺將配置放在board.dtsi 中實現(xiàn)。下面說明了修改board.dtsi 的注意事項。
4.8.1 管腳定義
在配置RGB 屏或者LVDS 屏時,現(xiàn)在不再需要復雜的定義,也不需要了解到底哪些管腳需要配置,也不需要lcd0_suspend節(jié)點了。其中rgb24_pins_a這個名字是
定義好的,直接用即可,一般LCD屏直接可用的配置會在注釋中寫明,你可以在內(nèi)核目錄下arch/arm/boot/dts或者arch/arm64/boot/dts下的平臺-pinctrl.dtsi 文
件中找。
例子:
pinctrl-0 = <&rgb24_pins_a>; pinctrl-1 = <&rgb24_pins_b>;//休眠時候的定義,io_disable
當然,你也可以自定義一組腳,寫在board.dtsi 中,只要名字不要和現(xiàn)有名字重復就行。
為了規(guī)范,我們將在所有平臺保持一致的名字,其中后綴為a 即為管腳使能,b 的為io_disable用于設備關閉時。
目前有以下管腳定義可用:
?
表4-2: 顯示管腳名稱表
?
管腳名稱 | 描述 |
---|---|
rgb24_pins_a 和rgb24_pins_b | RGB 屏接口,而且數(shù)據(jù)位寬是24,RGB888 |
rgb18_pins_a 和rgb18_pins_b | RGB 屏接口,而且數(shù)據(jù)位寬是16,RGB666 |
lvds0_pins_a和lvds0_pins_b | Single link LVDS 接口0 管腳定義(主顯lcd0) |
lvds1_pins_a 和lvds1_pins_b | Single link LVDS 接口1 管腳定義(主顯lcd0) |
lvds2link_pins_a 和lvds2link_pins_b | Dual link LVDS 接口管腳定義(主顯lcd0) |
lvds2_pins_a 和lvds2_pins_b | Single link LVDS 接口0 管腳定義(主顯lcd1) |
lvds3_pins_a 和lvds3_pins_b | Single link LVDS 接口1 管腳定義(主顯lcd1) |
lcd1_lvds2link_pins_a 和lcd1_lvds2link_pins_b | Dual link LVDS 接口管腳定義(主顯lcd1) |
dsi4lane_pins_a 和dsi4lane_pins_b | DSI 屏接口管腳定義,4lane,如果是其它lane 數(shù)量,只 |
4.8.2 電源定義
電源定義在舊的SDK 中并不需要注意什么,還是直接把axp 的別名字符串賦值給想lcd_power這樣的屬性上即可,但是新的SDK 中,如果需要使用某路電源必須先
在disp 節(jié)點中定義,然后lcd 部分使用的字符串則要和disp 中定義的一致。比如下面的例子:
disp: disp@01000000 { disp_init_enable = <1>; disp_mode = <0>; /* VCC-LCD */ dc1sw-supply = ; /* VCC-LVDS and VCC-HDMI */ bldo1-supply = ; /* VCC-TV */ cldo4-supply = ; };
其中”-supply” 是固定的,它之前的字符串則是隨意的,不過建議取有意義的名字。而后面的像 則必須在board.dtsi 的regulator0 節(jié)點中找到。
然后lcd0 節(jié)點中,如果要使用reg_sw,則類似下面這樣寫就行,dc1sw 對應dc1sw-supply。
lcd_power=”dc1sw”
由于u-boot 中也有axp 驅(qū)動和display 驅(qū)動,它們和內(nèi)核一樣,都是讀取同份配置,為了能互相兼容,取名的時候,有以下限制。
在u-boot 2018 中,axp 驅(qū)動只認類似bldo1 這樣從axp 芯片中定義的名字,所以命名xxxsupply的時候最好按照這個axp 芯片的定義來命名。
4.8.3 其它注意事項
board.dtsi 里面可能只有l(wèi)cd0 沒有l(wèi)cd1,或只有tv0 沒有tv1,這時候你要添加的話,需要參考內(nèi)核目錄arch/arm/boot/dts 或者arch/arm64/boot/dts 下對應的平
臺.dtsi 文件。其中最關鍵的是@ 后面那串地址必須與內(nèi)核中定義一致,比如:
lcd1: lcd1@01c0c000
5 硬件參數(shù)說明
5.1 LCD 接口參數(shù)說明
5.1.1 lcd_driver_name
Lcd 屏驅(qū)動的名字(字符串),必須與屏驅(qū)動的名字對應。
5.1.2 lcd_model_name
Lcd 屏模型名字,非必須,可以用于同個屏驅(qū)動中進一步區(qū)分不同屏。
5.1.3 lcd_if
Lcd Interface
設置相應值的對應含義為:
0:HV RGB接口 1:CPU/I80接口 2:Reserved 3:LVDS接口 4:DSI接口
5.1.4 lcd_hv_if
Lcd HV panel Interface
這個參數(shù)只有在lcd_if=0 時才有效。定義RGB 同步屏下的幾種接口類型。
設置相應值的對應含義為:
0:Parallel RGB 8:Serial RGB 10:Dummy RGB 11:RGB Dummy 12:Serial YUV (CCIR656)
5.1.5 lcd_hv_clk_phase
Lcd HV panel Clock Phase
這個參數(shù)只有在lcd_if=0 時才有效。定義RGB 同步屏的clock 與data 之間的相位關系??偣灿? 個相位可供調(diào)節(jié)。
設置相應值的對應含義為:
0: 0 degree 1: 90 degree 2: 180 degree 3: 270 degree
5.1.6 lcd_hv_sync_polarity
Lcd HV panel Sync signals Polarity
這個參數(shù)只有在lcd_if=0 時才有效。定義RGB 同步屏的hsync 和vsync 的極性。
設置相應值的對應含義為:
0:vsync active low,hsync active low 1:vsync active high,hsync active low 2:vsync active low,hsync active high 3:vsync active high,hsync active high
5.1.7 lcd_hv_srgb_seq
Lcd HV panel Serial RGB output Sequence
這個參數(shù)只有在lcd_if=0 且lcd_hv_if=8(Serial RGB)時才有效。
定義奇數(shù)行RGB 輸出的順序:
0: Odd lines R-G-B; Even line R-G-B 1: Odd lines B-R-G; Even line R-G-B 2: Odd lines G-B-R; Even line R-G-B 4: Odd lines R-G-B; Even line B-R-G 5: Odd lines B-R-G; Even line B-R-G 6: Odd lines G-B-R; Even line B-R-G 8: Odd lines R-G-B; Even line B-R-G 9: Odd lines B-R-G; Even line G-B-R 10: Odd lines G-B-R; Even line G-B-R
5.1.8 lcd_hv_syuv_seq
Lcd HV panel Serial YUV output Sequence
這個參數(shù)只有在lcd_if=0 且lcd_hv_if=12(Serial YUV)時才有效。
定義YUV 輸出格式:
0:YUYV 1:YVYU 2:UYVY 3:VYUY
5.1.9 lcd_hv_syuv_fdly
Lcd HV panel Serial YUV F line Delay
這個參數(shù)只有在lcd_if=0 且lcd_hv_if=12(Serial YUV)時才有效。
定義CCIR656 編碼時F 相對有效行延遲的行數(shù):
0:F toggle right after active video line 1:Delay 2 lines (CCIR PAL) 2:Delay 3 lines (CCIR NTSC)
5.1.10 lcd_cpu_if
Lcd CPU panel Interface
這個參數(shù)只有在lcd_if=1 時才有效, 具體時序可參照RGB 和I8080 管腳配置示意圖中CPU 那幾列。
設置相應值的對應含義為:
0:18bit/1cycle (RGB666) 2: 16bit/3cycle (RGB666) 4:16bit/2cycle (RGB666) 6:16bit/2cycle (RGB666) 8:16bit/1cycle (RGB565) 10:9bit/1cycle (RGB666) 12:8bit/3cycle (RGB666) 14:8bit/2cycle (RGB565)
5.1.11 lcd_cpu_te
Lcd CPU panel tear effect
設置相應值的對應含義為,設置為0 時,刷屏間隔時間為lcd_ht × lcd_vt;設置為1 或2 時,刷屏間隔時間為兩個te 脈沖:
Lcd CPU panel tear effect
設置相應值的對應含義為,設置為0 時,刷屏間隔時間為lcd_ht × lcd_vt;設置為1 或2 時,刷屏間隔時間為兩個te 脈沖:
0:frame trigged automatically 1:frame trigged by te rising edge 2:frame trigged by te falling edge
5.1.12 lcd_lvds_if
Lcd LVDS panel Interface
設置相應值的對應含義為:
0:Single Link( 1 clock pair+3/4 data pair) 1:Dual Link(8 data lane,每4條lane接受一半像素,奇數(shù)像素或者偶數(shù)像素) 2: Dual Link (每4條lane接受全部像素,常用于物理雙屏,且兩個屏一樣)
lcd_lvds_if 等于2 的場景是,接兩個一模一樣的屏,然后兩個屏顯示同樣的內(nèi)容,此時lcd 的其它timing 只需要填寫一個屏的timing 即可。
5.1.13 lcd_lvds_colordepth
Lcd LVDS panel color depth
設置相應值對應含義為:
0:8bit per color(4 data pair) 1:6bit per color(3 data pair)
5.1.14 lcd_lvds_mode
Lcd LVDS Mode
這個參數(shù)只有在lcd_lvds_bitwidth=0 時才有效。
設置相應值對應含義為(見下圖):
0:NS mode 1:JEIDA mode
?
圖5-1: lvds mode
?
5.1.15 lcd_dsi_if
Lcd MIPI DSI panel Interface
這個參數(shù)只有在lcd_if=4 時才有效。定義MIPI DSI 屏的兩種類型。
設置相應值的對應含義為:
0:Video mode 1:Command mode 2:video burst mode
注:Video mode 的LCD 屏,是實時刷屏的,有ht,hbp 等時序參數(shù)的定義;Command mode 的屏,屏上帶有顯示Buffer,一般會有一個TE 引腳。
5.1.16 lcd_dsi_lane
Lcd MIPI DSI panel Data Lane number
這個參數(shù)只有在lcd_if=4 時才有效。
設置相應值的對應含義為:
1:1 data lane 2:2 data lane 3:3 data lane 4:4 data lane
5.1.17 lcd_dsi_format
Lcd MIPI DSI panel Data Pixel Format
這個參數(shù)只有在lcd_if=4 時才有效。
設置相應值的對應含義為:
0:Package Pixel Stream, 24bit RGB 1:Loosely Package Pixel Stream, 18bit RGB 2:Package Pixel Stream, 18bit RGB 3:Package Pixel Stream, 16bit RGB
5.1.18 lcd_dsi_te
Lcd MIPI DSI panel Tear Effect
這個參數(shù)只有在lcd_if=4 時才有效。
設置相應值的對應含義為:
0:frame trigged automatically 1:frame trigged by te rising edge 2:frame trigged by te falling edge
注:設置為0 時,刷屏間隔時間為lcd_ht × lcd_vt;設置為1 或2 時,刷屏間隔時間為兩個te脈沖。
這個的作用就是屏一端發(fā)給SoC 端的信號,用于同步信號,如果使能這個變量,那么SoC 內(nèi)部的顯示中斷將由這個外部腳來觸發(fā)。
5.1.19 lcd_dsi_port_num
DSI 屏port 數(shù)量
這個參數(shù)只有在lcd_if=4 時才有效。
設置相應值的對應含義為:
0:一個port 1:兩個port
這個選項的一個作用是,單LCD 屏為8 條lane 的時候,如果只需要初始化其中一個driver IC,則這個設置1,如果兩個driver IC 都要初始化,這里設置成0。并使用lcd_source.c 定義的函數(shù)來進行初始化。
5.1.20 lcd_tcon_mode
Tcon 模式
這個參數(shù)只有在lcd_if=4 時才有效。
設置相應值的對應含義為:
0:normal mode 1:tcon master mode(在第一次發(fā)送數(shù)據(jù)同步) 2::tcon master mode(每一幀都同步) 3:tcon slave mode(依靠master mode來啟動) 4:one tcon driver two dsi(8條lane) 5.1.21 lcd_slave_tcon_num
5.1.21 lcd_slave_tcon_num
Slave Tcon 的序號
這個參數(shù)只有在lcd_if=4 時而且lcd_tcon_mode 等于1 或者2 才有效。用于告訴master 模式下的tcon,從tcon 的序號是多少。
設置相應值的對應含義為:
0:tcon_lcd0 1:tcon_lcd1
5.1.22 lcd_tcon_en_odd_even_div
這個參數(shù)只有在lcd_if=4 而且lcd_tcon_mode=4 時才有效。
設置相應值的對應含義為:
0:tcon將一幀圖像分左右兩半來發(fā)送給兩個DSI模塊 1:tcon將一幀圖像分奇偶像素來發(fā)給兩個DSI模塊
5.1.23 lcd_sync_pixel_num
這個參數(shù)只有在lcd_if=4 而且lcd_tcon_mode 等于2 或者3 時才有效。
設置同步從tcon 的起始pixel。
整數(shù):不超過lcd_ht
5.1.24 lcd_sync_line_num
這個參數(shù)只有在lcd_if=4 而且lcd_tcon_mode 等于2 或者3 時才有效。
設置同步從tcon 的起始行。
整數(shù):不超過lcd_vt
5.1.25 lcd_cpu_mode
Lcd CPU 模式,控制。
設置相應值的對應含義為,設置為0 時,刷屏間隔時間為lcd_ht × lcd_vt;設置為1 或2 時,刷屏間隔時間為兩個te 脈沖:
0:中斷自動根據(jù)時序,由場消隱信號內(nèi)部觸發(fā)。 1:中斷根據(jù)數(shù)據(jù)Block的counter觸發(fā)或者由外部te觸發(fā)。
5.1.26 lcd_fsync_en
LCD 使能fsync 功能,用于觸發(fā)sensor 出圖, 目的是同步,部分IC 支持。
0:disable 1:enable
5.1.27 lcd_fsync_act_time
LCD 的fsync 功能,其中的有效電平時間長度,單位:像素時鐘的個數(shù)。
0~lcd_ht-1
5.1.28 lcd_fsync_dis_time
LCD 的fsync 功能,其中的無效電平時間長度,單位:像素時鐘的個數(shù)。
0~lcd_ht-1
5.1.29 lcd_fsync_pol
LCD 的fsync 功能的有效電平的極性。
0:有效電平為低 1:有效電平為高
5.2 屏時序參數(shù)說明
下面幾個參數(shù)對于調(diào)屏非常關鍵,決定了發(fā)送端(SoC)發(fā)送數(shù)據(jù)時序。由于涉及到發(fā)送端和接收端的調(diào)試,除了分辨率和尺寸之外,其它幾個數(shù)值都不是絕對不
變的,兩款一樣分辨率,同種接口的屏,它們的數(shù)值也有可能不一樣。
獲取途徑如下:
詢問LCD 屏廠。
從屏手冊或者Driver IC 手冊中查找(向屏廠索要這些文檔),如下圖所示。
?
圖5-2: lcd_info1
?
?
圖5-3: lcd_info2
?
在前面兩步都搞不定的情況下,可以根據(jù)vesa 標準來設置,主要是DMT 和CVT 標準。
其中DMT,指的是《VESA and Industry Standards and Guidelines for Computer Display Monitor Timing(DMT)》,下載該標準,里面就有各種常用分辨率的
timing。其中的CVT,指的是《VESA Coordinated Video Timings(CVT) Standard》,該標準提供一種通用公式用于計算出指定分辨率,刷新率等參數(shù)的timing。
可以下載這個excel 表來計算VESA Coordinated Video Timing Generator。
由下面兩條公式得知,我們不需要設置lcd_hfp和lcd_vfp參數(shù),因為驅(qū)動會自動根據(jù)其它幾個已知參數(shù)中算出lcd_hfp和lcd_vfp。
lcd_ht = lcd_x + lcd_hspw + lcd_hbp + lcd_hfp lcd_vt = lcd_y + lcd_vspw + lcd_vbp + lcd_vfp
5.2.1 lcd_x
顯示屏的水平像素數(shù)量,也就是屏分辨率中的寬。
5.2.2 lcd_y
顯示屏的垂直行數(shù),也就是屏分辨率中的高。
5.2.3 lcd_ht
Horizontal Total time
指一行總的dclk 的cycle 個數(shù)。見下圖:
?
圖5-4: lcdht
?
5.2.4 lcd_hbp
Horizontal Back Porch
指有效行間,行同步信號(hsync)開始,到有效數(shù)據(jù)開始之間的dclk 的cycle 個數(shù),包括同步信號區(qū)。見上圖,注意的是包含了hspw 段。
說明 是包含了hspw 段,也就是lcd_hbp= 實際的hbp+ 實際的hspw
5.2.5 lcd_hspw
Horizontal Sync Pulse Width
指行同步信號的寬度。單位為1 個dclk 的時間(即是1 個data cycle 的時間)。見上圖。
5.2.6 lcd_vt
Vertical Total time
指一場的總行數(shù)。見下圖:
?
圖5-5: lcdvt
?
5.2.7 lcd_vbp
Vertical Back Porch
指場同步信號(vsync)開始,到有效數(shù)據(jù)行開始之間的行數(shù),包括場同步信號區(qū)。
說明
是包含了vspw 段,也就是lcd_vbp= 實際的vbp+ 實際的vspw
5.2.8 lcd_vspw
Vertical Sync Pulse Width
指場同步信號的寬度。單位為行。見上圖。
5.2.9 lcd_dclk_freq
Dot Clock Frequency
傳輸像素傳送頻率。單位為MHz。
fps = (lcd_dclk_freq×1000×1000) / (ht×vt)。
這個值根據(jù)以下公式計算:
lcd_dclk_freq=lcd_htlcd_vtfps
注意:
后面的三個參數(shù)都是從屏手冊中獲得,fps 一般是60。
如果是串行接口,發(fā)完一個像素需要2 到3 個周期的,那么。
lcd_dclk_freq * cycles = lcd_ht*lcd_vt*fps
或者
lcd_dclk_freq = lcd_ht*cycles*lcd_vt*fps
5.2.10 lcd_width
Width of lcd panel in mm
此參數(shù)描述lcd 屏幕的物理寬度,單位是mm。用于計算dpi。
5.2.11 lcd_height
height of lcd panel in mm
此參數(shù)描述lcd 屏幕的物理高度,單位是mm。用于計算dpi。
5.3 背光相關參數(shù)
目前用得比較廣泛的就是pwm 背光調(diào)節(jié),原理是利用pwm 脈沖開關產(chǎn)生的高頻率閃爍效應,通過調(diào)節(jié)占空比,達到欺騙人眼,調(diào)節(jié)亮暗的目的。
5.3.1 lcd_pwm_used
是否使用pwm。
此參數(shù)標識是否使用pwm 用以背光亮度的控制。
5.3.2 lcd_pwm_ch
Pwm channel used
此參數(shù)標識使用的Pwm 通道,這里是指使用SoC 哪個pwm 通道,通過查看原理圖連接可知。
5.3.3 lcd_pwm_freq
Lcd backlight PWM Frequency
這個參數(shù)配置PWM 信號的頻率,單位為Hz。
說明 頻率不宜過低否則很容易就會看到閃爍,頻率不宜過快否則背光調(diào)節(jié)效果差。部分屏手冊會標明所允許的pwm 頻率范圍,請遵循屏手冊固定范圍進行設置。 在低亮度的時候容易看到閃爍,是正?,F(xiàn)象,目前已知用上pwm 的背光都是如此。
5.3.4 lcd_pwm_pol
Lcd backlight PWM Polarity
這個參數(shù)配置PWM 信號的占空比的極性。設置相應值對應含義為:
0:active high 1:active low
5.3.5 lcd_pwm_max_limit
Lcd backlight PWM 最高限制,以亮度值表示
比如150,則表示背光最高只能調(diào)到150,0-255 范圍內(nèi)的亮度值將會被線性映射到0-150 范圍內(nèi)。用于控制最高背光亮度,節(jié)省功耗。
5.3.6 lcd_bl_en
背光使能腳,非必須,看原理圖是否有,用于使能或者禁止背光電路的電壓。
示例:lcd_bl_en = port:PD24<1><2><1>
含義:PD24 輸出高電平時打開LCD 背光;下拉,默認高電平
? 第一個尖括號:功能分配;1 為輸出;
? 第二個尖括號:內(nèi)置電阻;使用0 的話,標示內(nèi)部電阻高阻態(tài),如果是1 則是內(nèi)部電阻上拉,2 就代表內(nèi)部電阻下拉。使用default 的話代表默認狀態(tài),即電阻上
拉。其它數(shù)據(jù)無效。
? 第三個尖括號:驅(qū)動能力;default 表驅(qū)動能力是等級1
? 第四個尖括號:電平;0 為低電平,1 為高電平。
需要在屏驅(qū)動調(diào)用相應的接口進行開、關的控制。
說明
一般來說,高電平是使能,在這個前提下,建議將內(nèi)阻電阻設置成下拉,防止硬件原因造成的上拉,導致背光提前亮。默認電平請?zhí)顚懜唠娖?,這是uboot 顯示過
度到內(nèi)核顯示,平滑無閃爍的需要。
5.3.7 lcd_bl_n_percent
背光映射值,n 為(0-100)
此功能是針對亮度非線性的LCD 屏的,按照配置的亮度曲線方式來調(diào)整亮度變化,以使亮度變化更線性。
比如lcd_bl_50_percent = 60,表明將50% 的亮度值調(diào)整成60%,即亮度比原來提高10%。
說明
修改此屬性不當可能導致背光調(diào)節(jié)效果差。
5.3.8 lcd_backlight
背光默認值,0-255。
此屬性決定在uboot 顯示logo 階段的亮度,進入都內(nèi)核時則是讀取保存的配置來決定亮度。
說明
顯示logo 階段,一般來說需要比較亮的亮度,業(yè)內(nèi)做法都是如此。
5.4 顯示效果相關參數(shù)
5.4.1 lcd_frm
Lcd Frame Rate Modulator
FRM 是解決由于PIN 減少導致的色深問題。
這個參數(shù)設置相應值對應含義為:
0:RGB888 -- RGB888 direct 1:RGB888 -- RGB666 dither 2:RGB888 -- RGB565 dither
有些LCD 屏的像素格式是18bit 色深(RGB666)或16bit 色深(RGB565),建議打開FRM功能,通過dither 的方式彌補色深,使顯示達到24bit 色深(RGB888)
的效果。如下圖所示,上圖是色深為RGB66 的LCD 屏顯示,下圖是打開dither 后的顯示,打開dither 后色彩漸變的地方過度平滑。
?
圖5-6: lcd_frm 打開
?
?
圖5-7: lcd_frm 關閉
?
5.4.2 lcd_gamma_en
Lcd Gamma Correction Enable
設置相應值的對應含義為:
0:Lcd的Gamma校正功能關閉 1:Lcd的Gamma校正功能開啟
設置為1 時,需要在屏驅(qū)動中對lcd_gamma_tbl[256] 進行賦值。
5.4.3 lcd_cmap_en
Lcd Color Map Enable
設置相應值的對應含義為:
0:Lcd的色彩映射功能關閉 1:Lcd的色彩映射功能開啟
設置為1 時,需要對lcd_cmap_tbl 2[4] 進行賦值Lcd Color Map Table。
每個像素有R、G、B 三個單元,每四個像素組成一個選擇項,總共有12 個可選。數(shù)組第一維表示奇偶行,第二維表示像素的RGB,第三維表示第幾個像素,數(shù)組
的內(nèi)容即表示該位置映射到的內(nèi)容。
LCD CMAP 是對像素的映射輸出功能,只有像素有特殊排布的LCD 屏才需要配置。
LCD CMAP 定義每行的4 個像素為一個總單元,每個像素分R、G、B 3 個小單元,總共有12個小單元。通過lcd_cmap_tbl 定義映射關系,輸出的每個小單元可隨
意映射到12 個小單元之一。
__u32 lcd_cmap_tbl[2][3][4] = { { {LCD_CMAP_G0,LCD_CMAP_B1,LCD_CMAP_G2,LCD_CMAP_B3}, {LCD_CMAP_B0,LCD_CMAP_R1,LCD_CMAP_B2,LCD_CMAP_R3}, {LCD_CMAP_R0,LCD_CMAP_G1,LCD_CMAP_R2,LCD_CMAP_G3}, }, { {LCD_CMAP_B3,LCD_CMAP_G2,LCD_CMAP_B1,LCD_CMAP_G0}, {LCD_CMAP_R3,LCD_CMAP_B2,LCD_CMAP_R1,LCD_CMAP_B0}, {LCD_CMAP_G3,LCD_CMAP_R2,LCD_CMAP_G1,LCD_CMAP_R0}, }, };
如上,上三行代表奇數(shù)行的像素排布,下三行代表偶數(shù)行的像素排布。
每四個像素為一個單元,第一列代表每四個像素的第一個像素映射,第二列代表每四個像素的第二個像素映射,以此類推。
如上的定義,像素的輸出格式如下圖所示。
?
圖5-8: cmap
?
5.4.4 lcd_rb_swap
調(diào)換tcon 模塊RGB 中的R 分量和B 分量。
0:不變 1:調(diào)換R分量和B分量
5.5 電源和管腳參數(shù)
5.5.1 概述
如果需要使用某路電源必須現(xiàn)在[disp]節(jié)點中定義,然后[lcd]部分使用的字符串則要和disp 中定義的一致。比如下面的例子:
disp: disp@01000000 { disp_init_enable = <1>; disp_mode = <0>; /* VCC-LCD */ dc1sw-supply = ; /* VCC-LVDS and VCC-HDMI */ bldo1-supply = ; /* VCC-TV */ cldo4-supply = ; };
其中-supply是固定的,在-supply之前的字符串則是隨意的,不過建議取有意義的名字。在=后面的像則必須在board.dtsi 的regulator0節(jié)點中找到。
然后lcd0 節(jié)點中,如果要使用reg_sw,則像下面這樣寫就行,dc1sw 對應dc1sw-supply。
lcd_power=”dc1sw”
由于u-boot 中也有axp 驅(qū)動和display 驅(qū)動,和內(nèi)核,它們都是讀取同份配置,為了能互相兼容,取名的時候,有以下限制:
在u-boot 2018 中,axp 驅(qū)動只認類似bldo1 這樣從axp 芯片中定義的名字,所以命名xxxsupply的時候最好按照這個axp 芯片的定義來命名。
5.5.2 lcd_power
見上面概述的注意事項。
示例:lcd_power = “vcc-lcd”
配置regulator 的名字。配置好之后,需要在屏驅(qū)動調(diào)用相應的接口進行開、關的控制。
注意:如果有多個電源需要打開,則定義lcd_power1,lcd_power2 等。
5.5.3 lcd_pin_power
用法lcd_power一致,區(qū)別是用戶設置之后,不需要在屏驅(qū)動中去操作,而是驅(qū)動框架自行在屏驅(qū)動之前使能,在屏驅(qū)動之后禁止。
示例:lcd_pin_power = “vcc-pd”
注意:如果需要多組,則添加lcd_pin_power1,lcd_pin_power2 等。除了lcddx 之外,這里的電源還有可能是pwm 所對應管腳的電源。
5.5.4 lcd_gpio_0
示例:lcd_gpio_0 = port:PD25<0><0><0>
含義:lcd_gpio_0 引腳為PD25。
? 第一個尖括號:功能分配;0 為輸入,1 為輸出。
? 第二個尖括號:內(nèi)置電阻;使用0 的話,標示內(nèi)部電阻高阻態(tài),如果是1 則是內(nèi)部電阻上拉,2 就代表內(nèi)部電阻下拉。使用default 的話代表默認狀態(tài),即電阻上
拉。其它數(shù)據(jù)無效。
? 第三個尖括號:驅(qū)動能力;default 表驅(qū)動能力是等級1。
? 第四個尖括號:表示默認值;即是當設置為輸出時,該引腳輸出的電平,0 為低電平,1 為高電平。
需要在屏驅(qū)動調(diào)用相應的接口進行拉高,拉低的控制。請看管腳控制函數(shù)說明
注意:如果有多個gpio 腳需要控制,則定義lcd_gpio_0,lcd_gpio_1 等。
5.5.5 lcddx
示例:lcdd0 = port:PD00<3><0>
含義:lcdd0 這個引腳,即是PD0,配置為LVDS 輸出。
? 第一個尖括號:功能分配;0 為輸入,1 為輸出,2 為LCD 輸出,3 為LVDS 接口輸出,7 為disable。
? 第二個尖括號:內(nèi)置電阻;使用0 的話,標示內(nèi)部電阻高阻態(tài),如果是1 則是內(nèi)部電阻上拉,2 就代表內(nèi)部電阻下拉。使用default 的話代表默認狀態(tài),即電阻上
拉。其它數(shù)據(jù)無效。
? 第三個尖括號:驅(qū)動能力;default 表驅(qū)動能力是等級1。
? 第四個尖括號:表示默認值;即是當設置為輸出時,該引腳輸出的電平,0 為低電平,1 為高電平。
LCD PIN 的配置如下:
LCD 為HV RGB 屏,CPU/I80 屏時,必須定義相應的IO 口為LCD 輸出(如果是0 路輸出,第一個尖括號為2;如果是1 路輸出,第一個尖括號為3)。
具體的IO 對應關系可參考user manual 手冊進行配置。
LCD PIN 的所有IO,均可通過注釋方式去掉其定義,顯示驅(qū)動對注釋IO 不進行初始化操作。
需要在屏驅(qū)動調(diào)用相應的接口進行開、關的控制。
注意:不是一定要叫做lcdd0 這個名字,你改成其它名字對驅(qū)動不會造成任何影響,這里只是為了方便記憶。
5.5.6 pinctrl-0 和pinctrl-1
在配置lcd0節(jié)點時,當碰到需要配置管腳復用時,你只要把pinctrl-0和pinctrl-1賦值好就行,可以用提前定義好的,也可以用自己定義的,提前定義的管腳一般可
以在內(nèi)核目錄下arch/arm/boot/dts或者arch/arm64/boot/dts下找:平臺-pinctrl.dtsi 中找到定義。
例子:
pinctrl-0 = <&rgb24_pins_a>; pinctrl-1 = <&rgb24_pins_b>;//休眠時候的定義,io_disable
?
表5-1: 提前定義好的管腳名稱
?
管腳名稱 | 描述 |
---|---|
rgb24_pins_a 和rgb24_pins_b | RGB 屏接口,而且數(shù)據(jù)位寬是24,RGB888 |
rgb18_pins_a 和rgb18_pins_b | RGB 屏接口,而且數(shù)據(jù)位寬是16,RGB666 |
lvds0_pins_a 和lvds0_pins_b | Single link LVDS 接口0 管腳定義(主顯lcd0) |
lvds1_pins_a 和lvds1_pins_b | Single link LVDS 接口1 管腳定義(主顯lcd0) |
lvds2link_pins_a 和lvds2link_pins_b | Dual link LVDS 接口管腳定義(主顯lcd0) |
lvds2_pins_a 和lvds2_pins_b | Single link LVDS 接口0 管腳定義(主顯lcd1) |
lvds3_pins_a 和lvds3_pins_b | Single link LVDS 接口1 管腳定義(主顯lcd1) |
lcd1_lvds2link_pins_a 和lcd1_lvds2link_pins_b | Dual link LVDS 接口管腳定義(主顯lcd1) |
dsi4lane_pins_a 和dsi4lane_pins_b | 4 lane DSI 屏接口管腳定義 |
自定義一組腳
寫在board.dtsi 中,只要名字不要和現(xiàn)有名字重復就行,首先判斷自己需要用的管腳,屬于大cpu 域還是小cpu 域,以此判斷需要將管腳定義放在pio(大cpu
域)下面還是r_pio(小cpu域)下面。
例子:
&pio { I8080_8bit_pins_a: I8080_8bit@0 { allwinner,pins = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,pname = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,function = "I8080_8bit"; allwinner,muxsel = <2>; allwinner,drive = <3>; allwinner,pull = <0>; }; I8080_8bit_pins_b: I8080_8bit@1 { allwinner,pins = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,pname = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6", "PD7", "PD8", "PD18", " PD19", "PD20", "PD21"; allwinner,function = "I8080_8bit_suspend"; allwinner,muxsel = <7>; allwinner,drive = <3>; allwinner,pull = <0>; }; };
? pins,具體管腳。
? pname,管腳名稱,隨便取。
? function,管腳功能名稱,隨便取。
? muxsel,管腳功能選擇。根據(jù)port spec 來選擇對應功能。
? drive,驅(qū)動能力,數(shù)值越大驅(qū)動能力越大。
? pull,上下拉,使用0 的話,標示內(nèi)部電阻高阻態(tài),如果是1 則是內(nèi)部電阻上拉,2 就代表內(nèi)部電阻下拉。使用default 的話代表默認狀態(tài),即電阻上拉。其它數(shù)
據(jù)無效。
為了規(guī)范,我們將在所有平臺保持一致的名字,其中后綴為a 為管腳使能,b 的為io_disable 用于設備關閉時。
有時候,你需要用兩組不同功能的管腳,可以像下面這樣定義即可。
pinctrl-0 = <&rgb24_pins_a>, <&xxx_pins_a>; pinctrl-1 = <&rgb24_pins_b>, <&xxx_pins_b>;//休眠時候的定義,io_disable
5.6 ESD 靜電檢測自動恢復功能
這個功能在linux4.9 以及l(fā)inux 3.10 sunxi-product 分支上實現(xiàn)了,如果需要這個功能,需要完成以下步驟。
首先打開如下內(nèi)核配置:
?
圖5-9: ESD 內(nèi)核配置
?
修改屏驅(qū)動,實現(xiàn)三個回調(diào)函數(shù):
如下示例,在屏he0801a068 上添加esd 相關的回調(diào)函數(shù)。 (linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd/he0801a068.c)。
?
圖5-10: ESD 屏驅(qū)動添加函數(shù)
?
esd_check 函數(shù)原型:
S32 esd_check(u32 sel)
作用:是給上層反饋當前屏的狀態(tài)。
返回值:如果屏正常的話就返回0,不正常的話就返回非0。
sel:顯示索引。
由于屏的類型接口眾多,不同屏檢測屏的狀態(tài)各異,一般來說是通過驅(qū)動接口讀取屏的內(nèi)部信息(id 或者其它寄存器),如果獲取正常則認為屏是正常的,獲取失
敗則認為屏是異常的。比如下面dsi 屏的做法:
?
圖5-11: ESD 屏驅(qū)動函數(shù)實現(xiàn)
?
此外,一般情況下,也會通過dsi 接口讀取0x0A 命令(獲取power 模式)來判斷屏是否正常。
sunxi_lcd_dsi_dcs_read(sel, 0x0A, result, &num)
?
圖5-12: ESD MIPI 狀態(tài)寄存器
?
reset_panel 函數(shù)原型:
s32 reset_panel(u32 sel)
作用:當屏幕異常的時候所需要的復位操作。
返回值:復位成功就是0,復位失敗非0。
sel:顯示索引。
每個屏的初始化都不同,順序步驟都不一樣,總的來說就是執(zhí)行部分或者完整的屏驅(qū)動里面的close_flow 和open_flow 所定義的回調(diào)函數(shù)。根據(jù)實際情況靈活編寫
這個函數(shù)。
值得注意的是:某些dsi 屏中,需要至少執(zhí)行過一次sunxi_lcd_dsi_clk_disable(dsi 高速時鐘禁止)和sunxi_lcd_dsi_clk_enable(高速時鐘使能),否則可能導致
dsi 的讀函數(shù)異常。
下圖是復位函數(shù)示例:
?
圖5-13: ESD 復位函數(shù)1
?
set_esd_info 函數(shù)原型:
s32 set_esd_info(struct disp_lcd_esd_info *p_info)
作用:控制esd 檢測的具體行為。比如間隔多長時間檢測一次,復位的級別,以及檢測函數(shù)被調(diào)用的位置。
返回值:成功設置返回0,否則非0。
p_info:需要設置的esd 行為結(jié)構(gòu)體。
示例:下面圖所示,每隔60 次顯示中斷檢測一次(調(diào)用esd_check 函數(shù),如果顯示幀率是60fps 的話,那么就是1 秒一次),然后將在顯示中斷處理函數(shù)里面執(zhí)行
檢測函數(shù),由esd_check_func_pos 成員決定調(diào)用esd_check 函數(shù)的位置,如果是0 則在中斷之外執(zhí)行檢測函數(shù),之所以有這個選項是因為顯示中斷資源(中斷處
理時間)是非常珍貴的資源,關系到顯示幀率的問題。下圖中的level 為1 表示復位全志SoC 的LCD 相關模塊以及reset_panel 里面的操作,level 為0 的時候表示
僅僅執(zhí)行reset_panel 里面的操作。
?
圖5-14: ESD 設置信息函數(shù)
?
可以通過cat /sys/class/disp/disp/attr/sys 獲取當前的esd info。
screen 0: de_rate 594000000 hz, ref_fps:60 mgr0: 2560x1600 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] unblank err[0] force_sync[0] dmabuf: cache[0] cache max[0] umap skip[0] overflow[0] capture: dis req[0] runing[0] done[0,0] lcd output(enable) backlight( 50) fps:60.9 esd level(1) freq(300) pos(1) reset(244) 2560x1600 err:0 skip:0 skip T.O:50 irq:73424 vsync:0 vsync_skip:0 BUF en ch[1] lyr[0] z[0] prem[N] fbd[N] a[globl 255] fmt[ 0] fb [2560,1600;2560,1600;2560,1600] crop[ 0, 0,2560,1600] frame[ 0, 0,2560,1600] addr[98100000,00000000,00000000] right[00000000,00000000,00000000] flags[0x00] trd[0,0] depth[ 0] acquire: 0, 25.5 fps release: 0, 25.5 fps display: 0, 25.5 fps
esd level(1) freq(300) pos(1) reset(244)
esd levele 和freq 和pos 的意思請看上面set_esd_info 函數(shù)原型的解釋。
Reset 后面的數(shù)字表示屏復位的次數(shù)(也就是esd 導致屏掛掉之后,并且成功檢測到并復位的次數(shù))。
此功能可能遇到的問題。
打靜電掛了,但是讀出來的值仍然是正確的,此問題無解。
Dsi 讀操作卡住了,卡在中斷里面了。此問題可能和DSI 的lp 模式下的速率有關系,而lp 的速率又和dclk 的頻率有關系。此時可以嘗試修改de_dsi_28.c() 文件
中的dsi_basic_cfg 函數(shù),如下圖所示紅框所示的寄存器值,這個寄存器是Lp 模式時鐘分頻值,一般來說這個值越小,lp 速率越快,嘗試改小看是否還會卡
住。
?
圖5-15: Lp 模式時鐘分頻值
?
6 調(diào)試方法
系統(tǒng)起來之后可以讀取sysfs 一些信息,來協(xié)助調(diào)試。
6.1 加快調(diào)試速度的方法
很明顯,如果你在安卓上調(diào)試LCD 屏會比較不方便,安卓編譯時間和安卓固件都太過巨大,每次修改內(nèi)核后,可能都要經(jīng)過10 幾分鐘都才能驗證,這樣效率就太
低下了,可用采用如下方法:
使用linux 固件而不是安卓固件。SDK 是支持僅僅編譯linux 固件,一般是配置lichee 或者longan 的時候選擇linux,打包的時候,用lichee 或者longan 根目錄
下的build.sh 來打包就行。因為linux 內(nèi)核小得多,編譯更快,更方便調(diào)試。
使用內(nèi)核來調(diào)試LCD 屏。我們知道Uboot 和內(nèi)核都需要添加LCD 驅(qū)動,這樣才能快速顯示logo,但是uboot 并不方便調(diào)試,所以有時候我們需要把uboot 的
顯示驅(qū)動關掉,專心調(diào)試內(nèi)核的LCD 驅(qū)動,調(diào)好之后才移植到uboot,另外這樣做的一個優(yōu)點是,我可以非常方便的修改lcd timing 而不需要重燒固件。就是
利用uboot 命令的fdt 命令修改device tree。 比如說:
fdt set lcd0 lcd_hbp <40>
更多命令見fdt help。
如何關閉uboot 顯示呢,一般是在uboot 源碼路徑下inlcude/configs/平臺.h 中,注釋掉CONFIG_SUNXI_MODULE_DISPLAY 即可,如果是uboot 2018 則是注釋
掉configs/平臺_defconfig 中CONFIG_DISP2_SUNXI。
6.2 查看顯示信息
以下信息是所有信息中最重要的。
cat /sys/class/disp/disp/attr/sys screen 0: de_rate 297000000 hz, ref_fps:60 mgr0: 1280x800 fmt[rgb] cs[0x204] range[full] eotf[0x4] bits[8bits] err[0] force_sync[0] unblank direct_show[false] lcd output backlight( 50) fps:60.9 1280x 800 err:0 skip:31 irq:1942 vsync:0 vsync_skip:0 BUF enable ch[1] lyr[0] z[0] prem[N] a[globl 255] fmt[ 8] fb[1280, 800;1280, 800;1280, 800] crop[ 0, 0,1280, 800] frame[ 0, 0,1280, 800] addr[ 0, 0, 0] flags[0x 0] trd[0,0]
lcd output
表示當前顯示接口是LCD 輸出。
1280x800
表示當前LCD 的分辨率,與board.dts 中l(wèi)cd0 的設置一樣。
ref_fps:60
是根據(jù)你在board.dts的lcd0填的時序算出來的理論值。
fps:60.9
后面的數(shù)值是實時統(tǒng)計的,正常來說應該是在60(期望的fps) 附近,如果差太多則不正常,重新檢查屏時序,和在屏驅(qū)動的初始化序列是否有被調(diào)用到。
irq:1942
這是vsync 中斷的次數(shù),每加1 都代表刷新了一幀,正常來說是一秒60(期望的fps)次,重復cat sys,如果無變化,則異常。
BUF
開頭的表示圖層信息,一行BUF 表示一個圖層,如果一個BUF 都沒有出現(xiàn),那么將是黑屏,不過和屏驅(qū)動本身關系就不大了,應該查看應用層& 框架層。
err:0
這個表示缺數(shù),如果數(shù)字很大且一直變化,屏幕會花甚至全黑,全紅等。
skip:31
這個表示跳幀的數(shù)量,如果這個數(shù)值很大且一直變化,有可能卡頓,如果數(shù)字與irq 后面的數(shù)字一樣,說明每一幀都跳,會黑屏(有背光)。
6.3 查看電源信息
查看axp 某一路電源是否有enable 可以通過下面命令查看。當然這個只是軟件的,實際還是用萬用表量為準。
cat /sys/class/regulator/dump pmu1736_ldoio2 : disabled 0 700000 supply_name: pmu1736_ldoio1 : disabled 0 700000 supply_name: pmu1736_dc1sw : enabled 1 3300000 supply_name: vcc-lcd pmu1736_cpus : enabled 0 900000 supply_name: pmu1736_cldo4 : disabled 0 700000 supply_name: pmu1736_cldo3 : disabled 0 700000 supply_name: pmu1736_cldo2 : enabled 1 3300000 supply_name: vcc-pf pmu1736_cldo1 : disabled 0 700000 supply_name: pmu1736_bldo5 : enabled 2 1800000 supply_name: vcc-cpvin vcc-pc pmu1736_bldo4 : disabled 0 700000 supply_name: pmu1736_bldo3 : disabled 0 700000 supply_name: pmu1736_bldo2 : disabled 0 700000 supply_name: pmu1736_bldo1 : disabled 0 700000 supply_name: pmu1736_aldo5 : enabled 0 2500000 supply_name: pmu1736_aldo4 : enabled 0 3300000 supply_name: pmu1736_aldo3 : enabled 1 1800000 supply_name: avcc pmu1736_aldo2 : enabled 0 1800000 supply_name: pmu1736_aldo1 : disabled 0 700000 supply_name: pmu1736_rtc : enabled 0 1800000 supply_name: pmu1736_dcdc6 : disabled 0 500000 supply_name: pmu1736_dcdc5 : enabled 0 1480000 supply_name: pmu1736_dcdc4 : enabled 1 900000 supply_name: vdd-sys pmu1736_dcdc3 : enabled 0 900000 supply_name: pmu1736_dcdc2 : enabled 0 1160000 supply_name: pmu1736_dcdc1 : enabled 4 3300000 supply_name: vcc-emmc vcc-io vcc-io vcc-io
6.4 查看pwm 信息
pwm 的用處這里是提供背光電源。
cat /sys/kernel/debug/pwm platform/7020c00.s_pwm, 1 PWM device pwm-0 ((null) ): period: 0 ns duty: 0 ns polarity: normal platform/300a000.pwm, 2 PWM devices pwm-0 (lcd ): requested enabled period: 20000 ns duty: 3984 ns polarity: normal pwm-1 ((null) ): period: 0 ns duty: 0 ns polarity: normal
上面的“requested enabled” 表示請求并且使能了,括號里面的lcd 表示是由lcd 申請的。
6.5 查看管腳信息
cat /sys/kernel/debug/pinctrl/pio/pinmux-pins pin 227 (PH3): twi1 (GPIO UNCLAIMED) function io_disabled group PH3 pin 228 (PH4): (MUX UNCLAIMED) (GPIO UNCLAIMED) pin 229 (PH5): (MUX UNCLAIMED) pio:229 pin 230 (PH6): (MUX UNCLAIMED) pio:230 pin 231 (PH7): (MUX UNCLAIMED) pio:231
上面的信息我們知道PH5,PH6 這些IO 被申請為普通GPIO 功能,而PH3 被申請為twi1。
6.6 查看時鐘信息
cat /sys/kernel/debug/clk/clk_summary
這個命令可以看哪個時鐘是否使能,然后頻率是多少。
與顯示相關的是tcon,pll_video,mipi 等等。
cat /sys/kernel/debug/clk/clk_summary | grep tcon cat /sys/kernel/debug/clk/clk_summary | grep pll_video cat /sys/kernel/debug/clk/clk_summary | grep mipi
6.7 查看接口自帶colorbar
顯示是一整條鏈路,中間任何一個環(huán)節(jié)出錯,最終的表現(xiàn)都是顯示異常,圖像顯示異常幾個可能
原因:
圖像本身異常。
圖像經(jīng)過DE(Display Engine)后異常。
圖像經(jīng)過接口模塊后異常。這是我們關注的點。
有一個簡單的方法可以初步判斷,接口模塊(tcon 和dsi 等)可以自己輸出內(nèi)置的一些patten(比如說彩條、灰階圖、棋盤圖等),當接口輸出這些內(nèi)置patten
的時候,如果這時候顯示就異常,這說明了:
LCD 的驅(qū)動或者配置有問題。
LCD 屏由于外部環(huán)境導致顯示異常。
顯示自帶patten 的方式:
在linux-4.9 及其以上版本的內(nèi)核,disp 的sysfs 中有一個attr 可以直接操作顯示:
echo X > /sys/class/disp/disp/attr/colorbar
上面的操作是顯示colorbar,其中的X 可以是0 到8,對應的含義如下圖所示:
?
圖6-1: colorbar
?
如果有多個顯示設備,想讓第二個顯示設備顯示colorbar 的話,那么先:
echo 1 > /sys/class/disp/disp/attr/disp
然后再執(zhí)行上面操作。
如果沒有這個attr 的話,可以直接操作寄存器,也就是操作tcon 寄存器的040 偏移的最低3位。
在linux 下,cd /sys/class/sunxi_dump 然后:
echo 0x06511040 > dump;cat dump
這樣會打印當前tcon 的040 偏移寄存器的值,然后在上面值的基礎上修改最低3 位為上圖的值即可,修改方式示例:
echo 0x06511040 0x800001f1 > write
注意tcon 的基地址不一定是0x06511000,不同平臺不一樣,請參考SoC 文檔獲取tcon 的基地址。
6.8 DE 截屏
顯示出現(xiàn)異常的時候,有可能是下面三個原因:
SoC 端屏接口模塊+LCD 屏出現(xiàn)了問題。
圖像經(jīng)過SoC 端圖像合成模塊(DE)處理后出現(xiàn)了問題。
圖像源本身就有問題。 本節(jié)介紹,確認圖像源本身沒問題的前提下,如何進一步確認是否經(jīng)過DE 處理之后圖像是否有問題。
語法:
echo 屏幕索引> /sys/class/disp/disp/attr/disp echo 路徑/bmp文件名> /sys/class/disp/disp/attr/capture_dump
第一個echo 的作用是確定捕捉哪個顯示的,“屏幕索引” 可選取值是0 或者1。
第二個echo 作用是生成截屏bmp 文件,確?!奥窂健?是可寫的,有剩余空間的。
比如:
echo 0 > /sys/class/disp/disp/attr/disp echo /data/xx.bmp > /sys/class/disp/disp/attr/capture_dump
這樣就會在/data 目錄下生成screen 0 的bmp 截圖,文件名是xx.bmp。
除了bmp 之外,還支持保存raw 數(shù)據(jù),包括RGB 和YUV 顏色空間,它們以后綴來區(qū)分,用法
如下:
# 截取yuv420p顏色空間的raw數(shù)據(jù)。 echo /data/xx.yuv420_p > /sys/class/disp/disp/attr/capture_dump # 截取yuv420_sp_uvuv顏色空間的raw數(shù)據(jù)。 echo /data/xx.yuv420_sp_uvuv > /sys/class/disp/disp/attr/capture_dump # 截取yuv420_sp_vuvu顏色空間的raw數(shù)據(jù)。 echo /data/xx.yuv420_sp_vuvu > /sys/class/disp/disp/attr/capture_dump # 截取yuv420_sp_vuvu顏色空間的raw數(shù)據(jù)。 echo /data/xx.yuv420_sp_vuvu > /sys/class/disp/disp/attr/capture_dump # 截取argb8888顏色空間的raw數(shù)據(jù)。 echo /data/xx.argb8888 > /sys/class/disp/disp/attr/capture_dump # 截取abgr8888顏色空間的raw數(shù)據(jù)。 echo /data/xx.abgr8888 > /sys/class/disp/disp/attr/capture_dump # 截取rgb888顏色空間的raw數(shù)據(jù)。 echo /data/xx.rgb888 > /sys/class/disp/disp/attr/capture_dump # 截取bgr888顏色空間的raw數(shù)據(jù)。 echo /data/xx.bgr888 > /sys/class/disp/disp/attr/capture_dump # 截取rgba8888顏色空間的raw數(shù)據(jù)。 echo /data/xx.rgba8888 > /sys/class/disp/disp/attr/capture_dump # 截取bgra8888顏色空間的raw數(shù)據(jù)。 echo /data/xx.bgra8888 > /sys/class/disp/disp/attr/capture_dump
注意:這個功能只有l(wèi)inux-4.9 以及后續(xù)的內(nèi)核才支持這個功能。
7 FAQ
7.1 屏顯示異常
總結(jié)過往經(jīng)驗,絕大部分屏顯異常都是由于上下電時序和timing 不合理導致。
請看屏時序參數(shù)說明和屏驅(qū)動分解。
7.2 黑屏-無背光
問題表現(xiàn):完全黑屏,背光也沒有。
有兩種可能:
屏驅(qū)動添加失敗。驅(qū)動沒有加載屏驅(qū)動,導致背光電源相關函數(shù)沒有運行到。這個你可以通過調(diào)試方法定位下。
pwm 配置和背光電路的問題,pwm 的信息可以看pwm 信息和背光相關參數(shù),另外就是直接測量下硬件測量下相關管腳和電壓。
7.3 黑屏-有背光
黑屏但是有背光,可能有多種原因?qū)е?,請依次按以下步驟檢查:
沒送圖層。如果應用沒有送任何圖層那么表現(xiàn)的現(xiàn)象就是黑屏,通過查看顯示信息一小節(jié)可以確定有沒有送圖層。如果確定沒有圖層,可以通過查看接口自帶
colorbar,確認屏能否正常顯示。
SoC 端的顯示接口模塊沒有供電。SoC 端模塊沒有供電自然無法傳輸視頻信號到屏上。一般SoC 端模塊供電的axp 名字叫做vcc-lcd,vcc-dsi,vcc33-lcd,
vcc18-dsi 等。
復位腳沒有復位。如果有復位腳,請確保硬件連接正確,確保復位腳的復位操作有放到屏驅(qū)動中。
board.dts 中l(wèi)cd0 有嚴重錯誤。第一個是lcd 的timing 太離譜,請嚴格按照屏手冊中的提示來寫!參考屏時序參數(shù)說明。第二個就是,接口類型搞錯,比如接
的DSI 屏,配置卻寫成LVDS 的。
屏的初始化命令不對。包括各個步驟先后順序,延時等,這個時候請找屏廠確認初始化命令。
7.4 閃屏
分為幾種:
屏的整體在閃。
這個最大可能是背光電路的電壓不穩(wěn)定,檢查電壓。
屏部分在閃,而且是概率性。
board.dts 中的時序填寫不合理。
屏上由一個矩形區(qū)域在閃。
屏極化導致,需要關機放一邊再開機則不會。
7.5 條形波紋
有些LCD 屏的像素格式是18bit 色深(RGB666)或16bit 色深(RGB565),建議打開FRM功能,通過dither 的方式彌補色深,使顯示達到24bit 色深(RGB888)
的效果。如下圖所示,上圖是色深為RGB66 的LCD 屏顯示,下圖是打開dither 后的顯示,打開dither 后色彩漸變的地方過度平滑。
設置[lcd0] 的lcd_frm 屬性可以改善這種現(xiàn)象。請看lcd_frm解釋。
7.6 背光太亮或者太暗
請看背光相關參數(shù)。
7.7 重啟斷電測試屏異常
花屏的第一個原因是fps 過高,超過屏的限制:
FPS 異常是一件非常嚴重的事情,關系到整個操作系統(tǒng)的穩(wěn)定,如果fps 過高會造成系統(tǒng)帶寬增加,送顯流程異常,fps 過高還會造成LCD 屏花屏不穩(wěn)定,容易造
成LCD 屏損壞,F(xiàn)PS 過低則造成用戶體驗過差。
通過查看查看顯示信息一節(jié),可以得知現(xiàn)在的實時統(tǒng)計的fps。
如果fps 離正常值差很多,首先檢查board.dts 中[lcd0] 節(jié)點,所填信息必須滿足下面公式。
lcd_dclk_freq*num_of_pixel_clk=lcd_ht*lcd_vt*fps /1e9
其中,num_of_pixel_clk 通常為1,表示發(fā)送一個像素所需要的時鐘周期為1 一個,低分辨率的MCU 和串行接口通常需要2 到3 個時鐘周期才能發(fā)送完一個像素。
如果上面填寫沒有錯,通過查看查看時鐘信息一節(jié)可以確認下幾個主要時鐘的頻率信息,把這些信息和board.dts 發(fā)給維護者進一步分析。
7.8 RGB 接口或者I8080 接口顯示抖動有花紋
改大時鐘管腳的管腳驅(qū)動能力 參考lcd_gpio_0一小節(jié)和pinctrl-0 和pinctrl-1,修改驅(qū)動能力,改大。
還有另外一種寫法,比如原來是:
lcdclk = port:PD18<2><0><2>
可以改成:
lcdclk = port:PD18<2><0><3>
修改時鐘相位,也就是修改lcd_hv_clk_phase。由于發(fā)送端和接收端時鐘相位的不同導致接收端解錯若干位。
7.9 LCD 屏出現(xiàn)極化和殘影
何謂液晶極化現(xiàn)象:實際上就是液晶電介質(zhì)極化。就是在外界電場作用下,電介質(zhì)內(nèi)部沿電場方向產(chǎn)生感應偶極矩,在電解質(zhì)表明出現(xiàn)極化電荷的現(xiàn)象叫做電介質(zhì)
的極化。
通俗的講就是在液晶面板施加一定電壓后,會聚集大量電荷,當電壓消失的時候,這些聚集的電荷也要釋放,但由于介電效應,這些聚集的電荷不會立刻釋放消
失,這些不會馬上消失的惰性電荷造成了液晶的DC 殘留從而形成了極化現(xiàn)象。
幾種常見的液晶極化現(xiàn)象
液晶長期靜止某個畫面的時候,切換到灰階畫面的時候出現(xiàn)屏閃,屏閃一段時間后消失。這種現(xiàn)象屬于殘留電荷放電的過程。
液晶長期靜止某個畫面的時候,出現(xiàn)四周發(fā)黑中間發(fā)白的現(xiàn)象,業(yè)內(nèi)稱為黑白電視框異常。
非法關機的時候,重新上電會出現(xiàn)屏閃,屏閃一定時間后消失。與第一種原因相同。
殘影現(xiàn)象:當液晶靜止在一個畫面比較久的情況下,切換其他畫面出現(xiàn)的鏡像殘留。殘影的本質(zhì)來說是液晶DC 殘留電荷導致,某種意義來說也屬于液晶極化
現(xiàn)象。
針對液晶屏出現(xiàn)極化和殘影現(xiàn)象,有如下對策。
調(diào)整vcom 電壓大小。 VCOM 是液晶分子偏轉(zhuǎn)的參考電壓,要求要穩(wěn)定,對液晶顯示有直接影響,具體的屏不同的話也是不同的。電壓的具體值是根據(jù)輸入的數(shù)據(jù)以及Vcom 電壓大
小來確定的,用來顯示各種不同灰階,也就是實現(xiàn)彩色顯示GAMMA。Gamma 電壓是用來控制顯示器的灰階的,一般情況下分為G0~G14,不同的Gamma
電壓與Vcom 電壓之間的壓差造成液晶旋轉(zhuǎn)角度不同從而形成亮度的差異,Vcom 電壓最好的狀況是位于G0 和G14 的中間值,這樣液晶屏的閃爍狀況會最
好。
調(diào)節(jié)vcom 電壓的方式,如果屏管腳有vcom 管腳,直接調(diào)整相關電路,如果屏driver IC 提供寄存器接口,可以通過寄存器接口來調(diào)整大小。
嚴格按照屏規(guī)定的上下電時序來對屏進行開關屏。許多極化殘影現(xiàn)象并非長時間顯示靜止顯示某個畫面導致的,而是由于關機或者關屏時沒有嚴格按照下電時
序?qū)е碌?,比如該關的電沒關,或者延時不夠。
8 總結(jié)
調(diào)試LCD 顯示屏實際上就是調(diào)試發(fā)送端芯片(全志SoC)和接收端芯片(LCD 屏上的driver IC)的一個過程:
添加屏驅(qū)動請看添加屏驅(qū)動步驟和屏驅(qū)動說明。
仔細閱讀屏手冊以及driver IC 手冊。
仔細閱讀硬件參數(shù)說明。
確保LCD 所需要的各路電源管腳正常。
-
lcd
+關注
關注
34文章
4426瀏覽量
167494 -
Linux
+關注
關注
87文章
11304瀏覽量
209502 -
調(diào)試
+關注
關注
7文章
578瀏覽量
33943 -
Display
+關注
關注
1文章
53瀏覽量
24727 -
Tina
+關注
關注
2文章
45瀏覽量
16983
發(fā)布評論請先 登錄
相關推薦
評論