MTK6580(Android6.0)-camera 驱动分析


一、MTK6580 平台 Camera 驱动整体框架

mtk平台三大件调试中,camera的调试难度最大,问题也就最多,为此特地分析了一下整个camera驱动部分

实现过程,以下为camera驱动框架序列图:

      

从图中可以看出,整个框架分为三个部分hal部分逻辑调用,kernel层的通用驱动sensorlist.c 和具体IC的驱动

xxxx_mipi_raw.c,kernel起来后不会直接去访问硬件sensor,而是会注册相关的驱动,之后Android系统起来后

会启动相关的服务如:camera_service,在camera服务中会直接去访问hal,kernel驱动,进而操作camera。

为此本文也穿插了部分hal层的调用,至于camera_service后面章节会继续补充。

二、 Camera 驱动的具体实现

========================HAL 层部分初始调用========================
文件:vendor/mediatek/proprietary/hardware/mtkcam/common/module_hal/devicemgr/CamDeviceManagerBase.cpp

  1. int32_t  
  2. CamDeviceManagerBase::  
  3. getNumberOfDevices()  
  4. {  
  5.         …  
  6.         mi4DeviceNum = enumDeviceLocked();  
  7.       
  8.         …  
  9. }  
int32_t 
CamDeviceManagerBase::
getNumberOfDevices()
{

mi4DeviceNum = enumDeviceLocked();

    ...

}文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/devicemgr/CamDeviceManagerImp.cpp

  1. int32_t  
  2. CamDeviceManagerImp::  
  3. enumDeviceLocked()  
  4. {  
  5.     …  
  6. //——————————————————————————  
  7. #if ‘1’==MTKCAM_HAVE_SENSOR_HAL  
  8.     //  
  9.     IHalSensorList*const pHalSensorList = IHalSensorList::get();  
  10.     size_t const sensorNum = pHalSensorList->searchSensors();  
  11. #endif  
  12.     …  
  13.     return  i4DeviceNum;  
  14. }  
int32_t 
CamDeviceManagerImp::
enumDeviceLocked()
{

//——————————————————————————

if ‘1’==MTKCAM_HAVE_SENSOR_HAL

//
IHalSensorList*const pHalSensorList = IHalSensorList::get();
size_t const sensorNum = pHalSensorList->searchSensors();

endif

...
return  i4DeviceNum;

}文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.cpp

  1. MUINT  
  2. HalSensorList::  
  3. searchSensors()  
  4. {  
  5.     Mutex::Autolock _l(mEnumSensorMutex);  
  6.     //  
  7.     MY_LOGD(”searchSensors”);  
  8.     return  enumerateSensor_Locked();  
  9. }  
MUINT 
HalSensorList::
searchSensors()
{
Mutex::Autolock _l(mEnumSensorMutex);
//
MY_LOGD("searchSensors");
return enumerateSensor_Locked();
}
文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.enumList.cpp
  1. MUINT  
  2. HalSensorList::  
  3. enumerateSensor_Locked()  
  4. {  
  5.     ….  
  6.   
  7.   
  8.     MUINT halSensorDev = SENSOR_DEV_NONE;  
  9.     NSFeature::SensorInfoBase* pSensorInfo ;  
  10.   
  11.   
  12.     SensorDrv const pSensorDrv = SensorDrv::get();  
  13.     SeninfDrv const pSeninfDrv = SeninfDrv::createInstance();  
  14.       
  15.     int const iSensorsList = pSensorDrv->impSearchSensor(NULL);  
  16.   
  17.   
  18.     ….  
  19. }  
MUINT 
HalSensorList::
enumerateSensor_Locked()
{
….

MUINT halSensorDev = SENSOR_DEV_NONE;
NSFeature::SensorInfoBase* pSensorInfo ;


SensorDrv *const pSensorDrv = SensorDrv::get();
SeninfDrv *const pSeninfDrv = SeninfDrv::createInstance();

int const iSensorsList = pSensorDrv->impSearchSensor(NULL);


....

}文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/imgsensor_drv.cpp

  1. MINT32  
  2. ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)  
  3. {  
  4.     ….  
  5.   
  6.   
  7.     GetSensorInitFuncList(&m_pstSensorInitFunc);  
  8.   
  9.   
  10.     LOG_MSG(”SENSOR search start \n”);  
  11.   
  12.   
  13.     sprintf(cBuf,”/dev/%s”,CAMERA_HW_DEVNAME);  
  14.     m_fdSensor = ::open(cBuf, O_RDWR);  
  15.   
  16.   
  17.     ……  
  18.       
  19.         for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {  
  20.             ….  
  21.             err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );  
  22.             …  
  23.             err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);  
  24.   
  25.   
  26.     ……  
  27. }  
MINT32 
ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)
{
….

GetSensorInitFuncList(&amp;m_pstSensorInitFunc);


LOG_MSG("SENSOR search start \n");


sprintf(cBuf,"/dev/%s",CAMERA_HW_DEVNAME);
m_fdSensor = ::open(cBuf, O_RDWR);


......

    for (i = 0; i &lt; MAX_NUM_OF_SUPPORT_SENSOR; i++) {
        ....
        err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&amp;id[KDIMGSENSOR_INVOKE_DRIVER_0] );
        ...
        err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);


......

}GetSensorInitFuncList的实现
文件:vendor/mediatek/proprietary/custom/mt6580/hal/imgsensor_src/sensorlist.cpp

  1. UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)  
  2. {  
  3.     if (NULL == ppSensorList) {  
  4.         ALOGE(”ERROR: NULL pSensorList\n”);  
  5.         return MHAL_UNKNOWN_ERROR;  
  6.     }  
  7.     *ppSensorList = &SensorList[0];  
  8.     return MHAL_NO_ERROR;  
  9. }   
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;
}
Sensor 列表的定义如下:
  1. MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =  
  2. {  
  3. //xc add camera start  
  4. #if defined(GC2365MIPI_RAW)  
  5.     RAW_INFO(GC2365MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2365MIPI_RAW, NULL),  
  6. #endif  
  7.   
  8.   
  9. #if defined(GC2355_MIPI_RAW_BAIKANG_M8112)  
  10.     RAW_INFO(GC2355_SENSOR_ID, SENSOR_DRVNAME_GC2355_MIPI_RAW,NULL),  
  11. #endif  
  12. ….  
  13. }  
MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] = 
{
//xc add camera start

if defined(GC2365MIPI_RAW)

RAW_INFO(GC2365MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2365MIPI_RAW, NULL),

endif

if defined(GC2355_MIPI_RAW_BAIKANG_M8112)

RAW_INFO(GC2355_SENSOR_ID, SENSOR_DRVNAME_GC2355_MIPI_RAW,NULL),

endif

….
}获取sensor列表后,紧接着通过:
err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
访问kernel层的数据
====================== Kernel 层驱动的实现 ========================
1. 针对前后摄注册platform 设备和驱动
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c

  1. static int __init CAMERA_HW_i2C_init(void)  
  2. {  
  3.     ….  
  4.       
  5.   
  6.   
  7.     if (platform_driver_register(&g_stCAMERA_HW_Driver)) //注册主摄platform 驱动  
  8.     if (platform_driver_register(&g_stCAMERA_HW_Driver2)) //注册副摄platform 驱动  
  9.   
  10.   
  11.     ….  
  12.     return 0;  
  13. }  
