camera 流程分析和关键代码解释

时间:2024-11-17 07:20:26

参考文档:/computertechnology/article/details/17006107

                 /eternity9255/article/details/52085864#reply


Camera驱动的调试过程与方法总结

1、首先对照电路图,检查Camera的电路连接是否正确;

2、用万用表量Camera的电源管脚,查看Camera的供电是否正常,确定是否需要我们在程序中进行电源控制;

3、查看Camera的Spec文档,检查PWDN和RESET的管脚触发是否正常,是否需要在程序中进行控制;

4、在Camera的Datasheet中找出该设备的I2C地址,检查I2C地址配置是否正确;

5、查看I2C通信是否正常,是否能正常进行读写,用示波器量出I2C的SCL和SDA的波形是否正常,未通信时都为高电平,通信时SCL为I2C时钟信号,SDA为I2C数据通路信号;

6、用示波器量Camera的MCLK管脚,看是否正确,如果MCLK正常,通常情况下PCLK也应该有波形;

7、检查Camera的初始化寄存器列表的配置是否正确。


camera关键代码解释:

Android的各个子模块的启动都是从它们的Service的启动开始的,所以我们将从CameraService的启动开始分析。CameraService的启动就在MediaServer的main函数中,代码路径在:frameworks/av/media/mediaserver/main_mediaserver.cpp

[cpp]  view plain  copy
 
  1. int main(int argc __unused, char** argv)  
  2. {  
  3.     ......  
  4.     CameraService::instantiate();  
  5.     ......  
  6. }  

CameraService类定义如下:

[cpp]  view plain  copy
 
  1. class CameraService :  
  2.     public BinderService<CameraService>,  
  3.     public BnCameraService,  
  4.     public IBinder::DeathRecipient,  
  5.     public camera_module_callbacks_t  
  6. {  
  7.     static char const* getServiceName() { return ""; }  
  8.     ......  
  9. }  

mediaserver的main函数中调用了CameraService的instantiate函数来创建实例,该函数的实现在其父类BinderService中实现

[cpp]  view plain  copy
 
  1. template<typename SERVICE>  
  2. class BinderService  
  3. {  
  4.     static status_t publish(bool allowIsolated = false) {  
  5.         sp<IServiceManager> sm(defaultServiceManager());  
  6.         return sm->addService(  
  7.                 String16(SERVICE::getServiceName()),  
  8.                 new SERVICE(), allowIsolated);  
  9.     }     
  10.   
  11.     static void instantiate() { publish(); }  
  12.   
  13. }  

1. instantiate函数只是简单的调用了publish函数

2. publish函数先构造CameraService,再通过addService函数将它注册到ServiceManager当中,而getServiceName函数获取到的值为“media camera”。这一切都是为了binder通信做准备

3. 这里使用了c++模版,从上面的CameraService类定义中可以看出,这里的SERVICE等于CameraService,也就是说publish函数中的new SERVICE等于new CameraService

4. 同时还使用了智能指针,也就是说除了调用CameraService的构造函数外,还会调用onFirstRef函数

 

