一、Camera调用过程:

     imgsensor起到承上启下的作用,在系统起来时会创建整个camera驱动运行的环境,其中主要的文件和函数如下框图所示,先设备挂载时会调用注册platform设备platform_driver_register,在匹配成功后会调用probe函数进行初始相关的设备:

     其中camera的三路电压的上电方式可以通过GPIO来控制,也可以通过PMIC(REGULATOR)的方式来进行控制,在imgsensor_hw中通过不同的pdev信息,调用不同的set函数。涉及文件路径:
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/regulator/regulator.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/gpio/gpio.c

二、上电相关的结构体之间的联系:
(1) 上电时序控制相关:
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/imgsenor_cfg_table.h
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/imgsenor_cfg_table.c
上电方式控制:GPIO供电还是REGULATOR供电 查看原理图与规格书
上电时序控制结构体:

enum IMGSENSOR_SENSOR_IDX { //sensor di  MAIN = 0 SUB = 1 MAIN2 = 2IMGSENSOR_SENSOR_IDX_MIN_NUM = 0,IMGSENSOR_SENSOR_IDX_MAIN = IMGSENSOR_SENSOR_IDX_MIN_NUM,IMGSENSOR_SENSOR_IDX_SUB,IMGSENSOR_SENSOR_IDX_MAIN2,IMGSENSOR_SENSOR_IDX_SUB2,IMGSENSOR_SENSOR_IDX_MAIN3,IMGSENSOR_SENSOR_IDX_MAX_NUM,IMGSENSOR_SENSOR_IDX_NONE,
};
struct IMGSENSOR_HW_CFG {  //供电信息配置的结构体  PMIC供电 或 GPIO供电enum IMGSENSOR_SENSOR_IDX sensor_idx;enum IMGSENSOR_I2C_DEV i2c_dev;struct IMGSENSOR_HW_CUSTOM_POWER_INFO pwr_info[IMGSENSOR_HW_POWER_INFO_MAX];//电源信息结构体数组
};
struct IMGSENSOR_HW_CUSTOM_POWER_INFO {enum IMGSENSOR_HW_ID id;enum IMGSENSOR_HW_PIN pin;
};
struct IMGSENSOR_HW_CFG imgsensor_custom_config[] = {{IMGSENSOR_SENSOR_IDX_MAIN,IMGSENSOR_I2C_DEV_0,{{IMGSENSOR_HW_ID_MCLK, IMGSENSOR_HW_PIN_MCLK},{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_AVDD},//REGULATOR即为PMIC供电{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_DOVDD},{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_DVDD},{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_AFVDD},{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_AF_EN},   //GPIO即为GPIO供电{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_PDN},{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_RST},{IMGSENSOR_HW_ID_NONE, IMGSENSOR_HW_PIN_NONE},},},  ...

(2)上电时序控制结构体

struct IMGSENSOR_HW_POWER_INFO {enum IMGSENSOR_HW_PIN pin;enum IMGSENSOR_HW_PIN_STATE pin_state_on;u32 pin_on_delay;enum IMGSENSOR_HW_PIN_STATE pin_state_off;u32 pin_off_delay;
};
struct IMGSENSOR_HW_POWER_SEQ {  //上电时序结构体char *name;struct IMGSENSOR_HW_POWER_INFO pwr_info[IMGSENSOR_HW_POWER_INFO_MAX];u32 _idx;
};
struct IMGSENSOR_HW_POWER_SEQ platform_power_sequence[] = {#ifdef MIPI_SWITCH{PLATFORM_POWER_SEQ_NAME,{{IMGSENSOR_HW_PIN_MIPI_SWITCH_EN,IMGSENSOR_HW_PIN_STATE_LEVEL_0,0,IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,0},{IMGSENSOR_HW_PIN_MIPI_SWITCH_SEL,IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,0,IMGSENSOR_HW_PIN_STATE_LEVEL_0,0},},IMGSENSOR_SENSOR_IDX_SUB,},{PLATFORM_POWER_SEQ_NAME,{{IMGSENSOR_HW_PIN_MIPI_SWITCH_EN,IMGSENSOR_HW_PIN_STATE_LEVEL_0,0,IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,0},{IMGSENSOR_HW_PIN_MIPI_SWITCH_SEL,IMGSENSOR_HW_PIN_STATE_LEVEL_0,0,IMGSENSOR_HW_PIN_STATE_LEVEL_0,0},},IMGSENSOR_SENSOR_IDX_MAIN2,},
#endif
struct IMGSENSOR_HW_POWER_SEQ sensor_power_sequence[] = {#if defined(HI1336_MIPI_RAW){SENSOR_DRVNAME_HI1336_MIPI_RAW,   //上电时序{{DOVDD, Vol_1800, 1}, //电压相关查看规格书配置表{DVDD, Vol_1100, 5},{AVDD, Vol_2800, 1},{AFVDD, Vol_2800, 1}, //马达上电相关{AFVDD_EN, Vol_Low, 0}, //马达上电相关{AFVDD_EN, Vol_High, 1}, //马达上电相关{SensorMCLK, Vol_High, 0},{RST, Vol_Low, 10},{RST, Vol_High, 1},},},#endif ......VCAMD 主要给 ISP 供电; VCAM_IO 是数字IO电源,主要给I2C供电, VCAMA 是模拟供电,主要给 感光区 和 ADC 部分供电, VCAMAF 主要给对焦马达供电;

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c
上述的上电配置、时序最终都会在Imgsensor_hw.c中调用
├── imgsensor_power
├── imgsensor_power_sequence
├── imgsensor_hw_init
└── imgsensor_hw_release_all

三、平台设备驱动的注册加载
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_proc.c
kernel-4.9/drivers/base/platform.c
kernel-4.9/include/linux/of_device.h
平台设备驱动匹配的进化过程https://www.cnblogs.com/zzb-Dream-90Time/p/7250010.html
     camera 驱动先是注册 platform 平台驱动,然后注册Camera字符设备,创建class类,再通过 I2c 注册前后摄注册字符设备,封装底层方法 imgsensor_ioctl,上层访问底层驱动时候先是使用 setdriver 获取具体IC的驱动的入口,然后使用 checkisalive 对 sensorlist 中的 IC 进行上电,上电完成就通过 I2C 读取设备 ID ,到此为止,上层应用与底层驱动挂接完成,紧接着就是预览和拍照,具体 IC 驱动的实现了。
(1)设备加载 module_init加载模块,注册platform总线驱动

static const struct of_device_id gimgsensor_of_device_id[] = {{ .compatible = "mediatek,camera_hw", },{}
};static struct platform_driver gimgsensor_platform_driver = {.probe = imgsensor_probe,.remove = imgsensor_remove,.suspend = imgsensor_suspend,.resume = imgsensor_resume,.driver = {.name = "image_sensor",.owner = THIS_MODULE,#ifdef CONFIG_OF.of_match_table = gimgsensor_of_device_id,#endif}
};Platform.c调用of_driver_match_device → of_match_device(drv->of_match_table, dev) → __of_match_node()去匹配,
通过把device_driver的of_match_table(of_device_id结构体的数组)和device里的of_node(device_node结构体)进行匹配,匹配方式
是分别比较两者的name、type、和compatible字符串,三者要同时相同(一般name、和type为空,只比较compatible字符串),设备树加载
的时候构建了device设备,被初始化了of_node成员,即设备树加载之后,内核会自动把设备树节点转换成 platform_device这种格式,同时把
名字放到of_node这个地方static int imgsensor_probe(struct platform_device *pdev)
{/* Register char driver */if (imgsensor_driver_register()) {       //注册imgsensor字符设备驱动pr_err("[CAMERA_HW] register char device failed!\n");return -1;}gpimgsensor_hw_platform_device = pdev;#ifndef CONFIG_FPGA_EARLY_PORTINGimgsensor_clk_init(&pgimgsensor->clk);#endifimgsensor_hw_init(&pgimgsensor->hw);imgsensor_i2c_create();imgsensor_proc_init();//与proc文件系统有关  ↓↓atomic_set(&pgimgsensor->imgsensor_open_cnt, 0);//原子操作#ifdef CONFIG_MTK_SMI_EXT  //mmdevfs is set for mtk multimedia drivermmdvfs_register_mmclk_switch_cb(mmsys_clk_change_cb,MMDVFS_CLIENT_ID_ISP);#endifreturn 0;
}
proc_create("driver/camsensor", 0664, NULL,&fcamera_proc_fops); //在proc文件夹下创建虚拟文件及其权限
static const struct file_operations fcamera_proc_fops = {.owner = THIS_MODULE,.read = seq_read,.open = proc_camsensor_open,.write = CAMERA_HW_Reg_Debug
};

(2)创建字符设备

static const struct file_operations gimgsensor_file_operations = {.owner = THIS_MODULE,.open = imgsensor_open,.release = imgsensor_release,.unlocked_ioctl = imgsensor_ioctl,// camera的控制函数 adopt_CAMERA_HW_FeatureControl 硬件初始化#ifdef CONFIG_COMPAT               //上调用imgsensor_set_driver()  寻找sensor进行硬件初始化 .compat_ioctl = imgsensor_compat_ioctl   //上调用imgsensor_i2c_init() #endif
};
static inline int imgsensor_driver_register(void)
{dev_t dev_no = MKDEV(IMGSENSOR_DEVICE_NNUMBER, 0);//申请主设备号  if (alloc_chrdev_region(&dev_no, 0, 1, IMGSENSOR_DEV_NAME)) {  // 主 次设备号  申请次设备号的个数  cat /proc/devices显示的名称pr_debug("[CAMERA SENSOR] Allocate device no failed\n");return -EAGAIN;}
/* Allocate driver */gpimgsensor_cdev = cdev_alloc(); //cdev 分配空间if (gpimgsensor_cdev == NULL) {unregister_chrdev_region(dev_no, 1);pr_debug("[CAMERA SENSOR] Allocate mem for kobject failed\n");return -ENOMEM;}/* Attatch file operation. */cdev_init(gpimgsensor_cdev, &gimgsensor_file_operations);//字符设备的操作函数gpimgsensor_cdev->owner = THIS_MODULE;/* Add to system */if (cdev_add(gpimgsensor_cdev, dev_no, 1)) { //初始化cdev,通过cdev_add加入到系统中pr_debug("Attatch file operation failed\n");unregister_chrdev_region(dev_no, 1);//没有add成功,需要释放设备号return -EAGAIN;}gpimgsensor_class = class_create(THIS_MODULE, "sensordrv");//创建类 /sys/class/if (IS_ERR(gpimgsensor_class)) {int ret = PTR_ERR(gpimgsensor_class);pr_debug("Unable to create class, err = %d\n", ret);return ret;}gimgsensor_device =device_create(gpimgsensor_class,NULL, // sys/class/sensordrv/IMGSENSOR_DEV_NAMEdev_no,NULL,IMGSENSOR_DEV_NAME);return 0;
}

(3)时钟初始化
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/imgsensor_clk.c

enum IMGSENSOR_RETURN imgsensor_clk_init(struct IMGSENSOR_CLK *pclk)
{int i;struct platform_device *pplatform_dev = gpimgsensor_hw_platform_device;//extern外部//在imgsensor.c中 imgsensor_probe传入的platform_device*pdev赋值给gpimgsensor_hw_platform_deviceif (pplatform_dev == NULL) {pr_err("[%s] pdev is null\n", __func__);return IMGSENSOR_RETURN_ERROR;}/* get all possible using clocks */for (i = 0; i < IMGSENSOR_CCF_MAX_NUM; i++)//imgsensor_clk.h中enum IMGSENSOR_CCF中定义pclk->imgsensor_ccf[i] =           // ccf clock common framework      devm_clk_get(&pplatform_dev->dev,gimgsensor_mclk_name[i]); return IMGSENSOR_RETURN_SUCCESS;
}devm_clk_get,和clk_get一样,只是使用了device resource management,可以自动释放;在申请资源会判断是否失败,因此会充斥着大量繁琐的代码,设备资源管理即可driver你只管申请就行了,不用考虑释放,我设备模型帮你释放。clk_get,以device指针或者id字符串(可以看作name)为参数,查找clock。(1)dev和id的任意一个可以为空。如果id为空,则必须有device tree的支持才能获得device对应的clk;(2)根据具体的平台实现,id可以是一个简单的名称,也可以 是一个预先定义的、唯一的标识(一般在平台提供的头文件中定义,如mach/clk.h);(3)不可以在中断上下文调用。
char *gimgsensor_mclk_name[IMGSENSOR_CCF_MAX_NUM] = {"CLK_TOP_CAMTG_SEL","CLK_TOP_CAMTG1_SEL","CLK_TOP_CAMTG2_SEL","CLK_TOP_CAMTG3_SEL","CLK_MCLK_6M","CLK_MCLK_12M","CLK_MCLK_13M","CLK_MCLK_24M","CLK_MCLK_26M","CLK_MCLK_48M","CLK_MCLK_52M","CLK_CAM_SENINF_CG","CLK_MIPI_C0_26M_CG","CLK_MIPI_C1_26M_CG","CLK_MIPI_ANA_0A_CG","CLK_MIPI_ANA_0B_CG","CLK_MIPI_ANA_1A_CG","CLK_MIPI_ANA_1B_CG","CLK_MIPI_ANA_2A_CG","CLK_MIPI_ANA_2B_CG","CLK_TOP_CAMTM_SEL_CG","CLK_TOP_CAMTM_208_CG","CLK_SCP_SYS_CAM",
};

(4)电压初始化

(1)依次调用GPIO/REGULATOR/MCLK的init接口;
(2)解析出imgsensor_custom_config,获取到对应sensor的对应管脚(DVDD/AVDD…)的上电方式(GPIO/REGULATOR);
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c

enum IMGSENSOR_RETURN imgsensor_hw_init(struct IMGSENSOR_HW *phw)
{struct IMGSENSOR_HW_SENSOR_POWER      *psensor_pwr;struct IMGSENSOR_HW_CFG               *pcust_pwr_cfg;struct IMGSENSOR_HW_CUSTOM_POWER_INFO *ppwr_info;int i, j;char str_prop_name[LENGTH_FOR_SNPRINTF];struct device_node *of_node= of_find_compatible_node(NULL, NULL, "mediatek,camera_hw");//匹配节点,of操作之一//依次调用GPIO/REGULATOR/MCLK的init接口for (i = 0; i < IMGSENSOR_HW_ID_MAX_NUM; i++) {if (hw_open[i] != NULL)(hw_open[i])(&phw->pdev[i]);if (phw->pdev[i]->init != NULL)(phw->pdev[i]->init)(phw->pdev[i]->pinstance);}//解析出imgsensor_custom_configfor (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {psensor_pwr = &phw->sensor_pwr[i];pcust_pwr_cfg = imgsensor_custom_config;//上电时序while (pcust_pwr_cfg->sensor_idx != i)pcust_pwr_cfg++;if (pcust_pwr_cfg->sensor_idx == IMGSENSOR_SENSOR_IDX_NONE)continue;//退出循环ppwr_info = pcust_pwr_cfg->pwr_info;while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE) {//查询imgsensor_custom_config中ID_PIN 是否在GPIO/REGULATOR/Mclk中for (j = 0; j < IMGSENSOR_HW_ID_MAX_NUM; j++)if (ppwr_info->id == phw->pdev[j]->id)break;//将对应sensor的对应PIN(DVDD/AVDD...)设置为系统的ID_PIN(GPIO/REGULATOR/MCKL)psensor_pwr->id[ppwr_info->pin] = j;ppwr_info++;}}//判断dts中是否设定对应的index为对应的name,如:cam3_enable_sensor = "gc2375hmain3_mipi_raw";for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {memset(str_prop_name, 0, sizeof(str_prop_name));snprintf(str_prop_name, sizeof(str_prop_name), "cam%d_%s", i, "enable_sensor");if (of_property_read_string(of_node,str_prop_name,&phw->enable_sensor_by_index[i]) < 0) {pr_info("Property cust-sensor not defined\n");phw->enable_sensor_by_index[i] = NULL;}}return IMGSENSOR_RETURN_SUCCESS;
}

(5)imgsensor_i2c_create I2C设备初始化 //注册前后摄像头驱动
     IMGSENSOR_I2C_DEV_MAX_NUM 通过枚举进行赋值,其值为3,说明最多可以注册的摄像头驱动为3个。因为camera 驱动是挂载在 I2C总线 上,所以通过函数 i2c_add_driver() 进行注册。gi2c_driver 结构体对应一个具体 camera 设备的驱动。
/kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6739/camera_hw/imgsensor_cfg_table.h
下方匹配的名称都使用了imgsensor_cfg_table.h中

/* 如果不使用设备树,会匹配这三个宏 */  static const struct i2c_device_id gi2c_dev_id[] = {{IMGSENSOR_I2C_DRV_NAME_0, 0},{IMGSENSOR_I2C_DRV_NAME_1, 0},{IMGSENSOR_I2C_DRV_NAME_2, 0},{}};
#define IMGSENSOR_I2C_DRV_NAME_0  "kd_camera_hw"
#define IMGSENSOR_I2C_DRV_NAME_1  "kd_camera_hw_bus2"
#define IMGSENSOR_I2C_DRV_NAME_2  "kd_camera_hw_bus3"
/* 如果使用设备树,则会匹配这三个宏 */
#define IMGSENSOR_I2C_OF_DRV_NAME_0 "mediatek,camera_main"
#define IMGSENSOR_I2C_OF_DRV_NAME_1 "mediatek,camera_sub"
#define IMGSENSOR_I2C_OF_DRV_NAME_2 "mediatek,camera_main_two"

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_i2c.c

enum IMGSENSOR_RETURN imgsensor_i2c_create(void)
{int i;for (i = 0; i < IMGSENSOR_I2C_DEV_MAX_NUM; i++)i2c_add_driver(&gi2c_driver[i]);return IMGSENSOR_RETURN_SUCCESS;
}
#ifdef CONFIG_OF
static const struct of_device_id gof_device_id_0[] = {/* "mediatek,camera_main" */{ .compatible = IMGSENSOR_I2C_OF_DRV_NAME_0, },{}
};
static const struct of_device_id gof_device_id_1[] = {/* "mediatek,camera_sub" */{ .compatible = IMGSENSOR_I2C_OF_DRV_NAME_1, },{}
};
static const struct of_device_id gof_device_id_2[] = {/* "mediatek,camera_main_two" */{ .compatible = IMGSENSOR_I2C_OF_DRV_NAME_2, },{}
};
static struct i2c_driver gi2c_driver[IMGSENSOR_I2C_DEV_MAX_NUM] = {{.probe = imgsensor_i2c_probe_0,.remove = imgsensor_i2c_remove,.driver = {.name = IMGSENSOR_I2C_DRV_NAME_0, // "kd_camera_hw".owner = THIS_MODULE,
#ifdef CONFIG_OF.of_match_table = gof_device_id_0,
#endif},.id_table = gi2c_dev_id,},{.probe = imgsensor_i2c_probe_1,.remove = imgsensor_i2c_remove,.driver = {.name = IMGSENSOR_I2C_DRV_NAME_1, // "kd_camera_hw_bus2".owner = THIS_MODULE,
#ifdef CONFIG_OF.of_match_table = gof_device_id_1,
#endif},.id_table = gi2c_dev_id,},{.probe = imgsensor_i2c_probe_2,.remove = imgsensor_i2c_remove,.driver = {.name = IMGSENSOR_I2C_DRV_NAME_2, // "kd_camera_hw_bus3".owner = THIS_MODULE,
#ifdef CONFIG_OF.of_match_table = gof_device_id_2,
#endif},.id_table = gi2c_dev_id,}
}
#endif

使用MTK DrvGen生成
./out/target/product/xxx/obj/KERNEL_OBJ/arch/arm/boot/dts/xxx/cust.dtsi
xxx.dts中包含cust_mt6765_camera.dtsi中包含kd_camera_hw1节点;
cust.dtsi中也包含kd_camera_hw1节点,后者会出现下相同会进行覆盖

&i2c2 {#address-cells = <1>;#size-cells = <0>;clock-frequency = <400000>;mediatek,use-open-drain;camera_main_mtk:camera_main@20 {compatible = "mediatek,camera_main";reg = <0x20>;status = "okay";};camera_main_af_mtk:camera_main_af@0c {compatible = "mediatek,camera_main_af";reg = <0x0c>;status = "okay";};camera_sub_mtk:camera_sub@3c {compatible = "mediatek,camera_sub";reg = <0x3c>;status = "okay";};
};
...
...

当内核启动后,会解析dts编译生成的dtb文件,注册里面定义的 device ,代码中设置的 of_device_id 需要分别匹配上 cust.dtsi 文件中的 compatible 节点 “mediatek,camera_main” 和 “mediatek,camera_sub” 。如果和驱动中定义 compatible 字段一致,则挂载启动。上面注册了两个platform 驱动 gi2c_driver 。如果 compatible 匹配成功会调用各自的 probe 函数 imgsensor_i2c_probe_0,imgsensor_i2c_probe_1 。

(6) imgsensor_ioctl上层用于摄像头的具体操作
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/kd_sensorlist.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/kd_sensorlist.h

#define KDIMGSENSORIOC_T_OPEN _IO(IMGSENSORMAGIC, 0)
#define KDIMGSENSORIOC_X_SET_DRIVER _IOWR(IMGSENSORMAGIC, 35, SENSOR_DRIVER_INDEX_STRUCT)
#define HI1336_SENSOR_ID 0x1336
#define SENSOR_DRVNAME_HI1336_MIPI_RAW "hi1336_mipi_raw"

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_sensor_list.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_sensor_list.h

UINT32 HI1336_MIPI_RAW_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc);最终实现在具体sensor的驱动函数中hi336mipiraw_Sensor.c,操作寄存器去完成功能 ↓↓↓
struct IMGSENSOR_INIT_FUNC_LIST kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR] = {#if defined(HI1336_MIPI_RAW){HI1336_SENSOR_ID,SENSOR_DRVNAME_HI1336_MIPI_RAW,HI1336_MIPI_RAW_SensorInit},
#endif
.../*  ADD sensor driver before this line */{0, {0}, NULL}, /* end of list */
};

vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/sensorlist.cpp
注意Kernel层中的kdSensorList和HAL层中的sensorList的顺序必须保持一致

MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
{#if defined(HI1336_MIPI_RAW)RAW_INFO(HI1336_SENSOR_ID, SENSOR_DRVNAME_HI1336_MIPI_RAW,
CAM_CALGetCalData),
#endif
/*  ADD sensor driver before this line */{0, 0,{0}, NULL, NULL, NULL}//end of list
};UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT
**ppSensorList)
{if (NULL == ppSensorList) {ALOGE("ERROR: NULL pSensorList\n");return MHAL_UNKNOWN_ERROR;}*ppSensorList = &SensorList[0];return MHAL_NO_ERROR;
}

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/hi1336_mipi_raw/hi1336mipiraw_Sensor.c

static struct SENSOR_FUNCTION_STRUCT sensor_func = {open,get_info,get_resolution,feature_control,control,close
};
UINT32 HI1336_MIPI_RAW_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc)
{/* To Do : Check Sensor status here */if (pfFunc != NULL)*pfFunc =  &sensor_func;return ERROR_NONE;
}       /*      HI1336_MIPI_RAW_SensorInit      */

Hal层发送 ioctl(m_fdSensor, KDIMGSENSORIOC_X_FEATURECONCTROL, &sensorIdx);
     Kernel 接受 KDIMGSENSORIOC_X_FEATURECONCTROL指令,调用 adopt_CAMERA_HW_FeatureControl()

static long imgsensor_ioctl(struct file *a_pstFile,unsigned int a_u4Command,unsigned long a_u4Param)
{//还有一个函数imgsensor_compat_ioctl具体用于操作什么还未分析int i4RetValue = 0;void *pBuff = NULL;if (_IOC_DIR(a_u4Command) != _IOC_NONE) {    //_IOC_xx都是宏解析相关的        pBuff = kmalloc(_IOC_SIZE(a_u4Command), GFP_KERNEL);if (pBuff == NULL) {pr_debug("[CAMERA SENSOR] ioctl allocate mem failed\n");i4RetValue = -ENOMEM;goto CAMERA_HW_Ioctl_EXIT;}if (_IOC_WRITE & _IOC_DIR(a_u4Command)) {if (copy_from_user(pBuff, (void *)a_u4Param, _IOC_SIZE(a_u4Command))) {kfree(pBuff);pr_debug("[CAMERA SENSOR] ioctl copy from user failed\n");i4RetValue =  -EFAULT;goto CAMERA_HW_Ioctl_EXIT;}}} else {i4RetValue =  -EFAULT;goto CAMERA_HW_Ioctl_EXIT;}switch (a_u4Command) {case KDIMGSENSORIOC_X_GET_CONFIG_INFO:i4RetValue = adopt_CAMERA_HW_GetInfo(pBuff);break;case KDIMGSENSORIOC_X_FEATURECONCTROL:i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);break;case KDIMGSENSORIOC_X_CONTROL:i4RetValue = adopt_CAMERA_HW_Control(pBuff);break;case KDIMGSENSORIOC_X_SET_MCLK_PLL:i4RetValue = imgsensor_clk_set(&pgimgsensor->clk,(struct ACDK_SENSOR_MCLK_STRUCT *)pBuff);break;case KDIMGSENSORIOC_T_OPEN:case KDIMGSENSORIOC_T_CLOSE:case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:case KDIMGSENSORIOC_X_SET_DRIVER:...default:pr_debug("No such command %d\n", a_u4Command);i4RetValue = -EPERM;break;}if ((_IOC_READ & _IOC_DIR(a_u4Command)) &&copy_to_user((void __user *) a_u4Param, pBuff,_IOC_SIZE(a_u4Command))) {kfree(pBuff);pr_debug("[CAMERA SENSOR] ioctl copy to user failed\n");i4RetValue =  -EFAULT;goto CAMERA_HW_Ioctl_EXIT;}kfree(pBuff);
CAMERA_HW_Ioctl_EXIT:          //goto操作return i4RetValue;
}
static inline int adopt_CAMERA_HW_FeatureControl(void *pBuf)
{struct ACDK_SENSOR_FEATURECONTROL_STRUCT *pFeatureCtrl;struct IMGSENSOR_SENSOR *psensor;unsigned int FeatureParaLen = 0;void *pFeaturePara = NULL;struct ACDK_KD_SENSOR_SYNC_STRUCT *pSensorSyncInfo = NULL;signed int ret = 0;pFeatureCtrl = (struct ACDK_SENSOR_FEATURECONTROL_STRUCT *)pBuf;if (pFeatureCtrl  == NULL) {pr_err(" NULL arg.\n");return -EFAULT;}psensor = imgsensor_sensor_get_inst(pFeatureCtrl->InvokeCamera);if (psensor == NULL) {pr_err("[adopt_CAMERA_HW_FeatureControl] NULL psensor.\n");return -EFAULT;}if (pFeatureCtrl->FeatureId == SENSOR_FEATURE_SINGLE_FOCUS_MODE ||pFeatureCtrl->FeatureId == SENSOR_FEATURE_CANCEL_AF ||pFeatureCtrl->FeatureId == SENSOR_FEATURE_CONSTANT_AF ||pFeatureCtrl->FeatureId == SENSOR_FEATURE_INFINITY_AF) {/* YUV AF_init and AF_constent and AF_single has no params */} else {if (pFeatureCtrl->pFeaturePara == NULL ||pFeatureCtrl->pFeatureParaLen == NULL) {pr_err(" NULL arg.\n");return -EFAULT;}if (copy_from_user((void *)&FeatureParaLen,(void *) pFeatureCtrl->pFeatureParaLen, sizeof(unsigned int))) {pr_err(" ioctl copy from user failed\n");return -EFAULT;}if (FeatureParaLen > FEATURE_CONTROL_MAX_DATA_SIZE ||FeatureParaLen == 0)return -EINVAL;ret = check_length_of_para(pFeatureCtrl->FeatureId, FeatureParaLen);if (ret != 0)return ret;pFeaturePara = kmalloc(FeatureParaLen, GFP_KERNEL);if (pFeaturePara == NULL)return -ENOMEM;memset(pFeaturePara, 0x0, FeatureParaLen);}/* copy from user */switch (pFeatureCtrl->FeatureId) {case SENSOR_FEATURE_OPEN:ret = imgsensor_sensor_open(psensor);break;case SENSOR_FEATURE_CLOSE:ret = imgsensor_sensor_close(psensor);/* reset the delay frame flag */break;case SENSOR_FEATURE_SET_DRIVER:{MINT32 drv_idx;psensor->inst.sensor_idx = pFeatureCtrl->InvokeCamera;drv_idx = imgsensor_set_driver(psensor);memcpy(pFeaturePara, &drv_idx, FeatureParaLen);break;}case SENSOR_FEATURE_CHECK_IS_ALIVE:imgsensor_check_is_alive(psensor);break;....case SENSOR_FEATURE_SET_PDAF:case SENSOR_FEATURE_GET_PDAF_INFO:...case SENSOR_FEATURE_SET_STREAMING_RESUME:if (copy_from_user((void *)pFeaturePara,(void *) pFeatureCtrl->pFeaturePara,FeatureParaLen)) {kfree(pFeaturePara);pr_err("[CAMERA_HW][pFeaturePara] ioctl copy from user failed\n");return -EFAULT;}break;
/    * keep the information to wait Vsync synchronize */pSensorSyncInfo =(struct ACDK_KD_SENSOR_SYNC_STRUCT *)pFeaturePara;FeatureParaLen = 2;imgsensor_sensor_feature_control(psensor,SENSOR_FEATURE_SET_GAIN,(unsigned char *)&pSensorSyncInfo->u2SensorNewGain,(unsigned int *) &FeatureParaLen);break;}kfree(pFeaturePara);if (copy_to_user((void __user *) pFeatureCtrl->pFeatureParaLen,(void *)&FeatureParaLen,sizeof(unsigned int))) {pr_debug("[CAMERA_HW][pFeatureParaLen] ioctl copy to user failed\n"); return -EFAULT;}return ret;}

http://blog.csdn.net/LinuxArmbiggod/article/details/91884229
https://www.it610.com/article/1282418947416670208.htm
https://blog.csdn.net/u010783226/article/details/105658842
https://blog.csdn.net/LinuxArmbiggod/article/details/91884229
https://blog.csdn.net/wuye110/article/details/78536322/

Android MTK Camera驱动代码分析相关推荐

