跳到主要内容

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

image-20250106130802769

Camera 通路框架

image-20250106132416168

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-csivin-mipi为对csi接口和mipi接口的控制文件;
  • vin-isp文件夹为isp的库操作文件;
  • vin-video文件夹内主要是video设备操作文件。
模块版本驱动文件
Linux-5.4bsp/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.4bsp/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_bpsMIPI 速率:mipi bps = hts * vts * fps * raw bit(数据位宽) / lane num(mipi lane 数)
fps_fixed当前Sensor 寄存器配置对应的帧率
bin_factorISP binning配置,默认配置为1
intg_minISP可以设置的最小曝光时间(单位:曝光行),平台以16为一行,默认配置16
intg_max最大曝光时间(默认为当前帧率的VTS,或者 VTS - offset(部分Sensor无法跑满理论VTS时需扣除一定offset,与FAE确认即可)
gain_minISP可以设置的Sensor最小增益,平台以16为一倍,默认配置16
gain_maxISP可以设置的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=2700hts 值在 gc2053 datasheet 中没有找到,可以通过 pclk = hts × vts × fps 得出当前的 hts 值填写进去,或者询问 Sensor 原厂。

gc2053_vts寄存器

.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 设备地址。

gc2053_SlaveID

需要注意的是,有些 Sensor 支持通过修改外围电路设计从而更改设备 TWI 地址,在配置 TWI 设备地址时需要查看原理图或者询问硬件设计人员,如下是 gc2053 两组 TWI 地址:

gc2053_SlaveAddress

驱动文件里面的 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[]

gc2053TWI时序图

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_powerSensor 上下电函数
sensor_reset设置 Sensor 复位
sensor_detectSensor 探测函数(测试IIC通信)
sensor_initSensor 驱动初始化入口
sensor_ioctlSensor 功能函数系统调用入口
sensor_g_mbus_configSensor 工作接口类型定义
sensor_g_ctrlSensor v4l2_ctrl 功能函数
sensor_s_ctrlSensor v4l2_ctrl 功能函数
sensor_reg_initSensor 寄存器初始化函数
sensor_s_streamSensor 开流函数
sensor_init_controlsSensor v4l2_ctrl 系统调用初始化函数
sensor_probeSensor 驱动资源初始化函数
sensor_removeSensor 驱动卸载函数
init_sensorSensor 驱动注册函数
exit_sensorSensor 驱动注销函数

Sensor 驱动接口调用流程

如下是 Sensor 驱动挂载驱动接口的调用流程:

sensor驱动挂载调用流程

​ 如下是运行 sample_virvi 驱动接口的调用流程:

运行samplevirvi调用流程