9.1.6. PXA 攝像頭主機驅動¶
作者:Robert Jarzmik <robert.jarzmik@free.fr>
9.1.6.1. 約束¶
YUV422P 格式的影像大小 所有 YUV422P 影像都被強制要求 寬度 x 高度 % 16 = 0。這是由於 DMA 約束,其僅傳輸 8 位元組倍數的平面。
9.1.6.2. 全域性影片工作流程¶
QCI 已停止 最初,QCI 介面已停止。當一個緩衝區入隊時,呼叫 start_streaming,QCI 啟動。
QCI 已啟動 在 QCI 啟動時可以入隊更多緩衝區,而無需停止捕獲。 新的緩衝區被“附加”到 DMA 鏈的尾部,並一個接一個地平滑捕獲幀。
一旦 QCI 介面中的一個緩衝區被填滿,它將被標記為“DONE”並從活動緩衝區列表中刪除。 然後可以被使用者空間應用程式重新入隊或出隊。
一旦最後一個緩衝區被填滿,QCI 介面停止。
捕獲全域性有限狀態機模式
+----+ +---+ +----+
| DQ | | Q | | DQ |
| v | v | v
+-----------+ +------------------------+
| STOP | | Wait for capture start |
+-----------+ Q +------------------------+
+-> | QCI: stop | ------------------> | QCI: run | <------------+
| | DMA: stop | | DMA: stop | |
| +-----------+ +-----> +------------------------+ |
| / | |
| / +---+ +----+ | |
|capture list empty / | Q | | DQ | | QCI Irq EOF |
| / | v | v v |
| +--------------------+ +----------------------+ |
| | DMA hotlink missed | | Capture running | |
| +--------------------+ +----------------------+ |
| | QCI: run | +-----> | QCI: run | <-+ |
| | DMA: stop | / | DMA: run | | |
| +--------------------+ / +----------------------+ | Other |
| ^ /DMA still | | channels |
| | capture list / running | DMA Irq End | not |
| | not empty / | | finished |
| | / v | yet |
| +----------------------+ +----------------------+ | |
| | Videobuf released | | Channel completed | | |
| +----------------------+ +----------------------+ | |
+-- | QCI: run | | QCI: run | --+ |
| DMA: run | | DMA: run | |
+----------------------+ +----------------------+ |
^ / | |
| no overrun / | overrun |
| / v |
+--------------------+ / +----------------------+ |
| Frame completed | / | Frame overran | |
+--------------------+ <-----+ +----------------------+ restart frame |
| QCI: run | | QCI: stop | --------------+
| DMA: run | | DMA: stop |
+--------------------+ +----------------------+
Legend: - each box is a FSM state
- each arrow is the condition to transition to another state
- an arrow with a comment is a mandatory transition (no condition)
- arrow "Q" means : a buffer was enqueued
- arrow "DQ" means : a buffer was dequeued
- "QCI: stop" means the QCI interface is not enabled
- "DMA: stop" means all 3 DMA channels are stopped
- "DMA: run" means at least 1 DMA channel is still running
9.1.6.3. DMA 使用¶
- DMA 流程
第一個緩衝區入隊以進行捕獲 一旦第一個緩衝區入隊以進行捕獲,QCI 啟動,但資料傳輸未啟動。 在“幀結束”中斷時,irq 處理程式啟動 DMA 鏈。
捕獲一個影片緩衝區 DMA 鏈開始將資料傳輸到影片緩衝區 RAM 頁面。 當所有頁面都被傳輸時,DMA irq 在 “ENDINTR” 狀態下被觸發。
完成一個影片緩衝區 DMA irq 處理程式將影片緩衝區標記為 “done”,並將其從活動執行佇列中刪除。 同時,下一個影片緩衝區(如果存在)由 DMA 傳輸。
完成最後一個影片緩衝區 在最後一個影片緩衝區的 DMA irq 上,QCI 停止。
DMA 準備好的緩衝區將具有以下結構
+------------+-----+---------------+-----------------+
| desc-sg[0] | ... | desc-sg[last] | finisher/linker |
+------------+-----+---------------+-----------------+
該結構由 dma->sg_cpu 指向。 描述符的使用方式如下
desc-sg[i]: 第 i 個描述符,將第 i 個 sg 元素傳輸到影片緩衝區散列表。
finisher: 具有 ddadr=DADDR_STOP,dcmd=ENDIRQEN
linker: 具有下一個影片緩衝區的 desc-sg[0] 的 ddadr=,dcmd=0
對於下一個模式,假設 d0=desc-sg[0] .. dN=desc-sg[N],“f”代表 finisher,“l”代表 linker。 典型的執行鏈是
Videobuffer 1 Videobuffer 2
+---------+----+---+ +----+----+----+---+
| d0 | .. | dN | l | | d0 | .. | dN | f |
+---------+----+-|-+ ^----+----+----+---+
| |
+----+
在連結完成後,鏈看起來像
Videobuffer 1 Videobuffer 2 Videobuffer 3
+---------+----+---+ +----+----+----+---+ +----+----+----+---+
| d0 | .. | dN | l | | d0 | .. | dN | l | | d0 | .. | dN | f |
+---------+----+-|-+ ^----+----+----+-|-+ ^----+----+----+---+
| | | |
+----+ +----+
new_link
DMA 熱連結時間片問題
由於 DMA 連結是在 DMA _正在_ 執行時完成的,因此當 DMA 從一個影片緩衝區跳轉到另一個影片緩衝區時,可能會完成連結。 在該模式下,如果遇到以下序列將是一個問題
DMA 鏈是 Videobuffer1 + Videobuffer2
呼叫 pxa_videobuf_queue() 以將 Videobuffer3 入隊
DMA 控制器完成 Videobuffer2,DMA 停止
=>
Videobuffer 1 Videobuffer 2
+---------+----+---+ +----+----+----+---+
| d0 | .. | dN | l | | d0 | .. | dN | f |
+---------+----+-|-+ ^----+----+----+-^-+
| | |
+----+ +-- DMA DDADR loads DDADR_STOP
呼叫 pxa_dma_add_tail_buf(),Videobuffer2 “finisher” 被替換為指向 Videobuffer3 的 “linker”(建立 new_link)
pxa_videobuf_queue() 完成
呼叫 DMA irq 處理程式,它終止 Videobuffer2
Videobuffer3 捕獲未在 DMA 鏈上排程(因為它已停止!!!)
Videobuffer 1 Videobuffer 2 Videobuffer 3
+---------+----+---+ +----+----+----+---+ +----+----+----+---+
| d0 | .. | dN | l | | d0 | .. | dN | l | | d0 | .. | dN | f |
+---------+----+-|-+ ^----+----+----+-|-+ ^----+----+----+---+
| | | |
+----+ +----+
new_link
DMA DDADR still is DDADR_STOP
呼叫 pxa_camera_check_link_miss() 這會檢查 DMA 是否已完成,並且緩衝區是否仍在 pcdev->capture 列表中。 如果是這種情況,捕獲將重新啟動,並且 Videobuffer3 將在 DMA 鏈上排程。
DMA irq 處理程式完成
注意
如果 DMA 在 pxa_camera_check_link_miss() 讀取 DDADR() 值後立即停止,我們可以保證當 DMA 完成緩衝區時,DMA irq 處理程式將被回撥,並且 pxa_camera_check_link_miss() 將再次被呼叫,以重新排程 Videobuffer3。