[cpp]  view plain  copy
 
  1. CameraService::CameraService()  
  2.     :mSoundRef(0), mModule(0)  
  3. {  
  4.     ALOGI("CameraService started (pid=%d)", getpid());  
  5.     gCameraService = this;  
  6.   
  7.     for (size_t i = 0; i < MAX_CAMERAS; ++i) {  
  8.         mStatusList[i] = ICameraServiceListener::STATUS_PRESENT;  
  9.     }  
  10.   
  11.     this->camera_device_status_change = android::camera_device_status_change;  
  12. }  
  13.   
  14. void CameraService::onFirstRef()  
  15. {  
  16.     LOG1("CameraService::onFirstRef");  
  17.   
  18.     BnCameraService::onFirstRef();  
  19.   
  20.     if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,  
  21.                 (const hw_module_t **)&mModule) < 0) {   
  22.         ALOGE("Could not load camera HAL module");  
  23.         mNumberOfCameras = 0;   
  24.     }      
  25.     else {  
  26.         ALOGI("Loaded \"%s\" camera module", mModule->);  
  27.         mNumberOfCameras = mModule->get_number_of_cameras();  
  28.         if (mNumberOfCameras > MAX_CAMERAS) {  
  29.             ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",  
  30.                     mNumberOfCameras, MAX_CAMERAS);  
  31.             mNumberOfCameras = MAX_CAMERAS;  
  32.         }  
  33.         for (int i = 0; i < mNumberOfCameras; i++) {  
  34.             LOG1("setCameraFree(%d)", i);  
  35.             setCameraFree(i);  
  36.         }      
  37.   
  38.         if (mModule->common.module_api_version >=  
  39.                 CAMERA_MODULE_API_VERSION_2_1) {  
  40.             mModule->set_callbacks(this);  
  41.         }      
  42.   
  43.         VendorTagDescriptor::clearGlobalVendorTagDescriptor();  
  44.   
  45.         if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {  
  46.             setUpVendorTags();  
  47.         }      
  48.   
  49.         CameraDeviceFactory::registerService(this);  
  50.     }      
  51. }  

第20行. hw_get_module是jni层获取HAL层module的接口函数,通过hw_get_module函数加载了一个hw_module_t模块,这个模块是与hal层对接的接口,ID为CAMERA_HARDWARE_MODULE_ID,并将它保存在mModule成员变量中。

第27行. 通过mModule->get_number_of_cameras函数进入到hal层,获取到了camera的个数。这个函数很重要,对于frameworks层来说只是拿到了camera的个数,但对于hal层和drivers层来说Camera的上电和初始化流程都是从这里开始的



先来看看mtk camera module的定义,代码路径在:vendor/mediatek/proprietary/hardware/mtkcam/module_hal/module/

 

[cpp]  view plain  copy
 
  1. static  
  2. camera_module  
  3. get_camera_module()  
  4. {  
  5.     camera_module module = {   
  6.         common:{  
  7.              tag                    : HARDWARE_MODULE_TAG,  
  8.              #if (PLATFORM_SDK_VERSION >= 21)  
  9.              module_api_version     : CAMERA_MODULE_API_VERSION_2_3,  
  10.              #else  
  11.              module_api_version     : CAMERA_DEVICE_API_VERSION_1_0,  
  12.              #endif  
  13.              hal_api_version        : HARDWARE_HAL_API_VERSION,  
  14.              id                     : CAMERA_HARDWARE_MODULE_ID,  
  15.              name                   : "MediaTek Camera Module",  
  16.              author                 : "MediaTek",  
  17.              methods                : get_module_methods(),  
  18.              dso                    : NULL,  
  19.              reserved               : {0},  
  20.         },    
  21.         get_number_of_cameras       : get_number_of_cameras,  
  22.         get_camera_info             : get_camera_info,  
  23.         set_callbacks               : set_callbacks,  
  24.         get_vendor_tag_ops          : get_vendor_tag_ops,  
  25.         #if (PLATFORM_SDK_VERSION >= 21)  
  26.         open_legacy                 : open_legacy,  
  27.         #endif  
  28.         reserved                    : {0},  
  29.     };    
  30.     return  module;  
  31. };  

1. 保存在frameworks层CameraService的成员变量mModule里面的就是上面这个module结构体

 

2. 当frameworks层调用mModule->get_number_of_cameras函数时,实际就是调用上面结构体的get_number_of_cameras函数

[cpp]  view plain  copy
 
  1. CamDeviceManagerImp gCamDeviceManager;  
  2.   
  3. ICamDeviceManager*  
  4. getCamDeviceManager()  
  5. {  
  6.     return &gCamDeviceManager;  
  7. }  
  8.   
  9. static  
  10. int  
  11. get_number_of_cameras(void)  
  12. {  
  13.     return  NSCam::getCamDeviceManager()->getNumberOfDevices();  
  14. }  

1. 这里先通过getCamDeviceManager函数获取了CamDeviceManagerImp对象

 

