Camera 驱动介绍
V821 支持 MIPI CSI 输入,并行视频输入,其规格如下:
MIPI CSI 规格:
- MIPICSI Complaint with MIPI CSI-2 specification v1.1 and MIPI D-PHY specification v1.0
- Up to 1.0 Gbit/s per lane, 2M@25fps/2M@38fps, size up to 1920 x1920
- Configurable number of data lanes and sequence of data lanes for Miplinterface: 1 x 2-lane,2x1-lane
- Pixelformats:RAW8, RAW10, and RAW12; 8-bit YUV420 and YUV422; RGB888 and RGB565
并行视频输入规格:
- Supports 8/10/12-bit width
- Supports BT.601, BT.656, and Digital Camera(DC) protocol
- Dual Data Rate(DDR) sample mode with maximum pixel clock of 148.5MHz
- ITU-R BT.656 up to 4-ch720P@30fps
相关术语
摄像头相关术语:
-
MCLK:外部晶振或主控输出给Sensor的驱动时钟,典型值是24MHz、27MHz
-
SCL:串行时钟线,负责产生同步时钟脉冲
-
SDA:串行数据线,负责在设备间传输串行数据
并行视频输入相关术语:
- DVP:Digital Video Port 是并口传输,数据位宽有 8bit、10bit、12bit 等,是非差分信号,最高速率要比串行传输的MIPI接口低
- PCLK:pixel clock 像素时钟,每个时钟对应一个像素数据,一般为几十MHz
- HSYNC:horizonal synchronization,是行同步信号。就是在告诉接收端,HSYNC有效时段内接收端接收到的所有的信号输出属同一行
- VSYNC:vertical synchronization,是场同步信号。以高电平有效为例,VSYNC置高直到被拉低,这个区段所输出的所有影像数据组成一个frame
MIPI 相关术语:
-
MIPI:移动产业处理器接口联盟(Mobile Industry Processor Interface)
-
D-PHY:MIPI-CSI2 物理层,将 Sensor 端发来的模拟电信号转换为数字信号
-
CSI2:MIPI-CSI2 协议层,将数字信号按照协议内容进行解析,检错
-
Lane:连接 TX 和 RX 端的一组差分线代表一组lane,如下图所示 1lane 与 2lane 硬件连接图
-
Mbps:Mbit per second,表示 MIPI 数据传输速度的单位,比如 OV4689 的 MIPI 速率是 672Mbps,一般指的是单条 lane 上每秒钟传输的数据量是672Mbit
Camera 通路框架
VIN 驱动目录
VIN是全志基于 Linux 内核 V4L2 框架实现自己 SoC 的 Camera 驱动框架。
vin.c
是驱动的主要功能实现,包括注册/注销、参数读取、与v4l2上层接口、与各device的下层接口、中断处理、buffer申请切换等;- 使用过程中可简单的看成是vin模块+ device模块 +af driver + flash控制模块的方式;
modules/sensor
文件夹里面是各个sensor的器件层实现,一般包括上下电、初始化,各分辨率切换,yuv sensor
包括绝大部分的v4l2
定义的ioctrl
命令的实现;而raw sensor
的话大部分ioctrl命令在vin层调用isp库实现,少数如曝光/增益调节会透过vin层到实际器件层;modules/actuator
文件夹内是各种vcm的驱动;modules/flash
文件夹内是闪光灯控制接口实现;vin-csi
和vin-mipi
为对csi接口和mipi接口的控制文件;vin-isp
文件夹为isp的库操作文件;vin-video
文件夹内主要是video设备操作文件。
模块版本 | 驱动文件 |
---|---|
Linux-5.4 | bsp/drivers/vin/ |
vin/
├── Kconfig
├── Makefile
├── modules
│ ├── Sensor //sensor驱动文件目录
├── utility
├── vin.c //vin.c是驱动的主要功能实现,包括注册/注销、参数读取、与 v4l2 上层接口、与各 device 的下层接口、中断处理、buffer 申请切换等;
├── vin-cci
├── vin-csi //csi接口驱动文件
├── vin-isp
├── vin-mipi //mipi接口驱动文件
├── vin-stat
├── vin-tdm //TDM模块驱动文件
├── vin-video //video设备驱动文件
└── vin-vipp //VIPP模块驱动文件
Sensor 驱动目录
模块版本 | 驱动文件 |
---|---|
Linux-5.4 | bsp/drivers/vin/modules/sensor/ |
V系列平台 Sensor 驱动的目录概览:
sensor/
├── ar0238.c
├── ar0238_hispi.c
├── gc030a_mipi.c
├── gc0310_mipi.c
├── gc0339_mipi.c
├── gc0403_mipi.c
├── gc0406_mipi.c
....
Sensor 驱动数据结构
以 gc2053_mipi.c、gc1084_mipi.c 驱动文件为例,下面给出 Sensor 驱动关键数据结构的说明
bsp/drivers/vin/modules/sensor/gc1084_mipi.c
Sensor 寄存器配置定义
struct regval_list
结构体用于填写 Sensor 初始化配置列表下需要写入的地址和值,配置由 Sensor 厂提供,struct regval_list
结构体定义如下,每一组分辨率和帧率下对应一个 regval_list
数组,regval_list
结构体变量的命名规则一般是 sensor_xxx(分辨率帧率)_regs
。
struct regval_list {
addr_type addr;
data_type data;
};
/* 此结构体用于填写 Sensor 寄存器列表,由 Sensor原厂提供 */
static struct regval_list sensor_1080p12_regs[] = {
/* 1928*1088@12fps */
/****system****/
{0xfe, 0x80},
{0xfe, 0x80},
{0xfe, 0x80},
{0xfe, 0x00},
{0xf2, 0x00},
{0xf3, 0x00},
...
{0x02, 0x56},
{0x03, 0x8e},
{0x12, 0x80},
{0x13, 0x07},
{0x15, 0x12},
{0xfe, 0x00},
{0x17, 0x83},
};
Sensor 寄存器配置注册
/* Sensor 驱动由不同的分辨率/帧率的寄存器配置,它们填写在 sensor_win_sizes 结构体数组中 */
static struct sensor_win_size sensor_win_sizes[] = {
{
.width = 1920,
.height = 1088,
.hoffset = 4,//0,
.voffset = 4,//0,
.hts = 2200,
.vts = 2700,
.pclk = 74250000,
.mipi_bps = 297 * 1000 * 1000,
.fps_fixed = 12,//12.5
.bin_factor = 1,
.intg_min = 1 << 4,
.intg_max = (2700 - 16) << 4,
.gain_min = 1 << 4,
.gain_max = 110 << 4,
.regs = sensor_1080p12_regs,
.regs_size = ARRAY_SIZE(sensor_1080p12_regs),
.set_size = NULL,
},
...
};
成员变量 | 含义说明 |
---|---|
width | 图像输出宽度,定义 parser 接收进来的宽度 |
height | 图像输出高度,定义 parser 接收进来的高度 |
hoffset | 定义输入 ISP 的宽度偏移量,用于裁剪不需要的像素列 |
voffset | 定义输入 ISP 的宽度偏移量,用于裁剪不需要的像素行 |
hts | 行长(以pclk为单位) |
vts | 帧长(以hts为单位) |
pclk | 像素时钟:pclk = hts × vts × fps |
mipi_bps | MIPI 速率:mipi bps = hts * vts * fps * raw bit(数据位宽) / lane num(mipi lane 数) |
fps_fixed | 当前Sensor 寄存器配置对应的帧率 |
bin_factor | ISP binning配置,默认配置为1 |
intg_min | ISP可以设置的最小曝光时间(单位:曝光行),平台以16为一行,默认配置16 |
intg_max | 最大曝光时间(默认为当前帧率的VTS,或者 VTS - offset(部分Sensor无法跑满理论VTS时需扣除一定offset,与FAE确认即可) |
gain_min | ISP可以设置的Sensor最小增益,平台以16为一倍,默认配置16 |
gain_max | ISP可以设置的Sensor最大增益 |
regs | 当前帧率/分辨率对应的 Sensor 寄存器数组 |
regs_size | 前帧率/分辨率对应的 Sensor 寄存器数组的长度 |
set_size | 默认为NULL |
上述成员变量中,.hts
和 .vts
值的设置必须与当前所使用的初始化寄存器配置互相对应,一般在 Sensor 的 datasheet
中可以找到,如下,Sensor 原厂提供的配置里面也会进行标注,如果没有找到可以询问一下 Sensor 原厂。
下图是格科微 gc2053 datasheet 中找到配置 vts
寄存器值,对应格科微 gc2053 MIPI
接口 2lane 1080p
12帧 的寄存器配置中 {0x41, 0x0a},{0x42, 0x8c}
,所以对应的 vts
值为 0xa8c=2700
,hts
值在 gc2053 datasheet 中没有找到,可以通过 pclk = hts × vts × fps
得出当前的 hts 值填写进去,或者询问 Sensor 原厂。
.intg_max
是最大曝光时间,示例中 gc2053 的最大曝光限制为 vts-16
,因为主控端曝光是以 16 为一行,所以将 gc2053 最大曝光限制值左移 4 位填入 .intg_max
。每个 Sensor 的最大曝光限制都是不一样的,这个可以询问一下 Sensor 原厂或者翻阅 Sensor datasheet 进行查找。
.gain_max
是最大增益,每个 Sensor 的最大增益都是不一样的,这个可以询问一下 Sensor 原厂或者翻阅 Sensor datasheet 进行查找,本例中 Sensor 的最大增益为 110 倍,而主控端 ISP 是以 16 为一倍,所以该值需要左移 4 位后填入。
如果 Sensor 输出图像格式是 YUV 的话,则 .bin_factor/.intg_min/.intg_max/.gain_min/.gain_max
这几个成员变量无须填写。
Sensor 图像数据格式注册
/*
* Here we'll try to encapsulate the changes for just the output
* video format.
*
*/
static struct regval_list sensor_fmt_raw[] = {
// 一般为空
};
/*
* Store information about the video data format.
*/
static struct sensor_format_struct sensor_formats[] = {
/* 定义 Sensor 输出的图像数据格式,根据Sensor输出格式填写,下述为 RAW 数据格式示例 */
{
.desc = "Raw RGB Bayer",
.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
.regs = sensor_fmt_raw,
.regs_size = ARRAY_SIZE(sensor_fmt_raw),
.bpp = 1
},
};
#define N_FMTS ARRAY_SIZE(sensor_formats)
// 如果Sensor 输出图像格式是 YUV,则需要根据 Sensor 图像数据输出顺序选择 YUYV/VYUY/UYVY/YVYU 其中一种,如下:
static struct sensor_format_struct sensor_formats[] = {
{
.desc = "YUYV 4:2:2",
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.regs = sensor_fmt_raw,
.regs_size = ARRAY_SIZE(sensor_fmt_raw),
.bpp = 2,
},
};
#define N_FMTS ARRAY_SIZE(sensor_formats)
成员变量 | 含义说明 |
---|---|
desc | 描述 Sensor 输出的图像格式 |
mbus_code | 图像数据RGB分量排列顺序(常见 Bayer 格式:RGGB、BGGR、GRBG、GBRG) |
regs | 默认填写sensor_fmt_raw |
regs_size | 默认填写sensor_fmt_raw的大小 |
bpp | 默认为1 |
Sensor I2C 注册
Sensor I2C 设备地址用于告知主控端丛机所对应的设备地址,以便主控端在通过 I2C 通讯时,能够根据丛机(sensor)的设备地址对其进行读写寄存器操作,Sensor I2C 设备地址一般在 Sensor 的 datasheet 中可以找到,在 I2C 读写示例中有标明,如图所示,格科微 gc2053 datasheet 中描述了 Sensor I2C 设备地址。
需要注意的是,有些 Sensor 支持通过修改外围电路设计从而更改设备 TWI 地址,在配置 TWI 设备地址时需要查看原理图或者询问硬件设计人员,如下是 gc2053 两组 TWI 地址:
驱动文件里面的 I2C_ADDR 宏定义一般用于填写具体的I2C地址
#define I2C_ADDR 0x6e /* sensor的TWI地址,I2C_ADDR要和board.dts中的sensor0_twi_addr一致*/
Sensor I2C 数据位宽和地址位宽是在 cci_driver 结构体中定义的,数据位宽和地址位宽必须按照手册说明进行配置,否则 I2C 通讯时没有将 Sensor 寄存器值成功写入 Sensor 中,导致 Sensor 不出图。如下是 gc2053 datasheet I2C 通讯时序图。
/* 定义两组 Sensor CCi driver,CCi全称是camera control interface,由i2c和gpio组成 */
static struct cci_driver cci_drv[] = {
{
.name = SENSOR_NAME,
.addr_width = CCI_BITS_8,
.data_width = CCI_BITS_8,
}, {
.name = SENSOR_NAME_2,
.addr_width = CCI_BITS_8,
.data_width = CCI_BITS_8,
}
};
/* 用于下面Sensor_driver结构体来匹配设备树 */
static const struct i2c_device_id sensor_id[]
/* Sensor driver的定义,其中会通过id_table来匹配设备树 */
static struct i2c_driver sensor_driver[]
Sensor 电气接口注册
Sensor 数据传输接口以及 Lane 数定义在 sensor_g_mbus_config 函数中进行填写。
// 以 GC2053(MIPI 接口)2lane为例:
static int sensor_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg)
{
cfg->type = V4L2_MBUS_CSI2;
cfg->flags = 0 | V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0;
return 0;
}
// 以 GC2053(MIPI 接口)1lane为例:
static int sensor_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg)
{
cfg->type = V4L2_MBUS_CSI2;
cfg->flags = 0 | V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0;
return 0;
}
Sensor 驱动接口概览
接口定义 | 接口说明 |
---|---|
sensor_g_fps | 获取 Sensor 实时帧率 |
sensor_s_fps | 动态设置 Sensor 帧率 |
sensor_g_exp | 获取 Sensor 曝光时间(单位:曝光行) |
sensor_s_exp | 设置 Sensor 曝光时间(单位:曝光行) |
sensor_g_gain | 获取 Sensor 当前增益 |
sensor_s_gain | 设置 Sensor 增益 |
sensor_s_exp_gain | 设置 Sensor 曝光时间和增益 |
sensor_s_vflip | 动态设置 Sensor 垂直翻转 |
sensor_s_hflip | 动态设置 Sensor 水平翻转 |
sensor_g_flip | 获取 Sensor 当前翻转状态 |
sensor_get_temp | 获取 Sensor 当前温度 |
sensor_power | Sensor 上下电函数 |
sensor_reset | 设置 Sensor 复位 |
sensor_detect | Sensor 探测函数(测试IIC通信) |
sensor_init | Sensor 驱动初始化入口 |
sensor_ioctl | Sensor 功能函数系统调用入口 |
sensor_g_mbus_config | Sensor 工作接口类型定义 |
sensor_g_ctrl | Sensor v4l2_ctrl 功能函数 |
sensor_s_ctrl | Sensor v4l2_ctrl 功能函数 |
sensor_reg_init | Sensor 寄存器初始化函数 |
sensor_s_stream | Sensor 开流函数 |
sensor_init_controls | Sensor v4l2_ctrl 系统调用初始化函数 |
sensor_probe | Sensor 驱动资源初始化函数 |
sensor_remove | Sensor 驱动卸载函数 |
init_sensor | Sensor 驱动注册函数 |
exit_sensor | Sensor 驱动注销函数 |
Sensor 驱动接口调用流程
如下是 Sensor 驱动挂载驱动接口的调用流程:
如下是运行 sample_virvi
驱动接口的调用流程: