DRM驱动代码分析:开机过程中显示驱动做了什么
前言:
有些信息是在網上查資料后總結的,沒有去追代碼驗證。如果有說得不對的地方,歡迎提出指正。感謝!
手機啟動的大致流程
1.長按開機鍵
2.執行存儲在ROM里(應該是某一個固定地址或是預定義的地址)的Primary Bootloader,會做以下事情:
初始化RAM
將secondary stage bootloader拷貝到內存
3.secondary stage bootloader會做以下事情
準備好device tree,告訴內核dtb的首地址
初始化一些硬件設備,比如顯示
啟動內核,傳遞參數
與顯示相關的部分:dpu、dsi、dphy、屏幕上電,讀屏幕ID來識別屏幕,屏幕初始化,顯示開機logo
4.Kernel
啟動init進程
掛載根文件系統(init進程內核態)
解析cmdline參數
創建各種服務進程(init進程用戶態)
bootloader階段,顯示做了什么
目前在網上沒有找到高通最新的uefi源碼,先空著吧。
內核啟動時,顯示驅動做了什么
module_init
vendor\qcom\opensource\display-drivers\msm\msm_drv.c module_init(msm_drm_register);module_init是一個宏定義:#define module_init(x) __initcall(x);
將msm_drm_register函數放在.initcall6.init段中,在內核啟動過程中通過start_kernel -> reset_init -> kernel_init->do_initcalls調用通過module_init注冊的msm_drm_register函數。[10][11]
那register函數做了什么?
vendor\qcom\opensource\display-drivers\msm\msm_drv.c static int __init msm_drm_register(void) {...platform_driver_register(&msm_platform_driver);dsi_display_register();... } vendor\qcom\opensource\display-drivers\msm\dsi\dsi_display.c void __init dsi_display_register(void) {...dsi_phy_drv_register();dsi_ctrl_drv_register();dsi_display_parse_boot_display_selection();-------------2platform_driver_register(&dsi_display_driver); }調用platform_driver_register函數注冊以下platform driver:
msm_platform_driver、dsi_phy_platform_driver、dsi_ctrl_driver、dsi_display_driver
從名字上可以看出來,dsi_phy_platform_driver對于dphy模塊,dsi_ctrl_driver對應dsi模塊,其它兩個呢?
2.解析屏幕名字。具體分析參考DRM驅動代碼分析:uboot和kernel之間屏幕是如何匹配的
tips:
宏定義__init,用于告訴編譯器相關函數或變量僅用于初始化。
編譯器將標__init的所有代碼存在特殊的內存段中,初始化結束后就釋放這段內存。
來源:百度百科-__init
qcom DRM driver里的platform driver:
unisoc DRM driver里的platform driver:
不管是高通還是展訊,驅動里都定義了of_match_table的compatible變量,有的還定義了data。接下來看看compatible的作用。
drivers\base\platform.c static int platform_match(struct device *dev, struct device_driver *drv) {.../* Attempt an OF style match first */if (of_driver_match_device(dev, drv))------------------------1return 1;/* Then try to match against the id table */if (pdrv->id_table)return platform_match_id(pdrv->id_table, pdev) != NULL;-----2/* fall-back to driver name match */return (strcmp(pdev->name, drv->name) == 0);------------------3 }總線上的device和driver進行匹配的時候會調用bus的match函數,對于platform bus而言就是platform_match。
來源:Linux設備模型(8)_platform設備
1.將驅動of_match_table變量中的compatible、type、name和dts節點對應的值進行比較,來判斷設備和驅動是否匹配。
2.目前看起來顯示驅動的這幾個模塊都沒有定義id_table,暫時不管。
3.比較platform driver的name值。
module_platform_driver
除了module_init();也可以用module_platform_driver();
include\linux\platform_device.h /* module_platform_driver() - Helper macro for drivers that don't do* anything special in module init/exit. This eliminates a lot of* boilerplate. Each module may only use this macro once, and* calling it replaces module_init() and module_exit()*/ #define module_platform_driver(__platform_driver) \module_driver(__platform_driver, platform_driver_register, \platform_driver_unregister)include\linux\device\driver.h #define module_driver(__driver, __register, __unregister, ...) \ static int __init __driver##_init(void) \ { \return __register(&(__driver) , ##__VA_ARGS__); \ } \ module_init(__driver##_init); \ static void __exit __driver##_exit(void) \ { \__unregister(&(__driver) , ##__VA_ARGS__); \ } \ module_exit(__driver##_exit);如注釋所說,如果不需要在module init和exit函數里完成特定的操作,則可以使用module_platform_driver()。
LK、UEFI、uboot、bootloader是什么?
LK、UEFI、uboot都屬于bootloader。
設備驅動prove的時機有如下幾種(分為自動觸發和手動觸發):
將struct device類型的變量注冊到內核中時自動觸發(device_register,device_add,device_create_vargs,device_create)
將struct device_driver類型的變量注冊到內核中時自動觸發(driver_register)
手動查找同一bus下的所有device_driver,如果有和指定device同名的driver,執行probe操作(device_attach)
手動查找同一bus下的所有device,如果有和指定driver同名的device,執行probe操作(driver_attach)
自行調用driver的probe接口,并在該接口中將該driver綁定到某個device結構中----即設置dev->driver(device_bind_driver)
來源:Linux設備模型(5)_device和device driver
mdss_mdp是master,相關聯的設備有smmu_sde_unsec、smmu_sde_sec、sde_dp、sde_wb、sde_dsi、sde_dsi1、sde_rscc。 如果某些設備不支持,則需要刪掉。
todo:為什么是這些設備作為component?
調用component_add注冊sde_dsi設備。
static int msm_drm_bind(struct device *dev)|msm_drm_component_init(dev);|msm_component_bind_all(dev, ddev);|component_bind_all(dev, drm_dev);在master的bind函數msm_drm_bind中調用component_bind_all,從而調用各個子設備的bind函數。[14]
縮寫:
PBL:Primary Bootloader
UEFI:Unified extensible firmware interface統一的可擴展固件接口
MDP:mobile display processor
參考資料
[1]CSDN 木希 《安卓開機流程》
[2]《高通平臺UEFI有關介紹》
[3]《聊一聊汽車控制器的啟動——BOOT》
[4]CSDN 沒有皮卡丘的小志《 Android開機啟動流程簡析》
[5]CSDN 河馬虛擬化 《Linux啟動過程 - 從MBR到第一個應用》
[6]CSDN 花生醬拌面 《uboot移植——啟動內核》
[7]wowotech linuxer 《ARM64的啟動過程之(一):內核第一個腳印》
[8]Documentation/arm64/booting.txt
[9]CSDN 天糊土 《init進程的詳解》
[10]CSDN Richard_LiuJH《linux驅動 之 module_init解析 (上)》
[11]CSDN Richard_LiuJH《linux驅動 之 module_init解析 (下)》
[12]Linux設備模型(8)_platform設備
[13]Linux設備模型(5)_device和device driver
[14]linux kernel component框架分析
總結
以上是生活随笔為你收集整理的DRM驱动代码分析:开机过程中显示驱动做了什么的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个女孩喜欢上一个男性网友怎么办?
- 下一篇: LCD1602使用说明