單元 4 · 平台相機框架與驅動

V4L2 subdev、ov5640.c

V4L2 subdev 模型

/dev/v4l-subdev0(感測器)/dev/v4l-subdev1(CSI)/dev/video0

ov5640.c 驅動(mainline 範本)

查看 media 管線(實作)

media-ctl / v4l2-ctl
media-ctl -p -d /dev/media0     # 列出所有實體與連結
v4l2-ctl --list-devices         # 對應的 /dev/videoX
v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls   # 列出感測器 controls
調適關鍵:V4L2 controls(曝光、gain、白平衡)就是「感測器 register 的抽象介面」——調校透過它們,不手寫 register。

4.4 深入原理:subdev 生命週期與 media graph 結構

ov5640.c 這類 subdev 驅動不是「直接被使用者呼叫」,而是掛在 media graph 上由管線控制器驅動。它的核心回呼(v4l2_subdev_ops)對應感測器硬體狀態:

subdev op觸發時機OV5640 內部行為
init_cfg / set_fmtmedia-ctl 設定格式切解析度/時序 table
s_power(1)開電源上電時序、跑 init table
s_stream(1)開始串流設 MIPI 輸出、開始出圖
s_ctrlv4l2-ctl 改 control寫對應 register(曝光/增益/白平衡)

一個完整的相機管線是「圖」不是「鏈」:

ov5640 subdevcsi2 receiver(ISP)video nodeuserspace

每個節點在 kernel 是 struct media_entity;連結 struct media_link。使用者透過 /dev/media0media-ctl 操作圖,透過 /dev/v4l-subdevN 與 subdev 溝通,透過 /dev/videoN 拿資料。

為什麼 framework 這樣設計:感測器與 ISP 不必知道彼此細節,只要遵守 subdev 介面。這正是「換平台原理可平移」的根本——驅動介面在四平台(RPi5/Orange Pi/Orin/Thor)概念一致。

4.5 完整 Worked Example:跟蹤 subdev 與 video 節點

步驟 1|列 media graph
media-ctl -p -d /dev/media0
步驟 2|對照 /dev 節點
v4l2-ctl --list-devices
步驟 3|讀感測器 controls
v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls
步驟 4|觀察 kernel 物件
cat /sys/class/video4linux/video0/name   # device name
readlink -f /sys/class/video4linux/video0/device   # 對應 DT 節點
完成標準:你能指出「media graph 的哪個 entity 對應 /dev 的哪個節點」,並能說出該節點由哪段 DT/哪個驅動負責。

4.6 疑難排解決策樹:節點/管線對不上

現象可能原因檢查
media-ctl -p 只有感測器沒有 video管線後端未 probe / ISP 驅動沒載入dmesg 看 csi/isp 錯誤
--list-ctrls 沒列出曝光/增益驅動沒實作該 control / 模式不同切到另一解析度再列
改 control 回傳 EINVAL值超出 min/max 或格式不符看 --list-ctrls 的範圍
video 節點拿不到 buffer管線 link 未建 / 格式不符media-ctl 建 link 並統一格式
常見錯誤與陷阱:① 把 /dev/video0 誤當感測器——感測器是 /dev/v4l-subdev*,兩者 API 不同;② 在沒有平台 ISP 的板卡上想找「ISP 節點」——H618/H616 多半沒有,別浪費時間;③ 用 v4l2-ctl -d /dev/video0 控制感測器——那會設定 video 節點而非 subdev。

4.8 深入:從 /sys 追蹤驅動狀態

/sys 觀察驅動生命週期
readlink -f /sys/class/video4linux/video0/device   # 指向 DT 節點
cat /sys/class/video4linux/video0/name             # 節點名稱
cat /sys/bus/i2c/devices/3-003c/name               # 感測器 i2c device name
除錯利器:media-ctl -p 的輸出與預期不符,先看 /sys 確認驅動真的綁定到硬體。綁定成功才談管線。

