天天看點

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

come from :https://blog.csdn.net/xubin341719/article/details/7723725

關鍵詞:android  camera CMM 模組 camera參數

平台資訊:

核心:linux

系統:android

平台:S5PV310(samsung exynos 4210) 

作者:xubin341719(歡迎轉載,請注明作者)

下載下傳:常用攝像頭規格書(個别有android驅動程式)  :bf3703 30W、gc0308 30W、ov7670、gt2005 200W、gt2015 200W、NT99250 200W、s5k5ba 200W、s5k4ba

新項目開案,代碼他們還沒給得到,三星那邊辦事流程就是多,煩人(嘿嘿隻是說說,流程從另一方面說明了人家标準化的程度高)。看看代碼,把前一段時間工作的内容整理下,發出來。一方面有相同問題的“同學”可以看下,說不定問題就解決了; 再一方面自己工作方面記錄吧,整個流程整理出來,加深自己的印象,技術還得提高呀。這樣利人利己的事多做點好……“為人民服務!”(我不是**黨,隻是技術P民)

這篇比較基礎,做為科普知識看一下。

android camera(一):camera模組CMM介紹

android camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)

android camera(三):camera V4L2 FIMC

android camera(四):camera 驅動 GT2005

一、攝像頭模組(CCM)介紹:

1、camera特寫

    攝像頭模組,全稱CameraCompact Module,以下簡寫為CCM,是影像捕捉至關重要的電子器件。先來張特寫,各種樣子的都有,不過我前一段時間調試那個有點醜。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

2、攝像頭工作原理、camera的組成各元件的作用

想完全的去了解,還得去深入,如果是代碼我們就逐漸分析,模組的話我們就把它分解開來,看他到底是怎麼工作的。看下它是有那些部分構成的,如下圖所示:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(1)、工作原理:物體通過鏡頭(lens)聚集的光,通過CMOS或CCD內建電路,把光信号轉換成電信号,再經過内部圖像處理器(ISP)轉換成數字圖像信号輸出到數字信号處理器(DSP)加工處理,轉換成标準的GRB、YUV等格式圖像信号。

(2)、CCM 包含四大件: 鏡頭(lens)、傳感器(sensor)、軟闆(FPC)、圖像處理晶片(DSP)。決定一個攝像頭好壞的重要部件是:鏡頭(lens)、圖像處理晶片 (DSP)、傳感器(sensor)。CCM的關鍵技術為:光學設計技術、非球面鏡制作技術、光學鍍膜技術。

鏡頭(lens)是相機的靈魂,鏡頭(lens)對成像的效果有很重要的作用,是利用透鏡的折射原理,景物光線通過鏡頭,在聚焦平面上形成清晰的影像,通過感光材料CMOS或CCD感光器記錄景物的影像。鏡頭廠家主要集中在台灣、日本和南韓,鏡頭這種光學技術含量高的産業有比較高的門檻,業内比較知名的企業如富士精機、柯尼卡美能達、大立光、Enplas等

傳感器(sensor)是CCM的核心子產品,目前廣泛使用的有兩種:一種是廣泛使用的CCD(電荷藕合)元件;另一種是CMOS(互補金屬氧化物導體)器件。

電荷藕合器件圖像傳感器CCD(Charge Coupled Device),它使用一種高感光度的半導體材料制成,能把光線轉變成電荷,通過模數轉換器晶片轉換成數字信号。CCD由許多感光機關組成,通常以百萬像 素為機關。當CCD表面受到光線照射時,每個感光機關會将電荷反映在元件上,所有的感光機關所産生的信号加在一起,就構成了一幅完整的畫面。CCD傳感器子產品以日本廠商為主導,全球規模市場有90%以上被日本廠商壟斷,以索尼、松下、夏普為龍頭。

互補性氧化金屬半導體CMOS(Complementary Metal-Oxide Semiconductor)主要是利用矽和鍺這兩種元素所做成的半導體,使其在CMOS上共存着帶N(帶–電)和 P(帶+電)級的半導體,這兩個互補效應所産生的電流即可被處理晶片紀錄和解讀成影像。CMOS 傳感器主要美國、台灣和南韓為主導,主要生産廠家有美國 OmniVision、Agilent、Micron,台灣的銳像、原相、泰視等,南韓的三星、現代。

 圖像處理晶片(DSP)是CCM的重要組成部分,它的作用是将感光晶片獲得的資料及時快速地傳遞中央處理器并重新整理感光晶片,是以DSP晶片的好壞,直接影響畫面品質(比如色彩飽和度,清晰度等)。

FPC柔性電路闆(柔性PCB): 簡稱"軟闆", 又稱"柔性線路闆",連接配接晶片和手機。起到電信号傳輸作用。

3、camera模組的裝配方式

(1)、定焦模組裝配圖

CCM分為定焦模組和自動變焦模組,其中定焦模組主要由鏡頭、鏡座、感光內建電路、軟性線路闆、補強和鋼片裝配而成,其裝配圖如下:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(2)、自動變焦模組裝配圖

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

