一、MTK6580 平臺 Camera 驅動整體框架

原文: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後面章節會繼續補充。

二、 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-keyword" 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(174, 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驅動的實現了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章