static int __init CAMERA_HW_i2C_init(void) 
{
….

if (platform_driver_register(&amp;g_stCAMERA_HW_Driver)) //注册主摄platform 驱动
if (platform_driver_register(&amp;g_stCAMERA_HW_Driver2)) //注册副摄platform 驱动


....
return 0;

}主摄平台驱动的定义:

  1. #ifdef CONFIG_OF  
  2. static const struct of_device_id CAMERA_HW_of_ids[] = {  
  3.     {.compatible = ”mediatek,camera_hw”,},  //主摄匹配规则  
  4.     {}  
  5. };  
  6. #endif  
  7.   
  8.   
  9. static struct platform_driver g_stCAMERA_HW_Driver = {  
  10.     .probe = CAMERA_HW_probe,  
  11.     .remove = CAMERA_HW_remove,  
  12.     .suspend = CAMERA_HW_suspend,  
  13.     .resume = CAMERA_HW_resume,  
  14.     .driver = {  
  15.            .name = ”image_sensor”,  
  16.            .owner = THIS_MODULE,  
  17. #ifdef CONFIG_OF  
  18.            .of_match_table = CAMERA_HW_of_ids,  
  19. #endif  
  20.            }  
  21. };  
#ifdef CONFIG_OF 
static const struct of_device_id CAMERA_HW_of_ids[] = {
{.compatible = “mediatek,camera_hw”,}, //主摄匹配规则
{}
};

endif

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

       }

};副摄平台驱动的定义:

  1. #ifdef CONFIG_OF  
  2. static const struct of_device_id CAMERA_HW2_of_ids[] = {  
  3.     {.compatible = ”mediatek,camera_hw2”,},//副摄匹配规则  
  4.     {}  
  5. };  
  6. #endif  
  7.   
  8.   
  9. static struct platform_driver g_stCAMERA_HW_Driver2 = {  
  10.     .probe = CAMERA_HW_probe2,  
  11.     .remove = CAMERA_HW_remove2,  
  12.     .suspend = CAMERA_HW_suspend2,  
  13.     .resume = CAMERA_HW_resume2,  
  14.     .driver = {  
  15.            .name = ”image_sensor_bus2”,  
  16.            .owner = THIS_MODULE,  
  17. #ifdef CONFIG_OF  
  18.            .of_match_table = CAMERA_HW2_of_ids,  
  19. #endif  
  20.   
  21.   
  22.     }  
  23. };  
#ifdef CONFIG_OF 
static const struct of_device_id CAMERA_HW2_of_ids[] = {
{.compatible = “mediatek,camera_hw2”,},//副摄匹配规则
{}
};

endif

static 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

}

};主副摄cam在dts中定义设备信息:

  1. kd_camera_hw1:kd_camera_hw1@15008000 {  
  2.     compatible = ”mediatek,camera_hw”//这里必须和主摄一致  
  3.     reg = <0x15008000 0x1000>;  / SENINF_ADDR /  
  4.     vcama-supply = <&mt_pmic_vcama_ldo_reg>;  
  5.     vcamd-supply = <&mt_pmic_vcamd_ldo_reg>;  
  6.     vcamaf-supply = <&mt_pmic_vcamaf_ldo_reg>;  
  7.     vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;  
  8.   
  9.   
  10. };  
  11. kd_camera_hw2:kd_camera_hw2@15008000 {  
  12.     compatible = ”mediatek,camera_hw2”//这里必须和副摄一致  
  13.     reg = <0x15008000 0x1000>;  / SENINF_ADDR /  
  14. };  
kd_camera_hw1:kd_camera_hw1@15008000 { 
compatible = “mediatek,camera_hw”; //这里必须和主摄一致
reg = <0x15008000 0x1000>; /* SENINF_ADDR */
vcama-supply = <&mt_pmic_vcama_ldo_reg>;
vcamd-supply = <&mt_pmic_vcamd_ldo_reg>;
vcamaf-supply = <&mt_pmic_vcamaf_ldo_reg>;
vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;

};
kd_camera_hw2:kd_camera_hw2@15008000 {
compatible = “mediatek,camera_hw2”; //这里必须和副摄一致
reg = <0x15008000 0x1000>; /* SENINF_ADDR */
};       当内核启动后,会解析dts编译生成的dtb文件,注册里面定义的device,如果和驱动中定义id一致,则挂载启动。

上面注册了两个platform 驱动g_stCAMERA_HW_Driver,g_stCAMERA_HW_Driver2,如果匹配成功会调用各自的

probe函数CAMERA_HW_probe,CAMERA_HW_probe2

2. 平台probe 函数的实现
主摄probe,CAMERA_HW_probe的实现如下:

  1. static int CAMERA_HW_probe(struct platform_device *pdev)  
  2. {  
  3. #if !defined(CONFIG_MTK_LEGACY)  
  4.     mtkcam_gpio_init(pdev);  
  5.     mtkcam_pin_mux_init(pdev);  
  6. #endif  
  7.     return i2c_add_driver(&CAMERA_HW_i2c_driver);  
  8. }  
static int CAMERA_HW_probe(struct platform_device *pdev) 
{

if !defined(CONFIG_MTK_LEGACY)

mtkcam_gpio_init(pdev);
mtkcam_pin_mux_init(pdev);

endif

return i2c_add_driver(&amp;CAMERA_HW_i2c_driver);

}副摄probe,CAMERA_HW_probe的实现如下:

  1. static int CAMERA_HW_probe2(struct platform_device *pdev)  
  2. {  
  3.     return i2c_add_driver(&CAMERA_HW_i2c_driver2);  
  4. }  
static int CAMERA_HW_probe2(struct platform_device *pdev) 
{
return i2c_add_driver(&CAMERA_HW_i2c_driver2);
}
从上可以看出在main/sub 的平台probe中分别注册了各自的i2c驱动CAMERA_HW_i2c_driver,
CAMERA_HW_i2c_driver2, main sensor 的CAMERA_HW_i2c_driver定义如下:
  1. #ifdef CONFIG_OF  
  2. static const struct of_device_id CAMERA_HW_i2c_of_ids[] = {  
  3.     { .compatible = ”mediatek,camera_main”, },  
  4.     {}  
  5. };  
  6. #endif  
  7.   
  8.   
  9. struct i2c_driver CAMERA_HW_i2c_driver = {  
  10.     .probe = CAMERA_HW_i2c_probe,  
  11.     .remove = CAMERA_HW_i2c_remove,  
  12.     .driver = {  
  13.            .name = CAMERA_HW_DRVNAME1,  
  14.            .owner = THIS_MODULE,  
  15.   
  16.   
  17. #ifdef CONFIG_OF  
  18.            .of_match_table = CAMERA_HW_i2c_of_ids,  
  19. #endif  
  20.            },  
  21.     .id_table = CAMERA_HW_i2c_id,  
  22. };  
  23. sub sensor 的CAMERA_HW_i2c_driver定义如下:  
  24. #ifdef CONFIG_OF  
  25.     static const struct of_device_id CAMERA_HW2_i2c_driver_of_ids[] = {  
  26.     { .compatible = ”mediatek,camera_sub”, },  
  27.     {}  
  28.     };  
  29. #endif  
  30.   
  31.   
  32. struct i2c_driver CAMERA_HW_i2c_driver2 = {  
  33.     .probe = CAMERA_HW_i2c_probe2,  
  34.     .remove = CAMERA_HW_i2c_remove2,  
  35.     .driver = {  
  36.     .name = CAMERA_HW_DRVNAME2,  
  37.     .owner = THIS_MODULE,  
  38. #ifdef CONFIG_OF  
  39.     .of_match_table = CAMERA_HW2_i2c_driver_of_ids,  
  40. #endif  
  41.            },  
  42.     .id_table = CAMERA_HW_i2c_id2,  
  43. };  
#ifdef CONFIG_OF 
static const struct of_device_id CAMERA_HW_i2c_of_ids[] = {
{ .compatible = “mediatek,camera_main”, },
{}
};

endif

struct 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,

};
sub sensor 的CAMERA_HW_i2c_driver定义如下:

ifdef CONFIG_OF

static const struct of_device_id CAMERA_HW2_i2c_driver_of_ids[] = {
{ .compatible = "mediatek,camera_sub", },
{}
};

endif

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,

};对应main/sub camera i2c 设备dts定义如下
文件:kernel-3.18/arch/arm/boot/dts/cust_i2c.dtsi

  1. &i2c0 {  
  2.     camera_main@10 {  
  3.         compatible = ”mediatek,camera_main”//和 CAMERA_HW_i2c_driver定义的一致  
  4.         reg = <0x10>;  
  5.     };  
  6.   
  7.   
  8.     camera_main_af@0c {  
  9.         compatible = ”mediatek,camera_main_af”;  
  10.         reg = <0x0c>;  
  11.     };  
  12.   
  13.   
  14.     camera_sub@3c {  
  15.         compatible = ”mediatek,camera_sub”//和CAMERA_HW_i2c_driver2定义的一致  
  16.         reg = <0x3c>;  
  17.     };  
  18.   
  19.   
  20. };  
&i2c0 { 
camera_main@10 {
compatible = “mediatek,camera_main”; //和 CAMERA_HW_i2c_driver定义的一致
reg = <0x10>;
};

camera_main_af@0c {
    compatible = "mediatek,camera_main_af";
    reg = &lt;0x0c&gt;;
};


camera_sub@3c {
    compatible = "mediatek,camera_sub"; //和CAMERA_HW_i2c_driver2定义的一致
    reg = &lt;0x3c&gt;;
};

};3. I2c probe的实现

从上可以看出main/sub sensor在各自的平台probe中,注册了i2c_driver,当各自的i2c_driver和设备匹配

(如何匹配本章不作分析)成功后,会调用各自的i2c_probe函数。main sensor 的probe函数
CAMERA_HW_i2c_probe:

  1. static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)  
  2. {  
  3.     …..  
  4.     /* Register char driver */  
  5.     i4RetValue = RegisterCAMERA_HWCharDrv();  
  6.   
  7.   
  8.     …..  
  9.     return 0;  
  10. }  
static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    .....
    /* Register char driver */
    i4RetValue = RegisterCAMERA_HWCharDrv();


    .....
    return 0;
}
sub sensor 的probe函数CAMERA_HW_i2c_probe2:
  1. static int CAMERA_HW_i2c_probe2(struct i2c_client *client, const struct i2c_device_id *id)  
  2. {  
  3.     …..  
  4.   
  5.   
  6.     /* Register char driver */  
  7.     i4RetValue = RegisterCAMERA_HWCharDrv2();  
  8.   
  9.   
  10.     …..  
  11. }  
static int CAMERA_HW_i2c_probe2(struct i2c_client *client, const struct i2c_device_id *id)
{
    .....


    /* Register char driver */
    i4RetValue = RegisterCAMERA_HWCharDrv2();


    .....
}
       从上可以看出main/sub 在各自的i2cprobe中,通过该调用RegisterCAMERA_HWCharDrv,RegisterCAMERA_HWCharDrv2 注册了字符设备。 各自注册cdev函数实现如下:
  1. static inline int RegisterCAMERA_HWCharDrv(void)//main sensor 注册cdev  
  2. {  
  3.   
  4.   
  5.     …..  
  6.     /* Attatch file operation. */  
  7.     cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); //初始化字符设备  
  8.       
  9.     /* Add to system */  
  10.     cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, 1) //注册到内核  
  11.   
  12.   
  13.     //创建目录 /sys/class/sensordrv/  
  14.     sensor_class = class_create(THIS_MODULE, ”sensordrv”);   
  15.     //创建目录/sys/class/sensordrv/kd_camera_hw   
  16.     sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1);   
  17.   
  18.   
  19.     ….      
  20.     return 0;  
  21. }  
  22. static inline int RegisterCAMERA_HWCharDrv2(void)//sub sensor 注册cdev  
  23. {  
  24.     ….  
  25.   
  26.   
  27.     /* Attatch file operation. */  
  28.     cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0);//初始化字符设备   
  29.     /* Add to system */  
  30.     cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, 1));//注册到内核  
  31.     //创建目录 /sys/class/sensordrv2/  
  32.     sensor2_class = class_create(THIS_MODULE, ”sensordrv2”);  
  33.     //创建目录/sys/class/sensordrv2/kd_camera_hw_bus2  
  34.     sensor_device2 = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2);  
  35.     ….  
  36.     return 0;  
  37. }  
  38. main/sub 创建各自的字符设备过程中绑定各自的fops,g_stCAMERA_HW_fops和g_stCAMERA_HW_fops0  
  39. 他们各自定义如下  
  40. static const struct file_operations g_stCAMERA_HW_fops = { //main sensor fops  
  41.     .owner = THIS_MODULE,  
  42.     .open = CAMERA_HW_Open,  
  43.     .release = CAMERA_HW_Release,  
  44.     .unlocked_ioctl = CAMERA_HW_Ioctl,  
  45. #ifdef CONFIG_COMPAT  
  46.     .compat_ioctl = CAMERA_HW_Ioctl_Compat,  
  47. #endif  
  48.   
  49.   
  50. };  
  51.   
  52.   
  53. static const struct file_operations g_stCAMERA_HW_fops0 = { //sub sensor fops  
  54.     .owner = THIS_MODULE,  
  55.     .open = CAMERA_HW_Open2,  
  56.     .release = CAMERA_HW_Release2,  
  57.     .unlocked_ioctl = CAMERA_HW_Ioctl,  
  58. #ifdef CONFIG_COMPAT  
  59.     .compat_ioctl = CAMERA_HW_Ioctl_Compat,  
  60. #endif  
  61.   
  62.   
  63. };  
static inline int RegisterCAMERA_HWCharDrv(void)//main sensor 注册cdev
{


    .....
    /* Attatch file operation. */
    cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); //初始化字符设备

    /* Add to system */
    cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, 1) //注册到内核


    //创建目录 /sys/class/sensordrv/
    sensor_class = class_create(THIS_MODULE, "sensordrv"); 
    //创建目录/sys/class/sensordrv/kd_camera_hw 
    sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1); 


    ....    
    return 0;
}
static inline int RegisterCAMERA_HWCharDrv2(void)//sub sensor 注册cdev
{
    ....


    /* Attatch file operation. */
    cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0);//初始化字符设备 
    /* Add to system */
    cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, 1));//注册到内核
    //创建目录 /sys/class/sensordrv2/
    sensor2_class = class_create(THIS_MODULE, "sensordrv2");
    //创建目录/sys/class/sensordrv2/kd_camera_hw_bus2
    sensor_device2 = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2);
    ....
    return 0;
}
main/sub 创建各自的字符设备过程中绑定各自的fops,g_stCAMERA_HW_fops和g_stCAMERA_HW_fops0
他们各自定义如下
static const struct file_operations g_stCAMERA_HW_fops = { //main sensor 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

};