以前我不知道手機上的光學變焦是怎麼會事,以為那些都是忽悠人的,看這個圖這下明白了,如果你也不知道,看下這個圖,原來裡面有個音圈馬達,這個隻有高像素的模組才有,這個我們不用管,知道怎麼光學變焦就可以了。

自動變焦模組由鏡頭、音圈馬達、底座支架、感光內建電路、驅動內建電路和連接配接器組成,其裝配圖如下:

(3)、3D模組

傳說中的3D是怎麼會事,多幾台錄影機拍攝。手機上也有了??有點強大

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

看人家手機上用的,感覺看着不太好看,高科技的東西開始就是做得醜了一點,我們了解有這個東西就行了:

4、攝像頭的一些技術名額

(1)、圖像解析度/分辨率(Resolution)

QSIF/QQVGA 160 x 120 19200
QCIF  176 x 144 25344
SIF/QVGA 320 x 240    76800
CIF 352 x 288   101376  10萬像素
VGA   640 x 480 307200 30萬像素(35萬是指648X488)
SVGA 800 x 600 480000 50萬像素
XGA 1024 x 768 786438 80萬像素
SXGA  1280 x 1024  1310720    130萬像素
UXGA 1600 x 1200 1920000   200萬像素
QXGA  2048 x 1536 3145728  300萬像素(320W)
QSXGA 2592 x 1944 5038848 500萬像素
2816 x 2112 2947392 600萬像素
3072 x 2304  7077888 700萬像素
3200 x 2400 7680000 770萬像素
3264 x 2448  7990272  800萬像素
3876 x 2584 10015584 1000萬像素

(2)、圖像格式(imageFormat/Colorspace)

RGB24,420是目前最常用的兩種圖像格式。

RGB24:表示R、G、B三種顔色各8bit,最多可表現256級濃淡,進而可以再現256*256*256種顔色。

I420:YUV格式之一。其它格式有:RGB565,RGB444,YUV4:2:2等。

(3)、自動白平衡調整(AWB)

定義:要求在不同色溫環境下,照白色的物體,螢幕中的圖像應也是白色的。色溫表示光譜成份,光的顔色。色溫低表示長波光成分多。當色溫改變時,光源中三基色(紅、綠、藍)的比例會發生變化,需要調節三基色的比例來達到彩色的平衡,這就是白平衡調節的實際。

(4)、圖像壓縮方式

JPEG:(joint photo graphicexpert group)靜态圖像壓縮方式。一種有損圖像的壓縮方式。壓縮比越大,圖像品質也就越差。當圖像精度要求不高存儲空間有限時,可以選擇這種格式。目前大部分數位相機都使用JPEG格式。

(5)、彩色深度(色彩位數)

反映對色彩的識别能力和成像的色彩表現能力,實際就是A/D轉換器的量化精度,是指将信号分成多少個等級。常用色彩位數(bit)表示。彩色深度越高,獲得的影像色彩就越豔麗動人。現在市場上的攝像頭均已達到24位,有的甚至是32位

(6)、圖像噪音

指的是圖像中的雜點幹撓。表現為圖像中有固定的彩色雜點。

(7)、視角

與人的眼睛成像是相成原理,簡單說就是成像範圍。

(8)、輸出/輸入接口

串行接口(RS232/422):傳輸速率慢,為115kbit/s

  并行接口(PP):速率可以達到1Mbit/s

  紅外接口(IrDA):速率也是115kbit/s,一般筆記本電腦有此接口

  通用串行總線USB:即插即用的接口标準,支援熱插拔。USB1.1速率可達12Mbit/s,USB2.0可達480Mbit/s

  IEEE1394(火線)接口(亦稱ilink):其傳輸速率可達100M~400Mbit/s 

今天 有點晚了,後繼續分析camera sensor接口、s5pv310 CAMIF接口、V4L2、FIMC、和我們最終的sensor驅動。

android camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)

一、攝像頭工作原理

上一篇我們講了攝像頭模組的組成,工作原理,做為一種了解。下面我們析攝像頭從寄存器角度是怎麼工作的。如何閱讀攝像頭規格書(針對驅動調節時用到關鍵參數,以GT2005為例)。

規格書,也就是一個器件所有的說明,精确到器件每一個細節,軟體關心的寄存器、硬體關心的電氣特性、封裝等等。單單驅動方面,我們隻看對我們有用的方面就可以了,沒必要全部看完。主要這樣資料全都是鳥語(En),全部看完一方面時間上會用的比較多,找到關鍵的地方就行了。

1、camera的總體示意圖如下:控制部分為攝像頭上電、IIC控制接口,資料輸出為攝像頭拍攝的圖傳到主要晶片,所有要有data、行場同步和時鐘号。GT2005/GT2015是CMOS接口的圖像傳感器晶片,可以感覺外部的視覺信号并将其轉換為數字信号并輸出。

       我們需要通過MCLK給攝像頭提供時鐘,RESET是複位線,PWDN在攝像頭工作時應該始終為低。PCLK是像素時鐘,HREF是行參考信号,VSYNC是場同步信号。一旦給攝像頭提供了時鐘,并且複位攝像頭,攝像頭就開始工作了,通過HREF,VSYNC和PCLK同步傳輸數字圖像信号。 資料是通過D0~D7這八根資料線并行送出的。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(1)、Pixel Array

       GT2005陣列大小為 1268 列、1248 行,有效像素為 1616 列, 1216 行。也就是說攝像頭為1600X1200的時候,像素點要多于這個,去除邊緣一部分,保證圖像品質吧。

(2)、IIC 這個不用說了,攝像頭寄存器初始化的資料都從這裡傳輸的,所有的IIC器件都一樣的工作,來張圖吧,後面做詳細分析;

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

下面這一部分在調試驅動的過程中比較重要了:

(3)、MCLK

電子元件工作都得要個時鐘吧,攝像頭要工作,這個就是我們所要的時鐘,在主要制晶片提供,這個時鐘一定要有,要不然攝像頭不會工作的。

(4)、上下電時序,這個要接規格書上來,注間PWDN、RESETB這兩個腳,不同的攝像頭不太一樣,這個圖是上電時序,上電時參考一下,知道在那裡看就行;

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(5)PCLK \D1~D7

攝像頭得到的資料要傳出來吧,要有資料,當然資料出來要有時鐘和同步信号了,看下它的時序,和LCD顯示的時序一樣,道理是一樣的:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(6)、主要的寄存器:分辨率、YUV順序、X軸、Y軸鏡相、翻轉

以上工作完成後,也許還有一些問題,分辨率太小; YUV順序不對圖像不對; XY圖像方向。這些工作完成後,如果還有什麼細節的問題,如果你想花時間,看規格書裡面的寄存器可以解決的,如果不想看,找模組廠的FAE,他們專業的,很快會幫你搞定。

(7)、攝像頭的硬體接口

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

二、S5pv310上Camera主要晶片上的硬體接口

1、CAMIF   Camera Interface

先看一下攝像頭接口框圖:(這個看着有點抽像,我們放這裡,先了解一下,其實驅動中一般不會涉及到這裡,不過我們這裡分析了,就把這個帶出來了)

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(1)、攝像頭接口的主要屬性:

a、支援多種輸入接口:(就是上面我們看到的四模式)

    DMA (AXI 64-bitinterface) 模式;

    MIPI (CSI) 模式;

    ITU-R BT 601/ 656/ 709模式;

    Direct FIFO (PlayBack)模式;

b、支援多種輸出模式:

    DMA (AXI 64-bitinterface) 模式;

    Direct FIFO 模式;

c、支援數位變焦Digital Zoom In (DZI) capability;

d、支援多攝像頭輸入;

e、 支援視訊同步信号極性可程式設計控制;

f、支援最大輸入分辨率為8192X8192;

g、支援圖像翻轉(X軸、Y軸鏡相,90、180、270翻轉);

h、支援多種圖檔格式; 

i、支援捕獲幀控制;

j、支援的圖像特效。

2、FIMC  Fully InteractiveMobile Camera

    攝像頭的采集的資料要CPU無法直接處理,主要晶片裡面內建了Camera控制器,叫FIMC(FullyInteractive Mobile Camera)。攝像頭需要先把圖像資料傳給控制器,經過控制器處理(裁剪拉升後直接預覽或者編碼)之後交給CPU處理。實際上攝像頭工作需要的時鐘(MCLK)也是FIMC給它提供的。

    在s5pv310上的攝像頭接口是一個FIMC(完全互動式移動相機接口),支援ITUR BT-601-605标準、AMX接口、MIPI接口

MIPI 、ITU、AMX

(1)、ITU國際電信聯盟無線電通信部門ITU-RRadiocommunication Sector of ITU 簡稱ITU-RITU-R BT.601 16位資料傳輸;Y、U、V信号同時傳輸,是并行資料,行場同步單獨輸出。

ITU-R BT.6568/10位資料傳輸;不需要同步信号;串行資料傳輸;傳輸速率是601的2倍;先傳Y,後傳UV。行場同步信号嵌入在資料流中。

(2)、MIPI(移動行業處理器接口)是MobileIndustry Processor Interface的縮寫 MIPI 規範:Camera工作組:MIPI Camera Serial Interface 1.0specification .Camera Serial Interface 2 v1.0 (CSI-2)

(3)、AMX(Advanced eXtensible Interface)是一種總線協定,該協定是ARM公司提出的AMBA(Advanced Microcontroller BusArchitecture)3.0協定中最重要的部分,是一種面向高性能、高帶寬、低延遲的片内總線。

3、接口資訊

FIMC信号定義如下所示(YCbCr模式)

Signal I/O Description    Type
HREF I 行同步信号
PCLK I 像素時鐘
DATA[7:0] I 像素資料
FIELD O FIELD信号
MCLK O 系統時鐘信号

