3. RK平台Sensor驱动框架
在RK平台上,Camera Sensor驱动是连接硬件与ISP图像处理管线的桥梁。RK官方提供了一套标准化的驱动模板,开发者只需填充传感器特定的寄存器配置、电源时序和设备树信息,即可快速完成驱动适配。本章将深入剖析RK Sensor驱动的核心框架,包括模板结构、设备树配置、电源/时钟/复位管理以及完整的probe流程。
3.1 RK Sensor驱动模板结构
RK官方在Linux内核的 drivers/media/i2c/ 目录下提供了多个Sensor驱动模板,例如 ov5695.c、imx258.c 等。这些模板遵循统一的V4L2子设备架构,主要包含以下核心模块:
| 模块 | 文件/函数 | 职责 |
|---|---|---|
| 设备结构体 | struct sensor_device |
封装I2C客户端、电源控制、时钟、复位、模式列表、V4L2子设备等 |
| 模式表 | struct sensor_mode |
定义分辨率、帧率、曝光行、增益、MIPI数据速率等参数 |
| 寄存器操作 | sensor_write/read_array |
通过I2C批量写入/读取传感器寄存器序列 |
| 电源管理 | sensor_power_on/off |
控制AVDD/DOVDD/DVDD、MCLK、RST、PWDN的时序 |
| V4L2回调 | sensor_s_power/s_stream/g_mbus_config |
实现V4L2子设备标准接口,供ISP驱动调用 |
| 匹配表 | of_match_table |
设备树兼容字符串与驱动ID的映射 |
关键点: 模板中的
sensor_power_on 和 sensor_power_off 是开发者最需要关注的部分,电源时序错误会导致Sensor无法初始化或图像异常。
3.2 设备树(DTS)配置
设备树是RK平台描述硬件资源的核心方式。一个典型的Sensor节点配置如下:
&i2c4 {
status = "okay";
clock-frequency = <400000>;
ov5695: ov5695@36 {
compatible = "ovti,ov5695";
reg = <0x36>;
status = "okay";
clocks = <&cru CLK_MIPI_CAMARAOUT_M4>;
clock-names = "xvclk";
clock-frequency = <24000000>;
pinctrl-names = "default";
pinctrl-0 = <&cam_clk_m4 &cam_rst_m4 &cam_pwdn_m4>;
avdd-supply = <&vcc_camera_avdd>;
dovdd-supply = <&vcc_camera_dovdd>;
dvdd-supply = <&vcc_camera_dvdd>;
reset-gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_LOW>;
pwdn-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "YT-OV5695";
rockchip,camera-module-lens-name = "Largan-50013A1";
port {
ov5695_out: endpoint {
remote-endpoint = <&mipi_in_ucam0>;
data-lanes = <1 2>;
};
};
};
};
设备树属性说明:
- compatible:驱动匹配的关键字符串,必须与驱动中
of_match_table一致。 - clocks / clock-names:指定Sensor的主时钟(MCLK)源,通常为24MHz。
- avdd/dovdd/dvdd-supply:模拟、数字IO、核心电压的电源域。
- reset-gpios / pwdn-gpios:复位和掉电引脚,需与原理图一致。
- data-lanes:MIPI CSI-2数据通道映射,决定物理连接顺序。
实战建议: 在调试新Sensor时,先通过
i2cdetect 确认I2C地址是否正确,再检查电源和时钟是否稳定。设备树中的 clock-frequency 必须与Sensor datasheet一致,否则MIPI时钟失锁。
3.3 电源、时钟与复位管理
电源、时钟和复位是Sensor正常工作的三大基础。RK平台通过 regulator 框架管理电源,通过 clk 框架管理时钟,通过 gpio 控制复位和掉电引脚。典型的电源上电时序如下:
static int sensor_power_on(struct device *dev) {
struct sensor_device *sensor = to_sensor_device(dev);
// 1. 使能电源域
regulator_enable(sensor->avdd);
regulator_enable(sensor->dovdd);
regulator_enable(sensor->dvdd);
usleep_range(1000, 2000); // 等待电源稳定
// 2. 提供MCLK时钟
clk_prepare_enable(sensor->xvclk);
usleep_range(1000, 1000);
// 3. 释放复位(低有效)
gpiod_set_value_cansleep(sensor->reset_gpio, 1);
usleep_range(5000, 5000);
// 4. 解除掉电模式
gpiod_set_value_cansleep(sensor->pwdn_gpio, 0);
usleep_range(10000, 10000);
// 5. 初始化寄存器序列
sensor_write_array(sensor, sensor_init_regs, ARRAY_SIZE(sensor_init_regs));
return 0;
}
电源管理的关键时序参数:
| 步骤 | 操作 | 最小延时 | 说明 |
|---|---|---|---|
| 1 | AVDD/DOVDD/DVDD上电 | 1ms | 确保所有电源域稳定 |
| 2 | MCLK时钟使能 | 1ms | 时钟稳定后Sensor才能响应I2C |
| 3 | 复位释放(RST高) | 5ms | 复位脉冲宽度需满足datasheet |
| 4 | 掉电释放(PWDN低) | 10ms | 进入正常工作模式 |
| 5 | 初始化寄存器写入 | — | 配置分辨率、增益、曝光等 |
常见陷阱: 部分Sensor要求先上电再提供时钟,或先释放复位再解除掉电。务必严格遵循datasheet中的时序图,否则Sensor可能无法输出图像或产生花屏。
3.4 驱动Probe流程
Probe函数是驱动初始化的入口,RK Sensor驱动的probe流程通常包含以下步骤:
- 设备树解析:读取compatible、reg、clocks、supplies、gpios等属性。
- 资源分配:为
struct sensor_device分配内存,初始化互斥锁和V4L2子设备。 - 电源与时钟获取:通过
devm_regulator_get获取电源,devm_clk_get获取时钟。 - GPIO请求:通过
devm_gpiod_get获取复位和掉电引脚。 - I2C通信验证:读取Sensor的芯片ID寄存器,确认I2C通信正常。
- 模式表初始化:根据设备树或默认配置填充支持的分辨率和帧率列表。
- V4L2子设备注册:调用
v4l2_i2c_subdev_init和media_entity_pads_init。 - 电源关闭:probe完成后立即关闭电源,等待应用层通过
s_stream控制上电。
核心原则: Probe阶段只做资源获取和初始化验证,不进行Sensor的上电和流控。真正的电源管理由
s_power 和 s_stream 回调控制,以实现功耗优化。
3.5 Sensor驱动框架SVG架构图
下图展示了RK平台Sensor驱动的整体架构,从设备树解析到V4L2子设备注册的完整链路:
3.6 实战要点总结
- 模板复用:优先选择与目标Sensor分辨率、接口类型(RAW/YUV)最接近的官方模板进行修改,减少寄存器配置工作量。
- 设备树验证:使用
dtc -I dtb -O dts反编译设备树,确认节点属性正确加载。 - 电源时序调试:在
sensor_power_on中加入dev_dbg打印,配合示波器测量各电源和GPIO的时序。 - Probe失败排查:常见原因包括I2C地址错误、芯片ID读取失败、电源未稳定、时钟频率不匹配。建议在probe中增加
dev_err输出具体错误码。 - 性能优化:将初始化寄存器序列拆分为
init和stream_on两部分,减少流开启时的延迟。