全志Tina Linux Camera 摄像头模块开发指南 全网最详细版本支持百问网T113-Pro DongshanPI-NezhaD1-H DongshanPI-D1s V853-Pro等开发板

Posted 韦东山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全志Tina Linux Camera 摄像头模块开发指南 全网最详细版本支持百问网T113-Pro DongshanPI-NezhaD1-H DongshanPI-D1s V853-Pro等开发板相关的知识,希望对你有一定的参考价值。





1 概述

编写目的:介绍camera 模块在sunxi 平台上的开发流程。

适用范围:本文档目前适用于tina3.0 以上具备camera 的硬件平台。

2 模块介绍

2.1 模块功能介绍

用于接收并行或者mipi 接口的sensor 信号或者是bt656 格式的信号。

2.2 硬件介绍

目前Tina 系统的各平台camera 硬件接口、linux 内核版本以及camera 驱动框架如下表所示:

表2-1: 平台CSI 框架
平台支持接口是否具备ISP模块linux 内核版本camera 驱动框架
F35并口csi、mipi3.4VFE
R16并口csi3.4VFE
R18并口csi4.4VFE
R30并口csi4.4VFE
R40并口csi3.10VFE
R311mipi csi4.9VIN
MR133mipi csi4.9VIN
R818mipi csi4.9VIN
MR813mipi csi4.9VIN
R528并口csi5.4VIN
V536并口csi、mipi4.9VIN
V533并口csi、mipi4.9VIN
V831并口csi、mipi4.9VIN
V833并口csi、mipi4.9VIN
V851并口csi、mipi4.9VIN
V853并口csi、mipi4.9VIN

注意:

  1. 如果平台没有ISP 模块,那么将不支持RAW sensor(即sensor 只输出采集到的原始数据),文档中提到的RAW 等相关信息不用理会;
  2. 如果平台没有支持mipi 接口,文档中提到的mipi 相关信息忽略;
  3. 不同平台可能将使用不同的camera 驱动框架,这点注意区分;

2.3 源码结构介绍

2.3.1 linux3.4 VFE 框架

驱动路径位于linux-3.4/drivers/media/video/sunxi-vfe 下。

sunxi-vfe:.
│ bsp_common.c ;底层bsp共用的函数
│ bsp_common.h ;底层bsp共用函数头文件
│ config.c ;读取sys_config.fex的参数配置和isp参数
│ config.h ;读取sys_config.fex和isp参数函数的头文件
│ Kconfig
│ Makefile
│ platform_cfg.h ;区分各个平台的头文件
│ vfe.c ;v4l2驱动实现主体(包含视频接口和ISP部分)
│ vfe.h ;v4l2驱动头文件
│ vfe_os.c ;系统资源函数实现(pin,clock,memory)
│ vfe_os.h ;系统资源函数头文件
│ vfe_subdev.c ;sensor调用vfe资源函数
│ vfe_subdev.h ;sensor 调用vfe资源函数头文件
│
├─actuator
│ actuator.c ;vcm driver的一般行为
│ actuator.h ;vcm driver的头文件
│ dw9714_act.c ;具体vcm driver型号实现
│ Makefile
│
├─csi
│ bsp_csi.c ;底层csi bsp函数
│ bsp_csi.h ;底层csi bsp函数头文件
│ csi_reg.c ;csi硬件底层实现
│ csi_reg.h ;csi硬件底层实现头文件
│ csi_reg_i.h ;csi 寄存器资源头文件
│
├─device
│ camera.h ;camera公用结构体头文件
│ camera_cfg.h ;camera ioctl扩展命令头文件
│ Makefile
│ ov5640.c ;具体的sensor驱动
│
├─flash_light
│ flash.h ;led补光灯驱动头文件
│ flash_io.c ;led补光灯io控制实现
│ Makefile
│
├─lib
│ bsp_isp.h ;底层isp bsp函数头文件
│ bsp_isp_algo.h ;底层isp 算法bsp函数头文件
│ bsp_isp_comm.h ;底层isp共用函数头文件
│ isp_module_cfg.h ;isp里面各模块功能配置的头文件
│ libisp ;isp的函数库
│ lib_mipicsi2_v1 ;A31mipi库
│ lib_mipicsi2_v2 ;A80/A83mipi库
├─csi_cci
│ cci_helper.c ;cci 与设备相关初始化、注册以及通信等相关函数集实现
│ cci_helper.h ;cci 与设备相关初始化、注册以及通信等相关函数集实现头文件
│ bsp_cci.c ;cci 操作函数集实现
│ bsp_cci.h ;cci 操作函数集头文件
│ csi_cci_reg.c ;cci 底层实现
│ csi_cci_reg.h ;cci 底层实现头文件
│ csi_cci_reg_i.h ;cci寄存器资源头文件
│
├─mipi_csi
│ bsp_mipi_csi.c ;底层mipi bsp函数
│ bsp_mipi_csi.h ;底层mipi bsp函数头文件
│
└─utility
cfg_op.c ;读取ini文件的实现函数
cfg_op.h ;读取ini文件函数对应的头文件

2.3.2 linux3.10 VFE 框架

驱动路径位于linux-3.10/drivers/media/platform/sunxi-vfe 下。

sunxi-vfe:.
│ bsp_common.c ;底层bsp共用的函数
│ bsp_common.h ;底层bsp共用函数头文件
│ config.c ;读取sys_config.fex的参数配置和isp参数
│ config.h ;读取sys_config.fex和isp参数函数的头文件
│ Kconfig
│ Makefile
│ platform_cfg.h ;区分各个平台的头文件
│ vfe.c ;v4l2驱动实现主体(包含视频接口和ISP部分)
│ vfe.h ;v4l2驱动头文件
│ vfe_os.c ;系统资源函数实现(pin,clock,memory)
│ vfe_os.h ;系统资源函数头文件
│ vfe_subdev.c ;sensor调用vfe资源函数
│ vfe_subdev.h ;sensor 调用vfe资源函数头文件
│
├─actuator
│ actuator.c ;vcm driver的一般行为
│ actuator.h ;vcm driver的头文件
│ dw9714_act.c ;具体vcm driver型号实现
│ Makefile
│
├─csi
│ bsp_csi.c ;底层csi bsp函数
│ bsp_csi.h ;底层csi bsp函数头文件
│ csi_reg.c ;csi硬件底层实现
│ csi_reg.h ;csi硬件底层实现头文件
│ csi_reg_i.h ;csi 寄存器资源头文件
│
├─device
│ camera.h ;camera公用结构体头文件
│ camera_cfg.h ;camera ioctl扩展命令头文件
│ Makefile
│ ov5640.c ;具体的sensor驱动
│
├─flash_light
│ flash.h ;led补光灯驱动头文件
│ flash_io.c ;led补光灯io控制实现
│ Makefile
│
├─lib
│ bsp_isp.h ;底层isp bsp函数头文件
│ bsp_isp_algo.h ;底层isp 算法bsp函数头文件
│ bsp_isp_comm.h ;底层isp共用函数头文件
│ isp_module_cfg.h ;isp里面各模块功能配置的头文件
│ libisp ;isp的函数库
│ lib_mipicsi2_v1 ;A31mipi库
│ lib_mipicsi2_v2 ;A80/A83mipi库
├─csi_cci
│ cci_helper.c ;cci 与设备相关初始化、注册以及通信等相关函数集实现
│ cci_helper.h ;cci 与设备相关初始化、注册以及通信等相关函数集实现头文件
│ bsp_cci.c ;cci 操作函数集实现
│ bsp_cci.h ;cci 操作函数集头文件
│ csi_cci_reg.c ;cci 底层实现
│ csi_cci_reg.h ;cci 底层实现头文件
│ csi_cci_reg_i.h ;cci寄存器资源头文件
│
├─mipi_csi
│ bsp_mipi_csi.c ;底层mipi bsp函数
│ bsp_mipi_csi.h ;底层mipi bsp函数头文件
│
└─utility
cfg_op.c ;读取ini文件的实现函数
cfg_op.h ;读取ini文件函数对应的头文件

2.3.3 linux4.4 VFE 框架

驱动路径位于linux-4.4/drivers/media/platform/sunxi-vfe 下。

