camera开机初始化流程

一.开机camera启动流程framework到hal

Main_mediaserver.cpp (frameworks\av\media\mediaserver)
CameraService::instantiate();
    //mediaserver的main函数中调用了CameraService的instantiate函数来创建实例,该函数的实现在其父类BinderService中实现
    //CameraService.cpp (frameworks\av\services\camera\libcameraservice)
    CameraService::onFirstRef

        // Update battery life tracking if service is restarting

       BatteryNotifier& notifier(BatteryNotifier::getInstance());

       notifier.noteResetCamera();

       notifier.noteResetFlashlight();

        //通过hw_get_module函数加载了一个hw_module_t模块,这个模块是与hal层对接的接口,ID为CAMERA_HARDWARE_MODULE_ID,并将它保存在mModule成员变量中。
        int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,  (const hw_module_t **)&rawModule);
        mModule = new CameraModule(rawModule);
        err = mModule->init();
        //通过mModule->get_number_of_cameras函数进入到hal层,获取到了camera的个数。这个函数很重要,对于frameworks层来说只是拿到了camera的个数,
        //但对于hal层和drivers层来说Camera的上电和初始化流程都是从这里开始的

        mNumberOfCameras = mModule->getNumberOfCameras();

            //CameraModule.cpp (frameworks\av\services\camera\libcameraservice\common)

            return mModule->get_number_of_cameras(); //调用到HAL层
 
Module.h (vendor\mediatek\proprietary\hardware\mtkcam\legacy\module_hal\module)
NSCam::getCamDeviceManager()->getNumberOfDevices();
    //CamDeviceManagerImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\devicemgr)
    &gCamDeviceManager;getNumberOfDevices
        //CamDeviceManagerBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\module_hal\devicemgr)
        mi4DeviceNum = enumDeviceLocked();
            //CamDeviceManagerImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\devicemgr)
            IHalSensorList*const pHalSensorList = IHalSensorList::get();
            size_t const sensorNum = pHalSensorList->searchSensors(); //搜索看从HAL层开始分析
 

具体分析可以参考

http://blog.csdn.net/eternity9255/article/details/52085864

 

 

 

二.开机打开sensor总结           

  • HAL层运行Search sensor这个线程
  • HAL层遍历sensorlist列表并挂载HAL层性能3A等一些参数获取的接口
  • HAL层下达setDriver的cmd,并下传正在遍历的sensorlist列表中的ID
  • Driver层根据这个ID,挂载Driver层sensorlist中对应的Sensorlist中对应的Sensor和具体Sensor底层操作接口
  • HAL层对正确遍历的sensor下达check ID的指令
  • Driver层为对应sensor上电,通过I2C读取预存在寄存器中的sensor id
  • 比较读取结果,不匹配,return error,继续遍历
  • 匹配,HAL层下达其他指令收集sensor信息
  • sensor下电
 
 kdSetDriver()函数有一个参数,这个参数是由impSearchSensor()传下来的,如果主(后)camera,那么这个值是10000、10001、10002等,如果是次(前)camera,那么这个值是20000、20001、20002等
如果是后camera,那么g_invokeSocketIdx[0]的值应为1,如果是前camera,那么应是2。而drvIdx[0]的值是sensor驱动列表的索引号,例如0、1、2等。
 
这就是找到一个sensor的流程,先主(后)camera,后次(前)camera。
找后camera,会遍历一遍sensor列表,找前camera,再遍历一遍sensor列表,注意模块的上电,id值的读取。
 
 