通過CAM_MCLK給攝像頭提供時鐘,RST是複位線,PWDN在攝像頭工作時應該始終為低。HREF是行參考信号,PCLK是像素時鐘,VSYNC是場同步信号。一旦給攝像頭提供了時鐘,并且複位攝像頭,攝像頭就開始工作了,通過HREF,PCLK和VSYNC同步傳輸數字圖像信号。資料是通過DATA0~DATA7這八根資料線并行送出的。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

4、不同接口模式的工作時序

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

(ITU-R BT 601: 16位資料傳輸;21芯;Y、U、V信号同時傳輸。  

ITU-R BT 656: 9芯,不需要同步信号;8位資料傳輸;串行視訊傳輸;傳輸速率是601的2倍;先傳Y,後傳UV。)

同步信号的時延參數

Ø        t1:表示VSYNC前、後插入周期

Ø        t2:表示HREF前插入周期

Ø        t3:表示 HREF寬度

Ø        t4:表示HREF後插入周期

5、camera的時鐘域,三個時鐘:系統時鐘、PCLK、MCLK

    每個攝像頭接口包括三個時鐘域,每一個時鐘域是系統總線時鐘,第二個是攝像頭像素時鐘PCLK,第三個時鐘域為内部時鐘MCLK。系統總線時鐘必需高于PCLK, CAM_MCLK 必需固定頻率分頻,如PLL時鐘。如果有外部時鐘晶振,CAM_MCLK 空掉。不需要同步MMCLK,PCLK應該與schmitt-triggered電平移位器連接配接。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

6、硬體接口電路

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

VSYNC與HSYNC與PCLK與什麼有關系

在手機平台,LCD,Camera,TV的接線上,都會用到PCLK,VSYNC和HSYNC這三個信号。可見這三個信号和顯示關系非常大。首先我們先看這三個信号的作用:

PCLK:有些方案給他起名字叫:DotCLK。是像素點同步時鐘信号。也就是每個PCLK對應一個像素點。

VSYNC:是場同步信号。以高電平有效為例,VSYNC置高直到被拉低,這個區段所輸出的所有影像資料組成一個frame。

HSYNC:是行同步信号。就是在告訴接收端:“HSYNC”有效時段内接收端接收到的所有的信号輸出屬同一行。

若要顯示一個640x480的畫面,顯示不正确的時候,若量PCLK,VSYNC和HSYNC這三個信号,就可以知道這三個信号配置是否有問題,一般來講,這種情況是有公式的:

VSync = HSYNC x 480;

Hsync = PCLK x 640;

————————————————————————————————————————————————————————————————————————————————

sensor的同步信号可以簡單的了解為sensor向其信号接收端所發送的宣告信号

比如HSYNC,就是sensor這告訴接收端:“HSYNC”有效時段内sensor所有的信号輸出屬同一行。

VSYNC同理,以高電平有效為例,VSYNC置高直到被拉低,這個區段sensor所輸出的所有影像資料組成一個frame

同步信号的頻率決定于pixel clock,比如一行有640個pixel,那麼HSYNC的頻率為:PCLK/(640+dummy);Vsync同理。

————————————————————————————————————————————————————————————————————————————————

android camera(三):camera V4L2 FIMC

1. V4L2

1)簡介

        在Linux中,攝像頭方面的标準化程度比較高,這個标準就是V4L2驅動程式,這也是業界比較公認的方式。

        V4L全稱是Video for Linux,是Linux核心中标準的關于視訊驅動程式,目前使用比較多的版本是Video for Linux 2,簡稱V4L2。它為Linux下的視訊驅動提供了統一的接口,使得應用程式可以使用統一的API操作不同的視訊裝置。從核心空間到使用者空間,主要的資料流和控制類均由V4L2驅動程式的架構來定義。

V4L2驅動程式一般隻提供Video資料的獲得,而如何實作視訊預覽,如何向上層發送資料,如何把純視訊流和取景器、視訊錄制等實際業務組織起來,都是camera的硬體抽象層需要負責的工作。

V4L2驅動核心實作為如下檔案:drivers/media/video/v4l2-dev.c。

V4l2-dev.h中定義的video_device是V4L2驅動程式的核心資料結構,它為具體的攝像頭sensor驅動提供了接口調用。

V4l2的采集過程(應用程式):

1)     打開裝置,獲得檔案描述符;

2)     設定圖檔格式;

3)     配置設定緩沖區;

4)     啟動采集過程,讀取資料;

5)     停止采集,關閉裝置。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

2)資料結構

V4L2的主要資料結構是video_device,定義在v4l2_dev.h中:

struct video_device

{

    const struct v4l2_file_operations *fops;  

    struct device dev;        

    struct cdev *cdev;        

    struct device *parent;        

    struct v4l2_device *v4l2_dev;    

    char name[32];  

    int vfl_type;

    int minor;    

    u16 num;

    unsigned long flags;

    int index;

    spinlock_t        fh_lock;

    struct list_head    fh_list;

    int debug;            

