相机开发指南
本文主要介绍 SpacemiT K1 平台 Camera 模块的快速上手开发。
K1 仅支持 MIPI 类型接口,使用 SpacemiT camera 驱动框架。
Camera 快速点亮导览
点亮已支持的摄像头(两步)
第一步:确定摄像头接口并运行命令 确定摄像头连接的 MIPI CSI 接口(如 CSI1),运行以下命令(以 CSI1 为例):
cam-test /usr/share/camera_json/csi1_camera_detect.json
如果成功,如下示例输出,系统会自动生成可用的 JSON 文件到 /usr/share/camera_json/ 目录。如果失败,说明没有支持此摄像头,或者硬件有问题,建议联系进迭时空的技术支持。
......
I: ./sensors/cam_sensors_module.c(235): "detect ov16a10_spm sensors in csi1: success, set 3840x2160 to 1920x1080"
I: auto_detect_camera(1401): "auto detect sensor ===================== finish "
I: update_json_file(672): "save json to /usr/share/camera_json/csi1_camera_auto.json success"
从上述运行 log 还可以得出:
- ov16a10 sensor 生成的 json 默认使用模式 0
- sensor 输出分辨率为 3840x2160
- isp 输出分辨率为 1920x1080
json 配置文件的更多描述,请参阅下文的 JSON 参数说明。
第二步:启动摄像头出图测试
运行下列命令,启动摄像头出图 500 帧,并保存第 250 帧。
cam-test /usr/share/camera_json/csi1_camera_auto.json
- 正常运行的输出 log 请参阅 正常运行单路在线测试 log 章节
- 如果运行失败,建议联系进迭时空的技术支持
第  三步(可选):屏幕预览
如果摄像头需要实现屏幕预览,可以参考 gstreamer_user_guide 文档里的摄像头应用章节里的 MIPI 摄像头说明。
点亮一款新的摄像头
通常仅需要调整 cam-test 应用层的代码即可快速支持,所有 camera 相关的内核配置、DTS 无需修改。
点亮 sensor 所依赖的上下电 GPIO、MCLK 时钟、MIPI lane 配置等硬件功能,在方案对外发布前已由内部工程师验证完毕。极少数情况下需要修改 DTS 和驱动(如因外部不可抗拒原因必须修改主板 MIPI CSI 接口电路,上电 GPIOA 更改为 GPIOB,MCLKA 更改为 MCLKB 等),此情况下建议联系进迭工程师支持。
新摄像头点亮步骤
如果不考虑特殊情况,点亮一款新摄像头,建议按照以下步骤展开:
- 
复用相近型号代码 - 根据当前摄像头型号,复用列表中已支持的相近型号的应用代码
- 主要复用摄像头应用的代码结构排布(减少开发工作量)
- 修改函数名称、结构体名称为当前摄像头型号
- 详情参阅本文里的 Bring up 章节
 
- 
配置传感器参数 - 阅读摄像头数据手册,确定:
- 寄存器位数
- I2C 地址
- 上电流程
- ID 寄存器及 ID 值
 
- 修改 sensor 应用代码
- 上电流程可参阅本文里的 [Sensor 驱动] 章节
 
- 阅读摄像头数据手册,确定:
- 
配置寄存器参数 - 配置 setting tab 寄存器数组
- 根据原厂提供的信息或计算值,确定:
- lane 数 / HTS / VTS / MCLK / FPS / PCLK / 分辨率 / data Lane 等
 
- 完善函数内容(重点关注 xxx_spm_get_sensor_capbility和xxx_spm_get_sensor_work_info函数)
 
- 
调整寄存器地址 - 修改 xxx_sensor.c中的曝光、增益等寄存器地址
 
- 修改 
- 
读 ID 测试 - 尝试上电读 ID
- 如果失败,重新检查步骤 1
 
