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 結構體

之後,您需要使用唯一的名稱初始化 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(&notifier, 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 指標檢查,如果 sdNULL,則返回 -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_QUERYCTRLVIDIOC_QUERYMENUVIDIOC_G_CTRLVIDIOC_S_CTRLVIDIOC_G_EXT_CTRLSVIDIOC_S_EXT_CTRLSVIDIOC_TRY_EXT_CTRLS

控制元件 ioctl 與 V4L2 中定義的相同。它們的行為相同,唯一的例外是它們僅處理在子裝置中實現的控制元件。根據驅動程式,也可以透過一個(或多個)V4L2 裝置節點訪問這些控制元件。

VIDIOC_DQEVENTVIDIOC_SUBSCRIBE_EVENTVIDIOC_UNSUBSCRIBE_EVENT

事件 ioctl 與 V4L2 中定義的相同。它們的行為相同,唯一的例外是它們僅處理由子裝置生成的事件。根據驅動程式,也可以透過一個(或多個)V4L2 裝置節點報告這些事件。

想要使用事件的子裝置驅動程式需要在註冊子裝置之前設定 V4L2_SUBDEV_FL_HAS_EVENTS v4l2_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_FMTVIDIOC_SUBDEV_S_CROPVIDIOC_SUBDEV_S_SELECTION

這些 ioctl 僅允許在只讀子裝置裝置節點上用於 V4L2_SUBDEV_FORMAT_TRY 格式和選擇矩形。

VIDIOC_SUBDEV_S_FRAME_INTERVALVIDIOC_SUBDEV_S_DV_TIMINGSVIDIOC_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_typeaddr 填充 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)

type

VBI 服務型別 (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;
};

成員

vc

CSI-2 虛擬通道

dt

CSI-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.csi2

CSI-2 特定匯流排配置

enum v4l2_mbus_frame_desc_type

媒體匯流排幀描述型別

常量

V4L2_MBUS_FRAME_DESC_TYPE_UNDEFINED

未定義的幀描述型別。驅動程式不應使用此型別,它用於向後相容。

V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL

並行媒體匯流排。

V4L2_MBUS_FRAME_DESC_TYPE_CSI2

CSI-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_entries

entry 陣列中的條目數

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_streamsv4l2_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_WIDTH

IR 使用 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;
};

成員

format

struct v4l2_mbus_framefmt

crop

用於裁剪的 struct v4l2_rect

compose

用於合成的 struct v4l2_rect

interval

幀間隔

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;
};

成員

pad

pad 編號

stream

stream number

enabled

是否已使用 v4l2_subdev_enable_streams() 啟用流

fmt

struct v4l2_mbus_framefmt

crop

用於裁剪的 struct v4l2_rect

compose

用於合成的 struct v4l2_rect

interval

幀間隔

描述

此結構儲存流的配置。

struct v4l2_subdev_stream_configs

流配置的集合。

定義:

struct v4l2_subdev_stream_configs {
    u32 num_configs;
    struct v4l2_subdev_stream_config *configs;
};

成員

num_configs

config 中的條目數。

configs

struct v4l2_subdev_stream_configs 的陣列。

struct v4l2_subdev_krouting

subdev 路由表

定義:

struct v4l2_subdev_krouting {
    unsigned int len_routes;
    unsigned int num_routes;
    struct v4l2_subdev_route *routes;
};

成員

len_routes

routes 陣列的長度,以路由為單位

num_routes

路由數

routes

struct 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

狀態相關的子裝置

pads

struct v4l2_subdev_pad_config 陣列

routing

子裝置的路由表

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 的指標。可以為 NULL

tuner

指向 struct v4l2_subdev_tuner_ops 的指標。可以為 NULL

audio

指向 struct v4l2_subdev_audio_ops 的指標。可以為 NULL

video

指向 struct v4l2_subdev_video_ops 的指標。可以為 NULL

vbi

指向 struct v4l2_subdev_vbi_ops 的指標。可以為 NULL

ir

指向 struct v4l2_subdev_ir_ops 的指標。可以為 NULL

sensor

指向 struct v4l2_subdev_sensor_ops 的指標。可以為 NULL

pad

指向 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_regulators

Regululators 的數量

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->ownerv4l2_dev->dev 所有者的所有者匹配,則為 true。由 v4l2_device_register_subdev() 初始化。