    v4l2_std_id tvnorms;        

    v4l2_std_id current_norm;    

    void (*release)(struct video_device *vdev);

    const struct v4l2_ioctl_ops *ioctl_ops;   

};

主要接口函數有:

intvideo_register_device(struct video_device *vdev, int type, int nr);

static intv4l2_ioctl(struct inode *inode, struct file *filp,       unsigned int cmd, unsigned long arg);

2.  FIMC                     

1)簡介

FIMC這個子產品不僅僅是一個攝像頭的控制接口,它還承擔着V4L2的output功能和overlay的功能。

FIMC的驅動在核心中的位置:drivers/media/video/samsung/fimc

它包含下邊的檔案:

      fimc_regs.c

        fimc_capture.c

        fimc_dev.c

        fimc_output.c

        fimc_overlay.c

        fimc_v4l2.c

它們的組織關系如下:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

可以看到,FIMC的驅動實作了v4l2所有的接口,可以分為v4l2-input裝置接口,v4l2-output裝置接口以及v4l2-overlay裝置接口。這裡我們主要關注v4l2-input裝置接口,因為攝像頭屬于視訊輸入裝置。

fimc_v4l2.c裡面注冊了很多的回調函數,都是用于實作v4l2的标準接口的,但是這些回調函數基本上都不是在fimc_v4l2.c裡面實作的,而是有相應的.c分别去實作。比如:

v4l2-input裝置的操作實作:fimc_capture.c

        v4l2-output裝置的操作實作: fimc_output.c

        v4l2-overlay裝置的操作實作: fimc_overlay.c

這些代碼其實都是和具體硬體操作無關的,這個驅動把所有操作硬體寄存器的代碼都寫到一個檔案裡面了,就是fimc40_regs.c。這樣把硬體相關的代碼和硬體無關的代碼分開來實作是非常好的方式,可以最大限度的實作代碼複用。

 2) 資料結構 

FIMC的主要資料結構fimc_control,定義在fimc.h中:

struct fimc_control {

    int                id;        

    char                name[16];

    atomic_t            in_use;

    void __iomem            *regs;        

    struct clk            *clk;        

    struct regulator    *regulator;        

    struct fimc_meminfo        mem;        

    struct mutex            lock;        

    struct mutex            alloc_lock;

    struct mutex            v4l2_lock;

    wait_queue_head_t        wq;

    struct device            *dev;

    int                irq;

    struct video_device        *vd;

    struct v4l2_device        v4l2_dev;

    struct fimc_limit        *limit;        

    struct s3c_platform_camera    *cam;        

    struct fimc_capinfo        *cap;        

    struct fimc_outinfo        *out;        

    struct fimc_fbinfo        fb;        

    struct fimc_scaler        sc;        

    struct fimc_effect        fe;        

    enum fimc_status        status;

    enum fimc_log            log;

    u32                ctx_busy[FIMC_MAX_CTXS];

};

因為FIMC一共有三套一樣的控制器(fimc0, fimc1, fimc2),是以驅動裡使用了一個數組來描述:

struct video_device fimc_video_device[FIMC_DEVICES] = {

    [0] = {

        .fops = &fimc_fops,

        .ioctl_ops = &fimc_v4l2_ops,

        .release = fimc_vdev_release,

    },

    [1] = {

        .fops = &fimc_fops,

        .ioctl_ops = &fimc_v4l2_ops,

        .release = fimc_vdev_release,

    },

    [2] = {

        .fops = &fimc_fops,

        .ioctl_ops = &fimc_v4l2_ops,

        .release = fimc_vdev_release,

    },

};

fb_ops結構體是針對v4l2裝置的基本操作,定義如下:

static const struct v4l2_file_operations fimc_fops = {

    .owner        = THIS_MODULE,

    .open        = fimc_open,

    .release    = fimc_release,

    .ioctl        = video_ioctl2,

    .read        = fimc_read,

    .write        = fimc_write,

    .mmap        = fimc_mmap,

    .poll        = fimc_poll,

};

3)FIMC初始設定

在S5PV210中,FIMC初始設定代碼在 /drivers/ arch/arm/mach-s5pv210/mach-smdkv310.c中:

static struct s3c_platform_fimc fimc_plat = {

    .srclk_name    = "mout_mpll",

    .clk_name    = "sclk_fimc",

    .lclk_name    = "sclk_fimc_lclk",

    .clk_rate    = 166750000,

    .default_cam    = CAMERA_CSI_C,

         .camera        = {

        &mt9p111,//5M back cam

        &s5k6aafx,///1.3M front cam

    },

    .hw_ver        = 0x43,

};

 對于GPIO的配置代碼在 /drivers/ arch/arm/mach-s5pv210/setup-fimc0.c中:

oid s3c_fimc0_cfg_gpio(struct platform_device *pdev)