sunxi-vfe:.
│ bsp_common.c ;底层bsp共用的函数
│ bsp_common.h ;底层bsp共用函数头文件
│ config.c ;读取sys_config.fex的参数配置和isp参数
│ config.h ;读取sys_config.fex和isp参数函数的头文件
│ Kconfig
│ Makefile
│ platform_cfg.h ;区分各个平台的头文件
│ vfe.c ;v4l2驱动实现主体(包含视频接口和ISP部分)
│ vfe.h ;v4l2驱动头文件
│ vfe_os.c ;系统资源函数实现(pin,clock,memory)
│ vfe_os.h ;系统资源函数头文件
│ vfe_subdev.c ;sensor调用vfe资源函数
│ vfe_subdev.h ;sensor 调用vfe资源函数头文件
│
├─actuator
│ actuator.c ;vcm driver的一般行为
│ actuator.h ;vcm driver的头文件
│ dw9714_act.c ;具体vcm driver型号实现
│ Makefile
│
├─csi
│ bsp_csi.c ;底层csi bsp函数
│ bsp_csi.h ;底层csi bsp函数头文件
│ csi_reg.c ;csi硬件底层实现
│ csi_reg.h ;csi硬件底层实现头文件
│ csi_reg_i.h ;csi 寄存器资源头文件
│
├─device
│ camera.h ;camera公用结构体头文件
│ camera_cfg.h ;camera ioctl扩展命令头文件
│ Makefile
│ ov5640.c ;具体的sensor驱动
│
├─flash_light
│ flash.h ;led补光灯驱动头文件
│ flash_io.c ;led补光灯io控制实现
│ Makefile
│
├─lib
│ bsp_isp.h ;底层isp bsp函数头文件
│ bsp_isp_algo.h ;底层isp 算法bsp函数头文件
│ bsp_isp_comm.h ;底层isp共用函数头文件
│ isp_module_cfg.h ;isp里面各模块功能配置的头文件
│ libisp ;isp的函数库
│ lib_mipicsi2_v1 ;A31mipi库
│ lib_mipicsi2_v2 ;A80/A83mipi库
├─csi_cci
│ cci_helper.c ;cci 与设备相关初始化、注册以及通信等相关函数集实现
│ cci_helper.h ;cci 与设备相关初始化、注册以及通信等相关函数集实现头文件
│ bsp_cci.c ;cci 操作函数集实现
│ bsp_cci.h ;cci 操作函数集头文件
│ csi_cci_reg.c ;cci 底层实现
│ csi_cci_reg.h ;cci 底层实现头文件
│ csi_cci_reg_i.h ;cci寄存器资源头文件
│
├─mipi_csi
│ bsp_mipi_csi.c ;底层mipi bsp函数
│ bsp_mipi_csi.h ;底层mipi bsp函数头文件
│
└─utility
cfg_op.c ;读取ini文件的实现函数
cfg_op.h ;读取ini文件函数对应的头文件

2.3.4 linux4.4 VIN 框架

驱动路径位于linux-4.4/drivers/media/platform/sunxi-vin 下。

sunxi-vin:
│ vin.c ;v4l2驱动实现主体(包含视频接口和ISP部分)
│ vin.h ;v4l2驱动头文件
│ top_reg.c ;vin对各v4l2 subdev管理接口实现主体
│ top_reg.h ;管理接口头文件
│ top_reg_i.h ;vin模块接口层部分结构体
│
├─modules
│ ├─actuator
│ │ actuator.c ;vcm driver的一般行为
│ │ actuator.h ;vcm driver的头文件
│ │ dw9714_act.c ;具体vcm driver型号实现
│ │ Makefile
│ ├─flash
│ │ flash.h ;led补光灯驱动头文件
│ │ flash_io.c ;led补光灯io控制实现
│ ├─sensor
│ │ camera.h ;camera公用结构体头文件
│ │ camera_cfg.h ;camera ioctl扩展命令头文件
│ │ sensor_helper.c ;sensor公用操作接口函数文件
│ │ sensor_helper.h ;sensor公用操作接口函数头文件
│ │ Makefile
│ │ ov5640.c ;具体的sensor驱动
│
├─platform
│ platform_cfg.h ;平台相关的配置接口
│
├─utility
│ bsp_common.h ;底层公用的格式配置函数头文件
│ bsp_common.c ;底层公用的格式配置函数文件
│ cfg_op.h ;解析配置文件接口头文件
│ cfg_op.c ;解析配置文件接口函数实现主体
│ config.h ;解析设备树的函数头文件
│ config.c ;解析设备树的接口函数主体
│ sensor_info.h ;sensor列表信息头文件
│ sensor_info.c ;获取sensor列表信息函数主体
│ vin_io.h ;vin框架io操作接口头文件
│ vin_io.c ;vin框架io操作接口文件
│ vin_os.h ;vin框架系统操作接口头文件
│ vin_os.c ;vin框架系统操作接口文件
│ vin_supply.h ;vin框架设置时钟频率等接口头文件
│ vin_supply.c ;vin框架设置时钟频率等接口函数主体
│
├─vin-cci
│ cci_helper.c ;cci 与设备相关初始化、注册以及通信等相关函数集实现
│ cci_helper.h ;cci 与设备相关初始化、注册以及通信等相关函数集实现头文件
│ bsp_cci.c ;cci 操作函数集实现
│ bsp_cci.h ;cci 操作函数集头文件
│ csi_cci_reg.c ;cci 底层实现
│ csi_cci_reg.h ;cci 底层实现头文件
│ csi_cci_reg_i.h ;cci寄存器资源头文件
│ sunxi_cci.c ;cci 接口封装实现
│ sunxi_cci.h ;cci 接口封装头文件
│
├─vin-csi
│ bsp_csi.c ;csi 操作函数集实现
│ bsp_csi.h ;csi 操作函数集头文件
│ csi_reg.c ;csi 底层实现
│ csi_reg.h ;csi 底层实现头文件
│ csi_reg_i.h ;csi寄存器资源头文件
│ parser_reg.c ;csi 底层实现
│ parser_reg.h ;csi 底层实现头文件
│ parser_reg_i.h ;csi寄存器资源头文件
│ sunxi_csi.c ;csi 接口封装实现
│ sunxi_csi.h ;csi 接口封装头文件
│
├─vin-isp
│ bsp_isp.c ;isp操作函数集实现
│ bsp_isp.h ;isp操作函数集头文件
│ bsp_isp_comm.h ;isp结构体定义
│ isp_default_tbl.h ;isp默认配置列表
│ isp_platform_drv.h ;isp平台操作集头文件
│ isp_platform_drv.c ;isp平台操作集实现
│ sunxi_isp.h ;sunxi平台isp操作集头文件
│ sunxi_isp.c ;sunxi平台isp操作集实现
│
├─vin-mipi
│ bsp_mipi_csi.c ;底层mipi bsp函数
│ bsp_mipi_csi.h ;底层mipi bsp函数头文件
│ bsp_mipi_csi_v1.c ;sunxi平台底层mipi bsp接口函数
│ sunxi_mipi.c ;sunxi平台mipi实现
│ bsp_mipi_csi.h ;sunxi平台mipi实现头文件
│ combo_common.c ;combo common头文件
│ protocol.h ;protocol头文件
├─vin-stat
│ vin_h3a.c ;vin 3a操作函数
│ vin_h3a.h ;vin 3a操作函数头文件
│ vin_ispstat.c ;sunxi isp stat操作函数
│ vin_ispstat.h ;sunxi isp stat操作函数头文件
│
├─vin-video
│ dma_reg.c ;csi模块dma操作函数
│ dma_reg.h ;csi模块dma操作函数头文件
│ dma_reg_i.h ;csi dma寄存器资源头文件
│ vin_core.c ;vin video核心函数
│ vin_core.h ;vin video核心函数头文件
│ vin_video.c ;vin video设备接口函数
│ vin_video.h ;vin video设备接口函数头文件
├─vin-vipp
│ sunxi_scaler.c ;scaler 子设备操作函数集
│ sunxi_scaler.h ;caler 子设备操作函数头文件
│ vipp_reg.c ;vipp操作函数集
│ vipp_reg.h ;vipp操作函数集头文件
│ vipp_reg_i.h ;vipp操作函数集资源头文件

2.3.5 linux4.9 VIN 框架

驱动路径位于linux-4.9/drivers/media/platform/sunxi-vin 下。

