2.7. V4L2 子裝置¶
許多驅動程式需要與子裝置通訊。這些裝置可以執行各種任務,但最常見的是處理音訊和/或影片的混合、編碼或解碼。對於網路攝像頭,常見的子裝置是感測器和攝像頭控制器。
通常這些是 I2C 裝置,但不一定。為了為驅動程式提供與這些子裝置一致的介面,建立了 v4l2_subdev 結構體 (v4l2-subdev.h)。
每個子裝置驅動程式都必須有一個 v4l2_subdev 結構體。對於簡單的子裝置,此結構體可以是獨立的,如果需要儲存更多狀態資訊,則可以嵌入到更大的結構體中。通常有一個低階裝置結構體(例如 i2c_client),其中包含核心設定的裝置資料。建議使用 v4l2_set_subdevdata() 將該指標儲存在 v4l2_subdev 的私有資料中。這樣可以輕鬆地從 v4l2_subdev 轉到實際的低階匯流排特定裝置資料。
您還需要一種從低階結構體轉到 v4l2_subdev 的方法。對於常見的 i2c_client 結構體,使用 i2c_set_clientdata() 呼叫來儲存 v4l2_subdev 指標,對於其他匯流排,您可能需要使用其他方法。
橋接器可能還需要儲存每個子裝置的私有資料,例如指向橋接器特定的每個子裝置的私有資料的指標。v4l2_subdev 結構體為此目的提供了主機私有資料,可以使用 v4l2_get_subdev_hostdata() 和 v4l2_set_subdev_hostdata() 訪問。
從橋接器驅動程式的角度來看,您載入子裝置模組,並以某種方式獲取 v4l2_subdev 指標。對於 i2c 裝置,這很容易:您呼叫 i2c_get_clientdata()。對於其他匯流排,需要執行類似的操作。存在用於 I2C 總線上的子裝置的輔助函式,可以為您完成大部分棘手的工作。
每個 v4l2_subdev 包含子裝置驅動程式可以實現的函式指標(或者如果不適用,則保留為 NULL)。由於子裝置可以做很多不同的事情,並且您不希望最終得到一個龐大的 ops 結構體,其中只有少數 ops 被普遍實現,因此函式指標按照類別排序,每個類別都有自己的 ops 結構體。
頂層 ops 結構體包含指向類別 ops 結構體的指標,如果 subdev 驅動程式不支援該類別中的任何內容,則該指標可能為 NULL。
它看起來像這樣
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*init)(struct v4l2_subdev *sd, u32 val);
...
};
struct v4l2_subdev_tuner_ops {
...
};
struct v4l2_subdev_audio_ops {
...
};
struct v4l2_subdev_video_ops {
...
};
struct v4l2_subdev_pad_ops {
...
};
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_pad_ops *video;
};
核心 ops 對所有 subdevs 都是通用的,其他類別根據子裝置實現。例如,影片裝置不太可能支援音訊 ops,反之亦然。
此設定限制了函式指標的數量,同時仍然可以輕鬆新增新的 ops 和類別。
子裝置驅動程式使用以下命令初始化 v4l2_subdev 結構體
v4l2_subdev_init(sd, &ops)。
之後,您需要使用唯一的名稱初始化 sd->name 並設定模組所有者。如果您使用 i2c 輔助函式,則會自動為您完成此操作。
如果需要與媒體框架整合,則必須透過呼叫 media_entity_pads_init() 來初始化嵌入在 v4l2_subdev 結構體(實體欄位)中的 media_entity 結構體,如果實體有 pad
struct media_pad *pads = &my_sd->pads;
int err;
err = media_entity_pads_init(&sd->entity, npads, pads);
pads 陣列必須已事先初始化。無需手動設定 struct media_entity 函式和名稱欄位,但如果需要,則必須初始化修訂欄位。
當子裝置裝置節點(如果有)開啟/關閉時,將自動獲取/釋放對實體的引用。
不要忘記在子裝置銷燬之前清理媒體實體
media_entity_cleanup(&sd->entity);
如果子裝置驅動程式實現接收器 pad,則 subdev 驅動程式可以在 v4l2_subdev_pad_ops 中設定 link_validate 欄位以提供自己的連結驗證函式。對於管道中的每個連結,都會呼叫連結的接收器端的 link_validate pad 操作。在這兩種情況下,驅動程式仍然負責驗證子裝置和影片節點之間的格式配置的正確性。
如果未設定 link_validate op,則使用預設函式 v4l2_subdev_link_validate_default()。此函式確保連結的源和接收器上的寬度、高度和媒體匯流排畫素程式碼相等。除了他們自己的檢查之外,Subdev 驅動程式還可以自由地使用此功能來執行上述檢查。
2.7.1. Subdev 註冊¶
目前有兩種方法可以將子設備註冊到 V4L2 核心。第一種(傳統)可能性是由橋接器驅動程式註冊子裝置。當橋接器驅動程式具有有關連線到它的子裝置的完整資訊,並且確切知道何時註冊它們時,可以執行此操作。這通常是內部子裝置的情況,例如 SoC 或複雜 PCI(e) 板內的影片資料處理單元、USB 攝像頭中的攝像頭感測器或連線到 SoC,它們通常在其平臺數據中將有關它們的資訊傳遞給橋接器驅動程式。
但是,在某些情況下,子裝置必須非同步地註冊到橋接器裝置。這種配置的一個示例是基於裝置樹的系統,其中有關子裝置的資訊獨立於橋接器裝置提供給系統,例如,當子裝置在 DT 中定義為 I2C 裝置節點時。第二種情況中使用的 API 在下面進一步描述。
使用一種或另一種註冊方法只會影響探測過程,在兩種情況下,執行時橋接器-子裝置互動是相同的。
2.7.1.1. 註冊同步子裝置¶
在同步情況下,裝置(橋接器)驅動程式需要使用 v4l2_device 註冊 v4l2_subdev
如果 subdev 模組在註冊之前消失,則此操作可能會失敗。成功呼叫此函式後,subdev->dev 欄位指向 v4l2_device。
如果 v4l2_device 父裝置具有非 NULL mdev 欄位,則子裝置實體將自動註冊到媒體裝置。
您可以使用以下命令登出子裝置
之後,可以解除安裝 subdev 模組,並且 sd->dev == NULL。
2.7.1.2. 註冊非同步子裝置¶
在非同步情況下,可以獨立於橋接器驅動程式的可用性來呼叫子裝置探測。然後,子裝置驅動程式必須驗證是否滿足成功探測的所有要求。這可以包括檢查主時鐘的可用性。如果任何條件未滿足,驅動程式可能會決定返回 -EPROBE_DEFER 以請求進一步的重新探測嘗試。一旦滿足所有條件,應使用 v4l2_async_register_subdev() 函式註冊子裝置。登出使用 v4l2_async_unregister_subdev() 呼叫執行。以這種方式註冊的子裝置儲存在子裝置的全域性列表中,準備好被橋接器驅動程式拾取。
驅動程式必須在使能夠執行時 PM 之前,在使用 v4l2_async_register_subdev() 註冊子裝置之前完成子裝置的所有初始化。這是因為子裝置在註冊後立即變得可訪問。
2.7.1.3. 非同步子裝置通知器¶
反過來,橋接器驅動程式必須註冊一個通知器物件。這是使用 v4l2_async_nf_register() 呼叫執行的。要登出通知器,驅動程式必須呼叫 v4l2_async_nf_unregister()。在釋放未註冊通知器的記憶體之前,必須透過呼叫 v4l2_async_nf_cleanup() 來清理它。
在註冊通知器之前,橋接器驅動程式必須做兩件事:首先,必須使用 v4l2_async_nf_init() 初始化通知器。其次,橋接器驅動程式可以開始形成橋接器裝置執行所需的非同步連線描述符列表。v4l2_async_nf_add_fwnode()、v4l2_async_nf_add_fwnode_remote() 和 v4l2_async_nf_add_i2c()
非同步連線描述符描述了與外部子裝置的連線,這些子裝置的驅動程式尚未被探測。基於非同步連線,當相關的子裝置可用時,可能會建立一個媒體資料或輔助連結。可能有一個或多個到給定子裝置的非同步連線,但這在將連線新增到通知器時是未知的。非同步連線在找到匹配的非同步子裝置時,逐個繫結。
2.7.1.4. 子裝置的非同步子裝置通知器¶
註冊非同步子裝置的驅動程式也可以註冊非同步通知器。這稱為非同步子裝置通知器,該過程與橋接器驅動程式的過程類似,不同之處在於使用 v4l2_async_subdev_nf_init() 初始化通知器。只有在 V4L2 裝置可用後,即存在透過非同步子裝置和通知器到非非同步子裝置通知器的路徑時,子裝置通知器才能完成。
2.7.1.5. 攝像頭感測器驅動程式的非同步子設備註冊助手¶
v4l2_async_register_subdev_sensor() 是感測器驅動程式註冊自己的非同步連線的輔助函式,但它也註冊一個通知器,並進一步註冊韌體中找到的鏡頭和閃光裝置的非同步連線。子裝置的通知器使用 v4l2_async_unregister_subdev() 登出並與非同步子裝置一起清理。
2.7.1.6. 非同步子裝置通知器示例¶
這些函式分配一個非同步連線描述符,該描述符是型別結構體 v4l2_async_connection 嵌入到驅動程式特定的結構體中。&struct v4l2_async_connection 應是此結構體的第一個成員
struct my_async_connection {
struct v4l2_async_connection asc;
...
};
struct my_async_connection *my_asc;
struct fwnode_handle *ep;
...
my_asc = v4l2_async_nf_add_fwnode_remote(¬ifier, ep,
struct my_async_connection);
fwnode_handle_put(ep);
if (IS_ERR(my_asc))
return PTR_ERR(my_asc);
2.7.1.7. 非同步子裝置通知器回撥¶
然後,V4L2 核心將使用這些連線描述符將非同步註冊的子裝置與它們匹配。如果檢測到匹配,則呼叫 .bound() 通知器回撥。在繫結所有連線後,呼叫 .complete() 回撥。當從系統中刪除連線時,呼叫 .unbind() 方法。所有三個回撥都是可選的。
驅動程式可以在其驅動程式特定的 v4l2_async_connection 包裝器中儲存任何型別的自定義資料。如果在釋放結構體時任何資料需要特殊處理,則驅動程式必須實現 .destroy() 通知器回撥。框架將在釋放 v4l2_async_connection 之前立即呼叫它。
2.7.2. 呼叫 subdev 操作¶
使用 v4l2_subdev 的優點是它是一個通用結構體,不包含有關底層硬體的任何知識。因此,驅動程式可能包含多個使用 I2C 匯流排的 subdev,但也可能包含一個透過 GPIO 引腳控制的 subdev。這種區別僅在設定裝置時才相關,但一旦註冊 subdev,它就完全透明。
註冊 subdev 後,您可以直接呼叫 ops 函式
err = sd->ops->core->g_std(sd, &norm);
但最好且更容易使用此宏
err = v4l2_subdev_call(sd, core, g_std, &norm);
該宏將執行正確的 NULL 指標檢查,如果 sd 是 NULL,則返回 -ENODEV,如果 sd->core 或 sd->core->g_std 是 NULL,則返回 -ENOIOCTLCMD,否則返回 sd->ops->core->g_std ops 的實際結果。
也可以呼叫所有或部分子裝置
v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm);
任何不支援此 ops 的 subdev 都會被跳過,並且錯誤結果會被忽略。如果要檢查錯誤,請使用此命令
err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm);
除了 -ENOIOCTLCMD 之外的任何錯誤都將以該錯誤退出迴圈。如果沒有發生錯誤(除了 -ENOIOCTLCMD),則返回 0。
兩次呼叫的第二個引數是一個組 ID。如果為 0,則呼叫所有 subdev。如果為非零值,則僅呼叫那些組 ID 與該值匹配的 subdev。在橋接器驅動程式註冊 subdev 之前,它可以將 sd->grp_id 設定為它想要的任何值(預設為 0)。此值歸橋接器驅動程式所有,子裝置驅動程式永遠不會修改或使用它。
組 ID 使橋接器驅動程式可以更好地控制如何呼叫回撥。例如,一個板上可能有多個音訊晶片,每個晶片都能夠改變音量。但是,通常在使用者想要更改音量時,只會實際使用一個。您可以將該 subdev 的組 ID 設定為例如 AUDIO_CONTROLLER,並在呼叫 v4l2_device_call_all() 時將其指定為組 ID 值。這確保它只會轉到需要的 subdev。
如果子裝置需要將其 v4l2_device 父裝置通知事件,則它可以呼叫 v4l2_subdev_notify(sd, notification, arg)。此宏檢查是否定義了 notify() 回撥,如果未定義,則返回 -ENODEV。否則,將返回 notify() 呼叫的結果。
2.8. V4L2 子裝置使用者空間 API¶
傳統上,橋接器驅動程式向用戶空間公開一個或多個影片節點,並透過 v4l2_subdev_ops 操作來控制子裝置,以響應影片節點操作。這嚮應用程式隱藏了底層硬體的複雜性。對於複雜的裝置,可能需要比影片節點提供的更精細的裝置控制。在這些情況下,實現 媒體控制器 API 的橋接器驅動程式可以選擇直接從使用者空間訪問子裝置操作。
可以在 /dev 中建立名為 v4l-subdevX 的裝置節點以直接訪問子裝置。如果子裝置支援直接使用者空間配置,則必須在註冊之前設定 V4L2_SUBDEV_FL_HAS_DEVNODE 標誌。
註冊子裝置後,v4l2_device 驅動程式可以為所有標記有 V4L2_SUBDEV_FL_HAS_DEVNODE 的已註冊子裝置建立裝置節點,方法是呼叫 v4l2_device_register_subdev_nodes()。當登出子裝置時,這些裝置節點將被自動刪除。
裝置節點處理 V4L2 API 的子集。
VIDIOC_QUERYCTRL、VIDIOC_QUERYMENU、VIDIOC_G_CTRL、VIDIOC_S_CTRL、VIDIOC_G_EXT_CTRLS、VIDIOC_S_EXT_CTRLS 和 VIDIOC_TRY_EXT_CTRLS
控制元件 ioctl 與 V4L2 中定義的相同。它們的行為相同,唯一的例外是它們僅處理在子裝置中實現的控制元件。根據驅動程式,也可以透過一個(或多個)V4L2 裝置節點訪問這些控制元件。
VIDIOC_DQEVENT、VIDIOC_SUBSCRIBE_EVENT 和 VIDIOC_UNSUBSCRIBE_EVENT
事件 ioctl 與 V4L2 中定義的相同。它們的行為相同,唯一的例外是它們僅處理由子裝置生成的事件。根據驅動程式,也可以透過一個(或多個)V4L2 裝置節點報告這些事件。
想要使用事件的子裝置驅動程式需要在註冊子裝置之前設定
V4L2_SUBDEV_FL_HAS_EVENTSv4l2_subdev.flags。註冊後,事件可以像往常一樣在v4l2_subdev.devnode 裝置節點上排隊。為了正確支援事件,還實現了
poll()檔案操作。
私有 ioctl
上面列表中未包含的所有 ioctl 都透過 core::ioctl 操作直接傳遞給子裝置驅動程式。
2.9. 只讀子裝置使用者空間 API¶
橋接驅動程式透過直接呼叫由 v4l2_subdev_ops 結構實現的核心 API 來控制其連線的子裝置,通常不希望使用者空間能夠透過子裝置裝置節點更改相同的引數,因此通常不註冊任何內容。
有時透過只讀 API 向用戶空間報告當前子裝置配置很有用,該 API 不允許應用程式更改裝置引數,但允許與子裝置裝置節點互動以檢查它們。
例如,為了實現基於計算攝影的相機,使用者空間需要了解每個支援的輸出解析度的詳細相機感測器配置(在跳過、合併、裁剪和縮放方面)。為了支援此類用例,橋接驅動程式可以透過只讀 API 將子裝置操作公開給使用者空間。
要為所有註冊了 V4L2_SUBDEV_FL_HAS_DEVNODE 的子裝置建立只讀裝置節點,v4l2_device 驅動程式應呼叫 v4l2_device_register_ro_subdev_nodes()。
對於使用 v4l2_device_register_ro_subdev_nodes() 註冊的子裝置裝置節點,使用者空間應用程式對以下 ioctl 的訪問受到限制。
VIDIOC_SUBDEV_S_FMT、VIDIOC_SUBDEV_S_CROP、VIDIOC_SUBDEV_S_SELECTION
這些 ioctl 僅允許在只讀子裝置裝置節點上用於 V4L2_SUBDEV_FORMAT_TRY 格式和選擇矩形。
VIDIOC_SUBDEV_S_FRAME_INTERVAL、VIDIOC_SUBDEV_S_DV_TIMINGS、VIDIOC_SUBDEV_S_STD
這些 ioctl 不允許在只讀子裝置節點上使用。
如果 ioctl 不允許,或者要修改的格式設定為 V4L2_SUBDEV_FORMAT_ACTIVE,則核心將返回一個負錯誤程式碼,並且 errno 變數設定為 -EPERM。
2.10. I2C 子裝置驅動程式¶
由於這些驅動程式非常常見,因此可以使用特殊的輔助函式來簡化這些驅動程式的使用 (v4l2-common.h)。
將 v4l2_subdev 支援新增到 I2C 驅動程式的推薦方法是將 v4l2_subdev 結構嵌入到為每個 I2C 裝置例項建立的狀態結構中。非常簡單的裝置沒有狀態結構,在這種情況下,您可以直接建立一個 v4l2_subdev。
典型的狀態結構如下所示(其中 “chipname” 替換為晶片的名稱)
struct chipname_state {
struct v4l2_subdev sd;
... /* additional state fields */
};
按如下方式初始化 v4l2_subdev 結構
v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
此函式將填寫 v4l2_subdev 的所有欄位,確保 v4l2_subdev 和 i2c_client 都相互指向。
您還應該新增一個輔助行內函數,以從 v4l2_subdev 指標轉到 chipname_state 結構
static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct chipname_state, sd);
}
使用此函式從 v4l2_subdev 結構轉到 i2c_client 結構
struct i2c_client *client = v4l2_get_subdevdata(sd);
使用此函式從 i2c_client 轉到 v4l2_subdev 結構
struct v4l2_subdev *sd = i2c_get_clientdata(client);
確保在呼叫 remove() 回撥時呼叫 v4l2_device_unregister_subdev()(sd)。這將從橋接驅動程式中登出子裝置。即使從未註冊子裝置,也可以安全地呼叫此函式。
您需要這樣做,因為當橋接驅動程式銷燬 i2c 介面卡時,會呼叫該介面卡上的 i2c 裝置的 remove() 回撥。之後,相應的 v4l2_subdev 結構將無效,因此必須首先登出它們。從 remove() 回撥呼叫 v4l2_device_unregister_subdev()(sd) 可確保始終正確地完成此操作。
橋接驅動程式還有一些可以使用的輔助函式
struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter,
"module_foo", "chipid", 0x36, NULL);
這將載入給定的模組(如果沒有模組需要載入,則可以為 NULL),並使用給定的 i2c_adapter 和晶片/地址引數呼叫 i2c_new_client_device()。如果一切順利,它將向 v4l2_device 註冊子裝置。
您還可以使用 v4l2_i2c_new_subdev() 的最後一個引數來傳遞它應該探測的可能的 I2C 地址陣列。僅當上一個引數為 0 時才使用這些探測地址。非零引數意味著您知道確切的 i2c 地址,因此在這種情況下不會進行探測。
如果出現問題,這兩個函式都返回 NULL。
請注意,您傳遞給 v4l2_i2c_new_subdev() 的 chipid 通常與模組名稱相同。它允許您指定晶片變體,例如 “saa7114” 或 “saa7115”。但總的來說,i2c 驅動程式會自動檢測到這一點。chipid 的使用需要在以後更仔細地研究。它在 i2c 驅動程式之間有所不同,因此可能會造成混淆。要檢視支援哪些晶片變體,您可以檢視 i2c 驅動程式程式碼中的 i2c_device_id 表。這列出了所有可能性。
還有一個輔助函式
v4l2_i2c_new_subdev_board() 使用傳遞給 i2c 驅動程式的 i2c_board_info 結構,並替換 irq、platform_data 和 addr 引數。
如果子裝置支援 s_config core ops,則在設定子裝置後使用 irq 和 platform_data 引數呼叫該 op。
v4l2_i2c_new_subdev() 函式將呼叫 v4l2_i2c_new_subdev_board(),在內部使用 client_type 和 addr 填充 i2c_board_info 結構。
2.11. 集中管理的子裝置活動狀態¶
傳統上,V4L2 子裝置驅動程式維護活動裝置配置的內部狀態。這通常實現為例如 struct v4l2_mbus_framefmt 陣列,每個 pad 一個條目,對於裁剪和合成矩形也是如此。
除了活動配置之外,每個子裝置檔案控制代碼都有一個由 V4L2 核心管理的 struct v4l2_subdev_state,其中包含嘗試配置。
為了簡化子裝置驅動程式,V4L2 子裝置 API 現在可以選擇性地支援由 v4l2_subdev_state 表示的集中管理的活動配置。一個狀態例項(包含活動裝置配置)作為 v4l2_subdev 結構的一部分儲存在子裝置本身中,而核心將一個嘗試狀態與每個開啟的檔案控制代碼相關聯,以儲存與該檔案控制代碼相關的嘗試配置。
子裝置驅動程式可以選擇使用狀態來管理其活動配置,方法是在註冊子裝置之前呼叫 v4l2_subdev_init_finalize() 初始化子裝置狀態。它們還必須呼叫 v4l2_subdev_cleanup() 以釋放所有已分配的資源,然後才能登出子裝置。核心自動為每個開啟的檔案控制代碼分配和初始化一個狀態,以儲存嘗試配置,並在關閉檔案控制代碼時釋放它。
V4L2 子裝置操作使用 ACTIVE 和 TRY 格式,透過 “狀態” 引數接收要操作的正確狀態。狀態必須由呼叫者透過呼叫 v4l2_subdev_lock_state() 和 v4l2_subdev_unlock_state() 來鎖定和解鎖。呼叫者可以透過呼叫 v4l2_subdev_call_state_active() 宏來執行此操作。
不接收狀態引數的操作隱式地對子裝置活動狀態進行操作,驅動程式可以透過呼叫 v4l2_subdev_lock_and_get_active_state() 來獨佔訪問該狀態。子裝置活動狀態也必須透過呼叫 v4l2_subdev_unlock_state() 來釋放。
驅動程式絕不能手動訪問儲存在 v4l2_subdev 或檔案控制代碼中的狀態,而不使用指定的輔助函式。
雖然 V4L2 核心將正確的嘗試或活動狀態傳遞給子裝置操作,但許多現有裝置驅動程式在呼叫 v4l2_subdev_call() 的操作時傳遞 NULL 狀態。這種遺留結構導致子裝置驅動程式出現問題,這些驅動程式讓 V4L2 核心管理活動狀態,因為它們期望接收適當的狀態作為引數。為了幫助將子裝置驅動程式轉換為託管活動狀態,而無需同時轉換所有呼叫者,v4l2_subdev_call() 中添加了一個額外的包裝器層,它透過使用 v4l2_subdev_lock_and_get_active_state() 獲取和鎖定被呼叫者的活動狀態來處理 NULL 情況,並在呼叫後解鎖狀態。
整個子裝置狀態實際上分為三個部分:v4l2_subdev_state、子裝置控制元件和子裝置驅動程式的內部狀態。將來,這些部分應該合併為一個狀態。目前,我們需要一種方法來處理這些部分的鎖定。這可以透過共享鎖來完成。v4l2_ctrl_handler 已經透過其 “lock” 指標支援這一點,並且相同的模型也用於狀態。驅動程式可以在呼叫 v4l2_subdev_init_finalize() 之前執行以下操作
sd->ctrl_handler->lock = &priv->mutex;
sd->state_lock = &priv->mutex;
這在控制元件和狀態之間共享驅動程式的私有互斥鎖。
2.12. 流、多路複用媒體 pad 和內部路由¶
子裝置驅動程式可以透過設定 V4L2_SUBDEV_FL_STREAMS 子裝置標誌並實現對集中管理的子裝置活動狀態、路由和基於流的配置的支援來實現對多路複用流的支援。
2.13. V4L2 子裝置函式和資料結構¶
-
struct v4l2_decode_vbi_line¶
用於 decode_vbi_line
定義:
struct v4l2_decode_vbi_line {
u32 is_second_field;
u8 *p;
u32 line;
u32 type;
};
成員
is_second_field對於第一個(奇數)場,設定為 0;對於第二個(偶數)場,設定為 1。
p指向解碼器中切片的 VBI 資料的指標。退出時,指向有效負載的開始。
line切片的 VBI 資料的行號 (1-23)
typeVBI 服務型別 (V4L2_SLICED_*)。如果未找到服務,則為 0
-
enum v4l2_subdev_io_pin_bits¶
子裝置外部 IO 引腳配置位
常量
V4L2_SUBDEV_IO_PIN_DISABLE停用引腳配置。假定啟用。
V4L2_SUBDEV_IO_PIN_OUTPUT如果引腳是輸出,則設定它。
V4L2_SUBDEV_IO_PIN_INPUT如果引腳是輸入,則設定它。
V4L2_SUBDEV_IO_PIN_SET_VALUE透過
struct v4l2_subdev_io_pin_config->value 設定輸出值。V4L2_SUBDEV_IO_PIN_ACTIVE_LOW引腳活動為位 0。否則,假定為 ACTIVE HIGH。
-
struct v4l2_subdev_io_pin_config¶
子裝置外部 IO 引腳配置
定義:
struct v4l2_subdev_io_pin_config {
u32 flags;
u8 pin;
u8 function;
u8 value;
u8 strength;
};
成員
flags此引腳配置的標誌位掩碼,其位由
enum v4l2_subdev_io_pin_bits定義。pin要配置的晶片外部 IO 引腳
function要路由到 IO 引腳的內部訊號 pad/函式
value引腳的初始值 - 例如 GPIO 輸出值
strength引腳驅動強度
-
struct v4l2_subdev_core_ops¶
為子裝置定義核心 ops 回撥
定義:
struct v4l2_subdev_core_ops {
int (*log_status)(struct v4l2_subdev *sd);
int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n, struct v4l2_subdev_io_pin_config *pincfg);
int (*init)(struct v4l2_subdev *sd, u32 val);
int (*load_fw)(struct v4l2_subdev *sd);
int (*reset)(struct v4l2_subdev *sd, u32 val);
int (*s_gpio)(struct v4l2_subdev *sd, u32 val);
long (*command)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
#ifdef CONFIG_COMPAT;
long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd, unsigned long arg);
#endif;
#ifdef CONFIG_VIDEO_ADV_DEBUG;
int (*g_register)(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg);
int (*s_register)(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg);
#endif;
int (*s_power)(struct v4l2_subdev *sd, int on);
int (*interrupt_service_routine)(struct v4l2_subdev *sd, u32 status, bool *handled);
int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, struct v4l2_event_subscription *sub);
};
成員
log_status用於 VIDIOC_LOG_STATUS() ioctl 處理程式程式碼的回撥。
s_io_pin_config為晶片配置一個或多個晶片 I/O 引腳,這些晶片將不同的內部訊號 pad 多路複用到 IO 引腳。此函式採用指向 “n” 個引腳配置條目陣列的指標,每個引腳配置一個條目。此函式可以在子裝置初始化之外的其他時間呼叫。
init將感測器暫存器初始化為某種合理的預設值。不要用於新的驅動程式,應在現有驅動程式中刪除。
load_fw載入韌體。
reset通用重置命令。該引數選擇要重置的子系統。傳遞 0 將始終重置整個晶片。沒有在 linux-media 郵件列表中首先討論這一點,不要用於新的驅動程式。通常沒有理由重置裝置。
s_gpio設定 GPIO 引腳。現在很簡單,如果需要,可能需要用方向引數進行擴充套件。
command由核心驅動程式呼叫,以便呼叫子裝置驅動程式內部的具有單獨回撥的函式驅動程式。
ioctl在 V4L2 核心的 ioctl() 系統呼叫處理程式的末尾呼叫。用於提供對驅動程式上使用的私有 ioctl 的支援。
compat_ioctl32當 32 位應用程式使用 64 位核心時呼叫,以便修復從/到使用者空間傳遞的資料。
g_register用於 VIDIOC_DBG_G_REGISTER() ioctl 處理程式程式碼的回撥。
s_register用於 VIDIOC_DBG_S_REGISTER() ioctl 處理程式程式碼的回撥。
s_power將子裝置置於省電模式(on == 0)或正常操作模式(on == 1)。已棄用。請參閱 編寫相機感測器驅動程式。pre_streamon 和 post_streamoff 回撥可以用於例如在呼叫 s_stream 之前將匯流排設定為 LP-11 模式。
interrupt_service_routine當由於此子裝置而引發中斷狀態時,由橋接晶片的中斷服務處理程式呼叫,以便此子裝置可以處理詳細資訊。它可能會安排稍後執行的工作。它不得睡眠。從 IRQ 上下文中呼叫。
subscribe_event驅動程式使用它來請求控制元件框架,以便在控制元件值更改時收到警告。
unsubscribe_event從控制元件框架中刪除事件訂閱。
-
struct v4l2_subdev_tuner_ops¶
在無線電模式下開啟 v4l 裝置時使用的回撥。
定義:
struct v4l2_subdev_tuner_ops {
int (*standby)(struct v4l2_subdev *sd);
int (*s_radio)(struct v4l2_subdev *sd);
int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq);
int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);
int (*enum_freq_bands)(struct v4l2_subdev *sd, struct v4l2_frequency_band *band);
int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
int (*s_tuner)(struct v4l2_subdev *sd, const struct v4l2_tuner *vt);
int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
};
成員
standby將調諧器置於待機模式。下次使用它時,它將自動喚醒。
s_radio將調諧器切換到無線電模式的回撥。驅動程式應在無線電模式下操作調諧器 ops 時顯式呼叫它,然後才能處理它。用於同時具有 AM/FM 無線電接收器和 TV 的裝置。
s_frequency用於 VIDIOC_S_FREQUENCY() ioctl 處理程式程式碼的回撥。
g_frequency用於 VIDIOC_G_FREQUENCY() ioctl 處理程式程式碼的回撥。必須填寫 freq->type。通常由
video_ioctl2()或橋接驅動程式完成。enum_freq_bands用於 VIDIOC_ENUM_FREQ_BANDS() ioctl 處理程式程式碼的回撥。
g_tuner用於 VIDIOC_G_TUNER() ioctl 處理程式程式碼的回撥。
s_tuner用於 VIDIOC_S_TUNER() ioctl 處理程式程式碼的回撥。必須填寫 vt->type。通常由 video_ioctl2 或橋接驅動程式完成。
g_modulator用於 VIDIOC_G_MODULATOR() ioctl 處理程式程式碼的回撥。
s_modulator用於 VIDIOC_S_MODULATOR() ioctl 處理程式程式碼的回撥。
s_type_addr設定調諧器型別及其 I2C 地址。
s_config設定 tda9887 特定內容,如 port1、port2 和 qss
描述
注意
在同時具有 AM/FM 和 TV 的裝置上,由驅動程式顯式呼叫 s_radio,以便在處理其他需要它的 struct v4l2_subdev_tuner_ops 之前將調諧器切換到無線電模式。此類用法的示例是
static void s_frequency(void *priv, const struct v4l2_frequency *f)
{
...
if (f.type == V4L2_TUNER_RADIO)
v4l2_device_call_all(v4l2_dev, 0, tuner, s_radio);
...
v4l2_device_call_all(v4l2_dev, 0, tuner, s_frequency);
}
-
struct v4l2_subdev_audio_ops¶
用於音訊相關設定的回撥
定義:
struct v4l2_subdev_audio_ops {
int (*s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_i2s_clock_freq)(struct v4l2_subdev *sd, u32 freq);
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
};
成員
s_clock_freq設定音訊時鐘輸出的頻率(以 Hz 為單位)。用於將音訊處理器與影片解碼器連線起來,確保音訊和影片保持同步。頻率的常用值為 48000、44100 或 32000 Hz。如果不支援該頻率,則返回 -EINVAL。
s_i2s_clock_freq以 bps 為單位設定 I2S 速度。這用於提供一種標準方法來選擇某些板設計中用於驅動數字音訊流的 I2S 時鐘。頻率的常用值為 1024000 和 2048000。如果不支援該頻率,則返回
-EINVAL。s_routing用於定義音訊晶片的輸入和/或輸出引腳,以及任何其他配置資料。切勿嘗試在此級別使用使用者級別的輸入 ID(例如複合、S-Video、調諧器)。i2c 裝置不應該知道輸入引腳是否連線到複合聯結器,因為在另一個板或平臺上,它可能連線到完全不同的東西。呼叫驅動程式負責將使用者級別的輸入對映到 i2c 裝置上的正確引腳。
s_stream用於通知音訊程式碼流將開始或已停止。
-
struct v4l2_mbus_frame_desc_entry_csi2¶
定義:
struct v4l2_mbus_frame_desc_entry_csi2 {
u8 vc;
u8 dt;
};
成員
vcCSI-2 虛擬通道
dtCSI-2 資料型別 ID
-
enum v4l2_mbus_frame_desc_flags¶
媒體匯流排幀描述標誌
常量
V4L2_MBUS_FRAME_DESC_FL_LEN_MAX指示
struct v4l2_mbus_frame_desc_entry->length 欄位指定最大資料長度。V4L2_MBUS_FRAME_DESC_FL_BLOB指示格式沒有行偏移量,即接收器應使用 1D DMA。
-
struct v4l2_mbus_frame_desc_entry¶
媒體匯流排幀描述結構
定義:
struct v4l2_mbus_frame_desc_entry {
enum v4l2_mbus_frame_desc_flags flags;
u32 stream;
u32 pixelcode;
u32 length;
union {
struct v4l2_mbus_frame_desc_entry_csi2 csi2;
} bus;
};
成員
flags位掩碼標誌,由
enum v4l2_mbus_frame_desc_flags定義。stream路由配置中的流
pixelcode媒體匯流排畫素程式碼,如果未設定 flags
FRAME_DESC_FL_BLOB,則有效。length每幀的八位位元組數,如果設定了 flags
V4L2_MBUS_FRAME_DESC_FL_LEN_MAX,則有效。bus匯流排特定幀描述符引數
bus.csi2CSI-2 特定匯流排配置
-
enum v4l2_mbus_frame_desc_type¶
媒體匯流排幀描述型別
常量
V4L2_MBUS_FRAME_DESC_TYPE_UNDEFINED未定義的幀描述型別。驅動程式不應使用此型別,它用於向後相容。
V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL並行媒體匯流排。
V4L2_MBUS_FRAME_DESC_TYPE_CSI2CSI-2 媒體匯流排。幀描述引數必須在
struct v4l2_mbus_frame_desc_entry->csi2 中設定。
-
struct v4l2_mbus_frame_desc¶
媒體匯流排資料幀描述
定義:
struct v4l2_mbus_frame_desc {
enum v4l2_mbus_frame_desc_type type;
struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
unsigned short num_entries;
};
成員
type匯流排型別 (
enum v4l2_mbus_frame_desc_type)entry幀描述符陣列
num_entriesentry 陣列中的條目數
-
enum v4l2_subdev_pre_streamon_flags¶
用於 pre_streamon 子裝置核心 op 的標誌
常量
V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP在呼叫 s_stream() 之前,將發射器設定為 LP-11 或 LP-111 模式。
-
struct v4l2_subdev_video_ops¶
在影片模式下開啟 v4l 裝置時使用的回撥。
定義:
struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
int (*g_std_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_tvnorms_output)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
int (*s_stream)(struct v4l2_subdev *sd, int enable);
int (*g_pixelaspect)(struct v4l2_subdev *sd, struct v4l2_fract *aspect);
int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf, unsigned int *size);
int (*pre_streamon)(struct v4l2_subdev *sd, u32 flags);
int (*post_streamoff)(struct v4l2_subdev *sd);
};
成員
s_routing請參閱 audio_ops 中的 s_routing,除了此版本適用於影片裝置。
s_crystal_freq以 Hz 為單位設定用於生成時鐘的晶體頻率。一個額外的標誌欄位允許裝置進行特定的配置,例如時鐘分頻器等。如果未使用,則將標誌設定為 0。如果不支援該頻率,則返回 -EINVAL。
g_std用於 VIDIOC_G_STD() ioctl 處理程式程式碼的回撥。
s_std用於 VIDIOC_S_STD() ioctl 處理程式程式碼的回撥。
s_std_output為影片輸出裝置設定 v4l2_std_id。影片輸入裝置會忽略此設定。
g_std_output獲取影片輸出裝置當前的制式標準。影片輸入裝置會忽略此設定。
querystd用於 VIDIOC_QUERYSTD() ioctl 處理程式程式碼的回撥。
g_tvnorms獲取影片採集裝置支援的所有制式的
v4l2_std_id。影片輸出裝置會忽略此設定。g_tvnorms_output獲取影片輸出裝置支援的所有制式的 v4l2_std_id。影片採集裝置會忽略此設定。
g_input_status獲取輸入狀態。與
struct v4l2_input中的 status 欄位相同。s_stream啟動(enabled == 1)或停止(enabled == 0)子裝置上的流傳輸。停止失敗將移除流傳輸啟動時獲取的任何資源,但驅動程式仍會返回錯誤程式碼。呼叫者應跟蹤子裝置狀態,不應啟動或停止已啟動或停止的子裝置。另請參見 v4l2-subdev.c 中的 call_s_stream 包裝器。
此回撥已棄用。新的驅動程式應改為實現
v4l2_subdev_pad_ops.enable_streams和v4l2_subdev_pad_ops.disable_streams操作,併為v4l2_subdev_video_ops.s_stream操作使用 v4l2_subdev_s_stream_helper 以支援舊版使用者。驅動程式也不應直接呼叫 .s_stream() 子裝置操作,而應使用
v4l2_subdev_enable_streams()和v4l2_subdev_disable_streams()輔助函式。g_pixelaspect返回畫素寬高比的回撥。
s_rx_buffer為子裝置設定主機分配的記憶體緩衝區。子裝置可以將 size 調整為較低的值,並且從 data 開始,寫入緩衝區的資料不得超過 size 的原始值。
pre_streamon可以在實際開始流傳輸之前呼叫,以幫助初始化匯流排。當前的用法是在流傳輸之前將 CSI-2 發射器設定為 LP-11 或 LP-111 模式。請參見
enum v4l2_subdev_pre_streamon_flags。如果 pre_streamon 無法執行標誌引數指示的操作,則應返回錯誤。特別是,-EACCES 表示不支援該操作。對於每次成功呼叫 pre_streamon,呼叫者都應呼叫 post_streamoff。
post_streamoff在停止流傳輸後呼叫,但僅當之前呼叫過 pre_streamon 時才呼叫。
-
struct v4l2_subdev_vbi_ops¶
透過 vbi 裝置節點以影片模式開啟 v4l 裝置時使用的回撥。
定義:
struct v4l2_subdev_vbi_ops {
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
int (*s_raw_fmt)(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
int (*g_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
int (*s_sliced_fmt)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
};
成員
decode_vbi_line支援分片 VBI 的影片解碼器需要實現此 ioctl。
struct v4l2_decode_vbi_line的欄位 p 設定為解碼器生成的 VBI 資料的開始位置。然後,驅動程式解析分片 VBI 資料並相應地設定結構中的其他欄位。指標 p 更新為指向有效負載的開始位置,可以逐字複製到struct v4l2_sliced_vbi_data的 data 欄位中。如果沒有找到有效的 VBI 資料,則在返回時將 type 欄位設定為 0。s_vbi_data用於在影片訊號上生成 VBI 訊號。
struct v4l2_sliced_vbi_data填充了應該輸出的資料包。請注意,如果將 line 欄位設定為 0,則會停用該 VBI 訊號。如果沒有找到有效的 VBI 資料,則在返回時將 type 欄位設定為 0。g_vbi_data用於從讀取回暫存器獲取分片 VBI 資料包。並非所有影片解碼器都支援此功能。如果由於讀取回暫存器包含無效或錯誤資料而沒有可用資料,則返回
-EIO。請注意,您必須填寫“id”成員和“field”成員(以確定應獲取來自第一個還是第二個欄位的 CC 資料)。g_sliced_vbi_cap用於 VIDIOC_G_SLICED_VBI_CAP() ioctl 處理程式程式碼的回撥。
s_raw_fmt為原始 VBI 設定影片編碼器/解碼器。
g_sliced_fmt檢索當前的分片 VBI 設定。
s_sliced_fmt設定分片 VBI 設定。
-
struct v4l2_subdev_sensor_ops¶
v4l2-subdev 感測器操作
定義:
struct v4l2_subdev_sensor_ops {
int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames);
};
成員
g_skip_top_lines要跳過的影像頂部行數。某些感測器需要此設定,這些感測器總是會損壞輸出影像的幾個頂部行,或者在這些行中傳送其元資料。
g_skip_frames流開始時要跳過的幀數。對於一些有缺陷的感測器,在開啟時會生成錯誤的幀,因此需要此設定。
-
enum v4l2_subdev_ir_mode¶
描述了支援的 IR 型別
常量
V4L2_SUBDEV_IR_MODE_PULSE_WIDTHIR 使用 struct ir_raw_event 記錄
-
struct v4l2_subdev_ir_parameters¶
用於 IR TX 或 TX 的引數
定義:
struct v4l2_subdev_ir_parameters {
unsigned int bytes_per_data_element;
enum v4l2_subdev_ir_mode mode;
bool enable;
bool interrupt_enable;
bool shutdown;
bool modulation;
u32 max_pulse_width;
unsigned int carrier_freq;
unsigned int duty_cycle;
bool invert_level;
bool invert_carrier_sense;
u32 noise_filter_min_width;
unsigned int carrier_range_lower;
unsigned int carrier_range_upper;
u32 resolution;
};
成員
bytes_per_data_element讀取或寫入呼叫中每個資料元素佔用的位元組數。
mode由
enum v4l2_subdev_ir_mode定義的 IR 模式。enable如果為 true,則裝置處於活動狀態
interrupt_enable如果為 true,則啟用 IR 中斷
shutdown如果為 true:將硬體設定為低/無功耗模式;false:正常模式
modulation如果為 true,則使用載波;如果為 false,則使用基帶
max_pulse_width最大脈衝寬度,以納秒為單位,僅對基帶訊號有效
carrier_freq載波頻率,以赫茲為單位,僅對調製訊號有效
duty_cycle佔空比百分比,僅對調製訊號有效
invert_level反轉訊號電平
invert_carrier_sense將 0/space 作為載波突發傳送。僅在 TX 中使用。
noise_filter_min_width有效脈衝的最小時間,以納秒為單位。僅用於 RX。
carrier_range_lower較低的載波範圍,以赫茲為單位,僅對調製訊號有效。僅用於 RX。
carrier_range_upper較高的載波範圍,以赫茲為單位,僅對調製訊號有效。僅用於 RX。
resolution接收解析度,以納秒為單位。僅用於 RX。
-
struct v4l2_subdev_ir_ops¶
用於 IR 子裝置的操作
定義:
struct v4l2_subdev_ir_ops {
int (*rx_read)(struct v4l2_subdev *sd, u8 *buf, size_t count, ssize_t *num);
int (*rx_g_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*rx_s_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*tx_write)(struct v4l2_subdev *sd, u8 *buf, size_t count, ssize_t *num);
int (*tx_g_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
int (*tx_s_parameters)(struct v4l2_subdev *sd, struct v4l2_subdev_ir_parameters *params);
};
成員
rx_read讀取接收到的程式碼或脈衝寬度資料。語義與非阻塞 read() 呼叫類似。
rx_g_parameters獲取 IR 接收器的當前操作引數和狀態。
rx_s_parameters設定 IR 接收器的當前操作引數和狀態。建議首先呼叫 [rt]x_g_parameters 來填寫當前狀態,然後只更改需要更改的欄位。返回時,將返回實際的裝置操作引數和狀態。請注意,硬體限制可能會阻止實際設定與請求的設定匹配 - 例如,當請求 36,000 Hz 時,實際載波設定為 35,904 Hz。例外情況是 shutdown 引數為 true。將返回上次使用的操作引數,但硬體的實際狀態可能不同,以最大限度地減少功耗和處理(當 shutdown 為 true 時)。
tx_write寫入程式碼或脈衝寬度資料以進行傳輸。語義與非阻塞 write() 呼叫類似。
tx_g_parameters獲取 IR 發射器的當前操作引數和狀態。
tx_s_parameters設定 IR 發射器的當前操作引數和狀態。建議首先呼叫 [rt]x_g_parameters 來填寫當前狀態,然後只更改需要更改的欄位。返回時,將返回實際的裝置操作引數和狀態。請注意,硬體限制可能會阻止實際設定與請求的設定匹配 - 例如,當請求 36,000 Hz 時,實際載波設定為 35,904 Hz。例外情況是 shutdown 引數為 true。將返回上次使用的操作引數,但硬體的實際狀態可能不同,以最大限度地減少功耗和處理(當 shutdown 為 true 時)。
-
struct v4l2_subdev_pad_config¶
用於儲存 subdev pad 資訊。
定義:
struct v4l2_subdev_pad_config {
struct v4l2_mbus_framefmt format;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_fract interval;
};
成員
formatcrop用於裁剪的
struct v4l2_rectcompose用於合成的
struct v4l2_rectinterval幀間隔
-
struct v4l2_subdev_stream_config¶
用於儲存流配置。
定義:
struct v4l2_subdev_stream_config {
u32 pad;
u32 stream;
bool enabled;
struct v4l2_mbus_framefmt fmt;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_fract interval;
};
成員
padpad 編號
streamstream number
enabled是否已使用
v4l2_subdev_enable_streams()啟用流fmtcrop用於裁剪的
struct v4l2_rectcompose用於合成的
struct v4l2_rectinterval幀間隔
描述
此結構儲存流的配置。
-
struct v4l2_subdev_stream_configs¶
流配置的集合。
定義:
struct v4l2_subdev_stream_configs {
u32 num_configs;
struct v4l2_subdev_stream_config *configs;
};
成員
num_configsconfig 中的條目數。
configs
-
struct v4l2_subdev_krouting¶
subdev 路由表
定義:
struct v4l2_subdev_krouting {
unsigned int len_routes;
unsigned int num_routes;
struct v4l2_subdev_route *routes;
};
成員
len_routesroutes 陣列的長度,以路由為單位
num_routes路由數
routesstruct v4l2_subdev_route
描述
此結構包含子裝置的路由表。
-
struct v4l2_subdev_state¶
用於儲存 subdev 狀態資訊。
定義:
struct v4l2_subdev_state {
struct mutex _lock;
struct mutex *lock;
struct v4l2_subdev *sd;
struct v4l2_subdev_pad_config *pads;
struct v4l2_subdev_krouting routing;
struct v4l2_subdev_stream_configs stream_configs;
};
成員
_lock“鎖”的預設值
lock狀態的互斥鎖。可以由使用者替換。
sd狀態相關的子裝置
padsrouting子裝置的路由表
stream_configs流配置(僅適用於 V4L2_SUBDEV_FL_STREAMS)
描述
只有在主引數的“which”欄位設定為 V4L2_SUBDEV_FORMAT_TRY 時,才需要將此結構傳遞給 pad 操作。對於 V4L2_SUBDEV_FORMAT_ACTIVE,傳遞 NULL 是安全的。
-
struct v4l2_subdev_pad_ops¶
v4l2-subdev pad 級別操作
定義:
struct v4l2_subdev_pad_ops {
int (*enum_mbus_code)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code);
int (*enum_frame_size)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse);
int (*enum_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie);
int (*get_fmt)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_format *format);
int (*set_fmt)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_format *format);
int (*get_selection)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel);
int (*set_selection)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_selection *sel);
int (*get_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *interval);
int (*set_frame_interval)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *interval);
int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
int (*s_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*g_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*query_dv_timings)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_dv_timings *timings);
int (*dv_timings_cap)(struct v4l2_subdev *sd, struct v4l2_dv_timings_cap *cap);
int (*enum_dv_timings)(struct v4l2_subdev *sd, struct v4l2_enum_dv_timings *timings);
#ifdef CONFIG_MEDIA_CONTROLLER;
int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt);
#endif ;
int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *fd);
int (*get_mbus_config)(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_config *config);
int (*set_routing)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state,enum v4l2_subdev_format_whence which, struct v4l2_subdev_krouting *route);
int (*enable_streams)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, u32 pad, u64 streams_mask);
int (*disable_streams)(struct v4l2_subdev *sd,struct v4l2_subdev_state *state, u32 pad, u64 streams_mask);
};
成員
enum_mbus_code用於 VIDIOC_SUBDEV_ENUM_MBUS_CODE() ioctl 處理程式程式碼的回撥。
enum_frame_size用於 VIDIOC_SUBDEV_ENUM_FRAME_SIZE() ioctl 處理程式程式碼的回撥。
enum_frame_interval用於 VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL() ioctl 處理程式程式碼的回撥。
get_fmt用於 VIDIOC_SUBDEV_G_FMT() ioctl 處理程式程式碼的回撥。
set_fmt用於 VIDIOC_SUBDEV_S_FMT() ioctl 處理程式程式碼的回撥。
get_selection用於 VIDIOC_SUBDEV_G_SELECTION() ioctl 處理程式程式碼的回撥。
set_selection用於 VIDIOC_SUBDEV_S_SELECTION() ioctl 處理程式程式碼的回撥。
get_frame_interval用於 VIDIOC_SUBDEV_G_FRAME_INTERVAL() ioctl 處理程式程式碼的回撥。
set_frame_interval用於 VIDIOC_SUBDEV_S_FRAME_INTERVAL() ioctl 處理程式程式碼的回撥。
get_edid用於 VIDIOC_SUBDEV_G_EDID() ioctl 處理程式程式碼的回撥。
set_edid用於 VIDIOC_SUBDEV_S_EDID() ioctl 處理程式程式碼的回撥。
s_dv_timings在子裝置中設定自定義 dv 時序。當子裝置能夠在硬體中設定詳細的時序資訊以生成/檢測影片訊號時,將使用此功能。
g_dv_timings在子裝置中獲取自定義 dv 時序。
query_dv_timings用於 VIDIOC_QUERY_DV_TIMINGS() ioctl 處理程式程式碼的回撥。
dv_timings_cap用於 VIDIOC_SUBDEV_DV_TIMINGS_CAP() ioctl 處理程式程式碼的回撥。
enum_dv_timings用於 VIDIOC_SUBDEV_ENUM_DV_TIMINGS() ioctl 處理程式程式碼的回撥。
link_validate由媒體控制器程式碼使用,以檢查屬於管道的連結是否可用於流傳輸。
get_frame_desc獲取當前的低級別媒體匯流排幀引數。
set_frame_desc設定低級別媒體匯流排幀引數,fd 陣列可以由 subdev 驅動程式調整到裝置功能。
get_mbus_config獲取遠端子裝置的媒體匯流排配置。媒體匯流排配置通常在子裝置探測時從韌體介面檢索,立即應用於硬體,並最終由驅動程式調整。遠端子裝置(通常是影片接收器)應使用此操作來查詢傳送端匯流排配置,以便相應地調整自己的匯流排配置。呼叫者應確保他們從遠端端獲取儘可能最新的配置,可能會盡可能接近流傳輸時間呼叫此操作。如果已呼叫的 pad 索引無效或發生不可恢復的故障,則該操作將失敗。在呼叫操作之前,已將 config 引數 memset 為 0。
set_routing啟用或停用子裝置路由表中描述的資料連線路由。實現此操作的 Subdevs 必須設定 V4L2_SUBDEV_FL_STREAMS 標誌。
enable_streams在給定的源 pad 上啟用 streams_mask 中定義的流。實現此操作的 Subdevs 必須使用 subdev 核心提供的活動狀態管理(透過在初始化時呼叫
v4l2_subdev_init_finalize()啟用)。不要直接呼叫,請改用v4l2_subdev_enable_streams()。如果驅動程式僅支援單個流而不設定 V4L2_SUBDEV_CAP_STREAMS 子裝置功能標誌,則可以忽略 mask 引數。
disable_streams在給定的源 pad 上停用 streams_mask 中定義的流。實現此操作的 Subdevs 必須使用 subdev 核心提供的活動狀態管理(透過在初始化時呼叫
v4l2_subdev_init_finalize()啟用)。不要直接呼叫,請改用v4l2_subdev_disable_streams()。如果驅動程式僅支援單個流而不設定 V4L2_SUBDEV_CAP_STREAMS 子裝置功能標誌,則可以忽略 mask 引數。
-
struct v4l2_subdev_ops¶
Subdev 操作
定義:
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
成員
core指向
struct v4l2_subdev_core_ops的指標。可以為NULLtuner指向
struct v4l2_subdev_tuner_ops的指標。可以為NULLaudio指向
struct v4l2_subdev_audio_ops的指標。可以為NULLvideo指向
struct v4l2_subdev_video_ops的指標。可以為NULLvbi指向
struct v4l2_subdev_vbi_ops的指標。可以為NULLir指向
struct v4l2_subdev_ir_ops的指標。可以為NULLsensor指向
struct v4l2_subdev_sensor_ops的指標。可以為NULLpad指向
struct v4l2_subdev_pad_ops的指標。可以為NULL
-
struct v4l2_subdev_internal_ops¶
V4L2 subdev 內部操作
定義:
struct v4l2_subdev_internal_ops {
int (*init_state)(struct v4l2_subdev *sd, struct v4l2_subdev_state *state);
int (*registered)(struct v4l2_subdev *sd);
void (*unregistered)(struct v4l2_subdev *sd);
int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
void (*release)(struct v4l2_subdev *sd);
};
成員
init_state將 subdev 狀態初始化為預設值
registered在此 subdev 註冊時呼叫。呼叫時,v4l2_dev 欄位設定為正確的 v4l2_device。
unregistered在此 subdev 登出時呼叫。呼叫時,v4l2_dev 欄位仍設定為正確的 v4l2_device。
open當應用程式開啟 subdev 裝置節點時呼叫。
close當 subdev 裝置節點關閉時呼叫。請注意,可能在 unregistered 之後呼叫 close!
release當 subdev 裝置的最後一個使用者消失時呼叫。這發生在 unregistered 回撥之後,並且當 v4l-subdevX 裝置節點的最後一個開啟的檔案控制代碼關閉時。如果沒有為此子裝置建立裝置節點,則在 unregistered 回撥之後立即呼叫 release 回撥。release 回撥通常用於釋放包含 v4l2_subdev 結構的記憶體。對於設定 V4L2_SUBDEV_FL_HAS_DEVNODE 標誌的任何子裝置,幾乎肯定需要此回撥。
描述
注意
永遠不要從驅動程式中呼叫此函式,只有 v4l2 框架可以呼叫這些操作。
-
struct v4l2_subdev_platform_data¶
regulators 配置結構
定義:
struct v4l2_subdev_platform_data {
struct regulator_bulk_data *regulators;
int num_regulators;
void *host_priv;
};
成員
regulators用於開啟/關閉 subdevice 的可選 regulators
num_regulatorsRegululators 的數量
host_priv每個子裝置的資料,特定於某個影片主機裝置
-
struct v4l2_subdev¶
描述 V4L2 子裝置
定義:
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER);
struct media_entity entity;
#endif;
struct list_head list;
struct module *owner;
bool owner_v4l2_dev;
u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;
const struct v4l2_subdev_internal_ops *internal_ops;
struct v4l2_ctrl_handler *ctrl_handler;
char name[52];
u32 grp_id;
void *dev_priv;
void *host_priv;
struct video_device *devnode;
struct device *dev;
struct fwnode_handle *fwnode;
struct list_head async_list;
struct list_head async_subdev_endpoint_list;
struct v4l2_async_notifier *subdev_notifier;
struct list_head asc_list;
struct v4l2_subdev_platform_data *pdata;
struct mutex *state_lock;
struct led_classdev *privacy_led;
struct v4l2_subdev_state *active_state;
u64 enabled_pads;
bool s_stream_enabled;
};
成員
entity指向
struct media_entity的指標list子裝置列表
owner所有者與驅動程式的
struct device所有者相同。owner_v4l2_dev如果
sd->owner與 v4l2_dev->dev 所有者的所有者匹配,則為 true。由v4l2_device_register_subdev()初始化。flagssubdev 標誌。可以是:
V4L2_SUBDEV_FL_IS_I2C- 如果此 subdev 是 i2c 裝置,則設定此標誌;V4L2_SUBDEV_FL_IS_SPI- 如果此 subdev 是 spi 裝置,則設定此標誌;V4L2_SUBDEV_FL_HAS_DEVNODE- 如果此 subdev 需要裝置節點,則設定此標誌;V4L2_SUBDEV_FL_HAS_EVENTS- 如果此 subdev 生成事件,則設定此標誌。v4l2_dev指向 struct
v4l2_device的指標ops指向 struct
v4l2_subdev_ops的指標internal_ops指向 struct
v4l2_subdev_internal_ops的指標。永遠不要從驅動程式中呼叫這些內部操作!ctrl_handler此 subdev 的控制處理程式。可以為 NULL。
nameSub-device 的名稱。請注意,名稱必須是唯一的。
grp_id可用於對類似的 subdevs 進行分組。值是特定於驅動程式的
dev_priv指向私有資料的指標
host_priv指向裝置附加的 subdev 使用的私有資料的指標。
devnodesubdev 裝置節點
dev指向物理裝置的指標(如果有)
fwnodesubdev 的 fwnode_handle,通常與 dev->of_node->fwnode 或 dev->fwnode 相同(以非 NULL 者為準)。
async_list將此 subdev 連結到全域性 subdev_list 或 notifier->done_list 列表。
async_subdev_endpoint_liststruct v4l2_async_subdev_endpoint的 async_subdev_endpoint_entry 中的列表條目。subdev_notifier使用
v4l2_async_register_subdev_sensor()為 sub- device 隱式註冊的子裝置通知程式。asc_list非同步連線列表,
struct v4l2_async_connection.subdev_entry。pdatasubdevice 平臺數據的公共部分
state_lock指向用於所有 subdev 狀態的鎖的指標,由驅動程式設定。這是可選的。如果為 NULL,則每個狀態例項將獲得自己的鎖。
privacy_led指向感測器隱私 LED 的 LED classdev 的可選指標。
active_statesubdev 的活動狀態(對於內部跟蹤狀態的 subdevs,為 NULL)。透過呼叫
v4l2_subdev_init_finalize()初始化。enabled_pads由
v4l2_subdev_enable_streams()和v4l2_subdev_disable_streams()輔助函式(用於回退情況)使用的已啟用 pads 的位掩碼。s_stream_enabled跟蹤是否已使用 s_stream 啟用流傳輸。這僅用於 call_s_stream() 內部使用。
描述
subdev 驅動程式的每個例項都應建立此結構,無論是獨立的還是嵌入在更大的結構中。
此結構應由 v4l2_subdev_init() 或其變體之一初始化:v4l2_spi_subdev_init()、v4l2_i2c_subdev_init()。
-
media_entity_to_v4l2_subdev¶
media_entity_to_v4l2_subdev (ent)
從嵌入的
struct media_entity返回struct v4l2_subdev。
Parameters
ent指向
struct media_entity的指標。
-
vdev_to_v4l2_subdev¶
vdev_to_v4l2_subdev (vdev)
從嵌入它的
struct video_device返回struct v4l2_subdev。
Parameters
vdev指向
struct video_device的指標
-
struct v4l2_subdev_fh¶
用於儲存每個檔案控制代碼的 subdev 資訊
定義:
struct v4l2_subdev_fh {
struct v4l2_fh vfh;
struct module *owner;
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API);
struct v4l2_subdev_state *state;
u64 client_caps;
#endif;
};
成員
vfh指向
struct v4l2_fh的指標owner指向此檔案控制代碼所有者的模組指標
state指向
struct v4l2_subdev_state的指標client_capsV4L2_SUBDEV_CLIENT_CAP_*的位掩碼
-
to_v4l2_subdev_fh¶
to_v4l2_subdev_fh (fh)
從嵌入它的
struct v4l2_fh返回struct v4l2_subdev_fh。
Parameters
fh指向
struct v4l2_fh的指標
-
void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)¶
設定 V4L2 dev 私有裝置資料
Parameters
struct v4l2_subdev *sd指向
struct v4l2_subdev的指標void *p指向要儲存的私有裝置資料的指標。
-
void *v4l2_get_subdevdata(const struct v4l2_subdev *sd)¶
獲取 V4L2 dev 私有裝置資料
-
void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)¶
設定 V4L2 dev 私有主機資料
Parameters
struct v4l2_subdev *sd指向
struct v4l2_subdev的指標void *p指向要儲存的私有資料的指標。
-
void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)¶
獲取 V4L2 dev 私有資料
-
int v4l2_subdev_get_fwnode_pad_1_to_1(struct media_entity *entity, struct fwnode_endpoint *endpoint)¶
從 subdev fwnode 端點獲取 pad 編號,假設 1:1 埠:pad
Parameters
struct media_entity *entity指向 subdev 實體的指標
struct fwnode_endpoint *endpoint指向已解析的 fwnode 端點的指標
描述
對於將埠號和 pad 索引 1:1 對映的子裝置,此函式可以用作 .get_fwnode_pad 操作。 如果端點由子裝置擁有,則該函式返回端點埠號。
成功時返回端點埠號,否則返回負錯誤程式碼。
-
int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd, struct media_link *link, struct v4l2_subdev_format *source_fmt, struct v4l2_subdev_format *sink_fmt)¶
驗證媒體連結
Parameters
struct v4l2_subdev *sd指向
struct v4l2_subdev的指標struct media_link *link指向
struct media_link的指標struct v4l2_subdev_format *source_fmt指向
struct v4l2_subdev_format的指標struct v4l2_subdev_format *sink_fmt指向
struct v4l2_subdev_format的指標
描述
此函式確保連結的源和目標上的寬度、高度和媒體匯流排畫素程式碼相等。
-
int v4l2_subdev_link_validate(struct media_link *link)¶
驗證媒體連結
Parameters
struct media_link *link指向
struct media_link的指標
描述
此函式呼叫 subdev 的 link_validate ops 來驗證媒體連結是否對流式傳輸有效。 它還在內部呼叫 v4l2_subdev_link_validate_default() 以確保連結的源和目標上的寬度、高度和媒體匯流排畫素程式碼相等。
該函式可用作 v4l2_subdev 例項的直接 media_entity_ops.link_validate 實現。 它支援子裝置之間的所有連結,以及子裝置和影片裝置之間的連結,前提是影片裝置也實現了它們的 media_entity_ops.link_validate 操作。
-
bool v4l2_subdev_has_pad_interdep(struct media_entity *entity, unsigned int pad0, unsigned int pad1)¶
子裝置的 MC has_pad_interdep 實現
Parameters
struct media_entity *entity指向
struct media_entity的指標unsigned int pad0第一個 pad 的 pad 編號
unsigned int pad1第二個 pad 的 pad 編號
描述
此函式是 media_entity_operations.has_pad_interdep 操作的實現,適用於實現多路複用流 API 的子裝置(如 V4L2_SUBDEV_FL_STREAMS 子裝置標誌所示)。
如果 pad0 和 pad1 之間存在活動路由,則它認為兩個 pad 是相互依賴的。
-
struct v4l2_subdev_state *__v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name, struct lock_class_key *key)¶
分配 v4l2_subdev_state
Parameters
struct v4l2_subdev *sd指向
struct v4l2_subdev的指標,為其分配狀態。const char *lock_name狀態鎖的名稱
struct lock_class_key *key鎖的 lock_class_key
描述
當不再需要狀態時,必須呼叫 __v4l2_subdev_state_free()。
不要由驅動程式直接呼叫。
-
void __v4l2_subdev_state_free(struct v4l2_subdev_state *state)¶
釋放 v4l2_subdev_state
Parameters
struct v4l2_subdev_state *state要釋放的 v4l2_subdev_state。
描述
不要由驅動程式直接呼叫。
-
v4l2_subdev_init_finalize¶
v4l2_subdev_init_finalize (sd)
完成子裝置的初始化
Parameters
sd子裝置
描述
此函式完成子裝置的初始化,包括為子裝置分配活動狀態。
在使用集中式活動狀態的子裝置驅動程式初始化 subdev struct 並呼叫 media_entity_pads_init() 之後,但在註冊 subdev 之前,必須呼叫此函式。
在刪除子裝置時,使用者必須呼叫 v4l2_subdev_cleanup()。
-
void v4l2_subdev_cleanup(struct v4l2_subdev *sd)¶
釋放子裝置分配的資源
Parameters
struct v4l2_subdev *sd子裝置
描述
清除 V4L2 非同步子裝置。 如果資源已使用 v4l2_async_subdev_endpoint_add() 或 v4l2_subdev_init_finalize() 與之關聯,則必須在釋放子裝置時呼叫此函式。
-
v4l2_subdev_state_get_format¶
v4l2_subdev_state_get_format (state, pad, ...)
獲取指向流格式的指標
Parameters
state子裝置狀態
padpad id
...流 id(可選引數)
描述
這會為子裝置狀態中給定的 pad + 流返回指向 struct v4l2_mbus_framefmt 的指標。
對於不知道流的驅動程式,會返回相應 pad 的格式。 如果 pad 不存在,則返回 NULL。
-
v4l2_subdev_state_get_crop¶
v4l2_subdev_state_get_crop (state, pad, ...)
獲取指向流裁剪矩形的指標
Parameters
state子裝置狀態
padpad id
...流 id(可選引數)
描述
這會為子裝置狀態中給定的 pad + 流返回指向裁剪矩形的指標。
對於不知道流的驅動程式,會返回相應 pad 的裁剪矩形。 如果 pad 不存在,則返回 NULL。
-
v4l2_subdev_state_get_compose¶
v4l2_subdev_state_get_compose (state, pad, ...)
獲取指向流合成矩形的指標
Parameters
state子裝置狀態
padpad id
...流 id(可選引數)
描述
這會為子裝置狀態中給定的 pad + 流返回指向合成矩形的指標。
對於不知道流的驅動程式,會返回相應 pad 的合成矩形。 如果 pad 不存在,則返回 NULL。
-
v4l2_subdev_state_get_interval¶
v4l2_subdev_state_get_interval (state, pad, ...)
獲取指向流幀間隔的指標
Parameters
state子裝置狀態
padpad id
...流 id(可選引數)
描述
這會為子裝置狀態中給定的 pad + 流返回指向幀間隔的指標。
對於不知道流的驅動程式,會返回相應 pad 的幀間隔。 如果 pad 不存在,則返回 NULL。
-
int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_format *format)¶
基於狀態填充格式
Parameters
struct v4l2_subdev *sd子裝置
struct v4l2_subdev_state *state子裝置狀態
struct v4l2_subdev_format *format指向
struct v4l2_subdev_format的指標
描述
基於 format 結構中的資訊填充 format->format 欄位。
如果 subdev 驅動程式不需要在其 get_fmt op 中執行任何特殊操作,則支援活動狀態的 subdev 驅動程式可以使用此函式來實現 v4l2_subdev_pad_ops.get_fmt。
成功時返回 0,否則返回錯誤值。
-
int v4l2_subdev_get_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval *fi)¶
基於狀態填充幀間隔
Parameters
struct v4l2_subdev *sd子裝置
struct v4l2_subdev_state *state子裝置狀態
struct v4l2_subdev_frame_interval *fi指向
struct v4l2_subdev_frame_interval的指標
描述
基於 fi 結構中的資訊填充 fi->interval 欄位。
如果 subdev 驅動程式不需要在其 get_frame_interval op 中執行任何特殊操作,則支援活動狀態的 subdev 驅動程式可以使用此函式來實現 v4l2_subdev_pad_ops.get_frame_interval。
成功時返回 0,否則返回錯誤值。
-
int v4l2_subdev_set_routing(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing)¶
將給定路由設定為 subdev 狀態
Parameters
struct v4l2_subdev *sd子裝置
struct v4l2_subdev_state *state子裝置狀態
const struct v4l2_subdev_krouting *routing將複製到 subdev 狀態的路由
描述
這將從狀態中釋放舊路由表(如果存在),為給定路由分配足夠的空間,並複製路由。
這可以從 subdev 驅動程式的 set_routing op 中使用,在驗證路由之後。
-
for_each_active_route¶
for_each_active_route (routing, route)
迭代路由表的所有活動路由
Parameters
routing路由表
route路由迭代器
-
int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, const struct v4l2_subdev_krouting *routing, const struct v4l2_mbus_framefmt *fmt)¶
將給定的路由和格式設定為 subdev 狀態
Parameters
struct v4l2_subdev *sd子裝置
struct v4l2_subdev_state *state子裝置狀態
const struct v4l2_subdev_krouting *routing將複製到 subdev 狀態的路由
const struct v4l2_mbus_framefmt *fmt用於初始化所有流的格式
描述
這與 v4l2_subdev_set_routing 相同,但還會使用給定的格式初始化所有流。
-
int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing, u32 pad, u32 stream, u32 *other_pad, u32 *other_stream)¶
查詢相反的流
Parameters
const struct v4l2_subdev_krouting *routing用於查詢另一側的路由
u32 padpad id
u32 stream流 id
u32 *other_pad用於返回相反 pad 的指標
u32 *other_stream用於返回相反流的指標
描述
此函式使用路由表查詢與給定 pad + 流相反的 pad + 流。
如果呼叫方不需要該值,則 other_pad 和/或 other_stream 可以為 NULL。
成功時返回 0,如果未找到匹配的路由,則返回 -EINVAL。
-
struct v4l2_mbus_framefmt *v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state, u32 pad, u32 stream)¶
獲取指向相反流格式的指標
Parameters
struct v4l2_subdev_state *state子裝置狀態
u32 padpad id
u32 stream流 id
描述
這會為子裝置狀態中與給定 pad + 流相反的 pad + 流返回指向 struct v4l2_mbus_framefmt 的指標。
如果狀態不包含給定的 pad + 流,則返回 NULL。
-
u64 v4l2_subdev_state_xlate_streams(const struct v4l2_subdev_state *state, u32 pad0, u32 pad1, u64 *streams)¶
將流從一個 pad 轉換為另一個 pad
Parameters
const struct v4l2_subdev_state *state子裝置狀態
u32 pad0第一個 pad
u32 pad1第二個 pad
u64 *streams第一個 pad 上的流位掩碼
描述
subdev 的 sink pad 上的流根據 subdev 狀態路由表中的表示式路由到源 pad。 流編號在路由的 sink 和源側不一定匹配。 此函式使用 state 中的路由表將 pad0 上的流(表示為 streams 中的位掩碼)轉換為 pad1 上的相應流。 它返回 pad1 上的流掩碼,並使用在路由表中找到的流更新 streams。
pad0 和 pad1 必須是 sink 和源,順序不限。
返回
路由到 pad0 上的 streams 的 pad1 的流的位掩碼。
-
enum v4l2_subdev_routing_restriction¶
子裝置內部路由限制
常量
V4L2_SUBDEV_ROUTING_NO_1_TO_N輸入流不應路由到多個輸出流(流重複)
V4L2_SUBDEV_ROUTING_NO_N_TO_1多個輸入流不應路由到同一個輸出流(流合併)
V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX來自 sink pad 的所有流必須路由到單個源 pad
V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX源 pad 上的所有流必須源自單個 sink pad
V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXINGsink pad 不應包含多路複用流
V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING源 pad 不應包含多路複用流
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1僅允許非重疊的 1 對 1 流路由(V4L2_SUBDEV_ROUTING_NO_1_TO_N 和 V4L2_SUBDEV_ROUTING_NO_N_TO_1 的組合)
V4L2_SUBDEV_ROUTING_NO_STREAM_MIX來自 sink pad 的所有流必須路由到單個源 pad,並且該源 pad 不應從任何其他 sink pad 獲取路由(V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX 和 V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX 的組合)
V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING在源端或 sink 端都不允許使用多路複用流。
-
int v4l2_subdev_routing_validate(struct v4l2_subdev *sd, const struct v4l2_subdev_krouting *routing, enum v4l2_subdev_routing_restriction disallow)¶
驗證路由是否符合驅動程式約束
Parameters
struct v4l2_subdev *sd子裝置
const struct v4l2_subdev_krouting *routing要驗證的路由
enum v4l2_subdev_routing_restriction disallow路由限制
描述
這會驗證給定的路由是否符合 disallow 約束。
成功時返回 0,否則返回錯誤值。
-
int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask)¶
在 pad 上啟用流
Parameters
struct v4l2_subdev *sd子裝置
u32 padpad
u64 streams_mask要啟用的流的位掩碼
描述
此函式在子裝置的源 pad 上啟用流。 pad 由其索引標識,而流由 streams_mask 位掩碼標識。 這允許一次在 pad 上啟用多個流。
不允許啟用已啟用的流。 如果 streams_mask 包含已啟用的流,則此函式將返回 -EALREADY,而不執行任何操作。
每個流啟用僅適用於實現 .enable_streams() 和 .disable_streams() 操作的子裝置。 對於其他子裝置,此函式透過呼叫 .s_stream() 操作來實現最大程度的相容性,該操作僅限於具有單個源 pad 的子裝置。
不知道流的驅動程式應將 streams_mask 設定為 BIT_ULL(0)。
返回
0:成功
-EALREADY:streams_mask 中的一個流已啟用
-EINVAL: pad 索引無效,或者不對應於源 pad
-EOPNOTSUPP: 無法回退到舊的 .s_stream() 操作,因為 subdev 有多個源 pad
-
int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad, u64 streams_mask)¶
停用 pad 上的流
Parameters
struct v4l2_subdev *sd子裝置
u32 padpad
u64 streams_mask要停用的流的位掩碼
描述
此函式停用子裝置的源 pad 上的流。 pad 由其索引標識,而流由 streams_mask 位掩碼標識。這允許一次停用 pad 上的多個流。
不允許停用未啟用的流。如果 streams_mask 包含停用的流,則此函式返回 -EALREADY 而不執行任何操作。
每個流的停用僅適用於實現 .enable_streams() 和 .disable_streams() 操作的 subdev。對於其他 subdev,此函式透過呼叫 .s_stream() 操作來實現盡力而為的相容性,僅限於具有單個源 pad 的 subdev。
不知道流的驅動程式應將 streams_mask 設定為 BIT_ULL(0)。
返回
0:成功
-EALREADY: streams_mask 中的一個流未啟用
-EINVAL: pad 索引無效,或者不對應於源 pad
-EOPNOTSUPP: 無法回退到舊的 .s_stream() 操作,因為 subdev 有多個源 pad
-
int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)¶
使用 enable_streams 和 disable_streams 實現 subdev s_stream 操作的輔助函式
Parameters
struct v4l2_subdev *sd子裝置
int enable啟用或停用流式傳輸
描述
實現流感知的 v4l2_subdev_pad_ops.enable_streams 和 v4l2_subdev_pad_ops.disable_streams 操作的子裝置驅動程式可以使用此輔助函式來實現舊的 v4l2_subdev_video_ops.s_stream 操作。
此輔助函式只能由具有單個源 pad 的 subdev 使用。
返回
成功時為 0,否則為負錯誤程式碼。
-
void v4l2_subdev_lock_state(struct v4l2_subdev_state *state)¶
鎖定 subdev 狀態
Parameters
struct v4l2_subdev_state *state子裝置狀態
描述
鎖定給定的 subdev 狀態。
使用後必須使用 v4l2_subdev_unlock_state() 解鎖該狀態。
-
void v4l2_subdev_unlock_state(struct v4l2_subdev_state *state)¶
解鎖 subdev 狀態
Parameters
struct v4l2_subdev_state *state子裝置狀態
描述
解鎖給定的 subdev 狀態。
-
void v4l2_subdev_lock_states(struct v4l2_subdev_state *state1, struct v4l2_subdev_state *state2)¶
鎖定兩個子裝置狀態
Parameters
struct v4l2_subdev_state *state1一個子裝置狀態
struct v4l2_subdev_state *state2另一個子裝置狀態
描述
鎖定兩個子裝置的狀態。
使用後必須使用 v4l2_subdev_unlock_states() 解鎖這些狀態。
這不同於對兩個狀態都呼叫 v4l2_subdev_lock_state(),這樣如果狀態共享同一個鎖,則鎖只會被獲取一次(因此不會發生死鎖)。呼叫者負責確保鎖將始終以相同的順序獲取。
-
void v4l2_subdev_unlock_states(struct v4l2_subdev_state *state1, struct v4l2_subdev_state *state2)¶
解鎖兩個子裝置狀態
Parameters
struct v4l2_subdev_state *state1一個子裝置狀態
struct v4l2_subdev_state *state2另一個子裝置狀態
描述
解鎖兩個子裝置的狀態。
這不同於對兩個狀態都呼叫 v4l2_subdev_unlock_state(),這樣如果狀態共享同一個鎖,則鎖只會被釋放一次。
-
struct v4l2_subdev_state *v4l2_subdev_get_unlocked_active_state(struct v4l2_subdev *sd)¶
檢查活動 subdev 狀態是否已解鎖並返回它
Parameters
struct v4l2_subdev *sd子裝置
描述
返回子裝置的活動狀態,如果 subdev 不支援活動狀態,則返回 NULL。如果狀態不為 NULL,則呼叫 lockdep_assert_not_held() 以在狀態被鎖定時發出警告。
此函式用於例如當獲取活動狀態僅用於向前傳遞而無需訪問狀態欄位時。
-
struct v4l2_subdev_state *v4l2_subdev_get_locked_active_state(struct v4l2_subdev *sd)¶
檢查活動 subdev 狀態是否已鎖定並返回它
Parameters
struct v4l2_subdev *sd子裝置
描述
返回子裝置的活動狀態,如果 subdev 不支援活動狀態,則返回 NULL。如果狀態不為 NULL,則呼叫 lockdep_assert_held() 以在狀態未鎖定時發出警告。
當呼叫者知道活動狀態已被鎖定時,應使用此函式。
-
struct v4l2_subdev_state *v4l2_subdev_lock_and_get_active_state(struct v4l2_subdev *sd)¶
鎖定並返回子裝置的活動 subdev 狀態
Parameters
struct v4l2_subdev *sd子裝置
描述
返回子裝置的鎖定的活動狀態,如果 subdev 不支援活動狀態,則返回 NULL。
使用後必須使用 v4l2_subdev_unlock_state() 解鎖該狀態。
-
void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)¶
初始化子裝置結構
Parameters
struct v4l2_subdev *sd指向要初始化的
struct v4l2_subdev的指標const struct v4l2_subdev_ops *ops指向
struct v4l2_subdev_ops的指標。
-
v4l2_subdev_call¶
v4l2_subdev_call (sd, o, f, args...)
呼叫 v4l2_subdev 的操作。
Parameters
sd指向
struct v4l2_subdev的指標o包含 f 的
struct v4l2_subdev_ops中元素的名稱。那裡的每個元素都對一組回撥函式進行分組。f要呼叫的回撥函式。回撥函式根據
struct v4l2_subdev_ops中每個元素進行分組。args...f 的引數。
例子
err = v4l2_subdev_call(sd, video, s_std, norm);
-
v4l2_subdev_call_state_active¶
v4l2_subdev_call_state_active (sd, o, f, args...)
呼叫 v4l2_subdev 的一個操作,該操作將狀態作為引數,並將 subdev 的活動狀態傳遞給它。
Parameters
sd指向
struct v4l2_subdev的指標o包含 f 的
struct v4l2_subdev_ops中元素的名稱。那裡的每個元素都對一組回撥函式進行分組。f要呼叫的回撥函式。回撥函式根據
struct v4l2_subdev_ops中每個元素進行分組。args...f 的引數。
描述
這類似於 v4l2_subdev_call(),只是此版本只能用於將 subdev 狀態作為引數的操作。該宏將在呼叫 op 之前獲取活動狀態並將其鎖定,並在呼叫之後將其解鎖。
-
v4l2_subdev_call_state_try¶
v4l2_subdev_call_state_try (sd, o, f, args...)
呼叫 v4l2_subdev 的一個操作,該操作將狀態作為引數,並將 subdev 的新分配的 try 狀態傳遞給它。
Parameters
sd指向
struct v4l2_subdev的指標o包含 f 的
struct v4l2_subdev_ops中元素的名稱。那裡的每個元素都對一組回撥函式進行分組。f要呼叫的回撥函式。回撥函式根據
struct v4l2_subdev_ops中每個元素進行分組。args...f 的引數。
描述
這類似於 v4l2_subdev_call_state_active(),只是由於此版本分配了一個新狀態,因此它僅適用於 V4L2_SUBDEV_FORMAT_TRY 用例。
注意
只有舊的非 MC 驅動程式可能需要此宏。
-
v4l2_subdev_has_op¶
v4l2_subdev_has_op (sd, o, f)
檢查 subdev 是否定義了某個操作。
Parameters
sd指向
struct v4l2_subdev的指標o回撥函式 f 所屬的
struct v4l2_subdev_ops中的回撥函式組。f要檢查其存在的回撥函式。
-
void v4l2_subdev_notify_event(struct v4l2_subdev *sd, const struct v4l2_event *ev)¶
傳遞子裝置的事件通知
Parameters
struct v4l2_subdev *sd要為其傳遞事件的 subdev
const struct v4l2_event *ev要傳遞的事件
描述
將指定的事件傳遞給所有訂閱了 v42l subdev 事件佇列的使用者空間事件偵聽器,以及使用通知回撥的橋接驅動程式。通知回撥的通知型別將是 V4L2_DEVICE_NOTIFY_EVENT。
-
bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd)¶
返回 subdev 是否正在流式傳輸
Parameters
struct v4l2_subdev *sd子裝置
描述
v4l2_subdev_is_streaming() 告訴 subdev 當前是否正在流式傳輸。“流式傳輸”在此處表示是否已成功呼叫 .s_stream() 或 .enable_streams(),並且尚未停用流式傳輸。
如果 subdev 實現了 .enable_streams(),則必須在保持活動狀態鎖定的情況下呼叫此函式。