{

    int i = 0;

    for (i = 0; i < 8; i++) {

        s3c_gpio_cfgpin(S5PV210_GPE0(i), S3C_GPIO_SFN(2));

        s3c_gpio_setpull(S5PV210_GPE0(i), S3C_GPIO_PULL_NONE);

    }

    for (i = 0; i < 5; i++) {

        s3c_gpio_cfgpin(S5PV210_GPE1(i), S3C_GPIO_SFN(2));

        s3c_gpio_setpull(S5PV210_GPE1(i), S3C_GPIO_PULL_NONE);

    }

    for (i = 0; i < 8; i++) {

        s3c_gpio_cfgpin(S5PV210_GPJ0(i), S3C_GPIO_SFN(3));

        s3c_gpio_setpull(S5PV210_GPJ0(i), S3C_GPIO_PULL_NONE);

    }

    for (i = 0; i < 5; i++) {

        s3c_gpio_cfgpin(S5PV210_GPJ1(i), S3C_GPIO_SFN(3));

        s3c_gpio_setpull(S5PV210_GPJ1(i), S3C_GPIO_PULL_NONE);

    }

}

4)接口函數

FIMC的主要回調函數如下,實作在fimc_v4l2.c中:

onst struct v4l2_ioctl_ops fimc_v4l2_ops = {

    .vidioc_querycap        = fimc_querycap,

    .vidioc_reqbufs            = fimc_reqbufs,

    .vidioc_querybuf        = fimc_querybuf,

    .vidioc_g_ctrl            = fimc_g_ctrl,

    .vidioc_s_ctrl            = fimc_s_ctrl,

    .vidioc_s_ext_ctrls        = fimc_s_ext_ctrls,

    .vidioc_cropcap            = fimc_cropcap,

    .vidioc_g_crop            = fimc_g_crop,

    .vidioc_s_crop            = fimc_s_crop,

    .vidioc_streamon        = fimc_streamon,

    .vidioc_streamoff        = fimc_streamoff,

    .vidioc_qbuf            = fimc_qbuf,

    .vidioc_dqbuf            = fimc_dqbuf,

    .vidioc_enum_fmt_vid_cap    = fimc_enum_fmt_vid_capture,

    .vidioc_g_fmt_vid_cap        = fimc_g_fmt_vid_capture,

    .vidioc_s_fmt_vid_cap        = fimc_s_fmt_vid_capture,

    .vidioc_try_fmt_vid_cap        = fimc_try_fmt_vid_capture,

    .vidioc_enum_input        = fimc_enum_input,

    .vidioc_g_input            = fimc_g_input,

    .vidioc_s_input            = fimc_s_input,

    .vidioc_g_parm            = fimc_g_parm,

    .vidioc_s_parm            = fimc_s_parm,

    .vidioc_queryctrl        = fimc_queryctrl,

    .vidioc_querymenu        = fimc_querymenu,

    .vidioc_g_fmt_vid_out        = fimc_g_fmt_vid_out,

    .vidioc_s_fmt_vid_out        = fimc_s_fmt_vid_out,

    .vidioc_try_fmt_vid_out        = fimc_try_fmt_vid_out,

    .vidioc_g_fbuf            = fimc_g_fbuf,

    .vidioc_s_fbuf            = fimc_s_fbuf,

    .vidioc_try_fmt_vid_overlay    = fimc_try_fmt_overlay,

    .vidioc_g_fmt_vid_overlay    = fimc_g_fmt_vid_overlay,

    .vidioc_s_fmt_vid_overlay    = fimc_s_fmt_vid_overlay,

};

對于寄存器的操作,實作都在fimc_regs.c檔案中,如

int fimc_hwset_camera_source(struct fimc_control *ctrl)

{

    struct s3c_platform_camera *cam = ctrl->cam;

    u32 cfg = 0;

    cfg |= S3C_CISRCFMT_ITU601_8BIT;

    cfg |= cam->order422;

    if (cam->type == CAM_TYPE_ITU)

        cfg |= cam->fmt;

    cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);

    cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);

    writel(cfg, ctrl->regs + S3C_CISRCFMT);

    return 0;

}

int fimc_hwset_enable_irq(struct fimc_control *ctrl, int overflow, int level)

{

    u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);

    cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_LEVEL);

    cfg |= S3C_CIGCTRL_IRQ_ENABLE;

    if (overflow)

        cfg |= S3C_CIGCTRL_IRQ_OVFEN;

    if (level)

        cfg |= S3C_CIGCTRL_IRQ_LEVEL;

    writel(cfg, ctrl->regs + S3C_CIGCTRL);

    return 0;

}

android camera(四):camera 驅動 GT2005

攝像頭主要參數:

1、MCLK  24MHz;

2、PCLK  48~52MHz~;

3、電壓 1.8V(1.5V)、2.8V;

4、scl(IIC時鐘)100KHz或者400KHz。

我們以GT2005為例,來講述一個攝像頭驅動的調試過程:

攝像頭和主要的關系圖,如下:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

攝像頭驅動比較簡單,完成一面三大步就可以:

攝像頭的上電、時鐘這些基本條件;

IIC保證攝像頭的初始化;