sunxi-vin:
│ vin.c ;v4l2驱动实现主体(包含视频接口和ISP部分)
│ vin.h ;v4l2驱动头文件
│ top_reg.c ;vin对各v4l2 subdev管理接口实现主体
│ top_reg.h ;管理接口头文件
│ top_reg_i.h ;vin模块接口层部分结构体
├── modules
│ ├── actuator ;vcm driver
│ │ ├── actuator.c
│ │ ├── actuator.h
│ │ ├── dw9714_act.c
│ │ ├── Makefile
│ ├── flash ;闪光灯driver
│ │ ├── flash.c
│ │ └── flash.h
│ └── sensor ;sensor driver
│ ├── ar0144_mipi.c
│ ├── camera_cfg.h ;camera ioctl扩展命令头文件
│ ├── camera.h ;camera公用结构体头文件
│ ├── Makefile
│ ├── ov2775_mipi.c
│ ├── ov5640.c
│ ├── sensor-compat-ioctl32.c
│ ├── sensor_helper.c ;sensor公用操作接口函数文件
│ ├── sensor_helper.h
├── platform ;平台相关的配置接口
├── utility
│ ├── bsp_common.c
│ ├── bsp_common.h
│ ├── cfg_op.c
│ ├── cfg_op.h
│ ├── config.c
│ ├── config.h
│ ├── sensor_info.c
│ ├── sensor_info.h
│ ├── vin_io.h
│ ├── vin_os.c
│ ├── vin_os.h
│ ├── vin_supply.c
│ └── vin_supply.h
├── vin-cci
│ ├── sunxi_cci.c
│ └── sunxi_cci.h
├── vin-csi
│ ├── parser_reg.c
│ ├── parser_reg.h
│ ├── parser_reg_i.h
│ ├── sunxi_csi.c
│ └── sunxi_csi.h
├── vin-isp
│ ├── sunxi_isp.c
│ └── sunxi_isp.h
├── vin-mipi
│ ├── sunxi_mipi.c
│ └── sunxi_mipi.h
├── vin-stat
│ ├── vin_h3a.c
│ ├── vin_h3a.h
│ ├── vin_ispstat.c
│ └── vin_ispstat.h
├── vin_test
├── vin-video
│ ├── vin_core.c
│ ├── vin_core.h
│ ├── vin_video.c
│ └── vin_video.h
└── vin-vipp
├── sunxi_scaler.c
├── sunxi_scaler.h
├── vipp_reg.c
├── vipp_reg.h
└── vipp_reg_i.h

2.3.6 linux5.4 VIN 框架

驱动路径位于linux-5.4/drivers/media/platform/sunxi-vin 下。

sunxi-vin:
├── Kconfig
├── Makefile
├── modules
│ ├── actuator ;vcm driver
│ │ ├── actuator.c
│ │ ├── actuator.h
│ │ ├── dw9714_act.c
│ │ ├── Makefile
│ ├── flash ;flash driver
│ │ ├── flash.c
│ │ └── flash.h
│ ├── sensor ;cmos sensor driver
│ │ ├── camera_cfg.h
│ │ ├── camera.h
│ │ ├── gc0310_mipi.c
│ │ ├── Makefile
│ │ ├── ov2710_mipi.c
│ │ ├── ov5640.c
│ │ ├── sensor-compat-ioctl32.c
│ │ ├── sensor_helper.c
│ │ ├── sensor_helper.h
│ ├── sensor-list
│ │ ├── sensor_list.c
│ │ └── sensor_list.h
│ └── sensor_power ;sensor上下电接口函数
│ ├── Makefile
│ ├── sensor_power.c
│ └── sensor_power.h
├── platform
├── top_reg.c
├── top_reg.h
├── top_reg_i.h
├── utility ;驱动通用接口
│ ├── bsp_common.c
│ ├── bsp_common.h
│ ├── cfg_op.c
│ ├── cfg_op.h
│ ├── config.c
│ ├── config.h
│ ├── vin_io.h
│ ├── vin_os.c
│ ├── vin_os.h
│ ├── vin_supply.c
│ └── vin_supply.h
├── vin.c ;sunxi-vin驱动注册入口
├── vin-cci ;i2c操作相关接口
│ ├── bsp_cci.c
│ ├── bsp_cci.h
│ ├── cci_helper.c
│ ├── cci_helper.h
│ ├── Kconfig
│ ├── sunxi_cci.c
│ └── sunxi_cci.h
├── vin-csi ;csi操作相关接口
│ ├── sunxi_csi.c
│ └── sunxi_csi.h
├── vin.h
├── vin-isp ;isp驱动
│ ├── sunxi_isp.c
│ └── sunxi_isp.h
├── vin-mipi ;mipi驱动
│ ├── sunxi_mipi.c
│ └── sunxi_mipi.h
├── vin-stat
│ ├── vin_h3a.c
│ └── vin_h3a.h
├── vin-tdm
│ ├── vin_tdm.c
│ └── vin_tdm.h
├── vin-video ;video节点相关的接口定义
│ ├── vin_core.c
│ ├── vin_core.h
│ ├── vin_video.c
│ └── vin_video.h
└── vin-vipp
├── sunxi_scaler.c
├── sunxi_scaler.h

3 模块开发

3.1 模块体系结构描述

3.1.1 VFE 框架

• 使用过程中可简单的看成是vfe 模块+ device 模块+af driver + flash 控制模块的方式;

• vfe.c 是驱动的主要功能实现,包括注册/注销、参数读取、与v4l2 上层接口、与各device 的下层接口、中断处理、buffer 申请切换等;

• device 文件夹里面是各个sensor 的器件层实现,一般包括上下电、初始化,各分辨率切换,yuv sensor 包括绝大部分的v4l2 定义的ioctrl 命令的实现;而raw

sensor 的话大部分 ioctrl 命令在vfe 层调用isp 的库实现,少数如曝光/增益调节会透过vfe 层到实际器件层;

• actuator 文件夹内是各种vcm 的驱动;

• flash_light 文件夹内是闪光灯控制接口实现;

• csi 和mipi_csi 为对csi 接口和mipi 接口的控制文件;

• lib 文件夹为isp 的库文件;

• linux-3.0 前的版本相当于vivi.c+csi bsp 层

• linux-3.4 版本支持isp 驱动和双CSI

• linux-3.10 版本将mipi/csi/isp 模块化(由vfe.c 直接调用=>v4l2_subdev_ops), 支持device tree

图3-1: VFE

3.1.2 VIN 框架

• 使用过程中可简单的看成是vin 模块+ device 模块+af driver + flash 控制模块的方式;

• vin.c 是驱动的主要功能实现,包括注册/注销、参数读取、与v4l2 上层接口、与各device 的下层接口、中断处理、buffer 申请切换等;

• modules/sensor 文件夹里面是各个sensor 的器件层实现,一般包括上下电、初始化,各分辨率切换,yuv sensor 包括绝大部分的v4l2 定义的ioctrl 命令的实

现;而raw sensor 的话大部分ioctrl 命令在vin 层调用isp 库实现,少数如曝光/增益调节会透过vin 层到实际器件层;

• modules/actuator 文件夹内是各种vcm 的驱动;

• modules/flash 文件夹内是闪光灯控制接口实现;

• vin-csi 和vin-mipi 为对csi 接口和mipi 接口的控制文件;

• vin-isp 文件夹为isp 的库操作文件;

• vin-video 文件夹内主要是video 设备操作文件;

图3-2: VIN

3.1.3 Camera 通路框架

• VIN 支持灵活配置单/双路输入双ISP 多通路输出的规格

• 引入media 框架实现pipeline 管理

• 将libisp 移植到用户空间解决GPL 问题

• 将统计buffer 独立为v4l2 subdev

• 将的scaler(vipp)模块独立为v4l2 subdev

• 将video buffer 修改为mplane 方式,使用户层取图更方便

• 采用v4l2-event 实现事件管理

• 采用v4l2-controls 新特性

图3-3: camera Input

3.2 驱动模块实现

3.2.1 硬件部分

检查硬件电源,gpio 是否和原理图一致并且正确连接;检查sys_config.fex 或者board.dts 是否正确配置,包括使用的电源名称和电压,详见CSI 板级配置章节说

明;如果是电源选择有多个源头的请确认板子上的连接正确,比如0ohm 电阻是否正确的焊接为0ohm,NC 的电阻是否有正确断开等等。带补光灯的也需要检查

灯和driver IC 和控制io 是否连好。

3.2.2 内核device 模块驱动

一般调试新模组的话建议以sdk 中的某个现成的驱动为基础修改:YUV 的并口模组以R40 平台(linux3.10) 的ov5640.c 为参考。

下面以ov5640.c 为例说明调试新模组需要注意的两点:

  1. 添加Makefile
[linux-3.10/drivers/media/platform/sunxi-vfe/device/Makefile]
添加
obj-m + = ov5640.o (详见1)
详注:
1.具体取决于使用的模组,如果是新模组则将驱动代码放置在该device目录下。
  1. 配置模组参数

