3. RK平台Sensor驱动框架:模板、设备树与platform_driver

本章深入RK平台Camera子系统的核心——Sensor驱动框架。RK官方为开发者提供了标准化的驱动模板,配合设备树(Device Tree)的硬件描述与platform_driver的Linux驱动模型,实现了Sensor驱动的快速移植与多Camera场景的无缝切换。理解这三者的协作关系,是掌握RK Camera开发的基础。

3.1 RK Sensor驱动模板结构

RK提供的Sensor驱动模板通常位于kernel/drivers/media/i2c/目录下,文件名以rk_sensor_或具体Sensor型号命名(如rk_sensor_imx415.c)。该模板封装了V4L2子设备(subdev)的注册、电源控制、流媒体操作等通用逻辑,开发者只需填充与具体Sensor相关的参数即可。

模板核心文件组成:
  • 驱动主文件(.c): 实现platform_driver的probe/remove、V4L2 subdev ops、电源序列。
  • 头文件(.h): 定义寄存器地址、模式表、数据结构。
  • 设备树绑定文档: 描述dts中需要配置的属性。

3.1.1 模板关键数据结构

数据结构 作用 关键成员
struct rk_sensor Sensor私有数据,贯穿驱动生命周期 regmap、pinctrl、power_seq、mode_list
struct rk_sensor_mode 定义一种分辨率和帧率组合 width、height、fps、reg_list
struct rk_sensor_power_seq 电源上电/下电时序步骤 gpio、delay_ms、value
struct v4l2_subdev_ops V4L2子设备操作函数集 core、video、pad
开发提示: 模板中的rk_sensor_mode数组是驱动适配的关键。每个模式对应一组寄存器配置,驱动在s_stream(1)时根据用户选择的模式加载对应寄存器列表。务必确保模式表中的reg_list完整且与Sensor数据手册一致。

3.2 设备树(dts)配置详解

在RK平台中,Sensor的设备树节点通常挂载在I2C总线或CSI(Camera Serial Interface)端口下。dts配置决定了驱动如何获取硬件资源(电源、时钟、复位GPIO、MCLK等)。

3.2.1 典型Sensor dts节点示例

// 以RK3588 + IMX415为例
&i2c4 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = &i2c4m2_xfer;

    imx415: imx415@1a {
        compatible = "sony,imx415";
        reg = <0x1a>;
        clocks = <&cru CLK_MIPI_CAMARAOUT_M4>;
        clock-names = "xvclk";
        pinctrl-names = "default";
        pinctrl-0 = &cam_clk_out0;
        power-domains = <&power RK3588_PD_VI>;

        // 电源序列
        avdd-supply = &vcc_cam_avdd;      // 模拟电压 2.8V
        dovdd-supply = &vcc_cam_dovdd;    // 数字IO电压 1.8V
        dvdd-supply = &vcc_cam_dvdd;      // 数字核心电压 1.2V

        // GPIO控制
        reset-gpios = &gpio1 RK_PB0 GPIO_ACTIVE_LOW;
        pwdn-gpios = &gpio1 RK_PB1 GPIO_ACTIVE_HIGH;

        // 物理连接信息
        rockchip,camera-module-index = <0>;
        rockchip,camera-module-facing = "back";
        rockchip,camera-module-name = "CMK-OT2022-P1";
        rockchip,camera-module-lens-name = "M12-40IRC-4MP-F20";

        port {
            imx415_out: endpoint {
                remote-endpoint = &mipi_in_ucam0;
                data-lanes = <1 2 3 4>;
                link-frequencies = /bits/ 64 <480000000>;
            };
        };
    };
};

3.2.2 dts关键属性说明

属性 说明 注意事项
compatible 驱动匹配字符串,必须与驱动中of_match_table一致 大小写敏感,通常为"厂商,型号"
clocks / clock-names Sensor主时钟(MCLK)源,通常为24MHz或27MHz 频率需与Sensor datasheet匹配,否则无法初始化
reset-gpios / pwdn-gpios 硬件复位和掉电控制引脚 注意GPIO的active电平,ACTIVE_LOW或ACTIVE_HIGH
data-lanes MIPI CSI数据通道映射,如<1 2 3 4>表示使用4 lane 必须与硬件连线一致,lane顺序可重映射
link-frequencies MIPI链路传输频率,单位Hz 影响PHY配置,错误会导致无图或花屏
常见错误: 电源时序错误是Sensor驱动不工作的首要原因。dts中定义的*-supply顺序不代表上电顺序,实际时序由驱动中的power_seq结构控制。务必在驱动中显式定义先上AVDD、再上DOVDD、最后上DVDD,并插入足够延时(通常5-10ms)。

3.3 platform_driver结构解析

RK Sensor驱动基于Linux platform_driver框架,通过of_match_table与dts节点匹配。驱动入口、出口以及核心操作函数集构成了驱动的主体骨架。

3.3.1 驱动注册与匹配流程