flags

subdev 標誌。可以是: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。

name

Sub-device 的名稱。請注意,名稱必須是唯一的。

grp_id

可用於對類似的 subdevs 進行分組。值是特定於驅動程式的

dev_priv

指向私有資料的指標

host_priv

指向裝置附加的 subdev 使用的私有資料的指標。

devnode

subdev 裝置節點

dev

指向物理裝置的指標(如果有)

fwnode

subdev 的 fwnode_handle,通常與 dev->of_node->fwnode 或 dev->fwnode 相同(以非 NULL 者為準)。

async_list

將此 subdev 連結到全域性 subdev_list 或 notifier->done_list 列表。

async_subdev_endpoint_list

struct 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。

pdata

subdevice 平臺數據的公共部分

state_lock

指向用於所有 subdev 狀態的鎖的指標,由驅動程式設定。這是可選的。如果為 NULL,則每個狀態例項將獲得自己的鎖。

privacy_led

指向感測器隱私 LED 的 LED classdev 的可選指標。

active_state

subdev 的活動狀態(對於內部跟蹤狀態的 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_caps

V4L2_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 私有裝置資料

Parameters

const struct v4l2_subdev *sd

指向 struct v4l2_subdev 的指標

描述

返回指向要儲存的私有裝置資料的指標。

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 私有資料

Parameters

const struct v4l2_subdev *sd

指向 struct v4l2_subdev 的指標

描述

返回指向要儲存的私有主機資料的指標。

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 操作。 如果端點由子裝置擁有,則該函式返回端點埠號。

成功時返回端點埠號,否則返回負錯誤程式碼。

驗證媒體連結

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 的指標

描述

此函式確保連結的源和目標上的寬度、高度和媒體匯流排畫素程式碼相等。

驗證媒體連結

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

子裝置狀態

pad

pad id

...

流 id(可選引數)

描述

這會為子裝置狀態中給定的 pad + 流返回指向 struct v4l2_mbus_framefmt 的指標。

對於不知道流的驅動程式,會返回相應 pad 的格式。 如果 pad 不存在,則返回 NULL。

v4l2_subdev_state_get_crop

v4l2_subdev_state_get_crop (state, pad, ...)

獲取指向流裁剪矩形的指標

Parameters

state

子裝置狀態

pad

pad id

...

流 id(可選引數)

描述

這會為子裝置狀態中給定的 pad + 流返回指向裁剪矩形的指標。

對於不知道流的驅動程式,會返回相應 pad 的裁剪矩形。 如果 pad 不存在,則返回 NULL。

v4l2_subdev_state_get_compose

v4l2_subdev_state_get_compose (state, pad, ...)

獲取指向流合成矩形的指標

Parameters

state

子裝置狀態

pad

pad id

...

流 id(可選引數)

描述

這會為子裝置狀態中給定的 pad + 流返回指向合成矩形的指標。

對於不知道流的驅動程式,會返回相應 pad 的合成矩形。 如果 pad 不存在,則返回 NULL。

v4l2_subdev_state_get_interval

v4l2_subdev_state_get_interval (state, pad, ...)

獲取指向流幀間隔的指標

Parameters

state

子裝置狀態

pad

pad 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 pad

pad 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 pad

pad 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

pad0pad1 必須是 sink 和源,順序不限。

返回

路由到 pad0 上的 streamspad1 的流的位掩碼。

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_MULTIPLEXING

sink pad 不應包含多路複用流

V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING

源 pad 不應包含多路複用流

V4L2_SUBDEV_ROUTING_ONLY_1_TO_1

僅允許非重疊的 1 對 1 流路由(V4L2_SUBDEV_ROUTING_NO_1_TO_NV4L2_SUBDEV_ROUTING_NO_N_TO_1 的組合)

V4L2_SUBDEV_ROUTING_NO_STREAM_MIX

來自 sink pad 的所有流必須路由到單個源 pad,並且該源 pad 不應從任何其他 sink pad 獲取路由(V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIXV4L2_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 pad

pad

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 pad

pad

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_streamsv4l2_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

包含 fstruct 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

包含 fstruct 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

包含 fstruct 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(),則必須在保持活動狀態鎖定的情況下呼叫此函式。