2. CamDeviceManagerImp继承了CamDeviceManagerBase,这里的getNumberOfDevices方法将由父类CamDeviceManagerBase实现

[cpp]  view plain  copy
 
  1. int32_t  
  2. CamDeviceManagerBase::  
  3. getNumberOfDevices()  
  4. {  
  5.     mi4DeviceNum = enumDeviceLocked();  
  6.     return  mi4DeviceNum;  
  7. }  

这里只是调用了enumDeviceLocked函数,并将它的返回值(代表了camera的个数)返回到frameworks层。接着看enumDeviceLocked的实现

[cpp]  view plain  copy
 
  1. int32_t  
  2. CamDeviceManagerImp::  
  3. enumDeviceLocked()  
  4. {  
  5.     IHalSensorList*const pHalSensorList = IHalSensorList::get();  
  6.     size_t const sensorNum = pHalSensorList->searchSensors();  
  7.   
  8.     for (size_t i = 0; i < sensorNum; i++)  
  9.     {  
  10.         int32_t const deviceId = i;  
  11.   
  12.         sp<EnumInfo> pInfo = new EnumInfo;  
  13.         (deviceId, pInfo);  
  14.   
  15.         IMetadataProvider> pMetadataProvider = IMetadataProvider::create(deviceId);  
  16.         pInfo->pMetadata            = pMetadataProvider->getStaticCharacteristics();  
  17.         pInfo->iFacing              = (pMetadataProvider->getDeviceFacing() == MTK_LENS_FACING_FRONT)  
  18.                                         ? CAMERA_FACING_FRONT  
  19.                                         : CAMERA_FACING_BACK  
  20.                                         ;  
  21.         pInfo->iWantedOrientation   = pMetadataProvider->getDeviceWantedOrientation();  
  22.         pInfo->iSetupOrientation    = pMetadataProvider->getDeviceSetupOrientation();  
  23.         i4DeviceNum++;  
  24.     }  
  25.   
  26.     return i4DeviceNum;  
  27. }  

第5-6行. 这里需要重点关注pHalSensorList->searchSensors函数,它的返回值就是camera的个数

第8-24行. 循环构造并初始化一个EnumInfo对象,并把它保存在mEnumMap中

 

[cpp]  view plain  copy
 
  1. MUINT  
  2. HalSensorList::  
  3. enumerateSensor_Locked()  
  4. {     
  5.     int ret_count = 0;  
  6.     SensorDrv *const pSensorDrv = SensorDrv::get();  
  7.     int const iSensorsList = pSensorDrv->impSearchSensor(NULL);  
  8.   
  9.     if((iSensorsList & SENSOR_DEV_MAIN) == SENSOR_DEV_MAIN)  
  10.     {  
  11.         halSensorDev = SENSOR_DEV_MAIN;  
  12.         pSensorInfo = pSensorDrv->getMainSensorInfo();  
  13.         addAndInitSensorEnumInfo_Locked(halSensorDev, ret_count, mapToSensorType(pSensorInfo->GetType()), pSensorInfo->getDrvMacroName());  
  14.         ret_count++;  
  15.     }  
  16.   
  17.     if((iSensorsList & SENSOR_DEV_SUB) == SENSOR_DEV_SUB)  
  18.     {  
  19.         halSensorDev = SENSOR_DEV_SUB;  
  20.         pSensorInfo = pSensorDrv->getSubSensorInfo();  
  21.         addAndInitSensorEnumInfo_Locked(halSensorDev, ret_count, mapToSensorType(pSensorInfo->GetType()), pSensorInfo->getDrvMacroName());  
  22.         ret_count++;  
  23.     }  
  24.   
  25.     mEnumSensorCount = ret_count;  
  26.     return  ret_count;  
  27. }  
  28.   
  29. MUINT  
  30. HalSensorList::  
  31. searchSensors()  
  32. {     
  33.     return  enumerateSensor_Locked();  
  34. }     

第33行. searchSensors函数只是调用了enumerateSensor_Locked函数,这里并没有贴出enumerateSensor_Locked函数的所有代码,删减了一些我们暂时不关注的东西

