3. RK平台Sensor驱动框架:模板、设备树与注册流程
在瑞芯微RK平台上开发Camera Sensor驱动,核心是理解官方提供的驱动模板、设备树(Device Tree)配置以及Platform Driver的注册机制。本章将拆解这三部分,帮助开发者快速搭建标准化的Sensor驱动框架。
3.1 RK提供的Sensor驱动模板结构
RK平台为Sensor驱动提供了标准模板,通常位于内核源码 drivers/media/i2c/ 目录下,文件名如 ov5645.c 或 imx258.c。模板采用分层设计,主要包含以下核心模块:
| 模块/文件 | 功能描述 | 关键函数/结构体 |
|---|---|---|
| 驱动入口 | 定义platform_driver结构体,完成注册与注销 | module_platform_driver() |
| 设备树匹配 | 通过of_match_table匹配dts节点 | of_match_table, sensor_of_match[] |
| 上电序列 | 控制Sensor的电源、时钟、复位时序 | sensor_power_on(), sensor_power_off() |
| 初始化序列 | 通过I2C写入寄存器数组,配置Sensor工作模式 | sensor_init(), regval_table[] |
| V4L2子设备 | 实现v4l2_subdev_ops,提供视频操作接口 | sensor_subdev_ops, sensor_video_ops |
| 媒体控制器 | 定义实体、pad、链接,用于pipeline管理 | media_entity, media_pad |
模板核心思想: 驱动开发者只需填充寄存器表、电源控制函数和V4L2回调,即可完成一个标准Sensor驱动的移植,无需重复编写框架代码。
3.2 设备树(dts)配置详解
设备树是RK平台硬件描述的核心,Sensor节点通常挂载在I2C总线下。以下是一个典型的Sensor dts配置示例:
// rk3588-evb.dts 或 board.dtsi
&i2c4 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c4m2_xfer>;
ov5645: ov5645@3c {
compatible = "ovti,ov5645";
reg = <0x3c>;
clocks = <&cru CLK_MIPI_CAMARAOUT_M4>;
clock-names = "xvclk";
power-domains = <&power RK3588_PD_VI>;
// 电源控制
avdd-supply = <&vcc_1v8>;
dvdd-supply = <&vcc_1v2>;
dovdd-supply = <&vcc_1v8>;
// 复位与电源引脚
reset-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_LOW>;
pwdn-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
// 旋转与镜像
rotation = <90>;
orientation = <0>;
// 物理信息
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
rockchip,camera-module-name = "YT-OV5645";
rockchip,camera-module-lens-name = "Largan-50013A1";
port {
ov5645_out: endpoint {
remote-endpoint = <&mipi_in_ucam0>;
data-lanes = <1 2>;
};
};
};
};
配置要点:
data-lanes 必须与Sensor输出能力匹配(如1-lane、2-lane或4-lane);rotation 和 orientation 影响ISP的预处理方向,错误配置会导致图像颠倒。
dts中关键属性的作用对照表:
| 属性 | 类型 | 说明 |
|---|---|---|
compatible |
字符串 | 驱动匹配的关键字,必须与驱动中 of_match_table 一致 |
reg |
u32 | Sensor的I2C从设备地址(7位) |
clocks |
phandle | Sensor主时钟(xvclk)的时钟源 |
avdd/dvdd/dovdd-supply |
phandle | 模拟/数字/IO电源的regulator句柄 |
reset-gpios |
gpio | 复位引脚,低电平有效 |
pwdn-gpios |
gpio | 掉电引脚,高电平进入掉电模式 |
data-lanes |
数组 | MIPI CSI使用的数据通道编号 |
3.3 Platform Driver注册流程
RK平台的Sensor驱动基于 platform_driver 框架,注册流程分为以下步骤:
- 定义platform_driver结构体:填充
.probe、.remove、.driver.of_match_table等成员。 - 调用module_platform_driver宏:在模块初始化/退出时自动完成注册与注销。
- probe函数执行:解析dts、获取资源、初始化I2C、注册V4L2子设备。
- 注册v4l2_subdev:将Sensor设备注册到V4L2框架,供ISP或应用层调用。
- 注册media_entity:建立媒体拓扑,定义输入输出pad。
以下是一个简化的probe函数流程代码:
static int sensor_probe(struct platform_device *pdev)
{
struct sensor_dev *sensor;
struct i2c_client *client;
int ret;
// 1. 分配私有数据结构
sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
if (!sensor)
return -ENOMEM;
// 2. 获取I2C client(从dts解析)
client = to_i2c_client(pdev->dev.parent);
sensor->client = client;
// 3. 解析dts属性(电源、时钟、GPIO等)
ret = sensor_parse_dt(sensor);
if (ret)
return ret;
// 4. 上电并初始化Sensor
ret = sensor_power_on(sensor);
if (ret)
return ret;
ret = sensor_init(sensor);
if (ret)
goto power_off;
// 5. 注册V4L2子设备
v4l2_i2c_subdev_init(&sensor->sd, client, &sensor_subdev_ops);
sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
// 6. 注册媒体实体
sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
if (ret)
goto power_off;
dev_info(&pdev->dev, "Sensor probe success\n");
return 0;
power_off:
sensor_power_off(sensor);
return ret;
}
常见错误: 在probe中未正确释放电源或时钟资源,会导致系统挂起或Sensor无法再次上电。务必在错误路径中调用
sensor_power_off()。
3.4 驱动框架整体架构图
下图展示了从设备树到V4L2子设备的完整驱动框架流程:
3.5 关键数据结构与回调
驱动模板中必须实现的核心数据结构包括:
- struct v4l2_subdev_ops:包含
.core、.video、.pad等操作集。 - struct v4l2_subdev_video_ops:实现
s_stream()(启动/停止流)、g_frame_interval()等。 - struct v4l2_subdev_pad_ops:实现
set_fmt()、get_fmt()、enum_mbus_code()等。 - struct media_entity_operations:定义
link_validate()回调,用于pipeline链路验证。
性能调优提示: 在
s_stream(1) 中尽量减少I2C写入次数,可将多个寄存器配置合并为批量写入(如使用 regmap_multi_reg_write()),显著缩短启动延迟。
通过以上模板、dts配置和注册流程,开发者可以快速在RK平台上适配新的Camera Sensor,并为后续的ISP调优和性能优化打下坚实基础。