參考:
http://blog.csdn.net/sunweizhong1024/article/details/8447915
platform_driver_register(&mtkfb_driver)
probe
strstr(saved_command_line, "fps="); //得到UBOOT傳過來的參數
mtkfb_find_lcm_driver :hj101na02a_lcm_drv
disp_drv_get_lcm_driver
lcm->set_util_funcs(&lcm_utils); //設置LCD操作函數
lcm->get_params(lcm_params); //得到LCD的一些硬件參數
disp_drv_init_ctrl_if //如果是DBI(mcu 屏)
//LCM_CTRL_SERIAL_DBI
LCD_Init()
LCD_ConfigSerialIF
//LCM_CTRL_PARALLEL_DBI
LCD_Init()
LCD_ConfigParallelIF
LCD_SelectWriteIF //選擇是串口還是並口
LCD_ConfigIfFormat //配置接口的數據類型
to_lcd_if_width //數據寬度,DBI
disp_drv_set_driving_current //設置接口的電流
LCD_Init_IO_pad //初始化GPIO
disp_drv_init_context
DISP_GetDriverDBI :DBI_DISP_DRV 操作函數
DISP_GetDriverDPI :DPI_DISP_DRV
DISP_GetDriverDSI :DSI_DISP_DRV
//得到LCD的一些參數
DISP_GetScreenWidth
。。。。。。
kthread_create(esd_recovery_kthread, NULL, "esd_recovery_kthread"); //esd檢測
得到指點屏幕的信息:
DISPCHECK("[POWER]lcm suspend[begin]\n");while (1) {msleep(2000);/* esd check every 2s */ 兩秒就會檢測一次ret = wait_event_interruptible(esd_check_task_wq, atomic_read(&esd_check_task_wakeup));兩種檢測模式1./* / Esd Check : EXT TE */ 配置dsi.customization_esd_check_enable == 02./* / Esd Check : Read from lcm */ 配置dsi.customization_esd_check_enable == 1/* 0.create esd check cmdq */cmdqRecCreate(CMDQ_SCENARIO_DISP_ESD_CHECK, &(pgc->cmdq_handle_config_esd));dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_ALLC_SLOT);MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 2);/* 1.use cmdq to read from lcm */if (primary_display_is_video_mode())ret = _esd_check_config_handle_vdo();/* 2.check data(*cpu check now) */ret = dpmgr_path_build_cmdq(pgc->dpmgr_handle, pgc->cmdq_handle_config_esd, CMDQ_ESD_CHECK_CMP);MMProfileLogEx(ddp_mmp_get_events()->esd_rdlcm, MMProfileFlagPulse, 0, 4);/* 3.destroy esd config thread */cmdqRecDestroy(pgc->cmdq_handle_config_esd);}if (ret == 1) { //如果發現LCM被打死,需要重啟
primary_display_esd_recovery();
DISPCHECK("[POWER]lcm suspend[end]\n");
三、Display
1.lcm 相關概念
1.1) MIPI接口:
一共有三種接口:DBI(也做CPU或MCU接口)、DPI(也叫RGB接口)、DSI.
在使用DSI接口時,目前75/77都只支持到2條data lane,加上一條clock lane.
使用DPI接口時,根據LCM IC支持的情況,可以選擇16bus、18bus傳輸RGB格式文件,在GPIO部分分為R、G、B分別對應 8個GPIO(GPIO20~46期間),客戶采用DPI接口需要根據選擇的bus方式進行配置,推薦RGB端口全部配置為對應的復選模 式,並設置為OUT輸出。
采用DBI接口,有兩種模式選擇,一種是選擇共用DPI的bus腳 +DPI控制線,另一種是共用nand data pin+CPU 控制線。
1.2) DSI接口有兩種sync 模式:
video mode和command mode,其中video mode是BB端一直刷數據到LCM,cmd mode是在有數 據更新時刷數據到LCM GRAM中) 和DSI command mode相比,video mode 是需要實時傳輸image data到lcm端,DSI 的refresh rate決定了lcm的refresh rate。
1.3)EDS機制:
92平台LCM driver中定義了esd_check和esd_recovery的接口,但ESD線程不工作。
目前在MT6589之前平台,video mode的ESD實現有三種模式,分別是:ext TE(外部TE信號檢測)、int TE(內部TE信號檢 測)、non cout clk不同ESD方式需要注意的方面
a) int TE和ext TE的檢測,都不需要實現lcm_esd_check函數,而需要實現lcm_esd_recover函數。
non cont clk則不需要實現lcm_esd_check函數和lcm_esd_recover函數,而只需要在上面 params中配置為TRUE即可
b) ext TE的實現,需要LCM外接TE pin到BB端,同時在inital code中配置寄存器打開TE信號的輸出 (一般是寫0x35寄存器,具體需要和LCM IC FAE確認)
1.4)HDMI/MHL:
目前我司HDMI/MHL的相關code和driver都是有集成在codebase中的,要使用的話,只需要只需要在對應的 ProjectConfig.mk文件中開啟,並且在dct中配置好對應的引腳定義即可。
以下以MHL為例:
ProjectConfig中配置:
MTK_HDMI_SUPPORT=yes #表明開啟HDMI/MHL功能
CUSTOM_KERNEL_HDMI=Sii8338 #表明配置為MHL的IC型號
1.5)TE 信號:
大部分TE問題是由於沒有正常開啟TE所導致,首先檢查TE是否開啟。
89平台使用內部TE,lcm driver中只需要在init過程中打開LCM TE即可,一般是寫0x35寄存器,部分IC需要額外寫其他 寄存器,可與FAE確認。
檢查TE是否正常開啟,如果是工版,則可使用如下方式打開fps的log,查看TE信息:
adb shell
cd sys/kernel/debug
echo fps:on>mtkfb
然后查看mtklog, 搜索“FPS”,若看到等待TE時間為0, 表示TE未正常開啟,需要與LCM IC的FAE進一步確認開啟流程 。
若TE已經成功開啟,依然有Teering現象,可從如下方面思考分析。
1)是否使用了豎屏橫用,導致對GRAM的讀寫方向不一致,一般會出現斜線切屏現象。
2)是否clock速度過低,FPS低於LCM自刷新率的1/2?
3)是否clock速率過快,超過LCM的自刷新率,導致寫GRAM時可能從后面趕上讀,導致Teering發生。
4)fmark周期與CS周期
出現TE現象的根本原因是兩邊速度不一致,具體是LCM的刷新速度要快於主控送數據的速度,兩者的速度要符合一定的范圍才行。只要保證CS的周期在兩個TE周期之間即可,也就是CS的寫頻率不能低於TE讀頻率的二分之一,Tearing出現的根本條件是讀寫有交叉。通常都是寫Gram速度(WR)慢於lcd刷屏速度(TE)[x2] ,只要刷屏的位置不超過寫Gram位置就不會有切屏現象。[x3]
舉個實例:比如CS差不多就比兩個TE周期小一點,要刷兩楨數據,首先第一楨刷屏開始刷屏了,表示讀GRAM開始,它的速度比較快,它讀的是老舊數據;緊接着主控開始寫GRAM,大概寫到GRAM的快一半時,這時候已經刷完一楨,然后開始刷第二楨,即又從GRAM的最上方開始讀並刷屏,此時讀出來的才是剛寫入的新數據,在寫完GRAM之前,讀的步驟永遠跟不上寫的步驟,就不會出現tearing。
如果CS比兩個TE周期大,假設相當於三個TE周期,那么只有在第三個TE讀周期時,顯示的數據才是寫好的GRAM的數據;第一個TE讀的是老舊的數據,第二個TE周期由於GRAM還沒有寫完,但讀步驟趕上寫GRAM步驟了,導致顯式一部分是舊的一部分是新的,所以出現TE。此即本質。
5) TE類型
TE顯示使能時,必須保證CPU的LCD TE使能和LCM驅動的TE功能都打開。LCM的TM使能有兩
1.6)HS/LP:
HS:high speed , clock切為HS模式,高速模式。
LP:low power,低電平
有些LCM在開機的時候,如果使用LP下發init code,可能會不准確或者導致花屏等問題,這時候需要使用HS mode發送init code,比如三星的某款OLED(D53D6EA8061V-Amoled)。
continuous clock/no-continuous clock模式
1.6)dithering:
抖動顯示技術:
MT6572 如所用lcm不支持RGB888 color format, 顯示效果差需要開啟dithering的。
1.7)其他概念:
AAL:BB端CABC(即AAL),為1種方式控制背光
continuous clock/Non-continuous clock : Switch clock lane from HS to LP
2.LCM時鍾配置
MT6582 LCM Driver中配置:params->dsi.PLL_CLOCK = 234;
計算方法:
展頻開關:
如果MIPI Clock對RF/WCN產生干擾,並且在嘗試尋找相應的頻點依然無法解除 EMI,可以嘗試做Frequency Hopping;
82平台默認打開展頻開關,不同於72/89平台,將展頻的開關以及展頻幅度的選擇 ,都開放到LCM Driver中,以如下為例:
params->dsi.ssc_range =4;
params->dsi.ssc_disable = 0;
代表:展頻打開,ssc_range = 4%
3.AAL與CABC背光選擇(兩種方式控制背光):
參考[FAQ05966]
【BB端CABC(即AAL)】
- 打開功能,向MTK申請patch,並在ProjectConfig.mk中打開MTK_AAL_SUPPORT = yes