1.从HAL层开始分析

   CamDeviceManagerImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\devicemgr)的enumDeviceLocked()函数
   pHalSensorList->searchSensors() 将调用SensorDrv::searchSensor(NULL)函数,该函数再调用ImgSensor_drv.cpp文件中中的ImgSensorDrv::impSearchSensor函数
     enumDeviceLocked()
        sensorNum = pHalSensorList->searchSensors(); 
            //Imgsensor_drv.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\hal\sensor)
            ImgSensorDrv::impSearchSensor 
               //If imp sensor search process already done before,only need to return the sensorDevs, not need to search again.
               //如果已经运行了搜索进程,就不会再进程搜索,直接返回。
                GetSensorInitFuncList(&m_pstSensorInitFunc);  //没有搜索的情况下,调用这个函数,单独分析1
                sprintf(cBuf,"/dev/%s",CAMERA_HW_DEVNAME);  //这个宏在device/mediatek/common/kernel-headers/kd_imgsensor.h中
                       #define CAMERA_HW_DEVNAME                       "kd_camera_hw"
                m_fdSensor = ::open(cBuf, O_RDWR);  //打开/dev/kd_camera_hw节点,在Kd_sensorlist.c (kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735)生成                                                                          的file_operations的open
                for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++)  //MAX_NUM_OF_SUPPORT_SENSOR是32个
                    //在device/mediatek/common/kernel-headers/kd_imgsensor_define.h中
                        #define KDIMGSENSOR_INVOKE_DRIVER_0     (0)
                        #define KDIMGSENSOR_DUAL_SHIFT               16
                        DUAL_CAMERA_MAIN_SENSOR = 1
                    ////因为前面SensorEnum = (MUINT32)DUAL_CAMERA_MAIN_SENSOR;,所以SensorEnum = 1;
                    id[KDIMGSENSOR_INVOKE_DRIVER_0] = (SensorEnum << KDIMGSENSOR_DUAL_SHIFT) | i;   化简==>id[0] = 0x10000 | i;  
                    err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] ); //获取底层的摄像头相应的操作函数
                    err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);  //检测摄像头是否存在,主要是读ID
                    sensorType = this->getCurrentSensorType((SENSOR_DEV_ENUM)SensorEnum); 
                        getInfo(scenarioId, m_psensorInfo, m_psensorConfigData)
                            ioctl(m_fdSensor, KDIMGSENSORIOC_X_GETINFO , &getInfo);     //得到sensor的信息
                    socketPos = this->getSocketPosition((CAMERA_DUAL_CAMERA_SENSOR_ENUM)SensorEnum);
                        err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_GET_SOCKET_POS , &socketPos);  //得到分辨率
                     //保存一些信息
                    m_mainSensorDrv.index[m_mainSensorDrv.number] = i;
                    m_mainSensorDrv.position = socketPos;
                    。。。。。。。。。。。。。。。
                //close system call may be off sensor power. check first!!!
                ::close(m_fdSensor);
                   err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_CURRENT_SENSOR, &sensorIdx);
                   err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CLOSE); //关闭摄像头     
                    
                    
 
 
单独分析1
GetSensorInitFuncList(&m_pstSensorInitFunc);  //没有搜索的情况下,调用这个函数,单独分析
      //Sensorlist.cpp (vendor\mediatek\proprietary\custom\mt6735\hal\d1\imgsensor_src)
      GetSensorInitFuncList //调用这个函数,获取hal层sensor列表
           MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] = {
              #if defined(GC5005_MIPI_RAW)
                    RAW_INFO(GC5005_SENSOR_ID, SENSOR_DRVNAME_GC5005_MIPI_RAW,NULL), //单独分析2
               #endif  
            }
 
//单独分析2
RAW_INFO和YUV_INFO
#define YUV_INFO(_id, name, getCalData)\    //
    { \
    _id, name, \
    NSFeature::YUVSensorInfo<_id>::createInstance(name, #name), \
    (NSFeature::SensorInfoBase*(*)()) \
    NSFeature::YUVSensorInfo<_id>::getInstance, \
    NSFeature::YUVSensorInfo<_id>::getDefaultData, \
    getCalData, \
NSFeature::YUVSensorInfo<_id>::getNullFlickerPara \
 
#define RAW_INFO(_id, name, getCalData)\
    { \
    _id, name, \
    NSFeature::RAWSensorInfo<_id>::createInstance(name, #name), \
    (NSFeature::SensorInfoBase*(*)()) \
    NSFeature::RAWSensorInfo<_id>::getInstance, \
    NSFeature::RAWSensorInfo<_id>::getDefaultData, \
    getCalData, \
NSFeature::RAWSensorInfo<_id>::getFlickerPara \
    }
   根据不同的sensor类型使用RAW_INFO或YUV_INFO,再根据ID和name生成结构体,所以ID和NAME需要唯一。
 
 
 
 
二.驱动分析
    Kd_sensorlist.c (kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735)
    
1.初始化
static struct platform_device camerahw_platform_device = {
.name = "image_sensor",
.id = 0,
.dev = {
.coherent_dma_mask = DMA_BIT_MASK(32),
}
};
static struct platform_device camerahw2_platform_device = {
    .name = "image_sensor_bus2",
    .id = 0,
    .dev = {
    }
};
 
static struct platform_driver g_stCAMERA_HW_Driver = {
.probe      = CAMERA_HW_probe,
.remove     = CAMERA_HW_remove,
.suspend    = CAMERA_HW_suspend,
.resume     = CAMERA_HW_resume,
.driver     = {
.name   = "image_sensor",
.owner  = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = CAMERA_HW_of_ids,
#endif
}
};
 
tatic struct platform_driver g_stCAMERA_HW_Driver2 = {
.probe      = CAMERA_HW_probe2,
.remove     = CAMERA_HW_remove2,
.suspend    = CAMERA_HW_suspend2,
.resume     = CAMERA_HW_resume2,
.driver     = {
.name   = "image_sensor_bus2",
.owner  = THIS_MODULE,
#ifdef CONFIG_OF
    .of_match_table = CAMERA_HW2_of_ids,
#endif
 
 
CAMERA_HW_i2C_init
    platform_device_register(&camerahw_platform_device); //注册device
    platform_device_register(&camerahw2_platform_device);
 
    platform_driver_register(&g_stCAMERA_HW_Driver) //注册driver,进入CAMERA_HW_probe
    platform_driver_register(&g_stCAMERA_HW_Driver2) ////注册driver,进入CAMERA_HW_probe2
 
    proc_create("driver/camsensor", 0, NULL, &fcamera_proc_fops); // proc/driver/camsensor调试文件节点,写寄存器
    proc_create("driver/camsensor2", 0, NULL, &fcamera_proc_fops2);
    proc_create("driver/camsensor3", 0, NULL, &fcamera_proc_fops3);
    proc_create(PROC_CAMERA_INFO, 0, NULL, &fcamera_proc_fops1); //#define PROC_CAMERA_INFO "driver/camera_info",读取摄像头信息
 
 
2.平台probe函数
truct i2c_driver CAMERA_HW_i2c_driver = {
.probe = CAMERA_HW_i2c_probe,
.remove = CAMERA_HW_i2c_remove,
.driver = {
.name = CAMERA_HW_DRVNAME1,
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = CAMERA_HW_i2c_of_ids,
#endif
},
.id_table = CAMERA_HW_i2c_id,
};
 
CAMERA_HW_probe
   mtkcam_gpio_init(pdev); //获取DTS的端口
       camctrl = devm_pinctrl_get(&pdev->dev);
       cam0_pnd_h = pinctrl_lookup_state(camctrl, "cam0_pnd1");
   i2c_add_driver(&CAMERA_HW_i2c_driver);    //注册I2C设备,进入I2C的CAMERA_HW_i2c_probe函数
 
 
 
struct i2c_driver CAMERA_HW_i2c_driver2 = {
    .probe = CAMERA_HW_i2c_probe2,
    .remove = CAMERA_HW_i2c_remove2,
    .driver = {
    .name = CAMERA_HW_DRVNAME2,
    .owner = THIS_MODULE,
#ifdef CONFIG_OF
    .of_match_table = CAMERA_HW2_i2c_driver_of_ids,
#endif
    },
    .id_table = CAMERA_HW_i2c_id2,
};
 
CAMERA_HW_probe2
    i2c_add_driver(&CAMERA_HW_i2c_driver2); //注册
 
 
 
3.I2C的probe函数
static const struct file_operations g_stCAMERA_HW_fops = {
.owner = THIS_MODULE,
.open = CAMERA_HW_Open,
.release = CAMERA_HW_Release,
.unlocked_ioctl = CAMERA_HW_Ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = CAMERA_HW_Ioctl_Compat,
#endif
 
CAMERA_HW_i2c_probe
    /* set I2C clock rate */
    g_pstI2Cclient2->timing = 100;/* 100k */
    /* Register char driver */
    RegisterCAMERA_HWCharDrv();、
      alloc_chrdev_region(&g_CAMERA_HWdevno, 0, 1, CAMERA_HW_DRVNAME1)  // #define CAMERA_HW_DRVNAME1  "kd_camera_hw"
        g_pCAMERA_HW_CharDrv = cdev_alloc(); ///* Allocate driver */
        cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); //设置操作函数
        cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, 1) //添加到系统
        sensor_class = class_create(THIS_MODULE, "sensordrv");  //sysfs类型
        device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1); //sysfs节点
 
 
static const struct file_operations g_stCAMERA_HW_fops0 = {
.owner = THIS_MODULE,
.open = CAMERA_HW_Open2,
.release = CAMERA_HW_Release2,
.unlocked_ioctl = CAMERA_HW_Ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = CAMERA_HW_Ioctl_Compat,
#endif
 
};
 
CAMERA_HW_i2c_probe2
    g_pstI2Cclient2->timing = 100;/* 100k */
    RegisterCAMERA_HWCharDrv2();
        alloc_chrdev_region(&g_CAMERA_HWdevno2, 0, 1, CAMERA_HW_DRVNAME2) //#define CAMERA_HW_DRVNAME2  "kd_camera_hw_bus2"
        g_pCAMERA_HW_CharDrv2 = cdev_alloc();
        cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0); //操作函数
        cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, 1)
        sensor2_class = class_create(THIS_MODULE, "sensordrv2");
        device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2);
 
 
 
 