4.7 練習

  1. 畫出你板卡完整的 media graph,標註每個 entity 的類型(subdev/video)。
  2. --list-ctrls 找出曝光、增益、白平衡的 id/範圍/單位。
  3. 在 kernel source 中找到 ov5640.cs_stream,讀它做了哪三件事。
  4. 說明「video 節點」與「subdev 節點」的 API 差別,並各舉一個使用情境。

4.9 進階真實情境 Worked Example:從 sysfs 追蹤 subdev 綁定到 DT 節點

場景:Orange Pi 5(RK3588)probe 成功但 v4l2-ctl --list-devices 沒出現預期的 video device,需要從 /sys 追蹤驅動綁定鏈。

步驟 1|找 DT 節點對應的 sysfs 路徑
cat /sys/class/video4linux/video0/name
readlink -f /sys/class/video4linux/video0/device
ls -la /sys/bus/platform/devices/*/video4linux/
步驟 2|追蹤 I2C subdev 的綁定
ls /sys/bus/i2c/devices/
cat /sys/bus/i2c/devices/3-003c/name   # 應為 "ov5640"
readlink -f /sys/bus/i2c/devices/3-003c/driver
步驟 3|確認 media entity 數量
media-ctl -p -d /dev/media0 2>/dev/null | grep "entity"
# 正常應有 sensor + csi + (isp) + video = 3~5 entities
設計決策:v4l2-ctl --list-devices 沒出現 video device 時,問題通常不在驅動本身,而在 DT 的 media controller 設定——RK3588 需要 DT 同時啟用 sensor subdev + CSI receiver + video device 三個 entity。

4.10 深入原理擴充:RK3588 RGA 在 V4L2 之外的角色

RK3588 的 RGA(Raster Graphic Acceleration)是一個常被誤解的模組:

模組介面media graph 內?用途
ISP3V4L2 subdev✅ 是RAW → YUV 管線
RGA/dev/rga IOCTL❌ 否即時旋轉/縮放/color convert
CIFV4L2 video device✅ 是Allwinner MIPI 接收

容易忽略的邊界案例:如果你在 GStreamer 管線中用 rga element,它在底層走的是 /dev/rga 而非 V4L2 media graph——所以 media-ctl -p 看不到 RGA 的設定。若 RGA 的格式與 ISP 輸出不匹配,GStreamer 會靜默失敗而非報錯。

除錯技巧:懷疑 RGA 問題時,直接用 rga_test(Rockchip 工具)測試 RGA 是否能正確轉換格式,再回頭查 GStreamer 管線。

4.11 診斷式疑難排解表

症狀可能原因解決方案
media-ctl -p 只有 sensor 沒有 csi/videoDT 未啟用 CSI receiver 或 video device 節點在 DT overlay 中加入 csi2 + video device 節點
--list-ctrls 只有 brightness 沒有 exposure驅動未實作 V4L2_CID_EXPOSURE查 ov5640.c 的 ov5640_ctrls 陣列確認是否包含
subdev 有 controls 但設值回 EINVAL值超出 min/max/step 範圍--list-ctrls 看 min/max/step/default
video device 存在但 media-ctl -p 無 video entitymedia controller 與 V4L2 device 未綁定確認 DT 中 video device 節點有 portsport/endpoint
RK3588 ISP node 存在但 media-ctl -l 失敗ISP subdev 未 probe 或 lane 數不符dmesg 搜 rkisp 確認 probe;檢查 CSI lane 數 DT 設定

4.12 進階挑戰題

  1. 在 RK3588 上畫出完整的 media graph 圖(手繪或 SVG),標註每個 entity 的 type、pad 數量、與 link 方向。對照 media-ctl -p 的輸出。
  2. /sys/class/video4linux/ 的資訊,寫一支 script 自動產出「video device → DT 節點 → 驅動」的對照表。
  3. 測試 v4l2-ctl -d /dev/v4l-subdev0v4l2-ctl -d /dev/video0 對同一個 control(如 exposure)的差異,解釋為什麼 API 不同。

4.13 專案級 Worked Example:驅動與節點盤點自動化專案 — 從 /sys 到 media graph

把單元 4 的 subdev 知識做成可交付的盤點工具:自動建立「video device → subdev → DT 節點 → 驅動」完整對照表。這是跨平台移植、多人協作除錯時的「單一事實來源」。

階段 1|自動列 video 與 subdev
for d in /sys/class/video4linux/*; do
  name=$(basename $d)
  devname=$(cat $d/name)
  dt=$(readlink -f $d/device)
  echo "$name | $devname | $dt"
done
階段 2|抓 media graph 的 entity 對照
media-ctl -p -d /dev/media0 | grep -E "entity|type|device node" | head -30
階段 3|列出感測器 controls 全集
v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls
階段 4|產生對照表
#!/bin/bash
echo "===== 平台相機節點盤點表 $(date) ====="
echo "--- video devices ---"
v4l2-ctl --list-devices
echo "--- i2c devices bound to ov5640 ---"
ls -la /sys/bus/i2c/devices/ | grep -i ov
echo "--- driver ---"
readlink -f /sys/bus/i2c/devices/*/driver 2>/dev/null | grep -i ov
專案完成標準:你有一支 camera_inventory.sh,跑一次就產出完整盤點表。把輸出存進 repo,任何人接手都能在 5 分鐘內看懂這片板卡的相機系統架構。

