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。