四.驱动层给HAL层提供的IOCTL函数
Kd_sensorlist.c (kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735)
 
CAMERA_HW_Ioctl 
    _IOC_NONE == _IOC_DIR(a_u4Command) // 获取读写属性域值 (bit30 ~ bit31)
    pBuff = kmalloc(_IOC_SIZE(a_u4Command), GFP_KERNEL); //分配4个字节
    if (_IOC_WRITE & _IOC_DIR(a_u4Command)) //如果是写
        copy_from_user(pBuff , (void *) a_u4Param, _IOC_SIZE(a_u4Command)) //拷贝用户空间的数据
    switch (a_u4Command) //执行IOCTL
    case KDIMGSENSORIOC_X_SET_DRIVER:   //设置对应摄像头的操作函数
       i4RetValue = kdSetDriver((unsigned int *)pBuff);  //单独分析1,这个pBuff是从上层传下来的
    case KDIMGSENSORIOC_T_CHECK_IS_ALIVE: //检查摄像头是否存在,上电和读取id
        i4RetValue = adopt_CAMERA_HW_CheckIsAlive(); //单独分析2
     case KDIMGSENSORIOC_X_GETINFO: //获取摄像头信息
        i4RetValue = adopt_CAMERA_HW_GetInfo(pBuff);
            g_pSensorFunc->SensorGetInfo(pScenarioId, pInfo, pConfig);
                SensorGetInfo //调用具体摄像头驱动的SensorGetInfo
        copy_to_user((void __user *)(pSensorGetInfo->pInfo[i]), (void *)pInfo[i] , sizeof(MSDK_SENSOR_INFO_STRUCT))  /* SenorInfo */
        copy_to_user((void __user *)(pSensorGetInfo->pConfig[i]) , (void *)pConfig[i] , sizeof(MSDK_SENSOR_CONFIG_STRUCT)) /* SensorConfig */
    case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:  //设置现在的摄像头id
        i4RetValue = kdSetCurrentSensorIdx(*pIdx);
            g_CurrentSensorIdx = idx;
    case KDIMGSENSORIOC_T_CLOSE:  //关闭摄像头
        i4RetValue = adopt_CAMERA_HW_Close();
            g_pSensorFunc->SensorClose(); //调用具体的摄像头的函数
                
 
 
static SENSOR_FUNCTION_STRUCT sensor_func = {
    open,
    get_info,
    get_resolution,
    feature_control,
    control,
    close
};        
 
//单独分析1
kdSetDriver
    kdGetSensorInitFuncList(&pSensorList) //得到sensor列表
        *ppSensorList = &kdSensorList[0];  //Kd_sensorlist.h (kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735)中的
            ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] = {
                #if defined(IMX220_MIPI_RAW)
                {IMX220_SENSOR_ID, SENSOR_DRVNAME_IMX220_MIPI_RAW, IMX220_MIPI_RAW_SensorInit},
               #endif
           }
    for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++)  //化简得到==> for(i=0;i<2;i++)
        g_bEnableDriver[i] = FALSE;
        //化简下面的==》g_invokeSocketIdx[i] = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((pDrvIndex[i] & 0xFFFF0000) >> 16); 得到高16位是1还是2,1就是主摄像头
        g_invokeSocketIdx[i] = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_MSB) >> KDIMGSENSOR_DUAL_SHIFT);
        //化简下面==》 drvIdx[i] = (pDrvIndex[i] & 0x0000FFFF); 得到低16位,就也是摄像头在表中的位置,所以kdSensorList和SensorList要一一对应
        drvIdx[i] = (pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_LSB);
        if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i])  //如果是前置摄像头
            gI2CBusNum = SUPPORT_I2C_BUS_NUM2;
        else  //否则
            gI2CBusNum = SUPPORT_I2C_BUS_NUM1;
        pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);  //执行  SensorInit函数,这里就是kdSensorList里面填的函数,得到sensor的接口函数,赋值
            GC2355_MIPI_RAW_SensorInit  //比如GC2355
                *pfFunc=&sensor_func;
        g_bEnableDriver[i] = TRUE;
        memcpy((char *)g_invokeSensorNameStr[i], (char *)pSensorList[drvIdx[i]].drvname, sizeof(pSensorList[drvIdx[i]].drvname)); //得到sensor的名字   
 
        
 
