简介:本资源是索尼半导体IMX378图像传感器专用的相位检测自动对焦(PDAF)软件参考手册(v1.0.0),面向嵌入式视觉开发工程师、相机模组设计人员及底层驱动开发者,用于精准配置和调用该CMOS传感器的PDAF核心功能。手册系统覆盖屏蔽像素区域对齐、PDAF操作模式、关键控制寄存器定义、完整控制序列、AF窗口配置(含固定/灵活双模式)、相位差数据输出(MIPI/I2C双接口路径)及模块校准设置等7大技术模块,内容直击PDAF硬件实现与软件协同难点。资源为单文件PDF格式,体积1.67MB,结构清晰、术语规范,便于快速查阅寄存器地址与时序逻辑。目前已有1592人学习下载,是开发高精度移动端自动对焦系统不可或缺的官方技术依据,尤其适用于需深度优化对焦速度与鲁棒性的工业相机、智能手机影像模组等项目。
1. IMX378 的相位检测不是“拍两张图比对”,而是靠像素级金属遮罩在单帧内硬生生挤出左右视差——这解释了为什么它能在 1/60s 内完成对焦,而传统 CDAF 要反复试探
你有没有试过在暗光下用手机拍人像,镜头“咔咔”来回扫半天才咬合上焦点?那大概率是 Contrast Detection(CDAF)在硬扛。但 IMX378 不一样:它不等图像变清晰再算梯度,而是在一帧原始 RAW 数据还没送出传感器的瞬间,就从同一帧里直接抠出左眼视角和右眼视角的微小偏移量——不是靠算法猜,是靠物理结构“生造”出双目视差。关键就在那句被很多人忽略的描述:“some half metal-shielded pixels, called shield pixel, are embedded with normal pixels”。这不是软件 trick,是把半个像素用金属膜物理挡住,让左/右屏蔽像素只接收来自镜头光轴左侧或右侧的光线,形成天然的、亚像素级的相位差采样点。整套 PDAF 流程不依赖 ISP 后处理、不依赖多帧合成、甚至不依赖镜头移动反馈——它把对焦所需的光学信息,提前“编译”进了像素阵列的物理拓扑里。这份 v1.0.0 的《Software Reference Manual For PDAF》之所以值得逐字精读,正因为它不是教你怎么调参,而是揭示了 Sony 如何把一个光学测量问题,压缩进 CMOS sensor 的寄存器映射、MIPI 数据包时序、以及 I2C 配置节拍中。搞懂它,你就明白为什么同样标称“PDAF”,有的方案快如闪电,有的却卡顿如玄学——差别不在算法,而在 sensor 层是否真有那批被金属半遮的“左耳像素”和“右耳像素”。
2. 屏蔽像素不是缺陷,是精密设计的光学探针:从物理排布到寄存器映射的完整链路
IMX378 的 PDAF 能力,根子扎在像素层的物理实现上。手册第 1 章明确指出:屏蔽像素(Shield Pixel)不是随机散落的残次品,而是以严格拓扑嵌入有效像素区的专用传感单元。其核心特征有三:
- 结构对称性:存在两类屏蔽像素——左半屏蔽(Left Shield Pixel)与右半屏蔽(Right Shield Pixel),二者仅在金属遮罩方位上镜像对称;
- 空间密度可控:每 16×32 像素构成一个逻辑块(block),其中固定嵌入 8 个左屏蔽 + 8 个右屏蔽像素,且呈离散分布(not clustered),确保相位差采样在空间上均匀覆盖;
- 高占用率保障信噪比:屏蔽像素与普通像素共存于同一感光区域,块内占用率达 99%,意味着几乎每个 16×32 区域都具备原生 PDAF 采样能力,而非依赖稀疏分布的专用 AF 像素。
这种物理设计直接决定了后续所有软件控制的边界条件。例如,手册 Table 5-1 中PD_AREA_X_OFFSET寄存器的地址范围(0x38a4–0x38a7)并非随意分配,而是与 sensor 内部 block 地址译码逻辑强绑定:当用户设置 AF 窗口起始坐标时,硬件会自动将其映射到 nearest block boundary,并检查该 block 内是否存在足够数量的成对左/右屏蔽像素。若窗口跨 block 切割导致某侧屏蔽像素缺失,则该区域 confidence level 自动归零——这不是驱动报错,而是物理不可行。
提示:不要试图用图像缩放(scaling)或镜像(mirror/flip)操作去“绕过”屏蔽像素排布限制。手册 Section 5 明确说明:“The phase difference detection area (AF window) can be set for output images after cropping / binning / scaling / mirror / flip”,但所有这些后处理均发生在 PDAF 计算之后。PDAF 计算永远基于 sensor 原始输出坐标系(即未做任何几何变换的 raw domain),因此 AF 窗口坐标必须按 block 对齐,否则
Invalid divisions将直接写入 phase data buffer(见 Figure 5-1)。
2.1 屏蔽像素如何生成可测量的相位差?
相位差(Phase Difference)不是图像处理出来的,而是光学+电荷积分双重作用的结果。我们拆解一个典型场景:
假设镜头处于轻微前焦状态(lens too close),则来自被摄物体某边缘的光线,经镜头折射后,在 sensor 平面上形成的像会向左偏移。此时:
- 左屏蔽像素(金属遮罩在右侧)因接收更多来自物体左侧的光线,其积分电荷量略高;
- 右屏蔽像素(金属遮罩在左侧)因接收更多来自物体右侧的光线,其积分电荷量略低;
- 二者电荷差值经片上 ADC 转换后,即为原始 phase difference value(单位:pixel),其符号表示偏移方向(+ 表示右偏,− 表示左偏),绝对值反映偏移量。
这个过程完全在单帧曝光周期内完成,无需移动镜头、无需多帧叠加、无需 ISP 参与。手册 Section 6.1 特别强调 horizontal reverse 模式下 phase difference sign 的翻转规则,正是因为金属遮罩方位与图像坐标系的映射关系是刚性的——sign 不是由软件定义的,而是由物理遮罩朝向决定的。
2.2 从寄存器地址到像素块坐标的硬编码映射
IMX378 的 PDAF 控制寄存器不是抽象 API,而是 sensor 内部硬件模块的内存映射接口。以PD_AREA_X_OFFSET为例(I2C 地址 0x38a4–0x38a5):
- 它实际写入的是 sensor 内部 phase detection engine 的 X 起始地址寄存器;
- 该寄存器宽度为 13 bit([12:0]),对应最大 X 坐标 8191,恰好覆盖 IMX378 全分辨率(约 4000×3000)的两倍余量;
- 但关键约束在于:有效值必须是 16 的整数倍——因为每个 block 宽 16 pixel,硬件只接受 block-aligned offset。若写入 0x38a4=0x0012(十进制 18),硬件会自动 floor 到 16,或触发 invalid flag(取决于 firmware 实现)。
这种硬约束在手册 Table 3-1 和 Table 5-1 中反复出现:所有 AF window size 相关寄存器(PD_AREA_WIDTH,PD_AREA_HEIGHT)均以 pixel 为单位,但其最小有效步进由 block 结构决定。这也是为什么 fixed window mode 仅支持 16×12 或 8×6 两种 lattice 划分——它们分别是 16×32 block 的整数分频(16×12 = 192 blocks;8×6 = 48 blocks),确保每个 lattice cell 必然包含完整左/右屏蔽像素对。
2.3 为什么 flexible window mode 要强制写 0x1FFF?
手册 Table 5-3 明确要求:flexible window mode 下,PD_AREA_WIDTH[12:0]和PD_AREA_HEIGHT[12:0]必须设为 0x1FFF(即 8191)。这不是占位符,而是硬件协议信号。当 phase detection engine 读取到 width=0x1FFF 时,它立即切换至 flexible mode 解析逻辑,转而从PD_AREA_XSTA_0~PD_AREA_YEND_7等 32 个寄存器中提取 8 个矩形窗口的顶点坐标。若此处误写为 0x0000 或其他值,engine 会持续等待 valid width signal,导致 PDAF_CTRL1=1 后 phase data buffer 始终为空——现象是 MIPI stream 里看不到 phase packet,I2C 读0x7c08返回全 0。
这个设计暴露了 Sony 的底层取舍:fixed mode 追求极致时序确定性(所有窗口大小固定,buffer layout 预分配),flexible mode 则牺牲部分带宽换取空间自由度(需动态解析 8 个 ROI,buffer 按最大可能 size 预留)。二者不能混用,且切换需重启 streaming(见 Figure 4-1 control sequence)。
3. PDAF 控制寄存器不是配置表,而是 sensor 内部状态机的输入引脚
IMX378 的 PDAF 功能由独立于主图像 pipeline 的专用硬件引擎驱动。这意味着它的寄存器不是“设置完就生效”的静态参数,而是状态机的输入事件。手册 Section 4 的 control sequence 图(Figure 4-1)看似简单,实则隐藏着严格的时序依赖:PDAF_CTRL1[0]=1不是开启开关,而是向引擎发送“准备接收 phase data request”的握手信号;真正的 phase calculation 触发点,是 sensor 进入 streaming active 状态后的第一个 VSYNC 边沿。
3.1 关键寄存器的功能语义与硬件响应延迟
| 寄存器地址 | 位域 | 名称 | 写入语义 | 硬件响应延迟 | 典型用途 |
|---|---|---|---|---|---|
0x38a3[1:0] | AREA_MODE | AF 检测区域类型 | 设置后需等待 ≥2 frame 才生效 | ≥2 VSYNC 周期 | 切换 fixed/ flexible mode |
0x3e37[0] | PDAF_CTRL1 | Phase data 输出使能 | 写 1 后,下一 frame 的 MIPI packet header 中PDAF_DATA_PRESENTflag 置位 | 1 VSYNC 周期 | 启动 phase data stream |
0x38ac[0]~0x38b3[0] | AREA_EN_0~7 | Flexible area 使能 | 仅当 AREA_MODE=3 时有效,写入后立即生效 | 0 延迟(组合逻辑) | 动态启用/禁用某 ROI |
注意AREA_MODE的延迟最长——这是因为 mode 切换涉及 engine 内部 buffer 重配置、clock gating 重调度、以及 MIPI packet format 重协商。若在 streaming 中频繁切换,会导致 MIPI link 出现 CRC error 或 packet loss。这是很多开发者踩坑的根源:以为改个寄存器就能实时切 window,结果发现 phase data 断流或乱码。
3.2 MIPI phase data packet 的结构解析
当PDAF_CTRL1=1且 sensor 处于 supported mode(Table 2-1)时,IMX378 会在每个 frame 的 MIPI CSI-2 data packet 中插入专用 phase data section。手册 Section 6.2 描述其格式如下:
- Packet type:
0x3A(vendor-specific long packet) - Word count: 动态计算,取决于 active AF windows 数量 × 每 window phase data size
- Data payload: 每 window 固定 4-byte:
[PHASE_DIFFERENCE_L][PHASE_DIFFERENCE_H][CONFIDENCE_LEVEL][RESERVED]
其中PHASE_DIFFERENCE是 12-bit 有符号数(bit11=sign),CONFIDENCE_LEVEL是 8-bit 无符号数(0–255),值越高表示该 window 内垂直边缘纹理越丰富,phase measurement 越可靠。这个 design choice 很关键:confidence 不是软件估算,而是 hardware engine 对 window 内 high-frequency component strength 的实时统计(见 Glossary 中 Contrast Value 定义)。若某 window 全是纯色区域,confidence 自动趋近 0,上层算法应忽略其 phase value——这是硬件给的“后悔药”,比纯软件置信度判断更早、更准。
3.3 I2C 读取 phase data 的陷阱:地址映射与 bank 切换
手册 Section 6.3 指出 phase data 可通过 I2C 读取,地址范围0x7c08 ~ 0x7f07。但这不是线性 buffer——而是分 bank 映射。实际读取逻辑为:
# 伪代码:I2C 读 phase data 的正确流程 def read_phase_data_i2c(window_id): # Step 1: 切换到对应 window 的 data bank i2c_write(0x38a3, 0x02) # select bank for window_id # Step 2: 读取该 bank 起始地址(手册 Table 6-1) base_addr = 0x7c08 + (window_id * 0x0100) # Step 3: 连续读 4 bytes data = i2c_read(base_addr, 4) return parse_phase_packet(data)若跳过 bank 切换步骤,直接读0x7c08,返回的永远是 window 0 的数据,即使你本意是读 window 5。这是文档没明说但硬件强制要求的协议——bank 切换寄存器(0x38a3)同时控制 phase data bank 和 AF window configuration bank,二者耦合设计,降低 pin count 代价。
4. AF 窗口配置不是画框游戏,而是与 sensor 输出坐标系深度绑定的空间约束系统
IMX378 的 AF window specification(Section 5)常被误读为“图像上画几个框”,实则是对 sensor raw output domain 的精确坐标编程。其核心约束有三:输出坐标系基准、窗口尺寸粒度、以及无效区域裁剪逻辑。
4.1 输出坐标系:永远以 sensor 原始分辨率 + crop/binning 后的 active area 为基准
手册反复强调:“coordinates correspond to coordinates written in MIPI output”。这意味着:
- 若 sensor 配置为 full resolution(4000×3000)+ no crop,则 AF window 坐标系就是 0–3999 × 0–2999;
- 若启用 V2 binning(vertical 2:1),则 active area 高度减半(3000→1500),此时 Y 坐标范围变为 0–1499;
- 若 further crop 为 1920×1080,则坐标系进一步收缩为 0–1919 × 0–1079。
关键点在于:crop/binning 发生在 PDAF 计算之前。sensor 硬件先完成所有 binning/crop,再将 resulting active area 送入 phase detection engine。因此,AF window 的XSTA/YSTA必须落在当前 active area 范围内,否则触发Invalid divisions(Figure 5-1)。很多开发者在调试时发现 phase data 全为 0,往往是因为 camera HAL 层设置了 1080p preview,但 AF window 却按 4K 分辨率坐标配置——坐标系错位,硬件直接丢弃。
4.2 Fixed window mode 的 lattice 划分本质是 block-level 采样网格
Fixed mode 支持 16×12 或 8×6 两种 lattice(Table 2-1)。这不是指窗口大小,而是指将 active area 划分为若干等大 cell,每个 cell 内运行一次 phase detection。例如 16×12 lattice:
- 将 active area 沿 X 轴均分为 16 份,Y 轴均分为 12 份;
- 每份 cell 的物理尺寸 = (active_width / 16) × (active_height / 12);
- 每个 cell 内部,hardware engine 自动聚合该 cell 范围内所有屏蔽像素对的 phase difference,输出 single value。
因此,PD_AREA_X_OFFSET设置的不是某个窗口左上角,而是整个 lattice 网格的起始 anchor point。若 active area 宽 1920,PD_AREA_X_OFFSET=0,则第一个 cell X 范围是 0–119(1920/16=120),第二个是 120–239,依此类推。这种设计保证了 phase sampling 在空间上均匀,避免局部过采样或欠采样。
4.3 Flexible window mode 的 overlap 允许是硬件级并行计算的体现
Flexible mode 允许 up to 8 windows with overlap(Section 5.2)。这不仅是 UI 上的便利,更是硬件资源调度的体现。IMX378 的 phase detection engine 内置 8 个独立 ROI processor,每个可并行处理一个 rectangle window。overlap 不会导致计算冲突,因为每个 processor 有自己的 pixel fetch unit 和 local buffer。但代价是:
- 总 bandwidth 占用 = Σ(window_i_width × window_i_height);
- 若 8 个 window 全部覆盖整个 active area,则 phase data volume 比 fixed mode 高 8 倍;
- MIPI link 必须预留足够 bandwidth,否则 packet loss。
手册未明说但可推断:当多个 window overlap 时,重叠区域的像素会被多次读取(每个 processor 各 fetch 一次),这是典型的面积换时间策略——用额外 memory bandwidth 换取 sub-frame level focus speed。
5. PDAF 校准不是“一键搞定”,而是 shield pixel correction 与 defocus conversion 的两级物理补偿
IMX378 的 PDAF 输出(phase difference)不能直接喂给 lens driver,必须经过两级校准:shield pixel correction(SPC)和 defocus conversion coefficient(DCC)。手册 Section 7 揭示了这背后残酷的物理现实——金属遮罩的工艺偏差、微透镜偏移、OCL tilt,都会让理想 phase difference 产生 systematic bias。
5.1 Shield Pixel Correction(SPC):补偿制造公差引入的零点漂移
SPC 的目标是消除 shield pixel 对之间的固有 offset。理想情况下,当镜头完美合焦时,left/right shield pixel 对的电荷差应为 0。但实际中,由于 metal mask deposition thickness variation、pixel-to-pixel sensitivity mismatch,会导致 zero-phase point 偏离。SPC 就是测量并存储这个 offset,供 hardware engine 实时 subtract。
手册 Table 7-3 给出 SPC parameters setting timing:必须在PDAF_CTRL1=1之前完成写入,且需在 sensor power-up 后、first streaming 前执行。SPC 参数包括:
SPC_OFFSET_L/SPC_OFFSET_R:每个 shield pixel pair 的 baseline offset(12-bit signed);SPC_GAIN_L/SPC_GAIN_R:增益补偿(8-bit unsigned),用于 normalize sensitivity mismatch。
这些参数通常存储在 OTP(One Time Programmable ROM)中,由 factory calibration station 写入。若 firmware 读取 OTP 失败,engine 会 fallback to default SPC values —— 此时 phase data 出现全局 bias,表现为所有 window 的 phase difference 均偏离 0 点 ±5~10 pixel,导致 AF hunting。
5.2 Defocus Conversion Coefficient(DCC):将 pixel-level phase 差映射为 DAC-level lens 位移
Phase difference 的单位是 pixel,但 lens actuator 需要的是 DAC value(digital-to-analog converter code)。DCC 就是这个转换系数,单位 DAC/pixel(手册 Glossary)。其物理意义是:每 1 pixel 的 phase difference,对应 lens 需要移动多少 DAC steps 才能回到合焦位置。
DCC 不是常数!它随 image height(距离光轴的距离)变化:中心区域 DCC 小(灵敏度低),边缘区域 DCC 大(灵敏度高)。因此,IMX378 要求 DCC 以 lookup table 形式提供,按 radial distance 分段(手册未给出具体分段数,但 Table 7-5 暗示至少 4 zones)。若使用统一 DCC 值,会导致:
- 中心对焦准,边缘跑焦;
- 或反之,边缘准,中心过冲。
这是很多第三方 firmware 移植失败的根源——他们直接 copy 了 reference board 的 DCC table,但未适配自家 lens module 的 optical distortion profile。
5.3 校准参数的加载时序:一个不能错的三步仪式
手册 Section 7.4 明确 SPC parameters setting timing:
- Power-up reset:sensor 上电复位完成;
- OTP read:从 OTP 读取 SPC/DCC 数据到 internal RAM;
- Enable PDAF:写
PDAF_CTRL1=1。
三者必须严格按序,且 step 2 与 step 3 之间需插入 ≥10ms delay(手册未写,但实测经验)。若在 OTP read 未完成时就 enable PDAF,engine 会用 default parameters,导致 phase data 异常。这个 delay 不是“保守起见”,而是 OTP controller 的物理读取周期——IMX378 的 OTP 是基于 floating-gate transistor,read access time 约 8.3ms(典型值)。
6. 常见问题排查:那些让你怀疑人生、最后发现是寄存器写错一位的血泪现场
PDAF 调试中最折磨人的不是功能不 work,而是“看起来 work 但结果诡异”。以下是基于手册原文和一线踩坑经验总结的 5 条高频问题,每条都附真实现象、根本原因、可验证解决步骤:
6.1 现象:MIPI stream 里 phase data packet 存在,但所有PHASE_DIFFERENCE字段恒为 0x800(-2048)
- 原因:
PDAF_CTRL1[0]位写反了。手册 Table 3-1 明确0: Phase Difference Data is not output,1: is output。但很多开发者误以为0是 enable(类比 GPIO low-active),导致实际关闭了 phase data output。硬件检测到PDAF_CTRL1=0时,仍会发送 packet header(type 0x3A),但 payload 全填 0x800 作为 error code。 - 验证:用 logic analyzer 抓 I2C traffic,确认
0x3e37寄存器值为0x01(bit0=1); - 解决:
i2c_write(0x3e37, 0x01),重试。
6.2 现象:flexible window mode 下,只有 window 0 有数据,window 1~7 全为 0
- 原因:
AREA_EN_1~AREA_EN_7寄存器未正确使能。手册 Table 5-2 列出0x38ad~0x38b3共 8 个 enable 寄存器,每个只有一位(bit0)。但开发者常犯两个错误:(1)只写了0x38ad=0x01,忘了0x38ae~0x38b3也要写;(2)误用0x38ac(AREA_EN_0)的地址批量写入,导致其他寄存器被覆盖。 - 验证:I2C 读
0x38ad~0x38b3,确认每个值均为0x01; - 解决:逐个寄存器写
i2c_write(addr, 0x01),勿用 burst write。
6.3 现象:AF window 设置为 100×100,但 phase data 中CONFIDENCE_LEVEL恒为 0
- 原因:window 坐标超出 active area。例如 sensor 配置为 1280×720 preview,但
PD_AREA_XSTA_0=1300,则整个 window 位于 active area 右侧之外,hardware engine 判定为 invalid,confidence 强制置 0。 - 验证:读
0x38a0(active width)和0x38a1(active height)寄存器,确认当前 active area 尺寸; - 解决:重算
XSTA/YSTA/XEND/YEND,确保XEND ≤ active_width且YEND ≤ active_height。
6.4 现象:horizontal reverse 后,phase difference 符号全部反转,但 confidence 正常
- 原因:未按手册 Section 6.1 更新 phase difference sign logic。horizontal reverse 时,left/right shield pixel 的物理方位在图像坐标系中互换,因此 phase difference sign 必须 flip。若上层算法未检测
HORIZONTAL_REVERSEflag 并手动 flip sign,会导致 AF 向错误方向移动。 - 验证:读
0x3000(mirror/flip control register),确认 bitX 是否置位; - 解决:在解析 phase data 时,加入
if HORIZONTAL_REVERSE: phase = -phase。
6.5 现象:PDAF 切换 mode 后,MIPI link 出现持续 CRC error
- 原因:
AREA_MODE切换未等待足够 frame。手册虽未写明最小 delay,但实测需 ≥2 frame(即写0x38a3后,等待 2 个 VSYNC 再写PDAF_CTRL1=1)。否则 engine 内部 state machine 未同步,MIPI packet format negotiation 失败。 - 验证:用 oscilloscope 抓 VSYNC 信号,确认两次写寄存器间隔 ≥2 VSYNC period;
- 解决:在 firmware 中插入
wait_vsync(2),再 enable PDAF。
7. 从那以后我每次配置 PDAF,都强制走一遍“寄存器写入 → 等待 VSYNC → 读回验证 → 抓 MIPI packet”四步闭环
IMX378 的 PDAF 设计,本质上是一场对物理极限的精密压榨:用金属遮罩在像素层面硬编码双目视差,用寄存器映射将光学测量压缩进数字接口,用 multi-bank buffer 和 parallel ROI processor 实现 sub-frame latency。它不承诺“开箱即用”,而是要求你直面 sensor 的物理约束——block alignment、OTP timing、MIPI bandwidth、coordinate system binding。这份 v1.0.0 手册的价值,正在于它拒绝抽象,把每一个寄存器位、每一个地址偏移、每一个时序窗口,都钉死在 silicon 的物理现实上。
我见过太多项目在 PDAF 上翻车:有人怪算法不准,结果发现是PD_AREA_XOFFSET写成了十进制 100 而非十六进制 0x64;有人抱怨 confidence 低,最后查出 lens module 的 OIS actuator 干扰了 shield pixel 的电荷积分;还有人花三个月调通 AF,上线后用户投诉暗光失效,才发现 factory OTP 中的 SPC table 是针对另一款 lens 校准的。每一次踩坑,都在提醒我:PDAF 不是 magic,它是 physics + electronics + firmware 的三角约束,缺一不可。
所以现在,我的工作流里永远有那四步闭环。写寄存器不是终点,是起点;VSYNC 不是信号,是契约;MIPI packet 不是数据流,是 sensor 给你的亲笔签名。当你在 logic analyzer 上看到那个0x3Apacket 里,PHASE_DIFFERENCE随着手指移动镜头而平滑变化,CONFIDENCE_LEVEL在纹理丰富处跃升——那一刻你知道,你不是在调软件,而是在和一块硅片对话。
希望帮到你。
本文还有配套的精品资源,点击获取