Camera硬件及基于V4L2驱动源码分析
Jorgen Quan
2012-12-18
摘要:本文主要描述camera的硬件工作原理以及基于V4l2驱动框架的SC8810平台camera源码进行分析,从而弄懂camera整个底层部分的工作原理。为今后工作准备好扎实的理论基础。
疑问:
1. v4l2_device_register和video_register_device的区别,为什么这两个都要注册起来??
2. 视频缓存队列是如何管理的?驱动中在哪里申请分配内存?怎么入列出列?
3. 展讯平台中如何与硬件操作关联起来?
一、Camera硬件工作原理
1. 摄像头模组介绍
摄像头模组,全称CameraCompact Module,以下简写为CCM,是影像捕捉至关重要
的电子器件。主要组成部分:lens和Sensor IC,其中有些Sensor IC是集成了DSP,有些是没有集成DSP,没有集成DSP的module需要外部外挂DSP。
2. 摄像头工作原理、camera的组成和各组件的作用
图1-1.摄像头模组结构示意图
2.1、工作原理:
物体通过镜头(lens)聚集的光,通过CMOS或CCD集成电路,把光信号转换成电信号,再经过内部图像处理器(ISP)转换成数字图像信号输出到数字信号处理器(DSP)加工处理,转换成标准的GRB、YUV等格式图像数据。
2.2、CCM包含四大组件:
镜头(lens)、传感器(sensor)、软板(FPC)、图像处理芯片(DSP)。决定一个摄像头好坏的重要部件是:镜头(lens)、图像处理芯片(DSP)、传感器(sensor)。CCM的关键技术为:光学设计技术、非球面镜制作技术、光学镀膜技术。
镜头(lens)是相机的灵魂,仅次于CMOS芯片影响画质的第二要素,镜头(lens)是利用透镜的折射原理,景物光线通过镜头,在聚焦平面上形成清晰的影像,通过感光材料CMOS或CCD感光器记录景物的影像。其组成是透镜结构,由几片透镜组成,一般可分为塑胶透镜(plastic)或玻璃透镜(glass)。当然,所谓塑胶透镜也非纯粹塑料,而是树脂镜片,当然其透光率感光性之类的光学指标是比不上镀膜镜片的。通常摄像头用的镜头构造有:1P、2P、1G1P、1G2P、2G2P、2G3P、4G、5G等。透镜越多,成本越高,相对成像效果会更出色,镜头厂家主要集中在*、日本和韩国,镜头这种光学技术含量高的产业有比较高的门槛,业内比较知名的企业如富士精机、柯尼卡美能达、大立光、Enplas等。
传感器(sensor)是CCM的核心模块.摄像头的主要组件中,最重要的就是图像传感器了,因为感光器件对成像质量的重要性不言而喻。Sensor将从lens上传导过来的光线转换为电信号,再通过内部的DA转换为数字信号。由于Sensor的每个pixel只能感光R光或者B光或者G光,因此每个像素此时存贮的是单色的,我们称之为RAW DATA数据。要想将每个像素的RAW DATA数据还原成三基色,就需要ISP来处理。目前广泛使用的有两种:一种是广泛使用的CCD(电荷藕合)元件;另一种是CMOS(互补金属氧化物导体)器件。
图像处理芯片(DSP)是CCM的重要组成部分,由ISP和JPEGdecoder组成。它的作用是将感光芯片获得的数据及时快速地传递*处理器并刷新感光芯片,因此DSP芯片的好坏,直接影响画面品质(比如色彩饱和度,清晰度等)。
FPC绕性电路板
2.3.摄像头的常用技术指标
A. 图像解析度/分辨率(resolution):常见摄像头为130W(1280x1024)、500W(2592x1944)、800W(3264x2448)
B.图像格式(ImageFormat/colorspace):RGB24和YUV420是常用的两种图像格式。RGB24表示RGB三种颜色各8位,最多可表现256级浓度,从而可以再现256*256*256种颜色;420是YUV格式之一,这种格式可以避免相互干扰,还可以降低色度的采样率而不会对图像质量影响太大。此外还有类似,RGB565,YUV422等格式。
YUV知识链接:http://blog.csdn.net/searchsun/article/details/2443867
http://baike.baidu.com/view/189685.htm
C.自动白平衡调整(Auto White Balance):
定义:要求在不同色温环境下,照白色的物体,屏幕中的图像应也是白色的。色温表示光谱成份,光的颜色。色温低表示长波光成分多。当色温改变时,光源中三基色(红、绿、蓝)的比例会发生变化,需要调节三基色的比例来达到彩色的平衡,这就是白平衡调节的实际。
D.图像压缩方式:JPEG:(joint photo graphicexpert group)静态图像压缩方式。一种有损图像的压缩方式。压缩比越大,图像质量也就越差。当图像精度要求不高存储空间有限时,可以选择这种格式。目前大部分数码相机都使用JPEG格式。
E.彩色深度(色彩位数):反映对色彩的识别能力和成像的色彩表现能力,实际就是A/D转换器的量化精度,是指将信号分成多少个等级。常用色彩位数(bit)表示。彩色深度越高,获得的影像色彩就越艳丽动人。现在市场上的摄像头均已达到24位,有的甚至是32位.
F.图像噪音:指的是图像中的杂点干挠。表现为图像中有固定的彩色杂点。
G.输出/输入接口
串行接口(RS232/422):传输速率慢,为115kbit/s
并行接口(PP):速率可以达到1Mbit/s
红外接口(IrDA):速率也是115kbit/s,一般笔记本电脑有此接口
通用串行总线USB:即插即用的接口标准,支持热插拔。USB1.1速率可达12Mbit/s,USB2.0可达480Mbit/s
IEEE1394(火线)接口(亦称ilink):其传输速率可达100M~400Mbit/s
2.4、CCM内部工作原理:
A.Sensor内部工作原理:外部光线穿过lens后,经过colorfilter滤波后照射到Sensor面上, Sensor将从lens上传导过来的光线转换为电信号,再通过内部的DA转换为数字信号。如果Sensor没有集成DSP,则通过DVP的方式传输到baseband,此时的数据格式是RAW RGB。
如果集成了DSP,则RAW DATA 数据经过AWB、color matrix、lensshading、gamma、sharpness、AE和de-noise处理,后输出YUV或者RGB格式的数据.下图是ov5640的硬件框图:
B.DVP传输方式简介:
DVP分为三个部分:1)输出总线;2)输入总线;3)电源总线。如下图:
1)输入总线介绍
a、PWD为camera的使能管脚。当camera处于PWD模式时,一切对camera的操作都是无效的。因此,在RESET之前,一定要将PWD管脚置为normal模式。
b、RESET为camera的复位管脚。此方式为硬复位模式,一般管脚置为低,camera处于硬复位状态,camera的各个IO口恢复到出厂默认状态。只有在MCLK开启后,将RESET置为低,硬复位才有效,否则复位无效。
c、MCLK为camera工作时钟管脚。此管脚为BB提供camera的工作时钟。
d、I2C为camera与BB通信管脚。BB与camera的通信总线。
2)输出总线介绍
a、data为camera的数据管脚。此数据脚可以输出的格式有YUV、RGB、JPEG。
b、VSYNC为camera的帧同步信号管脚。一个VYSNC信号结束表示一帧(即一个画面)的数据已经输出完毕。
c、HSYNC为camera行同步信号管脚。一个HSYNC信号结束表示一行的数据已经输出完毕。
d、PCLK为像素同步信号管脚。一个PCLK信号结束表示一个数据已经输出完毕。
Data,VSYNC,HSYNC,PCLK时序图如下:
3)Power线介绍
a、AVDD为camera的模拟电压。
b、DOVDD为camera的GPIO口数字电压。
c、DVDD为camera的核工作电压。
一般来说,要求先提供sensor的GPIO口电压,接着提供模拟电压,最后提供工作电压。时序如下图:
2.5、摄像头外部工作原理:
采用DVP方式传输数据的camera(OV系列摄像头),主要硬件接口可以进行如下划分:
l 控制接口:PWD、MCLK、RESET、SDA/SCL;
l 供电引脚:AVDD、DVDD、DOVDD;
l 数据输出接口:DATA(8bit或者10bit)、PCLK、VSYNC、HSYNC;
使camera进入工作状态的步骤:
1. 按照手册上面的供电时序给camera的各路供电引脚上电;
2. 打开MCLK时钟;
3. 拉低PWD信号线(PWD引脚在camera工作时始终保持低电平);
4. 复位camera,使能RESET引脚,或者通过I2C总线发送RESETB给sensorIC;
PCLK是像素时钟,HREF是行参考信号,VSYNC是场同步信号。一旦给摄像头提供了时钟,并且复位摄像头,
摄像头就开始工作了,通过HREF,VSYNC和PCLK同步传输数字图像信号。 数据是通过D0~D7这八根数据线并行送出的
Camera调试主要要点:
l I2C:camera相关寄存器的数据都是通过I2C总线传输的。如果I2C不能正常工作,就初始化camera相关寄存器;
l MCLK:Camera要正常工作,必须由主控芯片(SOC芯片)给它提供时钟信号,没有时钟信号,Camera是一定不会干活的;
l 上下电时序:camera需要按照datasheet提供的上下点时序,为Camera进行上电操作;
l PCLK/DATA1-7:数据传输信号和时钟同步信号;
l 主要寄存器设置:分辨率、YUV顺序、X轴、Y轴、镜像、翻转;
3.展讯SC8810平台DCAM模块工作原理:
3.1Multi_SubSystemàDcam
4.OV5640 Camera简要描述:
二、Dcam_v4l2.c源码分析
1.展讯video_device的定义和注册:
static struct video_devicedcam_template = {
.name = "dcam",
.fops = &dcam_fops,
.ioctl_ops = &dcam_ioctl_ops,
.minor = -1,
.release = video_device_release,
.tvnorms = V4L2_STD_525_60,
.current_norm = V4L2_STD_NTSC_M,
};
Dcam_template是展讯camera的video_device设备,在dcam_probe函数中被video_register_device()所调用,用来注册一个video设备。Dcam_fops和dcam_ioctl_ops分别是对应的v4l2文件操作方法和IOCTL操作方法;
2.文件操作指针:
2.1、V4l2文件操作的定义:
static const structv4l2_file_operations dcam_fops = {
.owner = THIS_MODULE,
.open = open,
.write = video_write,
.release = close,
.ioctl = video_ioctl2, /* V4L2ioctl handler */
};
V4l2文件操作指针,这里只定义了open,video_write,close,video_ioctl2函数,其中,video_ioctl2是videodev.c中是实现的。video_ioctl2中会根据ioctl不同的cmd来调用video_device中ioctl_ops的操作方法.
2.1、open函数
static int open(struct file *file)
{
struct dcam_dev *dev =video_drvdata(file);
struct dcam_fh *fh =NULL;
int retval = 0;
if (atomic_inc_return(&dev->users) > 1) {//增加引用计数,当前只能有一个用
atomic_dec_return(&dev->users); 户进程打开video_device设备。
return -EBUSY;
}
dprintk(dev, 1,"open /dev/video%d type=%s users=%d\n", dev->vfd->num,
v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE],dev->users.counter);
/* allocate +initialize per filehandle data */
fh =kzalloc(sizeof(*fh), GFP_KERNEL); //为dcam_fh对象fh分配内存空间
if (NULL == fh) {
atomic_dec_return(&dev->users);
retval = -ENOMEM;
}
if (retval)
return retval;
file->private_data =fh; //将dcam_fh对象赋值给file文件结构的
private_data,以便在后续的ioctl等操作中调用fh
//初始化fh结构体:{
fh->dev = dev;
fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fh->fmt =&formats[0];
fh->width = 640;
fh->height = 480;
/* Resets framecounters */
dev->h = 0;
dev->m = 0;
dev->s = 0;
dev->ms = 0;
dev->mv_count = 0;
dev->jiffies =jiffies;
sprintf(dev->timestr,"%02d:%02d:%02d:%03d",
dev->h,dev->m, dev->s, dev->ms);
videobuf_queue_vmalloc_init(&fh->vb_vidq,&dcam_video_qops, //初始化
NULL, &dev->slock, fh->type, //视频缓存
V4L2_FIELD_INTERLACED, //队列
sizeof(struct dcam_buffer), fh,&dev->lock);
}
g_fh = fh;
//初始化DCAM_INFO_T结构体,该结构体保存dcam和sensor的配置信息,如预览模式,图片效果,闪光灯状态,对焦,对比度,亮度等参数。
g_dcam_info.wb_param =INVALID_VALUE;
g_dcam_info.brightness_param= INVALID_VALUE;
g_dcam_info.contrast_param= INVALID_VALUE;
g_dcam_info.saturation_param= INVALID_VALUE;
g_dcam_info.imageeffect_param= INVALID_VALUE;
g_dcam_info.hflip_param= INVALID_VALUE;
g_dcam_info.vflip_param= INVALID_VALUE;
g_dcam_info.previewmode_param= INVALID_VALUE;
g_dcam_info.ev_param =INVALID_VALUE;
g_dcam_info.focus_param= 0;
g_dcam_info.power_freq= INVALID_VALUE;
g_dcam_info.flash_mode= FLASH_CLOSE;
g_dcam_info.recording_start= 0;
g_dcam_info.sensor_work_mode= DCAM_PREVIEW_MODE;
s_auto_focus =DCAM_AF_IDLE;
//打开摄像头相关服务
if (0 != dcam_open()) {
return 1;
}
s_dcam_err_info.is_stop= DCAM_THREAD_END_FLAG;
dcam_create_thread();
dcam_init_timer(&s_dcam_err_info.dcam_timer);
DCAM_V4L2_PRINT("###DCAM:OK to open dcam.\n");
init_MUTEX(&s_dcam_err_info.dcam_start_sem);
down(&s_dcam_err_info.dcam_start_sem);
/*dcam_callback_fun_register(DCAM_CB_SENSOR_SOF,dcam_cb_ISRSensorSOF); */
dcam_callback_fun_register(DCAM_CB_CAP_SOF,dcam_cb_ISRCapSOF);
/*dcam_callback_fun_register(DCAM_CB_CAP_EOF,dcam_cb_ISRCapEOF); */
dcam_callback_fun_register(DCAM_CB_PATH1_DONE,dcam_cb_ISRPath1Done);
/*dcam_callback_fun_register(DCAM_CB_PATH2_DONE,dcam_cb_ISRPath2Done);*/
dcam_callback_fun_register(DCAM_CB_CAP_FIFO_OF,dcam_cb_ISRCapFifoOF);
dcam_callback_fun_register(DCAM_CB_SENSOR_LINE_ERR,
dcam_cb_ISRSensorLineErr);
dcam_callback_fun_register(DCAM_CB_SENSOR_FRAME_ERR,
dcam_cb_ISRSensorFrameErr);
dcam_callback_fun_register(DCAM_CB_JPEG_BUF_OF,dcam_cb_ISRJpegBufOF);
return 0;
}