配置参数在linux-3.10/drivers/media/platform/sunxi-vfe/device/ov5640.c 中,只需注意下面两个参数。

#define SENSOR_NAME "ov5640" (详见1)
#define I2C_ADDR 0x78 (详见2)
详注:
1.该参数为模组名,必须和sys_config.fex的csi0_dev0_mname或者board.dts的sensor0_mname保持一致。
2.I2C_ADDR可参考相应模组的datasheet,sys_config.fex的csi0_dev0_twi_addr与此值保持一致。
3.2.2.1 驱动宏定义
#define MCLK (24*1000*1000)

sensor 输入时钟频率,可查看模组厂提供的sensor datasheet,datasheet 中会有类似inputclock frequency: 6~27 MHz 信息,这个信息说明可提供给sensor 的

MCLK 可以在6 M 到27 M之间。其中MCLK 和使用的寄存器配置强相关,在模组厂提供寄存器配置时,可直接询问当前配置使用的MCLK 频率是多少。

#define VREF_POL V4L2_MBUS_VSYNC_ACTIVE_LOW
#define HREF_POL V4L2_MBUS_HSYNC_ACTIVE_HIGH
#define CLK_POL V4L2_MBUS_PCLK_SAMPLE_RISING

并口sensor 必须填写,MIPI sensor 无需填写,可在sensor 规格书找到,如下

图3-4: timing

从上述的图像可得到以下信息:

  1. VSYNC 在低电平的时候,data pin 输出有效数据,所以VREF_POL 设置为V4L2_MBUS_VSYNC_ACTIVE_即低电平有效;

  2. HREF 在高电平的时候,data pin 输出有效数据,所以HREF_POL 设置为V4L2_MBUS_HSYNC_ACTIVE_即高电平有效;

  3. CLK_POL 则是表明SOC 是在sensor 输出的pclk 上升沿采集data pin 的数据还是下降沿采集数据,如果sensor 在pclk 上升沿改变data pin 的数据,那么SOC

应该在下降沿采集,CLK_POL 设置为V4L2_MBUS_PCLK_SAMPLE_FALLING;如果sensor在pclk 下降沿改变data pin 的数据,那么SOC 应该在上降沿采集,

CLK_POL 设置为V4L2_MBUS_PCLK_SAMPLE_RISING。

#define V4L2_IDENT_SENSOR 0x2770

一般填写sensor ID,用于sensor 检测。sensor ID 可在sensor 规格书的找到,如下

图3-5: sensorid
#define I2C_ADDR 0x6c

sensor I2C 通讯地址,可在sensor 规格书找到,如下

图3-6: sccbid
#define SENSOR_NAME OV5640

定义驱动名字,与系统其他文件填写的名字要一致,比如需要和sys_config.fex 中的sensorname 一致。

3.2.2.2 初始化代码
static struct regval_list sensor_default_regs[] = ; /* 填写寄存器代码的公共部分*/
static struct regval_list sensor_XXX_regs[] = ; /* 填写各模式的寄存器代码,不同的模式可以是分辨率、帧率等*/

上述部分的寄存器配置,公共部分可以忽略,直接在模式代码中配置sensor 即可,相应的寄存器配置,可让模组厂提供。

3.2.2.3 曝光增益接口函数
static int sensor_s_exp(struct v4l2_subdev *sd, unsigned int exp_val) /* 曝光函数*/
static int sensor_s_gain(struct v4l2_subdev *sd, unsigned int gain_val) /* 增益函数*/

AE 是同时控制曝光时间和增益的,所以需要在上面的函数中分别同时sensor 曝光和增益的寄存器。

图3-7: expgain

根据规格书中的寄存器说明,在相应的函数配置即可。若设置exp/gain 无效,可能的原因有:

• sensor 寄存器打开了AE;

• 设置值超出了有效范围

具体可根据模组厂提供的配置设置,如若检查之后设置仍失效,可与模组厂沟通,确认配置是否正确。

3.2.2.4 上下电控制函数
static int sensor_power(struct v4l2_subdev *sd, int on)

控制sensor 上电、下电及进出待机状态,操作步骤须与规格书描述相同,注意power down 和reset pin 的电平变化。

图3-8: powerup

驱动中,按照规格书的上电时序进行配置,而如果上电之后测量硬件并没有相应的电压,这时候
检查硬件和软件配置是否一致。关于csi 电源的配置,操作流程可如下:

  1. 先通过原理图确认sensor 模组的各路电源是连接到axp 的哪个ldo;
  2. 查看sys_config.fex 的regulator 配置,在相应的ldo 后增加相应的字段,比如“csi-vdd”等;
  3. 在sys_config.fex 的csi 部分,sensor 部分的电源后的字段再填写与上述一样的字段即可;
  4. 根据sensor 规格书的要求,填写相应的电压即可;

以上图为例,确认sensor 驱动中的上电时序。

static int sensor_power(struct v4l2_subdev *sd, int on)

    int ret;
    ret = 0;
    switch (on) 
    /* STBY_ON 和STBY_OFF 基本不使用,可忽略这两个选项的配置*/
    case STBY_ON:
        ...
        break;
    case STBY_OFF:
        ...
        break;
    /* 上电操作*/
    case PWR_ON:
        sensor_print("PWR_ON!\\n");
        cci_lock(sd);
        /* 将PWDN、RESET 引脚设置为输出*/
        vin_gpio_set_status(sd, PWDN, 1);
        vin_gpio_set_status(sd, RESET, 1);
        /* 按照上图知道,上电前PWDN、RESET 信号为低,所以将其设置为低电平*/
        vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
        vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
        /* 延时*/
        usleep_range(1000, 1200);
        /* CAMERAVDD 为SOC 中的供电电源,部分板子可以忽略该电源,
        * 因为有些板子会通过一个vcc-pe 给上拉电阻等供电,所以需要
        * 使能该路电,有些是直接和iovdd 共用了,所以有部分会忽略该
        * 路电源配置.
        */
        vin_set_pmu_channel(sd, CAMERAVDD, ON);
        /* 将PWDN 设置为高电平*/
        vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
        /*AF上电*/
        vin_set_pmu_channel(sd, AFVDD, ON);
        /* AVDD 上电*/
        vin_set_pmu_channel(sd, AVDD, ON);
        /* 延时,延时时长为T1,T1 的大小在datasheet 的上电时序图下面有标注*/
        usleep_range(1000, 1200);
        /* DOVDD 上电*/
        vin_set_pmu_channel(sd, IOVDD, ON);
        /* 延时,按照上电时序中的标注的T2 时间延时*/
        usleep_range(1000, 1200);
        /* DVDD 上电*/
        vin_set_pmu_channel(sd, DVDD, ON);
        /* 延时,按照上电时序中的标注的T3 时间延时*/
        usleep_range(1000, 1200);
        /* 将PWDN 设置为低电平*/
        vin_gpio_write(sd, PWDN, CSI_GPIO_LOW);
        /* 设置MCLK 频率并使能*/
        vin_set_mclk_freq(sd, MCLK);
        vin_set_mclk(sd, ON);
        /* 延时,按照上电时序中的标注的T4 时间延时*/
        usleep_range(1000, 1200);
        /* 将RESET 设置为高电平*/
        vin_gpio_write(sd, RESET, CSI_GPIO_HIGH);
        /* 延时,按照上电时序中的标注的T6 时间延时*/
        usleep_range(10000, 12000);
        cci_unlock(sd);
        break;
    /* 掉电操作*/
        case PWR_OFF:
        sensor_print("PWR_OFF!\\n");
        cci_lock(sd);
        /* 具体的掉电操作同样的按照datasheet 的power off 操作即可*/
        vin_gpio_write(sd, PWDN, CSI_GPIO_HIGH);
        vin_gpio_write(sd, RESET, CSI_GPIO_LOW);
        vin_set_mclk(sd, OFF);
        vin_set_pmu_channel(sd, AFVDD, OFF);
        vin_set_pmu_channel(sd, AVDD, OFF);
        vin_set_pmu_channel(sd, DVDD, OFF);
        vin_set_pmu_channel(sd, IOVDD, OFF);
        vin_set_pmu_channel(sd, CAMERAVDD, OFF);
        vin_gpio_set_status(sd, PWDN, 0);
        cci_unlock(sd);
        break;
    default:
    	return -EINVAL;
    
    return 0;

3.2.2.5 检测函数
static int sensor_detect(struct v4l2_subdev *sd)

