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); //讀,如果成功,說明存在
                    
                    
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                        
                    
     
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM