camera驅動框架分析(上)

前言

  camera驅動框架涉及到的知識點比較多,特別是camera本身的接口就有很多,有些是直接連接到soc的camif口上的,有些是通過usb接口導出的,如usb camera。我這里主要討論前者,也就是與soc直連的。我認為凡是涉及到usb的,都不是一兩句話可以說明白的!如有錯誤,歡迎指正,謝謝!!!

環境說明

涉及到的基礎知識點:
字符設備驅動
設備模型
平臺設備驅動
v4l2框架
i2c驅動框架

涉及到的術語:
camera : 指的是整個camera,包括它本身的硬件連接方式及支持i2c控制的i2c設備
sensor : 指的是支持i2c控制的i2c設備,它屬于camera的一部分,在內核實現里也能體現出來
camera host: 指的是與camera相連接的,一般內嵌在soc里面的控制器

涉及到的文件夾:
drivers/media/platform/soc_camera/ 主要存放camera host驅動,通用的camera驅動也存放在此
drivers/media/i2c/soc_camera/ 主要存放sensor驅動

分析所采用的內核版本:

VERSION = 3                                                                                                                                                   
PATCHLEVEL = 15                                                                 
SUBLEVEL = 0                                                                    
EXTRAVERSION =                                                                  
NAME = Shuffling Zombie Juror    

camera的驅動包括通用camera的驅動、camera host的驅動以及sensor的驅動,下面一個個來分析

這里先插一張圖,來自:http://blog.csdn.net/kickxxx/article/details/8484498(該圖片及圖片后的文字是在我寫完這篇博文后發現的,我認為對理解camera驅動會有幫助,所以就摘抄了^_^)
soc camera 子系統 系統架構圖

Soc camera sub-system對應著drivers/media/video/下的soc_camera.c soc_camera_platform.c

Soc camera host 是host端實現,是由平臺廠商實現的,向上實現soc_camera_host_ops接口,向下操作Camera host硬件以及通過平臺特定的接口操作Soc camera device

Soc camera device 是平臺的camera device(同時也是subdev),由驅動開發者來實現v4l2_subdev_call調用的subdev 接口,同時還要為soc camera host實現平臺特定的操作接口;向下操作camera sensor或者video AD芯片。

Camera host hardware是平臺硬件相關的,不同的平臺有不同的host硬件,比如imx51的ipu,三星s5pv210的fimc控制器等。

soc_camera_host,soc_camera_device,v4l2_device,v4l2_subdev關系如下:理論上系統內可以有多個soc_camera_host,物理上soc_camera_host就是系統的camera處理模塊驅動一個soc_camera_host可以對應多個soc_camera_device,物理上soc_camera_device是一個camera接口,每個soc_camera_host對應一個v4l2_dev每個soc_camera_device,系統會為他們創建設備節點/dev/videoX。每個soc_camera_device有多個v4l2_subdev,物理上v4l2_subdev可以是sensor,video AD芯片v4l2_subdev可以通過i2c掛接到v4l2_device,也可以通過soc_camera_link提供的add_device來增加,這依賴于sensor和video AD芯片掛接到MCU camera接口的方式。

通用camera驅動

對應文件drivers/media/platform/soc_camera/soc_camera.c

static struct platform_driver __refdata soc_camera_pdrv = {.probe = soc_camera_pdrv_probe,.remove  = soc_camera_pdrv_remove,.driver  = {.name   = "soc-camera-pdrv",.owner  = THIS_MODULE,},
};module_platform_driver(soc_camera_pdrv);