在开机加载驱动的时候,将会检测sensor ID,用于测试I2C 通讯是否正常和sensor 识别。

#define V4L2_IDENT_SENSOR 0x7750
    sensor_read(sd, 0x300A, &rdval);
    if (rdval != (V4L2_IDENT_SENSOR >> 8))
    	return -ENODEV;
    sensor_read(sd, 0x300B, &rdval);
    if (rdval != (V4L2_IDENT_SENSOR & 0xff))
    	return -ENODEV;

图3-9: sensordetect
3.2.2.6 SENSOR 相关的IOCTL
static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)

用于应用层获取曝光增益,及进行与sensor 相关模块的驱动控制,如对焦,闪光等

case VIDIOC_VIN_SENSOR_EXP_GAIN:/*设置sensor的曝光增益*/
    ret = sensor_s_exp_gain(sd, (struct sensor_exp_gain *)arg);
    break;
case VIDIOC_VIN_SENSOR_CFG_REQ:/*获取sensor驱动的基础配置信息*/
    sensor_cfg_req(sd, (struct sensor_config *)arg);
    break;
case VIDIOC_VIN_ACT_SET_CODE:/*设置对焦马达配置参数,在配置AF模块时,需要此ioctl*/
	actuator_set_code(sd, (struct actuator_ctrl *)arg);
3.2.2.7 与CSI 的接口
static struct sensor_format_struct sensor_formats[] = ;
RAW sensor:
.desc = "Raw RGB Bayer",
.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
.regs = sensor_fmt_raw,
.regs_size = ARRAY_SIZE(sensor_fmt_raw),
.bpp = 1
YUV sensor:
.desc = "YUYV 4:2:2",
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.regs = sensor_fmt_yuyv422_yuyv,
.regs_size = ARRAY_SIZE(sensor_fmt_yuyv422_yuyv),
.bpp = 2

其中,mbus_code 中BGGR 可以根据sensor raw data 输出顺序修改为GBRG/RGGB/-GRBG。若填错, 会导致色彩偏紫红和出现网格状纹理。10_1X10 表示10 bit

并口输出, 若是12 bit MIPI 输出, 则改为12_12X1。其他情况类推。对于DVP YUV sensor, 需根据yuv 输出顺序选择yuyv/vyuy/uyvy/yvyu 其中一种。

static int sensor_g_mbus_config(struct v4l2_subdev *sd,struct v4l2_mbus_config *cfg)
DVP sensor:
    cfg->type = V4L2_MBUS_PARALLEL;
    cfg->flags = V4L2_MBUS_MASTER | VREF_POL | HREF_POL | CLK_POL;
MIPI sensor:
    cfg->type = V4L2_MBUS_CSI2;
    cfg->flags = 0 | V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0;

其中,MIPI sensor 须根据实际使用的lane 数,修改V4L2_MBUS_CSI2_X_LANE 中的X值。如果使用LVDS 接口,需要将cfg->type 配置为V4L2_MBUS_SUBLVDS。

3.2.2.8 分辨率配置
static struct sensor_win_size sensor_win_sizes[] = 

    .width = VGA_WIDTH,
    .height = VGA_HEIGHT,
    .hoffset = 0,
    .voffset = 0,
    .hts = 928,
    .vts = 1720,
    .pclk = 48 * 1000 * 1000,
    .mipi_bps = 480 * 1000 * 1000,
    .fps_fixed = 30,
    .bin_factor = 1,
    .intg_min = 1 << 4,
    .intg_max = (1720) << 4,
    .gain_min = 1 << 4,
    .gain_max = 16 << 4,
    .regs = sensor_VGA_regs,
    .regs_size = ARRAY_SIZE(sensor_VGA_regs),
    .set_size = NULL,
,

    /* 定义图像输出的大小*/
    .width = VGA_WIDTH,
    .height = VGA_HEIGHT,
    /* 定义输入ISP 的偏移量,用于截取所需的Size,丢弃不需要的部分图像*/
    .hoffset = 0,
    .voffset = 0,
    /*
    定义行长(以pclk 为单位)、帧长(以hts 为单位) 和像素时钟频率。hts 又称line_length_pck,vts 又称frame_length_lines,与寄存器的值要一致。pclk(pixel clock)的值由PLL 寄存器计算得出。
    */
    .hts = 928,
    .vts = 1720,
    .pclk = 48 * 1000 * 1000,
    /* 定义MIPI 数据速率,MIPI sensor 必需,其他sensor 忽略*/
    /* mipi_bps = hts * vts * fps * raw bit / lane num */
    .mipi_bps = 480 * 1000 * 1000,
    /* 定义帧率,fps * hts * vts = pclk */
    .fps_fixed = 30,
    /*
    定义曝光行数最小值和最大值,增益最小值和最大值,以16 为1 倍。最值的设置应在sensor 规格和
    曝光函数限定的范围内,若超出会导致画面异常。此外,若AE table 中的最值超出这里的限制,会使得
    AE table 失效。
    */
    .intg_min = 1 << 4,
    .intg_max = (1720) << 4,
    .gain_min = 1 << 4,
    .gain_max = 16 << 4,
    /* (必需)说明这部分的配置对应哪个寄存器初始化代码*/
    .regs = sensor_VGA_regs,
    .regs_size = ARRAY_SIZE(sensor_VGA_regs),
    ,
;

根据应用的需求,在这里配置驱动能输出的不同尺寸帧率组合,注意,一种分辨率、帧率配置为一个数组成员,不要混淆。

3.2.3 LVDS 接口须知

除了完成以上函数的实现,LVDS Sensor 驱动还需要完成combo 同步校验函数和combo 数据线映射函数。combo 校验码可以在sensor 规格书获取,combo 数

据线映射关系需要查看原理图设计进行配对,可参考imx274_slvds.c 完成开发。

图3-10: SYNC_CODE
static void sensor_g_combo_sync_code(struct v4l2_subdev *sd,
struct combo_sync_code *sync)

    int i;
    for (i = 0; i < 12; i++) 
    sync->lane_sof[i].low_bit = 0x0000ab00;
    sync->lane_sof[i].high_bit = 0xFFFF0000;
    sync->lane_sol[i].low_bit = 0x00008000;
    sync->lane_sol[i].high_bit = 0xFFFF0000;
    sync->lane_eol[i].low_bit = 0x00009d00;
    sync->lane_eol[i].high_bit = 0xFFFF0000;
    sync->lane_eof[i].low_bit = 0x0000b600;
    sync->lane_eof[i].high_bit = 0xFFFF0000;


static void sensor_g_combo_lane_map(struct v4l2_subdev *sd,
	struct combo_lane_map *map)
	
	struct sensor_info *info = to_state(sd);
    if (info->isp_wdr_mode == ISP_DOL_WDR_MODE) 
        map->lvds_lane0 = LVDS_MAPPING_A_D0_TO_LANE0;
        map->lvds_lane1 = LVDS_MAPPING_A_D1_TO_LANE1;
        map->lvds_lane2 = LVDS_MAPPING_B_D2_TO_LANE2;
        map->lvds_lane3 = LVDS_MAPPING_B_D0_TO_LANE3;
        map->lvds_lane4 = LVDS_MAPPING_B_D3_TO_LANE4;
        map->lvds_lane5 = LVDS_MAPPING_C_D2_TO_LANE5;
        map->lvds_lane6 = LVDS_LANE6_NO_USE;
        map->lvds_lane7 = LVDS_LANE7_NO_USE;
        map->lvds_lane8 = LVDS_LANE8_NO_USE;
        map->lvds_lane9 = LVDS_LANE9_NO_USE;
        map->lvds_lane10 = LVDS_LANE10_NO_USE;
        map->lvds_lane11 = LVDS_LANE11_NO_USE;
 else 
        map->lvds_lane0 = LVDS_MAPPING_A_D1_TO_LANE0;
        map->lvds_lane1 = LVDS_MAPPING_B_D2_TO_LANE1;
        map->lvds_lane2 = LVDS_MAPPING_B_D0_TO_LANE2;
        map->lvds_lane3 = LVDS_MAPPING_B_D3_TO_LANE3;
        map->lvds_lane4 = LVDS_LANE4_NO_USE;
        map->lvds_lane5 = LVDS_LANE5_NO_USE;
        map->lvds_lane6 = LVDS_LANE6_NO_USE;
        map->lvds_lane7 = LVDS_LANE7_NO_USE;
        map->lvds_lane8 = LVDS_LANE8_NO_USE;
        map->lvds_lane9 = LVDS_LANE9_NO_USE;
        map->lvds_lane10 = LVDS_LANE10_NO_USE;
        map->lvds_lane11 = LVDS_LANE11_NO_USE;
	