攝像頭工作後傳回資料到主要。

完成這三個步驟就完成了攝像頭基本工作的調試。

1、 攝像頭的上電、時鐘這些基本條件的實作

電源部分,上電時對應規格書,确認上電時序;MCLK攝像頭的主時鐘是否提供,看下面是和電和規格書中的

(1)、主意攝像頭工作要兩組電壓:1.8V(1.5V)、2.8V還有MCLK

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

程式中對電源控制:我們在arch\arm\mach-smdkv310.c中,完成上面兩個步驟的代碼,(這一點不同平台也許有所不同,這裡這是一個執行個體,這部分代碼隻是針對三星平台的)

#ifdef CONFIG_VIDEO_GT2005

static void set_cam2005_main_power(int onoff)

{

    unsigned int gpio;

    int err;

    if(onoff)

    {

        err = gpio_request(S5PV210_GPB(2), "GPB");

        if (err)

            printk(KERN_ERR "#### failed to request GPB2 for CAM\n");

            s3c_gpio_cfgpin(S5PV210_GPB(2),S3C_GPIO_OUTPUT);

            s3c_gpio_setpull(S5PV210_GPB(2), S3C_GPIO_PULL_UP);

            gpio_direction_output(S5PV210_GPB(2), 1);

            gpio_free(S5PV210_GPB(2));

        //RESET

            err = gpio_request(S5PV210_GPE1(4), "GPE1");

            if (err)

                printk(KERN_ERR "#### failed to request GPE1_4 for CAM\n");

                s3c_gpio_setpull(S5PV210_GPE1(4), S3C_GPIO_PULL_NONE);

                gpio_direction_output(S5PV210_GPE1(4),0);

                mdelay(100);

                gpio_direction_output(S5PV210_GPE1(4), 1);

                gpio_free(S5PV210_GPE1(4));

        //PWDN CAM_back

            err = gpio_request(S5PV210_GPB(4), "GPB");

            if (err)

                printk(KERN_ERR "#### failed to request GPB4 for CAM\n");

                s3c_gpio_cfgpin(S5PV210_GPB(4),S3C_GPIO_OUTPUT);

                s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);

                gpio_direction_output(S5PV210_GPB(4), 0);

                mdelay(100);

                gpio_direction_output(S5PV210_GPB(4), 1);

                gpio_free(S5PV210_GPB(4));

    }

    else    

    {    

        ………………

    }

    return;

}

#endif

提供MCLK代碼如下:

static int smdkv210_cam_clk_init(void)

{

    unsigned int tempvalue=0;

          tempvalue = readl(S5P_CLK_DIV1);    

    tempvalue = (tempvalue &0xffff0fff);    

    writel(tempvalue,S5P_CLK_DIV1);    

    tempvalue = readl(S5P_CLK_SRC1);    

    tempvalue = (tempvalue &0xffff0fff)|0x00001000;    

    writel(tempvalue,S5P_CLK_SRC1);    

    return 0;

}

這時拿示波器抓到上電時的波形和MCLK24MHZ的時鐘,信号就說明我們完成了這一步,其實在實際工作中,我們一般出問題的時候才會測這些資料,确認問題點。

上電時序:

(1)、上電時序;

(2)、MCLK如下所示。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

2、 IIC和一些參數的配置

#ifdef CONFIG_VIDEO_GT2005

static struct GT2005_platform_data GT2005_plat = {

    .default_width = 640,

    .default_height = 480,

    .pixelformat = V4L2_PIX_FMT_UYVY,   //    .freq = 24000000,

    .is_mipi = 0,

};

static struct i2c_board_info GT2005_i2c_info = {

    I2C_BOARD_INFO("GT2005", 0x78 >> 1), //1、IIC位址

    .platform_data = >2005_plat,

};

static struct s3c_platform_camera GT2005 = {

#ifdef CAM_ITU_CH_A

    .id        = CAMERA_PAR_A,   

#else

    .id        = CAMERA_PAR_B,

#endif

    .type        = CAM_TYPE_ITU,   //2、資料接口選擇(ITU\MIPI等)

    .fmt        = ITU_601_YCBCR422_8BIT,

    .order422    = CAM_ORDER422_8BIT_CBYCRY, //3、圖像資料格式 

    .i2c_busnum    = 1,

    .info        = >2005_i2c_info,

    .pixelformat    = V4L2_PIX_FMT_UYVY,    

    .srclk_name    = "mout_mpll",              //4、這部分關系到時鐘

    .clk_name    = "sclk_cam1",

    .clk_rate    = 24000000,              

    .line_length    = 640,              

    .width        = 640,

    .height        = 480,

    .window        = {

        .left   = 16,

        .top    = 0,

        .width  = (640 - 16),

        .height = 480,

    },

                                //5、信号的極性,    .inv_pclk    = 0,

    .inv_vsync    = 1,

    .inv_href    = 0,

    .inv_hsync    = 1,

    .initialized    = 0,

    .cam_power=set_cam2005_main_power

};

#endif

