OV5647 MIPI RAW 在 MTK Android 平台的驱动移植与调试指南

发布时间:2026/10/5 3:44:10
OV5647 MIPI RAW 在 MTK Android 平台的驱动移植与调试指南 简介针对Android平台上OV5647摄像头驱动开发的参考资料聚焦MediaTekMTK芯片方案解决MIPI接口摄像头模组的驱动配置与适配问题。压缩包内共4个文件包含3个头文件和1个C源文件整体大小仅16KB文件精简却覆盖了设备节点定义、传感器参数表、MIPI发送/接收配置以及部分初始化控制逻辑。通过阅读这套源码开发者能够了解OV5647的寄存器配置流程、MTK Camera HAL层对接方式、ISP图像处理管路的建立以及RAW数据输出时的相关参数调整方法同时涵盖驱动注册、传感器上电、数据流与中断处理等关键环节为在MTK平台上移植或调试MIPI摄像头提供具体的代码级参考。资源已有773人学习/下载适合熟悉Linux驱动基础、需要快速介入Android摄像头开发的工程师作为入门与参照。1. 拿到 ov5647_mipi_raw.rar 之后先别急着点亮先读懂这套 MTK Android 驱动在解决什么做过 MTK 平台 camera bring-up 的工程师看到这种命名基本就能猜到包里是什么一颗 OV5647 摄像头传感器、走 MIPI 接口、输出 RAW 数据面向 Android 系统里的 MTK 平台。这类 rar 通常是从某个量产方案里流出来的参考工程里面装着 imgsensor 驱动、dts 配置、PD tuning 参数运气好的还有一份 commit log。它的价值不是让你省掉写驱动的功夫而是给你一条已经跑通的路径OV5647 在 MTK Android 上怎么初始化、怎么出 RAW、tuning 从哪下手。适合正在做安卓方案集成、sensor bring-up 或者从 YUV 传感器转向 RAW 传感器的驱动工程师。这篇文章就按我自己的习惯把这条路径从解包到出图完整拆开顺带把最容易翻车的地方都标出来。2. OV5647 在 MTK 平台上的 MIPI RAW 链路从 sensor 数据到 Android 相机 HAL 的完整通路2.1 为什么选 OV5647500 万像素、MIPI RAW 与树莓派模组的性价比OV5647 是 OmniVision 的一颗 500 万像素 CMOS 传感器1/4 英寸光学尺寸单像素 1.4um支持 RAW10/RAW8、YUV422 和压缩 JPEG 输出接口上同时带 DVP 和 MIPI。真正让它普及的是树莓派摄像头模组树莓派官方 Camera Module V1 用的就是 OV5647这颗料因此被大量模组厂做成标准 15pin MIPI 接口的成品淘宝上几十块钱就能买到带软排线的模组焊盘、排线定义还基本统一。对做方案的人来说这意味着采购容易、替代料多、手里随便就能找来两三家的模组交叉验证。在 MTK Android 平台上选它更实际的理由是性价比。MTK 的中低端 SoC 带 5M sensor 绰绰有余OV5647 的驱动资料在公版 SDK 里长期存在网上甚至能找到树莓派和 MTK 两套完全不同风格的参考代码。它的 RAW 输出对理解 ISP 管线非常有帮助Bayer 数据直接进 MTK 的 ISP白平衡、降噪、色彩校正全交给 3A 和 tuning跟 YUV sensor 那种“sensor 内部已经处理完、HAL 只能做小修”的模式完全是两套玩法。RAW 的好处是前端信息不丢失后期可以调的空间大坏处是 tuning 做不好画面会很难看这个后面单独展开。2.2 MTK imgsensor 驱动的三层结构sensor 驱动、HAL 注册与 PD tuningMTK 平台的 camera 驱动不是一份代码而是三层各管一段。最底层是 imgsensor 驱动也就是 rar 里最值钱的.c和.h文件它负责通过 I2C 读写 sensor 寄存器、配置分辨率切换、控制曝光增益、设置 MIPI 参数。这一层跑在 kernel 态通常放在vendor/mediatek/proprietary/custom/[平台]/hal/imgsensor/下面编译出来的东西叫imgsensor内核模块。第二层是 HAL 的 sensor 注册。MTK 的 Camera HAL 启动时会扫描 imgsensor 列表每个 sensor 驱动里有一个SENSOR_DRVNAME宏和get_drv_name()接口HAL 靠这个名字去匹配 dts 里配置的 sensor 节点。名字不匹配是最常见的低级错误编译能通过但 HAL 就是枚举不到摄像头后面会专门讲。第三层是 PD tuning也就是 MTK 的 3AAE、AF、AWB参数包。RAW sensor 没有内置 ISP颜色和亮度全靠这颗 sensor 对应的 tuning 参数来校正。常见做法是把 tuning 的 bin 文件挂在系统分区或者vendor/etc/camera下HAL 在初始化时按 sensor 名字加载。很多从其他地方移植过来的驱动能出图但颜色奇奇怪怪问题就出在 tuning 是别的传感器的直接套用。2.3 MIPI 链路的时序要点MCLK、lane、data_rate 的匹配关系MIPI 摄像头链路最值得先搞懂的是 MCLK、lane 数和 data_rate 三者的匹配关系。OV5647 建议的 master clock 是 24MHz这个频率由 SoC 的 MCLK 引脚输出通常通过 dts 里的pinctrl配置引脚后由 PMIC 或 SoC 内部时钟产生。MCLK 不稳sensor 的 PLL 就锁不住表现出来的就是偶尔黑屏或者画面闪。lane 数方面OV5647 支持 1-lane 和 2-lane MIPI。MTK 平台默认走 2-lane每 lane 的 data rate 由 sensor 驱动里的mipi_data_rate字段控制单位通常折算成 Mbps。日常调试里经常遇到预览只有 5 帧甚至一帧一帧跳的情况一半以上是 data_rate 配得比 sensor PCLK 还低数据来不及传完。简单记一个原则MIPI 总带宽要大于 sensor 输出 pixel clock 对应的码流RAW10 就是 10 bit per pixel算一下就知道够不够不用靠猜。MCLK 频率、CSI 的 lane 数、data_rate 三者必须一起出现在 imgsensor 驱动里MTK 在sensor_init阶段会去读这些字段然后交给 DPHY 做时序匹配。改任何一个都要重新编译 imgsensor 模块并比对 log后面避坑章节会再提。3. 把 ov5647_mipi_raw 集成进 MTK Android 工程解包核对、驱动注册与最小出图3.1 解包先核对四样东西驱动源码、dts 配置、tuning 文件与文档这类 rar 解压出来内容通常很杂有硬件原理图 PDF、有 I2C 地址确认表、有 camera 模组规格书但真正决定能不能编译的是四样东西。我拿到包的第一件事不是直接往工程里塞而是先找一个干净的 MTK SDK 工程把这四样核出来第一imgsensor 驱动源码也就是ov5647_mipi_raw.c和对应的头文件。留意这个.c文件的#define SENSOR_DRVNAME和sensor_id后面注册要用。第二dts 相关配置常见是一段i2c节点和 pinctrl 定义包含 sensor 的 I2C 地址和 reset/powerdown 引脚编号。第三tuning 文件通常是名字里带 sensor 型号的 bin 或者 so。第四工程配置文件里面写了这个 sensor 在哪个摄像头 index 上注册。如果解压出来没有第四样也别慌MTK 的标准做法是在 project config 里手动加后面第 3.2 节就讲这个。还有一个小习惯我会顺手看一眼包里的模组规格书确认 I2C 地址。OV5647 的常见 I2C 地址是 0x36但也有模组厂做成 0x20 或者 0x30以规格书为准。I2C 地址错了后面所有步骤都白做。3.2 在 imgsensor 的 sensor list 里注册 OV5647 并确认工程配置MTK imgsensor 驱动有一个全局数组每个 sensor 在这个数组里占一项。常见的注册代码长这样static const struct imgsensor_list_t g_sensor_list[] { #if defined(OV5647_MIPI_RAW) { SENSOR_DRVNAME_OV5647_MIPI_RAW, ov5647_mipi_raw_sensor_init }, #endif /* 其他 sensor 条目 */ { NULL, NULL }, };这段代码的意思是把 OV5647 的初始化函数挂到 HAL 扫描的链表上。SENSOR_DRVNAME_OV5647_MIPI_RAW来自驱动头文件里的宏定义ov5647_mipi_raw_sensor_init是驱动的入口函数它返回一个struct imgsensor_struct里面包含sensor_id、分辨率表、MCLK 频率等信息。这里的名字必须和 imgsensor 驱动的目录名、宏定义三者保持一致否则编译过了也枚举不到。然后是工程配置文件。MTK 的 SDK 老版本里有ProjectConfig.mk新版本较多改用cust文件或者vendor/mediatek/proprietary/custom/[平台]/hal/imgsensor下的配置头关键字是CUSTOM_KERNEL_IMGSENSOR和CAMERA_SENSOR_LIST。常见做法是这样的# 在工程配置里补上这一行让 imgsensor 编译系统把该 sensor 编进去 CUSTOM_KERNEL_IMGSENSOR ov5647_mipi_raw配置完之后用make kernel或者./build.sh kernel编译内核模块。编译日志里如果能看到ov5647_mipi_raw.o生成说明驱动进入了编译列表如果找不到优先检查配置关键字拼写和大小写mtk平台对文件名大小写敏感O5647和ov5647在这个环节经常让人白折腾半小时。3.3 编译后在串口和 adb 下验证 I2C 枚举与 sensor ID 读取编译通过只是开始真正确认 sensor 活着要看 I2C 能不能读到 ID。OV5647 有一个只读的chip_id寄存器常见地址是 0x300A 和 0x300B高字节和低字节驱动初始化时会去读它和宏OV5647_SENSOR_ID比对。这一步不通过黑屏是必然的。常见做法是在 host 上用 adb 连上开发板然后抓 kernel logadb shell dmesg | grep -i -E ov5647|sensor|imgsensor正常log里能看到类似sensor_id 0x5647或chip version的打印同时 I2C 总线上能看到3-0036这样的设备节点adb shell ls /sys/bus/i2c/devices/如果这里没有出现3-0036下一步就要确认 dts 里的 i2c 总线号和使能状态。MTK 的摄像头 sensor 通常挂在专用的 i2c 通道上通道号错了表现为系统启动时根本没有 probe 它dmesg 里甚至看不到 OV5647 这个名字。还有一种常见情况是 probe 有但读 ID 超时先查 scl/sda 上拉电阻有没有焊再查 reset 引脚电平这类硬件问题后面避坑章节再详说。3.4 最小出图验证preview 与 RAW 抓帧的检查方法ID 读到了接下来就是最小出图验证。先把系统相机打开正常情况下 preview 画面能出来虽然颜色可能不对但至少说明 CSI 数据通路是通的。如果 preview 黑屏但驱动 log 正常问题大概率在 ISP 和 HAL 之间先查vendor/etc/camera下对应 tuning 文件是否存在再查 camera 服务有没有 crashadb shell dumpsys media.camera | grep -i ov5647这个命令能列出 Camera HAL 枚举到的 camera 设备信息包括 sensor 名字、方向、分辨率。如果输出为空说明 HAL 没有加载到这颗 sensor如果有名字但 preview 黑就要查 PD tuning 的版本和 sensor 驱动里的sensor_id是不是匹配。RAW 抓帧在 MTK 平台上通常靠 Camera2 API 或者工厂模式下的 raw dump 工具。最容易的操作是打开相机后用adb shell dumpsys media.camera能看到当前 preview 的 crop 窗口确认输出分辨率。更彻底的验证是抓一帧 RAW 下来看 bayer 顺序这个放到最后一章先说结论只要 preview 有画面驱动主链路已经通了剩下的全是 tuning 和参数校准的活儿。4. MTK 平台上 OV5647 的 5 个必调参数时钟、bayer、曝光与 PD tuning4.1 MCLK 与 mipi_data_rate先算对像素时钟再谈图像稳定OV5647 的 MCLK 一般是 24MHz 外部时钟。这个值写在 imgsensor 驱动的imgsensor_struct里的mclk字段MTK HAL 会按照它去配置 SoC 的 MCLK 引脚频率。如果你用的模组是带晶振的版本那 MCLK 可以不管但大部分树莓派同款模组是无源晶体必须由 SoC 提供 24MHz 时钟。接下来是 mipi data rate。OV5647 在 2592x1944 全分辨率下输出 RAW10帧率如果按 15fps 算需要的裸数据量是2592 x 1944 x 10bit x 15 ≈ 756Mbps加上 blanking 开销2-lane 下每 lane 至少要跑 400~500Mbps所以驱动里mipi_data_rate我一般至少给到 800Mbps 才留够余量。这个值太小会直接表现为帧率上不去而且不是线性下降是那种一卡一卡的感觉。驱动端通常有一个长这样的初始化函数static struct imgsensor_struct ov5647_mipi_raw { .sensor_id OV5647_SENSOR_ID, .mclk 24, .mipi_data_rate 800, /* Mbps per lane */ /* ... */ };mclk单位是 MHzmipi_data_rate单位是 Mbps注意别把 800 写成 8000这类参数值在 rar 里如果有 readme 一般会标注没有的话按模组规格书算。判定方法很简单preview 帧率正常、每秒 30 帧左右就说明 data rate 够拖影、跳帧就往大调一档再编译验证不用看示波器也能判断个大概。4.2 Bayer 顺序、mirror/flip 与颜色矩阵偏色翻车的第一现场RAW sensor 输出的数据是 Bayer 格式每个像素只有 R/G/B 其中一个分量ISP 必须知道第一行第一个像素是什么颜色才能正确插值。OV5647 模组因为生产工艺不同bayer 顺序可能是 BGGR、RGGB、GRBG 或 GBRG 其中之一。MTK imgsensor 驱动里有专门字段static struct imgsensor_struct ov5647_mipi_raw { /* ... */ .pixel_order SENSOR_PIXEL_ORDER_BGGR, };最常见的问题是预览画面颜色完全错乱绿色植物变成紫色红色变成青色整个画面像反转负片。这时候十有八九是pixel_order和模组实际不一致。错误信息看着像 ISP 的 bug其实只是顺序没对上。调整方法就是四种枚举值轮着试每次编译重烧哪个颜色正常就用哪个。这个办法粗暴但高效我在两个项目上都靠它解决的偏色问题。另外一个误导项是 mirror 和 flip。树莓派模组的默认安装方向是镜头朝上到了手机上如果摄像头倒装就需要在驱动里设置 mirror/flip否则预览画面上下颠倒。注意这个设置会影响 bayer 顺序的实际输出先定 mirror/flip再定 pixel_order顺序不能反。4.3 曝光行数与最大帧率AE 参数不匹配时的过曝与暗场OV5647 的曝光控制由行数line决定一行对应的时间由 PCLK 和行长算出。MTK 驱动里 AE 会根据场景自动调整曝光行数但驱动必须提供“一行的时间”和“最大行数”这两个参数否则 AE 算出来的曝光完全没参照画面要么过曝到全白要么暗到看不清。我自己写驱动时习惯加一段计算用来核对最大行数u32 pclk 84000000; /* sensor 内部 pixel clock, 单位 Hz */ u32 line_length 2688; /* 全分辨率下每行总像素 */ u32 line_time_ns 1000000000 / (pclk / line_length); /* 单位 ns */ u32 max_frame_rate 15; /* 目标帧率 */ u32 max_exp_line 1000000000 / line_time_ns / max_frame_rate;这里line_length包含了 blanking不是简单的 2592必须从模组规格书或者 sensor 驱动里那个frame_length字段反推。如果最终算出来的max_exp_line和 MTK tuning 工具里的 AE 上限对不上最典型的症状就是高亮场景过曝压不下来明明曝光时间在降画面还是白花花一片。这种情况优先查max_exp_line别去调 tuning。OV5647 的两个核心曝光寄存器在 0x3500 到 0x3502曝光高、中、低字节增益在 0x3508 和 0x3509。驱动里读写这些地址时要注意字节序MTK 平台通常通过imu[0].i2c_write写寄存器出错的话曝光会跳变亮暗来回闪。4.4 PD tuning 的落地RAW sensor 的颜色和噪点靠它兜底驱动把 RAW 数据送出来只是第一步颜色能不能看全靠 PD tuning。PD 是 MTK 3A tuning 的统称里面包含 AWB 的色温校准、AE 的曝光曲线、降噪强度、色彩矩阵这些内容。OV5647 的 tuning 文件通常和传感器型号绑定放在系统里后由 HAL 加载。拿到 rar 里的 tuning 文件后我一般先看它的内容是不是针对 OV5647。怎么判断看 tuning 文件里的 sensor 名字字符串是否匹配不匹配的话 HAL 加载时会报 warning但不会 crash表现就是颜色怪又有 log 可以查。全套照搬别的 sensor 的 tuning 能出图但色偏、白平衡漂移、夜景噪点都会成倍放大。更严谨的做法是用 MTK 的 Camera Tuning Tool 对 OV5647 重新校准流程是先用 golden 模组在标准光源箱D65、A 光、CWF 等下拍灰卡然后通过工具自动生成 AWB 和色彩参数再回灌到 tuning 文件里。这步在量产前一定要做尤其做出口产品的光源环境和国内差别大拿默认 tuning 出货会遇到大量客诉。5. OV5647 在 MTK Android 上最容易翻车的 5 个问题现象、原因与排查路线5.1 黑屏无预览但 I2C 能读到 ID先查 MCLK 波形和 PWDN 电平现象驱动 log 正常I2C 能读到 sensor ID但 preview 全黑连噪点都没有。原因MCLK 没送到 sensor或者 PWDN 引脚一直拉高让传感器处于 power down 状态。这个问题的隐蔽性在于驱动看起来是活的I2C 地址能应答但 sensor 内部 PLL 根本没起来自然也没有 MIPI 数据输出。解决先查 pinctrl 配置确认 MCLK 引脚复用正确再用示波器量 sensor 端 24MHz 有没有波形。如果没有示波器一个土办法是把 MCLK 频率从 24MHz 改成 13.5MHz 试试如果能出图说明晶振电路没问题是 SoC 时钟配置错了。5.2 预览出图但偏色严重bayer 顺序与 sensor 镜像配置不一致现象预览画面能看清东西但颜色完全不对树叶变紫、人脸发绿像反转片。原因pixel_order字段和模组实际的 bayer 顺序不匹配或者 mirror/flip 设置后没有同步调整 bayer 顺序。解决先固定 mirror/flip 到实际安装方向然后依次尝试SENSOR_PIXEL_ORDER_BGGR、RGGB、GRBG、GBRG四种枚举值每种都重启相机看颜色。这个方法别嫌土它比重新读模组规格书快得多。注意每次改完都要重新编译 imgsensor 模块最好写一个脚本批量改省得来回烧。5.3 预览正常但拍照 RAW 全黑曝光行数与最大行时间没对齐现象预览画面正常但切到拍照或者抓 RAW 时拍出来的图全是黑的偶尔曝光时间极长时有微弱轮廓。原因拍照时 AE 从 preview 切换到 full size曝光行数上限和 full size 下的最大行时间不匹配导致 AE 直接把曝光压到最低。解决回到驱动里核对 full size2592x1944下的max_exp_line和 preview通常是 1280x720下的值是否成套。这类问题最容易发生在从树莓派代码移植到 MTK 的项目里两边 AE 模型的行时间概念不同不能直接照搬。5.4 系统相机找不到摄像头sensor index 与主副摄配置冲突现象kernel log 里能看到 OV5647 初始化成功ID 也读到了但 Android 系统相机打开后提示“无法连接相机”dumpsys media.camera只显示一个摄像头。原因MTK 平台区分 main camera 和 sub camera驱动注册时的 index 和 dts 里的camera_af节点、HAL 配置的前后摄序号对不上。解决打开工程配置里 camera sensor 的 index 相关字段确认 OV5647 是 main 还是 sub同时比对 dts 里的position属性。Vendor 的 HAL 配置里还有一个sensor_idx数组也要一起看这三个地方只要有一处不一致系统就枚举不到摄像头。5.5 预览帧率只有 5 帧mipi_data_rate 小于 PCLK 的真实需求现象预览画面能出但卡到没法用目测每秒 5 帧左右和 30fps 差得远。原因mipi_data_rate配得太小MIPI 链路带宽不够sensor 端不断的丢数据或者等待导致帧率被强制拖慢。解决把mipi_data_rate从 800 往上调比如 1000 或者 1200重编后看效果。这个场景下不要过度迷信公式因为 OV5647 的 blanking 参数不同实际带宽需求差异很大先给一个余量比较大的值验证正常后再逐步调低找到刚够用的值可以省一点功耗。6. 用 adb 和 dumpsys 做不插示波器的 sensor 健康检查以及把 RAW 校准前的最后一步设备没有示波器、没有逻辑分析仪的时候判断 sensor 是否真的工作靠 adb 和 dumpsys 也能完成七八成。第一步先用 dmesg 抓 imgsensor 的初始化记录能读到 sensor_id 说明 I2C 和 MCLK 大概率没问题第二步用dumpsys media.camera看 HAL 枚举出来的 camera 设备信息确认 sensor 名字和 index第三步打开相机预览同时抓 dmesg看有没有 MIPI error 或者 CSI timeout 的打印。这三步都过链路基本就算通了。剩下最后一步也是最容易被跳过的抓一帧 RAW确认 bayer 顺序和颜色矩阵。用 Camera2 API 的RAW_SENSOR能力可以拿到未处理的 RAW 数据或者 MTK 工厂模式下直接 dump。把 RAW 数据用 Python 按 10bit 解包看第一个 2x2 块的 R/G/G/B 分布就能验证驱动里pixel_order字段是否正确。我自己在项目上就用这个办法发现过模组批次不一致的问题同一个型号两批货 bayer 顺序居然不同不抓 RAW 根本看不出来。做这套验证时最好固定一个 golden 模组也就是用示波器确认过的完美模组先抓一套基准 RAW 存档。之后每次改驱动参数都拿新模组和基准对比偏差超过 5% 就要怀疑模组批次问题而不是继续调驱动。这是量产前必须做的回归动作。我的习惯是每调一个参数就更新一次 dts 和驱动里的注释把当时用的模组型号、批号、vender 名字、MCLK 频率、pixel_order 全写进去。这个习惯救过我很多次因为这类重新移植的 sensor 项目隔三个月再回来改 bug你会感谢自己当时留下的注释。希望这篇能帮你在 OV5647 的 MTK 集成路上少走几步弯路。本文还有配套的精品资源点击获取