- 
出图测试 - 使用 single online test测试(参阅本文里的 场景介绍 章节
- 如果失败,可使用 only viisp case再测试
- 仍失败则检查步骤 3、4,或联系工程师分析
 
- 使用 
- 
验证 log - single online test正常出图的 log 可参阅本文里的 实操 log 章节
 
备注:
关于测试应用及各 test 的介绍,可参阅本文里的 场景介绍 章节。
参考文档
- 
Camera 模块规格特性 
 芯片规格说明书
- 
ISP 效果调试 
 ISP PQ 工具用户指南
- 
ISP API 开发 
 ISP API 开发指南
Camera 子系统硬件框图

核心功能模块说明:
- 
SENSOR(图像传感器) - 将从镜头传导过来的光线转换为电信号,再通过内部的 AD 转换为数字信号,最终输出 MIPI RAW 数据。
 
- 
CCIC(CMOS Camera Image Controller) - 解析接收 Sensor 发送的 MIPI 数据。
 
- 
IDI(ISP 数据输入模块) - 接收 CCIC 发送的数据或者从 DDR 读取数据,发送到 ISP Pipeline
- 同时将 CCIC 数据转存至 DDR
 
- 
ISP-PIPE(图像处理流水线) - ISP 硬件内部 pipeline
- 进行一系列图像相关算法的处理
 
- 
ISP-FORMAT(输出格式控制) - ISP 硬件内部模块
- 控制输出的图像格式
 
- 
ISP-DMA(直接内存访问) - ISP 硬件内部模块
- 将图像输出到 DDR 中
 
- 
CPP(后处理单元) - 图像降噪处理和边缘增强。
 
系统数据流说明
原始光信号 → SENSOR(光电转换)→ CCIC(数据接收)→ IDI(数据路由)→ ISP-PIPE(图像处理)→ ISP-FORMAT(格式转换)→ ISP-DMA(内存写入)→ CPP(后处理)→ 最终输出
Camera 驱动框架
说明:
本章节内容仅需了解即可,实际开发中除 Sensor 驱动部分外,其他内容在 sensor bring up 时基本不会涉及。
框架简介
SpacemiT camera 驱动基于 Linux 内核 V4L2 框架实现,主要功能包括:
- 硬件寄存器访问
- 中断响应处理
- 缓冲区与事件管理
- 用户空间 SDK 接口提供
在 Camera 子系统中各个模块之间的关系如下图所示:

从软件调用关系来看,从上到下依次分为以下三层:
- 
用户空间(Userspace):运行在用户空间。 - 主要包括 ISP、CPP、VI 和 tuningtools 软件库,以及 ISP、CPP 的 firmware 库和 sensor 模块的源码。
- 用户主要通过调用 ISP、CPP、VI 和 sensor 模块的接口来实现 camera 应用场景。Firmware 库中的接口由 ISP 和 CPP 软件库在内部调用。
- 另外,如果用户需要使用 ASR 的 tuning tool 来调试 ISP/CPP 的输出图像效果,需要在应用程序中调用 libtuningtools.so的接口来创建 tuning server。
 
- 
内核空间(Kernel Space): - 运行在内核空间。
- 主要提供 ISP、CPP、VI、CCIC 和 sensor 的驱动。
 
- 
硬件层(Hardware Layer): - 这是驱动实际 调用的硬件模块。
 
对于 sensor bring up 需求,主要关注用户空间的 APP demo 实现,即如何调用 SDK 接口满足场景需求。
源码结构
~/k1x/linux-6.6/drivers/media/platform/spacemit/camera$ tree
.
|-- built-in.a
|-- cam_ccic
|   |-- ccic_drv.c
|   |-- ccic_drv.h
|   |-- ccic_hwreg.c
|   |-- ccic_hwreg.h
|   |-- csiphy.c
|   |-- csiphy.h
|   |-- dptc_drv.c
|   |-- dptc_drv.h
|   `-- dptc_pll_setting.h
|-- cam_cpp 
|   |-- cpp_compat_ioctl32.c
|   |-- cpp_compat_ioctl32.h
|   |-- cpp_dmabuf.c
|   |-- cpp_dmabuf.h
|   |-- cpp_iommu.c
|   |-- cpp_iommu.h
|   |-- cpp-v2p0.c
|   |-- k1x_cpp.c
|   |-- k1x_cpp.h
|   |-- regs-cpp-iommu.h
|   |-- regs-cpp-v2p0.h
|   `-- regs-fbc-v2p0.h
|-- cam_isp
|   |-- k1x_isp_drv.c
|   |-- k1x_isp_drv.h
|   |-- k1x_isp_pipe.c
|   |-- k1x_isp_pipe.h
|   |-- k1x_isp_reg.c
|   |-- k1x_isp_reg.h
|   |-- k1x_isp_statistic.c
|   `-- k1x_isp_statistic.h
|-- cam_plat
|   |-- cam_plat.c
|   `-- cam_plat.h
|-- cam_sensor
|   |-- cam_sensor.c
|   `-- cam_sensor.h
|-- cam_util
|   |-- cam_dbg.c
|   `-- cam_dbg.h
|-- Kconfig
|-- Makefile
|-- modules.order
`-- vi
    |-- cam_block.c
    |-- cam_block.h
    |-- k1xvi
    |   |-- fe_isp.c
    |   |-- fe_isp.h
    |   |-- hw-seq
    |   |   |-- hw_ccic.c
    |   |   |-- hw_ccic.h
    |   |   |-- hw_dma.c
    |   |   |-- hw_dma.h
    |   |   |-- hw_iommu.c
    |   |   |-- hw_iommu.h
    |   |   |-- hw_isp.c
    |   |   |-- hw_isp.h
    |   |   |-- hw_postpipe.c
    |   |   |-- hw_postpipe.h
    |   |   |-- hw_reg.h
    |   |   `-- hw_reg_iommu.h
    |   |-- k1xvi.c
    |   `-- k1xvi.h
    |-- mlink.c
    |-- mlink.h
    |-- spacemit_videobuf2.h
    |-- subdev.c
    |-- subdev.h
    |-- vdev.c
    |-- vdev.h
    |-- vsensor.c
    `-- vsensor.h