該檔案為高通顯卡的驅動檔案,比較重要的函數介面和資料結構如下:
A、高通msm fb裝置的檔案操作函數介面
static struct fb_ops msm_fb_ops = { .owner = THIS_MODULE, .fb_open = msm_fb_open, .fb_release = msm_fb_release, .fb_read = NULL, .fb_write = NULL, .fb_cursor = NULL, .fb_check_var = msm_fb_check_var, /* 參數檢查 */ .fb_set_par = msm_fb_set_par, /* 設定顯示相關參數 */ .fb_setcolreg = NULL, /* set color register */ .fb_blank = NULL, /* blank display */ .fb_pan_display = msm_fb_pan_display, /* 顯示 */ .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */ .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */ .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */ .fb_cursor = NULL, .fb_rotate = NULL, .fb_sync = NULL, /* wait for blit idle, optional */ .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */ .fb_mmap = NULL, };
B、高通msm fb的driver介面
static struct platform_driver msm_fb_driver = { .probe = msm_fb_probe,//驅動探測函數 .remove = msm_fb_remove, #ifndef CONFIG_ANDROID_POWER .suspend = msm_fb_suspend, .suspend_late = NULL, .resume_early = NULL, .resume = msm_fb_resume, #endif .shutdown = NULL, .driver = { /* Driver name must match the device name added in platform.c. */ .name = "msm_fb", }, };
C、msm_fb_init()
向系統註冊msm fb的driver,初始化時會調用
D、msm_fb_add_device
向系統中添加新的lcd裝置,在mddi_toshiba.c中會被調用
mddi_toshiba.c 函數和資料結構介紹
該檔案包含了所有和具體LCD(Toshiba)相關的資訊和驅動,重點的資料結構和函數結構如下:
A、LCD裝置相關資訊
static struct platform_device this_device_0 = { .name = "mddi_toshiba_vga", .id = TOSHIBA_VGA_PRIM, .dev = { .platform_data = &toshiba_panel_data0, } };
其中toshiba_panel_data0包含了硬體LCD的控制函數,如開關、初始化等等
B、LCD driver介面
static struct platform_driver this_driver = { .probe = mddi_toshiba_lcd_probe, .driver = { .name = "mddi_toshiba_vga", }, };
其中mddi_toshiba_lcd_probe中會調用msm_fb_add_device介面把具體LCD添加到系統中去。
C、mddi_toshiba_lcd_init
註冊LCD裝置及driver到系統中去,同時也把LCD的固有資訊(大小、格式、位率等)一併註冊到系統中去。
D、LCD相關控制函數
toshiba_common_initial_setup():初始化MDDI bridge
toshiba_prim_start():初始化LCD
Display Kernel資料流分析
本部分來看一下應用程式層以下,顯示資料的流程是怎樣的。
先來分析一下傳統的Linux平台下FB裝置是如果調用的,如所示:
上層調用FB API(主要是fb_ioctl()),fb_ioctl()會調用具體顯卡的驅動,這裡是高通的顯卡驅動,其實就是MDP DMA的驅動,通過MDP DMA把顯示資料經MDDI介面送到外圍LCD組件。
Note:這裡的MDP DMA並不對資料進行任何處理(可以完成簡單的格式轉換,如RGB565->RGB666)。
接下來再分析一下Android平台下顯示資料是如何處理的,如所示:
同樣上層也是調用FB API,不過這裡其實把FB bypass了,相當於直接調用的是高通MDP PPP的驅動,然後資料經PPP處理後再經MDDI介面送出到外圍LCD組件。
Note:這裡的MDP PPP可以完成很多顯示資料處理功能,如YUV->RGB、Scale、Rotate、Blending等。
Display Kernel初始化過程分析
Kernel部分display的初始化包含下面幾個步驟:
1)、在linux fb裝置初始化時會向系統中註冊msm_fb_driver。Name為msm_fb。
msm_fb_init-> msm_fb_register_driver-> platform_driver_register(&msm_fb_driver)
其中的probe函數會對msm fb進行初始化,分配顯存等(見msm_fb_probe函數)。
2)、在LCD模組初始化時會先向系統中註冊驅動(在mddi_toshiba_lcd_init函數中)
platform_driver_register(&this_driver);名字為mddi_toshiba_vga;
this_driver的probe函數為mddi_toshiba_lcd_probe,其內部會調用msm_fb_add_device向系統中添加MSM fb裝置。
3)、調用platform_device_register(&this_device_0)向系統中註冊裝置,名字為mddi_toshiba_vga,其中this_device_0包含了一些操作LCD的介面,如on/off。
Note:裝置和driver的name需要一致才可以綁定;另外,如果某些裝置不需要讓platform的匯流排來管理,那麼只需要註冊驅動即可,而無須向系統中註冊device,如msm_touch。