static const struct file_operations g_stCAMERA_HW_fops0 = { //sub sensor fops
.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

};

从上可以看出各自的fops指定了相同的Iioctl函数,意味着上层操作main/sub sensor 只需要对应一个底层

的ioctl即可,至于sensor的区分可以借助idx,后面会讲到

  1. /******************************************************************************* 
  2. * CAMERA_HW_Ioctl 
  3. ********************************************************************************/  
  4.   
  5.   
  6. static long CAMERA_HW_Ioctl(struct file *a_pstFile,  
  7.                 unsigned int a_u4Command, unsigned long a_u4Param)  
  8. {  
  9.   
  10.   
  11.     …  
  12.     pIdx = (u32 *) pBuff;  
  13.     switch (a_u4Command) {  
  14.     …  
  15.   
  16.   
  17.     case KDIMGSENSORIOC_X_SET_DRIVER:  
  18.         i4RetValue = kdSetDriver((unsigned int *)pBuff);  
  19.         break;  
  20.   
  21.   
  22.     case KDIMGSENSORIOC_X_FEATURECONCTROL:  
  23.         i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);  
  24.         break;  
  25.   
  26.   
  27.     case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:  
  28.         i4RetValue = adopt_CAMERA_HW_CheckIsAlive();  
  29.         break;  
  30.       
  31.     ….  
  32.     default:  
  33.         PK_DBG(”No such command\n”);  
  34.         i4RetValue = -EPERM;  
  35.         break;  
  36.   
  37.   
  38.     }  
  39.   
  40.   
  41.     …..  
  42. }  
/*******************************************************************************
* CAMERA_HW_Ioctl
********************************************************************************/


static long CAMERA_HW_Ioctl(struct file *a_pstFile,
                unsigned int a_u4Command, unsigned long a_u4Param)
{


    ...
    pIdx = (u32 *) pBuff;
    switch (a_u4Command) {
    ...


    case KDIMGSENSORIOC_X_SET_DRIVER:
        i4RetValue = kdSetDriver((unsigned int *)pBuff);
        break;


    case KDIMGSENSORIOC_X_FEATURECONCTROL:
        i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
        break;


    case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
        i4RetValue = adopt_CAMERA_HW_CheckIsAlive();
        break;

    ....
    default:
        PK_DBG("No such command\n");
        i4RetValue = -EPERM;
        break;


    }


    .....
}
这里ioctl和上层一一对应,上层要控制caemra 只需要传入相应的cmd和data而已

============================== HAL 调用Kernel 层驱动的逻辑 ========================
       前面介绍了HAL层调用ioctl 和 kernel层注册驱动,接下来继续分析,HAL层调用 后驱动 具体的实现流程。
4. ioctl 底层的实现
4.1先来看ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
当KDIMGSENSORIOC_X_SET_DRIVER被传下时,会调用kernel层的kdSetDriver接口
  1. int kdSetDriver(unsigned int *pDrvIndex)  
  2. {  
  3.     …  
  4.   
  5.   
  6.     kdGetSensorInitFuncList(&pSensorList))   //获得sensor初始化列表  
  7.   
  8.   
  9.     for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {  
  10.     ….  
  11.         pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); //获取各个cam驱动中Init函数入口  
  12.   
  13.   
  14.     ….  
  15.     }  
  16.     return 0;  
  17. }  
int kdSetDriver(unsigned int *pDrvIndex)
{
    ...


    kdGetSensorInitFuncList(&pSensorList))   //获得sensor初始化列表


    for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
    ....
        pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); //获取各个cam驱动中Init函数入口


    ....
    }
    return 0;
}
kdGetSensorInitFuncList的实现:
  1. UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)  
  2. {  
  3.     if (NULL == ppSensorList) {  
  4.         PK_ERR(”[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n”);  
  5.         return 1;  
  6.     }  
  7.     *ppSensorList = &kdSensorList[0];  //获取sensorlist数组首地址  
  8.     return 0;  
  9. }               /* kdGetSensorInitFuncList() */  
UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{
    if (NULL == ppSensorList) {
        PK_ERR("[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n");
        return 1;
    }
    *ppSensorList = &kdSensorList[0];  //获取sensorlist数组首地址
    return 0;
}               /* kdGetSensorInitFuncList() */
kdSensorList定义如下:
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.h
  1. ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =  
  2. {  
  3.     ….  
  4.   
  5.   
  6. #if defined(SUB_GC2355_MIPI_RAW)  
  7.     {GC2355S_SENSOR_ID, SENSOR_DRVNAME_GC2355S_MIPI_RAW,Sub_GC2355_MIPI_RAW_SensorInit},  
  8. #endif  
  9.   
  10.   
  11.     ….  
  12. }  
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
{
    ....






if defined(SUB_GC2355_MIPI_RAW)

{GC2355S_SENSOR_ID, SENSOR_DRVNAME_GC2355S_MIPI_RAW,Sub_GC2355_MIPI_RAW_SensorInit},

endif

....

}获取列表之后紧接着调用各自的Init函数,这里以GC2355为例

  1. UINT32 GC2235MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT pfFunc)  
  2. {  
  3.     / To Do : Check Sensor status here /  
  4.     if (pfFunc!=NULL)  
  5.         *pfFunc=&sensor_func;  
  6.     return ERROR_NONE;  
  7. }   /  GC2235MIPI_RAW_SensorInit   */  
UINT32 GC2235MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) 
{
/* To Do : Check Sensor status here */
if (pfFunc!=NULL)
*pfFunc=&sensor_func;
return ERROR_NONE;
} /* GC2235MIPI_RAW_SensorInit */

     丛中可以看出,gc2355的Init函数地址传给了pfFunc,也就是时候,后面在通用驱动可以直接凭借

pfun指针调用sensorlist中的驱动
4.2 再来看ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);

当KDIMGSENSORIOC_T_CHECK_IS_ALIVE被传下时,会调用kernel层的adopt_CAMERA_HW_CheckIsAlive

