
简介面向RK3288平台压缩包内含XC6130与OV2710摄像头组合在Android/Linux系统下的驱动适配代码适用于嵌入式驱动开发、Camera调试及BSP集成场景。包体仅26KB内容紧凑共5个文件2个C源文件实现驱动主体逻辑1个头文件定义接口Android.mk负责编译集成cam_board_rk3288.xml用于板级配置。目前已有140人学习下载。从内部目录看资源按XC6130、include_priv、source等模块组织覆盖从底层寄存器操作、i2c通信到board级参数配置的完整链路可直接参考OV2710 sensor驱动注册、上电时序设置及hal层对接方式。对于需要快速在RK3288上点亮XC6130OV2710组合的工程师这套小型驱动包能有效节省排错时间提供可移植的代码骨架与配置范例兼具实用性与学习价值。1. 拿到 xc6130_ov2710_driver.tar.gz 之后先搞清它是什么一块 RK3288 主板Android 7.1 固件跑得好好的点歌机、广告机今天要换摄像模组OV2710 接上后 /dev/video0 就是不出图。这个问题我遇到过不止一次不是硬件坏了而是驱动没有按平台套路放对位置。标题里这个 tar.gz 就是这类方案的典型交付物——RK3288 平台、Android 系统、OV2710 传感器外加一颗配套芯片 xc6130。xc6130 在多数模组里负责给 OV2710 提供干净的供电和参考时钟偶尔还兼顾复位和 MIPI 时序所以光有 ov2710.c 不解决全部问题得 xc6130 一起改。下面按我自己的移植流程讲一遍先拆包再落位然后配设备树、编译、排查。2. 把驱动接进 RK3288 内核解压、落位和 Kconfig2.1 解包先看目录别急着跑 install.sh很多厂商给的 sensor 驱动包入口是一个 install.sh 或者 auto_build.sh。我一般不会直接去执行这个脚本因为这类脚本默认把文件拷贝到 SDK 的 kernel 目录覆盖范围可能远大于我们要的 ov2710.c 和 xc6130.c。一旦它把 dts、config、HAL 一起覆盖掉后面翻车了都不知道是哪一步动的手。先把它解压到一个独立目录看一遍真实结构mkdir -p ~/rk_drv_xc6130 tar -xzf xc6130_ov2710_driver.tar.gz -C ~/rk_drv_xc6130 find ~/rk_drv_xc6130 -maxdepth 3 -type f | sort这里-C指把压缩包释放到~/rk_drv_xc6130不污染当前内核源码树find -maxdepth 3只看前两层文件足够判断包里是完整 Android 工程还是纯内核补丁。大部分驱动包是后者常见的会包含ov2710.c、ov2710.h、xc6130.c以及一个用于参考的.dts片段或 README。随后打开 README 或 Makefile 看它的编译方式。如果 README 里写了“MIPI 2 lane / 1080P30fps”这类字样说明它默认按标准的 OV2710 输出做如果写了“使用 GPIO0_C1 做复位”这一类平台相关参数说明它还需要和板子本身的 pinctrl 对齐。2.2 把源文件放进 kernel/drivers/media/video并接进 Kconfig/MakefileRK3288 的 Android 7.1 SDK 里sensor 类驱动的位置通常在内核的drivers/media/video/少数定制 BSP 会挪到drivers/media/platform/rockchip/camera/。判断依据很简单看 SDK 内核中已经存在的 sensor 驱动放哪就放哪。我这边常用路径是kernel/drivers/media/video/照它放不会错。KSRC~/rk3288_7.1/kernel cd ~/rk_drv_xc6130 cp -a ov2710.c ov2710.h $KSRC/drivers/media/video/ cp -a xc6130.c xc6130.h $KSRC/drivers/media/video/ grep -n ov2710\|xc6130 $KSRC/drivers/media/video/Makefile grep -n VIDEO_OV2710\|XC6130 $KSRC/drivers/media/video/Kconfig第一次执行时两个 grep 多半没有输出因为 Kconfig 和 Makefile 里还没加这一项。这时不要用“把某文件替换成同名的另一个”这种偷懒方式因为不同 BSP 会冲突。正确做法是在现有文件末尾追加一个独立的配置块cat $KSRC/drivers/media/video/Kconfig EOF config VIDEO_OV2710_XC6130 tristate OV2710 sensor with XC6130 companion depends on VIDEO_V4L2 I2C ARCH_ROCKCHIP help This is a camera sensor module using OV2710 and XC6130. EOF cat $KSRC/drivers/media/video/Makefile EOF obj-$(CONFIG_VIDEO_OV2710_XC6130) ov2710_xc6130.o ov2710_xc6130-objs : ov2710.o xc6130.o EOF这里的逻辑我重点讲一下ov2710_xc6130-objs把两个 .o 合成一个独立模块是为了让xc6130.c里的供电和时序函数只服务于 ov2710两个文件一起编译避免出现符号被别的 sensor 驱动误用的情况。如果你坚持obj-m ov2710.o xc6130.o分开编那么 xc6130 导出的符号会被当作通用 PMU 驱动后面的 insmod 顺序会变成玄学。编译前确认配置项已经开启。如果是整体打包进内核建议直接放ycd $KSRC make ARCHarm rockchip_defconfig grep VIDEO_OV2710_XC6130 .config如果 grep 看不到y就手动在arch/arm/configs/rockchip_defconfig末尾加一行CONFIG_VIDEO_OV2710_XC6130y再重新生成 .config。否则后面make menuconfig会按默认值落成mAndroid 的 rootfs 里没有模块加载器系统启动时根本不加载你的 .ko图像自然出不来。2.3 头文件、平台宏和 GPIO 的静态检查代码落位后先别急着编译。sensor 驱动大多是厂商从小平台搬过来的里面有大量#include mach/xxx.h和gpio_xxx()旧接口。RK3288 的 Android 7.1 内核已经全面切到设备树和gpiod_*/gpio_set_value接口直接编译会报几十个错。先做一轮静态检查grep -n include.*mach/ $KSRC/drivers/media/video/ov2710.c grep -n include.*mach/ $KSRC/drivers/media/video/xc6130.c grep -n gpio_request\|gpio_free $KSRC/drivers/media/video/ov2710.c看到mach/board.h、mach/gpio.h这类头文件直接把它们删掉改用linux/gpio.h和linux/gpio/consumer.h。而gpio_request这一类老接口在 RK3288 4.6、4.4 内核里虽然还存在但它不认设备树里通过pinctrl-0申请过的 pin会造成申请冲突。我习惯的做法是把复位、电源控制全部改成设备树节点在probe里用devm_gpiod_get取句柄。另一个要检查的地方是 xc6130 的 I2C 地址。xc6130 作为 companion 芯片驱动里多半会写死一个 device address例如 0x11 或 0x12。不要只信驱动里的注释要拿模组原理图或者模组厂家邮件确认 7-bit I2C 地址。I2C 地址错位的表现很迷惑它不会立即报错而是在ov2710_probe里回读 chip ID 时得到 0x00然后被当成“硬件未连接”。静态检查通过后再执行编译范围尽量小cd $KSRC make ARCHarm CROSS_COMPILEarm-linux-android- names...这里只编译内核映像个 image 即可。RK3288 的 kernel 编出boot.img后还需要单独打包进resource.img这部分放到后面提到固件打包时再说。第一次编译如果 OV2710 寄存器表里的数组定义很大不必担心那是正常的几百行{0x12, 0x80}形式的配置表是 OmniVision 驱动的传统风格。3. 设备树OV2710 和 XC6130 的平台参数3.1 在 RK3288 的设备树里声明 ov2710 节点RK3288 上的 Camera 一般挂在一路 I2C 上常见是 I2C2 或 I2C4。在板级 dts 里找到那一路 i2c 节点追加 ov2710 子节点i2c2 { status okay; clock-frequency 400000; ov2710: ov271036 { compatible ovti,ov2710; reg 0x36; pinctrl-names default; pinctrl-0 cam0_rst, cam0_pwdn; reset-gpios gpio2 RK_PB2 GPIO_ACTIVE_LOW; pwdn-gpios gpio2 RK_PB3 GPIO_ACTIVE_HIGH; clocks cru SCLK_CAMERA0; clock-names xvclk; clock-frequency 24000000; rockchip,camera-module-index 0; rockchip,camera-module-facing back; avdd-supply vcc2v8_cam; dovdd-supply vcc1v8_cam; dvdd-supply vcc1v2_cam; }; };reg 0x36这里先说明一下这个是 7-bit I2C 地址的常见示例值不同模组会把 SID 引脚拉到不同电平实际要用i2cdetect探测为准我会在后面的排查章节再展开。clocks里的SCLK_CAMERA0是 RK3288 的 camera 参考时钟频率默认给 24MHzOV2710 能接收的 xvclk 范围通常是 6MHz 到 27MHz24MHz 是最稳妥值。avdd/dovdd/dvdd三个 supply 是否需要写取决于 xc6130 的控制方式。如果 xc6130 通过 I2C 寄存器控制内部 LDO那这行可以不加让 xc6130 驱动自己调如果板子上用的是独立 LDO需要在内核里找到对应 regulator 节点。二者不要重复配置否则两个驱动会争抢同一路电源。3.2 xc6130 节点与上下电时序xc6130 在设备树里不是 sensor是 sensor 的配套芯片所以它挂在同一个 I2C 总线但代表一个独立的从设备xc6130: xc613011 { compatible xc,6130; reg 0x11; status okay; };在很多模组里xc6130 实际是一个连续输出的时钟发生器和电源管理芯片。它的工作方式是主控上电后先给 xc6130 写寄存器让它提供 24MHz 参考时钟并建立好 2.8V/1.8V/1.2V 三路电压再触发 OV2710 复位最后才去读 sensor ID。因此ov2710.c的power_on函数里要按顺序调用 xc6130 的操作函数而不是直接拉 GPIOstatic int ov2710_power_on(struct ov2710_priv *priv) { int ret; /* 先让 xc6130 输出 24MHz xvclk并建立 DOVDD 1.8V */ ret xc6130_on(); if (ret) return ret; usleep_range(10000, 20000); /* OV2710 复位信号从低到高拉高后等待内部 PLL 稳定 */ gpiod_set_value_cansleep(priv-reset_gpio, 0); usleep_range(5000, 10000); gpiod_set_value_cansleep(priv-reset_gpio, 1); usleep_range(20000, 30000); return 0; }这一段是结构示意重点看顺序xc6130_on()必须在复位释放之前完成。如果先给 sensor 复位再开时钟OV2710 内部会检测不到 xvclk芯片 ID 可能读到但后续 MIPI 信号会一直不稳定。xc6130 关闭的顺序反过来先拉低复位再关 xc6130。热切换摄像头时这个顺序比想象中敏感。RK3288 的 Android 框架在切换前后两个预览 session 时会调power_off如果顺序错第二路预览就可能黑屏。3.3 MIPI CSI-2 的 endpoint 与时钟参数OV2710 输出是并行或者 MIPI CSI-2RK3288 方案里通常走 MIPI 2-lane。设备树里要定义 sensor 端和 PHY 端的连接关系port { ov2710_ep: endpoint { remote-endpoint mipi_dphy0_ep; >i2cdetect -y 2 i2cdetect -y 4如果扫到地址是 0x6c而驱动写的是 0x368-bit 和 7-bit 是一回事0x36 1 0x6c。把驱动地址宏改成 0x36 后再读到 chip ID 0x2710就说明地址问题解决了。4.2 probe 成功但 dmesg 里没有 MIPI 中断现象cat /sys/kernel/debug/gpio能看到复位引脚状态正常sensor chip ID 读到了但isr一次都不触发多路摄像头视频流起不来。原因最常见的是 MIPI CSI 的>frame_rate xvclk / (HTS * VTS)注意寄存器值是 16-bit 大端格式低字节和高字节不要反。如果算出来偏差超过 5%优先改时钟源配置而不是硬调 VTS因为 VTS 调太大会压缩曝光范围暗光下画面会噪点爆炸。4.5 热启动时 probe 偶尔失败现象冷启动每次都能出图但 Android 上执行reboot后有 30% 概率黑屏必须断电再开才正常。原因OV2710 模组上的大电容没有完全放电power_off了但电压还维持在 1.5V 左右。下次 probe 时复用 I2C 的 xc6130 读到的是一个半初始化状态的 sensorchip ID 可能读到 0x2710但寄存器表没被执行干净。解决在power_off里让 xc6130 先断 AVDD然后主动拉低 xvclk 输出并保持 50ms 以上放电。不要担心这 50ms 影响切换速度它换来的是热启动稳定性。这个坑我在量产 RK3288 点歌机主板时遇到过不下十次随后把power_off里的usleep_range(50000, 60000)写成了固定流程的一部分再没黑屏过。5. 验证与进阶用 V4L2 工具和日志习惯收尾5.1 用 v4l2-ctl 确认驱动真正工作设备树和 Kconfig 都改完后不要急着打开 Android 相机应用先用 V4L2 工具确认内核侧状态。在 RK3288 的 Android shell 里跑v4l2-ctl -d /dev/video0 --list-formats v4l2-ctl -d /dev/video0 --get-fmt-video--list-formats列出内核驱动支持的像素格式如果里面只有YUYV而没有NV21说明驱动没有做格式转换HAL 层要按实际能力去接。--get-fmt-video能直接看到当前分辨率和四字符编码这一步排除 HAL 和 framework 黑匣子问题比看 logcat 更快。还可以配合media-ctl查看 pipelinemedia-ctl -d /dev/media0 -pRK3288 的 media controller 会把ov2710、mipi_dphy、isp、mipi_vdev四个 entity 串在一条链路上。如果缺了任何一个节点Android 的 Camera HAL 就会卡在open阶段预览不出来。刷完驱动我先跑这条命令看到xc6130节点正常挂在 i2c 总线上才继续往下调。5.2 一个值得坚持的习惯先量波形再改寄存器这是我想强调的最后一件事。OV2710 这类 sensor 的驱动看起来是一张几百行的寄存器表但真正出问题的地方通常在看不到的时序里。遇到黑屏或花屏我习惯先用示波器量三个点xc6130 输出的 xvclk 是否稳定 24MHz、reset 引脚的高低电平是否干净、MIPI lane 上有没有数据包。这些量完只剩两种可能寄存器配置表与模组不对或者 PHY 硬件连接有断线。不做波形检查就直接调 VTS/HTS只会把问题压到别的场景。示波器量完后把每个测量点的频率和幅值记录到一个本地文件里下次换同一模组批次时拿出来比对基线。这个小习惯帮我省过很多无意义的寄存器改动。希望帮到你。本文还有配套的精品资源点击获取