從這里可以看出,我們要使該驅動probe得到調用,先得注冊一個平臺設備,且名字為soc-camera-pdrv。通用camera的驅動就是定義了一套數據結構,然后告訴大家,你如果想用通用的camera驅動,那就照著數據結構填好,然后用soc-camera-pdrv的名字通過平臺總線注冊上來就可以了。平臺設備的注冊可以通過兩種方式來實現,一種是通過設備樹,它是最新的一種機制,通過dts文件來描述硬件信息,使得內核里面不會再硬編碼一堆和用于描述硬件信息的代碼。對應到這里的硬件信息就是camera sensor硬件信息以及camera硬件布線信息。另一種就是以前采用的方式,直接用代碼在板子相關的啟動文件里來描述那些信息并通過平臺設備的注冊。soc_camera_pdrv里面沒有設備樹的相關支持,說明這類設備的添加還是采用后面那種方式,通過下面的命令輸出也可以證實這一點:

我用命令(grep -rns soc-camera-pdrv arch/arm*/)搜索一下,就可以得到以下結果:

arch/arm/mach-shmobile/board-lager.c:394:   platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
arch/arm/mach-shmobile/board-bockw.c:606:   platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
arch/arm/mach-shmobile/board-bockw.c:609:   platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
arch/arm/mach-shmobile/board-mackerel.c:1224:   .name   = "soc-camera-pdrv",
arch/arm/mach-shmobile/board-armadillo800eva.c:910: .name   = "soc-camera-pdrv",
arch/arm/mach-shmobile/board-marzen.c:299:  .name   = "soc-camera-pdrv",                \
arch/arm/mach-at91/board-sam9m10g45ek.c:241:    .name   = "soc-camera-pdrv",
arch/arm/mach-omap1/board-ams-delta.c:435:  .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/ezx.c:788:    .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/ezx.c:1062:   .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/em-x270.c:1034:   .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/palmz72.c:339:    .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/pcm990-baseboard.c:507:       .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/pcm990-baseboard.c:513:       .name   = "soc-camera-pdrv",
arch/arm/mach-pxa/mioa701.c:682:MIO_SIMPLE_DEV(mioa701_camera,    "soc-camera-pdrv",&iclink);
arch/arm/mach-imx/mach-imx27_visstrim_m10.c:572:    platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0,
arch/arm/mach-imx/mach-mx31_3ds.c:248:  .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-mx31_3ds.c:412:  REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx31_3ds.c:444:  REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx35_3ds.c:305:  .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-mx35_3ds.c:324:  REGULATOR_SUPPLY("cmos_vio", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx27_3ds.c:272:  REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx27_3ds.c:302:  REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
arch/arm/mach-imx/mach-mx27_3ds.c:410:  .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mx31moboard-smartbot.c:91:        .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mx31moboard-marxbot.c:181:        .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-pcm037.c:329:    .name   = "soc-camera-pdrv",
arch/arm/mach-imx/mach-pcm037.c:337:    .name   = "soc-camera-pdrv",

我選一個稍微簡單的mach來進行后面的分析,at91平臺(arch/arm/mach-at91/board-sam9m10g45ek.c),我把相關的代碼截取出來:

   * soc-camera OV2640                                                            */                                                                             #if defined(CONFIG_SOC_CAMERA_OV2640) || \                                      defined(CONFIG_SOC_CAMERA_OV2640_MODULE)                                    static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)   {                                                                               /* ISI board for ek using default 8-bits connection */                      return SOCAM_DATAWIDTH_8;                                                   }                                                                               static int i2c_camera_power(struct device *dev, int on)                         {                                                                               /* enable or disable the camera */                                          pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");       at91_set_gpio_output(AT91_PIN_PD13, !on);                                   if (!on)                                                                    goto out;                                                               /* If enabled, give a reset impulse */                                      at91_set_gpio_output(AT91_PIN_PD12, 0);                                     msleep(20);                                                                 at91_set_gpio_output(AT91_PIN_PD12, 1);                                     msleep(100);                                                                out:                                                                            return 0;                                                                   }                                                                               static struct i2c_board_info i2c_camera = {                                     I2C_BOARD_INFO("ov2640", 0x30),                                             };                                                                              static struct soc_camera_link iclink_ov2640 = {                                 .bus_id         = 0,                                                        .board_info     = &i2c_camera,                                              .i2c_adapter_id     = 0,                                                    .power          = i2c_camera_power,                                         .query_bus_param    = isi_camera_query_bus_param,                           };                                                                              static struct platform_device isi_ov2640 = {                                    .name   = "soc-camera-pdrv",                                                .id = 0,                                                                    .dev    = {                                                                 .platform_data = &iclink_ov2640,                                        },                                                                          };                                                                              #endif   

最重要的結構就是soc_camera_link,它是所有camera這類設備都需要用到的結構體。bus_id用來描述它是連接到哪條soc camera host總線上,后面會再講這個。board_info用來描述i2c設備的信息,比如它的型號名稱,它的i2c地址,相信研究過i2c驅動的人都比較熟悉。i2c_adapter_id用來描述i2c設備掛載哪條i2c總線上。sensor的控制一般通過i2c來實現,所以這里才會有i2c設備的描述,因為需要對應的i2c驅動來驅動它啊。power一般指sensor的電源模塊的開啟和關閉,一般是單獨通過一個gpio來控制的。query_bus_param這個成員先不看吧,用到的時候再看。

總之,通過上面的信息以及后面的平臺設備注冊后,就將soc-camera-pdrv平臺設備添加到平臺總線了。也就是說只要這段代碼編譯進入了內核并調用了這段代碼,那么soc_camera_pdrv_probe就一定會執行了。下面繼續分析前面列出來的soc_camera_pdrv_probe吧!

soc_camera_pdrv_probe的實現很短,為了方面說明,也貼出來吧:

static int soc_camera_pdrv_probe(struct platform_device *pdev)
{struct soc_camera_desc *sdesc = pdev->dev.platform_data;struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc;struct soc_camera_device *icd;int ret;if (!sdesc)return -EINVAL;icd = devm_kzalloc(&pdev->dev, sizeof(*icd), GFP_KERNEL);if (!icd)return -ENOMEM;/** In the asynchronous case ssdd->num_regulators == 0 yet, so, the below* regulator allocation is a dummy. They are actually requested by the* subdevice driver, using soc_camera_power_init(). Also note, that in* that case regulators are attached to the I2C device and not to the* camera platform device.*/ret = devm_regulator_bulk_get(&pdev->dev, ssdd->sd_pdata.num_regulators,ssdd->sd_pdata.regulators);if (ret < 0)return ret;icd->iface = sdesc->host_desc.bus_id;icd->sdesc = sdesc;icd->pdev = &pdev->dev;platform_set_drvdata(pdev, icd);icd->user_width     = DEFAULT_WIDTH;icd->user_height    = DEFAULT_HEIGHT;return soc_camera_device_register(icd);
}

這里我們會開始接觸第二個重要的數據結構soc_camera_device,它在內核里代表的就是一個camera sensor設備。有一點需要提前說明下,我們之前談到數據結構soc_camera_link,對應到驅動使用的時候,將其拆分成兩個結構體了,我想也是為了代碼更清晰吧!對應的結構如下:

struct soc_camera_desc {struct soc_camera_subdev_desc subdev_desc;struct soc_camera_host_desc host_desc;
};

因此,soc_camera_pdrv_probe里面的icd->iface = sdesc->host_desc.bus_id其實就是上面我說過的bus_id,用來描述它是連接到哪條soc camera host線上。soc_camera_pdrv_probe主要是創建對象 soc_camera_device,它代表著一個camera sensor設備。當然可以有多個這樣的設備同時存在,且都由該驅動負責創建。并將platform設備傳過來的各種數據放到soc_camera_device里面,最終調用soc_camera_device_register將該camera sensor注冊。

soc_camera_device_register的代碼就不貼了,它其實主要就做了一件事情,將代表著camera sensor的對象soc_camera_device放到了全局鏈表devices中,其他的就是做參數檢查等等。

好了,到這里,我們的系統里的devices全局鏈表里已經有一個用于代表camera sensor的設備了,它就在這里靜靜的等待著負責它的驅動的到來,我們應該可以想象到,負責它的就是camera host咯。順便說一下,如果我們僅僅需要寫一個sensor驅動,那么到這里,就算完成了一小半了,剩下的就是完成我們camera sensor里對應的i2c設備的驅動(參考drivers/media/i2c/soc_camera/,里面有一些已經實現了的i2c sensor驅動),至于camera host驅動,一般對應的soc的sdk都會實現啦。

未完,待續!
2015年6月

轉載于:https://www.cnblogs.com/rongpmcu/p/7662738.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391118.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391118.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391118.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

工程項目管理需要注意哪些問題

在社會科學技術發展和市場經濟繁榮昌盛的今天&#xff0c;為更好的滿足社會人性化的需求&#xff0c;建設施工企業在建筑施工、布局以及內部運行都給予了落實。而工程項目是建筑施工企業面向建筑市場的窗口&#xff0c;是企業建筑活動的前沿陣地&#xff0c;管理需更嚴謹。 雖說…

leetcode 872. 葉子相似的樹(dfs)

請考慮一棵二叉樹上所有的葉子&#xff0c;這些葉子的值按從左到右的順序排列形成一個 葉值序列 。 舉個例子&#xff0c;如上圖所示&#xff0c;給定一棵葉值序列為 (6, 7, 4, 9, 8) 的樹。 如果有兩棵二叉樹的葉值序列是相同&#xff0c;那么我們就認為它們是 葉相似 的。 …

探索感染了COVID-19的動物的數據

數據 (The data) With the number of cases steadily rising day by day, COVID-19 has been pretty much in the headlines of every newspaper known to man. Despite the massive amount of attention, a topic that has remained mostly untouched (some exceptions being …

Facebook哭暈在廁所,調查顯示用VR體驗社交的用戶僅為19%

美國娛樂軟件協會ESA調查顯示&#xff0c;有74%的用戶使用VR玩游戲&#xff0c;而僅有19%的用戶會用VR進行社交。 當我們說到VR社交&#xff0c;必然離不開Facebook。在剛剛結束的F8大會上&#xff0c;小扎展示了VR社交平臺Facebook Spaces測試版&#xff0c;巧的是此前也有好…

網頁自動刷新

eg1&#xff1a;<meta http-equiv”refresh” content”4” /> 間隔4秒網頁自動刷新 eg2&#xff1a;<meta http-equiv”refresh” content”8;http://www.baidu.com” /> 等待8秒自動跳轉到百度頁面轉載于:https://www.cnblogs.com/zwtqf/p/7667774.html

解決Javascript疲勞的方法-以及其他所有疲勞

Learn your fundamentals, and never worry again. 了解您的基礎知識&#xff0c;再也不用擔心。 新工具讓我擔心 (New Tools Worry Me) When JavaScripts shiny tool of the day comes out, I sometimes overreact. 當JavaScript一天一度的閃亮工具問世時&#xff0c;我有時R…

Java 8 的List<V> 轉成 Map<K, V>

問題&#xff1a; Java 8 的List 轉成 Map<K, V> 我想要使用Java 8的streams和lambdas轉換一個 List 對象為 Map 下面是我在Java 7里面的寫法 private Map<String, Choice> nameMap(List<Choice> choices) {final Map<String, Choice> hashMap new…

已知兩點坐標拾取怎么操作_已知的操作員學習-第4部分

已知兩點坐標拾取怎么操作有關深層學習的FAU講義 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as mu…

北京供銷大數據集團發布SinoBBD Cloud 一體化推動產業云發展

9月5日&#xff0c;第五屆全球云計算大會在上海世博展覽館盛大開幕&#xff0c;國內外頂尖企業匯聚一堂&#xff0c;新一代云計算技術產品紛紛亮相。作為國內領先的互聯網基礎服務提供商&#xff0c;北京供銷大數據集團(以下簡稱“SinoBBD”)受邀參加此次大會&#xff0c;并正式…

windows下有趣的小玩意

1.顯示文件和隱藏文件。在當前目錄下shift右鍵 選擇cmd命令 運行顯示文件: attrib -s -h 文件名 隱藏文件: attrib -s h 文件名 2.查看電腦支持的最大內存 在cmd下運行wmic memphysical get maxcapacity所得結果單位mb 所得/1024/1024 得到單位G 3.windowsR 輸入…

rxjs angular_Angular RxJS深度

rxjs angularIn this tutorial, well learn to use the RxJS 6 library with Angular 6 or Angular 7. Well learn about:在本教程中&#xff0c;我們將學習將RxJS 6庫與Angular 6或Angular 7結合使用。我們將了解&#xff1a; How to import the Observable class and the ot…

HashMap, LinkedHashMap 和 TreeMap的區別

HashMap, LinkedHashMap 和 TreeMap的區別 Java里面的HashMap, LinkedHashMap 和 TreeMap 有什么區別?我看不出以下3個key和value有什么不同的。Hashtables里面又是怎么樣的呢&#xff1f; Map m1 new HashMap(); m1.put("map", "HashMap"); m1.put(&q…

“陪護機器人”研報:距離真正“陪護”還差那么一點

一款有“缺陷”的機器人&#xff0c;怎能做到真正的“陪護”&#xff1f; 近日&#xff0c;鼎盛智能發布了一款名為Ibotn的&#xff08;愛蹦&#xff09;幼兒陪伴機器人&#xff0c;核心看點就是通過人臉識別、場景識別等計算機視覺技術來實現機器人對兒童的陪護。不過&#xf…

neo-6m uno_Uno-統治所有人的平臺

neo-6m unoFirst, we should start off with what Uno is and why you should care. 首先&#xff0c;我們應該從Uno是什么以及為什么要關心開始。 As stated on their website, Uno is "The only platform for building native mobile, desktop and WebAssembly apps wi…

【轉】消息隊列應用場景

一、消息隊列概述 消息隊列中間件是分布式系統中重要的組件&#xff0c;主要解決應用耦合&#xff0c;異步消息&#xff0c;流量削鋒等問題。實現高性能&#xff0c;高可用&#xff0c;可伸縮和最終一致性架構。是大型分布式系統不可缺少的中間件。 目前在生產環境&#xff0c;…

JDK和JRE區別是什么

問題&#xff1a;JDK和JRE區別是什么 他們的角色分別是什么&#xff1f;我們應該什么時候使用他們&#xff1f; 回答一 JRE是Java Runtime Environment&#xff08;Java運行時環境&#xff09;。它是一個包&#xff0c;集合了運行一個編譯好的Java程序的一切必須的東西&…

樹莓派新手入門教程

http://www.ruanyifeng.com/blog/2017/06/raspberry-pi-tutorial.html

lime 模型_使用LIME的糖尿病預測模型解釋— OneZeroBlog

lime 模型Article outline文章大綱 Introduction 介紹 Data Background 資料背景 Aim of the article 本文的目的 Exploratory analysis 探索性分析 Training a Random Forest Model 訓練隨機森林模型 Global Importance 全球重要性 Local Importance 當地重要性 介紹 (Introd…

react 生命掛鉤_如何在GraphQL API中使用React掛鉤來管理狀態

react 生命掛鉤In this blog post, we are going to learn -在這篇博客中&#xff0c;我們將學習- What React hooks are 什么是React鉤子 How to use hooks for state management 如何使用掛鉤進行狀態管理 Before we start working with hooks, let us take a brief moment …

Linux第三周作業

1.三個法寶 ①存儲程序計算機工作模型&#xff0c;計算機系統最最基礎性的邏輯結構&#xff1b; ②函數調用堆棧&#xff0c;堆棧完成了計算機的基本功能&#xff1a;函數的參數傳遞機制和局部變量存取 &#xff1b; ③中斷&#xff0c;多道程序操作系統的基點&#xff0c;沒有…