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配置,错误会导致无图或花屏 |
*-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函数执行流程
- 解析dts资源: 获取时钟、GPIO、电源、pinctrl等。
- 初始化regmap: 通过I2C或SPI与Sensor通信。
- 读取Sensor ID: 验证硬件是否正确(如读取CHIP_ID寄存器)。
- 注册V4L2 subdev: 调用
v4l2_i2c_subdev_init()或v4l2_spi_subdev_init()。 - 注册媒体实体(media entity): 设置subdev的pad数量(通常1个sink,1个source)。
- 初始化电源序列: 将dts中的supply转换为驱动内部的power_seq链表。
- 创建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以及硬件之间的数据流与控制流关系:
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切换调试的基础。