Control接口

  1. static inline int adopt_CAMERA_HW_CheckIsAlive(void)  
  2. {  
  3.     ….  
  4.     /* power on sensor */  
  5.     kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *) g_invokeSocketIdx, g_invokeSensorNameStr,  
  6.             true, CAMERA_HW_DRVNAME1);  
  7.   
  8.   
  9.     ….  
  10.       
  11.     if (g_pSensorFunc) {  
  12.         for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {  
  13.             if (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) {  
  14.                 err =  
  15.                     g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],  
  16.                                     SENSOR_FEATURE_CHECK_SENSOR_ID,  
  17.                                     (MUINT8 *) &sensorID,  
  18.                                     &retLen);  
  19.                 if (sensorID == 0) {    /* not implement this feature ID */  
  20.                     PK_DBG  
  21.                         (” Not implement!!, use old open function to check\n”);  
  22.                     err = ERROR_SENSOR_CONNECT_FAIL;  
  23.                 } else if (sensorID == 0xFFFFFFFF) {    /* fail to open the sensor */  
  24.                     PK_DBG(” No Sensor Found”);  
  25.                     err = ERROR_SENSOR_CONNECT_FAIL;  
  26.                 } else {  
  27.   
  28.   
  29.                     PK_INF(” Sensor found ID = 0x%x\n”, sensorID);  
  30.                     snprintf(mtk_ccm_name, sizeof(mtk_ccm_name),  
  31.                          ”%s CAM[%d]:%s;”, mtk_ccm_name,  
  32.                          g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);  
  33.                     psensorResolution[0] = &sensorResolution[0];  
  34.                     psensorResolution[1] = &sensorResolution[1];  
  35.                     // don’t care of the result  
  36.                     g_pSensorFunc->SensorGetResolution(psensorResolution);  
  37.                     if(g_invokeSocketIdx[i] == DUAL_CAMERA_MAIN_SENSOR)  
  38.                         curr_sensor_id = 0;  
  39.                     else if(g_invokeSocketIdx[i] == DUAL_CAMERA_SUB_SENSOR)  
  40.                         curr_sensor_id = 1;  
  41.                     /* fill the cam infos with name/width/height */  
  42.                     snprintf(g_cam_infos, sizeof(g_cam_infos),“%s CAM[%d]:%s,Width:%d, Height:%d;”,  
  43.                                 g_cam_infos, g_invokeSocketIdx[i], g_invokeSensorNameStr[i],  
  44.                                 sensorResolution[curr_sensor_id].SensorFullWidth, sensorResolution[curr_sensor_id].SensorFullHeight);  
  45.   
  46.   
  47.                     err = ERROR_NONE;  
  48.                 }  
  49.                 if (ERROR_NONE != err) {  
  50.                     PK_DBG  
  51.                         (”ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n”);  
  52.                 }  
  53.             }  
  54.         }  
  55.     } else {  
  56.         PK_DBG(”ERROR:NULL g_pSensorFunc\n”);  
  57.     }  
  58. }               /* adopt_CAMERA_HW_Open() */  
static inline int adopt_CAMERA_HW_CheckIsAlive(void)
{
    ....
    /* power on sensor */
    kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *) g_invokeSocketIdx, g_invokeSensorNameStr,
            true, CAMERA_HW_DRVNAME1);


    ....

    if (g_pSensorFunc) {
        for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
            if (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) {
                err =
                    g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],
                                    SENSOR_FEATURE_CHECK_SENSOR_ID,
                                    (MUINT8 *) &sensorID,
                                    &retLen);
                if (sensorID == 0) {    /* not implement this feature ID */
                    PK_DBG
                        (" Not implement!!, use old open function to check\n");
                    err = ERROR_SENSOR_CONNECT_FAIL;
                } else if (sensorID == 0xFFFFFFFF) {    /* fail to open the sensor */
                    PK_DBG(" No Sensor Found");
                    err = ERROR_SENSOR_CONNECT_FAIL;
                } else {


                    PK_INF(" Sensor found ID = 0x%x\n", sensorID);
                    snprintf(mtk_ccm_name, sizeof(mtk_ccm_name),
                         "%s CAM[%d]:%s;", mtk_ccm_name,
                         g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);
                    psensorResolution[0] = &sensorResolution[0];
                    psensorResolution[1] = &sensorResolution[1];
                    // don't care of the result
                    g_pSensorFunc->SensorGetResolution(psensorResolution);
                    if(g_invokeSocketIdx[i] == DUAL_CAMERA_MAIN_SENSOR)
                        curr_sensor_id = 0;
                    else if(g_invokeSocketIdx[i] == DUAL_CAMERA_SUB_SENSOR)
                        curr_sensor_id = 1;
                    /* fill the cam infos with name/width/height */
                    snprintf(g_cam_infos, sizeof(g_cam_infos),"%s CAM[%d]:%s,Width:%d, Height:%d;",
                                g_cam_infos, g_invokeSocketIdx[i], g_invokeSensorNameStr[i],
                                sensorResolution[curr_sensor_id].SensorFullWidth, sensorResolution[curr_sensor_id].SensorFullHeight);


                    err = ERROR_NONE;
                }
                if (ERROR_NONE != err) {
                    PK_DBG
                        ("ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n");
                }
            }
        }
    } else {
        PK_DBG("ERROR:NULL g_pSensorFunc\n");
    }
}               /* adopt_CAMERA_HW_Open() */
这个函数非常重要,它主要进行了以下几个动作,
1)通过kdModulePowerOn给Sensor上电
2)通过SensorFeatureControl读取SensorID 
先看kdModulePowerOn的实现
  1. int  
  2. kdModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM socketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS],  
  3.         char sensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][32], BOOL On, char *mode_name)  
  4. {  
  5.     MINT32 ret = ERROR_NONE;  
  6.     u32 i = 0;  
  7.   
  8.   
  9.     for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {  
  10.         if (g_bEnableDriver[i]) {  
  11.             /* PK_XLOG_INFO(“[%s][%d][%d][%s][%s]\r\n”,__FUNCTION__,g_bEnableDriver[i],socketIdx[i],sensorNameStr[i],mode_name); */  
  12. #ifndef CONFIG_FPGA_EARLY_PORTING  
  13.             ret = _kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name);  
  14. #endif  
  15.             if (ERROR_NONE != ret) {  
  16.                 PK_ERR(”[%s]”, __func__);  
  17.                 return ret;  
  18.             }  
  19.         }  
  20.     }  
  21.     return ERROR_NONE;  
  22. }  
int
kdModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM socketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS],
        char sensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][32], BOOL On, char *mode_name)
{
    MINT32 ret = ERROR_NONE;
    u32 i = 0;


    for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
        if (g_bEnableDriver[i]) {
            /* PK_XLOG_INFO("[%s][%d][%d][%s][%s]\r\n",__FUNCTION__,g_bEnableDriver[i],socketIdx[i],sensorNameStr[i],mode_name); */




ifndef CONFIG_FPGA_EARLY_PORTING

        ret = _kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name);

endif

        if (ERROR_NONE != ret) {
            PK_ERR("[%s]", __func__);
            return ret;
        }
    }
}
return ERROR_NONE;

}在kdModulePowerOn中又调用_kdCISModulePowerOn

  1. int _kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On,  
  2.             char *mode_name)  
  3. {  
  4.     ….  
  5.   
  6.   
  7.     ret = kdCISModulePowerOn(SensorIdx, currSensorName, On, mode_name);  
  8.     ….  
  9.     return ret;  
  10. }  