  1. 【高通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 ...

  2. Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程

    Android 8.1/9.0 MTK Camera源码分析之快门声音控制 在Android 8.1上mtk camera有控制快门声音的接口,但是并没有了控制录像快门声音的接口.之所以会有这个现象, ...

  3. 【高通SDM660平台 Android 10.0】(12) --- Camera Chromatix 代码分析

    [高通SDM660平台 Android 10.0]Qcom Camera Daemon 代码分析 一.chromatix_imx258_lc898217xc 目录 1.1 例:imx258_lc898 ...

  4. Android 8.1/9.0 MTK Camera源码分析之录像快门声音控制流程

    前面已经针对拍照快门声音控制流程进行了分析,接下来分析一下录像快门声音的控制流程. Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程 这两篇文章其实都是相对于手机系统RO ...

  5. Android MTK Camera博客分享

    MTK Camera博客分享 MTK Camera OTP调用过程 MTK Camera Flashlight调用过程 MTK Camera 应用层到底层过程 MTK Camera HAL层分析 深入 ...

  6. android mtk camera startpreview,android8.1 mtk camera hal各种操作流程

    最近一年,一直在做android上的视频编解码和录相.以及camera hal和系统框架这一块.随着做的慢慢的深入,越发觉得mtk的camera hal这一块,有其独到之处.偏偏网上相关的资料却是极少 ...

