为什么一个 Camera Sensor 有这么多 Register
# 为什么一个 Camera Sensor 有这么多 Register
第一次看 camera sensor datasheet,很容易产生一种朴素的困惑:
一个传感器,不就是把光变成图像吗?为什么要几百个、上千个 register?
更离谱的是,很多 datasheet 还不愿意把话说透。你看到一堆地址:
有些名字看起来还能猜,比如 exposure、gain、frame length。还有一些直接写 reserved,或者 vendor recommended。工程师看久了会有一种错觉:这个 sensor 不是用来拍照的,是用来测试人的耐心的。
但 register 多这件事,其实不是厂商单纯想折磨驱动工程师。虽然有时候确实很像。
真正原因是:camera sensor 不是一个简单的光电转换器,它是一条高度可配置的图像采集流水线。
# Sensor 不是只有像素阵列
一个 camera sensor 里面当然有 pixel array。光照到像素上,产生电荷,再转换成数字信号。这是最核心的部分。
但真正要把一张图稳定地送到 SoC,并不是“像素一亮,图像就来了”这么简单。
中间至少有这些东西:
- pixel array
- row/column scanner
- analog front-end
- ADC
- black level correction
- gain control
- timing generator
- PLL / clock tree
- crop / binning / skipping
- test pattern generator
- MIPI CSI-2 transmitter
- OTP / calibration data
- power sequencing / standby control
这些模块每一个都需要配置。每一个模块背后都有一堆 register。
所以 sensor register 多,本质上是因为 sensor 内部模块多,而且这些模块必须协同工作。你不是在配置一个开关,而是在配置一条流水线。
# 第一类:身份和基本控制
最简单的一类 register 是身份识别和基础状态。
比如 chip id、revision、standby、stream on/off。
驱动 probe 的时候通常会先读 chip id:
确认自己没有认错人。否则把 A sensor 的初始化序列写进 B sensor,轻则黑屏,重则工程师开始怀疑人生。
stream control 通常也很关键:
很多 sensor 的寄存器配置必须在 standby 状态下写,最后再打开 streaming。顺序不对,sensor 可能不会报错,只是安静地给你一片黑。硬件有时候很礼貌,礼貌到不告诉你它不高兴。
# 第二类:电源、复位和时钟
camera sensor 对时钟非常敏感。
外部给它一个 xvclk,比如 24MHz。sensor 内部再通过 PLL 生成 pixel clock、系统时钟、MIPI clock。不同分辨率、不同帧率、不同 lane 数,都可能需要不同的 PLL 配置。
这就是为什么你会看到一堆看起来很抽象的 register:
这些值不是随便写的。它们最终决定:
- pixel clock 是多少
- 一帧需要多少时间
- MIPI 输出速率够不够
- SoC 接收端能不能锁住数据
camera 黑屏问题里,时钟和 MIPI 配置经常是嫌疑人。图像链路里有些错误会很直观,比如颜色不对。有些错误很沉默,比如 lane 根本没起来。沉默的问题一般比较费咖啡。
# 第三类:时序控制
sensor 输出图像不是只输出有效像素。
它还需要行消隐、帧消隐、同步时序。常见的概念包括:
- line length
- frame length
- horizontal blanking
- vertical blanking
- exposure line
- frame interval
很多 sensor 里会看到类似:
有效图像可能是 1920x1080,但一行的总周期不一定只有 1920 个 pixel clock。它还包含 blanking。每帧也不只是 1080 行,还会包含 vertical blanking。
这些值决定帧率,也会影响最大曝光时间。
比如曝光时间通常不能超过一帧的长度。如果你想低光下长曝光,可能要增加 VTS。于是一个“调亮画面”的需求,最后会落到 frame length register 上。第一次遇到时会觉得绕,后来就习惯了:图像世界里,亮度问题经常会变成时序问题。
# 第四类:窗口、裁剪、binning 和 skipping
同一个 sensor 可以输出很多模式:
这些模式不是凭空来的。sensor 需要知道:
- 从 pixel array 的哪个位置开始读
- 读多宽多高
- 是否裁剪
- 是否 binning
- 是否 skipping
- 输出尺寸是多少
所以会有一堆 window 相关 register:
binning 是把相邻像素合并,提升感光能力或降低分辨率。skipping 是跳着读,减少数据量。它们都会影响画质、视场角、噪声、帧率和 MIPI 带宽。
也就是说,一个 mode table 其实不是“分辨率配置”,而是在告诉 sensor:请用这个方式从像素阵列里读出一张图。
# 第五类:曝光和增益
曝光和增益是大家最容易理解的一类。
曝光控制积分时间。增益控制信号放大。常见有:
- coarse integration time
- fine integration time
- analog gain
- digital gain
这类 register 通常会被 3A 算法频繁更新。所谓 3A,就是 AE、AWB、AF。sensor driver 一般不会自己决定曝光策略,但它要提供设置曝光和增益的能力。
在 Linux V4L2 里,这些通常会变成 control:
用户态或者 ISP 算法调 control,driver 再把 control 翻译成 sensor register。
这里有一个细节:曝光和帧长经常绑定。曝光想变长,可能需要改 VBLANK。VBLANK 改了,帧率又变了。帧率变了,MIPI 带宽和应用预期也会受影响。
camera sensor 的复杂性就在这里。一个 register 很少只影响一个东西。
# 第六类:模拟和图像质量调校
sensor 不是只负责吐 raw data。很多 sensor 内部还有一些基础图像质量相关模块。
比如:
- black level correction
- defect pixel correction
- lens shading correction
- color gain
- HDR / WDR mode
- noise reduction
- test pattern
有些处理最终会交给 ISP,但 sensor 端仍然要提供基础校准和模式配置。尤其是 black level、坏点、HDR 读出方式,这些和 sensor 物理特性关系很深。
这也是为什么 vendor 经常给一大段 recommended settings。里面很多值不是驱动作者能凭空推导出来的,而是厂商实验室调出来的。
所以看到一大段神秘初始化序列时,不要急着嘲笑它。它可能确实是魔法,但它是带实验数据的魔法。
# 第七类:MIPI CSI-2 输出
sensor 最后要把数据送给 SoC。现在常见的是 MIPI CSI-2。
这里又有一批 register:
- lane 数
- lane mapping
- data type
- virtual channel
- mipi timing
- hs_prepare / hs_zero / trail
- output bit depth
比如 RAW10、RAW12、RAW8 的输出格式不同,MIPI data type 不同,SoC 接收端也要匹配。
sensor 端配置错了,SoC 端可能表现为:
- 没有 frame start
- CRC / ECC error
- 只有部分行
- 图像花屏
- 数据格式解释错误
camera bring-up 很多时间都花在这里。你以为自己在调 sensor,实际上你在调 sensor、PHY、CSI receiver、ISP、clock tree 之间的互相信任关系。它们都说自己没问题,但图就是不出来。
# 为什么 mode table 像一段咒语
很多 camera driver 里会有这种东西:
这就是 mode table。
它看起来像一段咒语,是因为它确实承担了“把整个 sensor 切到某个工作状态”的职责。里面可能包含 PLL、timing、crop、MIPI、analog setting、vendor tuning。
驱动作者最怕的不是 register 多,而是 register 之间关系不清楚。单独看一个值没意义,只有整组配置一起看,sensor 才进入正确模式。
所以调 camera 时,不要只问“这个 register 是什么意思”。还要问:
这些问题比单纯翻地址表更有用。
# 驱动真正要做什么
sensor driver 的工作不是把所有 register 暴露给用户态。
它真正要做的是把复杂的 register 世界收敛成稳定的内核接口。比如 V4L2 subdev 里的:
- enum mode
- set format
- set stream
- set exposure
- set gain
- set vblank
- get frame interval
也就是说,driver 应该把“成百上千个 register”包装成“几个可理解的操作”。
用户态不应该知道 0x0340 和 0x0341 怎么拼成 VTS。用户态应该知道它可以调 VBLANK 或 EXPOSURE。至于背后写哪些 register,那是 driver 的活。
这个抽象很重要。否则每个应用都要学习一遍 sensor datasheet,那 Linux camera stack 就会变成大型民间秘术交流现场。
# 怎么读一个 sensor datasheet
如果第一次读 camera sensor datasheet,我建议不要从 register address 一行一行啃。
可以按这个顺序看:
- 先看 sensor 支持哪些输出格式、分辨率、帧率。
- 再看 clock tree 和 PLL,确认输入时钟和输出速率。
- 看 timing:HTS、VTS、exposure、blanking。
- 看 image window:crop、output size、binning、skipping。
- 看 MIPI CSI-2:lane、bit depth、data type、timing。
- 最后再看 recommended register sequence。
这样读会清楚很多。
register 表像字典。mode table 像句子。sensor 架构图才是语法。只看字典,很难理解一门语言。
# 多不是问题,乱才是问题
camera sensor 有很多 register,这本身不是坏事。
多,说明它能配置的东西多。能支持不同分辨率、帧率、曝光策略、MIPI 输出、HDR 模式和图像质量调校。
真正麻烦的是 register 之间关系不透明,datasheet 写得克制,vendor tuning 又像祖传菜谱:盐少许,火候适量,其余全靠经验。
所以理解 camera sensor register,核心不是背地址,而是建立模块图:
每个 register 都尽量放回这张图里。
放得回去,它就是工程配置。放不回去,它就是暂时不要乱动的黑盒调参。
一个 sensor 为什么有这么多 register?
因为它不是一个按钮。它是一台很小、很精密、脾气还有点细的图像工厂。驱动工程师要做的,就是让这座工厂按正确节奏开工,把光变成一帧一帧能被系统理解的数据。