int _kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On, 
char *mode_name)
{
….

ret = kdCISModulePowerOn(SensorIdx, currSensorName, On, mode_name);
....
return ret;

}在kdCISModulePowerOn又调用kdCISModulePowerOn函数
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/camera_hw/kd_camera_hw.c
//改函数为上下电函数,通过传入BOOL值来判断上/下电

  1. int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On,  
  2.                char *mode_name)  
  3. {  
  4.   
  5.   
  6.     u32 pinSetIdx = 0;  /* default main sensor */  
  7.   
  8.   
  9. #define IDX_PS_CMRST 0  
  10. #define IDX_PS_CMPDN 4  
  11. #define IDX_PS_MODE 1  
  12. #define IDX_PS_ON   2  
  13. #define IDX_PS_OFF  3  
  14. #define VOL_2800 2800000  
  15. #define VOL_1800 1800000  
  16. #define VOL_1500 1500000  
  17. #define VOL_1200 1200000  
  18. #define VOL_1000 1000000  
  19.   
  20.   
  21.   
  22.   
  23.     u32 pinSet[3][8] = {  
  24.         /* for main sensor */  
  25.         {       /* The reset pin of main sensor uses GPIO10 of mt6306, please call mt6306 API to set */  
  26.          CAMERA_CMRST_PIN,  
  27.          CAMERA_CMRST_PIN_M_GPIO,   /* mode */  
  28.          GPIO_OUT_ONE,  /* ON state */  
  29.          GPIO_OUT_ZERO, /* OFF state */  
  30.          CAMERA_CMPDN_PIN,  
  31.          CAMERA_CMPDN_PIN_M_GPIO,  
  32.          GPIO_OUT_ONE,  
  33.          GPIO_OUT_ZERO,  
  34.          },  
  35.         /* for sub sensor */  
  36.         {  
  37.          CAMERA_CMRST1_PIN,  
  38.          CAMERA_CMRST1_PIN_M_GPIO,  
  39.          GPIO_OUT_ONE,  
  40.          GPIO_OUT_ZERO,  
  41.          CAMERA_CMPDN1_PIN,  
  42.          CAMERA_CMPDN1_PIN_M_GPIO,  
  43.          GPIO_OUT_ONE,  
  44.          GPIO_OUT_ZERO,  
  45.          },  
  46.         /* for main_2 sensor */  
  47.         {  
  48.          GPIO_CAMERA_INVALID,  
  49.          GPIO_CAMERA_INVALID,   /* mode */  
  50.          GPIO_OUT_ONE,  /* ON state */  
  51.          GPIO_OUT_ZERO, /* OFF state */  
  52.          GPIO_CAMERA_INVALID,  
  53.          GPIO_CAMERA_INVALID,  
  54.          GPIO_OUT_ONE,  
  55.          GPIO_OUT_ZERO,  
  56.          }  
  57.     };  
  58.   
  59.   
  60.     if (DUAL_CAMERA_MAIN_SENSOR == SensorIdx)  
  61.         pinSetIdx = 0;  
  62.     else if (DUAL_CAMERA_SUB_SENSOR == SensorIdx)  
  63.         pinSetIdx = 1;  
  64.     else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx)  
  65.         pinSetIdx = 2;  
  66.   
  67.   
  68.     /* power ON */  
  69.     if (On) {  
  70.   
  71.   
  72. #if 0  
  73.         ISP_MCLK1_EN(1);  
  74.         ISP_MCLK2_EN(1);  
  75.         ISP_MCLK3_EN(1);  
  76. #else  
  77.         if (pinSetIdx == 0)  
  78.             ISP_MCLK1_EN(1);  
  79.         else if (pinSetIdx == 1)  
  80.             ISP_MCLK2_EN(1);  
  81. #endif  
  82.   
  83.   
  84.     printk(”fangkuiccm %d ,currSensorName = %s pinSetIdx = %d ”,LINE,currSensorName,pinSetIdx );  
  85.       
  86.     //通过DriverName来区分SensorIC  
  87.     if (currSensorName && (0 == strcmp(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {  
  88.               
  89.             /* First Power Pin low and Reset Pin Low */  
  90.             if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])  
  91.                 mtkcam_gpio_set(pinSetIdx, CAMPDN,  
  92.                         pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);  
  93.   
  94.   
  95.             if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST])  
  96.                 mtkcam_gpio_set(pinSetIdx, CAMRST,  
  97.                         pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);  
  98.   
  99.   
  100.             mdelay(50);  
  101.   
  102.   
  103.             /* VCAM_A */  
  104.             if (TRUE != _hwPowerOn(VCAMA, VOL_2800)) {  
  105.                 PK_DBG  
  106.                     (”[CAMERA SENSOR] Fail to enable analog power (VCAM_A),power id = %d\n”,  
  107.                      VCAMA);  
  108.                 goto _kdCISModulePowerOn_exit;  
  109.             }  
  110.   
  111.   
  112.             mdelay(10);  
  113.   
  114.   
  115.             / VCAM_IO /  
  116.             if (TRUE != hwPowerOn(VCAMIO, VOL_1800)) {  
  117.                 PK_DBG  
  118.                     (”[CAMERA SENSOR] Fail to enable IO power (VCAM_IO),power id = %d\n”,  
  119.                      VCAMIO);  
  120.                 goto _kdCISModulePowerOn_exit;  
  121.             }  
  122.   
  123.   
  124.             mdelay(10);  
  125.   
  126.   
  127.             if (TRUE != hwPowerOn(VCAMD, VOL_1500)) {  
  128.                 PK_DBG  
  129.                     (”[CAMERA SENSOR] Fail to enable digital power (VCAM_D),power id = %d\n”,  
  130.                      VCAMD);  
  131.                 goto _kdCISModulePowerOn_exit;  
  132.             }  
  133.   
  134.   
  135.             mdelay(10);  
  136.   
  137.   
  138.             / AF_VCC /  
  139.             if (TRUE != hwPowerOn(VCAMAF, VOL_2800)) {  
  140.                 PK_DBG  
  141.                     (”[CAMERA SENSOR] Fail to enable analog power (VCAM_AF),power id = %d\n”,  
  142.                      VCAMAF);  
  143.                 goto _kdCISModulePowerOn_exit;  
  144.             }  
  145.   
  146.   
  147.   
  148.   
  149.             mdelay(50);  
  150.   
  151.   
  152.             if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) {  
  153.                 mtkcam_gpio_set(pinSetIdx, CAMRST,  
  154.                         pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);  
  155.                 mdelay(5);  
  156.                 mtkcam_gpio_set(pinSetIdx, CAMRST,  
  157.                         pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON]);  
  158.             }  
  159.             mdelay(5);  
  160.             / enable active sensor /  
  161.             if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {  
  162.                 mtkcam_gpio_set(pinSetIdx, CAMPDN,  
  163.                         pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]);  
  164.                 mdelay(5);  
  165.                 mtkcam_gpio_set(pinSetIdx, CAMPDN,  
  166.                         pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);  
  167.             }  
  168.   
  169.   
  170.             mdelay(5);  
  171.         }   
  172.     }else//poweroff  
  173.      if (currSensorName   //上完电就要下电不然会造成漏电,最终会影响手机功耗  
  174.                && (0 == strcmp(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {  
  175. #if 0  
  176.             mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_MODE_00);  
  177.             mt_set_gpio_dir(GPIO_SPI_MOSI_PIN, GPIO_DIR_OUT);  
  178.             mt_set_gpio_out(GPIO_SPI_MOSI_PIN, GPIO_OUT_ONE);  
  179. #endif  
  180.             / First Power Pin low and Reset Pin Low /  
  181.             if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {  
  182.                 if (mt_set_gpio_mode  
  183.                     (pinSet[pinSetIdx][IDX_PS_CMPDN],  
  184.                      pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) {  
  185.                     PK_DBG(”[CAMERA LENS] set gpio mode failed!! (CMPDN)\n”);  
  186.                 }  
  187.                 if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) {  
  188.                     PK_DBG(”[CAMERA LENS] set gpio dir failed!! (CMPDN)\n”);  
  189.                 }  
  190.                 if (mt_set_gpio_out  
  191.                     (pinSet[pinSetIdx][IDX_PS_CMPDN],  
  192.                      pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) {  
  193.                     PK_DBG(”[CAMERA LENS] set gpio failed!! (CMPDN)\n”);  
  194.                 }  
  195.             }  
  196.     }  
  197. }  
int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On, 
char *mode_name)
{

u32 pinSetIdx = 0;  /* default main sensor */

define IDX_PS_CMRST 0

define IDX_PS_CMPDN 4

define IDX_PS_MODE 1

define IDX_PS_ON 2

define IDX_PS_OFF 3

define VOL_2800 2800000

define VOL_1800 1800000

define VOL_1500 1500000

define VOL_1200 1200000

define VOL_1000 1000000

u32 pinSet[3][8] = {
    /* for main sensor */
    {       /* The reset pin of main sensor uses GPIO10 of mt6306, please call mt6306 API to set */
     CAMERA_CMRST_PIN,
     CAMERA_CMRST_PIN_M_GPIO,   /* mode */
     GPIO_OUT_ONE,  /* ON state */
     GPIO_OUT_ZERO, /* OFF state */
     CAMERA_CMPDN_PIN,
     CAMERA_CMPDN_PIN_M_GPIO,
     GPIO_OUT_ONE,
     GPIO_OUT_ZERO,
     },
    /* for sub sensor */
    {
     CAMERA_CMRST1_PIN,
     CAMERA_CMRST1_PIN_M_GPIO,
     GPIO_OUT_ONE,
     GPIO_OUT_ZERO,
     CAMERA_CMPDN1_PIN,
     CAMERA_CMPDN1_PIN_M_GPIO,
     GPIO_OUT_ONE,
     GPIO_OUT_ZERO,
     },
    /* for main_2 sensor */
    {
     GPIO_CAMERA_INVALID,
     GPIO_CAMERA_INVALID,   /* mode */
     GPIO_OUT_ONE,  /* ON state */
     GPIO_OUT_ZERO, /* OFF state */
     GPIO_CAMERA_INVALID,
     GPIO_CAMERA_INVALID,
     GPIO_OUT_ONE,
     GPIO_OUT_ZERO,
     }
};


if (DUAL_CAMERA_MAIN_SENSOR == SensorIdx)
    pinSetIdx = 0;
else if (DUAL_CAMERA_SUB_SENSOR == SensorIdx)
    pinSetIdx = 1;
else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx)
    pinSetIdx = 2;


/* power ON */
if (On) {

if 0

    ISP_MCLK1_EN(1);
    ISP_MCLK2_EN(1);
    ISP_MCLK3_EN(1);

else

    if (pinSetIdx == 0)
        ISP_MCLK1_EN(1);
    else if (pinSetIdx == 1)
        ISP_MCLK2_EN(1);

endif

printk("fangkuiccm %d ,currSensorName = %s pinSetIdx = %d ",__LINE__,currSensorName,pinSetIdx );

//通过DriverName来区分SensorIC
if (currSensorName &amp;&amp; (0 == strcmp(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {

        /* First Power Pin low and Reset Pin Low */
        if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])
            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]);


        mdelay(50);


        /* VCAM_A */
        if (TRUE != _hwPowerOn(VCAMA, VOL_2800)) {
            PK_DBG
                ("[CAMERA SENSOR] Fail to enable analog power (VCAM_A),power id = %d\n",
                 VCAMA);
            goto _kdCISModulePowerOn_exit_;
        }


        mdelay(10);


        /* VCAM_IO */
        if (TRUE != _hwPowerOn(VCAMIO, VOL_1800)) {
            PK_DBG
                ("[CAMERA SENSOR] Fail to enable IO power (VCAM_IO),power id = %d\n",
                 VCAMIO);
            goto _kdCISModulePowerOn_exit_;
        }


        mdelay(10);


        if (TRUE != _hwPowerOn(VCAMD, VOL_1500)) {
            PK_DBG
                ("[CAMERA SENSOR] Fail to enable digital power (VCAM_D),power id = %d\n",
                 VCAMD);
            goto _kdCISModulePowerOn_exit_;
        }


        mdelay(10);


        /* AF_VCC */
        if (TRUE != _hwPowerOn(VCAMAF, VOL_2800)) {
            PK_DBG
                ("[CAMERA SENSOR] Fail to enable analog power (VCAM_AF),power id = %d\n",
                 VCAMAF);
            goto _kdCISModulePowerOn_exit_;
        }




        mdelay(50);


        if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) {
            mtkcam_gpio_set(pinSetIdx, CAMRST,
                    pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);
            mdelay(5);
            mtkcam_gpio_set(pinSetIdx, CAMRST,
                    pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON]);
        }
        mdelay(5);
        /* enable active sensor */
        if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {
            mtkcam_gpio_set(pinSetIdx, CAMPDN,
                    pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]);
            mdelay(5);
            mtkcam_gpio_set(pinSetIdx, CAMPDN,
                    pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);
        }


        mdelay(5);
    } 
}else{ //poweroff
 if (currSensorName   //上完电就要下电不然会造成漏电,最终会影响手机功耗
           &amp;&amp; (0 == strcmp(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {

if 0

        mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_MODE_00);
        mt_set_gpio_dir(GPIO_SPI_MOSI_PIN, GPIO_DIR_OUT);
        mt_set_gpio_out(GPIO_SPI_MOSI_PIN, GPIO_OUT_ONE);

endif

        /* First Power Pin low and Reset Pin Low */
        if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {
            if (mt_set_gpio_mode
                (pinSet[pinSetIdx][IDX_PS_CMPDN],
                 pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) {
                PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n");
            }
            if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) {
                PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n");
            }
            if (mt_set_gpio_out
                (pinSet[pinSetIdx][IDX_PS_CMPDN],
                 pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) {
                PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n");
            }
        }
}

}上电操作完成后,紧接着读取SensorID,通用驱动使用SensorFeatureControl来读取ID如:
 g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],
SENSOR_FEATURE_CHECK_SENSOR_ID,
(MUINT8 *) &sensorID,
&retLen);
这步操作会调用GC2355中的feature_control函数如下:
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/gc2355_mipi_raw/gc2355mipi_Sensor.c

  1. static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id,  
  2.                              UINT8 *feature_para,UINT32 *feature_para_len)  
  3. {  
  4.     ….  
  5.     LOG_INF(”feature_id = %d\n”, feature_id);  
  6.     switch (feature_id) {  
  7.         ….  
  8.         case SENSOR_FEATURE_CHECK_SENSOR_ID:  
  9.             get_imgsensor_id(feature_return_para_32);  
  10.             break;  
  11.         ….  
  12.         default:  
  13.             break;  
  14.     }  
  15.   
  16.   
  17.     return ERROR_NONE;  
  18. }      
