9.1.6. PXA 攝像頭主機驅動

作者:Robert Jarzmik <robert.jarzmik@free.fr>

9.1.6.1. 約束

  1. YUV422P 格式的影像大小 所有 YUV422P 影像都被強制要求 寬度 x 高度 % 16 = 0。這是由於 DMA 約束,其僅傳輸 8 位元組倍數的平面。

9.1.6.2. 全域性影片工作流程

  1. QCI 已停止 最初,QCI 介面已停止。當一個緩衝區入隊時,呼叫 start_streaming,QCI 啟動。

  2. QCI 已啟動 在 QCI 啟動時可以入隊更多緩衝區,而無需停止捕獲。 新的緩衝區被“附加”到 DMA 鏈的尾部,並一個接一個地平滑捕獲幀。

    一旦 QCI 介面中的一個緩衝區被填滿,它將被標記為“DONE”並從活動緩衝區列表中刪除。 然後可以被使用者空間應用程式重新入隊或出隊。

    一旦最後一個緩衝區被填滿,QCI 介面停止。

  3. 捕獲全域性有限狀態機模式

+----+                             +---+  +----+
| 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 使用

  1. DMA 流程
    • 第一個緩衝區入隊以進行捕獲 一旦第一個緩衝區入隊以進行捕獲,QCI 啟動,但資料傳輸未啟動。 在“幀結束”中斷時,irq 處理程式啟動 DMA 鏈。

    • 捕獲一個影片緩衝區 DMA 鏈開始將資料傳輸到影片緩衝區 RAM 頁面。 當所有頁面都被傳輸時,DMA irq 在 “ENDINTR” 狀態下被觸發。

    • 完成一個影片緩衝區 DMA irq 處理程式將影片緩衝區標記為 “done”,並將其從活動執行佇列中刪除。 同時,下一個影片緩衝區(如果存在)由 DMA 傳輸。

    • 完成最後一個影片緩衝區 在最後一個影片緩衝區的 DMA irq 上,QCI 停止。

  2. 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
  1. 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。