第7行. 重点函数pSensorDrv->impSearchSensor,它的返回值决定了enumerateSensor_Locked的返回值,也就是camera的个数

 

[cpp]  view plain  copy
 
  1. MINT32  
  2. ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)  
  3. {  
  4.     MUINT32 SensorEnum = (MUINT32) DUAL_CAMERA_MAIN_SENSOR;  
  5.     MUINT32 i,id[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0,0};  
  6.     MINT32 sensorDevs = SENSOR_NONE;  
  7.   
  8.     GetSensorInitFuncList(&m_pstSensorInitFunc);  
  9.     m_fdSensor = ::open("/dev/kd_camera_hw", O_RDWR);  
  10.   //这里有2个循环:第一层循环2次,先主后次;第2层循环16次;通过这2层循环就遍历sensorlist中所有可能存在的camera,并给出找出的camera的sensorType  position  sensorid
  11.     for (SensorEnum = DUAL_CAMERA_MAIN_SENSOR; SensorEnum <= DUAL_CAMERA_SUB_SENSOR; SensorEnum <<= 1) {  
  12.         for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {  
  13.             //end of driver list  
  14.             if (m_pstSensorInitFunc[i].getCameraDefault == NULL) {  
  15.                 LOG_MSG("m_pstSensorInitFunc[i].getCameraDefault is NULL: %d \n", i);  
  16.                 break;  
  17.             }  
  18.   
  19.             id[KDIMGSENSOR_INVOKE_DRIVER_0] = (SensorEnum << KDIMGSENSOR_DUAL_SHIFT) | i;  
  20.             err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );   //获取当前camera的名字,并把sensorinit 函数赋值给对应的驱动;
  21.             err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);  //通过检查i2c 通讯是否正常来判断camera 驱动是否已经加载正常
  22.   
  23.             if (err < 0 || err2 < 0) {  
  24.                 LOG_MSG("sensor ID mismatch\n");  
  25.                 continue;  
  26.             }  
  27.   
  28.             if (SensorEnum == DUAL_CAMERA_MAIN_SENSOR) {  
  29.                 m_mainSensorDrv.index[m_mainSensorDrv.number] = i;  
  30.                 m_mainSensorDrv.type[m_mainSensorDrv.number] = sensorType;  
  31.                 m_mainSensorDrv.position = socketPos;  
  32.                 m_mainSensorDrv.sensorID = m_pstSensorInitFunc[m_mainSensorDrv.index[m_mainSensorDrv.number]].SensorId;  
  33.                 m_mainSensorDrv.number++;  
  34.             } else if (SensorEnum == DUAL_CAMERA_SUB_SENSOR) {  
  35.                 m_subSensorDrv.index[m_subSensorDrv.number] = i;  
  36.                 m_subSensorDrv.type[m_subSensorDrv.number] = sensorType;  
  37.                 m_subSensorDrv.position = socketPos;  
  38.                 m_subSensorDrv.sensorID = m_pstSensorInitFunc[m_subSensorDrv.index[m_subSensorDrv.number]].SensorId;  
  39.                 m_subSensorDrv.number++;  
  40.             }  
  41.         }  
  42.     }  
  43.   
  44.     if (BAD_SENSOR_INDEX != m_mainSensorDrv.index[0]) {  
  45.         m_mainSensorId = m_mainSensorDrv.sensorID;  
  46.         m_mainSensorIdx = m_mainSensorDrv.index[0];  
  47.         sensorDevs |= SENSOR_MAIN;  
  48.     }  
  49.     if (BAD_SENSOR_INDEX != m_subSensorDrv.index[0]) {  
  50.         m_subSensorId = m_subSensorDrv.sensorID;  
  51.         m_subSensorIdx = m_subSensorDrv.index[0];  
  52.         sensorDevs |= SENSOR_SUB;  
  53.     }  
  54.   
  55.     return sensorDevs;  
  56. }  

这个函数比较长,所以只贴出关键代码

第8行, 调用GetSensorInitFuncList函数来获取hal层的sersors列表,并把它保存在m_pstSensorInitFunc变量中

