drm/vc4 Broadcom VC4 圖形驅動¶
Broadcom VideoCore 4(存在於 Raspberry Pi 中)包含一個與 OpenGL ES 2.0 相容的 3D 引擎,名為 V3D,以及一個高度可配置的顯示輸出管道,支援 HDMI、DSI、DPI 和複合電視輸出。
3D 引擎還有一個介面,用於提交任意的計算著色器風格的任務,使用與 GLES 2.0 中頂點和片段著色器相同的著色器處理器。 但是,鑑於硬體無法公開任何標準介面,如 OpenGL 計算著色器或 OpenCL,因此該驅動程式不支援它。
顯示硬體處理¶
本節涵蓋與顯示硬體相關的所有內容,包括模式設定基礎設施、平面、精靈和游標處理以及顯示、輸出探測和相關主題。
畫素閥 (DRM CRTC)¶
在 VC4 中,畫素閥與 DRM 的 CRTC 概念最為接近。 PV 從編碼器的時鐘及其配置生成影片時序。 它以該時序從 HVS 獲取縮放後的畫素,並將其饋送到編碼器。
但是,DRM CRTC 還會收集附加到它的所有 DRM 平面的配置。 因此,CRTC 還負責為 CRTC 將使用的 HVS 通道編寫顯示列表。
2835 有 3 個不同的畫素閥。 音訊電源域中的 pv0 提供 DSI0 或 DPI,而 pv1 提供 DS1 或 SMI。 影像域中的 pv2 可以提供 HDMI 或 SDTV 控制器。 畫素閥根據多路複用器中選擇的輸出型別從 CPRMAN 時鐘(HSM 用於 HDMI,VEC 用於 SDTV 等)中進行選擇。
對於電源管理,畫素閥的暫存器全部由 AXI 時鐘計時,而時序和 FIFO 則使用特定於輸出的時鐘。 由於編碼器也直接消耗 CPRMAN 時鐘,並且知道它們需要的時序,因此它們是設定時鐘的編碼器。
HVS¶
硬體影片縮放器 (HVS) 是一塊硬體,它執行幀緩衝區中儲存的畫素的轉換、縮放、色彩空間轉換和合成,並將它們轉換為輸出到畫素閥 (CRTC) 的畫素 FIFO。 它以系統時鐘速率(特別是系統音訊時鐘門)執行,該速率遠高於畫素時鐘速率。
有一個全域性 HVS,帶有多個輸出 FIFO,可以被 PV 消耗。 該檔案僅管理 HVS 的資源,而 vc4_crtc.c 程式碼實際上驅動每個 CRTC 的 HVS 設定。
HVS 平面¶
每個 DRM 平面都是 HVS 掃描出的畫素層。
在原子模式設定檢查時,我們計算顯示平面所需的 HVS 顯示元素狀態(使我們有機會確定平面配置是否無效),然後在原子重新整理時,CRTC 將要求我們將元素狀態寫入它為我們分配的 HVS 區域中。
HDMI 編碼器¶
HDMI 核心具有狀態機和 PHY。 在 BCM2835 上,大多數單元都透過 CPRMAN 的 HSM 時鐘執行。 它還在內部使用 PLLH_PIX 時鐘作為 PHY 的時鐘。
HDMI 資訊幀儲存在一個小型資料包 RAM 中,每個資料包都可以單獨啟用以包含在幀中。
HDMI 音訊完全在 HDMI IP 塊中實現。 HDMI 編碼器中的一個暫存器從 DMA 引擎獲取 SPDIF 幀,並透過內部 MAI(多通道音訊互連)匯流排將它們傳輸到編碼器側,以插入到影片消隱區域中。
驅動程式的 HDMI 編碼器尚不支援電源管理。 HDMI 編碼器的電源域和 HSM/畫素時鐘保持持續執行,只有 HDMI 邏輯和資料包 RAM 在停用/啟用時斷電/通電。
驅動程式尚不支援 CEC 控制,儘管 HDMI 編碼器塊具有 CEC 支援。
DSI 編碼器¶
BCM2835 包含兩個 DSI 模組,DSI0 和 DSI1。 DSI0 是一個單通道 DSI 控制器,而 DSI1 是一個更現代的 4 通道 DSI 控制器。
大多數 Raspberry Pi 板將 DSI1 公開為其“DISPLAY”聯結器,而計算模組則同時引出 DSI0 和 DSI1。
目前僅針對 DSI1 影片模式顯示測試了此驅動程式,希望 DSI0 的大部分必要資訊都存在。
DPI 編碼器¶
VC4 DPI 硬體支援 MIPI DPI 型別 4 和 Nokia ViSSI 訊號。 在 BCM2835 上,這些訊號可以透過 ALT2 功能路由到 GPIO0-27。
VEC(複合電視輸出)編碼器¶
VEC 編碼器生成 PAL 或 NTSC 複合影片輸出。
電視模式選擇由編碼器上的原子屬性完成,因為 drm_mode_modeinfo 不足以區分 PAL 和 PAL-M 或 NTSC 和 NTSC-J。
KUnit 測試¶
VC4 驅動程式使用 KUnit 來執行特定於驅動程式的單元和整合測試。
這些測試使用模擬驅動程式,可以使用以下命令在 arm 或 arm64 架構上執行,
$ ./tools/testing/kunit/kunit.py run \
--kunitconfig=drivers/gpu/drm/vc4/tests/.kunitconfig \
--cross_compile aarch64-linux-gnu- --arch arm64
- 當前測試覆蓋的驅動程式部分有
BCM2835-7 和 BCM2711 的 HVS 到 PixelValve 動態 FIFO 分配。
記憶體管理和 3D 命令提交¶
本節介紹 vc4 驅動程式中的 GEM 實現。
GPU 緩衝區物件 (BO) 管理¶
VC4 GPU 架構(掃描輸出和渲染)可以直接訪問系統記憶體,而沒有 MMU。 為了支援它,我們使用 GEM DMA 輔助函式為我們的 BO 分配連續的物理記憶體範圍。
由於 DMA 分配器非常慢,因此我們保留一個最近釋放的 BO 快取,以便核心為 3D 渲染分配物件可以快速返回。
V3D 分箱器命令列表 (BCL) 驗證¶
由於 VC4 在它和系統記憶體之間沒有 IOMMU,因此有權執行命令列表的使用者可以透過覆蓋系統記憶體(將其繪製為幀緩衝區)或讀取它不應該讀取的系統記憶體(將其讀取為頂點緩衝區或索引緩衝區)來升級許可權。
我們驗證分箱器命令列表,以確保所有訪問都在提交作業引用的 GEM 物件的範圍內。 它顯式地列入資料包白名單,並檢視任何地址欄位中的偏移量,以確保它們包含在它們引用的 BO 中。
請注意,由於 CL 驗證已經在讀取使用者提交的 CL 並將驗證後的副本寫入 GPU 實際將讀取的記憶體中,因此這也是 GEM 重定位處理(將 BO 引用轉換為 GPU 使用的實際地址)發生的位置。
V3D 渲染命令列表 (RCL) 生成¶
在 V3D 硬體中,渲染命令列表用於載入和儲存幀緩衝區的平鋪,並選擇性地呼叫分箱器生成的命令列表來執行該平鋪的 3D 繪製。
在 VC4 驅動程式中,渲染命令列表的生成由核心而不是使用者空間執行。 我們這樣做是因為驗證使用者提交的命令列表很難做到正確並且 CPU 開銷很高,而渲染命令列表的有效配置數量實際上相當少。
VC4 著色器驗證器¶
由於 VC4 在它和系統記憶體之間沒有 IOMMU,因此有權執行著色器的使用者可以透過覆蓋系統記憶體(使用通用 DMA 模式下的 VPM 寫入地址暫存器)或讀取它不應該讀取的系統記憶體(將其讀取為紋理、統一資料或直接定址的 TMU 查詢)來升級許可權。
著色器驗證器會遍歷著色器的 BO,確保其訪問受到適當的限制,並記錄進行紋理訪問的位置,以便我們可以在統一流中進行重定位。
著色器 BO 在其生命週期內是不可變的(透過不允許 mmap、GEM prime 匯出或從 CL 渲染到著色器 BO 來強制執行),因此此驗證僅在 BO 建立時執行。
V3D 中斷¶
我們有一箇中斷狀態暫存器 (V3D_INTCTL),它報告中斷,並且寫入 1 位會清除這些中斷。 還有一對中斷暫存器 (V3D_INTENA/V3D_INTDIS),將 1 寫入它們的位會啟用或停用該特定中斷,而寫入的 0 會被忽略(讀取任何一個暫存器都會返回已啟用的中斷集)。
當我們採用完成中斷的分箱重新整理時,我們需要提交下一個要分箱的幀,並將完成的幀移動到渲染執行緒。
當我們採用渲染幀中斷時,我們需要喚醒等待某個幀完成的程序,並儘快提交下一個幀(以便在有工作要做時硬體不會閒置)。
當我們採用分箱器記憶體不足中斷時,我們需要分配一些新記憶體並將其傳遞給分箱器,以便當前作業可以取得進展。