4. Sensor驱动与I2C配置
在Snapdragon Camera底层工程中,Sensor驱动是打通摄像头链路的第一道关口。它负责把一颗物理图像传感器从“上电后无响应”的状态,逐步带入“可输出稳定图像流”的工作状态。这一过程涉及I2C总线通信、寄存器序列写入、曝光增益计算以及sensor mode切换等多个环节。理解这些环节的先后依赖与参数传递关系,是后续调试曝光异常、切换分辨率失败、黑屏或花屏等问题的基础。
一、Sensor Probe流程:从设备树到驱动绑定
Sensor probe是Linux设备驱动模型中的标准入口。在Snapdragon平台,Camera Sensor通常以I2C从设备形式挂载在某个I2C控制器下,设备树(DTS)中会描述其compatible字符串、reg地址、电源引脚、时钟源、复位引脚以及MIPI CSI通道等资源。内核启动或模块加载时,I2C核心根据compatible匹配到对应的sensor驱动,随后调用驱动的probe函数。
probe函数内部通常按以下顺序执行:首先获取并初始化regulator(如vddio、vdig、vana)、gpio(reset、pwdn)和clk;然后使能电源和时钟,释放复位;接着通过I2C读取sensor的chip ID寄存器,确认通信正常且器件型号匹配;最后注册v4l2 subdev、初始化sensor mode列表、申请必要的buffer资源。如果chip ID读取失败,probe会返回错误,驱动不会绑定,上层Camera HAL也就无法枚举到该摄像头。
这里有一个容易忽略的细节:I2C读写时序必须与sensor上电时序配合。如果电源尚未稳定就发起I2C访问,chip ID可能读到0x00或0xFF。因此probe中通常会在上电后插入毫秒级延时,再执行首次I2C读操作。
二、寄存器序列:初始化与流启动
Sensor上电后,其内部寄存器处于默认状态,必须通过I2C写入一系列配置值才能输出符合MIPI CSI-2规范的图像数据。这个序列通常由厂商提供,称为“初始化寄存器表”或“setting”。在Snapdragon Camera驱动中,它一般以数组形式存放在sensor的mode结构体里,每个mode对应一组独立的寄存器序列。
一个典型的初始化序列包含以下阶段:首先是软复位(如写入0x0103=0x01),让sensor回到已知状态;然后配置PLL,确定MIPI时钟与像素时钟的分频比;接着设置MIPI输出参数,包括lane数、数据格式(RAW10/RAW12)、帧长与行长;再写入曝光和增益的初始值,避免首帧过曝或全黑;最后写入0x0100=0x01启动图像流。部分sensor还需要在启动流之前写入一组“stream on”专用寄存器,顺序错误会导致无数据输出。
在代码层面,这些序列通常通过一个辅助函数批量写入,例如:
static int sensor_write_regs(struct i2c_client *client,
struct reg_val *regs, int size)
{
int i, ret;
for (i = 0; i < size; i++) {
ret = sensor_write_reg(client, regs[i].addr, regs[i].val);
if (ret < 0) {
pr_err("write 0x%04x failed\n", regs[i].addr);
return ret;
}
}
return 0;
}
调试时,如果sensor无输出,可以先用I2C工具读取0x0100的值,确认是否已置1;再读取0x0000或0x0001等chip ID寄存器,确认通信链路正常。若chip ID正确但无图像,则重点检查PLL和MIPI时序寄存器。
三、曝光与增益控制
曝光和增益是Camera成像质量的核心参数。曝光时间决定传感器感光积分时长,通常以“行数”为单位写入寄存器;增益则分为模拟增益和数字增益,两者相乘得到总增益。在Snapdragon Camera HAL中,AE算法根据环境亮度计算出目标曝光和增益,再通过v4l2控制接口下发到sensor驱动,驱动将其转换为寄存器值写入。
以常见的RAW10 sensor为例,曝光寄存器可能为16位,分布在0x3501和0x3502两个字节中;模拟增益寄存器为0x3508和0x3509,数字增益为0x350A和0x350B。写入时需要先写高字节再写低字节,或者使用连续写模式。曝光行数的最大值受帧长限制,通常不能超过VTS(垂直总行数)减去若干行消隐。如果AE请求的曝光超过最大值,驱动需要做clamp处理,否则会出现帧率下降或图像异常。
增益的换算关系因sensor而异。例如某sensor的模拟增益寄存器值0x00对应1倍,0x20对应2倍,0x40对应4倍,呈非线性映射。驱动中通常维护一张增益表,将HAL下发的浮点增益转换为最接近的寄存器值。数字增益则用于补偿模拟增益的步进间隙,两者配合可以实现平滑的曝光过渡。
四、Sensor Mode与分辨率切换
一颗sensor通常支持多种输出模式,例如全尺寸、2x2 binning、裁切1080p等。每种模式对应不同的分辨率、帧率、MIPI数据率和寄存器序列。在Snapdragon Camera架构中,sensor驱动会为每个mode注册一个v4l2 subdev格式,HAL根据场景需求选择合适的mode。
切换mode时,不能直接改写寄存器,因为sensor可能正在输出图像流。正确的流程是:先停止流(写入0x0100=0x00),然后写入新mode的完整寄存器序列,最后重新启动流(写入0x0100=0x01)。部分sensor支持“快速切换”,即只改写分辨率相关寄存器而不完全复位,但这种情况需要厂商确认时序要求。
在实际调试中,分辨率切换失败常见原因包括:新mode的寄存器序列不完整、MIPI lane数配置与CSI接收端不匹配、帧长/行长设置超出sensor能力、以及切换时未正确停流导致I2C写入被忽略。建议在驱动中为每个mode单独维护寄存器数组,并在切换函数中加入日志,打印当前mode索引和关键寄存器值,便于定位问题。
i2cget -y <bus> <addr> <reg> 可以在adb shell中直接读取sensor寄存器,快速验证I2C通信和关键配置是否生效。读取前请确认sensor已上电且时钟正常。
总结来说,Sensor驱动与I2C配置是Camera底层工程中“从硬件到数据”的关键桥梁。probe流程确保器件被正确识别和初始化,寄存器序列决定sensor能否输出合规数据,曝光增益控制影响画面亮度与噪声,mode切换则支撑多分辨率场景。掌握这四个环节的依赖关系与调试方法,才能在遇到黑屏、花屏、曝光异常或切换失败时快速定位根因。