- Bring Up Master
? ? ? ? 上一篇文章提到,bring up master 的條件是所有的子元件都匹配成功。滿足此條件之後,會(huì)呼叫 master 的 imx_drm_ops 的 bind function。在這個(gè) imx_drm_bind() 裡面除了會(huì)初始化〝mode config〞以及〝vblank〞,更重要的,因?yàn)樽釉家呀?jīng)準(zhǔn)備好了,所以有辦法將所有的子元件綁定在一起。就在 component_bind_all() 裡面,會(huì)逐一掃過所有的 match 的元件,呼叫其各自的 bind function,讓 master 與子元件建立交互關(guān)係。最後,會(huì)初始化 fbdev(drm_fbdev_cma_init())完成 DRM 子系統(tǒng)的初始化過程。
|
? ? ? ? 以我們舉的例子來看,會(huì)呼叫的 bind function 有兩個(gè),一個(gè)是 CRTC 的 lcdif_crtc_bind(),還有另一個(gè)是 Encoder 的 imx_sec_dsim_bind()。
? ? ? ? CRTC 主要負(fù)責(zé)接收來自多個(gè) drm_plane 的 pixel data,並將它們做好疊圖的處理。另外也負(fù)責(zé) maintain drm_display_mode,讓 panel 有正確的 resolution 以及 timing 的設(shè)定。下一步這些 pixel data 就可以餵給 drm_encoder 做下一步的處理。所以,lcdif_crtc_bind() 所進(jìn)行的 drm_crtc 初始化,其中就包括了 plane、mode config function 等設(shè)定,完成之後的 CRTC 就 ready 好處?kù)犊傻却蠈又噶畹臓顟B(tài)。
|
? ? ? ? Encoder 主要連接 drm_crtc 跟 drm_connector,負(fù)責(zé)將 CRTC 過來的 pixel data 轉(zhuǎn)換成適合 Connector 的格式,再交給 Connector。所以在 imx_sec_dsim_bind() 裡,因?yàn)榈讓舆B接的介面是 MIPI DSI,所以自然就會(huì)選用 type 為 DRM_MODE_ENCODER_DSI 的 codec 為 drm_encoder 進(jìn)行初始化。
? ? ? ? 另外,有一個(gè)子元件〝bridge〞前面沒有提到,是一個(gè)鏈狀的結(jié)構(gòu),可以視為 Encoder 的延伸,最終才會(huì)接到 Connector(panel)。因此,會(huì)進(jìn)行延伸 bridge 的 bind function,而且此動(dòng)作會(huì)重複直到連接到 Connector 為止。在 Connector 完成 drm_connector_init()、drm_mode_connector_attach_encoder()、還有 drm_panel_attach() 之後,Encoder 跟 Connector 也完成它們的初始化等待上層指令。
|
?
? ? ? ? Frame Buffer 主要功能為提供一塊記憶體來儲(chǔ)存要秀出的圖像資料,而 DRM 的 Frame Buffer 是由 GEM 來管理。在談 drm_framebuffer 之前,系統(tǒng)需要開啟 CONFIG_DRM_FBDEV_EMULATION 的功能。開啟這個(gè)功能後,表示 DRM 將可以模擬一個(gè) Frame Buffer 設(shè)備,如此上層便可使用基於 fbdev 的顯示框架。於是乎,drm_framebuffer 的初始化,drm_fbdev_cma_init(),這個(gè) function 也成為我們最後一個(gè)在 imx_drm_bind() 裡面要分析的。
|
?
- 小結(jié)
? ? ? ? 流程至此,已經(jīng)完成 DRM 子系統(tǒng)的初始化過程。表示 DRM driver 已經(jīng) ready 等待上層使用,所以在下一章節(jié)會(huì)簡(jiǎn)單介紹上層如何使用 DRM。
2. DRM 應(yīng)用程式開發(fā)
? ? ? ? 這個(gè)章節(jié)將說明如何開發(fā)一個(gè) DRM 應(yīng)用程式。關(guān)於應(yīng)用程式與 kernel space 之間的交互關(guān)係,其實(shí)我們?cè)?Chapter 1.3 有提到一點(diǎn)點(diǎn),我們?cè)侔岩韵逻@張架構(gòu)圖拿出來複習(xí)一下。這張架構(gòu)圖說明了,在 user space 的應(yīng)用程式會(huì)透過 libdrm 間接對(duì) kernel space 進(jìn)行 ioctrl 操作。而一般的 DRM 應(yīng)用程式需要包含的基本內(nèi)容有,
- open("/dev/dri/card0")
? ? ? ? 最基本的 open file node 取得 handle。
?
- drmModeGetResources(...)
? ? ? ? 利用 DRM_IOCTL_MODE_GETRESOURCES,取得 CRTC、Encoder、Connector 等 ID 以及個(gè)數(shù)。
?
- drmModeGetConnector(...)
? ? ? ? 利用上式內(nèi)容,DRM_IOCTL_MODE_GETCONNECTOR 可取得 Connector 真實(shí)的資訊,包含 modes setting。
?
- DRM_IOCTL_MODE_CREATE_DUMB、drmModeAddFB(...)、drmIoctl(DRM_IOCTL_MODE_MAP_DUMB)、mmap(...)
? ? ? ? 以上 function 可建立一個(gè) dumb framebuffer 並完成映射。
?
- drmModeSetCrtc(crtc_id, fb_id, connector_id, mode)
? ? ? ? 設(shè)定 CRTC 並連接到 dumb framebuffer,開始進(jìn)行螢?zāi)伙@示。
?
? ? ? ? 基於上面的架構(gòu),我們?cè)诰W(wǎng)路上找到一個(gè)範(fàn)例程式,single buffer。這隻範(fàn)例程式建立一個(gè) dumb framebuffer,內(nèi)容全部都是 0xFF(也就是白色),並把它顯示到螢?zāi)簧稀⒖脊?fàn)例程式碼連結(jié)以及實(shí)際上執(zhí)行的結(jié)果如下:
https://blog.csdn.net/hexiaolong2009/article/details/83721242 此時(shí),螢?zāi)粺o(wú)輸出變?yōu)楹谏?br/> 1. 執(zhí)行測(cè)試程式 ./modeset-single-buffer 此時(shí),螢?zāi)惠敵?dumb framebuffer 內(nèi)容,0xFF,為白色, |
?
- 小結(jié)
? ? ? ?以上我們整篇文章從 device tree 開始,一路介紹到 kernel space 的 DRM driver 的初始化流程,然後更進(jìn)一步完成 user space 的 DRM 應(yīng)用程式範(fàn)例。從下到上,對(duì)於 Linux Display 可說是有了一個(gè)整體性的概念,基於此概念往上延伸不論是 Android 的 display 子系統(tǒng)或是 Wayland等 framework 可說是打下了深厚的基礎(chǔ)。因此,各位開發(fā)者在未來遇到 display 的問題時(shí),對(duì)於如何排錯(cuò)就擁有了一個(gè)好的起手式,不至於毫無(wú)頭緒。完成 DRM 之後,後續(xù)我們將繼續(xù)深究其它在 i.MX8M Mini 上的 Linux driver,一塊一塊的組合出整個(gè) i.MX8M Mini EVK 指日可待。TBC…
3. 參考文件
- https://events.static.linuxfound.org/sites/events/files/slides/brezillon-drm-kms.pdf
- https://blog.csdn.net/hexiaolong2009/category_9281458.html
- https://blog.csdn.net/qq_33487044/category_8454463.html
- DRM wiki (https://en.wikipedia.org/wiki/Direct_Rendering_Manager)
- Linux DRM 原始碼
- http://betteros.org/tut/graphics1.php
參考來源