3.2.4 内核代码注意事项

驱动中一般禁止使用mdelay 或者msleep 实现延时,例如使用msleep 实现10~20ms的延时,通常会因为系统调度而变成延时更长的时间,这种做法精度较差。

所以如果需要使用ms 级别延时,则使用usleep_range(a, b),比如原来mdelay(1)、mdelay(10) 可改为usleep_range(1000, 2000)、usleep_range(10000,

12000)。如果是长达30ms 或以上的延时可选择使用msleep();

中断过程中不能使用msleep 和usleep_range,除了特殊情况必须加延时之外,mdelay 一般也不可使用。

4 模块配置

4.1 Tina 配置

Tina 中主要是修改平台的modules.mk 配置,modules.mk 主要完成两个方面:

1.拷贝相关的ko 模块到小机rootfs 中

2.rootfs 启动时,按顺序自动加载相关的ko 模块。

由于内核框架的不一样,需要区分vfe 和vin 进行相应的配置。

4.1.1 vfe 框架

modules.mk 配置路径(以R40 平台的为例):

target/allwinner/r40-common/modules.mk

其中的r40-common 为R40 平台共有的配置文件目录,相应的修改对应平台的modules.mk即可。

define KernelPackage/sunxi-vfe
    SUBMENU:=$(VIDEO_MENU)
    TITLE:=sunxi-vfe support
    FILES:=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-core.ko
    FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-memops.ko
    FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-dma-contig.ko
    FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-v4l2.ko
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vfe/vfe_io.ko
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vfe/device/ov5640.ko (详见1)
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vfe/vfe_v4l2.ko
    AUTOLOAD:=$(call AutoLoad,90,videobuf2-core videobuf2-memops videobuf2-dma-contig
    videobuf2-v4l2 vfe_io ov5640 vfe_v4l2) (详见2)
endef
    define KernelPackage/sunxi-vfe/description
    	Kernel modules for sunxi-vfe support
endef
详注:
    1.由具体使用的模组确定,需要确定内核路径中这个驱动是否被编译出来。
    2.AUTOLOAD为小机rootfs挂载后自动加载的机制,vfe_v4l2.ko必须在最后加载,其它ko可以按照上面的相对顺序加载。必须修改相应的sensor ko才会开启自加载。

4.1.2 vin 框架

modules.mk 配置路径(以R30 平台的为例):

target/allwinner/r30-common/modules.mk

其中的r30-common 为R30 平台共有的配置文件目录,相应的修改对应平台的modules.mk即可。

define KernelPackage/sunxi-vin
    SUBMENU:=$(VIDEO_MENU)
    TITLE:=sunxi-vin support
    FILES:=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-core.ko
    FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-memops.ko
    FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-dma-contig.ko
    FILES+=$(LINUX_DIR)/drivers/media/v4l2-core/videobuf2-v4l2.ko
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/vin_io.ko
    /*对焦马达驱动加载*/
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/modules/actuator/actuator.ko
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/modules/actuator/dw9714_act.ko(详见
    3)
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/modules/sensor/ov5640.ko (详见1)
    FILES+=$(LINUX_DIR)/drivers/media/platform/sunxi-vin/vin_v4l2.ko
    AUTOLOAD:=$(call AutoLoad,90,videobuf2-core videobuf2-memops videobuf2-dma-contig
    videobuf2-v4l2 vin_io actuator dw9714_act ov5640 vin_v4l2) (详见2)
endef
    define KernelPackage/sunxi-vin/description
    	Kernel modules for sunxi-vin support
endef
详注:
    1.由具体使用的模组确定,需要确定内核路径中这个驱动是否被编译出来。
    2.AUTOLOAD为小机rootfs挂载后自动加载的机制,vin_v4l2.ko必须在最后加载,其它ko可以按照上面的相对顺序加载。
    3.对焦马达驱动加载顺序必须在sensor驱动加载之前,具体驱动型号根据模组规格书进行确认。

V 系列平台在完成modules.mk 配置后,还需要完成.ko 挂载脚本S00mpp 的配置,S00mpp

配置路径(以V853 平台为例):

target/allwinner/v853-perf1/busybox-init-base-files/etc/init.d

其中的v853-perf1 为V 系列平台共有的配置文件目录,相应的修改对应平台的S00mpp 即可。

#!/bin/sh
#
# Load mpp modules....
#
MODULES_DIR="/lib/modules/`uname -r`"
start() 
    printf "Load mpp modules\\n"
    insmod $MODULES_DIR/videobuf2-core.ko
    insmod $MODULES_DIR/videobuf2-memops.ko
    insmod $MODULES_DIR/videobuf2-dma-contig.ko
    insmod $MODULES_DIR/videobuf2-v4l2.ko
    insmod $MODULES_DIR/vin_io.ko
    # insmod $MODULES_DIR/sensor_power.ko
    insmod $MODULES_DIR/gc4663_mipi.ko
    insmod $MODULES_DIR/vin_v4l2.ko
    insmod $MODULES_DIR/sunxi_aio.ko
    insmod $MODULES_DIR/sunxi_eise.ko
    # insmod $MODULES_DIR/vipcore.ko

stop() 
    printf "Unload mpp modules\\n"
    # rmmod $MODULES_DIR/vipcore.ko
    rmmod $MODULES_DIR/sunxi_eise.ko
    rmmod $MODULES_DIR/sunxi_aio.ko
    rmmod $MODULES_DIR/vin_v4l2.ko
    rmmod $MODULES_DIR/gc4663_mipi.ko
    # rmmod $MODULES_DIR/sensor_power.ko
    rmmod $MODULES_DIR/vin_io.ko
    rmmod $MODULES_DIR/videobuf2-v4l2.ko
    rmmod $MODULES_DIR/videobuf2-dma-contig.ko
    rmmod $MODULES_DIR/videobuf2-memops.ko
    rmmod $MODULES_DIR/videobuf2-core.ko

case "$1" in
        start)
        start
        ;;
        stop)
        stop
        ;;
        restart|reload)
        stop
        start
        ;;
    *)
    echo "Usage: $0 start|stop|restart"
    exit 1
esac
exit $?

4.2 CSI 板级配置

Tina 平台根据不同的平台差异分别使用sys_config.fex 或board.dst 配置camera CSI,具体的对应关系如下表,下面将分别介绍sys_config.fex 和board.dts 中关

于camera CSI 配置。

表4-1: 平台配置方式对应表
平台CSI 使用的配置方式
F35sys_config.fex
R16sys_config.fex
R18sys_config.fex
R30sys_config.fex
R40sys_config.fex
R311sys_config.fex
MR133sys_config.fex
R818board.dts
MR813board.dts
R528board.dts
V536sys_config.fex
V533board.dts
V831board.dts
V833board.dts
V851board.dts
V853board.dts

4.2.1 sys_config.fex 平台配置

sys_config.fex 配置camera CSI,CSI sys_config.fex 部分对应的字段为:[csi0]。通过举例R40 平台说明在实际使用中应该如何配置:假如使用一个并口camera

模组需要配置[csi0] 的公用部分和[csi0] 的vip_dev0_(x) 部分,另外[csi0] 中vip_used 设置为1,[csi1]中vip_used 设置为0。

下面给出一个ov5640 模组的参考配置:其中[csi0] 为并口的配置。具体填写方法请参照以下说明:

