一、MTK6580 平台 Camera 驱动整体框架
2016-08-17 10:42
801 查看
原文:http://www.codexiu.cn/android/blog/33878/
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后面章节会继续补充。
========================HAL 层部分初始调用========================
文件:vendor/mediatek/proprietary/hardware/mtkcam/common/module_hal/devicemgr/CamDeviceManagerBase.cpp
文件:vendor/mediatek/proprietary/custom/mt6580/hal/imgsensor_src/sensorlist.cpp
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
则挂载启动。上面注册了两个platform 驱动g_stCAMERA_HW_Driver,g_stCAMERA_HW_Driver2,
如果匹配成功会调用各自的probe函数CAMERA_HW_probe,CAMERA_HW_probe2
2. 平台probe 函数的实现
主摄probe,CAMERA_HW_probe的实现如下:
CAMERA_HW_i2c_driver2,main sensor 的CAMERA_HW_i2c_driver定义如下:
文件:kernel-3.18/arch/arm/boot/dts/cust_i2c.dtsi
从上可以看出main/sub sensor在各自的平台probe中,注册了i2c_driver,当各自的i2c_driver和设备
匹配(如何匹配本章不作分析)成功后,会调用各自的i2c_probe函数。main sensor 的probe函数
CAMERA_HW_i2c_probe:
底层的ioctl即可,至于sensor的区分可以借助idx,后面会讲到
=================== 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接口
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.h
指针调用sensorlist中的驱动
4.2 再来看ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
当KDIMGSENSORIOC_T_CHECK_IS_ALIVE被传下时,会调用kernel层的adopt_CAMERA_HW_Feature
Control接口
1)通过kdModulePowerOn给Sensor上电
2)通过SensorFeatureControl读取SensorID
先看kdModulePowerOn的实现
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/camera_hw/kd_camera_hw.c
//改函数为上下电函数,通过传入BOOL值来判断上/下电
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
优化传入的cmd为SENSOR_FEATURE_CHECK_SENSOR_ID,则会调用feature_control中的
get_imgsensor_id再看get_imgsensor_id的实现
这一步完成I2c的读取,也就是说如果I2c配置正确,并且上电正确,到这一步就可以正确的读取ID,整
个camera也就基本就调通了。
通过上述分析,我们可以看出,camera驱动先是注册平台驱动,再注册I2c驱动,然后又为前后摄注册
字符设备,封装底层方法,上层访问底层驱动时候显示使用setdriver将具体IC的驱动入口获取,然后使用
checkisalive对sensorlist中的IC进行上电,上电完成就读取设备ID,到此为止,上层应用与底层驱动挂接
完成,紧接着就是预览和拍照,不过这都是具体IC驱动的实现了。
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
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">int32_t CamDeviceManagerBase:: getNumberOfDevices() { ... mi4DeviceNum = enumDeviceLocked(); ... }</code>文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/devicemgr/CamDeviceManagerImp.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">int32_t CamDeviceManagerImp:: enumDeviceLocked() { ... <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//------------------------------------------------------------------------------</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if '1'==MTKCAM_HAVE_SENSOR_HAL</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//</span> IHalSensorList*<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> pHalSensorList = IHalSensorList::get(); size_t <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> sensorNum = pHalSensorList->searchSensors(); <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> ... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> i4DeviceNum; }</code>文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MUINT HalSensorList:: searchSensors() { Mutex::Autolock _l(mEnumSensorMutex); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//</span> MY_LOGD(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"searchSensors"</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> enumerateSensor_Locked(); }</code>文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.enumList.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MUINT HalSensorList:: enumerateSensor_Locked() { .... MUINT halSensorDev = SENSOR_DEV_NONE; NSFeature::SensorInfoBase* pSensorInfo ; SensorDrv *<span class="hljs-k 4000 eyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> pSensorDrv = SensorDrv::get(); SeninfDrv *<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> pSeninfDrv = SeninfDrv::createInstance(); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> iSensorsList = pSensorDrv->impSearchSensor(NULL); .... }</code>文件:vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/imgsensor_drv.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MINT32 ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf) { .... GetSensorInitFuncList(&m_pstSensorInitFunc); LOG_MSG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"SENSOR search start \n"</span>); <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">sprintf</span>(cBuf,<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"/dev/%s"</span>,CAMERA_HW_DEVNAME); m_fdSensor = ::open(cBuf, O_RDWR); ...... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) { .... err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] ); ... err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE); ...... }</code>GetSensorInitFuncList的实现
文件:vendor/mediatek/proprietary/custom/mt6580/hal/imgsensor_src/sensorlist.cpp
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (NULL == ppSensorList) { ALOGE(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"ERROR: NULL pSensorList\n"</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> MHAL_UNKNOWN_ERROR; } *ppSensorList = &SensorList[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> MHAL_NO_ERROR; } </code>Sensor 列表的定义如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] = { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//xc add camera start</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if defined(GC2365MIPI_RAW)</span> RAW_INFO(GC2365MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2365MIPI_RAW, NULL), <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if defined(GC2355_MIPI_RAW_BAIKANG_M8112)</span> RAW_INFO(GC2355_SENSOR_ID, SENSOR_DRVNAME_GC2355_MIPI_RAW,NULL), <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> .... }</code>获取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
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> __init CAMERA_HW_i2C_init(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>) { .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (platform_driver_register(&g_stCAMERA_HW_Driver)) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册主摄platform 驱动</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (platform_driver_register(&g_stCAMERA_HW_Driver2)) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册副摄platform 驱动</span> .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; }</code>主摄平台驱动的定义:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW_of_ids[] = { {.compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw"</span>,}, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//主摄匹配规则</span> {} }; <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_driver g_stCAMERA_HW_Driver = { .probe = CAMERA_HW_probe, .remove = CAMERA_HW_remove, .suspend = CAMERA_HW_suspend, .resume = CAMERA_HW_resume, .driver = { .name = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"image_sensor"</span>, .owner = THIS_MODULE, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> .of_match_table = CAMERA_HW_of_ids, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> } };</code>副摄平台驱动的定义:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW2_of_ids[] = { {.compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw2"</span>,},<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//副摄匹配规则</span> {} }; <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_driver g_stCAMERA_HW_Driver2 = { .probe = CAMERA_HW_probe2, .remove = CAMERA_HW_remove2, .suspend = CAMERA_HW_suspend2, .resume = CAMERA_HW_resume2, .driver = { .name = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"image_sensor_bus2"</span>, .owner = THIS_MODULE, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> .of_match_table = CAMERA_HW2_of_ids, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> } };</code>主副摄cam在dts中定义设备信息:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">kd_camera_hw1:kd_camera_hw1@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">15008000</span> { compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//这里必须和主摄一致</span> reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x15008000</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x1000</span>>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* SENINF_ADDR */</span> 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@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(1 193a0 74, 129, 255);">15008000</span> { compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_hw2"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//这里必须和副摄一致</span> reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x15008000</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x1000</span>>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* SENINF_ADDR */</span> };</code>当内核启动后,会解析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的实现如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_probe(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_device *pdev) { <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if !defined(CONFIG_MTK_LEGACY)</span> mtkcam_gpio_init(pdev); mtkcam_pin_mux_init(pdev); <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> i2c_add_driver(&CAMERA_HW_i2c_driver); }</code>副摄probe,CAMERA_HW_probe的实现如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_probe2(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> platform_device *pdev) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> i2c_add_driver(&CAMERA_HW_i2c_driver2); }</code>从上可以看出在main/sub 的平台probe中分别注册了各自的i2c驱动CAMERA_HW_i2c_driver,
CAMERA_HW_i2c_driver2,main sensor 的CAMERA_HW_i2c_driver定义如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW_i2c_of_ids[] = { { .compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_main"</span>, }, {} }; <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_driver CAMERA_HW_i2c_driver = { .probe = CAMERA_HW_i2c_probe, .remove = CAMERA_HW_i2c_remove, .driver = { .name = CAMERA_HW_DRVNAME1, .owner = THIS_MODULE, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> .of_match_table = CAMERA_HW_i2c_of_ids, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> }, .id_table = CAMERA_HW_i2c_id, }; sub sensor 的CAMERA_HW_i2c_driver定义如下: <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> of_device_id CAMERA_HW2_i2c_driver_of_ids[] = { { .compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_sub"</span>, }, {} }; <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_driver CAMERA_HW_i2c_driver2 = { .probe = CAMERA_HW_i2c_probe2, .remove = CAMERA_HW_i2c_remove2, .driver = { .name = CAMERA_HW_DRVNAME2, .owner = THIS_MODULE, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_OF</span> .of_match_table = CAMERA_HW2_i2c_driver_of_ids, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> }, .id_table = CAMERA_HW_i2c_id2, };</code>对应main/sub camera i2c 设备dts定义如下
文件:kernel-3.18/arch/arm/boot/dts/cust_i2c.dtsi
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">&i2c0 { camera_main@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span> { compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_main"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//和 CAMERA_HW_i2c_driver定义的一致</span> reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x10</span>>; }; camera_main_af@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>c { compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_main_af"</span>; reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x0c</span>>; }; camera_sub@<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">3</span>c { compatible = <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"mediatek,camera_sub"</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//和CAMERA_HW_i2c_driver2定义的一致</span> reg = <<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0x3c</span>>; }; };</code>3. I2c probe的实现
从上可以看出main/sub sensor在各自的平台probe中,注册了i2c_driver,当各自的i2c_driver和设备
匹配(如何匹配本章不作分析)成功后,会调用各自的i2c_probe函数。main sensor 的probe函数
CAMERA_HW_i2c_probe:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_i2c_probe(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_client *client, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_device_id *id) { ..... <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Register char driver */</span> i4RetValue = RegisterCAMERA_HWCharDrv(); ..... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; }</code>sub sensor 的probe函数CAMERA_HW_i2c_probe2:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> CAMERA_HW_i2c_probe2(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_client *client, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> i2c_device_id *id) { ..... <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Register char driver */</span> i4RetValue = RegisterCAMERA_HWCharDrv2(); ..... }</code>从上可以看出main/sub 在各自的i2cprobe中,通过该调用RegisterCAMERA_HWCharDrv,RegisterCAMERA_HWCharDrv2注册了字符设备。各自注册cdev函数实现如下:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">inline</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> RegisterCAMERA_HWCharDrv(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//main sensor 注册cdev</span> { ..... <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Attatch file operation. */</span> cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//初始化字符设备</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Add to system */</span> cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册到内核</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录 /sys/class/sensordrv/</span> sensor_class = class_create(THIS_MODULE, <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"sensordrv"</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录/sys/class/sensordrv/kd_camera_hw </span> sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1); .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">inline</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> RegisterCAMERA_HWCharDrv2(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>)<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//sub sensor 注册cdev</span> { .... <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Attatch file operation. */</span> cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0);<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//初始化字符设备 </span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Add to system */</span> cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>));<span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//注册到内核</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录 /sys/class/sensordrv2/</span> sensor2_class = class_create(THIS_MODULE, <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"sensordrv2"</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//创建目录/sys/class/sensordrv2/kd_camera_hw_bus2</span> sensor_device2 = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2); .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; } main/sub 创建各自的字符设备过程中绑定各自的fops,g_stCAMERA_HW_fops和g_stCAMERA_HW_fops0 他们各自定义如下 <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> file_operations g_stCAMERA_HW_fops = { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//main sensor fops</span> .owner = THIS_MODULE, .open = CAMERA_HW_Open, .release = CAMERA_HW_Release, .unlocked_ioctl = CAMERA_HW_Ioctl, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_COMPAT</span> .compat_ioctl = CAMERA_HW_Ioctl_Compat, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> }; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">const</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> file_operations g_stCAMERA_HW_fops0 = { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//sub sensor fops</span> .owner = THIS_MODULE, .open = CAMERA_HW_Open2, .release = CAMERA_HW_Release2, .unlocked_ioctl = CAMERA_HW_Ioctl, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifdef CONFIG_COMPAT</span> .compat_ioctl = CAMERA_HW_Ioctl_Compat, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> };</code>从上可以看出各自的fops指定了相同的Iioctl函数,意味着上层操作main/sub sensor 只需要对应一个
底层的ioctl即可,至于sensor的区分可以借助idx,后面会讲到
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/******************************************************************************* * CAMERA_HW_Ioctl ********************************************************************************/</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">long</span> CAMERA_HW_Ioctl(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">struct</span> file *a_pstFile, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> a_u4Command, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">long</span> a_u4Param) { ... pIdx = (u32 *) pBuff; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">switch</span> (a_u4Command) { ... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> KDIMGSENSORIOC_X_SET_DRIVER: i4RetValue = kdSetDriver((<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> *)pBuff); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> KDIMGSENSORIOC_X_FEATURECONCTROL: i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> KDIMGSENSORIOC_T_CHECK_IS_ALIVE: i4RetValue = adopt_CAMERA_HW_CheckIsAlive(); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>; .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">default</span>: PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"No such command\n"</span>); i4RetValue = -EPERM; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>; } ..... }</code>这里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接口
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> kdSetDriver(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">unsigned</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> *pDrvIndex) { ... kdGetSensorInitFuncList(&pSensorList)) <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//获得sensor初始化列表</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { .... pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//获取各个cam驱动中Init函数入口</span> .... } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; }</code>kdGetSensorInitFuncList的实现:
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (NULL == ppSensorList) { PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n"</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; } *ppSensorList = &kdSensorList[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//获取sensorlist数组首地址</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; } <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* kdGetSensorInitFuncList() */</span></code>kdSensorList定义如下:
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.h
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>] = { .... <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if defined(SUB_GC2355_MIPI_RAW)</span> {GC2355S_SENSOR_ID, SENSOR_DRVNAME_GC2355S_MIPI_RAW,Sub_GC2355_MIPI_RAW_SensorInit}, <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> .... }</code>获取列表之后紧接着调用各自的Init函数,这里以GC2355为例
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);">UINT32 GC2235MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc) { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* To Do : Check Sensor status here */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (pfFunc!=NULL) *pfFunc=&sensor_func; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE; } <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* GC2235MIPI_RAW_SensorInit */</span></code>丛中可以看出,gc2355的Init函数地址传给了pfFunc,也就是时候,后面在通用驱动可以直接凭借pfun
指针调用sensorlist中的驱动
4.2 再来看ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
当KDIMGSENSORIOC_T_CHECK_IS_ALIVE被传下时,会调用kernel层的adopt_CAMERA_HW_Feature
Control接口
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">inline</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> adopt_CAMERA_HW_CheckIsAlive(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>) { .... <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* power on sensor */</span> kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *) g_invokeSocketIdx, g_invokeSensorNameStr, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">true</span>, CAMERA_HW_DRVNAME1); .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_pSensorFunc) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) { err = g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i], SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *) &sensorID, &retLen); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (sensorID == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>) { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* not implement this feature ID */</span> PK_DBG (<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">" Not implement!!, use old open function to check\n"</span>); err = ERROR_SENSOR_CONNECT_FAIL; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (sensorID == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xFFFFFFFF</span>) { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* fail to open the sensor */</span> PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">" No Sensor Found"</span>); err = ERROR_SENSOR_CONNECT_FAIL; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> { PK_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">" Sensor found ID = 0x%x\n"</span>, sensorID); <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">snprintf</span>(mtk_ccm_name, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">sizeof</span>(mtk_ccm_name), <span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"%s CAM[%d]:%s;"</span>, mtk_ccm_name, g_invokeSocketIdx[i], g_invokeSensorNameStr[i]); psensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>] = &sensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]; psensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>] = &sensorResolution[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>]; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">// don't care of the result</span> g_pSensorFunc->SensorGetResolution(psensorResolution); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span>(g_invokeSocketIdx[i] == DUAL_CAMERA_MAIN_SENSOR) curr_sensor_id = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span>(g_invokeSocketIdx[i] == DUAL_CAMERA_SUB_SENSOR) curr_sensor_id = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* fill the cam infos with name/width/height */</span> <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">snprintf</span>(g_cam_infos, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">sizeof</span>(g_cam_infos),<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"%s CAM[%d]:%s,Width:%d, Height:%d;"</span>, g_cam_infos, g_invokeSocketIdx[i], g_invokeSensorNameStr[i], sensorResolution[curr_sensor_id].SensorFullWidth, sensorResolution[curr_sensor_id].SensorFullHeight); err = ERROR_NONE; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (ERROR_NONE != err) { PK_DBG (<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n"</span>); } } } } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> { PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"ERROR:NULL g_pSensorFunc\n"</span>); } } <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* adopt_CAMERA_HW_Open() */</span></code>这个函数非常重要,它主要进行了以下几个动作,
1)通过kdModulePowerOn给Sensor上电
2)通过SensorFeatureControl读取SensorID
先看kdModulePowerOn的实现
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> kdModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM socketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS], <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> sensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">32</span>], BOOL On, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *mode_name) { MINT32 ret = ERROR_NONE; u32 i = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">for</span> (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_bEnableDriver[i]) { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* PK_XLOG_INFO("[%s][%d][%d][%s][%s]\r\n",__FUNCTION__,g_bEnableDriver[i],socketIdx[i],sensorNameStr[i],mode_name); */</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#ifndef CONFIG_FPGA_EARLY_PORTING</span> ret = _kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name); <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (ERROR_NONE != ret) { PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[%s]"</span>, __func__); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ret; } } } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE; }</code>在kdModulePowerOn中又调用_kdCISModulePowerOn
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> _kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *currSensorName, BOOL On, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *mode_name) { .... ret = kdCISModulePowerOn(SensorIdx, currSensorName, On, mode_name); .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ret; }</code>在_kdCISModulePowerOn又调用kdCISModulePowerOn函数
文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/camera_hw/kd_camera_hw.c
//改函数为上下电函数,通过传入BOOL值来判断上/下电
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *currSensorName, BOOL On, <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *mode_name) { u32 pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* default main sensor */</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_CMRST 0</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_CMPDN 4</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_MODE 1</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_ON 2</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define IDX_PS_OFF 3</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_2800 2800000</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1800 1800000</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1500 1500000</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1200 1200000</span> <span class="hljs-preprocessor" style="border-radius: 0px !important;">#define VOL_1000 1000000</span> u32 pinSet[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">3</span>][<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">8</span>] = { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* for main sensor */</span> { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* The reset pin of main sensor uses GPIO10 of mt6306, please call mt6306 API to set */</span> CAMERA_CMRST_PIN, CAMERA_CMRST_PIN_M_GPIO, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* mode */</span> GPIO_OUT_ONE, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* ON state */</span> GPIO_OUT_ZERO, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* OFF state */</span> CAMERA_CMPDN_PIN, CAMERA_CMPDN_PIN_M_GPIO, GPIO_OUT_ONE, GPIO_OUT_ZERO, }, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* for sub sensor */</span> { 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, }, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* for main_2 sensor */</span> { GPIO_CAMERA_INVALID, GPIO_CAMERA_INVALID, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* mode */</span> GPIO_OUT_ONE, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* ON state */</span> GPIO_OUT_ZERO, <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* OFF state */</span> GPIO_CAMERA_INVALID, GPIO_CAMERA_INVALID, GPIO_OUT_ONE, GPIO_OUT_ZERO, } }; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_MAIN_SENSOR == SensorIdx) pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_SUB_SENSOR == SensorIdx) pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx) pinSetIdx = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">2</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* power ON */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (On) { <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if 0</span> ISP_MCLK1_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); ISP_MCLK2_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); ISP_MCLK3_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); <span class="hljs-preprocessor" style="border-radius: 0px !important;">#else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (pinSetIdx == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>) ISP_MCLK1_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (pinSetIdx == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) ISP_MCLK2_EN(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> printk(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"fangkuiccm %d ,currSensorName = %s pinSetIdx = %d "</span>,__LINE__,currSensorName,pinSetIdx ); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//通过DriverName来区分SensorIC</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (currSensorName && (<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span> == <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">strcmp</span>(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) { <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* First Power Pin low and Reset Pin Low */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) mtkcam_gpio_set(pinSetIdx, CAMRST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]); mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">50</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* VCAM_A */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMA, VOL_2800)) { PK_DBG (<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable analog power (VCAM_A),power id = %d\n"</span>, VCAMA); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_; } mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* VCAM_IO */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMIO, VOL_1800)) { PK_DBG (<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable IO power (VCAM_IO),power id = %d\n"</span>, VCAMIO); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_; } mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMD, VOL_1500)) { PK_DBG (<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable digital power (VCAM_D),power id = %d\n"</span>, VCAMD); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_; } mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">10</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* AF_VCC */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (TRUE != _hwPowerOn(VCAMAF, VOL_2800)) { PK_DBG (<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] Fail to enable analog power (VCAM_AF),power id = %d\n"</span>, VCAMAF); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">goto</span> _kdCISModulePowerOn_exit_; } mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">50</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) { mtkcam_gpio_set(pinSetIdx, CAMRST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]); mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>); mtkcam_gpio_set(pinSetIdx, CAMRST, pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON]); } mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* enable active sensor */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]); mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>); mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]); } mdelay(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">5</span>); } }<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span>{ <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//poweroff</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (currSensorName <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//上完电就要下电不然会造成漏电,最终会影响手机功耗</span> && (<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span> == <span class="hljs-built_in" style="border-radius: 0px !important; color: rgb(230, 219, 116);">strcmp</span>(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) { <span class="hljs-preprocessor" style="border-radius: 0px !important;">#if 0</span> 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); <span class="hljs-preprocessor" style="border-radius: 0px !important;">#endif</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* First Power Pin low and Reset Pin Low */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (mt_set_gpio_mode (pinSet[pinSetIdx][IDX_PS_CMPDN], pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) { PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA LENS] set gpio mode failed!! (CMPDN)\n"</span>); } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) { PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA LENS] set gpio dir failed!! (CMPDN)\n"</span>); } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (mt_set_gpio_out (pinSet[pinSetIdx][IDX_PS_CMPDN], pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) { PK_DBG(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA LENS] set gpio failed!! (CMPDN)\n"</span>); } } } }</code>上电操作完成后,紧接着读取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
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id, UINT8 *feature_para,UINT32 *feature_para_len) { .... LOG_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"feature_id = %d\n"</span>, feature_id); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">switch</span> (feature_id) { .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">case</span> SENSOR_FEATURE_CHECK_SENSOR_ID: get_imgsensor_id(feature_return_para_32); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>; .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">default</span>: <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">break</span>; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE; } </code>
优化传入的cmd为SENSOR_FEATURE_CHECK_SENSOR_ID,则会调用feature_control中的
get_imgsensor_id再看get_imgsensor_id的实现
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint32 get_imgsensor_id(UINT32 *sensor_id) { kal_uint8 i = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; kal_uint8 retry = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">2</span>; <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//sensor have two i2c address 0x6c 0x6d & 0x21 0x20, we should detect the module used i2c address</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">while</span> (imgsensor_info.i2c_addr_table[i] != <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xff</span>) { spin_lock(&imgsensor_drv_lock); imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i]; spin_unlock(&imgsensor_drv_lock); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">do</span> { *sensor_id = return_sensor_id(); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">//return_sensor_id读取IC的ID</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (*sensor_id == imgsensor_info.sensor_id) { LOG_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"i2c write id: 0x%x, sensor id: 0x%x\n"</span>, imgsensor.i2c_write_id,*sensor_id); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE; } LOG_INF(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"Read sensor id fail, write id: 0x%x, id: 0x%x\n"</span>, imgsensor.i2c_write_id,*sensor_id); retry--; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">while</span>(retry > <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>); i++; retry = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">2</span>; } .... <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ERROR_NONE; }</code>再看return_sensor_id的实现
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint32 return_sensor_id(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">void</span>) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> ((read_cmos_sensor(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xf0</span>) << <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">8</span>) | read_cmos_sensor(<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xf1</span>)); } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">static</span> kal_uint16 read_cmos_sensor(kal_uint32 addr) { kal_uint16 get_byte=<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> pu_send_cmd[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>] = {(<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span>)(addr & <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0xFF</span>) }; iReadRegI2C(pu_send_cmd, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>, (u8*)&get_byte, <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>, imgsensor.i2c_write_id); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> get_byte; }</code>文件:kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c
<code class=" hljs " style="border-radius: 3px; padding: 0.5em; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(248, 248, 242); border: 0px; display: block; overflow-x: auto; background: rgb(35, 36, 31);"><span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> iReadRegI2C(u8 *a_pSendData, u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData, u16 i2cId) { <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">int</span> i4RetValue = <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) { spin_lock(&kdsensor_drv_lock); g_pstI2Cclient->addr = (i2cId >> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Remove i2c ack error log during search sensor */</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* PK_ERR("g_pstI2Cclient->ext_flag: %d", g_IsSearchSensor); */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_IsSearchSensor == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) { g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> { g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_A_FILTER_MSG); } spin_unlock(&kdsensor_drv_lock); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* */</span> i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeSendData) { PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n"</span>, a_pSendData[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; } i4RetValue = i2c_master_recv(g_pstI2Cclient, (<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *)a_pRecvData, a_sizeRecvData); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeRecvData) { PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C read failed!!\n"</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; } } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> { spin_lock(&kdsensor_drv_lock); g_pstI2Cclient2->addr = (i2cId >> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>); <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* Remove i2c ack error log during search sensor */</span> <span class="hljs-comment" style="border-radius: 0px !important; color: rgb(117, 113, 94);">/* PK_ERR("g_pstI2Cclient2->ext_flag: %d", g_IsSearchSensor); */</span> <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (g_IsSearchSensor == <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>) { g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG; } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">else</span> { 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); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeSendData) { PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n"</span>, a_pSendData[<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>]); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; } i4RetValue = i2c_master_recv(g_pstI2Cclient2, (<span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">char</span> *)a_pRecvData, a_sizeRecvData); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">if</span> (i4RetValue != a_sizeRecvData) { PK_ERR(<span class="hljs-string" style="border-radius: 0px !important; color: rgb(230, 219, 116);">"[CAMERA SENSOR] I2C read failed!!\n"</span>); <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> -<span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">1</span>; } } <span class="hljs-keyword" style="border-radius: 0px !important; color: rgb(249, 38, 114);">return</span> <span class="hljs-number" style="border-radius: 0px !important; color: rgb(174, 129, 255);">0</span>; }</code>
这一步完成I2c的读取,也就是说如果I2c配置正确,并且上电正确,到这一步就可以正确的读取ID,整
个camera也就基本就调通了。
三、总结
通过上述分析,我们可以看出,camera驱动先是注册平台驱动,再注册I2c驱动,然后又为前后摄注册字符设备,封装底层方法,上层访问底层驱动时候显示使用setdriver将具体IC的驱动入口获取,然后使用
checkisalive对sensorlist中的IC进行上电,上电完成就读取设备ID,到此为止,上层应用与底层驱动挂接
完成,紧接着就是预览和拍照,不过这都是具体IC驱动的实现了。
相关文章推荐
- 一、MTK6580 平台 Camera 驱动整体框架
- 请把Camera hold住 - Android高通平台调试Camera驱动全纪录
- FS_S5PC100平台上Linux Camera驱动开发详解(一)
- FS_S5PC100平台上Linux Camera驱动开发详解(一)
- Android Tegra平台back camera 驱动实现三 Android中的camera架构及工作原理
- FS_S5PC100平台上Linux Camera驱动开发详解
- 使用Mule框架设计事件驱动和面向服务的平台
- Tegra平台back camera 驱动实现一
- 请把Camera hold住 - Android高通平台调试Camera驱动全纪录
- FS_S5PC100平台上Linux Camera驱动开发详解(一)
- FS_S5PC100平台上Linux Camera驱动开发详解
- FS_S5PC100平台上Linux Camera驱动开发详解(二)
- FS_S5PC100平台上Linux Camera驱动开发详解(一)
- S5PC100平台上Linux Camera驱动开发详解(二)
- 请把Camera hold住 - Android高通平台调试Camera驱动全纪录
- WinCE6.0 Camera驱动整体结构
- S5PC100平台上Linux Camera驱动开发详解(一)
- FS_S5PC100平台上Linux Camera驱动开发详解(一) .
- tegra平台的camera驱动应用
- WinCE6.0 Camera驱动整体结构