1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 【高通SDM660平台 Android 10.0】(10) --- Camera Sensor lib 与 Kernel Camera Probe 代码分析

【高通SDM660平台 Android 10.0】(10) --- Camera Sensor lib 与 Kernel Camera Probe 代码分析

时间:2020-08-11 22:45:29

相关推荐

【高通SDM660平台 Android 10.0】(10) --- Camera Sensor lib 与 Kernel Camera Probe 代码分析

【高通SDM660平台 Android 10.0】Camera Sensor lib 与 Kernel Camera Probe 代码分析

一、libmmcamera_imx258.so 代码分析1.1 struct sensor_lib_t 结构体1.2 imx258_lib.h 头文件分析二、 Kernel Camera Probe 代码分析2.1 msm_sensor_driver_probe() 代码分析2.1.1 创建 /dev/videoX、 /dev/v4l-subdevX 节点

《【高通SDM660平台】(1) — Camera 驱动 Bringup Guide》

《【高通SDM660平台】(2) — Camera Kernel 驱动层代码逻辑分析》

《【高通SDM660平台】(3) — Camera V4L2 驱动层分析 》

《【高通SDM660平台】(4) — Camera Init 初始化流程 》

《【高通SDM660平台】(5) — Camera Open 流程》

《【高通SDM660平台】(6) — Camera getParameters 及 setParameters 流程》

《【高通SDM660平台】(7) — Camera onPreview 代码流程》

《【高通SDM660平台】(8) — Camera MetaData介绍》

《【高通SDM660平台 Android 10.0】(9) — Qcom Camera Daemon 代码分析》

《【高通SDM660平台 Android 10.0】(10) — Camera Sensor lib 与 Kernel Camera Probe 代码分析》

《【高通SDM660平台】Camera Capture 流程》

《【高通SDM660平台】Camera mm-qcamera-app 代码分析》

在前面《【高通SDM660平台 Android 10.0】Qcom Camera Daemon 代码分析》 中,

我们分析了 Camera module_sensor_init() 的整个过程,考虑到篇幅的问题,本文是接module_sensor_init() 继续分析的。

主题如下:

分析 Camera lib 库的代码vendor 下发 CFG_SINIT_PROBE 后,Kernel 中 Camera Probe的流程

好, 开始吧!

一、libmmcamera_imx258.so 代码分析

Sensor LIB 库代码位于/vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs

本文以 imx258 为例。

先来看下imx258_lib.c,其最核心的函数就是sensor_open_lib

返回sensor_lib_ptr结构体,所有的 Camera 信息,都保存在该结构体中。

@ /vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs/imx258/imx258_lib.c/*** FUNCTION: sensor_open_lib* DESCRIPTION: Open sensor library and returns data pointer**/void *sensor_open_lib(void){return &sensor_lib_ptr;}

我们来看下sensor_lib_ptr结构体的定义

1.1 struct sensor_lib_t 结构体

