查看: 5296|回复: 0
收起左侧

MTK6577Camera驱动浅析

[复制链接]
发表于 2015-8-31 08:24:48 | 显示全部楼层 |阅读模式

1.png

# d4 z! K+ F  F" X

图1


6 L0 s$ v1 g  t& G- ]

1.     Camera拍照相关概念

1.1  ISP

: W& J! W- j' R$ y0 J

isp——(Image Signal Processor)——影视处理


; s, p7 E- |  y& j! D+ Z

无论数码相机、摄像机或者摄像手机,其影像数据从前端感应后,皆须经过ASP(Analog Signal Processing)、ADC(Analog-Digital Converter)、前期影像处理(Pre-ISP)与后端影像处理(Post-ISP)四个阶段后,影像数据才能最终呈现于终端设备上


6 N" f1 `( b  l. v8 N1 R7 m

1.2  720p

720P是美国电影电视工程师协会(SMPTE)制定的高等级高清数字电视的格式标准,有效显示格式为:1280×720.SMPTE(美国电影电视工程协会)将数字高清信号数字电视扫描线的不同分为1080P、1080I、720P(i是interlace,隔行的意思,p是Progressive,逐行的意思)。720P是一种在逐行扫描下达到1280×720的分辨率的显示格式。是数字电影成像技术和计算机技术的融合。

3 O- G* m; ~& ]6 A2 Z

分辨率为1280×720p/60Hz,行频为45kHz


5 a) O: G. ]$ e1 S$ K6 H9 j. G/ C2 a

2.     MTK6577Camera控制器部分

2.1  camera控制器概述

MT6577 camera可接受RAM和SOC传感器处理之后的图像数据(sensor image data),并输出YUV数据给MDP(什么的简称)。Camera控制器可同时连接2个并行SOC传感器,它提供像素缺陷补偿(bad pixel compensation)、去马赛克(demosaic)、边缘曾强(edge enhancement)、标准色自适应(preference color adaptation)、空间和暂时噪声消除(spatial and temporal noise reduction)这些特征,用于图像处理。


& }& A; ]3 v2 v* Q8 R

2.2  camera特征

* o+ ~9 ?3 S3 d

MT6577内部集成的ISP,包含了一个功能强大的图像信号处理器,用于连接各种各样的图像传感器模组,这个处理器由时序产生单元(timing generated unit: TG)、镜头/传感器补偿(lens/sensor compensation)单元和图像处理单元。