  7. MTK Camera驱动移植

    对于MTK Camera驱动移植一般分为四部分: 1.硬件IO口配置: 2.Camera驱动移植: 3.上电时序: 4.修改i2c控制器: 硬件电路: 1.GPIO配置 打开 mediatek\dct ...

  8. MTK6735 Android之Camera驱动移植篇

    MTK6735 Android之Camera驱动移植篇 首先我们需要向sensor原厂拿到我们对应平台型号的驱动hal层和kernel层的代码. 1.拷贝hal层代码到\vendor\mediatek ...

  9. DRM驱动代码分析:开机过程中显示驱动做了什么

    前言: 有些信息是在网上查资料后总结的,没有去追代码验证.如果有说得不对的地方,欢迎提出指正.感谢! 手机启动的大致流程 1.长按开机键 2.执行存储在ROM里(应该是某一个固定地址或是预定义的地址) ...

最新文章

  1. 什么?Spring Boot CommandLineRunner 有坑!?
  2. Codeforces Round #183 (Div. 2)
  3. Ⅲ:zookeeper之查看节点的状态及其监听器的使用
  4. CSS的六种垂直居中
  5. SWIFT(Society for Worldwide Interbank Financial SWIFT Telecommunications---环球同业银行金融电讯协会)
  6. lucene全文搜索之三:生成索引字段,创建索引文档(给索引字段加权)基于lucene5.5.3...
  7. 编写一个学生类 student,包含的属性有学号、姓名年龄,将所有学生存储在一个数组中
  8. 基于JAVA+SpringMVC+Mybatis+MYSQL的保险业务管理系统
  9. Java web Tomcat Server总结
  10. python不等于缺陷
  11. Spring单一类型依赖查找Bean
  12. Code For Better 谷歌开发者之声——谷歌Web工具包(GWT)
  13. 微型计算机原理与接口技术知识点
  14. 解决使用Keil5不能生成bin文件或生成的是.bin文件夹问题
  15. Redis集群-哨兵
  16. vue tab页面缓存处理
  17. Auto.js Pro安卓免ROOT引流脚本开发系列教程28网易公开课(6)-取随机话术
  18. Spring如何用“声明式事务”保护亿万数据安全?【万字解决并发冲突】
  19. PHP 中GET、POST、REQUEST用法
  20. 常用的排序算法-快速记忆

热门文章

  1. h5活动是什么意思_H5是什么_H5页面是什么_什么意思_企业服务汇
  2. 台式计算机用电视机做显示器,电脑怎么一次连接显示器和电视
  3. OpenVPN 技术支持
  4. LaTeX入门|(2)定制专属模板
  5. 单片机很好玩 ,制作呼吸灯(转载)
  6. 输入netsh winsock reset 重启电脑生效
  7. 微信小程序开发(五) - 全局(app.js)逻辑 - js 文件
  8. namedtuple使用
  9. 【GPGPU编程】GPGPU架构剖析之谓词寄存器
  10. 记录vultr搭建https爬虫代理