// 驱动入口
static const struct of_device_id rk_sensor_of_match[] = {
    { .compatible = "sony,imx415", .data = &imx415_data },
    { .compatible = "ovti,ov5648", .data = &ov5648_data },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rk_sensor_of_match);

static struct platform_driver rk_sensor_driver = {
    .probe  = rk_sensor_probe,
    .remove = rk_sensor_remove,
    .driver = {
        .name = "rk_sensor",
        .of_match_table = rk_sensor_of_match,
        .pm = &rk_sensor_pm_ops,
    },
};

module_platform_driver(rk_sensor_driver);

3.3.2 probe函数执行流程

  1. 解析dts资源: 获取时钟、GPIO、电源、pinctrl等。
  2. 初始化regmap: 通过I2C或SPI与Sensor通信。
  3. 读取Sensor ID: 验证硬件是否正确(如读取CHIP_ID寄存器)。
  4. 注册V4L2 subdev: 调用v4l2_i2c_subdev_init()或v4l2_spi_subdev_init()。
  5. 注册媒体实体(media entity): 设置subdev的pad数量(通常1个sink,1个source)。
  6. 初始化电源序列: 将dts中的supply转换为驱动内部的power_seq链表。
  7. 创建sysfs属性: 用于调试和动态控制。

3.3.3 subdev核心ops

ops函数 触发时机 典型实现
s_power(on) 打开/关闭设备节点时 执行power_seq上电/下电,配置pinctrl
s_stream(on) 开始/停止视频流时 写入模式寄存器,使能MIPI TX
enum_mbus_code 查询支持的图像格式 返回MEDIA_BUS_FMT_SGRBG10_1X10等
s_fmt / g_fmt 设置/获取当前格式 更新rk_sensor_mode指针
s_frame_interval 设置帧率 修改PLL寄存器分频系数

3.4 框架协作关系图

下图展示了dts、platform_driver、V4L2 subdev以及硬件之间的数据流与控制流关系:

RK Sensor驱动框架协作关系 RK Sensor驱动框架协作关系图 设备树 (dts) compatible / GPIO / 时钟 / 电源 platform_driver probe / remove / of_match V4L2 Subdev s_power / s_stream / s_fmt 匹配 注册 硬件资源 I2C / GPIO / MCLK / MIPI Sensor芯片 IMX415 / OV5648 / GC系列 图像数据流 MIPI CSI -> ISP -> V4L2 解析 控制 产生 关键协作流程: 1. 内核启动时,platform_driver通过dts中的compatible匹配到Sensor节点。 2. probe函数解析dts资源,初始化I2C/GPIO,注册V4L2 subdev到媒体框架。 3. 用户空间打开设备时,subdev ops控制Sensor上电、配置模式、启动MIPI流。

3.5 多Camera切换的驱动层支持

RK平台通过媒体控制器(Media Controller)框架实现多Camera的动态切换。每个Sensor subdev注册为独立的实体,用户空间通过media-ctl工具或V4L2 ioctl动态连接/断开数据链路。

3.5.1 多Camera切换的dts配置要点

  • 独立I2C地址: 每个Sensor必须有唯一的I2C地址,或通过片选信号分时访问。
  • 独立的GPIO控制: 每个Sensor的reset/pwdn引脚必须独立,不能共享。
  • MIPI通道隔离: 使用不同的MIPI CSI D-PHY通道(如csi0和csi1),或通过虚拟通道(Virtual Channel)复用同一物理通道。
  • 电源域管理: 未使用的Sensor应处于下电状态,通过s_power(0)关闭电源以降低功耗。

3.5.2 切换流程示例

// 用户空间切换Camera的典型命令序列
# 1. 断开当前Sensor链路
media-ctl -d /dev/media0 -l '"imx415 4-001a":0->"rockchip-csi2-dphy0":0[0]'

# 2. 连接目标Sensor链路
media-ctl -d /dev/media0 -l '"ov5648 4-0036":0->"rockchip-csi2-dphy0":0[1]'

# 3. 设置目标Sensor格式
media-ctl -d /dev/media0 -V '"ov5648 4-0036":0 [fmt:UYVY8_2X8/1920x1080]'

# 4. 启动视频流
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=UYVY
v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=100
驱动层注意事项:
  • 切换前必须确保当前Sensor已通过s_stream(0)停止流。
  • MIPI D-PHY的PLL重新锁定需要时间(通常5-10ms),驱动中应加入等待机制。
  • 如果两个Sensor使用不同的MCLK频率,切换时需要动态配置CRU时钟。

3.6 本章小结

RK Sensor驱动框架通过设备树解耦硬件描述、platform_driver提供标准驱动模型、V4L2 subdev封装Sensor操作,三者协同实现了高效、可复用的Sensor驱动开发。掌握dts中电源/时钟/GPIO的配置、probe函数的资源获取流程、以及subdev ops的实现要点,是后续进行多Camera切换调试的基础。