, S1 [" {5 W  _

支持的特征如下:

(1)   抓图分辨率达8M像素(image capture resolution)。

(2)   录像分辨率达720p(video recording resolution)。

(3)   原始图像数据转储帧率8M@15(raw dump frame rate)。

(4)   曝光抓图率8M@7(burst capture rate)。

(5)   图像处理

低像素补偿(poor pix compensation)、镜头阴影补偿(lens shading compensation)、去马赛克(demosaic)、色彩削波(color clipping)、局部对比度增强(local contrast enhancement)、伽玛校正(gamma correction)、边缘曾强(edge enhancement)、噪声消除(noise reduction)、标准色自适应(preference color adaptation)、空间和暂时噪声消除(spatial and temporal noise reduction)。

$ U  V3 `: x- a8 |: E$ P

(6)   3A统计和校正(statistics and correction)

(7)   闪烁检测(flicker detection)。


8 ]6 `& o" W, F6 _7 h- K

2.3  camera框图

2.png

$ v& j2 R$ _& N

图2

       TG只配合主图像传感器(master type image sensor),也就是说主图像传感器应发送垂直和水平信号给TG。TG通过内部自动同步 (internal auto synchronization)或外部像素时钟同步来提供传感器所需要的数据时钟和接收传感器Bayer模式原始数据(Bayer pattern raw data)。TG的主要目的是为主图像传感器创建数据时钟和接收垂直/水平同步信号与sensor数据,然后产生Bayer数据的捕获区域(grabbed area of Bayer data)或是YUV422/RGB565数据给镜头/传感器补偿(lens/sensor compensation)单元。


' P2 d  v' E" G8 T; i' P/ s/ P8 l5 f

在Bayer原始数据输入模式,镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据给色彩处理单元(color process unit);在YUV422/RGB565 输入模式,这步被忽略。


9 t( {+ y- X% r, V8 k  f. }+ ^

色彩处理单元接受来之镜头/传感器补偿(lens/sensor compensation)单元产生补偿的原始数据或是YUV422/RGB565数据。ISP的输出的是很容易被压缩引擎(compress engine,JPEG编码器和MPEG4编码器)编码的YCbCr888数据格式,它是其他数据格式转化的基本数据域(比如R/G/B domain)(it can be the basic data domain of otherdata format translation such as the R/G/B domain)。ISP是流水线式(pipelined),在处理阶段ISP硬件能够为后面的AE/AF/AWB计算提取有意义的信息,这些信息被临时保存在ISP寄存器或是内存中,并且能够被MCU读取出来。


/ o  c/ m# o/ Q

下面给出一些性能参数:

3.png

: i4 w6 d' Z) n, X

图3


$ z9 a7 F* g  l0 l$ @' C

3.     原理图设计

5 N- m& H1 N, D- z; F5 N8 G( `

MT6577支持两路camera接口,一路是MIPI接口,一路是并行接口,这里我们采用的是并行接口,下面给出MT6577 CAM并行接口定义:

4.png

3 P% ~5 x4 j9 c* h1 G2 D6 {

图4

Camera sensor连接座如下:

5.png

" f. }0 O7 N, G4 K; L' c

图5


8 f& E2 x: s# G1 @1 U5 s  c

(1)  OV5640输出的数据格式

《Y1MT6577 design notice V0.1.pdf》文档给出这样的说明:

Sensor outputformat is RAM8/YUV/JPEG,connect sensor output to CMDAT[0:7] or CMDAT[2:9]

Sensor outputformat is RAM10,connect sensor output to CMDAT[0:9]

而我们采用摄像头模组的驱动IC为OV5640(500万像素: active array size: 2592 x 1944) Sensor :outputformats: 8-/10-bit RGB RAW output,这是由OV5640寄存器0x4745决定的。原则就是:首先看硬件上采用的是8根数据线还是10根数据线,然后初始化参数-也就是寄存器设定也可以设定是8位或10位。如下图:

6.png


& @7 \5 N) e/ i/ U: l& j

图6

' ~% p. P( Q7 G8 j! f3 u) |2 w( l0 t

2 `4 S: F7 }0 ]

(2)  OV5640IIC地址

) C, k+ C) [* w

IIC 8bit写地址为0x78,读地址为0x79,查询Sensor规格书可以看到:

7.png


" x+ B- w( a; R9 v

图7

IIC 8bit地址最后一位为0时是写地址,为1时是读地址。这属于IIC通讯规则

) H( c1 X$ L: j

! V% `5 T; B9 K* e0 U2 Z1 B" v" g% O5 G- W" i; W9 `2 H+ Y

4.     驱动实现


/ A! k/ c! ]9 r
; Y3 _& [1 Y" k1 p, |

4.1  相关代码

(1)  CameraSensor驱动相关文件

\mediatek\custom\common\kernel\imgsensor\ov5642_yuv


% `& v+ X+ k' H. S# [- d6 s7 J

(2)  SensorID和一些枚举类型的定义

\mediatek\custom\common\kernel\imgsensor\inc

kd_imgsensor.h---------SensorID

kd_imgsensor_define.h--------------一些枚举类型的定义

$ u$ L  O/ T( v1 v" v

(3)  Sensor供电

\mediatek\custom\common\kernel\camera\camera

kd_camera_hw.c和kd_camera_hw.h


$ I& ]+ t  V- o

(4)  KernelSpace的SensorList,imgsensor模块注册

\mediatek\custom\common\kernel\imgsensor\src

kd_sensorlist.c和kd_sensorlist.h-----------camera模块加载

; y! u& B3 G8 I. I8 W

(5)  UserSpace的SensorList,向用户空间提供支持的SensorList

\mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp

提供给用户空间的SensorList

$ y5 _0 Q/ J7 r$ K1 ]# Z) |0 B& y
0 `$ q* u. O; l# C) v" y

(6)  Sensor效果调整的接口

\mediatek\custom\common\hal\imgsensor\ov5642_yuv


3 q: ~  c0 T  c) v" r4 W/ [
8 a3 X0 y5 B! H* _+ S

