4. Sensor驱动核心数据结构
在RK平台Camera Sensor驱动开发中,核心数据结构是连接硬件寄存器、驱动逻辑与ISP图像调优的桥梁。本章深入剖析四个关键数据结构:struct v4l2_subdev、struct rkmodule_inf、struct rk_sensor_reg 和 struct rk_sensor_mode,理解它们的设计意图与协作关系是驱动开发与ISP联调的基础。
学习提示: 这四个结构体分别对应V4L2框架标准层、RK平台私有扩展层、寄存器操作层和模式配置层。建议结合源码逐字段理解,并在实际驱动中追踪它们的初始化与调用链路。
4.1 struct v4l2_subdev:V4L2子设备抽象
struct v4l2_subdev 是V4L2框架中所有子设备(包括Sensor、Flash、AF等)的通用抽象。Sensor驱动通过注册该结构体,将硬件控制接口暴露给上层ISP和应用程序。
| 字段 | 类型 | 说明 |
|---|---|---|
name |
char[32] | 设备名称,如 "imx415 0-001a" |
grp_id |
u32 | 组ID,用于多Sensor绑定 |
entity |
struct media_entity | 媒体实体,用于管道管理 |
ops |
struct v4l2_subdev_ops * | 核心操作函数集(core/video/pad等) |
ctrl_handler |
struct v4l2_ctrl_handler * | 控制句柄,管理曝光/增益/白平衡等 |
host_priv |
void * | 私有数据指针,指向Sensor驱动自定义结构 |
dev |
struct device * | 内核设备指针 |
在Sensor驱动中,host_priv 字段通常指向包含 struct rkmodule_inf 和 struct rk_sensor_mode 的私有结构体,实现标准框架与平台扩展的桥接。
// 典型注册流程
static struct v4l2_subdev sensor_subdev;
// 初始化子设备
v4l2_subdev_init(&sensor_subdev, &sensor_subdev_ops);
sensor_subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sensor_subdev.ctrl_handler = &sensor_ctrl_handler;
sensor_subdev.host_priv = sensor_priv; // 指向私有数据
// 注册到V4L2框架
media_entity_pads_init(&sensor_subdev.entity, 1, &sensor_pad);
v4l2_async_register_subdev(&sensor_subdev);
关键点:
v4l2_subdev 的 ops 中必须实现 core.s_power、video.s_stream、pad.set_fmt 等回调,这些是ISP调优时控制Sensor工作的入口。
4.2 struct rkmodule_inf:RK平台模块信息扩展
struct rkmodule_inf 是RK平台在V4L2标准之上定义的私有扩展结构,用于传递Sensor模块的硬件特性、调优参数和平台特定配置。它通常嵌入在Sensor驱动的私有数据中,通过 host_priv 访问。
struct rkmodule_inf {
struct module_otp_info otp_info; // OTP校准信息
struct module_cis_info cis_info; // CIS模组信息
struct module_gpio_info gpio_info; // GPIO控制信息
struct module_awb_info awb_info; // AWB增益校准
struct module_lsc_info lsc_info; // 镜头阴影校正
struct module_af_info af_info; // 自动对焦信息
struct module_pdaf_info pdaf_info; // 相位对焦信息
u32 module_index; // 模组索引
u32 sensor_index; // Sensor索引
u32 flip; // 镜像翻转标志
};
| 子结构 | 主要字段 | 调优用途 |
|---|---|---|
module_otp_info |
otp_valid, golden_value, module_id | 读取OTP校准数据,修正增益偏差 |
module_cis_info |
sensor_name, i2c_addr, mclk | 标识Sensor型号与时钟配置 |
module_gpio_info |
pwdn_gpio, reset_gpio, power_gpio | 电源与复位时序控制 |
module_awb_info |
r_gain, gr_gain, gb_gain, b_gain | 白平衡增益校准值 |
module_lsc_info |
lsc_table, lsc_size | 镜头阴影校正表 |
注意事项:
rkmodule_inf 中的数据通常来自模组OTP或设备树配置。在驱动初始化阶段必须正确解析并填充,否则ISP调优时无法获取准确的校准参数,导致图像偏色或亮度不均。
4.3 struct rk_sensor_reg:寄存器操作原子单元
struct rk_sensor_reg 是Sensor驱动中最基础的寄存器操作结构,用于描述一条I2C写操作。它被广泛应用于初始化序列、模式切换、增益/曝光设置等场景。
struct rk_sensor_reg {
u16 reg_addr; // 寄存器地址(16位)
u16 reg_val; // 寄存器值(16位)
u8 reg_len; // 地址长度:1字节或2字节
u8 val_len; // 值长度:1字节或2字节
u8 delay; // 写完后延时(ms)
};
| 字段 | 取值范围 | 说明 |
|---|---|---|
reg_addr |
0x0000 ~ 0xFFFF | Sensor内部寄存器地址 |
reg_val |
0x00 ~ 0xFFFF | 要写入的值 |
reg_len |
1 或 2 | 地址字节数,常见8位Sensor用1,16位用2 |
val_len |
1 或 2 | 值字节数,8位寄存器用1,16位用2 |
delay |
0 ~ 100 | 写入后等待时间,用于时序敏感寄存器 |
驱动中通常以数组形式定义初始化序列,并通过工具函数批量写入:
// 初始化序列示例(IMX415部分寄存器)
static const struct rk_sensor_reg imx415_init_regs[] = {
{0x3000, 0x00, 2, 1, 0}, // 软件复位
{0x3002, 0x00, 2, 1, 10}, // 复位后等待10ms
{0x3010, 0x01, 2, 1, 0}, // 设置输出模式
{0x3020, 0x33, 2, 1, 0}, // PLL配置
{0x3030, 0x10, 2, 1, 0}, // 帧长设置高位
{0x3031, 0xE0, 2, 1, 0}, // 帧长设置低位
{0x3040, 0x05, 2, 1, 0}, // 曝光设置
{RK_SENSOR_REG_END, 0x00, 0, 0, 0} // 结束标记
};
// 批量写入函数
int rk_sensor_write_regs(struct i2c_client *client,
const struct rk_sensor_reg *regs) {
int ret = 0;
while (regs->reg_addr != RK_SENSOR_REG_END) {
ret = rk_sensor_write_reg(client, regs->reg_addr,
regs->reg_val, regs->reg_len,
regs->val_len);
if (ret)
break;
if (regs->delay)
msleep(regs->delay);
regs++;
}
return ret;
}
实践要点: 在ISP调优过程中,曝光和增益的实时调整就是通过构造
struct rk_sensor_reg 数组并调用写入函数实现的。注意 delay 字段在切换帧率或模式时至关重要,过短的延时可能导致寄存器写入失败。
4.4 struct rk_sensor_mode:Sensor工作模式描述
struct rk_sensor_mode 定义了Sensor的完整工作模式,包括分辨率、帧率、输出格式、时钟配置等。每个模式对应一组寄存器序列,驱动根据应用需求切换不同模式。
struct rk_sensor_mode {
u32 width; // 图像宽度(像素)
u32 height; // 图像高度(像素)
u32 max_fps; // 最大帧率(fps * 1000)
u32 hts_def; // 默认水平总像素
u32 vts_def; // 默认垂直总像素
u32 mipi_freq; // MIPI时钟频率(MHz)
u32 bpp; // 位深(10/12/14)
u32 bus_type; // 总线类型:MIPI/DVP
u32 lane_num; // MIPI通道数
const struct rk_sensor_reg *regs; // 模式对应的寄存器序列
const char *desc; // 模式描述
};
| 字段 | 示例值 | 调优关联 |
|---|---|---|
width / height |
3840 x 2160 | 决定ISP输入尺寸和裁剪窗口 |
max_fps |
30000(30fps) | 影响曝光时间和帧间隔 |
hts_def / vts_def |
4400 / 2250 | 计算实际帧率和曝光行数 |
mipi_freq |
800 | MIPI PHY配置,影响带宽 |
bpp |
10 | RAW数据位深,ISP处理精度 |
regs |
寄存器数组指针 | 模式切换时写入的寄存器序列 |
// 模式定义示例
static const struct rk_sensor_mode imx415_modes[] = {
{
.width = 3840,
.height = 2160,
.max_fps = 30000,
.hts_def = 4400,
.vts_def = 2250,
.mipi_freq = 800,
.bpp = 10,
.bus_type = RK_SENSOR_BUS_MIPI,
.lane_num = 4,
.regs = imx415_4k_regs,
.desc = "3840x2160 30fps 10bit",
},
{
.width = 1920,
.height = 1080,
.max_fps = 60000,
.hts_def = 2200,
.vts_def = 1125,
.mipi_freq = 800,
.bpp = 10,
.bus_type = RK_SENSOR_BUS_MIPI,
.lane_num = 4,
.regs = imx415_1080p_regs,
.desc = "1920x1080 60fps 10bit",
},
};
调优技巧: 在ISP调优时,
hts_def 和 vts_def 直接影响曝光行数的计算。如果发现实际帧率与预期不符,应优先检查这两个值是否与Sensor datasheet一致。另外,bpp 必须与ISP的RAW格式配置匹配,否则会出现数据错位。
4.5 四个数据结构的协作关系
在RK平台Sensor驱动中,这四个结构体形成清晰的层次化协作关系:
- 框架层:
struct v4l2_subdev作为V4L2标准接口,负责与上层ISP和应用程序通信。 - 扩展层:
struct rkmodule_inf通过host_priv挂载到v4l2_subdev,提供RK平台特有的模组信息。 - 配置层:
struct rk_sensor_mode定义Sensor的工作模式,包含分辨率、帧率等参数。 - 操作层:
struct rk_sensor_reg是寄存器操作的最小单元,被模式切换和实时控制调用。
总结: 掌握这四个数据结构,就掌握了RK平台Sensor驱动的骨架。
v4l2_subdev 是门面,rkmodule_inf 是身份证,rk_sensor_mode 是工作证,rk_sensor_reg 是执行者。在后续的ISP调优实战中,我们将反复操作这些结构体,实现从驱动到图像的完整链路。