4.14 量測/驗證 SOP:subdev 介面驗證

步驟指令通過判據
1. 節點存在性ls /dev/v4l-subdev* /dev/video*節點存在
2. 驅動綁定readlink -f /sys/bus/i2c/devices/*/driver指向 ov5640 驅動
3. entity 數量media-ctl -p -d /dev/media0sensor + csi + (isp) + video 齊全
4. controls 可用v4l2-ctl -d /dev/v4l-subdev0 --list-ctrls有 exposure/gain/white_balance
5. 控制生效-c exposure=2000-C exposure讀回與設定一致
SOP 紀律:驗證「驅動有沒有綁定」永遠比「media-ctl 為什麼沒有輸出」先做——綁定失敗時 media graph 一定不完整,別浪費時間在後端。

4.15 平台間對照:相機框架與驅動

面向Orange PiRPi5Orin NanoThor
框架V4L2 + media controllerlibcamerategracam + ArgusHoloscan + GXF
感測器驅動ov5640.c(mainline)libcamera 驅動 + IPANVIDIA 封閉驅動NVIDIA 封閉驅動
subdev 節點/dev/v4l-subdevNlibcamera 抽象(無直接節點)內部抽象內部抽象
controlsV4L2_CID_*libcamera controlsArgus SensorModeHoloscan 參數
可移植性Linux 標準,最通用RPi 專屬但開源NVIDIA 專屬NVIDIA 新世代
核心領悟:「感測器驅動」在四平台的共同點是「都實作 subdev 概念(開電源、設定格式、開始串流、控制)」——Orange Pi 的 V4L2 subdev 是最低層、最接近感測器 register 的抽象,學透它,其他平台只是包裝。

4.16 互動式檢核清單:本單元進階驗收

checklist
- [ ] 我能跑出 camera_inventory.sh 並產出完整盤點表。
- [ ] 我能指出 video 節點與 subdev 節點的 API 差異。
- [ ] 我已從 /sys 追蹤出 OV5640 的驅動綁定鏈。
- [ ] 我能列出本平台感測器的全部 controls 與範圍。
- [ ] 我了解 libcamera / Argus / V4L2 之間的抽象層差異。
- [ ] 我能從「media graph 不完整」反推是驅動還是 DT 問題。

4.17 Register 位元級完整工作流

V4L2 subdev 的控制介面是 register 的高階抽象。以下是以 OV5640 為例的位元級操作序列:

步驟V4L2 控制register 對應操作預期值
1. 查 controlsv4l2-ctl -lv4l2-ctl -d /dev/v4l-subdev0 -l列出所有控制項
2. 讀曝光值exposure0x3500/0x3501/0x3502v4l2-ctl -d subdev0 --get-ctrl=exposure依場景
3. 寫曝光值exposure同上v4l2-ctl -d subdev0 --set-ctrl=exposure=500值已設定
4. 驗證 registeri2cget0x3500~0x3502i2cget -y 3 0x3c 0x3500對應 high byte
5. 查 media graphmedia-ctl -pmedia-ctl -p -d /dev/media0entities + links
6. 建 linkmedia-ctl -lmedia-ctl -l "...:0->...:0[1]"link 設為 active
位元級關鍵: V4L2 control 是 register 的「語意包裝」。exposure=500 代表 500 lines,對應 OV5640 的 0x3500/0x3501/0x3502。理解這層對應關係是驅動工程師的核心能力。

4.18 多層疑難排解決策樹

決策樹 A:media graph 不完整

決策樹 A
media-ctl -p 有 sensor entity 嗎?
├─ 無 → DT 未描述 sensor 節點
│  ├─ 檢查 DT overlay 是否含 i2c + sensor
│  └─ 檢查 compatible 字串是否匹配驅動
├─ 有但缺 link → 驅動未建 link
│  ├─ 手動建:media-ctl -l "..."
│  └─ 檢查 DT 的 port/endpoint 描述
└─ 有 link 但缺 format → 需手動設定
   └─ media-ctl -V "...:0[fmt:SRGGB10_1X10/1920x1080]"

決策樹 B:controls 找不到

決策樹 B
v4l2-ctl -l 無控制項?
├─ subdev 節點不存在 → 驅動未 probe
│  └─ dmesg 看 probe 失敗原因
├─ subdev 存在但無 controls → 驅動未暴露
│  └─ 檢查 ov5640.c 的 .s_ctrl 實作
└─ controls 有但 set 失敗 → register 被鎖
   └─ 檢查 AEC/AGC auto 模式是否覆蓋手動

4.19 量測驗證完整 SOP

步驟指令預期輸出判讀標準
1. 列出 subdevls /dev/v4l-subdev*subdev0..N數量與 DT 一致
2. 查 controlsv4l2-ctl -d /dev/v4l-subdev0 -l列出 V4L2_CID_*含 exposure/gain/...
3. 讀 media graphmedia-ctl -p -d /dev/media0entities + linkssensor → csi → video
4. 設定 formatmedia-ctl -V "...:0[fmt:SRGGB10_1X10/1920x1080]"格式設定成功match sensor 能力
5. 建 linkmedia-ctl -l "...:0->...:0[1]"link 設為 active正確的 pad 端點
6. 驗證控制v4l2-ctl -d subdev0 --set-ctrl=exposure=500值已設定回讀確認

4.20 四平台終極對照

面向Orange PiRPi5Orin NanoThor推薦
驅動框架V4L2 subdevlibcameraNVIDIA 自有Holoscan底層→V4L2
subdev 節點/dev/v4l-subdevNlibcamera 抽象內部抽象內部抽象除錯→Orange Pi
controlsV4L2_CID_*libcamera controlsArgus SensorModeHoloscan 參數底層→V4L2
media controller✅ 開放libcamera 抽象封閉封閉學習→Orange Pi
可移植性Linux 標準RPi 專屬但開源NVIDIA 專屬NVIDIA 新世代通用→V4L2

4.21 完整 Bring-up 專案 Checklist

checklist
- [ ] 確認所有 /dev/v4l-subdev* 節點存在
- [ ] 用 v4l2-ctl -l 列出全部 controls 與範圍
- [ ] 用 media-ctl -p 確認完整 media graph
- [ ] 手動建 link 並設定 format
- [ ] 用 v4l2-ctl 設定 exposure 並回讀驗證
- [ ] 追蹤 /sys 下的驅動綁定鏈
- [ ] 產出「platform inventory」(subdev/video/controls/media)
- [ ] 確認 libcamera / Argus / V4L2 的抽象差異
- [ ] 驗證 DT overlay 描述與實際 media graph 一致
- [ ] 用 dmesg 追蹤 probe 回呼序列
看完這單元你應該能說出:
  • V4L2 subdev 與 media 管線。
  • ov5640.c 是 Linux 驅動範本。
  • V4L2 controls 是 register 的抽象。
  • media-ctl/v4l2-ctl 查管線與 controls。
  • subdev 生命週期回呼與硬體狀態對應。
  • 節點與管線對不上的排解方向。

延伸閱讀