4.2  针对OV5640的修改

! k' _: r! }" L* v0 G0 `( [

4.2.1       mediatek\config\hsimobile77_ics2\ProjectConfig.mk

8 }  q# Y# h, z! X, E/ f4 L5 d

CUSTOM_KERNEL_IMGSENSOR=mt9p017_rawgc0329_yuv

mt9p017_raw表示后置摄像头(也就是主摄像头),mt9p017是摄像头sensor驱动IC,raw是sensor一种输出的数据格式,是CCD或CMOS在将光信号转换为电信号时的电平高低的原始记录,单纯地没有将没有进行任何处理的图像数据,即摄像元件直接得到的电信号进行数字化处理而得到的。

* e: f7 P* X" G

gc0329_yuv是前置摄像头,yuvsensor一种输出的数据格式,支持YUV/RGB格式的模组,一般会带有ISP(image single processor),经过A/D转换过的原始数据经过ISP处理生成YUV标准格式传到BB。


! }/ W; {0 ?% b3 ?& z

我们采用的OV5640就带有ISP,输出YUV格式


7 P( ]! n3 d* j3 Q$ S! _1 E

(1)  把mt9p017_raw 改为ov5640_yuv,去掉gc0329_yuv因为我们的产品没有后置摄像头

(2)  去掉类似CUSTOM_KERNEL_LENS后面的dummy_lens因为没有后置摄像头

  y* L. x! a- z

修改之后的HAL层的配置:

" h$ o' I% [& Q# c
  • CUSTOM_HAL_IMGSENSOR=ov5640_yuv  
  • CUSTOM_HAL_LENS=fm50afdummy_lens  
  • CUSTOM_HAL_MAIN_BACKUP_IMGSENSOR=  
  • CUSTOM_HAL_MAIN_BACKUP_LENS=  
  • CUSTOM_HAL_MAIN_IMGSENSOR=ov5640_yuv  
  • CUSTOM_HAL_MAIN_LENS=fm50af  
  • CUSTOM_HAL_MATV=  
  • CUSTOM_HAL_MSENSORLIB=mmc328xakm8975 ami304 yamaha530 mag3110 akmd8963  
  • CUSTOM_HAL_SENSORS=sensor  
  • CUSTOM_HAL_SUB_BACKUP_IMGSENSOR=  
  • CUSTOM_HAL_SUB_BACKUP_LENS=  
  • CUSTOM_HAL_SUB_IMGSENSOR=  
  • CUSTOM_HAL_SUB_LENS=dummy_lens  / ~% {  R! m4 {% z/ a! c9 n" K1 c
1 Y1 {# N% T) }
9 J% Z: e& F$ }. N( _! `

% B) j0 t3 U7 K0 h

修改之后的kernel层的配置:

7 W1 {  {: i" }0 b! x: ~3 K% s
  • CUSTOM_KERNEL_IMGSENSOR=ov5640_yuv  
  • CUSTOM_KERNEL_JOGBALL=  
  • CUSTOM_KERNEL_KPD=kpd  
  • CUSTOM_KERNEL_LCM=ili9806e  
  • CUSTOM_KERNEL_LEDS=mt65xx  
  • CUSTOM_KERNEL_LENS=fm50afdummy_lens  
  • CUSTOM_KERNEL_MAGNETOMETER=akm8975  
  • CUSTOM_KERNEL_MAIN_BACKUP_IMGSENSOR=  
  • CUSTOM_KERNEL_MAIN_BACKUP_LENS=  
  • CUSTOM_KERNEL_MAIN_IMGSENSOR=ov5640_yuv  
  • CUSTOM_KERNEL_MAIN_LENS=fm50af  
  • CUSTOM_KERNEL_MATV=  
  • CUSTOM_KERNEL_OFN=  
  • CUSTOM_KERNEL_RTC=rtc  
  • CUSTOM_KERNEL_SOUND=amp_6329pmic_2in1_spk  
  • CUSTOM_KERNEL_SUB_BACKUP_IMGSENSOR=  
  • CUSTOM_KERNEL_SUB_BACKUP_LENS=  
  • CUSTOM_KERNEL_SUB_IMGSENSOR=  
  • CUSTOM_KERNEL_SUB_LENS=dummy_lens  , h* Z- }0 q7 u4 W" m/ B- |* X: r/ s
0 d: Q" [5 A/ K' ^; h& G

8 a% r" e! A  n  i& Z! z. o) |; I" L7 U
0 y, Z0 ]) Z0 ^7 G

虽然我们没有后置摄像头,但不能去掉dummy_lens,我尝试过去掉之后用./mk r dr编译会提示下面的错误:

! l' {& [$ B9 ]* {0 l8 q

' b1 Y) ?6 g( @$ ]( N
  • prebuilt/linux-x86/toolchain/arm-linux-androideabi-4.4.x/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld:out/target/product/hsimobile77_ics2/obj/SHARED_LIBRARIES/libcameracustom_intermediates/common/hal/lens/lenslist.o:in function global constructors keyed tolenslist.cpp:mediatek/source/external/mhal/src/custom/common/hal/lens/lenslist.cpp:82:error: undefined reference to 'pDummy_getDefaultData'  
  • make[3]: ***[out/target/product/hsimobile77_ics2/obj/SHARED_LIBRARIES/libcameracustom_intermediates/LINKED/libcameracustom.so]Error 1  
    . i& Z, o7 P( j; I! x) G
) H6 C0 z9 S! A- y
/ g$ a, @, F( {/ [! {' C
/ z0 o- N% f# \9 M  A
" m9 B2 x: i- h% Q

4.2.2       mediatek\custom\common\kernel\imgsensor----------kernel层

2 t- X8 u1 N9 d& B" R4 a$ q$ p# U' o

(1)  创建ov5640_yuv并建立需要的文件


$ m& E8 X  F8 b) h( E4 D

创建文件夹ov5640_yuv,把sensor IC厂家提供的ov5640yuv_Sensor.c放到此目录下。另外拷贝ov5642yuv_Sensor.h、ov5642yuv_Camera_Sensor_para.h、ov5642yuv_CameraCustomized.h拷贝过来改为ov5640yuv_Sensor.h等。


) l- [6 T& v8 w% k& n5 Y

编译发现mediatek\custom\common\kernel\imgsensor\ov5640_yuv\ov5640yuv_Sensor.c文件用到的OV5640_FULL_PERIOD_PIXEL_NUMS_HTS、OV5640_FULL_PERIOD_LINE_NUMS_VTS、OV5640_PV_PERIOD_PIXEL_NUMS_HTS和OV5640_PV_PERIOD_LINE_NUMS_VTS没有定义,但ov5642yuv_Sensor.c是没有这几个宏定义,我暂时定义如下:


0 A% W5 i1 J! d  G
  L. z' l! B/ R6 I# g2 u
  • //kandi add startat 2014.11.29  
  • #defineOV5640_FULL_PERIOD_PIXEL_NUMS_HTS  OV5640_FULL_PERIOD_PIXEL_NUMS  
  • #define  OV5640_FULL_PERIOD_LINE_NUMS_VTS   OV5640_FULL_PERIOD_LINE_NUMS  
  •    
  • #defineOV5640_PV_PERIOD_PIXEL_NUMS_HTS  OV5640_PV_PERIOD_PIXEL_NUMS  
  • #define  OV5640_PV_PERIOD_LINE_NUMS_VTS   OV5640_PV_PERIOD_LINE_NUMS  , ?5 a" H4 w  F9 N) K& W2 Q
( c3 t* j* N$ f
! s! ^! v: _. s9 _1 L

4 z' a4 `1 }3 \" a6 y' U

这是参考ov5642的相关定义来定义的。

. A0 N0 o7 u3 L) h8 [" F" C

(2)  在支持的sensor列表中增加目标sensor

8 t& ^$ @5 Q; `: k0 w

mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.h

在数组增加OV5640的内容,如下:

0 O! q1 C! ]0 P! g& Z" L
  s6 R1 F' i) U9 {
  • ACDK_KD_SENSOR_INIT_FUNCTION_STRUCTkdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =  
  • {  
  •        ………….  
  •        #if defined(OV5640_YUV)  
  • {OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, OV5640_YUV_SensorInit},  
  • #endif  
  • …………….  
  • }  - w5 G! U) w1 ~( V: [
    / @* H. s; M6 w$ L! G
1 `5 P  I* [9 c/ P2 D( g) q
* `/ t; |2 J  P+ b9 T, z* X3 c
) e5 V  g$ U9 R4 M# |% K

也增加UINT32 OV5640_YUV_SensorInit(PSENSOR_FUNCTION_STRUCT*pfFunc);

mediatek\custom\common\kernel\imgsensor\inc\kd_imgsensor.h

(3)  增加sensor ID和字符串的定义

! U7 u2 T2 f- p4 w+ {# r

' R6 [5 u& d! {! w( m$ K& P
  • #defineOV5640_SENSOR_ID            0x5640  
  • #defineSENSOR_DRVNAME_OV5640_YUV  "ov5640yuv"  
    & }2 S9 z8 ~: `4 e
; s: G; U1 R. B' p4 y3 Z/ M7 x
7 c- e) b5 a: D# D1 |0 X

" r( b! ^# I2 v8 D

4.2.3       mediatek\custom\common\hal\imgsensor---------------HAL层


) V5 D' j9 Z+ G+ a5 X. H% L3 r

(1)  创建ov5640_yuv文件夹

但这些文件夹下该有哪些文件,有需要哪些内容了,首先我对比了

ov3640_yuv和ov5642_yuv文件夹,只有cfg_ftbl_ov5642_yuv.h有差别:

8.png

图8

( `/ b: }/ T" [' G

这里主要是不同驱动IC支持的分辨率不同,以及设置默认的分辨率。

9.png

图9


5 f) x7 @  r4 p- z, e9 X

此文件下有两个这样的地方不同,这里是指自动对焦模式。

( ^) p; O8 q1 Y; \7 t5 ^. n+ f  x

因为我们的OV5640和OV5642非常接近,所以就直接把OV5642的目录复制过来修改为OV5640即可。

( q, N7 M; O" y9 \1 @+ y

所以把mediatek\custom\common\kernel\imgsensor\ov5642_yuv拷贝到imgsensor目录下,改为ov5640_yuv


! p3 S! r! h* a) r7 [& l

(2)  在支持的sensor列表中增加目标sensor

2 |( h- a- G5 f: r3 h. [, Q

\src\ sensorlist.cpp

% _& }" h$ ]5 J

7 D, _' J9 v; P9 Q+ K' S
  • MSDK_SENSOR_INIT_FUNCTION_STRUCTSensorList[] =  
  • {  
  • ………..  
  • #ifdefined(OV5640_YUV)  
  •     YUV_INFO(OV5640_SENSOR_ID,SENSOR_DRVNAME_OV5640_YUV, NULL),  
  • #endif  
  • …………  
  • }  & q% Q6 j' D4 N7 @3 P+ G

' N; ]" q( e3 I# D* t
% H$ G; F  E9 N( C9 k' b* E" o( ]1 X/ _+ H5 y  v, L. F" P' m% O

注意:在 kd_SensorList.h 和 SensorList.cpp 里面添加驱动的时候要注意,Sensor 添加的位置要一样。否则驱动会跑乱,轻则 ISP 参数不对,重则 Sensor 无法启动。


4 Z: p/ D/ K& d5 K# J
. [6 [: s- \5 |

4.3  拍照图片尺寸设置


1 q( [/ v/ B7 s: I1 u* {7 y2 _, B

mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h


$ s6 C1 ?: x3 e
* I9 U  z4 z2 U& L
( \% O# f( `) d# i5 g, _
  • // Capture Size  
  •    CONFIG_FEATURE_SI(FID_CAP_SIZE,  
  •        BY_DEFAULT(CAPTURE_SIZE_2560_1920),  
  •        CAPTURE_SIZE_1280_960,  CAPTURE_SIZE_1600_1200,  
  •        CAPTURE_SIZE_2048_1536,CAPTURE_SIZE_2560_1920  
  •    )  # B" o6 c( p# R+ k5 B# h1 j
    4 L1 \+ K8 x! }! D/ A. U  s& u

& I, H, u5 j/ K2 V. [6 \' f4 }! O* Y" k1 ]) d$ N

4.4  Camera物理角度旋转

Cfg_setting_imgsensor.h

8 W1 _7 w1 b; F  @
4 k0 w6 s( M' I
  • /*******************************************************************************
  • * Image SensorOrientation
  • *******************************************************************************/  
  • SensorOrientation_Tconst&  
  • getSensorOrientation()  
  • {  
  •     static SensorOrientation_T const inst = {  
  •         u4Degree_0  : 0,//270,//180,//90,   // main sensor in degree (0, 90, 180, 270),kandi change from 90 to 180  
  •         u4Degree_1  : 0,   //  sub  sensor in degree (0, 90, 180, 270)  
  •     };  
  •     return inst;  
  • }  4 K% R3 |# f. |* G; b$ H, O

    ( B- |$ H. V+ p
2 e. C" l$ M" V5 @2 T5 b( G
5 ~3 V  b+ K& S- O/ i( K

* b3 Y# [+ B+ W/ c8 g0 L7 m# \- K

        这几种都试过了,但都不行,预览和实际的都是成某种镜像关系。这是平台是提供旋转的功能。这个配置好了之后,如果方向不正确,可以通过驱动中的方向调整函数进行调整,如下: static void XXXXXSetMirror(kal_uint16ImageMirror)

参考:http://blog.csdn.net/loongembedded/article/details/41679977


- w8 F4 I. u, s6 P, T. w
+ \2 r2 {. ]) h! Z) s- o& Q( K/ b, v, v7 S3 x. X: v! A8 C+ Z: S

      看了OV5640的数据手册,寄存器0x3820和0x3821是用于控制图像发射(mirror)和翻转(flip)的,在u4Degree_0=270情况下,OV5640YUVPreview()调用OV5640YUV_Set_Mirror_Flip (IMAGE_V_MIRROR),预览和拍照后的预览都是OK,但拍好的照片在电脑上打开的时候发现是顺时针翻转了90度。

http://bbs.csdn.net/topics/390837150

可是我在OV5640YUV_Sensor_Init()调用OV5640YUV_Set_Mirror_Flip(IMAGE_V_MIRROR)却问题依旧,很奇怪。


0 F% j7 ~3 @4 O3 R6 s4 ^- ^4 S

mediatek\custom\common\hal\imgsensor\ov5640_yuv\cfg_ftbl_ov5640_yuv.h

2 a$ p0 G4 h( s  e
  • /*
  •     // Capture Size
  •     CONFIG_FEATURE_SI(FID_CAP_SIZE,
  •         BY_DEFAULT(CAPTURE_SIZE_2560_1920),
  •         CAPTURE_SIZE_1280_960,  CAPTURE_SIZE_1600_1200,
  •         CAPTURE_SIZE_2048_1536,CAPTURE_SIZE_2560_1920
  •     )
  •     */  
  •      // Capture Size  
  •     CONFIG_FEATURE_SI(FID_CAP_SIZE,  
  •         BY_DEFAULT(CAPTURE_SIZE_1920_2560),  
  •         CAPTURE_SIZE_960_1280,  CAPTURE_SIZE_1200_1600,  
  •         CAPTURE_SIZE_1536_2048,CAPTURE_SIZE_1920_2560  
  • )  - C  I& X  s5 @0 y
; L5 z/ q$ H" d8 x$ Z" M

+ ?& i' [' c3 d7 |/ {" L' d% U

我试过做上面的修改,但打开摄像头的时候,提示”Unfortunately, Camera has stopped”

本文作者:LoongEmbedded
$ z6 T. k! D0 h, }+ e
  t- R0 [1 Q6 H1 G/ h
高级模式
B Color Image Link Quote Code Smilies @朋友 |上传

本版积分规则

在线客服

客服电话

欢迎来电咨询

188-9985 8350

微信关注

手机APP程序:
扫码下载访问

微信公众平台:
摄像头之家公众号

微信小程序:
摄像头小程序

返回顶部

QQ|站点统计|小黑屋|手机版|Archiver|摄像头模组论坛网 ( 粤ICP备18155214号 )

Powered by Discuz! X3.4 Licensed© 2001-2013 Comsenz Inc.