Tina Linux Camera開發(fā)指南
1 概述
編寫目的:介紹camera 模塊在sunxi 平臺上的開發(fā)流程。
適用范圍:本文檔目前適用于tina3.0 以上具備camera 的硬件平臺。
2 模塊介紹
2.1 模塊功能介紹
用于接收并行或者mipi 接口的sensor 信號或者是bt656 格式的信號。
2.2 硬件介紹
目前Tina 系統(tǒng)的各平臺camera 硬件接口、linux 內核版本以及camera 驅動框架如下表所示:
?
表2-1: 平臺CSI 框架
?
平臺 | 支持接口 | 是否具備ISP模塊 | linux 內核版本 | camera 驅動框架 |
---|---|---|---|---|
F35 | 并口csi、mipi | 否 | 3.4 | VFE |
R16 | 并口csi | 否 | 3.4 | VFE |
R18 | 并口csi | 否 | 4.4 | VFE |
R30 | 并口csi | 否 | 4.4 | VFE |
R40 | 并口csi | 否 | 3.10 | VFE |
R311 | mipi csi | 是 | 4.9 | VIN |
MR133 | mipi csi | 是 | 4.9 | VIN |
R818 | mipi csi | 是 | 4.9 | VIN |
MR813 | mipi csi | 是 | 4.9 | VIN |
R528 | 并口csi | 否 | 5.4 | VIN |
V536 | 并口csi、mipi | 是 | 4.9 | VIN |
V533 | 并口csi、mipi | 是 | 4.9 | VIN |
V831 | 并口csi、mipi | 是 | 4.9 | VIN |
V833 | 并口csi、mipi | 是 | 4.9 | VIN |
V851 | 并口csi、mipi | 是 | 4.9 | VIN |
V853 | 并口csi、mipi | 是 | 4.9 | VIN |
注意:
如果平臺沒有ISP 模塊,那么將不支持RAW sensor(即sensor 只輸出采集到的原始數(shù)據),文檔中提到的RAW 等相關信息不用理會;
如果平臺沒有支持mipi 接口,文檔中提到的mipi 相關信息忽略;
不同平臺可能將使用不同的camera 驅動框架,這點注意區(qū)分;
2.3 源碼結構介紹
2.3.1 linux3.4 VFE 框架
驅動路徑位于linux-3.4/drivers/media/video/sunxi-vfe 下。
sunxi-vfe:.
│ bsp_common.c ;底層bsp共用的函數(shù)
│ bsp_common.h ;底層bsp共用函數(shù)頭文件
│ config.c ;讀取sys_config.fex的參數(shù)配置和isp參數(shù)
│ config.h ;讀取sys_config.fex和isp參數(shù)函數(shù)的頭文件
│ Kconfig
│ Makefile
│ platform_cfg.h ;區(qū)分各個平臺的頭文件
│ vfe.c ;v4l2驅動實現(xiàn)主體(包含視頻接口和ISP部分)
│ vfe.h ;v4l2驅動頭文件
│ vfe_os.c ;系統(tǒng)資源函數(shù)實現(xiàn)(pin,clock,memory)
│ vfe_os.h ;系統(tǒng)資源函數(shù)頭文件
│ vfe_subdev.c ;sensor調用vfe資源函數(shù)
│ vfe_subdev.h ;sensor 調用vfe資源函數(shù)頭文件
│
├─actuator
│ actuator.c ;vcm driver的一般行為
│ actuator.h ;vcm driver的頭文件
│ dw9714_act.c ;具體vcm driver型號實現(xiàn)
│ Makefile
│
├─csi
│ bsp_csi.c ;底層csi bsp函數(shù)
│ bsp_csi.h ;底層csi bsp函數(shù)頭文件
│ csi_reg.c ;csi硬件底層實現(xiàn)
│ csi_reg.h ;csi硬件底層實現(xiàn)頭文件
│ 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控制實現(xiàn)
│ Makefile
│
├─lib
│ bsp_isp.h ;底層isp bsp函數(shù)頭文件
│ bsp_isp_algo.h ;底層isp 算法bsp函數(shù)頭文件
│ bsp_isp_comm.h ;底層isp共用函數(shù)頭文件
│ isp_module_cfg.h ;isp里面各模塊功能配置的頭文件
│ libisp ;isp的函數(shù)庫
│ lib_mipicsi2_v1 ;A31mipi庫
│ lib_mipicsi2_v2 ;A80/A83mipi庫
├─csi_cci
│ cci_helper.c ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)
│ cci_helper.h ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)頭文件
│ bsp_cci.c ;cci 操作函數(shù)集實現(xiàn)
│ bsp_cci.h ;cci 操作函數(shù)集頭文件
│ csi_cci_reg.c ;cci 底層實現(xiàn)
│ csi_cci_reg.h ;cci 底層實現(xiàn)頭文件
│ csi_cci_reg_i.h ;cci寄存器資源頭文件
│
├─mipi_csi
│ bsp_mipi_csi.c ;底層mipi bsp函數(shù)
│ bsp_mipi_csi.h ;底層mipi bsp函數(shù)頭文件
│
└─utility
cfg_op.c ;讀取ini文件的實現(xiàn)函數(shù)
cfg_op.h ;讀取ini文件函數(shù)對應的頭文件
2.3.2 linux3.10 VFE 框架
驅動路徑位于linux-3.10/drivers/media/platform/sunxi-vfe 下。
sunxi-vfe:.
│ bsp_common.c ;底層bsp共用的函數(shù)
│ bsp_common.h ;底層bsp共用函數(shù)頭文件
│ config.c ;讀取sys_config.fex的參數(shù)配置和isp參數(shù)
│ config.h ;讀取sys_config.fex和isp參數(shù)函數(shù)的頭文件
│ Kconfig
│ Makefile
│ platform_cfg.h ;區(qū)分各個平臺的頭文件
│ vfe.c ;v4l2驅動實現(xiàn)主體(包含視頻接口和ISP部分)
│ vfe.h ;v4l2驅動頭文件
│ vfe_os.c ;系統(tǒng)資源函數(shù)實現(xiàn)(pin,clock,memory)
│ vfe_os.h ;系統(tǒng)資源函數(shù)頭文件
│ vfe_subdev.c ;sensor調用vfe資源函數(shù)
│ vfe_subdev.h ;sensor 調用vfe資源函數(shù)頭文件
│
├─actuator
│ actuator.c ;vcm driver的一般行為
│ actuator.h ;vcm driver的頭文件
│ dw9714_act.c ;具體vcm driver型號實現(xiàn)
│ Makefile
│
├─csi
│ bsp_csi.c ;底層csi bsp函數(shù)
│ bsp_csi.h ;底層csi bsp函數(shù)頭文件
│ csi_reg.c ;csi硬件底層實現(xiàn)
│ csi_reg.h ;csi硬件底層實現(xiàn)頭文件
│ 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控制實現(xiàn)
│ Makefile
│
├─lib
│ bsp_isp.h ;底層isp bsp函數(shù)頭文件
│ bsp_isp_algo.h ;底層isp 算法bsp函數(shù)頭文件
│ bsp_isp_comm.h ;底層isp共用函數(shù)頭文件
│ isp_module_cfg.h ;isp里面各模塊功能配置的頭文件
│ libisp ;isp的函數(shù)庫
│ lib_mipicsi2_v1 ;A31mipi庫
│ lib_mipicsi2_v2 ;A80/A83mipi庫
├─csi_cci
│ cci_helper.c ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)
│ cci_helper.h ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)頭文件
│ bsp_cci.c ;cci 操作函數(shù)集實現(xiàn)
│ bsp_cci.h ;cci 操作函數(shù)集頭文件
│ csi_cci_reg.c ;cci 底層實現(xiàn)
│ csi_cci_reg.h ;cci 底層實現(xiàn)頭文件
│ csi_cci_reg_i.h ;cci寄存器資源頭文件
│
├─mipi_csi
│ bsp_mipi_csi.c ;底層mipi bsp函數(shù)
│ bsp_mipi_csi.h ;底層mipi bsp函數(shù)頭文件
│
└─utility
cfg_op.c ;讀取ini文件的實現(xiàn)函數(shù)
cfg_op.h ;讀取ini文件函數(shù)對應的頭文件
2.3.3 linux4.4 VFE 框架
驅動路徑位于linux-4.4/drivers/media/platform/sunxi-vfe 下。
sunxi-vfe:.
│ bsp_common.c ;底層bsp共用的函數(shù)
│ bsp_common.h ;底層bsp共用函數(shù)頭文件
│ config.c ;讀取sys_config.fex的參數(shù)配置和isp參數(shù)
│ config.h ;讀取sys_config.fex和isp參數(shù)函數(shù)的頭文件
│ Kconfig
│ Makefile
│ platform_cfg.h ;區(qū)分各個平臺的頭文件
│ vfe.c ;v4l2驅動實現(xiàn)主體(包含視頻接口和ISP部分)
│ vfe.h ;v4l2驅動頭文件
│ vfe_os.c ;系統(tǒng)資源函數(shù)實現(xiàn)(pin,clock,memory)
│ vfe_os.h ;系統(tǒng)資源函數(shù)頭文件
│ vfe_subdev.c ;sensor調用vfe資源函數(shù)
│ vfe_subdev.h ;sensor 調用vfe資源函數(shù)頭文件
│
├─actuator
│ actuator.c ;vcm driver的一般行為
│ actuator.h ;vcm driver的頭文件
│ dw9714_act.c ;具體vcm driver型號實現(xiàn)
│ Makefile
│
├─csi
│ bsp_csi.c ;底層csi bsp函數(shù)
│ bsp_csi.h ;底層csi bsp函數(shù)頭文件
│ csi_reg.c ;csi硬件底層實現(xiàn)
│ csi_reg.h ;csi硬件底層實現(xiàn)頭文件
│ 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控制實現(xiàn)
│ Makefile
│
├─lib
│ bsp_isp.h ;底層isp bsp函數(shù)頭文件
│ bsp_isp_algo.h ;底層isp 算法bsp函數(shù)頭文件
│ bsp_isp_comm.h ;底層isp共用函數(shù)頭文件
│ isp_module_cfg.h ;isp里面各模塊功能配置的頭文件
│ libisp ;isp的函數(shù)庫
│ lib_mipicsi2_v1 ;A31mipi庫
│ lib_mipicsi2_v2 ;A80/A83mipi庫
├─csi_cci
│ cci_helper.c ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)
│ cci_helper.h ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)頭文件
│ bsp_cci.c ;cci 操作函數(shù)集實現(xiàn)
│ bsp_cci.h ;cci 操作函數(shù)集頭文件
│ csi_cci_reg.c ;cci 底層實現(xiàn)
│ csi_cci_reg.h ;cci 底層實現(xiàn)頭文件
│ csi_cci_reg_i.h ;cci寄存器資源頭文件
│
├─mipi_csi
│ bsp_mipi_csi.c ;底層mipi bsp函數(shù)
│ bsp_mipi_csi.h ;底層mipi bsp函數(shù)頭文件
│
└─utility
cfg_op.c ;讀取ini文件的實現(xiàn)函數(shù)
cfg_op.h ;讀取ini文件函數(shù)對應的頭文件
2.3.4 linux4.4 VIN 框架
驅動路徑位于linux-4.4/drivers/media/platform/sunxi-vin 下。
sunxi-vin:
│ vin.c ;v4l2驅動實現(xiàn)主體(包含視頻接口和ISP部分)
│ vin.h ;v4l2驅動頭文件
│ top_reg.c ;vin對各v4l2 subdev管理接口實現(xiàn)主體
│ top_reg.h ;管理接口頭文件
│ top_reg_i.h ;vin模塊接口層部分結構體
│
├─modules
│ ├─actuator
│ │ actuator.c ;vcm driver的一般行為
│ │ actuator.h ;vcm driver的頭文件
│ │ dw9714_act.c ;具體vcm driver型號實現(xiàn)
│ │ Makefile
│ ├─flash
│ │ flash.h ;led補光燈驅動頭文件
│ │ flash_io.c ;led補光燈io控制實現(xiàn)
│ ├─sensor
│ │ camera.h ;camera公用結構體頭文件
│ │ camera_cfg.h ;camera ioctl擴展命令頭文件
│ │ sensor_helper.c ;sensor公用操作接口函數(shù)文件
│ │ sensor_helper.h ;sensor公用操作接口函數(shù)頭文件
│ │ Makefile
│ │ ov5640.c ;具體的sensor驅動
│
├─platform
│ platform_cfg.h ;平臺相關的配置接口
│
├─utility
│ bsp_common.h ;底層公用的格式配置函數(shù)頭文件
│ bsp_common.c ;底層公用的格式配置函數(shù)文件
│ cfg_op.h ;解析配置文件接口頭文件
│ cfg_op.c ;解析配置文件接口函數(shù)實現(xiàn)主體
│ config.h ;解析設備樹的函數(shù)頭文件
│ config.c ;解析設備樹的接口函數(shù)主體
│ sensor_info.h ;sensor列表信息頭文件
│ sensor_info.c ;獲取sensor列表信息函數(shù)主體
│ vin_io.h ;vin框架io操作接口頭文件
│ vin_io.c ;vin框架io操作接口文件
│ vin_os.h ;vin框架系統(tǒng)操作接口頭文件
│ vin_os.c ;vin框架系統(tǒng)操作接口文件
│ vin_supply.h ;vin框架設置時鐘頻率等接口頭文件
│ vin_supply.c ;vin框架設置時鐘頻率等接口函數(shù)主體
│
├─vin-cci
│ cci_helper.c ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)
│ cci_helper.h ;cci 與設備相關初始化、注冊以及通信等相關函數(shù)集實現(xiàn)頭文件
│ bsp_cci.c ;cci 操作函數(shù)集實現(xiàn)
│ bsp_cci.h ;cci 操作函數(shù)集頭文件
│ csi_cci_reg.c ;cci 底層實現(xiàn)
│ csi_cci_reg.h ;cci 底層實現(xiàn)頭文件
│ csi_cci_reg_i.h ;cci寄存器資源頭文件
│ sunxi_cci.c ;cci 接口封裝實現(xiàn)
│ sunxi_cci.h ;cci 接口封裝頭文件
│
├─vin-csi
│ bsp_csi.c ;csi 操作函數(shù)集實現(xiàn)
│ bsp_csi.h ;csi 操作函數(shù)集頭文件
│ csi_reg.c ;csi 底層實現(xiàn)
│ csi_reg.h ;csi 底層實現(xiàn)頭文件
│ csi_reg_i.h ;csi寄存器資源頭文件
│ parser_reg.c ;csi 底層實現(xiàn)
│ parser_reg.h ;csi 底層實現(xiàn)頭文件
│ parser_reg_i.h ;csi寄存器資源頭文件
│ sunxi_csi.c ;csi 接口封裝實現(xiàn)
│ sunxi_csi.h ;csi 接口封裝頭文件
│
├─vin-isp
│ bsp_isp.c ;isp操作函數(shù)集實現(xiàn)
│ bsp_isp.h ;isp操作函數(shù)集頭文件
│ bsp_isp_comm.h ;isp結構體定義
│ isp_default_tbl.h ;isp默認配置列表
│ isp_platform_drv.h ;isp平臺操作集頭文件
│ isp_platform_drv.c ;isp平臺操作集實現(xiàn)
│ sunxi_isp.h ;sunxi平臺isp操作集頭文件
│ sunxi_isp.c ;sunxi平臺isp操作集實現(xiàn)
│
├─vin-mipi
│ bsp_mipi_csi.c ;底層mipi bsp函數(shù)
│ bsp_mipi_csi.h ;底層mipi bsp函數(shù)頭文件
│ bsp_mipi_csi_v1.c ;sunxi平臺底層mipi bsp接口函數(shù)
│ sunxi_mipi.c ;sunxi平臺mipi實現(xiàn)
│ bsp_mipi_csi.h ;sunxi平臺mipi實現(xiàn)頭文件
│ combo_common.c ;combo common頭文件
│ protocol.h ;protocol頭文件
├─vin-stat
│ vin_h3a.c ;vin 3a操作函數(shù)
│ vin_h3a.h ;vin 3a操作函數(shù)頭文件
│ vin_ispstat.c ;sunxi isp stat操作函數(shù)
│ vin_ispstat.h ;sunxi isp stat操作函數(shù)頭文件
│
├─vin-video
│ dma_reg.c ;csi模塊dma操作函數(shù)
│ dma_reg.h ;csi模塊dma操作函數(shù)頭文件
│ dma_reg_i.h ;csi dma寄存器資源頭文件
│ vin_core.c ;vin video核心函數(shù)
│ vin_core.h ;vin video核心函數(shù)頭文件
│ vin_video.c ;vin video設備接口函數(shù)
│ vin_video.h ;vin video設備接口函數(shù)頭文件
├─vin-vipp
│ sunxi_scaler.c ;scaler 子設備操作函數(shù)集
│ sunxi_scaler.h ;caler 子設備操作函數(shù)頭文件
│ vipp_reg.c ;vipp操作函數(shù)集
│ vipp_reg.h ;vipp操作函數(shù)集頭文件
│ vipp_reg_i.h ;vipp操作函數(shù)集資源頭文件
2.3.5 linux4.9 VIN 框架
驅動路徑位于linux-4.9/drivers/media/platform/sunxi-vin 下。
sunxi-vin:
│ vin.c ;v4l2驅動實現(xiàn)主體(包含視頻接口和ISP部分)
│ vin.h ;v4l2驅動頭文件
│ top_reg.c ;vin對各v4l2 subdev管理接口實現(xiàn)主體
│ 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公用操作接口函數(shù)文件
│ ├── 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上下電接口函數(shù)
│ ├── 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節(jié)點相關的接口定義
│ ├── vin_core.c
│ ├── vin_core.h
│ ├── vin_video.c
│ └── vin_video.h
└── vin-vipp
├── sunxi_scaler.c
├── sunxi_scaler.h
3 模塊開發(fā)
3.1 模塊體系結構描述
3.1.1 VFE 框架
? 使用過程中可簡單的看成是vfe 模塊+ device 模塊+af driver + flash 控制模塊的方式;
? vfe.c 是驅動的主要功能實現(xiàn),包括注冊/注銷、參數(shù)讀取、與v4l2 上層接口、與各device 的下層接口、中斷處理、buffer 申請切換等;
? device 文件夾里面是各個sensor 的器件層實現(xiàn),一般包括上下電、初始化,各分辨率切換,yuv sensor 包括絕大部分的v4l2 定義的ioctrl 命令的實現(xiàn);而raw
sensor 的話大部分 ioctrl 命令在vfe 層調用isp 的庫實現(xiàn),少數(shù)如曝光/增益調節(jié)會透過vfe 層到實際器件層;
? actuator 文件夾內是各種vcm 的驅動;
? flash_light 文件夾內是閃光燈控制接口實現(xiàn);
? 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 是驅動的主要功能實現(xiàn),包括注冊/注銷、參數(shù)讀取、與v4l2 上層接口、與各device 的下層接口、中斷處理、buffer 申請切換等;
? modules/sensor 文件夾里面是各個sensor 的器件層實現(xiàn),一般包括上下電、初始化,各分辨率切換,yuv sensor 包括絕大部分的v4l2 定義的ioctrl 命令的實
現(xiàn);而raw sensor 的話大部分ioctrl 命令在vin 層調用isp 庫實現(xiàn),少數(shù)如曝光/增益調節(jié)會透過vin 層到實際器件層;
? modules/actuator 文件夾內是各種vcm 的驅動;
? modules/flash 文件夾內是閃光燈控制接口實現(xiàn);
? vin-csi 和vin-mipi 為對csi 接口和mipi 接口的控制文件;
? vin-isp 文件夾為isp 的庫操作文件;
? vin-video 文件夾內主要是video 設備操作文件;
?
圖3-2: VIN
?
3.1.3 Camera 通路框架
? VIN 支持靈活配置單/雙路輸入雙ISP 多通路輸出的規(guī)格
? 引入media 框架實現(xiàn)pipeline 管理
? 將libisp 移植到用戶空間解決GPL 問題
? 將統(tǒng)計buffer 獨立為v4l2 subdev
? 將的scaler(vipp)模塊獨立為v4l2 subdev
? 將video buffer 修改為mplane 方式,使用戶層取圖更方便
? 采用v4l2-event 實現(xiàn)事件管理
? 采用v4l2-controls 新特性
?
圖3-3: camera Input
?
3.2 驅動模塊實現(xiàn)
3.2.1 硬件部分
檢查硬件電源,gpio 是否和原理圖一致并且正確連接;檢查sys_config.fex 或者board.dts 是否正確配置,包括使用的電源名稱和電壓,詳見CSI 板級配置章節(jié)說
明;如果是電源選擇有多個源頭的請確認板子上的連接正確,比如0ohm 電阻是否正確的焊接為0ohm,NC 的電阻是否有正確斷開等等。帶補光燈的也需要檢查
燈和driver IC 和控制io 是否連好。
3.2.2 內核device 模塊驅動
一般調試新模組的話建議以sdk 中的某個現(xiàn)成的驅動為基礎修改:YUV 的并口模組以R40 平臺(linux3.10) 的ov5640.c 為參考。
下面以ov5640.c 為例說明調試新模組需要注意的兩點:
添加Makefile
[linux-3.10/drivers/media/platform/sunxi-vfe/device/Makefile]
添加
obj-m + = ov5640.o (詳見1)
詳注:
1.具體取決于使用的模組,如果是新模組則將驅動代碼放置在該device目錄下。
配置模組參數(shù)
配置參數(shù)在linux-3.10/drivers/media/platform/sunxi-vfe/device/ov5640.c 中,只需注意下面兩個參數(shù)。
#define SENSOR_NAME "ov5640" (詳見1)
#define I2C_ADDR 0x78 (詳見2)
詳注:
1.該參數(shù)為模組名,必須和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 規(guī)格書找到,如下
?
圖3-4: timing
?
從上述的圖像可得到以下信息:
VSYNC 在低電平的時候,data pin 輸出有效數(shù)據,所以VREF_POL 設置為V4L2_MBUS_VSYNC_ACTIVE_即低電平有效;
HREF 在高電平的時候,data pin 輸出有效數(shù)據,所以HREF_POL 設置為V4L2_MBUS_HSYNC_ACTIVE_即高電平有效;
CLK_POL 則是表明SOC 是在sensor 輸出的pclk 上升沿采集data pin 的數(shù)據還是下降沿采集數(shù)據,如果sensor 在pclk 上升沿改變data pin 的數(shù)據,那么SOC
應該在下降沿采集,CLK_POL 設置為V4L2_MBUS_PCLK_SAMPLE_FALLING;如果sensor在pclk 下降沿改變data pin 的數(shù)據,那么SOC 應該在上降沿采集,
CLK_POL 設置為V4L2_MBUS_PCLK_SAMPLE_RISING。
#define V4L2_IDENT_SENSOR 0x2770
一般填寫sensor ID,用于sensor 檢測。sensor ID 可在sensor 規(guī)格書的找到,如下
?
圖3-5: sensorid
?
#define I2C_ADDR 0x6c
sensor I2C 通訊地址,可在sensor 規(guī)格書找到,如下
?
圖3-6: sccbid
?
#define SENSOR_NAME OV5640
定義驅動名字,與系統(tǒng)其他文件填寫的名字要一致,比如需要和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 曝光增益接口函數(shù)
static int sensor_s_exp(struct v4l2_subdev *sd, unsigned int exp_val) /* 曝光函數(shù)*/ static int sensor_s_gain(struct v4l2_subdev *sd, unsigned int gain_val) /* 增益函數(shù)*/
AE 是同時控制曝光時間和增益的,所以需要在上面的函數(shù)中分別同時sensor 曝光和增益的寄存器。
?
圖3-7: expgain
?
根據規(guī)格書中的寄存器說明,在相應的函數(shù)配置即可。若設置exp/gain 無效,可能的原因有:
? sensor 寄存器打開了AE;
? 設置值超出了有效范圍
具體可根據模組廠提供的配置設置,如若檢查之后設置仍失效,可與模組廠溝通,確認配置是否正確。
3.2.2.4 上下電控制函數(shù)
static int sensor_power(struct v4l2_subdev *sd, int on)
控制sensor 上電、下電及進出待機狀態(tài),操作步驟須與規(guī)格書描述相同,注意power down 和reset pin 的電平變化。
?
圖3-8: powerup
?
驅動中,按照規(guī)格書的上電時序進行配置,而如果上電之后測量硬件并沒有相應的電壓,這時候 檢查硬件和軟件配置是否一致。關于csi 電源的配置,操作流程可如下:
先通過原理圖確認sensor 模組的各路電源是連接到axp 的哪個ldo;
查看sys_config.fex 的regulator 配置,在相應的ldo 后增加相應的字段,比如“csi-vdd”等;
在sys_config.fex 的csi 部分,sensor 部分的電源后的字段再填寫與上述一樣的字段即可;
根據sensor 規(guī)格書的要求,填寫相應的電壓即可;
以上圖為例,確認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 檢測函數(shù)
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:/*設置對焦馬達配置參數(shù),在配置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。若填錯, 會導致色彩偏紫紅和出現(xiàn)網格狀紋理。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 數(shù),修改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 數(shù)據速率,MIPI sensor 必需,其他sensor 忽略*/ ? ?/* mipi_bps = hts * vts * fps * raw bit / lane num */ ? ?.mipi_bps = 480 * 1000 * 1000, ? ?/* 定義幀率,fps * hts * vts = pclk */ ? ?.fps_fixed = 30, ? ?/* ? ?定義曝光行數(shù)最小值和最大值,增益最小值和最大值,以16 為1 倍。最值的設置應在sensor 規(guī)格和 ? ?曝光函數(shù)限定的范圍內,若超出會導致畫面異常。此外,若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), ? ?}, };
根據應用的需求,在這里配置驅動能輸出的不同尺寸幀率組合,注意,一種分辨率、幀率配置為一個數(shù)組成員,不要混淆。
3.2.3 LVDS 接口須知
除了完成以上函數(shù)的實現(xiàn),LVDS Sensor 驅動還需要完成combo 同步校驗函數(shù)和combo 數(shù)據線映射函數(shù)。combo 校驗碼可以在sensor 規(guī)格書獲取,combo 數(shù)
據線映射關系需要查看原理圖設計進行配對,可參考imx274_slvds.c 完成開發(fā)。
?
圖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 實現(xiàn)延時,例如使用msleep 實現(xiàn)10~20ms的延時,通常會因為系統(tǒng)調度而變成延時更長的時間,這種做法精度較差。
所以如果需要使用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 模塊。
由于內核框架的不一樣,需要區(qū)分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驅動加載之前,具體驅動型號根據模組規(guī)格書進行確認。
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 modulesn" 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 modulesn" # 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 使用的配置方式 |
---|---|
F35 | sys_config.fex |
R16 | sys_config.fex |
R18 | sys_config.fex |
R30 | sys_config.fex |
R40 | sys_config.fex |
R311 | sys_config.fex |
MR133 | sys_config.fex |
R818 | board.dts |
MR813 | board.dts |
R528 | board.dts |
V536 | sys_config.fex |
V533 | board.dts |
V831 | board.dts |
V833 | board.dts |
V851 | board.dts |
V853 | board.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> csi0_mck = port:PE01<2> csi0_hsync = port:PE02<2> csi0_vsync = port:PE03<2> csi0_d0 = port:PE04<2> csi0_d1 = port:PE05<2> csi0_d2 = port:PE06<2> csi0_d3 = port:PE07<2> csi0_d4 = port:PE08<2> csi0_d5 = port:PE09<2> csi0_d6 = port:PE10<2> csi0_d7 = port:PE11<2> csi0_sck = port:PE12<2> csi0_sda = port:PE13<2> [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> csi_cci0_sda = port:PE02<2> [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 的數(shù)據鏈路 vinc0_used = 1 vinc0_csi_sel = 0 vinc0_mipi_sel = 0 vinc0_isp_sel = 0 vinc0_rear_sensor_sel = 1 ;配置使用sensor1 輸出圖像數(shù)據到video0 vinc0_front_sensor_sel = 1 ;配置使用sensor1 輸出圖像數(shù)據到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 輸入數(shù)據,該配置與硬件連接相關,可參考本文檔最后的其他注意事項章節(jié)。
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 = ,其他同理。 */ sensor0_iovdd-supply = ; sensor0_iovdd_vol = <1800000>; sensor0_avdd-supply = ; sensor0_avdd_vol = <2800000>; sensor0_dvdd-supply = ; sensor0_afvdd-supply = ;/*根據硬件原理圖,確定配的哪路電*/ sensor0_afvdd_vol = <2800000>;/*根據硬件原理圖,確認工作電壓*/ sensor0_dvdd_vol = <1200000>; sensor0_power_en = <>; /* 根據板子實際連接,修改 reset、pwdn 的引腳即可 */ /* GPIO 信息配置:pio 端口 組內序號 功能分配 內部電阻狀態(tài) 驅動能力 輸出電平狀態(tài) */ 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 = ; sensor1_iovdd_vol = <1800000>; sensor1_avdd-supply = ; sensor1_avdd_vol = <2800000>; sensor1_dvdd-supply = ; 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 的通道數(shù),一般配置為 0 */ vinc0_tdm_rx_sel = <0>; /* 與 isp_sel 保持一致即可 */ vinc0_rear_sensor_sel = <0>; /* 該 video 可以選擇從哪個 sensor 輸入圖像數(shù)據 */ 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 節(jié)點,內核配置 CONFIG_SUPPORT_ISP_TDM=n,此時 * 不同 sensor 輸出的節(jié)點不能同時使用,比如以下配置的 video0 不可以和 video2 video3 同時使用 */ vinc0:vinc@0 { vinc0_csi_sel = <0>; vinc0_mipi_sel = <0>; vinc0_isp_sel = <0>; vinc0_isp_tx_ch = <0>; vinc0_tdm_rx_sel = <0>; vinc0_rear_sensor_sel = <0>; vinc0_front_sensor_sel = <0>; vinc0_sensor_list = <0>; status = "okay"; }; vinc1:vinc@1 { vinc1_csi_sel = <0>; vinc1_mipi_sel = <0>; vinc1_isp_sel = <0>; vinc1_isp_tx_ch = <0>; vinc1_tdm_rx_sel = <0>; 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 = <0>; vinc2_isp_tx_ch = <0>; vinc2_tdm_rx_sel = <0>; 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 = <0>; vinc3_isp_tx_ch = <0>; vinc3_tdm_rx_sel = <0>; vinc3_rear_sensor_sel = <1>; vinc3_front_sensor_sel = <1>; vinc3_sensor_list = <0>; status = "okay"; }; /* 以下配置將可以從兩路 sensor 同時輸入,內核配置 CONFIG_SUPPORT_ISP_TDM=y,但是有個限制, * 只能先運行 video0,然后才可以運行 video2,關閉的時候也是如此,先關 video2,再關 video0 */ vinc0:vinc@0 { vinc0_csi_sel = <0>; vinc0_mipi_sel = <0>; vinc0_isp_sel = <0>; vinc0_isp_tx_ch = <0>; vinc0_tdm_rx_sel = <0>; vinc0_rear_sensor_sel = <0>; vinc0_front_sensor_sel = <0>; vinc0_sensor_list = <0>; status = "okay"; }; vinc1:vinc@1 { vinc1_csi_sel = <0>; vinc1_mipi_sel = <0>; vinc1_isp_sel = <0>; vinc1_isp_tx_ch = <0>; vinc1_tdm_rx_sel = <0>; 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"; };
修改該文件之后,需要重新編譯固件再打包,才會更新到dts。同時,如果需要使用雙攝,雙攝分別使用到兩個ISP,那么內核需要選上SUPPORT_ISP_TDM 配置。
4.3 menuconfig 配置說明
在命令行進入Tina 根目錄,執(zhí)行命令進入配置主界面:
source build/envsetup.sh (詳見1) lunch 方案編號(詳見2) make menuconfig (詳見3) 詳注: 1.加載環(huán)境變量及tina提供的命令; 2.輸入編號,選擇方案; 3.進入配置主界面(對一個shell而言,前兩個命令只需要執(zhí)行一次)
make menuconfig 配置路徑:
Kernel modules └─>Video Support └─>kmod-sunxi-vfe(vfe框架的csi camera) (詳見1) └─>kmod-sunxi-vin(vin框架的csi camera) (詳見2) └─>kmod-sunxi-uvc(uvc camera) (詳見3) 詳注: 1.平臺使用vfe框架的csi camera選擇該驅動; 2.平臺使用vin框架的csi camera選擇該驅動;(該項與vfe框架,在同一個平臺只會出現(xiàn)其中一個) 3.usb camera選擇該驅動;
在完成sensor 驅動編寫,modules.mk 和板級配置后,通過make menuconfig 選上相應的驅動,camera 即可正常使用。下面以R40 平臺介紹。首先,選擇
Kernel modules 選項進入下一級配置,如下圖所示:
?
圖4-1: menuconfig
?
然后,選擇Video Support 選項,進入下一級配置,如下圖所示:
?
圖4-2: video
?
最后,選擇kmod-sunxi-vfe 選項,可選擇<*> 表示編譯包含到固件,也可以選擇表示僅編譯不包含在固件。如下圖所示:
?
圖4-3: sunxi
?
4.4 如何增加ISP 效果配置
在完成ISP 調試之后,將會從ISP 調試工程師中得到相應的頭文件配置,添加操作如下:
4.4.1 VFE 框架
將頭文件添加到驅動的sunxi-vfe/isp_cfg/SENSOR_H 目錄下;
在驅動sunxi-vfe/isp_cfg 目錄下,有個isp_cfg.c 文件,這文件中有個isp_cfg_array 數(shù)組,在sensor 的ISP 配置文件最下面也有個相應的結構體,在
isp_cfg_array 數(shù)組中按照數(shù)組的結構,增加sensor 的name 和結構體即可,這樣將會在ISP 匹配的時候,將會根據name 匹配到相應的配置;
4.4.2 VIN 框架
4.4.2.1 R 系列
vin 框架的操作也是類似的,只是更換了位置。vin 的ISP 配置在tina/package/allwinner/libAWIspApi 目錄下,其中R311、MR133 在src/isp520,而R818、
MR813 在src/isp522。在libisp/isp_cfg/SENSOR 目錄下增加相應的頭文件,然后在上一層目錄的isp_ini_parse.c 文件增加頭文件以及修改相應的isp_cfg_array cfg_arr 數(shù)組匹配即可。
VIN 使用ISP,需要在camerademo 中make menuconfig 的時候,選擇上Choosewhether to use VIN ISP (YES)。同時VIN 的需要注意,當自己開發(fā)camera
HAL 層時,需要自己運行camera ISP service,具體實現(xiàn)可參考camerademo 的實現(xiàn)。添加正確時,在運行camerademo 將會輸出相應的sensor 配置信息,
比如:
[ISP]find imx278_mipi_2048_1152_60_0 [imx278_mipi_default_ini_mr813] isp config
上述表示正確查找到imx278_mipi 這個sensor 2048*1152 60fps 的ISP 配置,其他的sensorISP 配置移植正確也將會有類似的打印,輸出信息分別是sensor name 、分辨率、幀率,確認這些信息一致即可。
4.4.2.2 V 系列
V 系列ISP 庫目錄,V533、V83x 平臺位于:softwinner/eyesee-mpp/middleware/sun8iw19p1/media/V536 平臺位于:softwinner/eyesee-
mpp/middleware/v316/media/LIBRARY/libisp/,V85x 平臺位于:external/eyesee-mpp/middleware/sun8iw21/media/LIBRARY/libisp/
修改libisp/isp_cfg/isp_ini_parse.c,將ISP 效果.h 包含進來,并修改struct isp_cfg_arraycfg_arr[] 結構體;其中參數(shù)定義:
(1)Sensor 模塊名稱:sensor_mipi (2)ISP 效果頭文件名稱 (3)分辨率寬 (4)分辨率高 (5)幀率 (6)紅外IR 模式標志位 (7)WDR 模式標志位 (8)ISP 參數(shù)結構體
?
圖4-4: sunxi
?
4.5 如何輸出RAW 數(shù)據
在ioctl 的VIDIOC_S_FMT 命令,將其參數(shù)pixelformat 設置為RAW 格式即可,RAW 格式如下:
V4L2_PIX_FMT_SBGGR8 V4L2_PIX_FMT_SGBRG8 V4L2_PIX_FMT_SGRBG8 V4L2_PIX_FMT_SRGGB8 V4L2_PIX_FMT_SBGGR10 V4L2_PIX_FMT_SGBRG10 V4L2_PIX_FMT_SGRBG10 V4L2_PIX_FMT_SRGGB10 V4L2_PIX_FMT_SBGGR12 V4L2_PIX_FMT_SGBRG12 V4L2_PIX_FMT_SGRBG12 V4L2_PIX_FMT_SRGGB12
將pixelformat 設置為上述的其一即可輸出RAW 數(shù)據, 而如何選擇上述的操作, 這個根據sensor 驅動選擇, 如果驅動中sensor_formats 的mbus_code 設置為
MEDIA_BUS_FMT_SBGGR10_1X10,則在輸出RAW 數(shù)據時將pixelformat 設置為V4L2_PIX_FMT_SBGGR10
當前camerademo 已經支持輸出RAW 數(shù)據,可參照本文檔《camerademo 輸出RAW 數(shù)據》章節(jié)。
4.6 如何計算實際曝光時間
該部分為使用到ISP 的RAW sensor 配置信息。曝光時間的計算和曝光控制寄存器、hts、pclk這些配置相關,這些配置都在sensor 驅動,ISP 將會根據sensor 驅
動中的設置計算相應的曝光時間,所以驅動中的配置必須正確,否則在調試ISP 效果可能會遇到其他的一些問題。
static struct sensor_win_size sensor_win_sizes[] = { ... .hts = 928, .vts = 1720, .pclk = 48 * 1000 * 1000, ... }
在sensor 的驅動中有以上的一些配置,曝光時間在驅動中是以曝光行為計算單位的,即在sensor_s_exp() 函數(shù)中設置的參數(shù)為曝光行,部分sensor 是以16 為一
倍的,所以在計算實際的曝光行時,需要將上述函數(shù)參數(shù)除以16。
曝光時間= 曝光行× hts / pclk
一般的pclk 都是M 級別的,所以時間單位為us,部分sensor 的曝光行為參數(shù)的十六分之一,需要除以十六,同時,曝光行不能大于vts 的值,否則將會出現(xiàn)降
幀、沒有正常輸出圖像等問題。
4.7 如何脫離isp tuning 工具微調圖像亮度
在isp 配置文件中,有類似以下的信息:
.ae_cfg = { 256, 555, 256, 555, 31, 22, 22, 25, 3, 130, 16, 60, 1, 2 },
上述ae_cfg 參數(shù)的倒數(shù)第4 個數(shù)值(130)即是控制圖像亮度的閥門(期望亮度),該值越大,圖像亮度越高。ae_cfg 一共14 個,分別對應著不同的環(huán)境亮度
(Lux)。如何確定AE 當前處于哪組ae_cfg 參數(shù)呢?修改isp 配置文件中的isp_log_param = 0x1,然后重新編譯運行相機應用,留意應用中關于isp 的打印信息:
[ISP_DEBUG]: isp0 ae_target 92, pic_lum 0, weight_lum 0, delta_exp_idx 138, ae_delay 0, AE_TOLERANCE
5
從上述信息可以看到當前的目標亮度是92,這時可以查看isp 配置文件ae_cfg 中哪組的閥門處于92 這個范圍,如果需要增加亮度,則提高相應的閥門;降低亮度
則降低閥門。相應的根據實際調試情況修改即可。調試之后,記得將isp_log_param 參數(shù)還原為0。
4.8 VIN 如何設置裁剪和縮放
裁剪修改sensor 驅動:在驅動有類似以下的配置
static struct sensor_win_size sensor_win_sizes[] = { { .width = VGA_WIDTH, .height = VGA_HEIGHT, .hoffset = 0, .voffset = 0, .hts = 878, .vts = 683, .pclk = 72 * 1000 * 1000, .mipi_bps = 720 * 1000 * 1000, .fps_fixed = 120, .bin_factor = 1, .intg_min = 1 << 4, ? ? ? ?.intg_max = (683) << 4, ? ? ? ?.gain_min = 1 << 4, ? ? ? ?.gain_max = 16 << 4, ? ? ? ?.regs = sensor_VGA_120fps_regs, ? ? ? ?.regs_size = ARRAY_SIZE(sensor_VGA_120fps_regs), ? ? ? ?.set_size = NULL, ? ?}, };
上述的width height 表示經過isp 輸出之后的數(shù)據,如果需要裁剪,修改width、height、hoffset 和voffset。裁剪之后的輸出width = sensor_output_src -
2hoffset height = sensor_height_src - 2voffset 注意,上述的hoffset voffset 必須為雙數(shù)。
所以,假設sensor 輸出的是640 × 480,我們想裁剪為320 × 240 的,則上述配置修改為:
static struct sensor_win_size sensor_win_sizes[] = { { .width = 320, .height = 240, .hoffset = 160, .voffset = 120, .hts = 878, .vts = 683, .pclk = 72 * 1000 * 1000, .mipi_bps = 720 * 1000 * 1000, .fps_fixed = 120, .bin_factor = 1, .intg_min = 1 << 4, ? ? ? ?.intg_max = (683) << 4, ? ? ? ?.gain_min = 1 << 4, ? ? ? ?.gain_max = 16 << 4, ? ? ? ?.regs = sensor_VGA_120fps_regs, ? ? ? ?.regs_size = ARRAY_SIZE(sensor_VGA_120fps_regs), ? ? ? ?.set_size = NULL, ? ?}, };
縮放配置:使用硬件縮放,可以在應用層通過VIDIOC_S_FMT 設置分辨率的時候,直接設置分辨率的大小為縮放的分辨率即可。
fmt.fmt.pix_mp.width = 320; fmt.fmt.pix_mp.height = 240;
上述的操作,將會使用硬件完成相應的縮放輸出。
5 模塊調試常見問題
初次調試建議打開device 中的DEV_DBG_EN 為1,方便調試。
Camera 模塊調試一般可以分為三步:
使用lsmod 命令查看驅動是否加載,查看/lib/modules/內核版本號目錄下是否存在相應的ko,如果沒有,確認modules.mk 是否修改正確,配置了開機自動
加載。如果存在相應的ko,可手動加載測試確認ko 是否正常,手動加載成功,則確認內核的版本是否一致,導致開機時沒有找到相應的ko 從而沒有加載。
使用ls /dev/v* 查看是否有video0/1 節(jié)點生成
在adb shell 中使用cat /proc/kmsg 命令,或者是使用串口查看內核的打印信息,查看不能正常加載的原因。一般情況下驅動加載不成功的原因有:一是讀取
的sys_config.fex 文件中的配置信息與加載的驅動不匹配,二是probe 函數(shù)遇到某些錯誤沒能正確的完成probe 的時候返回。
5.1 移植一款sensor 需要進行哪些操作
移植camera sensor,主要進行以下操作:
根據主板的原理圖,確認與sensor 模組的接口是否一致,一致才可以保證配置和數(shù)據的正常接收。
根據產品的需求,讓sensor 模組廠提供產品所需的分辨率、幀率的寄存器配置,這一步需要注意,提供的配置需要是和模組匹配的。比如模組的mipi 接口只
引出2lane,而提供的寄存器配置卻是配置為4lane 輸出的,那么該配置在該模組無法正常使用,讓模組廠提供該模組可以正常使用的正確配置。注意,該寄存
器配置SOC 原廠沒有,需要sensor 廠提供。
拿到寄存器配置之后,按照本文檔《驅動模塊實現(xiàn)》章節(jié)完成sensor 驅動的編寫。
在完成驅動的編寫之后,按照本文檔《Tina 配置》章節(jié)完成modules.mk 的修改。
根據板子的原理圖與模組的硬件連接,參照本文檔《sys_config.fex 配置》或者《MR813/R818平臺配置》章節(jié)完成sys_config.fex 或者board.dts 的修改。
完成上述操作之后,按照本文檔《menuconfig 配置說明》章節(jié),選上camera 驅動模塊,按照《camera 功能測試》章節(jié)選上camera 的測試程序,測試驅動
移植是否正常。
5.2 I2C 通信出現(xiàn)問題
5.2.1 R16 R11 R40 等
I2C 出現(xiàn)問題內核一般會伴隨打印” cci_write_aX_dX error! slave = 0xXX, addr = 0xXX,value = 0xXX“。
如果與此同時,內核出現(xiàn)打印“chip found is not an target chip.”,則說明在初始化camera前,讀取camera 的ID 已經失敗。此時,一般是如下幾點出現(xiàn)問題。
a. 最先考慮應該是更換一個camera模組試試。 b. 電源 檢查sys_config.fex vip_dev0_iovdd = "axp22_eldo3" vip_dev0_iovdd_vol = 2800000 vip_dev0_avdd = "axp22_dldo4" vip_dev0_avdd_vol = 2800000 vip_dev0_dvdd = "axp22_eldo2" vip_dev0_dvdd_vol = 1500000 一定要與原理圖設計保持一致。必要時,需要用萬用表測量camera模組的各路電壓是否正常。 c. reset和power down腳 檢查sys_config.fex配置 vip_dev0_reset = port:PH2<1> vip_dev0_pwdn = port:PH1<1> 是否與原理圖設計保持一致。必要時,需要用示波器測量reset,pwdn腳,在camera加載時,是否有動作。 d. mclk 檢查sys_config.fex配置 vip_csi_mck = port:PE01<3> pin腳是否與原理圖設計保持一致。必要時,在加載camera時,測量mclk,看是否有正確輸出(一般是24MHz或27MHz )
如果已經能夠正確通過camera 的id 讀取,只是在使用過程當中,偶爾出現(xiàn)I2C 的讀寫錯誤,此時需要從打印里面,將報錯的地址和讀寫值,結合camera 具體的
spec 來分析,到底是操作了camera 哪些寄存器帶來的問題。
5.2.2 其他平臺
出錯時一般出現(xiàn)以下信息:
[ 5.556579] sunxi_i2c_do_xfer()1942 - [i2c1] incomplete xfer (status: 0x20, dev addr: 0 x30) [ 5.566234] sunxi_i2c_do_xfer()1942 - [i2c1] incomplete xfer (status: 0x20, dev addr: 0 x30) [ 5.575963] sunxi_i2c_do_xfer()1942 - [i2c1] incomplete xfer (status: 0x20, dev addr: 0 x30) [ 5.585375] [VIN_DEV_I2C]sc031gs_mipi sensor read retry = 2 [ 5.591666] [sensorname_mipi] error, chip found is not an target chip.
出現(xiàn)上述錯誤打印時,可按以下操作逐步debug。
確認sys_config.fex 中配置的sensor I2C 地址是否正確(sensor datasheet 中標注,讀地 址為0x6d,寫地址為0x6c,那么sys_config.fex 配置sensor I2C 地址為0x6c);
在完成以上操作之后,在senor 上電函數(shù)中,將掉電操作屏蔽,保持sensor 一直上電狀態(tài), 方便debug;
確認I2C 地址正確之后,測量sensor 的各路電源電壓是否正確且電壓幅值達到datasheet 標注的電壓要求;
測量MCLK 的電壓幅值與頻率,是否正常;
測量senso r 的reset、pown 引腳電平配置是否正確,I2C 引腳SCK、SDA 是否已經硬件 上拉;
確認I2C 接口使用正確并使能(CCI / TWI);
如果還是I2C 出錯,協(xié)調硬件同事使用邏輯分析儀等儀器進行debug;
5.2.3 經典錯誤
5.2.3.1 I2C 沒有硬件上拉
twi_start()450 - [i2c2] START can't sendout! twi_start()450 - [i2c2] START can't sendout! twi_start()450 - [i2c2] START can't sendout! [VFE_DEV_I2C_ERR]cci_write_a16_d16 error! slave = 0x1e, addr = 0xa03e, value = 0x1
出現(xiàn)上述的問題是因為SDA、SCK 沒有拉上,導致在進行I2C 通信時,發(fā)送開始信號失敗,SDA、SCK 添加上拉即可。
5.2.3.2 沒有使能I2C
[VFE]Sub device register "ov2775_mipi" i2c_addr = 0x6c start! [VFE_ERR]request i2c adapter failed! [VFE_ERR]vfe sensor register check error at input_num = 0
出現(xiàn)上述的錯誤,是因為使用twi 進行I2C 通信但沒有使能twi 導致的錯誤,此時需要確認sys_config.fex 中,[twiX] 中的twiX_used 是否已經設置為1。
5.3 圖像異常
5.3.1 運行camerademo 可以成功采集圖像,但圖像全黑(RAWsensor)
當camerademo 成功采集到圖像時,最起碼整條數(shù)據通路已經正常,而發(fā)現(xiàn)圖像時全黑的,注意以下幾點:
在編譯camerademo 之前,是根據平臺(MR813/R818/MR133/R311) 正確的選上了“Enable vin isp support”,選上之后,重新編譯camerademo
(建議cd package/allwinner/-camerademo 目錄后執(zhí)行mm -B 編譯);
通過上述操作之后, 執(zhí)行新編譯的camerademo 可執(zhí)行程序, 運行過程應可看到類似”[ISP]create isp0 server thread?‘信息,則正確運行isp,這時再查看新
抓取的圖像數(shù)據;
執(zhí)行運行camerademo 只會抓取5 張圖像數(shù)據,由于isp 計算合適的圖像曝光需要一定的幀數(shù),所以可能存在前面幾張圖像黑的情況,修改camerademo 運行
參數(shù),抓取多幾張圖像數(shù)據查看(20 張);
如果是沒有移植isp 的環(huán)境,則可修改sensor 驅動中寄存器組中的曝光參數(shù)配置,增加初始化時曝光時間,從而使初始輸出的圖像亮度較合適;
5.3.2 camerademo 采集的圖像顏色異常
運行camerademo 采集圖像之后,發(fā)現(xiàn)拍攝得到的輪廓正確但顏色不對,比如紅藍互換、畫面整體偏紅或偏藍等顏色異常的情況,出現(xiàn)這樣的問題,首先考慮是
sensor 驅動中配置的RAW 數(shù)據RGB 順序錯誤導致的。在sensor 驅動中有類似以下的配置:
static struct sensor_format_struct sensor_formats[] = { { .desc = "Raw RGB Bayer", .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, .regs = sensor_fmt_raw, .regs_size = ARRAY_SIZE(sensor_fmt_raw), .bpp = 1 }, };
以上配置表明sensor 輸出的圖像數(shù)據是RAW10,RGB 排列順序是BGGR,出現(xiàn)顏色異常時,一般就是RGB 的排列順序配置錯誤導致的,RGB 排列順序一共有4 種
(MEDIA_BUS_FMT_SBGGR10_1X10/MEDIA_BUS_FMT_SGBRG10_1X10/MEDIA_BUS_FMT_SGRBG10_修改驅動中的mbus_code 為上述的4 種之一,確認哪一種
顏色比較正常,則驅動配置正確。
如果顏色還有細微的不夠艷麗、準確等問題,需要進行isp 效果調試,改善圖像色彩。上述是以10bit sensor 為例進行介紹,其他的8bit、12bit、14bit 類似,參
考上述即可。
5.4 調試camera 常見現(xiàn)象和功能檢查
insmod 之后首先看內核打印,看加載有無錯誤打印,部分驅動在加載驅動進行上下電時候會進行i2c 操作,如果此時報錯的話就不需要再進入camera 了,先
檢查是否io 或電源配置不對。或者是在復用模組時候有可能是另外一個模組將i2c 拉住了。
如果i2c 讀寫沒有問題的話,一般就可以認為sensor 控制是ok 的,只需要根據sensor 的配置填好H/VREF、PCLK 的極性就能正常接收圖像了。這個時候可以
在進入camera 應用之后用示波器測量sensor 的各個信號,看h/vref、pclk 極性、幅度是否正常(2.8V 的vpp)。
如果看到畫面了,但是看起來是綠色和粉紅色的,但是有輪廓,一般是YUYV 的順序設置反了,可檢查yuyv 那幾個寄存器是否填寫正確配置,其次,看是否是
在配置的其他地方有填寫同一個寄存器的地方導致將yuyv fmt 的寄存器被改寫。
如果畫面顏色正常,但是看到有一些行是粉紅或者綠色的,往往是sensor 信號質量不好所致,通常在比較長的排線中出現(xiàn)這個情況。在信號質量不好并且
yuyv 順序不對的時候也會看見整個畫面的是綠色的花屏。
當驅動能力不足的時候增強sensor 的io 驅動能力有可能解決這個問題。此時用示波器觀察pclk 和數(shù)據線可能會發(fā)現(xiàn):pclk 波形擺幅不夠IOVDD 的幅度,或者
是data 輸出波形擺幅有時候能高電平達到IOVDD 的幅度,有時候可能連一半都不夠。
如果是兩個模組復用數(shù)據線的話,不排除是另外一個sensor 在進入standby 時候沒有將其數(shù)據線設置成高阻,也會影響到當前模組的信號擺幅,允許的話可
以剪斷另一個模組來證實。
當畫面都正常之后檢查前置攝像頭垂直方向是否正確,水平方向是否是鏡像,后置水平垂直是否正確,不對的話可以調節(jié)sys_config.fex 中的hflip 和vflip 參數(shù)
來解決,但如果屏幕上看到的畫面與人眼看到的畫面是成90 度的話,只能是通過修改模組的方向來解決。
之后可以檢查不同分辨率之間的切換是否ok,是否有切換不成功的問題;以及拍照時候是否圖形正常,亮度顏色是否和預覽一致;雙攝像頭的話需要檢查前后
切換是否正常。
如果上述都沒有問題的話,可認為驅動無大問題,接下來可以進行其他功能(awb/exp bias/-color effect 等其他功能的測試)。
測試對焦功能,單次點觸屏幕,可正確對上不同距離的物體;不點屏幕時候可以自動對焦對上畫面中心物體,點下拍照后拍出來的畫面能清晰。
打開閃光燈功能,檢查在單次對焦時候能打開燈,對完之后無論成功失敗或者超時能夠關閉,在點下拍照之后能打開,拍完之后能關閉。
如果加載模塊后,發(fā)現(xiàn)dev/videoX 節(jié)點沒有生成,請檢查下面幾點。
a. 模塊加載的順序 一定要按照以下順序加載模塊 insmod videobuf-core.ko insmod videobuf-dma-contig.ko ;如果有對應的vcm driver,在這里加載,如果沒有,請省略。 insmod actuator.ko insmod ad5820_act.ko ;以下是camera驅動和vfe驅動的加載,先安裝一些公共資源。 insmod vfe_os.ko insmod vfe_subdev.ko insmod cci.ko insmod ov5640.ko insmod gc0308.ko ;如果一個csi接兩個camera,所有camera對應的ko都要在vfe_v4l2.ko之前加載。 insmod vfe_v4l2.ko b. sys_config.fex配置 vip_used = 1 ;確保used為1 vip_dev_qty = 2 ;確保csi接口上接的camera數(shù)量與ko加載情況相同 vip_dev0_mname = "ov5640" ;確保camera型號與ko加載情況相同 vip_dev0_twi_id = 1 ;確保camera使用的i2c總線id與配置一樣 vip_dev1_mname = "gc0308" ;確保camera型號與ko加載情況相同 vip_dev1_twi_id = 1 ;確保camera使用的i2c總線id與配置一樣
5.5 畫面大體輪廓正常,顏色出現(xiàn)大片綠色和紫紅色
一般可能是csi 采樣到的yuyv 順序出現(xiàn)錯位。
確認camera 輸出的yuyv 順序的設置與camera 的spec 一致 若camera 輸出的yuyv 順序沒有問題,則可能是由于走線問題,導致pclk 采樣data 時發(fā)生錯位,此時可以調整pclk 的采樣沿。具體做法如下:
在對應的camara 驅動源碼,如ov5640.c 里面,找到宏定義#define CLK_POL。此宏定義可以有兩個值V4L2_MBUS_PCLK_SAMPLE_RISING 和
V4L2_MBUS_PCLK_SAMPLE_FALLING。若原來是其中一個值,則修改成另外一個值,便可將PCLK 的采樣沿做反相。
5.6 畫面大體輪廓正常,但出現(xiàn)不規(guī)則的綠色紫色條紋
一般可能是pclk 驅動能力不足,導致某個時刻采樣data 時發(fā)生錯位。
解決辦法:
? 若pclk 走線上有串聯(lián)電阻,嘗試將電阻阻值減小。
? 增強pclk 的驅動能力,需要設置camera 的內部寄存器。
5.7 畫面看起來像油畫效果,過渡漸變的地方有一圈一圈
一般是CSI 的data 線沒有接好,或短路,或斷路。
5.8 出現(xiàn)[VFE_WARN] Nobody is waiting on thisvideo buffer
上層還回來所有的buffer,但是沒有再來取buffer。
5.9 出現(xiàn)[VFE_WARN] Only three buffer left for csi
上層占用了大部分buffer,沒有還回,驅動部分只有三個buffer 此時驅動不再進行buffer 切換,直到有buffer 還回為止。
5.10 sensor 的硬件接口注意事項
如果是使用并口的sensor 模組,會使用到720p@30fps 或更高速度的,必須在mclk/pclk/- data/vsync/hsync 上面串33ohm 電阻,5M 的sensor 一律串電阻;
使用Mipi 模組時候PCB layout 需要盡量保證clk/data 的差分對等長,過孔數(shù)相等,特征 阻抗100ohm;
如果使用并口復用pin 的模組時候,不建議reset 腳的復用;
并口模組的排線長度加上pcb 板上走線長度不超過10cm,mipi 模組排線長度加上pcb 板上 走線長度不超過20cm,超過此距離不保證能正常使用。
主控并口數(shù)據線有D11~D0 共12bit,并口的sensor 輸出一般為8/10bit,原理圖連接需 要做高位對齊。
6 camera 功能測試
Tina 系統(tǒng)可以通過SDK 中的camerademo 包來驗證camera sensor(usb camera)是否移植成功,如果可以正常捕獲保存圖像數(shù)據,則底層驅動、板子硬件正常。
6.1 camerademo 配置
在命令行中進入Tina 根目錄,執(zhí)行make menuconfig 進入配置主界面,并按以下配置路徑操作:
Allwinner └─>camerademo
首先,選擇Allwinner 選項進入下一級配置,如下圖所示:
?
圖6-1: allwinner
?
然后,選擇camerademo 選項,可選擇<*> 表示直接編譯包含在固件,也可以選擇表示僅編譯不包含在固件。當平臺的camera 框架是VIN 且需要使用ISP 時,將
需要在camerademo 的選項處點擊回車進行以下界面選擇使能ISP。(該選項只能在VIN 框架中,使用RAW sensor時使用,在修改該選項之后,需要先單獨mm -
B 編譯該package)。
?
圖6-2: camerademo
?
?
圖6-3: vinisp
?
6.2 源碼結構
camerademo 的源代碼位于package/allwinner/camerademo/目錄下:
|---src | camerademo.c //camea測試的主流程代碼 | camerademo.h //camera demo相關數(shù)據結構 | common.c //實現(xiàn)共用的函數(shù),轉換時間、保存文件、測試幀率等 | common.h //共用函數(shù)頭文件 | convert.c //實現(xiàn)圖像格式轉換函數(shù) | convert.h //圖像格式轉換函數(shù)頭文件
6.3 camerademo 使用方法
在小機端加載成功后輸入camerademo help,假如驅動產生的節(jié)點video0(測試默認以/dev/video0 作為設備對象)可以打開則會出現(xiàn)下面提示:
通過提示我們可以得到一些提示信息,了解到該程序的運行方式、功能,可以查詢sensor 支持的分辨率、sensor 支持的格式以及設置獲取照片的數(shù)量、數(shù)據保存
的格式、路徑、添加水印、測試數(shù)據輸出的幀率、從open 節(jié)點到數(shù)據流打通需要的時間等,help 打印信息如下圖:
?
圖6-4: help
?
Camerademo 共有4 種運行模式:
默認方式:直接輸入camerademo 即可,在這種運行模式下,將設置攝像頭為640*480 的NV21 格式輸出圖像數(shù)據,并以BMP 和YUV 的格式保存在/tmp 目
錄下,而當輸入camerademodebug 將會輸出更詳細的debug 信息;
探測設置camerademo setting:將會在運行過程中根據具體camera 要求輸入設置參數(shù),當輸入camerademo setting debug 的時候,將會輸出詳細的debug 信息;
快速設置:camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7],將會按照輸入參數(shù)設置圖像輸出,同樣,當輸入camerademo argv[1]
argv[2] argv[3] argv[4] argv[5] argv[6] argv[7] debug 時將會輸出更詳細的debug 信息。
選擇camera 設置:camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7] argv[8],將會按照輸入參數(shù)設置圖像輸出,同樣,當輸入
camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7] argv[8] debug 時將會輸出更詳細的debug 信息。
6.3.1 默認方式
當輸入camerademo 之后,使用默認的參數(shù)運行,則會打印一下信息,如下圖:
?
圖6-5: camerademouser
?
首先可以清楚的看到成功open video0 節(jié)點,并且知道照片數(shù)據的保存路徑、捕獲照片的數(shù)量以及當前設置:是否添加水印、輸出格式、分辨率和從開啟流傳輸?shù)?/p>
第一幀數(shù)據達到時間間隔等信息。如果需要了解更多的詳細信息,可以在運行程序的時候輸入參數(shù)debug 即運行camerademo debug,將會打開demo 的debug
模式,輸出更詳細的信息,包括camera 的驅動類型,支持的輸出格式以及對應的分辨率,申請buf 的信息,實際輸出幀率等。
6.3.2 選擇方式
在選擇模式下有兩種運行方式,一種是逐步選擇,在camera 的探測過程,知道其支持的輸出格式以及分辨率之后再設置camera 的相關參數(shù);另一種是直接在運
行程序的時候帶上相應參數(shù),程序按照輸入參數(shù)運行(其中還可以選擇camera 索引,從而測試不同的camera)。
輸入camerademo setting,則按照程序的打印提示輸入相應選擇信息即可。 ? 輸入保存路徑、照片數(shù)量、保存的格式等。
?
圖6-6: info
?
? 選擇輸出格式。
?
圖6-7: format
?
? 選擇輸出圖像分辨率。
?
圖6-8: size
?
其它信息與默認設置一致,如需打印詳細的信息,運行camerademo setting debug 即可。
第二種是設置參數(shù): ? 默認的video 0 節(jié)點:camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7]。 輸入參數(shù)代表意義如下:
argv[1]:camera輸出格式---NV21 YUYV MJPEG等; argv[2]:camera分辨率width; argv[3]:camera分辨率height; argv[4]:sensor輸出幀率; argv[5]:保存照片的格式:all---bmp和yuv格式都保存、bmp---僅以bmp格式保存、yuv---僅以yuv格式保存; argv[6]:捕獲照片的保存路徑; argv[7]:捕獲照片的數(shù)量;
例如:camerademo NV21 640 480 30 yuv /tmp 2,將會輸出640*480@30fps 的NV21格式照片以yuv 格式、不添加水印保存在/tmp 路徑下,照片共2 張。
其它信息與默認設置一致,如需打印詳細的信息,運行camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7] debug 即可。
?
圖6-9: run1
?
? 選擇其他的video 節(jié)點:camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7] argv[8]。
輸入參數(shù)代表意義如下:
argv[1]:camera輸出格式---NV21 YUYV MJPEG等; argv[2]:camera分辨率width; argv[3]:camera分辨率height; argv[4]:sensor輸出幀率; argv[5]:保存照片的格式:all---bmp和yuv格式都保存、bmp---僅以bmp格式保存、yuv---僅以yuv格式保存; argv[6]:捕獲照片的保存路徑; argv[7]:捕獲照片的數(shù)量; argv[8]:video節(jié)點索引;
例如:camerademo YUYV 640 480 30 yuv /tmp 1 1,將會打開/dev/video1 節(jié)點并輸出640*480@30fps 的以yuv 格式、不添加水印保存在/tmp 路徑下,照片共
1 張。
其它信息與默認設置一致,如需打印詳細的信息,運行camerademo argv[1] argv[2] argv[3] argv[4] argv[5] argv[6] argv[7] argv[8] debug 即可。
?
圖6-10: run2
?
6.3.3 camerademo 保存RAW 數(shù)據
當需要使用camerademo 保存RAW 數(shù)據時,只需要將輸出格式設置為RAW 格式即可。先確認sensor 驅動中的mbus_code 設置為多少位, 假設驅動中, 配置為
mbus_code =MEDIA_BUS_FMT_SGRBG10_1X10,那么可以確認sensor 輸出是RAW10,camerademo 的輸出格式設置為RAW10 即可。比如輸入camerademo
RGGB10 1920 1080 30 bmp /tmp 5,以上命令輸出配置sensor 輸出RAW 數(shù)據并保存在/tmp 目錄,命令的含義參考本章節(jié)的《選擇方式》。
注意:RAW 數(shù)據文件的保存后綴是.raw 。
6.3.4 debug 信息解析
以下debug 信息將說明sensor 驅動的相關信息,拍攝到的照片保存位置、數(shù)量、保存的格式以及水印使用情況等:
?
圖6-11: debug1
?
以下debug 信息將說明驅動框架支持的格式以及sensor 支持的輸出格式:
?
圖6-12: debug2
?
類似以下的信息代表這相應格式支持的分辨率信息:
?
圖6-13: debug3
?
以下信息將會提示將要設置到sensor 的格式和分辨率等信息:
?
圖6-14: debug4
?
以下信息將會提示設置格式的情況,buf 的相應信息等:
?
圖6-15: debug5
?
以下信息將提示當前拍照的照片索引以及從開啟流傳輸?shù)絛qbuf 成功的時間間隔:
?
圖6-16: debug6
?
以下信息提示該sensor 的實際測量幀率信息:
?
圖6-17: debug7
?
以下信息提示從open 節(jié)點到可以得到第一幀數(shù)據的時間間隔,默認設置為測試拍照的相應設置:
?
圖6-18: debug8
?
6.3.5 文件保存格式
設置完畢之后,將會在所設路徑(默認/tmp)下面保存圖像數(shù)據,數(shù)據分別有兩種格式,一種是YUV 格式,以source_ 格式.yuv 名稱保存;一種是BMP 格式,以
bmp_ 格式.bmp 格式保存,如下圖所示。
查看圖像數(shù)據時,需要通過adb pull 命令將相應路徑下的圖像數(shù)據pull 到PC 端查看。
?
圖6-19: save
?
6.4 select timeout 了,如何操作?
在完成sensor 驅動的移植,驅動模塊正常加載,I2C 正常通信,將會在/dev 目錄下創(chuàng)建相應的video 節(jié)點,之后可以使用camerademo 進行捕獲測試,如果出現(xiàn)
select timeout,end capture thread!,這個情況可按照以下操作進行debug。
先和模組廠確認,當前提供的寄存器配置是否可以正常輸出圖像數(shù)據。有些模組廠提供的寄存器配置還需要增加一個使能寄存器,這些可以在sensor
datasheet 上查詢得到或者與模組廠溝通;
通過dmesg 命令, 查看在運行camerademo 的過程中內核是否有異常的打印。在MR813/R818 平臺,內核出現(xiàn)tdm 相關字段的連續(xù)打印,則需要確認,
board.dts 中的isp配置是否正確,單攝的配置,isp_sel 和tdm_rx_sel 都需要配置為0;雙攝的則需要先運行配置為isp0 的video 節(jié)點才能再運行isp1 的video
節(jié)點;
其他的按照是并口還是mipi 接口進行相應的debug;
6.4.1 DVP sensor
確定sensor 的出圖data 配置正確,是8 位的、10 位的、12 位的?確認之后,檢查驅動中的sensor_formats 和sys_config.fex 中的csi data pin 設置是否正
確;
MCLK 的頻率配置是否正確;
sensor 驅動的sensor_g_mbus_config() 函數(shù)配置為DVP sensor,type 需要設置為V4L2_MBUS_PARALLEL;
確定輸出的data 是高8 位、高10 位,確定硬件引腳配置沒有問題;
示波器測量VSYNC、HSYNC 有沒有波形輸出,這兩個標記著有一場數(shù)據、一行數(shù)據信號產 生;
測量data 腳有沒有波形,電壓幅值是否正常;
如果沒有波形,檢查一下sensor 的寄存器配置,看看有沒有軟件復位的操作,如果有,在該寄存器配置后面加上”{REG_DLY,0xff}“進行相應的延時,防止在
軟件復位的時候,sensor還沒有準備好就I2C 配置寄存器;
如果上面都還是沒有接收到數(shù)據,那么在sensor 的驅動文件,有以下配置,這三個宏定義的具體值。每個都有兩種配置,將這三個宏的配置兩兩組合,共8 種
配置,都嘗試一下;
#define VREF_POL V4L2_MBUS_VSYNC_ACTIVE_HIGH #define HREF_POL V4L2_MBUS_HSYNC_ACTIVE_HIGH #define CLK_POL V4L2_MBUS_PCLK_SAMPLE_RISING
6.4.2 mipi sensor
如果mipi sensor 沒有正常出圖,做以下debug 操作:
mipi 接口和主控板子連接不要飛線,mipi 信號本身就是高頻差分信號,布線時都要求高,飛線更會影響其信號質量,導致無法正常接收數(shù)據;
確認sensor 驅動設置的mipi 格式,同樣是查看sensor_g_mbus_config() 函數(shù)(lane 和通道數(shù));
示波器測量mipi 接口的data 線、時鐘線,看看有沒有數(shù)據輸出;
檢查一下寄存器配置方面有沒有軟件復位的,增加相應的延時;
和模組廠商確認sensor 驅動中對應分辨率的sensor_win_sizes 以下參數(shù)配置是否與寄存器組配合的,因為這些參數(shù)將會影響mipi 接收數(shù)據;
.hts = 3550, .vts = 1126, .pclk = 120 * 1000 * 1000, .mipi_bps = 480 * 1000 * 1000,
上面的hts,又稱line_length_pck,VTS 又稱frame_length_lines,與寄存器的值要一致,Pclk(Pixel clock) 的值由PLL 寄存器計算得出,可簡單計算,pclk = hts ×
vts × fps;而mipi_bps 為mipi 數(shù)據速率,mipi_bps = hts × vts × fps ×(12bit/10bit/8bit)/ lane。
有些sensor 的datasheet 沒有標注hts 和vts 的,但是他們有H Blanking 和Vertical blanking,他們的轉換公式是:
hts = H Blanking + output_width
vts = Vertical blanking + output_height
Output_width 就是輸出的一行的大小,output_height 就是輸出的一列的大小。
gc 廠的sensor,vts = VB + win_height + 16;VB 和win_height 都是可以從寄存器中獲取得到的,注意,win_height 是寄存器值,而不是輸出的高。
6.4.3 其他注意事項
6.4.3.1 R311、MR133
sensor_sel
在vin 框架中,sys_config.fex 有以下配置:
[vind0/sensor0] ... [vind0/sensor1] ... [vind0/vinc0] vinc0_used = 1 vinc0_csi_sel = 0 vinc0_mipi_sel = 0 vinc0_isp_sel = 0 vinc0_rear_sensor_sel = 0 vinc0_front_sensor_sel = 0 vinc0_sensor_list = 0
在這里主要是需要注意vinc0_rear_sensor_sel 和vinc0_front_sensor_sel 的配置,當它們都配置為0,表明vind0/vinc0 配置的video0 節(jié)點,使用的是
vind0/sensor0 節(jié)點中配置的sensor 輸出圖像數(shù)據;當它們配置為0、1,表明vind0/vinc0 配置的video0 節(jié)點,可以使用vind0/sensor0 和vind0/sensor1 兩個
sensor 輸出圖像數(shù)據,可以通過ioctl 的VIDIOC_S_INPUT 的index 選擇使用哪個sensor 的輸出;當它們都配置為1 的時候,表明vind0/vinc0 配置的video0 節(jié)
點,使用的是vind0/sensor1 的輸出。
mipi AB 配置
mipi 配置方面,還有一個需要注意的,該部分在R311、MR133 平臺才有這種情況。一般情況,我們使用的是MCSIB 組的mipi 接口,這個按照一般配置使用即
可,MCSIA、MCSIB,這兩個會在原理圖上表明使用的是哪一組接口,如果單獨使用MCSIA 組的mipi 接口,在sys_config.fex 中配置如下:
由于只是使用MCSIA,所以應該配置的是[vind0/sensor1] 組sensor,vinc0_rear_sensor_sel 和 vinc0_front_sensor_sel 都配置為1. [vind0/vinc0] vinc0_used = 1 vinc0_csi_sel = 0 vinc0_mipi_sel = 0 vinc0_isp_sel = 0 vinc0_rear_sensor_sel = 1 vinc0_front_sensor_sel = 1 vinc0_sensor_list = 0
-
Linux
+關注
關注
87文章
11232瀏覽量
208949 -
開發(fā)指南
+關注
關注
0文章
34瀏覽量
7531 -
Camera
+關注
關注
0文章
79瀏覽量
20788 -
Tina
+關注
關注
2文章
45瀏覽量
16957
發(fā)布評論請先 登錄
相關推薦
評論