static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, 
UINT8 *feature_para,UINT32 *feature_para_len)
{
….
LOG_INF(“feature_id = %d\n”, feature_id);
switch (feature_id) {
….
case SENSOR_FEATURE_CHECK_SENSOR_ID:
get_imgsensor_id(feature_return_para_32);
break;
….
default:
break;
}

return ERROR_NONE;

}

优化传入的cmd为SENSOR_FEATURE_CHECK_SENSOR_ID,则会调用feature_control中的

get_imgsensor_id再看get_imgsensor_id的实现

  1. static kal_uint32 get_imgsensor_id(UINT32 *sensor_id)  
  2. {  
  3.     kal_uint8 i = 0;  
  4.     kal_uint8 retry = 2;  
  5.     //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address  
  6.     while (imgsensor_info.i2c_addr_table[i] != 0xff) {  
  7.         spin_lock(&imgsensor_drv_lock);  
  8.         imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i];  
  9.         spin_unlock(&imgsensor_drv_lock);  
  10.         do {  
  11.             *sensor_id = return_sensor_id(); //return_sensor_id读取IC的ID  
  12.             if (*sensor_id == imgsensor_info.sensor_id) {  
  13.                 LOG_INF(”i2c write id: 0x%x, sensor id: 0x%x\n”, imgsensor.i2c_write_id,*sensor_id);  
  14.                 return ERROR_NONE;  
  15.             }  
  16.             LOG_INF(”Read sensor id fail, write id: 0x%x, id: 0x%x\n”, imgsensor.i2c_write_id,*sensor_id);  
  17.             retry–;  
  18.         } while(retry > 0);  
  19.         i++;  
  20.         retry = 2;  
  21.     }  
  22.     ….  
  23.     return ERROR_NONE;  
  24. }  
