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流程通常包含以下步骤:

  1. 设备树解析:读取compatible、reg、clocks、supplies、gpios等属性。
  2. 资源分配:为 struct sensor_device 分配内存,初始化互斥锁和V4L2子设备。
  3. 电源与时钟获取:通过 devm_regulator_get 获取电源,devm_clk_get 获取时钟。
  4. GPIO请求:通过 devm_gpiod_get 获取复位和掉电引脚。
  5. I2C通信验证:读取Sensor的芯片ID寄存器,确认I2C通信正常。
  6. 模式表初始化:根据设备树或默认配置填充支持的分辨率和帧率列表。
  7. V4L2子设备注册:调用 v4l2_i2c_subdev_init 和 media_entity_pads_init。
  8. 电源关闭:probe完成后立即关闭电源,等待应用层通过 s_stream 控制上电。
核心原则: Probe阶段只做资源获取和初始化验证,不进行Sensor的上电和流控。真正的电源管理由 s_power 和 s_stream 回调控制,以实现功耗优化。

3.5 Sensor驱动框架SVG架构图

下图展示了RK平台Sensor驱动的整体架构,从设备树解析到V4L2子设备注册的完整链路:

RK平台Sensor驱动框架架构图 RK平台Sensor驱动框架架构图 设备树 (DTS) of_match_table probe() 入口 资源分配 regulator_get clk_get gpiod_get I2C读ID 模式表初始化 V4L2子设备注册 s_power() s_stream() g_mbus_config() RKISP驱动调用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 两部分,减少流开启时的延迟。