本帖最后由 lin 于 2014-4-29 19:20 编辑
CSI 简介
CSI 是采集 Cmos Sensor,Video Encoder 等视频输出设备信号的接口。该接
口支持 Hsync,Vsync 同步控制方式或内嵌同步 BT656 方式。一般 camera 模组
采用 Hsync,Vsync 同步方式。
CSI 硬件工作原理
CSI timing
Vref= positive; Href= positive
在 Vsync 和 Hsync 有效的区域内,通过 pclk 对 data 的采样,将图像数据 buffer 到 dram
CSI 硬件调试注意
1. 在初始化 sensor 前,请保证 sensor 各个电源的电压正确
2. 在初始化 sensor 前,请确保 reset,standby 按照 sensor 规定的上电时序控制,否则可能带来很多难以解释的问题
3. 往 sensor 写 I2C 命令前,请保证 MCLK 已经有信号输出,一般来说 MCLK 应该在 24MHz。
4. 如果初始化时,发现 I2C 写命令 fail,则应该检查 sensor 各个电源,power on 的时序,以及 MCLK 是否有信号。也可以尝试将 I2C 降速,或每写一个 I2C 命令后,延时一定时间。
5. 一般来说,初始化后,如果 PCLK 和 VSYNC,HSYNC 有信号输出,则初始化应该成功,如果 PCLK,VSYNC 和 HSYNC 的极性配置正确,则图像接受一般都正确。
6. 若发现接收到的图像有不规则出现的绿横线,一般来说,可能是 PCLK 的驱动能力不足。可以通过 I2C 调大 sensor 输出 PCLK 的驱动能力,一般可以解决问题。
7. 若发现接收到的图像有横向的细彩线出现,可能是 camera 的 avdd 受到干扰。可尝试加小电容滤波。
8. 若两个 sensor 共用到一个 CSI 上,出现切换时黑屏,花屏,有彩线等问题,原因往往出现在切换时,没有将对应的 sensor 的 IO PAD 切换到高阻状态,此时另外一个 sensor 的IO 输出时,就会被拉住。
Linux 系统 CSI 驱动程序
CSI 驱动文件目录结构
CSI 驱动的位置在 linux-3.0/drivers/media/video/sun4i_csi/
目录结构如下
|‐‐ sun4i_csi
........
CSI 驱动层次结构
CSI 驱动基于 Linux 的 V4L2 架构设计,满足标准的 V4L2 API 调用方式。由于 CSI 硬件采集的视频缓冲数据要求物理上连续的内存,故采用 video-dma-contig 这种连续的内存申请管理方式。除 V4L2 Kernel 相关的源代码外,CSI 驱动主体包括 CSI Host 和 Sensor ModuleV4L2 Subdev。对应的源码为 sun4i_csi_reg.c, sun4i_drv_csi.c 以及 camera 模组源代码(如gc0308.c,gt2005.c 等)。其中 sun4i_csi_reg.c 是 CSI 硬件的 HAL 层, sun4i_drv_csi.c 是 CSI 驱动的主体,实现 CSI 驱动的初始化,V4L2 API 对接以及 video buffer 的管理等。Camera 模组源代码(如 gc0308.c,gt2005.c 等),实现相应 camera 的初始化,分辨率,图像格式,白平衡,特效,曝光等效果设置,以及电源管理。
V4L2 Subdev 函数集
Camera 驱动开发者重点关注的应该为 camera 模组与 CSI 主体之间的接口函数。
其分为两大类别,分别为 sensor_core_ops 和 sensor_video_ops。sensor_core_ops定义 power,standby,效果设置以及 ioctl 扩展;sensor_video_ops 定义设置图像数据格式以及帧率的接口。其具体定义如下:
static const struct v4l2_subdev_core_ops sensor_core_ops = {
.g_chip_ident = sensor_g_chip_ident,
.g_ctrl = sensor_g_ctrl,
.s_ctrl = sensor_s_ctrl,
.queryctrl = sensor_queryctrl,
.reset = sensor_reset,
.init = sensor_init,
.s_power = sensor_power,
.ioctl = sensor_ioctl,
.......
sensor_reset 函数
Prototype:static int sensor_reset(struct v4l2_subdev *sd, u32 val)
Main Function:实现三个与 reset 相关的指令
switch(val)
{
case CSI_SUBDEV_RST_OFF:
//控制摄像头 IO 或发送 I2C 命令使其 release reset
break;
case CSI_SUBDEV_RST_ON:
//控制摄像头 IO 或发送 I2C 命令使其 hold reset
break;
case CSI_SUBDEV_RST_PUL:
//控制摄像头 IO 或发送 I2C 命令使其经过 reset releaseholdrelease 的时序
break;
default:
return -EINVAL;
}
sensor_power 函数
Prototype:static int sensor_power(struct v4l2_subdev *sd, int on)
Main Function: 实现 4 个与 power/standby 相关的指令
switch(on)
{
case CSI_SUBDEV_STBY_ON:
//控制 sensor 进入 standby 的时序
break;
case CSI_SUBDEV_STBY_OFF:
//控制 sensor 退出 standby 的时序
break;
case CSI_SUBDEV_PWR_ON:
//控制 sensor 上电的时序
break;
case CSI_SUBDEV_PWR_OFF:
//控制 sensor 关电的时序
break;
default:
return -EINVAL;
}
sensor_init 函数
Prototype:static int sensor_init(struct v4l2_subdev *sd, u32 val)
Main Function:实现检测 sensor id,以及对 sensor 初始化。其中,sensor_detect 函数实现读
取 sensor 的 id 值,若与目标相同则返回 ok;sensor_default_regs 则是保存 sensor 初始化 I2C
命令的数组,不同 sensor 需要填不同的 I2C 初始化参数。
ret = sensor_detect(sd);
if (ret) {
csi_dev_err("chip found is not an target chip.\n");
return ret;
}
return sensor_write_array(sd, sensor_default_regs , ARRAY_SIZE(sensor_default_regs));
sensor_queryctrl 函数
Prototype:static int sensor_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
Main Function:返回 sensor 支持的各种效果设置,以及对应的设置最大值/最小值/步长。
需要注意的是,若实际操作中,sensor 不支持的效果特性,最好在这里注释掉,以免上层进
行 query 时,误认为 sensor 支持。一般而言,除了 GAIN 参数外,其他各个设置的最大值/
最小值/步长都不能再做修改。基本需要实现的参数设置是 VFLIP,HFLIP(这两个参数涉
及到摄像头的成像方向,对应 sys_config1 文件配置中的 csi_hflip 与 csi_vflip)
EXPOSURE(曝光目标值)
,DO_WHITE_BALANCE(各种白平衡场景)
,COLORFX(各种特效)
。
switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
return v4l2_ctrl_query_fill(qc, -4, 4, 1, 1);
case V4L2_CID_CONTRAST:
return v4l2_ctrl_query_fill(qc, -4, 4, 1, 1);
case V4L2_CID_SATURATION:
return v4l2_ctrl_query_fill(qc, -4, 4, 1, 1);
case V4L2_CID_HUE:
..........
sensor_s_ctrl 函数
Prototype:static int sensor_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Main Function:各种 sensor 效果特性的设置。基本实现 VFLIP,HFLIP,EXPOSURE,
DO_WHITE_BALANCE,AUTO_WHITE_BALANCE,COLORFX,其他可不实现。
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
return sensor_s_brightness(sd, ctrl->value);
case V4L2_CID_CONTRAST:
return sensor_s_contrast(sd, ctrl->value);
.......
case V4L2_CID_CAMERA_FLASH_MODE:
return sensor_s_flash_mode(sd,
(enum v4l2_flash_mode) ctrl->value);
}
return -EINVAL;
值得注意的是,sensor_s_ctrl 里面调用到的各个函数,针对不同的 sensor,需要不
同的实现。下面说一下各个函数需要实现的内容。
sensor_s_brightness(sd, ctrl->value)
sensor_s_contrast(sd, ctrl->value)
sensor_s_saturation(sd, ctrl->value)
sensor_s_exp(sd, ctrl->value)
//实现亮度/对比度/饱和度/曝光目标的调节(ctrl->value 最小值为-4,最大值为 4, step=1)。将
//抽象出来的-4~4 这 9 个等级的值,对应 sensor 具体的寄存器设置。
//brightness 对应实现 sensor_brightness_zero_regs[]等寄存器数组
//contrast 对应实现 sensor_contrast_zero_regs[]等寄存器数组
//saturation 对应实现 sensor_saturation_zero_regs[]等寄存器数组
//exp 对应实现 sensor_ev_zero_regs[]等寄存器数组
sensor_s_hue(sd, ctrl->value)
//调节 sensor 具体的寄存器,设置色调
sensor_s_vflip(sd, ctrl->value)
sensor_s_hflip(sd, ctrl->value)
sensor_s_autowb(sd, ctrl->value)
sensor_s_autoexp(sd,(enum v4l2_exposure_auto_type) ctrl->value)
//设置 sensor vflip(upsidedown)
,hflip(mirror)
,AWB(自动白平衡)
,AE(自动曝光)的
//enable 位
sensor_s_wb(sd,(enum v4l2_whiteblance) ctrl->value)
//设置各种白平衡场景
//对应实现
//sensor_wb_auto_regs[],sensor_wb_cloud_regs[],sensor_wb_daylight_regs[],
//sensor_wb_incandescence_regs[],sensor_wb_fluorescent_regs[],sensor_wb_tungsten_regs[]
//等寄存器数组
sensor_s_colorfx(sd,(enum v4l2_colorfx) ctrl->value);
//设置各种特效
//对应实现
// sensor_colorfx_none_regs[],sensor_colorfx_bw_regs[],sensor_colorfx_sepia_regs[],
// sensor_colorfx_negative_regs[],sensor_colorfx_emboss_regs[],sensor_colorfx_sketch_regs[]
// sensor_colorfx_sky_blue_regs[],sensor_colorfx_grass_green_regs[],
// sensor_colorfx_skin_whiten_regs[],sensor_colorfx_vivid_regs[]
//等寄存器数组
sensor_s_flash_mode(sd,(enum v4l2_flash_mode) ctrl->value)
//设置闪光灯模式
sensor_g_ctrl 函数
Prototype:static int sensor_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Main Function:获取各种 sensor 效果特性的设置。基本实现 VFLIP,HFLIP,EXPOSURE,
DO_WHITE_BALANCE,AUTO_WHITE_BALANCE,COLORFX,其他可不实现。
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
return sensor_g_brightness(sd, &ctrl->value);
.....................
case V4L2_CID_CAMERA_FLASH_MODE:
return sensor_g_flash_mode(sd, &ctrl->value);
}
return -EINVAL;
|