4. 調整Display 消耗的BW(bandwidth帶寬)方法:
•LCM driver建議如下:
–MIPI的clock 盡量低,建議60fps
–For DSI Video mode,建議不要使用burst mode(比較能吃BW)
params->dsi.mode = BURST_VDO_MODE;
–Video mode的時序,blank 區間(如VBP/VFP/HBP/HFP)盡量少(當然也需要滿足LCM module的spec)
5.DSI video mode相關參數配置方法:
對應配置文件:\alps\mediatek\custom\common\kernel\lcm\xxxx.c中lcm_get_params()函數
1,data lane每幀回LP11(Low Power state,dp,dn都為高電平),clk一直HS( High Speed),對應配置:
params->dsi.cont_clock=1;
params->dsi.clk_lp_per_line_enable=0;
2,data lane每一行回一次LP11,clk lane每一幀回一次LP,對應配置:
params->dsi.cont_clock=0;
params->dsi.clk_lp_per_line_enable=0;
3,data lane和clk lane都是每行回一次LP11,對應配置:
params->dsi.cont_clock=0;
params->dsi.clk_lp_per_line_enable=1;
6.LCM CABC 配置
參考[FAQ12413]
7.MHL 卡頓問題
8.ESD機制各個平台的差異:
對於89/72/82等新平台,Display架構做了調整,ESD的實現方式與之前的75/77等平台稍有差異。對於之前75/77平台,可以參考FAQ03210及FAQ05163.
新舊架構下,主要是DSI Video Mode下ESD方式不一樣。
之前的架構下Video Mode的屏采用檢測外部TE或者內部TE來做ESD Check,因此需要在lcm driver中配置相應的參數。
新架構下不支持外部TE或內部TE來做ESD check, lcm_get_params中關於esd的參數不用再配置。
如lcm_int_te_monitor、lcm_int_te_period、lcm_ext_te_monitor等無需配置。
[SOLUTION]
新的Display架構下,DSI Video Mode及DSI Command Mode都采用讀寄存器的方式來進行esd check. 因此都只需要在lcm driver中實現esd_check和esd_recover函數即可。
對於具體讀取哪些寄存器來進行esd check,需要與屏廠確認。
ESD實現后如果出現每兩秒閃屏的問題,可以按如下流程處理:
1. 首先檢查esd check中是否添了過多的log信息或者有delay操作,建議先去掉所有log測試。
2. 如果依然出現每兩秒閃屏,可參考FAQ05680和FAQ05681進行處理。
9.DBI/DPI接口的GPIO的配置情況
DBI:DBI接口分為串行和並行兩種。由lcm_params->ctrl這個參數控制。
LCM_CTRL_SERIAL_DBI/LCM_CTRL_PARALLEL_DBI
1.)如果是serial類型的,是通過MT6572 datasheet里面的0x14012028 DBI_SCNF (DBI Serial Interface Configuration Register)這個寄存器來config串行接口。比如使用LSDI還是LSDA,LSCK上升沿還是下降沿發送數據 ,LSCK在沒有數據的時候是LOW/HIGH.
配置幾個GPIO pin:LSCE0B(相當於數據使能信號,低電平有效), LSCK, LSDA/LSDI(傳送command時用),DBI[XX:0](傳 送data時用)
CSS,CSH:chip select setup time/chip select hold time
(這兩個時間之內是不會傳數據的,Invalid data)
2.)如果是Parallel類型的,
配置幾個GPIO pin:LPCE0B(相當於CS信號,低電平有效), LPA0(RS信號,MTK平台上面和CS信號是同步的), LCD CLK,LPWRB/LPRDB(類似數據使能信號)和DBI[XX:0](復用DPI的data pin,傳送data和command時用)
寫的時候用LPWRB,讀的時候用LPRDB
有C2WS和C2WH兩個變量:chip selection to write setup time和chip selection to write hold time
同理C2RS和C2RH.
硬件連接:
DBI Parallel類型:BB端需要打開LRDB、LWRB、LPA0 pin腳復用功能,並連接到LCM的RD、WR、RS
DBI serial類型: BB端需要打開LSCE0B、LSCK、LSDA/LSDI pin腳復用功能, 並連接到LCM的CSX, SCL, SDA/DOUT/DIN
lcm Driver里面變量write wait state time,是處於wait狀態的時間。比如大於等於C2WS,參考MT6572 datasheet PAGE1659原理圖
note:89和72的DBI的clock都是不可調整的,都是130Mhz.
但是如果需要調整DBI的FPS的話,可以調整C2WS/C2WH/WST,分別對應write_setup/write_hold/write_wait
DPI:
使用DPI接口時,根據LCM IC支持的情況,可以選擇16bus、18bus傳輸RGB格式文件,在GPIO部分分為R、G、B分別對應 8個GPIO(GPIO20~46期間),客戶采用DPI接口需要根據選擇的bus方式進行配置,推薦RGB端口全部配置為對應的復選模式,並設置為 OUT輸出。
同時DPI的接口需要BB端打開DPIHSYNC、DPIVSYNC、DPIDE、DPICK復用功能,並分別連接到對應的LCM控制端
另注:
其實DPI和DBI一樣,都是可以通過lcm_params->ctrl這個變量來控制是使用Parallel還是serial還是GPIO的類型來下 command。
但是一般DPI都會選擇使用LCM_CTRL_SERIAL_DBI這個類型,因為DPI的屏,DB[17..0]只是會用來做數據傳輸,控制線是 會通過LSDA/LSDI傳輸。
10.LCM Porting時如何配置Clock
clock配置方法:
lcm driver中配置clock有不同的方式,曾經使用過的配置方法有如下幾種:
Type1: 配置倍頻與分頻參數:dsi.pll_div1(倍頻), dsi.pll_div2(分頻)--- (適用於75/77等之前的平台)
Type2: 配置倍頻與分頻參數:dsi.pll_fbk_div(倍頻), dsi.pll_div1 & dsi.pll_div2 (分頻)---(適用於89/72等前 期版本)
Type3: 直接配置clock lane頻率:dsi.PLL_CLOCK(前期配置成枚舉值,后期將直接配置成對應的頻率常數值)----(適 用於89/72/82...)
11.如何使用PMIC的LDO方式供給LCM端 1.8/2.8v的電壓
參考[FAQ10038]
1. 如何在開機階段使用PMIC的LDO方式供給LCM端1.8/2.8v的電壓?
2. 如何在suspend/resume的時候,斷掉/供給LCM端1.8/2.8v的電壓?
1. )在開機的時候,建議在preloader或者LK階段就通過PMIC的LDO方式來給LCM端上電,
比如可以在alps\mediatek\platform\mt6589\preloader\src\drivers\mtk_pmic_6320.c文件里面的 pmic6320_init函數中做上電1.8/2.8v的操作。
AOSP版本mtk_pmic_6320.c的路徑 :alps/bootable/bootloader/preloader/platform/mt6572/src/drivers/mtk_pmic_6320.c
下面是在LK階段的上電/掉電方法:
使用upmu_common.c文件里面API來分別控制每一個LDO_VGPX.
比如:
upmu_set_rg_vgp6_vosel用來控制上電的電壓值;
upmu_set_rg_vgp6_en用來控制enable VGP6這個pin
2. )因為在suspend/resume的時候,kernel都是跑起來的,所以上電/掉電 1.8/2.8v的操作都應該放在kernel里面。
下面是在kernel里面的上電/掉電方法,在kernel里面有統一的上電/掉電的接口函數: 上電接口函數:hwPowerOn 掉電接口函數hwPowerDown
以下以PMIC6320的VGP6為例。
請在您要上電的文件#include <mach/mt_pm_ldo.h> 上電請調用 hwPowerOn,掉電請調用hwPowerDown
hwPowerOn(MT65XX_POWER_LDO_VGP6, VOL_2800, "ldo_test");
bool hwPowerDown(MT65XX_POWER_LDO_VGP6, "ldo_test");
12.如何拉低並保持LCM RESET PIN腳為低 電平
平台默認RESET PIN腳輸出為高平的,如果一定需要拉低,可以配置RESET PIN腳為GPIO模式,再通過GPIO方式拉低。
使用mediatek/dct目錄下的DCT工具,使用其打開custom/XXX/kernel/dct/dct目錄下的DWS文件,將GPIO131配置成 0:GPIO131.
對GPIO PIN腳的控制有如下一些方法:
lcm_util.set_gpio_mode(GPIO131, GPIO_MODE_00);
lcm_util.set_gpio_dir(GPIO131,GPIO_DIR_OUT);
lcm_util.set_gpio_out(GPIO131,0);
13.如何調節MIPI接口驅動能力
在使用DBI、DPI的MIPI接口時,可以在lcm_get_params函數中設置參數 io_driving_current的值來配置IO的驅動電流(6589上面不支持)
DSI的MIPI接口,不支持IO驅動電路的調節 ,其可選值的大小可以在lcm_drv.h看到定義。
其可選值的大小可以在lcm_drv.h看到定義:
typedef enum{
}LCM_DRIVING_CURRENT;
該值的會在lcd_drv.c文件中寫到寄存器中:
LCD_STATUS LCD_Set_DrivingCurrent();
14.如何通過檢測外部TE實現esd check的 功能
在72/82/92的JB/KK版本,我們都是通過讀取esd寄存器的方式實現esd check,但是由於esd check的時候會切換到cmd mode去讀,所以屏的玻璃存在最大1幀時間的等待,如果這個vdo
mode屏的玻璃延時等待時間較小(小於切換的時間),就會出現閃屏,所以不能使用讀esd寄存器 的方式做esd check。
如果這個屏有 external TE管腳的話,可以通過檢測ext.TE的方式來做esd check,具體原理 為:把原來的esd流程全部關閉,啟動一個新的線程,循環檢測外部TE中斷,如果檢測失敗,就
recovery。
新的esd流程里面需要做三件事:
1) 物理連接一根外部TE pin,然后在dws文件里面配置一個GPIO口為DSI_TE模式。
2) 在DSI初始化的時候,注冊該ext.TE的irq處理函數,收到中斷則設置irq_flag為TRUE。
3) 啟動線程定時去wait flag==1,如果超時,則做esd recovery。
15.如何配置DSI時鍾頻率
1、)DSI vdo mode下的數據速率data_rate的大致計算公式為: Data rate= (Height+VSA+VBP+VFP)*(Width+HSA+HBP+HFP)* total_bit_per_pixel*frame_per_second/total_lane_num
2、)DSI cmd mode下的數據速率data_rate的大致計算公式為: Data rate= width*height*1.2* total_bit_per_pixel*frame_per_second/total_lane_num
參數注釋:
data_rate : 表示的是數據速率
width,height :屏幕分辨率
VSA VBP VFP :DSI vdo mode的vertical porch配置參數
HSA HBP HFP :DSI vdo mode的horizontal porch配置參數
total_bit_per_pixel :表示的是一個pixel需要用幾個bit來表示,比如RGB565的話 就是16個bit
frame_per_second :就是我們通常看到的fps,叫做幀率,表示每秒發送多少個幀 ,一般是60幀每秒
total_lane_num :表示的是data lane的對數。
3、)DSI采用的是雙邊采樣,則clk等於數據速率的一半,因此: clk=data_rate/2
有兩種配置clk的方式,第一種方式配置四個參數得到,第二種配置方式直接配置頻 率,建議采用第二種。
第一種方式,通過div分頻倍頻實現,各個平台略有差異,但是原理基本一致,請參 考porting guide,如下舉例89平台:
params->dsi.pll_div1 = ; //配置范圍為0,1,2,3的時候,對應的 div1_real等於1,2,4,4
params->dsi.pll_div2 = ; //配置范圍為0,1,2,3的時候,對應的 div2_real等於1,2,4,4
params->dsi.fbk_div = ; //范圍 0..63
params->dsi.fbk_sel = ; //配置范圍為0,1,2,3的時候,對應的 fbk_sel_real等於1,2,4,4
輸出頻率 =26MHz*(fbk_div+1)*(2*fbk_sel_real)/(div1_real*div2_real)
第二種方式,直接配置clk大小:
params->dsi.PLL_CLOCK = LCM_DSI_6589_PLL_CLOCK_234;//這里舉例89平台,使用 一個宏,表示配置的clk等於234MHz。但是在89之后的平台,使用直接配置一個頻率
數字的方式,比如params->dsi.PLL_CLOCK = 234,表示234MHZ)
4、在lcm porting過程中,這些參數都定義在lcm_drv.h文件中的LCM_DSI_PARAMS結 構體中,隨着平台的發展,或許有所不同,但是基本原理都是一致的,如何配置clk的大小,請先根據自己的幀率、像素格式、porch值、屏的分辨率、 data lane對數等計算出data_rate,然后計算出clk。
16.背光模式設置成 T65XX_LED_MODE_CUST_BLS_PWM,如何修改PWM的工作頻率
前提:cust_leds.c文件里面使用的背光模式是MT65XX_LED_MODE_CUST_BLS_PWM
MT6582版本工作頻率計算公式如下:
PWM工作頻率計算公式:26MHz (clock freq.) / (PWM_CLKDIV+1) / 1024 (period) 26 KHz
所以需要修改PWM的工作頻率,可以通過修改PWM_CLKDIV,clock freq,或者period的值來達到修 改PWM的工作頻率的效果。
以下的三種方法可以任選1~2種來達到想要的PWM工作頻率:
1. 修改分頻參數方法,修改config_data里面的第二個參數:
{"lcd-backlight", MT65XX_LED_MODE_CUST_BLS_PWM, (int)disp_bls_set_backlight,{0, 1, 0, 0, 0}} //設置div=1
2. 修改clock freq:
在alps\mediatek\platform\mt6582\kernel\drivers\dispsys\ddp_bls.c文件的 disp_bls_init和disp_bls_config函數中設置CLK_CFG_1這個寄存器的值,來選擇合適的時鍾源,加入如下代碼:
mt65xx_reg_sync_writel(DRV_Reg32(CLK_CFG_1) | (0x00000003), CLK_CFG_1); //設置156 MHz的時鍾源