@ /vendor/qcom/proprietary/mm-camerasdk/sensor/includes/sensor_lib.htypedef struct {/* sensor slave info */ // 从设备包括,I2C地址、I2C速率、Sensor_id 寄存器地址及Sensor_id 值、上下电的时序及电压值struct camera_sensor_slave_info sensor_slave_info;/* sensor output settings */// 包括 出图的格式(BAYER / YCbCr), 连接类型为 MIPI CSIsensor_output_t sensor_output;/* sensor output register address */// 输出寄存器的地址,pclk,及line length pclk 、 frame length linesstruct sensor_output_reg_addr_t output_reg_addr;/* sensor exposure gain register address */// 曝光增益struct sensor_exp_gain_info_t exp_gain_info;/* sensor aec info */sensor_aec_data_t aec_info;/* number of frames to skip after start stream info */// preview 前丢弃过的 帧数unsigned short sensor_num_frame_skip;/* number of frames to skip after start HDR stream info */// HDR 丢弃的帧数unsigned short sensor_num_HDR_frame_skip;/* sensor pipeline delay */// pipeline 帧延时unsigned int sensor_max_pipeline_frame_delay;/* sensor lens info */// sensor line info 信息sensor_property_t sensor_property;/* imaging pixel array size info */// 像素点大小,宽高sensor_imaging_pixel_array_size pixel_array_size_info;/* Sensor color level information */// 颜色等级sensor_color_level_info color_level_info;/* sensor port info that consists of cid mask and fourcc mapaping */sensor_stream_info_array_t sensor_stream_info_array;/* Sensor Settings */// 初始化Camera 寄存器配置struct camera_i2c_reg_setting_array start_settings;// 关闭Camera 时的寄存器配置struct camera_i2c_reg_setting_array stop_settings;struct camera_i2c_reg_setting_array groupon_settings;struct camera_i2c_reg_setting_array groupoff_settings;struct camera_i2c_reg_setting_array embedded_data_enable_settings;struct camera_i2c_reg_setting_array embedded_data_disable_settings;struct camera_i2c_reg_setting_array aec_enable_settings;struct camera_i2c_reg_setting_array aec_disable_settings;struct camera_i2c_reg_setting_array dualcam_master_settings;struct camera_i2c_reg_setting_array dualcam_slave_settings;/* sensor test pattern info */// 测试图信息sensor_test_info test_pattern_info;/* sensor effects info */struct sensor_effect_info effect_info;/* Sensor Settings Array *///初始化 Camera 寄存器配置struct sensor_lib_reg_settings_array init_settings_array;struct sensor_lib_reg_settings_array res_settings_array;// 不同辨率的输出信息,xy像素大小,pclk,fps,数据传输速率struct sensor_lib_out_info_arrayout_info_array;// MIPI CSI 信息struct sensor_csi_params csi_params;struct sensor_csid_lut_params_array csid_lut_params_array;struct sensor_lib_crop_params_array crop_params_array;/* Exposure Info */sensor_exposure_table_t exposure_func_table;/* video_hdr mode info*/struct sensor_lib_meta_data_info_array meta_data_out_info_array;/* sensor optical black regions */sensor_optical_black_region_t optical_black_region_info;/* sensor_capability */sensor_capability_t sensor_capability;/* sensor_awb_table_t */sensor_awb_table_t awb_func_table;/* sensor_awb_table_t */sensor_fps_table_t fps_func_table;/* Parse RDI stats callback function */sensor_RDI_parser_stats_t parse_RDI_stats;/* full size info */sensor_rolloff_config rolloff_config;/* analog-digital conversion time */long long adc_readout_time;/* number of frames to skip for fast AEC use case */unsigned short sensor_num_fast_aec_frame_skip;/* add soft delay for sensor settings like exposure, gain ...*/unsigned char app_delay[SENSOR_DELAY_MAX];/* for noise profile calculationTuning team must update with proper values. */struct sensor_noise_coefficient_t noise_coeff;/* Flag to be set if any external library are to be loaded */unsigned char external_library;sensorlib_pdaf_apis_t sensorlib_pdaf_api;// PDAF 配轩pdaf_lib_t pdaf_config;/* sensor orientation flag */sensor_orientation_type_t sensor_orientation;} sensor_lib_t;

1.2 imx258_lib.h 头文件分析

@ /vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs/imx258/imx258_lib.h/* imx258_lib.h** Copyright (c) - Qualcomm Technologies, Inc.* All Rights Reserved.* Confidential and Proprietary - Qualcomm Technologies, Inc.*/#ifndef __IMX258_LIB_H__#define __IMX258_LIB_H__#include "sensor_lib.h"#include "eeprom_lib.h"#include "pdaf_api.h"#include "pdaf_camif_api.h"#define SENSOR_MODEL "imx258"/* IMX258 Regs */#define IMX258_DIG_GAIN_GR_ADDR 0x020E#define IMX258_DIG_GAIN_R_ADDR 0x0210#define IMX258_DIG_GAIN_B_ADDR 0x0212#define IMX258_DIG_GAIN_GB_ADDR 0x0214#define IMX258_EXP_RATIO_ADDR 0x0222#define IMX258_ABS_GAIN_R_WORD_ADDR 0x0B90#define IMX258_ABS_GAIN_B_WORD_ADDR 0x0B92/* IMX258 CONSTANTS */#define IMX258_MAX_INTEGRATION_MARGIN 20/* STATS DATA TYPE */#define IMX258_CSI_PD_ISTATS 0x2F#define IMX258_DATA_PEDESTAL 0x40 /* 10bit value */#define IMX258_MIN_AGAIN_REG_VAL 0 /* 1.0x */#define IMX258_MAX_AGAIN_REG_VAL 480 /* 16.0x */#define IMX258_MIN_DGAIN_REG_VAL 256 /* 1.0x */#define IMX258_MAX_DGAIN_REG_VAL 256 /* 1.0x */#define IMX258_MAX_DGAIN_DECIMATOR256/* IMX258 FORMULAS */#define IMX258_MIN_AGAIN (512 / (512 - IMX258_MIN_AGAIN_REG_VAL))#define IMX258_MAX_AGAIN (512 / (512 - IMX258_MAX_AGAIN_REG_VAL))#define IMX258_MIN_DGAIN (IMX258_MIN_DGAIN_REG_VAL / 256)#define IMX258_MAX_DGAIN (IMX258_MAX_DGAIN_REG_VAL / 256)#define IMX258_MIN_GAINIMX258_MIN_AGAIN * IMX258_MIN_DGAIN#define IMX258_MAX_GAINIMX258_MAX_AGAIN * IMX258_MAX_DGAIN/* uncomment FLIP_MIRROR macro toenable flip and mirror in sensor readoutchange bayer patternload pdaf flip and mirror header*///#define FLIP_MIRROR#define START_REG_ARRAY \{ \{0x0100, 0x01, 0x00}, \}#define STOP_REG_ARRAY \{ \{0x0100, 0x00, 0x00}, \}#define GROUPON_REG_ARRAY \{ \{0x0104, 0x01, 0x00}, \}#define GROUPOFF_REG_ARRAY \{ \{0x0104, 0x00, 0x00}, \}// 初始化 寄存器配置#define INIT0_REG_ARRAY \{ \/* External Clock Settings */ \{0x0136, 0x18, 0x00}, \{0x0137, 0x00, 0x00}, \/* Global Settings */ \{0x3051, 0x00, 0x00}, \...... //配置一系烈的寄存器{0x3006, 0x00, 0x00}, \{0x3007, 0x00, 0x00}, \}#ifndef FLIP_MIRROR#define FLIP_MIRROR_SETTING {{0x0101, 0x00, 0x00}}#else#define FLIP_MIRROR_SETTING {{0x0101, 0x03, 0x00}}#endif// 分辨率0 寄存器配置#define RES0_REG_ARRAY \{ \/* Mode A1: 4208x3120 Full 30fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \...... //配置一系烈的寄存器{0x0818, 0x00, 0x00}, \{0x0819, 0x47, 0x00}, \}// 分辨率1 寄存器配置#define RES1_REG_ARRAY \{\/* (Reg-10)Mode: Full 16:9 30 fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \/* Clock Settings */ \{0x0301, 0x05, 0x00}, \{0x0303, 0x02, 0x00}, \...... //配置一系烈的寄存器{0x0818, 0x00, 0x00}, \{0x0819, 0x47, 0x00}, \}// 分辨率2 寄存器配置#define RES2_REG_ARRAY \{ \/* Mode: 2100x1560 2x2 binning 30 fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \...... //配置一系烈的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \}// 分辨率3 寄存器配置#define RES3_REG_ARRAY \{ \/* Mode: 2100x1176 60 fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \...... //配置一系列的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \}// 分辨率4 寄存器配置#define RES4_REG_ARRAY \{ \/* Mode: 1400x784 90 fps*/ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \...... //配置一系列的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \}// 分辨率5 寄存器配置#define RES5_REG_ARRAY \{ \/* Mode: 1400x760 120 fps*/ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \...... //配置一系列的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \}/* Sensor Handler */static sensor_lib_t sensor_lib_ptr ={.sensor_slave_info ={.sensor_name = SENSOR_MODEL,// "imx258".slave_addr = 0x20,// 7位地址0x20, 010 0000, 对应的8位地址为0100 0000, 0x40.i2c_freq_mode = SENSOR_I2C_MODE_FAST,.addr_type = CAMERA_I2C_WORD_ADDR,.sensor_id_info ={.sensor_id_reg_addr = 0x0016,.sensor_id = 0x0258,},.power_setting_array ={.power_setting_a ={{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VANA,.config_val = GPIO_OUT_HIGH,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VANA,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VDIG,.config_val = GPIO_OUT_HIGH,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VDIG,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VIO,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VAF,.config_val = GPIO_OUT_HIGH,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_CLK,.seq_val = CAMERA_MCLK,.config_val = 24000000,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_HIGH,.delay = 12,},},.size = 9,.power_down_setting_a ={{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_CLK,.seq_val = CAMERA_MCLK,.config_val = 0,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VIO,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VDIG,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VDIG,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VANA,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VANA,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VAF,.config_val = GPIO_OUT_LOW,.delay = 1,},},.size_down = 8,},},.sensor_output ={.output_format = SENSOR_BAYER,.connection_mode = SENSOR_MIPI_CSI,.raw_output = SENSOR_10_BIT_DIRECT,#ifndef FLIP_MIRROR.filter_arrangement = SENSOR_RGGB,#else.filter_arrangement = SENSOR_BGGR,#endif},.output_reg_addr ={.x_output = 0x034C,.y_output = 0x034E,.line_length_pclk = 0x0342,.frame_length_lines = 0x0340,},.exp_gain_info ={.coarse_int_time_addr = 0x0202,.global_gain_addr = 0x0204,.vert_offset = IMX258_MAX_INTEGRATION_MARGIN,},.aec_info ={.min_gain = IMX258_MIN_GAIN,.max_gain = IMX258_MAX_GAIN,.max_analog_gain = IMX258_MAX_AGAIN,.max_linecount = 65525 - IMX258_MAX_INTEGRATION_MARGIN,},.sensor_num_frame_skip = 2,.sensor_num_HDR_frame_skip = 2,.sensor_max_pipeline_frame_delay = 2,.sensor_property ={.pix_size = 1.12, /* um */.sensing_method = SENSOR_SMETHOD_ONE_CHIP_COLOR_AREA_SENSOR,.crop_factor = 5.78,},.pixel_array_size_info ={.active_array_size ={.width = 4208,.height = 3120,},.left_dummy = 8,.right_dummy = 8,.top_dummy = 8,.bottom_dummy = 8,},.color_level_info ={.white_level = 1023,.r_pedestal = IMX258_DATA_PEDESTAL,.gr_pedestal = IMX258_DATA_PEDESTAL,.gb_pedestal = IMX258_DATA_PEDESTAL,.b_pedestal = IMX258_DATA_PEDESTAL,},.start_settings ={.reg_setting_a = START_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.stop_settings ={.reg_setting_a = STOP_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.groupon_settings ={.reg_setting_a = GROUPON_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.groupoff_settings ={.reg_setting_a = GROUPOFF_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.dualcam_master_settings ={.reg_setting_a = DUALCAM_MASTER_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,.size = 8,},.embedded_data_enable_settings ={.reg_setting_a = {},.addr_type = 0,.data_type = 0,.delay = 0,},.embedded_data_disable_settings ={.reg_setting_a = {},.addr_type = 0,.data_type = 0,.delay = 0,},.test_pattern_info ={.test_pattern_settings ={{.mode = SENSOR_TEST_PATTERN_OFF,.settings ={.reg_setting_a ={{0x0600, 0x0000, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,}},{.mode = SENSOR_TEST_PATTERN_SOLID_COLOR,.settings ={.reg_setting_a ={{0x0600, 0x0001, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},{.mode = SENSOR_TEST_PATTERN_COLOR_BARS,.settings ={.reg_setting_a ={{0x0600, 0x0002, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},{.mode = SENSOR_TEST_PATTERN_COLOR_BARS_FADE_TO_GRAY,.settings ={.reg_setting_a ={{0x0600, 0x0003, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},{.mode = SENSOR_TEST_PATTERN_PN9,.settings ={.reg_setting_a ={{0x0600, 0x0004, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},},.size = 5,.solid_mode_addr ={.r_addr = 0x0602,.gr_addr = 0x0604,.gb_addr = 0x0608,.b_addr = 0x0606,},},.init_settings_array ={.reg_settings ={{.reg_setting_a = INIT0_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},{.reg_setting_a = FLIP_MIRROR_SETTING,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},},.size = 2,},.res_settings_array ={.reg_settings ={/* Res 0 */{.reg_setting_a = RES0_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 1 */{.reg_setting_a = RES1_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 2 */{.reg_setting_a = RES2_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 3 */{.reg_setting_a = RES3_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 4 */{.reg_setting_a = RES4_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 5 */{.reg_setting_a = RES5_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},},.size = 6,},.out_info_array ={.out_info ={/* Res 0 */{.x_output = 4208,.y_output = 3120,.line_length_pclk = 5352,.frame_length_lines = 3224,.op_pixel_clk = 480000000,.binning_factor = 1,.min_fps = 7.500,.max_fps = 30.04,.mode = SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 0,.scale_factor = 1.000,.is_pdaf_supported = 1,.data_rate = 1296000000ULL * 4},/* Res 1 */{.x_output = 4208,.y_output = 2352,.line_length_pclk = 5352,.frame_length_lines = 2852,.op_pixel_clk = 458400000,.binning_factor = 1,.min_fps = 7.500,.max_fps = 30.03,.mode = SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 1,.data_rate = 1296000000ULL * 4},/* Res 2 */{.x_output = 2100,.y_output = 1560,.line_length_pclk = 5352,.frame_length_lines = 2851,.op_pixel_clk = 458400000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 30.04,.mode = SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 0,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},/* Res 3*/{.x_output = 2100,.y_output = 1176,.line_length_pclk = 5352,.frame_length_lines = 1424,.op_pixel_clk = 458400000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 60.14,.mode = SENSOR_HFR_MODE | SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},/* Res 4 */{.x_output = 1400,.y_output = 784,.line_length_pclk = 5352,.frame_length_lines = 948,.op_pixel_clk = 458400000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 90.18,.mode = SENSOR_HFR_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},/* Res 5 */{.x_output = 1400,.y_output = 760,.line_length_pclk = 5352,.frame_length_lines = 828,.op_pixel_clk = 480000000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 120.47,.mode = SENSOR_HFR_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},},.size = 6,},.csi_params ={.lane_cnt = 4,.settle_cnt = 0xB,.is_csi_3phase = 0,},.exposure_func_table ={.sensor_calculate_exposure = sensor_calculate_exposure,.sensor_fill_exposure_array = sensor_fill_exposure_array,},.meta_data_out_info_array ={.meta_data_out_info ={{/* set the meta half size which it should be to overcome the isp bug */.width = 80,.height = 1920,.stats_type = PD_STATS,.dt = IMX258_CSI_PD_ISTATS,},},.size = 1,},.sensor_capability = 0,.awb_func_table ={.sensor_fill_awb_array = 0,.awb_table_size = 0,},.parse_RDI_stats ={.parse_VHDR_stats = NULL,},.rolloff_config ={.enable = FALSE,.full_size_info ={.full_size_width = 0,.full_size_height = 0,.full_size_left_crop = 0,.full_size_top_crop = 0,},},.adc_readout_time = 0,.sensor_num_fast_aec_frame_skip = 0,.noise_coeff = {.gradient_S = 3.738032e-06,.offset_S = 3.651935e-04,.gradient_O = 6.396835e-11,.offset_O = -2.968624e-04,},.pdaf_config = {#ifndef FLIP_MIRROR#include "imx258_pdaf.h"#else#include "imx258_pdaf_flip_mirror.h"#endif},};#endif /* __IMX258_LIB_H__ */

二、 Kernel Camera Probe 代码分析

前面我们mm-camera/mm-camera2/media-controller/modules/sensors/module/sensor_init.c中,会下发CFG_SINIT_PROBE给到kernel 中。

memset(&cfg, 0, sizeof(cfg));cfg.cfgtype = CFG_SINIT_PROBE;cfg.cfg.setting = slave_info;ioctl(fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg);

Kernel 中处理的地方为:

@/kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c/* Static function definition */static int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init,void *arg){struct sensor_init_cfg_data *cfg = (struct sensor_init_cfg_data *)arg;switch (cfg->cfgtype) {case CFG_SINIT_PROBE:s_init->module_init_status = 0;rc = msm_sensor_driver_probe(cfg->cfg.setting, &cfg->probed_info, cfg->entity_name);break;}

前面代码中,cfg.setting就是cfg.cfg.setting = slave_info;, 而最终probe的结果,保存在cfg->probed_info中。

2.1 msm_sensor_driver_probe() 代码分析

获取上层下发的slave_info 信息根据camera id 获取该camera 的控制函数如果已经probe 过了,则更新 probed_info 信息获取 power 上下电信息保存 Camera_info 结构体,包括 slave_addr,sensor id, setting填充上电信息填充下电信息更新外设设备信息解析eeprom、actuator、flash 等的dts 信息开始上电,上电后会进行check_id 操作,如果 sensor id 匹配成功,则返回成功将sensor 加加载到V4L2 subdev 中,创建 节点 /dev/videoX下电,保存 sensor_info 信息到 s_strl 中

@ /kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c/* static function definition */int32_t msm_sensor_driver_probe(void *setting,struct msm_sensor_info_t *probed_info, char *entity_name){/* Allocate memory for slave info */slave_info = kzalloc(sizeof(*slave_info), GFP_KERNEL);{// 1. 获取上层下发的slave_info 信息。copy_from_user(slave_info, (void __user *)setting, sizeof(*slave_info));id_info = &(slave_info->sensor_id_info);reg_setting = kzalloc(id_info->setting.size * (sizeof(struct msm_camera_i2c_reg_array)), GFP_KERNEL);copy_from_user(reg_setting, (void __user *) slave_info->sensor_id_info.setting.reg_setting,slave_info->sensor_id_info.setting.size * sizeof(struct msm_camera_i2c_reg_array));slave_info->sensor_id_info.setting.reg_setting = reg_setting;}/* Print slave info */CDBG("camera id %d Slave addr 0x%X addr_type %d\n",slave_info->camera_id, slave_info->slave_addr,slave_info->addr_type);CDBG("sensor_id_reg_addr 0x%X sensor_id 0x%X sensor id mask %d",slave_info->sensor_id_info.sensor_id_reg_addr,slave_info->sensor_id_info.sensor_id,slave_info->sensor_id_info.sensor_id_mask);CDBG("power up size %d power down size %d\n",slave_info->power_setting_array.size,slave_info->power_setting_array.size_down);CDBG("position %d",slave_info->sensor_init_params.position);CDBG("mount %d",slave_info->sensor_init_params.sensor_mount_angle);CDBG("bypass video node creation %d",slave_info->bypass_video_node_creation);// 2. 根据camera id 获取该camera 的控制函数/* Extract s_ctrl from camera id */s_ctrl = g_sctrl[slave_info->camera_id];CDBG("s_ctrl[%d] %pK", slave_info->camera_id, s_ctrl);// 3. 如果已经probe 过了,则更新 probed_info 信息if (s_ctrl->is_probe_succeed == 1) {/* Different sensor on this camera slot has been connected* and probe already succeeded for that sensor. Ignore this probe */if (slave_info->sensor_id_info.sensor_id == s_ctrl->sensordata->cam_slave_info->sensor_id_info.sensor_id && !(strcmp(slave_info->sensor_name,s_ctrl->sensordata->cam_slave_info->sensor_name))) {pr_err("slot%d: sensor name: %s sensor id%d already probed\n",slave_info->camera_id,slave_info->sensor_name,s_ctrl->sensordata->cam_slave_info->sensor_id_info.sensor_id);msm_sensor_fill_sensor_info(s_ctrl,probed_info, entity_name);} rc = 0;goto free_slave_info;}// 4.获取 power 上下电信息rc = msm_sensor_get_power_settings(setting, slave_info, &s_ctrl->sensordata->power_info);// 5. 保存 Camera_info 结构体,包括 slave_addr,sensor id, settingcamera_info = kzalloc(sizeof(struct msm_camera_slave_info), GFP_KERNEL);s_ctrl->sensordata->slave_info = camera_info;/* Fill sensor slave info */camera_info->sensor_slave_addr = slave_info->slave_addr;camera_info->sensor_id_reg_addr = slave_info->sensor_id_info.sensor_id_reg_addr;camera_info->sensor_id = slave_info->sensor_id_info.sensor_id;camera_info->sensor_id_mask = slave_info->sensor_id_info.sensor_id_mask;camera_info->setting = &(slave_info->sensor_id_info.setting);/* Fill sensor address type */s_ctrl->sensor_i2c_client->addr_type = slave_info->addr_type;if (s_ctrl->sensor_i2c_client->client)s_ctrl->sensor_i2c_client->client->addr = camera_info->sensor_slave_addr;cci_client = s_ctrl->sensor_i2c_client->cci_client;cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;cci_client->sid = slave_info->slave_addr >> 1;cci_client->retries = 3;cci_client->id_map = 0;cci_client->i2c_freq_mode = slave_info->i2c_freq_mode;// 6. 填充上电信息/* Parse and fill vreg params for powerup settings */rc = msm_camera_fill_vreg_params(s_ctrl->sensordata->power_info.cam_vreg,s_ctrl->sensordata->power_info.num_vreg,s_ctrl->sensordata->power_info.power_setting,s_ctrl->sensordata->power_info.power_setting_size);// 7. 填充下电信息/* Parse and fill vreg params for powerdown settings*/rc = msm_camera_fill_vreg_params(s_ctrl->sensordata->power_info.cam_vreg,s_ctrl->sensordata->power_info.num_vreg,s_ctrl->sensordata->power_info.power_down_setting,s_ctrl->sensordata->power_info.power_down_setting_size);CSID_TG:/* Update sensor, actuator and eeprom name in* sensor control structure*/// 8. 更新外设设备信息s_ctrl->sensordata->sensor_name = slave_info->sensor_name;s_ctrl->sensordata->eeprom_name = slave_info->eeprom_name;s_ctrl->sensordata->actuator_name = slave_info->actuator_name;s_ctrl->sensordata->ois_name = slave_info->ois_name;s_ctrl->sensordata->flash_name = slave_info->flash_name;// 9. 解析eeprom、actuator、flash 等的dts 信息/* Update eeporm subdevice Id by input eeprom name */rc = msm_sensor_fill_eeprom_subdevid_by_name(s_ctrl);/* Update actuator subdevice Id by input actuator name */rc = msm_sensor_fill_actuator_subdevid_by_name(s_ctrl);rc = msm_sensor_fill_laser_led_subdevid_by_name(s_ctrl);rc = msm_sensor_fill_ois_subdevid_by_name(s_ctrl);rc = msm_sensor_fill_flash_subdevid_by_name(s_ctrl);// 10. 开始上电,上电后会进行check_id 操作,如果 sensor id 匹配成功,则返回成功,/* Power up and probe sensor */rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);========================>+@ /kernel/msm-4.14/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c+static struct msm_sensor_fn_t msm_sensor_func_tbl = {+.sensor_config = msm_sensor_config,+.sensor_power_up = msm_sensor_power_up,+.sensor_power_down = msm_sensor_power_down,+.sensor_match_id = msm_sensor_match_id,+};++rc = msm_camera_power_up(power_info, s_ctrl->sensor_device_type, sensor_i2c_client);+rc = msm_sensor_check_id(s_ctrl);<========================pr_err("%s probe succeeded", slave_info->sensor_name);s_ctrl->bypass_video_node_creation = slave_info->bypass_video_node_creation;/** Create /dev/videoX node, comment for now until dummy /dev/videoX* node is created and used by HAL*/// 11. 将sensor 加加载到V4L2 subdev 中,创建 节点 /dev/videoXif (s_ctrl->sensor_device_type == MSM_CAMERA_PLATFORM_DEVICE)rc = msm_sensor_driver_create_v4l_subdev(s_ctrl);elserc = msm_sensor_driver_create_i2c_v4l_subdev(s_ctrl);// 12. 下电,保存 sensor_info 信息到 s_strl 中。/* Power down */s_ctrl->func_tbl->sensor_power_down(s_ctrl);rc = msm_sensor_fill_slave_info_init_params(slave_info, s_ctrl->sensordata->sensor_info);rc = msm_sensor_validate_slave_info(s_ctrl->sensordata->sensor_info);/*Save sensor info*/s_ctrl->sensordata->cam_slave_info = slave_info;msm_sensor_fill_sensor_info(s_ctrl, probed_info, entity_name);/** Set probe succeeded flag to 1 so that no other camera shall* probed on this slot*/s_ctrl->is_probe_succeed = 1;return rc;}

2.1.1 创建 /dev/videoX、 /dev/v4l-subdevX 节点

创建 /dev/videoX 节点初始化 s_ctrl->msm_sd.sd 节构体信息,将ops 绑定到 sd 中更新 subdev 信息,并注册subdev将 subdev 添回到 subdev list 链表中创建 /dev/v4l-subdevX 节点

@ msm-4.14/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.cstatic int32_t msm_sensor_driver_create_v4l_subdev(struct msm_sensor_ctrl_t *s_ctrl){// 1. 创建 /dev/videoX 字付设备节点if (s_ctrl->bypass_video_node_creation == 0) {rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);=============>+@ msm-4.14/drivers/media/platform/msm/camera_v2/camera/camera.c+strlcpy(pvdev->vdev->name, "msm-sensor", sizeof(pvdev->vdev->name));+pvdev->vdev->fops= &camera_v4l2_fops;+pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;+video_register_device(pvdev->vdev,VFL_TYPE_GRABBER, -1);+----------------->+@ msm-4.14/include/media/v4l2-dev.h+__video_register_device(vdev, type, nr, 1, vdev->fops->owner);+------------>+name_base = "video";+/* Pick a device node number */+minor_offset = 0;+minor_cnt = 64;+nr = devnode_find(vdev, 0, minor_cnt);+video_device[vdev->minor] = vdev;+/* Part 3: Initialize the character device */+vdev->cdev->ops = &v4l2_fops;+vdev->cdev->owner = owner;+ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);+/* Part 4: register the device with sysfs */+vdev->dev.class = &video_class;+vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);+vdev->dev.parent = vdev->dev_parent;+dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);+ret = device_register(&vdev->dev);+<------------+<-----------------<=============}CDBG("rc %d session_id %d", rc, session_id);s_ctrl->sensordata->sensor_info->session_id = session_id;// 2. 初始化 s_ctrl->msm_sd.sd 节构体信息,将ops 绑定到 sd 中/* Create /dev/v4l-subdevX device */v4l2_subdev_init(&s_ctrl->msm_sd.sd, s_ctrl->sensor_v4l2_subdev_ops);// 3. 更新 subdev 信息,并注册// imx258snprintf(s_ctrl->msm_sd.sd.name, sizeof(s_ctrl->msm_sd.sd.name), "%s",s_ctrl->sensordata->sensor_name);v4l2_set_subdevdata(&s_ctrl->msm_sd.sd, s_ctrl->pdev);s_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;media_entity_pads_init(&s_ctrl->msm_sd.sd.entity, 0, NULL);s_ctrl->msm_sd.sd.entity.function = MSM_CAMERA_SUBDEV_SENSOR;s_ctrl->msm_sd.sd.entity.name = s_ctrl->msm_sd.sd.name; // imx258s_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x3;rc = msm_sd_register(&s_ctrl->msm_sd);=======================>@ msm-4.14/drivers/media/platform/msm/camera_v2/msm.c__msm_sd_register_subdev(&msm_subdev->sd);----------->// 3.1 将 subdev 添回到 subdev list 链表中rc = v4l2_device_register_subdev(msm_v4l2_dev, sd);--------->list_add_tail(&sd->list, &v4l2_dev->subdevs);<---------strlcpy(vdev->name, sd->name, sizeof(vdev->name));// imx258vdev->v4l2_dev = msm_v4l2_dev;vdev->fops = msm_cam_get_v4l2_subdev_fops_ptr();vdev->release = msm_sd_unregister_subdev;// 3.2 创建 /dev/v4l-subdevX 节点rc = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,sd->owner);--------->@ msm-4.14/drivers/media/v4l2-core/v4l2-ame_base = "v4l-subdev";minor_offset = 128;minor_cnt = 64;/* Pick a device node number */nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);video_device[vdev->minor] = vdev;/* Part 3: Initialize the character device */vdev->cdev->ops = &v4l2_fops;vdev->cdev->owner = owner;ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);/* Part 4: register the device with sysfs */vdev->dev.class = &video_class;vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);vdev->dev.parent = vdev->dev_parent;dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); // v4l-subdevXret = device_register(&vdev->dev);<---------<-----------<=======================msm_cam_copy_v4l2_subdev_fops(&msm_sensor_v4l2_subdev_fops);#ifdef pat_ioctl32 = msm_sensor_subdev_fops_ioctl;#endifs_ctrl->msm_sd.sd.devnode->fops = &msm_sensor_v4l2_subdev_fops;return rc;}

至此,整个probe 过程就 完毕了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。