注意下面幾個參數:

(1)、IIC位址

(2)、資料接口選擇(ITU\MIPI等),這幾個資料接口我們在前面提到過;

(3)、圖像資料格式 ,這就是我們前面提到的YVU\UVY之類不同的資料順序;

(4)、這部分關系到時鐘;

(5)、輸出信号的極性,就是我們PCLK、VSYNC、HSVNC這些信号的極性,不正确時會沒有圖像之類現象,這個也要注意了。

完成這一步确認IIC通信是否正常,如下圖所抓到波形:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

3、 完成上面兩步,攝像頭基本配置完成,我們确認下輸出端PCLK、VHSN、SVSN、D1-D7

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

二、攝像頭調試過程中常遇到的問題

1、錄相在預覽時正常,播放錄像時花屏(程式解釋為三星s5pv210/s5pv310是的,其它的可以參考,找相應代碼)

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

原因分析:

(1)錄相用fimc2,

在android/device/samsung/proprietary/libcamera/SecCamera.cpp中

int SecCamera::startRecord(void)

m_cam_fd_rec = open(CAMERA_DEV_NAME2, O_RDWR);

vendor\sec\sec_proprietary\smdkc110\libcamera\SecCamera.h

#define CAMERA_DEV_NAME2      "/dev/video2"

(2)所用的視訊格式,在

android/device/samsung/proprietary/libcamera/SecCameraHWInterface.cpp中

void CameraHardwareSec::m_initDefaultParameters(int camera_id)

 int default_preview_pixel_format = mSecCamera->getPreviewDefaultPixelFormat();

    switch (default_preview_pixel_format) {

    default:

    case V4L2_PIX_FMT_NV21:

        p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);

        break;

    case V4L2_PIX_FMT_NV12T:

        p.setPreviewFormat("yuv420sp_tiled");

        break;

    }

其中mSecCamera->getPreviewDefaultPixelFormat()在

vendor\sec\sec_proprietary\smdkc110\libcamera\SecCamera.cpp中實作,

int SecCamera::getPreviewDefaultPixelFormat(void)

{

    return DEFAULT_PREVIEW_PIXEL_FORMAT;

}

在android/device/samsung/proprietary/libcamera/SecCamera.h中設定初始值。我們這裡設的是

#ifdef DUAL_PORT_RECORDING

    #define DEFAULT_PREVIEW_PIXEL_FORMAT  (V4L2_PIX_FMT_NV21)

#else

    #define DEFAULT_PREVIEW_PIXEL_FORMAT  (V4L2_PIX_FMT_NV12T)

#endif

以上得出視訊格式為V4L2_PIX_FMT_NV21。

2、圖像幹擾問題,如下圖所示

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

原因可能是:

(1)、攝像頭模組有問題,換一個攝像頭試一下;

(2)、資料線驅動能力不足,這個可以在攝像頭寄存器裡面改,問下攝像頭模組FAE,看改那些地方;

(3)、兩個攝像頭共用資料線時,不工作的攝像頭會把工作的資料信号減弱;

(4)、PCB 走線太長,也會有幹擾,不過我覺得這個可能性小,調試好就一款這樣的的,模組廠FAE說的,不過他們模組本身也有問題,兩方面因素都有吧:PCB(線過長)、模組打樣也有問題。

3、YUV順序不對:

yuv順序不對時,出現如下現象。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

看下攝像頭規格書,把相應寄存器的值改一下就可以了。如下以紅框裡是不同yuv順序,找到改為相應的。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

4、 預覽方向不對(攝像頭寄存器隻能改以 180度為基數的,90度的就要在FIMC中改)

想知道和比較明确說明翻轉角度,最常用的就是寫一個“F”,然後看預覽裡的是怎麼轉的。

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

上面有90度的翻轉,因為這是FIMC中的寄存器,一般不會改這一部分的值。要不就在模組寄存器中改,要不就在上層。上面隻是說明如何去确認圖像翻轉。

看下GT2005關于翻轉的寄存器吧:

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

5、 雜光,鬼影:

其行業的專業術語統稱為Flare,是指在拍攝光源或者強光物體時,邊緣出現光影或出現一個完整物體的影子,而且這種現象隻能減輕不能完全消失,原因是由于鏡片的材質導緻光線不但存在折射還存在反射,整機由于鏡頭面到保護鏡片距離很大會更明顯!

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

6、 常見問題相關

攝像頭效果評測都有哪些?

camera模組 ------- super Goodandroid camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF)android camera(三):camera V4L2 FIMCandroid camera(四):camera 驅動 GT2005

以上以gt2005為例,說了一下攝像頭驅動,和驅動中常見到的問題,如果上面的問題解決,攝像頭點亮,說明在平台是運作是沒問題的,小的問題和細節,要找模組廠的FAE過來協助解決,不過你想多研究一下的話,也可以,如果項目允許,就多看看,做到調試一個驅動,所有問題都了解,這樣對工作經驗、積累很重要的,希望對大家有用。

繼續閱讀