第9行, 通过系统调用open函数打开camera的设备节点,后面会通过这个节点来进入到kernel层

第11-12行, 通过两个for循环来遍历sensorlist中所有可能存在的camera

第20行, 通过ioctl下达setDriver指令,并下传正在遍历的sensorlist中的ID。Driver层根据这个ID,挂载Driver层sensorlist中对应的操作接口

第21行, 通过ioctl下达check ID指令,Driver层为对应sensor上电,通过I2C读取预存在寄存器中的sensor id。然后比较读取结果,如果不匹配return error后继续遍历

第29-41行, 将sensor相关的信息保存在m_mainSensorDrv和m_subSensorDrv中

第45-56行, 给sensroDevs变量赋值,并将它返回给上一级

这里暂不分析kernel层的代码,先来看看GetSensorInitFuncList函数,代码在中

 

[cpp]  view plain  copy
 
  1. MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =  
  2. {  
  3. #if defined(IMX175_MIPI_RAW)  
  4.     RAW_INFO(IMX175_SENSOR_ID, SENSOR_DRVNAME_IMX175_MIPI_RAW,NULL),  
  5. #endif  
  6. #if defined(IMX179_MIPI_RAW)  
  7.     RAW_INFO(IMX179_SENSOR_ID, SENSOR_DRVNAME_IMX179_MIPI_RAW,NULL),  
  8. #endif  
  9. #if defined(IMX219_MIPI_RAW)  
  10.     RAW_INFO(IMX219_SENSOR_ID, SENSOR_DRVNAME_IMX219_MIPI_RAW, NULL),  
  11. #endif  
  12. #if defined(IMX214_MIPI_RAW)  
  13.     RAW_INFO(IMX214_SENSOR_ID, SENSOR_DRVNAME_IMX214_MIPI_RAW,NULL),  
  14. #endif  
  15. #if defined(GC2235_RAW)  
  16.     RAW_INFO(GC2235_SENSOR_ID, SENSOR_DRVNAME_GC2235_RAW, NULL),  
  17. #endif  
  18. #if defined(GC2035_YUV)  
  19.     YUV_INFO(GC2035_SENSOR_ID, SENSOR_DRVNAME_GC2035_YUV, NULL),  
  20. #endif  
  21.     ......  
  22. }  
  23.   
  24. UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)  
  25. {         
  26.     *ppSensorList = &SensorList[0];  
  27.     return MHAL_NO_ERROR;  
  28. }  

hal层的sensorList,再熟悉不过的代码,需要注意的是hal层sensorList和kernel层的sensorList顺序必须保持一致

代码路径参考:

mt6737 M0  c66项目    (同样适合mt8735_7.0) 
device/joya/joya6737m_65_m0/
device/mediatek/common/kernel-headers/kd_imgsensor.h 
kernel-3.18/arch/arm64/boot/dts/cust_i2c.dtsi 
kernel-3.18/arch/arm64/boot/dts/joya6737m_65_m0.dts
kernel-3.18/arch/arm64/configs/joya6737m_65_m0_debug_defconfig 
kernel-3.18/arch/arm64/configs/joya6737m_65_m0_defconfig 
kernel-3.18/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor.h 
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735m/camera_hw/kd_camera_hw.c 
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735m/kd_sensorlist.c 
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735m/kd_sensorlist.h
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735m/ov2710_mipi_yuv 
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735m/tvp5151_yuv 
kernel-3.18/drivers/misc/mediatek/mach/mt6735/joya6737m_65_m0/dct/dct/ 
vendor/mediatek/proprietary/bootable/bootloader/lk/target/joya6737m_65_m0/dct/dct/ 
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/joya6737m_65_m0/dct/dct/ 
vendor/mediatek/proprietary/custom/joya6737m_65_m0/kernel/dct/dct/ 
vendor/mediatek/proprietary/custom/mt6735/hal/D1/imgsensor_src/ 
vendor/mediatek/proprietary/custom/mt6735/hal/D2/imgsensor_src/