來公司上班現在已經整整一個月了,蔽人不才,能力有限,學習進度緩慢,不過也是有一點點的收穫與心得,在這裏寫出來與大家分享,養成良好的記錄習慣也免得後忘記。
不囉嗦了,開入正題。來公司一個月左右的時間,主要接觸了高通android4.0和android2.3的LCD驅動,當然在bootloader下LCD的驅動我也調試的。
(1) kernel
先來說一下kernel裏LCD的移植,之前從來沒有接觸過LINUX裏LCD的驅動,所以剛一開始我竟然連MIPI接口、LCDC接口這些最基本的都不知道,鄙視一下我自己,呵呵。感覺android2.3和android4.0在kernel裏LCD驅動上的區別不是特別大。只是android2.3裏多了一個late_display.c這個文件,背光和MDP的開關以及屏的初始化都是在這個文件裏調用的。
因爲高通給的codebase本身包含有一些LCD芯片的驅動,我在2.3上用的是MIPI接口的,是根據truly的例子來做的。在2.3上我們使用的是MIPI CMD模式,從truly的例子移植的時候代碼的大體結構不需要改動,一般只是需要針對要更改的屏的文檔作一些參數與配置的修改就可以了。我是照着truly的在/kernel/drivers/video/msm下創建mipi_hx8369a.c和Mipi_hx8369a_cmd_wvga_pt.c這兩個文件,從truly的例子中把內容拷過來,把名字全改成hx8369a,的mipi_hx8369a.c裏面,主要就是GPIO_HX8369A_LCD_RESET(對應GPIO_TRULY_LCD_RESET)的宏,根據原理圖來定義正確的RESET管腳,然後還有mipi_hx8369a_lcd_reset()裏LCD初始化之前reset的時序要根據lcd芯片的spec來,初始化之前的reset對lcd非常重要;最後就是根據FAE給的初始化指令填好初始化數組。
在Mipi_hx8369a_cmd_wvga_pt.c文件裏有一些要傳到frame_buffer中去的一些參數,這些參數與所選用的顯示屏有關,在這裏把最主要的一些列出來:
pinfo.xres = 480; // LCD的x方向寬度
pinfo.yres = 800; // LCD的y方向高度
pinfo.type = MIPI_CMD_PANEL; // LCD接口是哪種類型,如MIPI_VIDEO_PANEL,LCDC_PANEL
pinfo.pdest = DISPLAY_1;// 應該是系統中的第幾個屏(我自己猜測的)
pinfo.bpp = 24;//每個像素的bit位數,即是多少位色
//下面幾個porch值可以從FAE要到
pinfo.lcdc.h_back_porch = 16;
pinfo.lcdc.h_front_porch = 16;
pinfo.lcdc.h_pulse_width = 16;
pinfo.lcdc.v_back_porch = 4;
pinfo.lcdc.v_front_porch = 4;
pinfo.lcdc.v_pulse_width = 4;
pinfo.bl_max = 32; //背光的最大和最小等級
pinfo.bl_min = 1;
pinfo.fb_num = 2;// 顯存的個數
pinfo.clk_rate = 349000000;//LCD的p_clock時種頻率,要與Modem裏的值對應起來
pinfo.mipi.mode = DSI_CMD_MODE;
//mipi接口的模式
pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888; //RGB的格式
pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB; //RGB的排序
pinfo.mipi.data_lane0 = TRUE; //是否使用MIPI的第一個通道
pinfo.mipi.data_lane1 = TRUE; //是否使用MIPI的第二個通道
其它的一些參數我還沒弄清是什麼意思,不明白就照着別的例子抄來吧。
由於android2.3裏有一個late_display.c的函數,這個函數用來控制背光、MDP的開關以及打開屏的時候調用mipi_hx8369a.c和Mipi_hx8369a_cmd_wvga_pt.c中的初始化函數mipi_hx8369a_lcd_late_init()和mipi_cmd_hx8369a_wvga_pt_late_init()。所以late_display.c裏把變量gpio_backlight_en的值改爲當前使用的背光控制管腳。函數mipi_hx8369a_lcd_late_init()和mipi_cmd_hx8369a_wvga_pt_late_init()是在late_display_ioctl()裏調用,在上層打開LCD設備的時候會來設用這兩個函數來初始化LCD設備。
下面就是要改board文件了,在board文件裏會給LCD分配顯存,這裏會有一個宏MSM_FB_SIZE,通過計算後填一個有餘量的值便好。然後就是在board文件裏添加設備以及設備相關的一些資源,也可以參考別的芯片的例子來。定義
static struct msm_panel_common_pdata mipi_pdata = {
.gpio = GPIO_BACKLIGHT_EN,
};
這裏定義了控制背光的GPIO管腳,如果背光控制管腳使用的是PMIC的一個GPIO來控制,使用的方法也不一樣,在下一篇4.0的LCD移植中會寫這種方式。還要定義一個platform_device,static struct platform_device mipi_dsi_panel_device = {
.name = "mipi_hx8369a",
.id = 0,
.dev = {
.platform_data = &mipi_pdata,
}
};
這裏name要與mipi_hx8369a.c裏的platform_driver裏的名字一樣,id要選擇0,因爲mipi_hx8369a.c裏還會分配一個platform_device,它的name和這個一樣,所以mipi_hx8369a.c裏的probe函數會被調用兩次,第一次與board裏的platform_devices匹配,目的是爲了將背光的管腳號傳遞給驅動(因爲我這裏使用了late_display.c裏的變量,而且背光控制是在late_display.c裏,所以這裏的管腳號也不重要了)。
最後再把結構體mipi_dsi_panel_device加到board文件裏添加設備的數組中,當系統啓動時統一向內核中註冊設備。
kernel裏驅動文件添加和修改就基本完成了,然後就是要在/kernel/driver/video/msm裏修改Kconfig和Makefile文件.
在Makefile裏,添加
obj-$(CONFIG_FB_MSM_MIPI_DSI_HX8369A) += mipi_hx8369a.o
obj-$(CONFIG_FB_MSM_MIPI_HX8369A_CMD_WVGA_PT) += mipi_hx8369a_cmd_wvga_pt.o
在Kconfig裏,添加config FB_MSM_MIPI_HX8369A_CMD_WVGA_PT_PANEL
bool "MIPI Yassy Command WVGA PT Panel"
select FB_MSM_MIPI_HX8369A_CMD_WVGA_PT
config FB_MSM_MIPI_HX8369A_CMD_WVGA_PT
bool
select FB_MSM_MIPI_DSI_HX8369A
default n
但有一點要注意的是,config FB_MSM_MIPI_HX8369A_CMD_WVGA_PT_PANEL這個的位置要放在choice包含的裏面,具體可以參考truly的例子的位置。
最後,運行make kernelconfig,在裏面選中FB_MSM_MIPI_HX8369A_CMD_WVGA_PT_PANEL和FB_MSM_MIPI_HX8369A_CMD_WVGA_PT,
然後在/kernel/arch/arm/configs下找到與工程相關的配置文件,在裏面可以找到選中的配置,在編繹的時候,根據這個成.config文件,在out/target/product/$(Projec)/obj/KERNEL_OBJ,在這裏也可以查到最後選中的配置。
(2) bootloader
我每次都是先移植kernel裏的LCD驅動,因爲我覺得kernel裏的代碼要相對集中一些,而且就算是代碼弄的有問題,也不會造成手機找不到端口而下不了程序,而且kernel裏的LOG要容易抓一些,bootloader裏還得接個串口,太麻煩。然後就是有了kernel裏驅動,bootloader裏的LCD也要簡單一些了,畢竟有了一些經驗了。
在bootloader裏移植LCD有一點需要特別注意,就是/bootable/bootloader/lk/platform/msm_shared/splash.h這個文件,如果高通的codebase是Lcdc接口的,而你要改爲mipi接口的話,這個文件一定要注意更換,否則會造成手機找不到端口而直接掛掉。蔽人不才,由於這個原因燒壞了手機不下十次,鄙視一下在這裏,哈哈。更換了splash.h後還要註釋掉/vendor/qcom/opensource/qrdplus/QRDExtensions/DynamicComponents/res/Splash_QRD/Android.mk這個文件下的
ifeq ($(strip $(QRDExt_Splash)),cu)
$(shell cp $(LOCAL_PATH)/splash_cu.h bootable/bootloader/lk/platform/msm_shared/include/splash.h)
else
$(shell cp $(LOCAL_PATH)/splash_qrd.h bootable/bootloader/lk/platform/msm_shared/include/splash.h)
endif
這幾句,否則在你編譯的時候,你改過的splash.h會被更改回去。
步入正題吧,該說說bootloader裏移植lcd驅動了。高通的bootloader使用的是一個叫lk(little kernel)的bootloader,在lk裏也有不少高通提供的示例代碼,我一般也是參考truly的來改,同樣的,代碼的大體結構都不需要更改。首先要在目錄/bootable/bootloader/lk/target/$(Projec)下更改lcd的makefile文件rules.mk,由於我們的手機是從nand flash啓動,所以要改的都在NDND啓下的方式下改。在rules.mk下添加:
DEFINES += DISPLAY_MIPI_CMD_PANEL_HX8369A=1
代碼的主要流程基本上可以根着codebase裏truly的來照着填,這裏簡單的列一下:void kmain()(/bootable/bootloader/lk/kernel/main.c)
-> thread_resume (thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
-> bootstrap2
-> target_init(); (bootable\bootloader\lk\target\$(project)\Init.c)
->/*這裏是bootloader裏按鍵的驅動*/
#if (!ENABLE_NANDWRITE)
keys_init();
keypad_init();
#endif
/* 下面的就是與屏相關的函數,下面來一個一個的分析*/
#if DISPLAY_SPLASH_SCREEN
display_init();
dprintf(SPEW, "Diplay initialized\n");
display_image_on_screen();
mdelay(50);
//turn on backlight
gpio_set(I300_PANEL_BACKLIGHT, 1); /*打開LCD背光*/
#endif
display_init() (/bootable/bootloader/lk/platform/msm7627a/platform.c)
->panel_dsi_init()/*主要是初始化LCD相關的管腳,如reset和backlight*/
->mipi_init()(/bootable/bootloader/lk/platform/msm_shared/mipi_dsi.c)
->struct mipi_dsi_panel_config *panel_info = get_panel_info()
-> return &hx8369a_cmd_panel_info;/*結構體hx8369a_cmd_panel_info裏是一些與LCD相關的參數,可參考kernel裏填寫,但有一點要注意,就是這裏面有lcd芯片的初始化參數,它有特定的格式,第一個是參數個數,接着三是固定值,剩下的纔是初始化參數,而且所有這些必須是4的整數倍,若不夠則補0xff*/
->mipi_dsi_phy_init() (/bootable/bootloader/lk/target/$(project)/panel.c)/*設置mipi接口相關的一些寄存器*/
->status += mipi_dsi_panel_initialize(panel_info);
-> status = mipi_dsi_cmds_tx(pinfo->panel_cmds, pinfo->num_of_panel_cmds);/*這裏對LCD進行初始化,然後屏裏寫初始化參數*/
-> mipi_fb_cfg.base = MIPI_FB_ADDR; /*DMA地址*/
-> cmd_mode_status = 1;/*標記爲cmd模式*/
display_image_on_screen() (/bootable/bootloader/lk/dev/fbcon/fbcon.c)
-> for (i = 0; i < SPLASH_IMAGE_WIDTH_HDPI; i++) /*向DMA地址寫數據*/
{
memcpy (config->base + ((image_base_hdpi + (i * (config->width))) * bytes_per_bpp),
imageBuffer_rgb888 + (i * SPLASH_IMAGE_HEIGHT_HDPI * bytes_per_bpp),
SPLASH_IMAGE_HEIGHT_HDPI * bytes_per_bpp);
}
-> fbcon_flush();
-> if(is_cmd_mode_enabled()) /*如果是CMD模式,就啓動MDA,往LCD裏送顯示數據*/
-> mipi_dsi_cmd_mode_trigger();
到這裏lk裏LCD移植也寫完了,如果認爲有問題的地方,歡迎提出來。下一篇再寫4.0裏LCD的移植,4.0裏使用的是LCDC的接口。文章轉自:http://blog.csdn.net/dacaozuo/article/details/7796476