/* 下面部分的CSI配置适用4.9内核之前的平台*/
;--------------------------------------------------------------------------------
;csi (COMS Sensor Interface) configuration
;csi(x)_dev(x)_used: 0:disable 1:enable
;csi(x)_dev(x)_isp_used 0:not use isp 1:use isp
;csi(x)_dev(x)_fmt: 0:yuv 1:bayer raw rgb
;csi(x)_dev(x)_stby_mode: 0:not shut down power at standby 1:shut down power at standby
;csi(x)_dev(x)_vflip: flip in vertical direction 0:disable 1:enable
;csi(x)_dev(x)_hflip: flip in horizontal direction 0:disable 1:enable
;csi(x)_dev(x)_iovdd: camera module io power handle string, pmu power supply
;csi(x)_dev(x)_iovdd_vol: camera module io power voltage, pmu power supply
;csi(x)_dev(x)_avdd: camera module analog power handle string, pmu power supply
;csi(x)_dev(x)_avdd_vol: camera module analog power voltage, pmu power supply
;csi(x)_dev(x)_dvdd: camera module core power handle string, pmu power supply
;csi(x)_dev(x)_dvdd_vol: camera module core power voltage, pmu power supply
;csi(x)_dev(x)_afvdd: camera module vcm power handle string, pmu power supply
;csi(x)_dev(x)_afvdd_vol: camera module vcm power voltage, pmu power supply
;fill voltage in uV, e.g. iovdd = 2.8V, csix_iovdd_vol = 2800000
;fill handle string as below:
;axp22_eldo3
;axp22_dldo4
;axp22_eldo2
;fill handle string "" when not using any pmu power supply
;--------------------------------------------------------------------------------
[csi0]
csi0_used = 1
csi0_sensor_list = 0
csi0_pck = port:PE00<2><default><default><default>
csi0_mck = port:PE01<2><default><default><default>
csi0_hsync = port:PE02<2><default><default><default>
csi0_vsync = port:PE03<2><default><default><default>
csi0_d0 = port:PE04<2><default><default><default>
csi0_d1 = port:PE05<2><default><default><default>
csi0_d2 = port:PE06<2><default><default><default>
csi0_d3 = port:PE07<2><default><default><default>
csi0_d4 = port:PE08<2><default><default><default>
csi0_d5 = port:PE09<2><default><default><default>
csi0_d6 = port:PE10<2><default><default><default>
csi0_d7 = port:PE11<2><default><default><default>
csi0_sck = port:PE12<2><default><default><default>
csi0_sda = port:PE13<2><default><default><default>
[csi0/csi0_dev0]
csi0_dev0_used = 1
csi0_dev0_mname = "ov5640" ;必须和sensor驱动中的SENSOR_NAME一致
csi0_dev0_twi_addr = 0x78 ;请参考实际模组的8bit ID填写
csi0_dev0_twi_id = 2
csi0_dev0_pos = "rear"
csi0_dev0_isp_used = 0 ;YUV格式填0,RAW格式填1
csi0_dev0_fmt = 0 ;YUV格式填0,RAW格式填1
csi0_dev0_stby_mode = 0
csi0_dev0_vflip = 0
csi0_dev0_hflip = 0
csi0_dev0_iovdd = "csi-iovcc" ;电源请参考实际原理图填写,同时参考
sys_config.fex 的regulator 配置,确认该字段有效
csi0_dev0_iovdd_vol = 2800000 ;电压值参考datasheet
csi0_dev0_avdd = "csi-avdd" ;电源请参考实际原理图填写,同时参考
sys_config.fex 的regulator 配置,确认该字段有效
csi0_dev0_avdd_vol = 2800000 ;电压值参考datasheet
csi0_dev0_dvdd = "csi-dvdd" ;电源请参考实际原理图填写,同时参考
sys_config.fex 的regulator 配置,确认该字段有效
csi0_dev0_dvdd_vol = 1500000 ;电压值参考datasheet
csi0_dev0_afvdd = "csi-afvcc" ;电源请参考实际原理图填写,同时参考
sys_config.fex 的regulator 配置,确认该字段有效
csi0_dev0_afvdd_vol = 2800000 ;电压值参考datasheet
csi0_dev0_power_en =
csi0_dev0_reset = port:PE14<1><0><1><0> ;io选取参照实际原理图
csi0_dev0_pwdn = port:PE15<1><0><1><0> ;io选取参照实际原理图
csi0_dev0_flash_used = 0
csi0_dev0_flash_type = 2
csi0_dev0_flash_en =
csi0_dev0_flash_mode =
csi0_dev0_flvdd = ""
csi0_dev0_flvdd_vol =
csi0_dev0_af_pwdn =
csi0_dev0_act_used = 0
csi0_dev0_act_name = "ad5820_act"
csi0_dev0_act_slave = 0x18
/* 下面部分的CSI配置适用4.9内核平台*/
;--------------------------------------------------------------------------------
;csi (COMS Sensor Interface) configuration
;csi(x)_dev(x)_used: 0:disable 1:enable
;csi(x)_dev(x)_isp_used 0:not use isp 1:use isp
;csi(x)_dev(x)_fmt: 0:yuv 1:bayer raw rgb
;csi(x)_dev(x)_stby_mode: 0:not shut down power at standby 1:shut down power at standby
;csi(x)_dev(x)_vflip: flip in vertical direction 0:disable 1:enable
;csi(x)_dev(x)_hflip: flip in horizontal direction 0:disable 1:enable
;csi(x)_dev(x)_iovdd: camera module io power handle string, pmu power supply
;csi(x)_dev(x)_iovdd_vol: camera module io power voltage, pmu power supply
;csi(x)_dev(x)_avdd: camera module analog power handle string, pmu power supply
;csi(x)_dev(x)_avdd_vol: camera module analog power voltage, pmu power supply
;csi(x)_dev(x)_dvdd: camera module core power handle string, pmu power supply
;csi(x)_dev(x)_dvdd_vol: camera module core power voltage, pmu power supply
;csi(x)_dev(x)_afvdd: camera module vcm power handle string, pmu power supply
;csi(x)_dev(x)_afvdd_vol: camera module vcm power voltage, pmu power supply
;fill voltage in uV, e.g. iovdd = 2.8V, csix_iovdd_vol = 2800000
;fill handle string as below:
;axp22_eldo3
;axp22_dldo4
;axp22_eldo2
;fill handle string "" when not using any pmu power supply
;--------------------------------------------------------------------------------
[vind0]
vind0_used = 1
[vind0/csi_cci0]
csi_cci0_used = 1 ;配置是否使用CCI,如果使用CCI,需要使能该配置并配置下面的CCI引脚
csi_cci0_sck = port:PE01<2><default><default><default>
csi_cci0_sda = port:PE02<2><default><default><default>
[vind0/flash0]
flash0_used = 0
flash0_type = 2
flash0_en =
flash0_mode =
flash0_flvdd = ""
flash0_flvdd_vol =
[vind0/actuator0]
actuator0_used = 0
actuator0_name = "ad5820_act"
actuator0_slave = 0x18
actuator0_af_pwdn =
actuator0_afvdd = "afvcc-csi"
actuator0_afvdd_vol = 2800000
[vind0/sensor0]
sensor0_used = 0
sensor0_mname = "gc8034_mipi"
sensor0_twi_cci_id = 0
sensor0_twi_addr = 0x6e
sensor0_pos = "rear"
sensor0_isp_used = 1
sensor0_fmt = 1
sensor0_stby_mode = 0
sensor0_vflip = 0
sensor0_hflip = 0
sensor0_cameravdd = ""
sensor0_cameravdd_vol = 3300000
sensor0_iovdd = "iovdd-csi"
sensor0_iovdd_vol = 1800000
sensor0_avdd = "avdd-csi-f"
sensor0_avdd_vol = 2800000
sensor0_dvdd = "dvdd-csi"
sensor0_dvdd_vol = 1200000
sensor0_power_en =
sensor0_reset = port:PE06<0><0><1><0>
sensor0_pwdn = port:PE05<0><0><1><0>
[vind0/sensor1]
sensor1_used = 1
sensor1_mname = "gc8034_mipi" ;必须要和驱动的SENSOR_NAME 一致
sensor1_twi_cci_id = 0 ;配置使用的TWI id,如果使用TWI,则不使用CCI
sensor1_twi_addr = 0x6e ;配置sensor的i2c地址
sensor1_pos = "front"
sensor1_isp_used = 1 ;配置是否使用isp
sensor1_fmt = 1
sensor1_stby_mode = 0
sensor1_vflip = 0
sensor1_hflip = 0
sensor1_cameravdd = ""
sensor1_cameravdd_vol = 3300000
sensor1_iovdd = "iovdd-csi"
sensor1_iovdd_vol = 1800000
sensor1_avdd = "avdd-csi-f"
sensor1_avdd_vol = 2800000
sensor1_dvdd = "dvdd-csi"
sensor1_dvdd_vol = 1200000
sensor1_power_en =
sensor1_reset = port:PE06<0><0><1><0>
sensor1_pwdn = port:PE05<0><0><1><0>
[vind0/vinc0] ;配置video0 的数据链路
vinc0_used = 1
vinc0_csi_sel = 0
vinc0_mipi_sel = 0
vinc0_isp_sel = 0
vinc0_rear_sensor_sel = 1 ;配置使用sensor1 输出图像数据到video0
vinc0_front_sensor_sel = 1 ;配置使用sensor1 输出图像数据到video0
vinc0_sensor_list = 0
[vind0/vinc1]
vinc1_used = 0
vinc1_csi_sel = 0
vinc1_mipi_sel = 0
vinc1_isp_sel = 0
vinc1_rear_sensor_sel = 1
vinc1_front_sensor_sel = 1
vinc1_sensor_list = 0