static kal_uint32 get_imgsensor_id(UINT32 *sensor_id)
{
    kal_uint8 i = 0;
    kal_uint8 retry = 2;
    //sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address
    while (imgsensor_info.i2c_addr_table[i] != 0xff) {
        spin_lock(&imgsensor_drv_lock);
        imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i];
        spin_unlock(&imgsensor_drv_lock);
        do {
            *sensor_id = return_sensor_id(); //return_sensor_id读取IC的ID
            if (*sensor_id == imgsensor_info.sensor_id) {
                LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id);
                return ERROR_NONE;
            }
            LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id);
            retry--;
        } while(retry > 0);
        i++;
        retry = 2;
    }
    ....
    return ERROR_NONE;
}
再看return_sensor_id的实现
  1. static kal_uint32 return_sensor_id(void)  
  2. {  
  3.     return ((read_cmos_sensor(0xf0) << 8) | read_cmos_sensor(0xf1));  
  4. }  
  5. static kal_uint16 read_cmos_sensor(kal_uint32 addr)  
  6. {  
  7.     kal_uint16 get_byte=0;  
  8.   
  9.   
  10.     char pu_send_cmd[1] = {(char)(addr & 0xFF) };  
  11.     iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, imgsensor.i2c_write_id);  
  12.   
  13.   
  14.     return get_byte;  
  15.   
  16.   
  17. }  
static kal_uint32 return_sensor_id(void)
{
    return ((read_cmos_sensor(0xf0) << 8) | read_cmos_sensor(0xf1));
}
static kal_uint16 read_cmos_sensor(kal_uint32 addr)
{
    kal_uint16 get_byte=0;


    char pu_send_cmd[1] = {(char)(addr & 0xFF) };
    iReadRegI2C(pu_send_cmd, 1, (u8*)&get_byte, 1, imgsensor.i2c_write_id);


    return get_byte;


}
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c
  1. int iReadRegI2C(u8 *a_pSendData, u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData,  
  2.         u16 i2cId)  
  3. {  
  4.     int i4RetValue = 0;  
  5.   
  6.   
  7.     if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) {  
  8.         spin_lock(&kdsensor_drv_lock);  
  9.         g_pstI2Cclient->addr = (i2cId >> 1);  
  10.         g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG);  
  11.   
  12.   
  13.         /* Remove i2c ack error log during search sensor */  
  14.         /* PK_ERR(“g_pstI2Cclient->ext_flag: %d”, g_IsSearchSensor); */  
  15.         if (g_IsSearchSensor == 1) {  
  16.             g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG;  
  17.         } else {  
  18.             g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_A_FILTER_MSG);  
  19.         }  
  20.   
  21.   
  22.         spin_unlock(&kdsensor_drv_lock);  
  23.         /*  */  
  24.         i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData);  
  25.         if (i4RetValue != a_sizeSendData) {  
  26.             PK_ERR(”[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n”, a_pSendData[0]);  
  27.             return -1;  
  28.         }  
  29.   
  30.   
  31.         i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData);  
  32.         if (i4RetValue != a_sizeRecvData) {  
  33.             PK_ERR(”[CAMERA SENSOR] I2C read failed!!\n”);  
  34.             return -1;  
  35.         }  
  36.     } else {  
  37.         spin_lock(&kdsensor_drv_lock);  
  38.         g_pstI2Cclient2->addr = (i2cId >> 1);  
  39.   
  40.   
  41.         /* Remove i2c ack error log during search sensor */  
  42.         /* PK_ERR(“g_pstI2Cclient2->ext_flag: %d”, g_IsSearchSensor); */  
  43.         if (g_IsSearchSensor == 1) {  
  44.             g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG;  
  45.         } else {  
  46.             g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) & (~I2C_A_FILTER_MSG);  
  47.         }  
  48.         spin_unlock(&kdsensor_drv_lock);  
  49.         i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData);  
  50.         if (i4RetValue != a_sizeSendData) {  
  51.             PK_ERR(”[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n”, a_pSendData[0]);  
  52.             return -1;  
  53.         }  
  54.   
  55.   
  56.         i4RetValue = i2c_master_recv(g_pstI2Cclient2, (char *)a_pRecvData, a_sizeRecvData);  
  57.         if (i4RetValue != a_sizeRecvData) {  
  58.             PK_ERR(”[CAMERA SENSOR] I2C read failed!!\n”);  
  59.             return -1;  
  60.         }  
  61.     }  
  62.     return 0;  
  63. }  
int iReadRegI2C(u8 *a_pSendData, u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData,
        u16 i2cId)
{
    int i4RetValue = 0;


    if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) {
        spin_lock(&kdsensor_drv_lock);
        g_pstI2Cclient->addr = (i2cId >> 1);
        g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG);


        /* Remove i2c ack error log during search sensor */
        /* PK_ERR("g_pstI2Cclient->ext_flag: %d", g_IsSearchSensor); */
        if (g_IsSearchSensor == 1) {
            g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG;
        } else {
            g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_A_FILTER_MSG);
        }


        spin_unlock(&kdsensor_drv_lock);
        /*  */
        i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData);
        if (i4RetValue != a_sizeSendData) {
            PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]);
            return -1;
        }


        i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData);
        if (i4RetValue != a_sizeRecvData) {
            PK_ERR("[CAMERA SENSOR] I2C read failed!!\n");
            return -1;
        }
    } else {
        spin_lock(&kdsensor_drv_lock);
        g_pstI2Cclient2->addr = (i2cId >> 1);


        /* Remove i2c ack error log during search sensor */
        /* PK_ERR("g_pstI2Cclient2->ext_flag: %d", g_IsSearchSensor); */
        if (g_IsSearchSensor == 1) {
            g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG;
        } else {
            g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) & (~I2C_A_FILTER_MSG);
        }
        spin_unlock(&kdsensor_drv_lock);
        i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData);
        if (i4RetValue != a_sizeSendData) {
            PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]);
            return -1;
        }


        i4RetValue = i2c_master_recv(g_pstI2Cclient2, (char *)a_pRecvData, a_sizeRecvData);
        if (i4RetValue != a_sizeRecvData) {
            PK_ERR("[CAMERA SENSOR] I2C read failed!!\n");
            return -1;
        }
    }
    return 0;
}

      这一步完成I2c的读取,也就是说如果I2c配置正确,并且上电正确,到这一步就可以正确的读取ID,

整个camera也就基本就调通了。

三、总结

     通过上述分析,我们可以看出,camera驱动先是注册平台驱动,再注册I2c驱动,然后又为前后摄

注册字符设备,封装底层方法,上层访问底层驱动时候显示使用setdriver将具体IC的驱动入口获取,

然后使用checkisalive对sensorlist中的IC进行上电,上电完成就读取设备ID,到此为止,上层应用与

底层驱动挂接完成,紧接着就是预览和拍照,不过这都是具体IC驱动的实现了。












  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值