//单独分析2
adopt_CAMERA_HW_CheckIsAlive
    //上电,/* power on sensor */  
      g_invokeSocketIdx:是前摄还是后摄; g_invokeSensorNameStr:摄像头名称; true:上电; CAMERA_HW_DRVNAME1:名称
    kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *)g_invokeSocketIdx, g_invokeSensorNameStr, true, CAMERA_HW_DRVNAME1);
        if (g_bEnableDriver[i]) 
            ret = kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name);
                if (On) {
                    if (pinSetIdx == 0)  //主摄像头
ISP_MCLK1_EN(1); //第一路ISP时钟打开
   else if (pinSetIdx == 1) //副摄像头
ISP_MCLK1_EN(1); //第一路ISP时钟打开
                    if (currSensorName && (0 == strcmp(SENSOR_DRVNAME_OV5648_MIPI_RAW, currSensorName))) //匹配具体摄像头
                        if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])  //摄像头的上电脚
                            //pinSetIdx:主摄像头还是摄像头; CAMPDN:那个引脚; pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]:拉高还是拉低
           mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]); //拉低使能引脚
                        if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) 
   mtkcam_gpio_set(pinSetIdx, CAMRST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]); //拉低复位脚
                         _hwPowerOn(VCAMIO, VOL_1800)   //IO供电1.8V
                         _hwPowerOn(VCAMA, VOL_2800)  //模拟供电脚2.8v
                         _hwPowerOn(VCAMD, VOL_1500)  //数字供电聊2.5V
                         _hwPowerOn(VCAMAF, VOL_2800) //AF供电2.8v
                         if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])  
    mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]);    //拉高使能脚
                         if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST])  
   mtkcam_gpio_set(pinSetIdx, CAMRST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON]);     //拉高复位脚
                    else //如果没有特殊要求,使用默认供电函数
                        。。。。。。。。。。。。。
                else { /* power OFF */ 下电
                    if (pinSetIdx == 0)
ISP_MCLK1_EN(0);  //关闭ISP时钟
    else if (pinSetIdx == 1)
ISP_MCLK1_EN(0);
                     。。。。。。。。。。根据上电下电。。。。。。。。
    if (g_pSensorFunc)
        for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++)
            g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i], SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *)&sensorID, &retLen);
                feature_control //调用具体摄像头的feature_control函数
                   case SENSOR_FEATURE_CHECK_SENSOR_ID:  //这里获取sensor ID
                    get_imgsensor_id(feature_return_para_32); //通过I2C读取摄像头的ID
                    //如果读取到了ID就把摄像头的名字和前后摄状态记录
                    snprintf(mtk_ccm_name, sizeof(mtk_ccm_name), "%s CAM[%d]:%s;", mtk_ccm_name, g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);
                    /* reset sensor state after power off */
            err1 = g_pSensorFunc->SensorClose(); //关闭sensor
                    kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *)g_invokeSocketIdx, g_invokeSensorNameStr, false, CAMERA_HW_DRVNAME1); //下电
 
 
 
 
五.camera的i2c注册
 1. 首先注册一个假的I2C设备,然后通讯的时候用真的I2C地址,因为有两个摄像头,所以注册两个设备。
    i2c_add_driver(&CAMERA_HW_i2c_driver);    //注册I2C设备,进入I2C的CAMERA_HW_i2c_probe函数,在probe里面没有读取i2c设备,所以可以注册成功。
    g_pstI2Cclient = client;  //把client保存在g_pstI2Cclient 
 
    gc2355mipi_Sensor.c (kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735m\gc2355_mipi_raw)
   1.上层函数检查sensor是否存在的时候,也是就是四章中的单独分析2
    get_imgsensor_id(feature_return_para_32); //通过I2C读取摄像头的ID
        imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i];  //这是当前摄像头的I2C地址
        *sensor_id = return_sensor_id();
            return ((read_cmos_sensor(0xf0) << 8) | read_cmos_sensor(0xf1));
                iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, imgsensor.i2c_write_id); //读取i2c
                    //调用Kd_sensorlist.c (kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735)中的iReadRegI2C
                    g_pstI2Cclient->addr = (i2cId >> 1); //给I2Cclient赋值真正的I2C地址
                    i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); //写设备,如果能写成功,说明设备存在
                    i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData); //读,如果成功,说明存在
                    
                    
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                        
                    
     
 
posted @ 2021-04-21 20:21  luoyuna  阅读(1700)  评论(0编辑  收藏  举报