关于电源的配置,根据板子的原理图,了解需要sensor 驱动配置哪几路电,然后在sys_config.fex中进行配置:比如说sensor0 有个“CSI-IOVCC” 连接到AXP

的“LDO4”,那么,在sys_config.fex 中搜索LDO4 ,然后在其后面增加“csi-iovcc” ,这样,在sensor 端就可以使用该标号配置sensor0_iovdd。

regulator14 = "pmu1736_bldo2 none csi-iovdd"
sensor0_iovdd = "csi-iovdd"

同时关于mr133/R311 平台,sys_config.fex 中的vinc0_rear_sensor_sel 和vinc0_front_sensor_sel

配置决定着使用哪路sensor 输入数据,该配置与硬件连接相关,可参考本文档最后的其他注意事项章节。

4.2.2 board.dts 平台配置

当前MR813/R818/R528 平台的摄像头配置不再使用sys_config.fex 而使用board.dts,文件存放在tina/device/config/chips/mr813(R818、R528)/configs/

< 方案> 目录下,摄像头相关的配置如下:

    vind0:vind@0 
        vind0_clk = <336000000>;
        vind0_isp = <327000000>;
        status = "okay";
        actuator0:actuator@0 
        device_type = "actuator0";
        actuator0_name = "ad5820_act";/*必须要和驱动的SUNXI_ACT_NAME一致*/
        actuator0_slave = <0x18>;/*必须和驱动的SUNXI_ACT_ID一致*/
        actuator0_af_pwdn = <>;
        actuator0_afvdd = "afvcc-csi";
        actuator0_afvdd_vol = <2800000>;/*af模块的配电不在此处,在sensor配置中*/
        status = "disabled";/*使能开关,当使用AF功能时,status = "okay"*/
    ;
    flash0:flash@0 
        device_type = "flash0";
        flash0_type = <2>;
        flash0_en = <>;
        flash0_mode = <>;
        flash0_flvdd = "";
        flash0_flvdd_vol = <>;
        device_id = <0>;
        status = "disabled";
    ;
    sensor0:sensor@0 
        device_type = "sensor0";
        sensor0_mname = "imx278_mipi"; /* 必须要和驱动的 SENSOR_NAME 一致 */
        sensor0_twi_cci_id = <2>;
        sensor0_twi_addr = <0x20>;
        sensor0_mclk_id = <0>;
        sensor0_pos = "rear";
        sensor0_isp_used = <1>; /* R528 没有isp,该项需要配置为0 */
        sensor0_fmt = <1>;
        sensor0_stby_mode = <0>;
        sensor0_vflip = <0>;
        sensor0_hflip = <0>;
        /* sensor iovdd 连接的 ldo,根据硬件原理图的连接,
        * 确认是连接到 axp 哪个 ldo,假设 iovdd 连接到 aldo3,
        * 则 sensor0_iovdd-supply = <&reg_aldo3>,其他同理。
        */
        sensor0_iovdd-supply = <&reg_dldo2>;
        sensor0_iovdd_vol = <1800000>;
        sensor0_avdd-supply = <&reg_dldo3>;
        sensor0_avdd_vol = <2800000>;
        sensor0_dvdd-supply = <&reg_eldo2>;
        sensor0_afvdd-supply = <&reg_aldo3>;/*根据硬件原理图,确定配的哪路电*/
        sensor0_afvdd_vol = <2800000>;/*根据硬件原理图,确认工作电压*/
        sensor0_dvdd_vol = <1200000>;
        sensor0_power_en = <>;
        /* 根据板子实际连接,修改 reset、pwdn 的引脚即可 */
        /* GPIO 信息配置:pio 端口 组内序号 功能分配 内部电阻状态 驱动能力 输出电平状态 */
        sensor0_reset = <&pio PE 9 1 0 1 0>;
        sensor0_pwdn = <&pio PE 8 1 0 1 0>;
        status = "okay";
    ;
    sensor1:sensor@1 
        device_type = "sensor1";
        sensor1_mname = "imx386_mipi";
        sensor1_twi_cci_id = <3>;
        sensor1_twi_addr = <0x20>;
        sensor1_mclk_id = <1>;
        sensor1_pos = "front";
        sensor1_isp_used = <1>;
        sensor1_fmt = <1>;
        sensor1_stby_mode = <0>;
        sensor1_vflip = <0>;
        sensor1_hflip = <0>;
        sensor1_iovdd-supply = <&reg_dldo2>;
        sensor1_iovdd_vol = <1800000>;
        sensor1_avdd-supply = <&reg_dldo3>;
        sensor1_avdd_vol = <2800000>;
        sensor1_dvdd-supply = <&reg_eldo2>;
        sensor1_dvdd_vol = <1200000>;
        sensor0_power_en = <>;
        sensor1_reset = <&pio PE 7 1 0 1 0>;
        sensor1_pwdn = <&pio PE 6 1 0 1 0>;
        status = "okay";
    ;
    /* 一个 vinc 代表一个 /dev/video 设备 */
    vinc0:vinc@0 
        vinc0_csi_sel = <0>; /* 代表选择的 csi,MR813/R818 有两个 csi 接口
        */
        vinc0_mipi_sel = <0>; /* 代表选择的 mipi 接口,MR813/R818 有两个 mipi
        接口 */
        vinc0_isp_sel = <0>;
        vinc0_isp_tx_ch = <0>; /* 表示 ISP 的通道数,一般配置为 0 */
        vinc0_tdm_rx_sel = <0>; /* 与 isp_sel 保持一致即可 */
        vinc0_rear_sensor_sel = <0>; /* 该 video 可以选择从哪个 sensor 输入图像数据
        */
        vinc0_front_sensor_sel = <1>;
        vinc0_sensor_list = <0>;
        status = "okay";
    ;
    vinc1:vinc@1 
        vinc1_csi_sel = <0>;
        vinc1_mipi_sel = <0>; /* R528没有mipi,该项配置为0xff */
        vinc1_isp_sel = <0>; /* R528没有isp,该项配置为0 */
        vinc1_isp_tx_ch = <0>; /* R528没有isp,该项配置为0 */
        vinc1_tdm_rx_sel = <0>; /* R528没有isp,该项配置为0xff */
        vinc1_rear_sensor_sel = <0>;
        vinc1_front_sensor_sel = <1>;
        vinc1_sensor_list = <0>;
        status = "okay";
    ;
    vinc2:vinc@2 
        vinc2_csi_sel = <1>;
        vinc2_mipi_sel = <1>;
        vinc2_isp_sel = <1>;
        vinc2_isp_tx_ch = <0>;
        vinc2_tdm_rx_sel = <1>;
        vinc2_rear_sensor_sel = <1>;
        vinc2_front_sensor_sel = <1>;
        vinc2_sensor_list = <0>;
        status = "okay";
    ;
    vinc3:vinc@3 
        vinc3_csi_sel = <1>;
        vinc3_mipi_sel = <1>;
        vinc3_isp_sel = <1>;
        vinc3_isp_tx_ch = <0>;
        vinc3_tdm_rx_sel = <1>;
        vinc3_rear_sensor_sel = <1>;
        vinc3_front_sensor_sel = <1>;
        vinc3_sensor_list = <0>;
        status = "okay";
    ;
    ;
    /* 以下将配置两路 sensor 输入,产生 4 个 video 节点,内核配置 CONFIG_SUPPORT_ISP_TDM=n,此时
    * 不同 sensor 输出的节点不能同时使用,比如以下配置的 video0 不可以和 video2 video3 同时

以上是关于全志Tina Linux Camera 摄像头模块开发指南 全网最详细版本支持百问网T113-Pro DongshanPI-NezhaD1-H DongshanPI-D1s V853-Pro等开发板的主要内容,如果未能解决你的问题,请参考以下文章

Tina Linux Camera开发指南

全志Tina Linux Display 开发指南支持百问网T113 D1-H哪吒DongshanPI-D1s V853-Pro等开发板

全志Tina Linux Display 开发指南支持百问网T113 D1-H哪吒DongshanPI-D1s V853-Pro等开发板

全志Tina Linux MPP 开发指南

全志系列芯片如何在Tina Linux中使用脚本完成定制化升级?

全志 Tina Linux 系统调试 使用指南 GDB gdbserver coredump perf strace valgind