MT6580 Android N camera 框架分析

MT6580 Android N camera 框架分析


整个框架分为三个部分:hal部分逻辑调用,kernel层的通用驱动sensorlist.c 和具体IC的

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

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

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

========================HAL 层部分初始调用========================
vendor/mediatek/proprietary/hardware/mtkcam/legacy/module_hal/devicemgr/CamDeviceManagerBase.cpp
	int32_t
	CamDeviceManagerBase::
	getNumberOfDevices()
	{

		mi4DeviceNum = enumDeviceLocked();

		return  mi4DeviceNum;
	}

vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/devicemgr/CamDeviceManagerImp.cpp
	int32_t
	CamDeviceManagerImp::
	enumDeviceLocked()
	{
		...
	//------------------------------------------------------------------------------
	#if '1'==MTKCAM_HAVE_SENSOR_HAL
		//
		IHalSensorList*const pHalSensorList = IHalSensorList::get();
		size_t const sensorNum = pHalSensorList->searchSensors();
	#endif
		...
		return  i4DeviceNum;
	}

vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.cpp
	MUINT
	HalSensorList::
	searchSensors()
	{
		Mutex::Autolock _l(mEnumSensorMutex);
		//
		MY_LOGD("searchSensors");
		return  enumerateSensor_Locked();
	}

vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/HalSensorList.enumList.cpp
	MUINT
	HalSensorList::
	enumerateSensor_Locked()
	{
		....
	
		MUINT halSensorDev = SENSOR_DEV_NONE;
		NSFeature::SensorInfoBase* pSensorInfo ;
	
		SensorDrv *const pSensorDrv = SensorDrv::get();
		SeninfDrv *const pSeninfDrv = SeninfDrv::createInstance();
		
		int const iSensorsList = pSensorDrv->impSearchSensor(NULL);
	
		....
	}

vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/hal/sensor/imgsensor_drv.cpp
	MINT32
	ImgSensorDrv::impSearchSensor(pfExIdChk pExIdChkCbf)
	{
		....
	
		GetSensorInitFuncList(&m_pstSensorInitFunc);
	
		LOG_MSG("SENSOR search start \n");
	
		sprintf(cBuf,"/dev/%s",CAMERA_HW_DEVNAME);
		m_fdSensor = ::open(cBuf, O_RDWR);
	
		......
		
			for (i = 0; i < 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);
	
		......
	}

vendor/mediatek/proprietary/custom/mt6580/hal/imgsensor_src/sensorlist.cpp
	UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
	{
		if (NULL == ppSensorList) {
			ALOGE("ERROR: NULL pSensorList\n");
			return MHAL_UNKNOWN_ERROR;
		}
		*ppSensorList = &SensorList[0];
		return MHAL_NO_ERROR;
	}
	
	
	MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
	{
	//xc add camera start
	#if defined(GC2365MIPI_RAW)
		RAW_INFO(GC2365MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2365MIPI_RAW, NULL),
	#endif
	
	#if defined(GC2355_MIPI_RAW_BAIKANG_M8112)
		RAW_INFO(GC2355_SENSOR_ID, SENSOR_DRVNAME_GC2355_MIPI_RAW,NULL),
	#endif
	....
	}

获取sensor列表后,紧接着通过:
err = ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER,&id[KDIMGSENSOR_INVOKE_DRIVER_0] );
err = ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
访问kernel层的数据
====================== Kernel 层驱动的实现 ========================

kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c
	static int __init CAMERA_HW_i2C_init(void)
	{
		....
		
	
		if (platform_driver_register(&g_stCAMERA_HW_Driver)) //注册主摄platform 驱动
		if (platform_driver_register(&g_stCAMERA_HW_Driver2)) //注册副摄platform 驱动
	
		....
		return 0;
	}


主摄平台驱动的定义:	
	#ifdef CONFIG_OF
	static const struct of_device_id CAMERA_HW_of_ids[] = {
		{.compatible = "mediatek,camera_hw",},
		{}
	}; 
	#endif
	
	static struct platform_driver g_stCAMERA_HW_Driver = {
		.probe = CAMERA_HW_probe,
		.remove = CAMERA_HW_remove,
		.suspend = CAMERA_HW_suspend,
		.resume = CAMERA_HW_resume,
		.driver = {
			.name = "image_sensor",
			.owner = THIS_MODULE,
	#ifdef CONFIG_OF
			.of_match_table = CAMERA_HW_of_ids,
	#endif
			}
	};
	
副摄平台驱动的定义:
	#ifdef CONFIG_OF
	static const struct of_device_id CAMERA_HW2_of_ids[] = {
		{.compatible = "mediatek,camera_hw2",},
		{}
	};
	#endif
	
	static struct platform_driver g_stCAMERA_HW_Driver2 = {
		.probe = CAMERA_HW_probe2,
		.remove = CAMERA_HW_remove2,
		.suspend = CAMERA_HW_suspend2,
		.resume = CAMERA_HW_resume2,
		.driver = {
			.name = "image_sensor_bus2",
			.owner = THIS_MODULE,
	#ifdef CONFIG_OF
			.of_match_table = CAMERA_HW2_of_ids,
	#endif
	
			}
	};
	#endif

主副摄cam在dts中定义设备信息:kernel-3.18/arch/arm/boot/dts/mt6580.dtsi
	kd_camera_hw1:kd_camera_hw1@15008000 {
			compatible = "mediatek,camera_hw"; 这里必须和主摄一致
			reg = <0x15008000 0x1000>;  /* SENINF_ADDR */
			vcama-supply = <&mt_pmic_vcama_ldo_reg>;
			vcamd-supply = <&mt_pmic_vcamd_ldo_reg>;
			vcamaf-supply = <&mt_pmic_vcamaf_ldo_reg>;
			vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;
	
	};
	kd_camera_hw2:kd_camera_hw2@15008000 {
			compatible = "mediatek,camera_hw2"; 这里必须和副摄一致
			reg = <0x15008000 0x1000>;  /* SENINF_ADDR */
	};

当内核启动后,会解析dts编译生成的dtb文件,注册里面定义的 device,如果device中的 compatible 和驱动中定义 of_device_id 中的 compatible 一致,
则挂载启动。上面注册了两个 platform 驱动 g_stCAMERA_HW_Driver , g_stCAMERA_HW_Driver2 ,
如果匹配成功会调用各自的probe函数 CAMERA_HW_probe , CAMERA_HW_probe2

2. 平台probe 函数的实现
主摄probe, CAMERA_HW_probe 的实现如下:
	/*******************************************************************************
	* CAMERA_HW_probe
	********************************************************************************/
	static int CAMERA_HW_probe(struct platform_device *pdev)
	{
	#if !defined(CONFIG_MTK_LEGACY)
		mtkcam_gpio_init(pdev);
		mtkcam_pin_mux_init(pdev);
	#endif
		return i2c_add_driver(&CAMERA_HW_i2c_driver);
	}

副摄probe, CAMERA_HW_probe2 的实现如下:
	static int CAMERA_HW_probe2(struct platform_device *pdev)
	{
		return i2c_add_driver(&CAMERA_HW_i2c_driver2);
	}

从上可以看出在main/sub 的平台probe中分别注册了各自的i2c驱动 CAMERA_HW_i2c_driver ,
CAMERA_HW_i2c_driver2 ,

main sensor 的 CAMERA_HW_i2c_driver 定义如下
#ifdef CONFIG_OF
	static const struct of_device_id CAMERA_HW_i2c_of_ids[] = {
		{ .compatible = "mediatek,camera_main", },
		{}
	};
	#endif
	
	struct i2c_driver CAMERA_HW_i2c_driver = {
		.probe = CAMERA_HW_i2c_probe,
		.remove = CAMERA_HW_i2c_remove,
		.driver = {
			.name = CAMERA_HW_DRVNAME1,
			.owner = THIS_MODULE,
	
	#ifdef CONFIG_OF
			.of_match_table = CAMERA_HW_i2c_of_ids,
	#endif
			},
		.id_table = CAMERA_HW_i2c_id,
	};
	
sub sensor 的 CAMERA_HW_i2c_driver2 定义如下:	
	#ifdef CONFIG_OF
		static const struct of_device_id CAMERA_HW2_i2c_driver_of_ids[] = {
		{ .compatible = "mediatek,camera_sub", },
		{}
		};
	#endif
	
	struct i2c_driver CAMERA_HW_i2c_driver2 = {
		.probe = CAMERA_HW_i2c_probe2,
		.remove = CAMERA_HW_i2c_remove2,
		.driver = {
		.name = CAMERA_HW_DRVNAME2,
		.owner = THIS_MODULE,
	#ifdef CONFIG_OF
		.of_match_table = CAMERA_HW2_i2c_driver_of_ids,
	#endif
			},
		.id_table = CAMERA_HW_i2c_id2,
	};
	#endif

对应main/sub camera i2c 设备dts定义如下	
kernel-3.18/arch/arm/boot/dts/cust_i2c.dtsi
	&i2c0 {
			camera_main@10 {
					compatible = "mediatek,camera_main";
					reg = <0x10>;
			};
	
			camera_main_af@0c {
					compatible = "mediatek,camera_main_af";
					reg = <0x0c>;
			};
	
			camera_sub@3c {
					compatible = "mediatek,camera_sub";
					reg = <0x3c>;
			};
	
	};
	
3. I2c probe的实现
从上可以看出main/sub sensor在各自的平台probe中,注册了 i2c_driver,当各自的 i2c_driver 和设备
匹配成功后,会调用各自的 i2c_probe 函数。main sensor 的probe函数
CAMERA_HW_i2c_probe :	
	/*******************************************************************************
	* i2c relative start
	********************************************************************************/
	/*******************************************************************************
	* CAMERA_HW_i2c_probe
	********************************************************************************/
	static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
	{
		int i4RetValue = 0;
	
		PK_DBG("[CAMERA_HW] Attach I2C\n");
	
		/* get sensor i2c client */
		spin_lock(&kdsensor_drv_lock);
		g_pstI2Cclient = client;
		/* set I2C clock rate */
		g_pstI2Cclient->timing = 100;	/* 100k */
		g_pstI2Cclient->ext_flag &= ~I2C_POLLING_FLAG;	/* No I2C polling busy waiting */
	
		spin_unlock(&kdsensor_drv_lock);
	
		/* Register char driver */
		i4RetValue = RegisterCAMERA_HWCharDrv(); //注册一个字符型驱动
	
		if (i4RetValue) {
			PK_ERR("[CAMERA_HW] register char device failed!\n");
			return i4RetValue;
		}
	
		/* spin_lock_init(&g_CamHWLock); */
	#if !defined(CONFIG_MTK_LEGACY)
		Get_Cam_Regulator();
	#endif
	
		PK_DBG("[CAMERA_HW] Attached!!\n");
		return 0;
	}

sub sensor 的probe函数 CAMERA_HW_i2c_probe2 :	
	/*******************************************************************************
	* CAMERA_HW_i2c_probe
	********************************************************************************/
	static int CAMERA_HW_i2c_probe2(struct i2c_client *client, const struct i2c_device_id *id)
	{
		int i4RetValue = 0;
	
		PK_DBG("[CAMERA_HW] Attach I2C0\n");
	
		spin_lock(&kdsensor_drv_lock);
	
		/* get sensor i2c client */
		g_pstI2Cclient2 = client;
	
		/* set I2C clock rate */
		g_pstI2Cclient2->timing = 100;	/* 100k */
		g_pstI2Cclient2->ext_flag &= ~I2C_POLLING_FLAG;	/* No I2C polling busy waiting */
		spin_unlock(&kdsensor_drv_lock);
	
		/* Register char driver */
		i4RetValue = RegisterCAMERA_HWCharDrv2();//注册一个字符型驱动
	
		if (i4RetValue) {
			PK_ERR("[CAMERA_HW] register char device failed!\n");
			return i4RetValue;
		}
	
		/* spin_lock_init(&g_CamHWLock); */
	
		PK_DBG("[CAMERA_HW] Attached!!\n");
		return 0;
	}	

从上可以看出main/sub 在各自的i2c probe中,通过该调用 RegisterCAMERA_HWCharDrv ,
RegisterCAMERA_HWCharDrv2 注册了字符设备。各自注册 cdev函数实现如下:	
	/*******************************************************************************
	* RegisterCAMERA_HWCharDrv
	********************************************************************************/
	static inline int RegisterCAMERA_HWCharDrv(void)
	{
	
	#if CAMERA_HW_DYNAMIC_ALLOCATE_DEVNO
		if (alloc_chrdev_region(&g_CAMERA_HWdevno, 0, 1, CAMERA_HW_DRVNAME1)) {
			PK_DBG("[CAMERA SENSOR] Allocate device no failed\n");
	
			return -EAGAIN;
		}
	#else
		if (register_chrdev_region(g_CAMERA_HWdevno, 1, CAMERA_HW_DRVNAME1)) {
			PK_DBG("[CAMERA SENSOR] Register device no failed\n");
	
			return -EAGAIN;
		}
	#endif
	
		/* Allocate driver */
		g_pCAMERA_HW_CharDrv = cdev_alloc();
	
		if (NULL == g_pCAMERA_HW_CharDrv) {
			unregister_chrdev_region(g_CAMERA_HWdevno, 1);
	
			PK_DBG("[CAMERA SENSOR] Allocate mem for kobject failed\n");
	
			return -ENOMEM;
		}
	
		/* Attatch file operation. */
		cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops);//初始化字符设备
	
		g_pCAMERA_HW_CharDrv->owner = THIS_MODULE;
	
		/* Add to system */
		if (cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, 1)) {  //注册到内核
			PK_DBG("[mt6516_IDP] Attatch file operation failed\n");
	
			unregister_chrdev_region(g_CAMERA_HWdevno, 1);
	
			return -EAGAIN;
		}
	
		sensor_class = class_create(THIS_MODULE, "sensordrv"); //创建类 sys/class/sensordrv
		if (IS_ERR(sensor_class)) {
			int ret = PTR_ERR(sensor_class);
	
			PK_DBG("Unable to create class, err = %d\n", ret);
			return ret;
		}
		sensor_device =
			device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1); //创建类设备:创建目录/sys/class/sensordrv/kd_camera_hw
	
		return 0;
	}	
	

	static inline int RegisterCAMERA_HWCharDrv2(void)//sub sensor 注册cdev
	{
		....
	
		/* Attatch file operation. */
		cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0);//初始化字符设备 
		/* Add to system */
		cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, 1));//注册到内核
		
		sensor2_class = class_create(THIS_MODULE, "sensordrv2");//创建类: /sys/class/sensordrv2/
		
		//创建类设备:/sys/class/sensordrv2/kd_camera_hw_bus2
		sensor_device2 = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2);
		....
		return 0;
	}	
	
main/sub 创建各自的字符设备过程中绑定各自的fops, g_stCAMERA_HW_fops 和 g_stCAMERA_HW_fops0	
他们各自定义如下
	static const struct file_operations g_stCAMERA_HW_fops = { //main sensor fops
		.owner = THIS_MODULE,
		.open = CAMERA_HW_Open,
		.release = CAMERA_HW_Release,
		.unlocked_ioctl = CAMERA_HW_Ioctl,
	#ifdef CONFIG_COMPAT
		.compat_ioctl = CAMERA_HW_Ioctl_Compat,
	#endif
	
	};
	
	static const struct file_operations g_stCAMERA_HW_fops0 = { //sub sensor fops
		.owner = THIS_MODULE,
		.open = CAMERA_HW_Open2,
		.release = CAMERA_HW_Release2,
		.unlocked_ioctl = CAMERA_HW_Ioctl,
	#ifdef CONFIG_COMPAT
		.compat_ioctl = CAMERA_HW_Ioctl_Compat,
	#endif
	
	};
	
从上可以看出各自的fops指定了相同的 Iioctl 函数,意味着上层操作main/sub sensor 只需要对应一个
底层的ioctl即可,至于sensor的区分可以借助idx,后面会讲到	
	static long CAMERA_HW_Ioctl(struct file *a_pstFile,
					unsigned int a_u4Command, unsigned long a_u4Param)
	{
	
		int i4RetValue = 0;
		void *pBuff = NULL;
		u32 *pIdx = NULL;
	
		mutex_lock(&kdCam_Mutex);
	
	
		if (_IOC_NONE == _IOC_DIR(a_u4Command)) {
		} else {
			pBuff = kmalloc(_IOC_SIZE(a_u4Command), GFP_KERNEL);
	
			if (NULL == pBuff) {
				PK_DBG("[CAMERA SENSOR] ioctl allocate mem failed\n");
				i4RetValue = -ENOMEM;
				goto CAMERA_HW_Ioctl_EXIT;
			}
	
			if (_IOC_WRITE & _IOC_DIR(a_u4Command)) {
				if (copy_from_user(pBuff, (void *)a_u4Param, _IOC_SIZE(a_u4Command))) {
					kfree(pBuff);
					PK_DBG("[CAMERA SENSOR] ioctl copy from user failed\n");
					i4RetValue = -EFAULT;
					goto CAMERA_HW_Ioctl_EXIT;
				}
			}
		}
	
		pIdx = (u32 *) pBuff;
		switch (a_u4Command) {
	
	#if 0
		case KDIMGSENSORIOC_X_POWER_ON:
			i4RetValue =
			kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, true,
						CAMERA_HW_DRVNAME);
			break;
		case KDIMGSENSORIOC_X_POWER_OFF:
			i4RetValue =
			kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, false,
						CAMERA_HW_DRVNAME);
			break;
	#endif
		case KDIMGSENSORIOC_X_SET_DRIVER:
			i4RetValue = kdSetDriver((unsigned int *)pBuff);
			break;
		case KDIMGSENSORIOC_T_OPEN:
			i4RetValue = adopt_CAMERA_HW_Open();
			break;
		case KDIMGSENSORIOC_X_GETINFO:
			i4RetValue = adopt_CAMERA_HW_GetInfo(pBuff);
			break;
		case KDIMGSENSORIOC_X_GETRESOLUTION2:
			i4RetValue = adopt_CAMERA_HW_GetResolution(pBuff);
			break;
		case KDIMGSENSORIOC_X_GETINFO2:
			i4RetValue = adopt_CAMERA_HW_GetInfo2(pBuff);
			break;
		case KDIMGSENSORIOC_X_FEATURECONCTROL:
			i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
			break;
		case KDIMGSENSORIOC_X_CONTROL:
			i4RetValue = adopt_CAMERA_HW_Control(pBuff);
			break;
		case KDIMGSENSORIOC_T_CLOSE:
			i4RetValue = adopt_CAMERA_HW_Close();
			break;
		case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
			i4RetValue = adopt_CAMERA_HW_CheckIsAlive();
			break;
		case KDIMGSENSORIOC_X_GET_SOCKET_POS:
			i4RetValue = kdGetSocketPostion((unsigned int *)pBuff);
			break;
		case KDIMGSENSORIOC_X_SET_I2CBUS:
			/* i4RetValue = kdSetI2CBusNum(*pIdx); */
			break;
		case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK:
			/* i4RetValue = kdReleaseI2CTriggerLock(); */
			break;
	
		case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE:
			i4RetValue = kdSensorSetExpGainWaitDone((int *)pBuff);
			break;
	
		case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:
			i4RetValue = kdSetCurrentSensorIdx(*pIdx);
			break;
	
		case KDIMGSENSORIOC_X_SET_MCLK_PLL:
			i4RetValue = kdSetSensorMclk(pBuff);
			break;
	
		case KDIMGSENSORIOC_X_SET_GPIO:
			i4RetValue = kdSetSensorGpio(pBuff);
			break;
	
		case KDIMGSENSORIOC_X_GET_ISP_CLK:
			/* PK_DBG("get_isp_clk=%d\n",get_isp_clk()); */
			/* *(unsigned int*)pBuff = get_isp_clk(); */
			break;
	
		default:
			PK_DBG("No such command\n");
			i4RetValue = -EPERM;
			break;
	
		}
	
		if (_IOC_READ & _IOC_DIR(a_u4Command)) {
			if (copy_to_user((void __user *)a_u4Param, pBuff, _IOC_SIZE(a_u4Command))) {
				kfree(pBuff);
				PK_DBG("[CAMERA SENSOR] ioctl copy to user failed\n");
				i4RetValue = -EFAULT;
				goto CAMERA_HW_Ioctl_EXIT;
			}
		}
	
		kfree(pBuff);
	CAMERA_HW_Ioctl_EXIT:
		mutex_unlock(&kdCam_Mutex);
		return i4RetValue;
	}

这里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 接口
	/*******************************************************************************
	* kdSetDriver
	********************************************************************************/
	int kdSetDriver(unsigned int *pDrvIndex)
	{
		ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
		u32 drvIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = { 0, 0 };
		u32 i;
	
		/* set driver for MAIN or SUB sensor */
		PK_INF("pDrvIndex:0x%08x/0x%08x\n", pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0],
			pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_1]);
		/* Camera information */
		gDrvIndex = pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0];
	
		if (0 != kdGetSensorInitFuncList(&pSensorList)) {  //获得sensor初始化列表
			PK_ERR("ERROR:kdGetSensorInitFuncList()\n");
			return -EIO;
		}
	
		for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
			/*  */
			spin_lock(&kdsensor_drv_lock);
			g_bEnableDriver[i] = FALSE;
			g_invokeSocketIdx[i] =
				(CAMERA_DUAL_CAMERA_SENSOR_ENUM) ((pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_MSB) >>
								KDIMGSENSOR_DUAL_SHIFT);
			spin_unlock(&kdsensor_drv_lock);
			drvIdx[i] = (pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_LSB);
			/*  */
			if (DUAL_CAMERA_NONE_SENSOR == g_invokeSocketIdx[i]) {
				continue;
			}
	#if 0
			if (DUAL_CAMERA_MAIN_SENSOR == g_invokeSocketIdx[i]
				|| DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]
				|| DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i]) {
				spin_lock(&kdsensor_drv_lock);
				gI2CBusNum = SENSOR_I2C_BUS_NUM[g_invokeSocketIdx[i]];
				spin_unlock(&kdsensor_drv_lock);
				PK_XLOG_INFO("kd_MultiSensorOpen: switch I2C BUS%d\n", gI2CBusNum);
			}
	#else
	
			if (DUAL_CAMERA_SUB_SENSOR == g_invokeSocketIdx[i]) {
				spin_lock(&kdsensor_drv_lock);
				gI2CBusNum = SUPPORT_I2C_BUS_NUM2;
				spin_unlock(&kdsensor_drv_lock);
				/* PK_XLOG_INFO("kdSetDriver: switch I2C BUS2\n"); */
			} else {
				spin_lock(&kdsensor_drv_lock);
				gI2CBusNum = SUPPORT_I2C_BUS_NUM1;
				spin_unlock(&kdsensor_drv_lock);
				/* PK_XLOG_INFO("kdSetDriver: switch I2C BUS1\n"); */
			}
	#endif
			PK_INF("g_invokeSocketIdx[%d]=%d,drvIdx[%d]=%d\n", i, g_invokeSocketIdx[i], i,
				drvIdx[i]);
			/* PK_INF("[kdSetDriver]drvIdx[%d] = %d\n", i, drvIdx[i]); */
			/*  */
			if (MAX_NUM_OF_SUPPORT_SENSOR > drvIdx[i]) {
				if (NULL == pSensorList[drvIdx[i]].SensorInit) {
					PK_ERR("ERROR:kdSetDriver()\n");
					return -EIO;
				}
	
				pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); //获取各个cam驱动中Init函数入口
				if (NULL == g_pInvokeSensorFunc[i]) {
					PK_ERR("ERROR:NULL g_pSensorFunc[%d]\n", i);
					return -EIO;
				}
				/*  */
				spin_lock(&kdsensor_drv_lock);
				g_bEnableDriver[i] = TRUE;
				spin_unlock(&kdsensor_drv_lock);
				/* get sensor name */
				memcpy((char *)g_invokeSensorNameStr[i],
					(char *)pSensorList[drvIdx[i]].drvname,
					sizeof(pSensorList[drvIdx[i]].drvname));
				/* return sensor ID */
				/* pDrvIndex[0] = (unsigned int)pSensorList[drvIdx].SensorId; */
				PK_INF("[%d][%d][%d][%s][%d]\n", i, g_bEnableDriver[i],
					g_invokeSocketIdx[i], g_invokeSensorNameStr[i],
					sizeof(pSensorList[drvIdx[i]].drvname));
			}
		}
		return 0;
	}

	/*******************************************************************************
	* general camera image sensor kernel driver
	*******************************************************************************/
	UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
	{
		if (NULL == ppSensorList) {
			PK_ERR("[kdGetSensorInitFuncList]ERROR: NULL ppSensorList\n");
			return 1;
		}
		*ppSensorList = &kdSensorList[0];  //获取sensorlist数组首地址
		return 0;
	}				/* kdGetSensorInitFuncList() */

kdSensorList 定义如下
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.h
	ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
	{
		....
	
	#if defined(SUB_GC2355_MIPI_RAW)
		{GC2355S_SENSOR_ID, SENSOR_DRVNAME_GC2355S_MIPI_RAW,GC2235MIPI_RAW_SensorInit},
	#endif
	
		....
	}

获取列表之后紧接着调用各自的 Init 函数,这里以GC2355为例
	UINT32 GC2235MIPI_RAW_SensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
	{
		/* To Do : Check Sensor status here */
		if (pfFunc!=NULL)
			*pfFunc=&sensor_func;
		return ERROR_NONE;
	}	/*	GC2235MIPI_RAW_SensorInit	*/

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

4.2 再来看 ioctl(m_fdSensor, KDIMGSENSORIOC_T_CHECK_IS_ALIVE);
当 KDIMGSENSORIOC_T_CHECK_IS_ALIVE 被传下时,会调用kernel层的 adopt_CAMERA_HW_CheckIsAlive

Control接口	
	static inline int adopt_CAMERA_HW_CheckIsAlive(void)
	{
		/* power on sensor */
		kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM *) g_invokeSocketIdx, g_invokeSensorNameStr,
				true, CAMERA_HW_DRVNAME1);

	
		if (g_pSensorFunc) {
			for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
				if (DUAL_CAMERA_NONE_SENSOR != g_invokeSocketIdx[i]) {
					err =
						g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],
										SENSOR_FEATURE_CHECK_SENSOR_ID,
										(MUINT8 *) &sensorID,
										&retLen);
					if (sensorID == 0) {	/* not implement this feature ID */
						PK_DBG
							(" Not implement!!, use old open function to check\n");
						err = ERROR_SENSOR_CONNECT_FAIL;
					} else if (sensorID == 0xFFFFFFFF) {	/* fail to open the sensor */
						PK_DBG(" No Sensor Found");
						err = ERROR_SENSOR_CONNECT_FAIL;
					} else {
	
						PK_INF(" Sensor found ID = 0x%x\n", sensorID);
						snprintf(mtk_ccm_name, sizeof(mtk_ccm_name),
							"%s CAM[%d]:%s;", mtk_ccm_name,
							g_invokeSocketIdx[i], g_invokeSensorNameStr[i]);
						psensorResolution[0] = &sensorResolution[0];
						psensorResolution[1] = &sensorResolution[1];
						// don't care of the result
						g_pSensorFunc->SensorGetResolution(psensorResolution);
						if(g_invokeSocketIdx[i] == DUAL_CAMERA_MAIN_SENSOR)
							curr_sensor_id = 0;
						else if(g_invokeSocketIdx[i] == DUAL_CAMERA_SUB_SENSOR)
							curr_sensor_id = 1;
						/* fill the cam infos with name/width/height */
						snprintf(g_cam_infos, sizeof(g_cam_infos),"%s CAM[%d]:%s,Width:%d, Height:%d;",
									g_cam_infos, g_invokeSocketIdx[i], g_invokeSensorNameStr[i],
									sensorResolution[curr_sensor_id].SensorFullWidth, sensorResolution[curr_sensor_id].SensorFullHeight);
	
						err = ERROR_NONE;
					}
					if (ERROR_NONE != err) {
						PK_DBG
							("ERROR:adopt_CAMERA_HW_CheckIsAlive(), No imgsensor alive\n");
					}
				}
			}
		} else {
			PK_DBG("ERROR:NULL g_pSensorFunc\n");
		}

	}				/* adopt_CAMERA_HW_Open() */	

这个函数非常重要,它主要进行了以下几个动作,
1)通过 kdModulePowerOn 给Sensor 上电
2)通过 SensorFeatureControl 读取 SensorID 
先看 kdModulePowerOn 的实现	
	/*******************************************************************************
	* kdModulePowerOn
	********************************************************************************/
	int
	kdModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM socketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS],
			char sensorNameStr[KDIMGSENSOR_MAX_INVOKE_DRIVERS][32], BOOL On, char *mode_name)
	{
		MINT32 ret = ERROR_NONE;
		u32 i = 0;
	
		for (i = KDIMGSENSOR_INVOKE_DRIVER_0; i < KDIMGSENSOR_MAX_INVOKE_DRIVERS; i++) {
			if (g_bEnableDriver[i]) {
				/* PK_XLOG_INFO("[%s][%d][%d][%s][%s]\r\n",__FUNCTION__,g_bEnableDriver[i],socketIdx[i],sensorNameStr[i],mode_name); */
	#ifndef CONFIG_FPGA_EARLY_PORTING
				ret = _kdCISModulePowerOn(socketIdx[i], sensorNameStr[i], On, mode_name);
	#endif
				if (ERROR_NONE != ret) {
					PK_ERR("[%s]", __func__);
					return ret;
				}
			}
		}
		return ERROR_NONE;
	}

在 kdModulePowerOn 中又调用 _kdCISModulePowerOn
/*******************************************************************************
*  wrapper to count times of power on/off
********************************************************************************/
	int _kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On,
				char *mode_name)
	{
		int ret = -1;
	
		ret = kdCISModulePowerOn(SensorIdx, currSensorName, On, mode_name);
		if (ret == ERROR_NONE) {
			spin_lock(&power_count_lock);
			if (On) {
				if (SensorIdx == DUAL_CAMERA_MAIN_SENSOR) {
					cntPWROnMain += 1;
				} else if (SensorIdx == DUAL_CAMERA_SUB_SENSOR) {
					cntPWROnSub += 1;
				}
			} else {
				if (SensorIdx == DUAL_CAMERA_MAIN_SENSOR) {
					cntPWROnMain -= 1;
				} else if (SensorIdx == DUAL_CAMERA_SUB_SENSOR) {
					cntPWROnSub -= 1;
				}
			}
			spin_unlock(&power_count_lock);
		}
		return ret;
	}
在 _kdCISModulePowerOn 又调用 kdCISModulePowerOn 函数
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/camera_hw/kd_camera_hw.c
//改函数为上下电函数,通过传入 BOOL 值来判断上/下电
	int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, BOOL On,
				char *mode_name)
	{
	
		u32 pinSetIdx = 0;	/* default main sensor */
	
	#define IDX_PS_CMRST 0
	#define IDX_PS_CMPDN 4
	#define IDX_PS_MODE 1
	#define IDX_PS_ON   2
	#define IDX_PS_OFF  3
	#define VOL_2800 2800000
	#define VOL_1800 1800000
	#define VOL_1500 1500000
	#define VOL_1200 1200000
	#define VOL_1000 1000000
	
	
		u32 pinSet[3][8] = {
			/* for main sensor */
			{		/* The reset pin of main sensor uses GPIO10 of mt6306, please call mt6306 API to set */
			CAMERA_CMRST_PIN,
			CAMERA_CMRST_PIN_M_GPIO,	/* mode */
			GPIO_OUT_ONE,	/* ON state */
			GPIO_OUT_ZERO,	/* OFF state */
			CAMERA_CMPDN_PIN,
			CAMERA_CMPDN_PIN_M_GPIO,
			GPIO_OUT_ONE,
			GPIO_OUT_ZERO,
			},
			/* for sub sensor */
			{
			CAMERA_CMRST1_PIN,
			CAMERA_CMRST1_PIN_M_GPIO,
			GPIO_OUT_ONE,
			GPIO_OUT_ZERO,
			CAMERA_CMPDN1_PIN,
			CAMERA_CMPDN1_PIN_M_GPIO,
			GPIO_OUT_ONE,
			GPIO_OUT_ZERO,
			},
			/* for main_2 sensor */
			{
			GPIO_CAMERA_INVALID,
			GPIO_CAMERA_INVALID,	/* mode */
			GPIO_OUT_ONE,	/* ON state */
			GPIO_OUT_ZERO,	/* OFF state */
			GPIO_CAMERA_INVALID,
			GPIO_CAMERA_INVALID,
			GPIO_OUT_ONE,
			GPIO_OUT_ZERO,
			}
		};
	
		if (DUAL_CAMERA_MAIN_SENSOR == SensorIdx)
			pinSetIdx = 0;
		else if (DUAL_CAMERA_SUB_SENSOR == SensorIdx)
			pinSetIdx = 1;
		else if (DUAL_CAMERA_MAIN_2_SENSOR == SensorIdx)
			pinSetIdx = 2;
	
		/* power ON */
		if (On) {
	
	#if 0
			ISP_MCLK1_EN(1);
			ISP_MCLK2_EN(1);
			ISP_MCLK3_EN(1);
	#else
			if (pinSetIdx == 0)
				ISP_MCLK1_EN(1);
			else if (pinSetIdx == 1)
				ISP_MCLK2_EN(1);
	#endif
	
		printk("fangkuiccm %d ,currSensorName = %s pinSetIdx = %d ",__LINE__,currSensorName,pinSetIdx );
		
		//通过DriverName来区分SensorIC
		if (currSensorName && (0 == strcmp(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {
				
				/* First Power Pin low and Reset Pin Low */
				if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN])
					mtkcam_gpio_set(pinSetIdx, CAMPDN,
							pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);
	
				if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST])
					mtkcam_gpio_set(pinSetIdx, CAMRST,
							pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);
	
				mdelay(50);
	
				/* VCAM_A */
				if (TRUE != _hwPowerOn(VCAMA, VOL_2800)) {
					PK_DBG
						("[CAMERA SENSOR] Fail to enable analog power (VCAM_A),power id = %d\n",
						VCAMA);
					goto _kdCISModulePowerOn_exit_;
				}
	
				mdelay(10);
	
				/* VCAM_IO */
				if (TRUE != _hwPowerOn(VCAMIO, VOL_1800)) {
					PK_DBG
						("[CAMERA SENSOR] Fail to enable IO power (VCAM_IO),power id = %d\n",
						VCAMIO);
					goto _kdCISModulePowerOn_exit_;
				}
	
				mdelay(10);
	
				if (TRUE != _hwPowerOn(VCAMD, VOL_1500)) {
					PK_DBG
						("[CAMERA SENSOR] Fail to enable digital power (VCAM_D),power id = %d\n",
						VCAMD);
					goto _kdCISModulePowerOn_exit_;
				}
	
				mdelay(10);
	
				/* AF_VCC */
				if (TRUE != _hwPowerOn(VCAMAF, VOL_2800)) {
					PK_DBG
						("[CAMERA SENSOR] Fail to enable analog power (VCAM_AF),power id = %d\n",
						VCAMAF);
					goto _kdCISModulePowerOn_exit_;
				}
	
	
				mdelay(50);
	
				if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMRST]) {
					mtkcam_gpio_set(pinSetIdx, CAMRST,
							pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_OFF]);
					mdelay(5);
					mtkcam_gpio_set(pinSetIdx, CAMRST,
							pinSet[pinSetIdx][IDX_PS_CMRST + IDX_PS_ON]);
				}
				mdelay(5);
				/* enable active sensor */
				if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {
					mtkcam_gpio_set(pinSetIdx, CAMPDN,
							pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]);
					mdelay(5);
					mtkcam_gpio_set(pinSetIdx, CAMPDN,
							pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);
				}
	
				mdelay(5);
			} 
		}else{ //poweroff
		if (currSensorName   //上完电就要下电不然会造成漏电,最终会影响手机功耗
				&& (0 == strcmp(SENSOR_DRVNAME_GC2355_MIPI_RAW, currSensorName))) {
	#if 0
				mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_MODE_00);
				mt_set_gpio_dir(GPIO_SPI_MOSI_PIN, GPIO_DIR_OUT);
				mt_set_gpio_out(GPIO_SPI_MOSI_PIN, GPIO_OUT_ONE);
	#endif
				/* First Power Pin low and Reset Pin Low */
				if (GPIO_CAMERA_INVALID != pinSet[pinSetIdx][IDX_PS_CMPDN]) {
					if (mt_set_gpio_mode
						(pinSet[pinSetIdx][IDX_PS_CMPDN],
						pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_MODE])) {
						PK_DBG("[CAMERA LENS] set gpio mode failed!! (CMPDN)\n");
					}
					if (mt_set_gpio_dir(pinSet[pinSetIdx][IDX_PS_CMPDN], GPIO_DIR_OUT)) {
						PK_DBG("[CAMERA LENS] set gpio dir failed!! (CMPDN)\n");
					}
					if (mt_set_gpio_out
						(pinSet[pinSetIdx][IDX_PS_CMPDN],
						pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF])) {
						PK_DBG("[CAMERA LENS] set gpio failed!! (CMPDN)\n");
					}
				}
		}
	}
	
上电操作完成后,紧接着读取SensorID,通用驱动使用 SensorFeatureControl 来读取ID如:

 g_pSensorFunc->SensorFeatureControl(g_invokeSocketIdx[i],
SENSOR_FEATURE_CHECK_SENSOR_ID,
(MUINT8 *) &sensorID,
&retLen);
这步操作会调用 GC5025 中的 feature_control 函数如下:
	static kal_uint32 feature_control(MSDK_SENSOR_FEATURE_ENUM feature_id,
								UINT8 *feature_para,UINT32 *feature_para_len)
	{
		UINT16 *feature_return_para_16=(UINT16 *) feature_para;
		UINT16 *feature_data_16=(UINT16 *) feature_para;
		UINT32 *feature_return_para_32=(UINT32 *) feature_para;
		UINT32 *feature_data_32=(UINT32 *) feature_para;
		unsigned long long *feature_data=(unsigned long long *) feature_para;
		//unsigned long long *feature_return_para=(unsigned long long *) feature_para;
	
		SENSOR_WINSIZE_INFO_STRUCT *wininfo;
		MSDK_SENSOR_REG_INFO_STRUCT *sensor_reg_data=(MSDK_SENSOR_REG_INFO_STRUCT *) feature_para;
	
		LOG_INF("feature_id = %d\n", feature_id);
		printk("[carl]get GC5025_sensor bright = %d,GC0339_sensor bright = %d\n",main_cam_sensor_data(),fake_cam_sensor_data());	
	//	printk("[carl]get the GC0339_sensor bright = %x\n",fake_cam_sensor_data());
		switch (feature_id) {
			case SENSOR_FEATURE_GET_PERIOD:
				*feature_return_para_16++ = imgsensor.line_length;
				*feature_return_para_16 = imgsensor.frame_length;
				*feature_para_len=4;
				break;
			case SENSOR_FEATURE_GET_PIXEL_CLOCK_FREQ:
				*feature_return_para_32 = imgsensor.pclk;
				*feature_para_len=4;
				break;
			case SENSOR_FEATURE_SET_ESHUTTER:
				set_shutter(*feature_data);
				break;
			case SENSOR_FEATURE_SET_NIGHTMODE:
				night_mode((BOOL) *feature_data);
				break;
			case SENSOR_FEATURE_SET_GAIN:
				set_gain((UINT16) *feature_data);
				break;
			case SENSOR_FEATURE_SET_FLASHLIGHT:
				break;
			case SENSOR_FEATURE_SET_ISP_MASTER_CLOCK_FREQ:
				break;
			case SENSOR_FEATURE_SET_REGISTER:
				write_cmos_sensor(sensor_reg_data->RegAddr, sensor_reg_data->RegData);
				break;
			case SENSOR_FEATURE_GET_REGISTER:
				sensor_reg_data->RegData = read_cmos_sensor(sensor_reg_data->RegAddr);
				break;
			case SENSOR_FEATURE_GET_LENS_DRIVER_ID:
				// get the lens driver ID from EEPROM or just return LENS_DRIVER_ID_DO_NOT_CARE
				// if EEPROM does not exist in camera module.
				*feature_return_para_32=LENS_DRIVER_ID_DO_NOT_CARE;
				*feature_para_len=4;
				break;
			case SENSOR_FEATURE_SET_VIDEO_MODE:
				set_video_mode(*feature_data);
				break;
			case SENSOR_FEATURE_CHECK_SENSOR_ID:
				get_imgsensor_id(feature_return_para_32);
				break;
			case SENSOR_FEATURE_SET_AUTO_FLICKER_MODE:
				set_auto_flicker_mode((BOOL)*feature_data_16,*(feature_data_16+1));
				break;
			case SENSOR_FEATURE_SET_MAX_FRAME_RATE_BY_SCENARIO:
				set_max_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*feature_data, *(feature_data+1));
				break;
			case SENSOR_FEATURE_GET_DEFAULT_FRAME_RATE_BY_SCENARIO:
				get_default_framerate_by_scenario((MSDK_SCENARIO_ID_ENUM)*(feature_data), (MUINT32 *)(uintptr_t)(*(feature_data+1)));
				break;
			case SENSOR_FEATURE_SET_TEST_PATTERN:
				set_test_pattern_mode((BOOL)*feature_data);
				break;
			case SENSOR_FEATURE_GET_TEST_PATTERN_CHECKSUM_VALUE: //for factory mode auto testing
				*feature_return_para_32 = imgsensor_info.checksum_value;
				*feature_para_len=4;
				break;
			case SENSOR_FEATURE_SET_FRAMERATE:
				LOG_INF("current fps :%d\n", (UINT32)*feature_data);
				spin_lock(&imgsensor_drv_lock);
				imgsensor.current_fps = *feature_data;
				spin_unlock(&imgsensor_drv_lock);
				break;
			case SENSOR_FEATURE_SET_HDR:
				LOG_INF("ihdr enable :%d\n", (BOOL)*feature_data);
				spin_lock(&imgsensor_drv_lock);
				imgsensor.ihdr_en = (BOOL)*feature_data;
				spin_unlock(&imgsensor_drv_lock);
				break;
			case SENSOR_FEATURE_GET_CROP_INFO:
				LOG_INF("SENSOR_FEATURE_GET_CROP_INFO scenarioId:%d\n", (UINT32)*feature_data);
	
				wininfo = (SENSOR_WINSIZE_INFO_STRUCT *)(uintptr_t)(*(feature_data+1));
	
				switch (*feature_data_32) {
					case MSDK_SCENARIO_ID_CAMERA_CAPTURE_JPEG:
						memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[1],sizeof(SENSOR_WINSIZE_INFO_STRUCT));
						break;
					case MSDK_SCENARIO_ID_VIDEO_PREVIEW:
						memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[2],sizeof(SENSOR_WINSIZE_INFO_STRUCT));
						break;
					case MSDK_SCENARIO_ID_HIGH_SPEED_VIDEO:
						memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[3],sizeof(SENSOR_WINSIZE_INFO_STRUCT));
						break;
					case MSDK_SCENARIO_ID_SLIM_VIDEO:
						memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[4],sizeof(SENSOR_WINSIZE_INFO_STRUCT));
						break;
					case MSDK_SCENARIO_ID_CAMERA_PREVIEW:
					default:
						memcpy((void *)wininfo,(void *)&imgsensor_winsize_info[0],sizeof(SENSOR_WINSIZE_INFO_STRUCT));
						break;
				}
				break;
			case SENSOR_FEATURE_SET_IHDR_SHUTTER_GAIN:
				LOG_INF("SENSOR_SET_SENSOR_IHDR LE=%d, SE=%d, Gain=%d\n",(UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2));
				ihdr_write_shutter_gain((UINT16)*feature_data,(UINT16)*(feature_data+1),(UINT16)*(feature_data+2));
				break;
			default:
				break;
		}
	
		return ERROR_NONE;
	}    /*    feature_control()  */

优先传入的cmd为 SENSOR_FEATURE_CHECK_SENSOR_ID ,则会调用 feature_control 中的
get_imgsensor_id 再看 get_imgsensor_id 的实现
	static kal_uint32 get_imgsensor_id(UINT32 *sensor_id)
	{
		kal_uint8 i = 0;
		kal_uint8 retry = 2;
		
			while (imgsensor_info.i2c_addr_table[i] != 0xff) {
				spin_lock(&imgsensor_drv_lock);
				imgsensor.i2c_write_id = imgsensor_info.i2c_addr_table[i];
				spin_unlock(&imgsensor_drv_lock);
				do {
					*sensor_id = return_sensor_id(); //return_sensor_id 读取IC的ID
					//printk("[carl_2]Read GC0339 sensor id, write id: 0x%x, id: 0x%x\n", GC0339_sensor_addr,GC0339_return_sensor_id());
					if (*sensor_id == imgsensor_info.sensor_id) {
						LOG_INF("i2c write id: 0x%x, sensor id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id);
						return ERROR_NONE;
					}
					LOG_INF("Read sensor id fail, write id: 0x%x, id: 0x%x\n", imgsensor.i2c_write_id,*sensor_id);
					retry--;
				} while(retry > 0);
				i++;
				retry = 2;
			}
			if (*sensor_id != imgsensor_info.sensor_id) {
				// if Sensor ID is not correct, Must set *sensor_id to 0xFFFFFFFF
				*sensor_id = 0xFFFFFFFF;
				return ERROR_SENSOR_CONNECT_FAIL;
			}
			return ERROR_NONE;
	}
再看 return_sensor_id 的实现
	static kal_uint32 return_sensor_id(void)
	{
		return ((read_cmos_sensor(0xf0) << 8) | read_cmos_sensor(0xf1));
	}

再看 read_cmos_sensor 的实现
static kal_uint16 read_cmos_sensor(kal_uint32 addr)
{
	kal_uint16 get_byte=0;

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

	return get_byte;

}

再看 调用的 iReadRegI2C 函数的实现:
kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6580/kd_sensorlist.c
	/*******************************************************************************
	* iReadRegI2C 
	********************************************************************************/
	int iReadRegI2C(u8 *a_pSendData, u16 a_sizeSendData, u8 *a_pRecvData, u16 a_sizeRecvData,
			u16 i2cId)
	{
		int i4RetValue = 0;
	
		if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) {
			spin_lock(&kdsensor_drv_lock);
			g_pstI2Cclient->addr = (i2cId >> 1);
			g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG);
	
			/* Remove i2c ack error log during search sensor */
			/* PK_ERR("g_pstI2Cclient->ext_flag: %d", g_IsSearchSensor); */
			if (g_IsSearchSensor == 1) {
				g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) | I2C_A_FILTER_MSG;
			} else {
				g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_A_FILTER_MSG);
			}
	
			spin_unlock(&kdsensor_drv_lock);
			/*  */
			i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData);
			if (i4RetValue != a_sizeSendData) {
				PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]);
				return -1;
			}
	
			i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_pRecvData, a_sizeRecvData);
			if (i4RetValue != a_sizeRecvData) {
				PK_ERR("[CAMERA SENSOR] I2C read failed!!\n");
				return -1;
			}
		} else {
			spin_lock(&kdsensor_drv_lock);
			g_pstI2Cclient2->addr = (i2cId >> 1);
	
			/* Remove i2c ack error log during search sensor */
			/* PK_ERR("g_pstI2Cclient2->ext_flag: %d", g_IsSearchSensor); */
			if (g_IsSearchSensor == 1) {
				g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) | I2C_A_FILTER_MSG;
			} else {
				g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) & (~I2C_A_FILTER_MSG);
			}
			spin_unlock(&kdsensor_drv_lock);
			i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData);
			if (i4RetValue != a_sizeSendData) {
				PK_ERR("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x\n", a_pSendData[0]);
				return -1;
			}
	
			i4RetValue = i2c_master_recv(g_pstI2Cclient2, (char *)a_pRecvData, a_sizeRecvData);
			if (i4RetValue != a_sizeRecvData) {
				PK_ERR("[CAMERA SENSOR] I2C read failed!!\n");
				return -1;
			}
		}
		return 0;
	}
这一步完成I2c的读取,也就是说如果I2c配置正确,并且上电正确,到这一步就可以正确的读取ID,整

个camera也就基本就调通了。

接下来详细分析一下 I2c的读写程序 iReadRegI2C & iWriteRegI2C 


先来看看I2C的读取函数:
/****************************************************************************
功能:读取从机数据
iReadRegI2C 函数调用 i2c_master_send 函数来发送从机寄存器地址,接着调用 i2c_master_recv 函数来发送读地址并读取寄存器中的值。
参数:
a_pSendData :寄存器的地址
a_sizeSendData :寄存器地址的字节数
a_pRecvData :读取数据存放区
a_sizeRecvData :读取数据字节数
i2cId :读地址,I2C地址
***************************************************************************/

	static void write_cmos_sensor(kal_uint32 addr, kal_uint32 para)
	{
	#if 1
			char pu_send_cmd[2] = {(char)(addr & 0xFF), (char)(para & 0xFF)};
			iWriteRegI2C(pu_send_cmd, 2, imgsensor.i2c_write_id);
	#else
			iWriteReg((u16)addr, (u32)para, 2, imgsensor.i2c_write_id);
	#endif
	
	}


	/*******************************************************************************
	* iWriteRegI2C
	********************************************************************************/
	int iWriteRegI2C(u8 *a_pSendData, u16 a_sizeSendData, u16 i2cId)
	{
		int i4RetValue = 0;
		int retry = 3;
	
	/* PK_DBG("Addr : 0x%x,Val : 0x%x\n",a_u2Addr,a_u4Data); */
	
		/* KD_IMGSENSOR_PROFILE_INIT(); */
		spin_lock(&kdsensor_drv_lock);
		if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) {
			g_pstI2Cclient->addr = (i2cId >> 1);
			g_pstI2Cclient->ext_flag = (g_pstI2Cclient->ext_flag) & (~I2C_DMA_FLAG);
		} else {
			g_pstI2Cclient2->addr = (i2cId >> 1);
			g_pstI2Cclient2->ext_flag = (g_pstI2Cclient2->ext_flag) & (~I2C_DMA_FLAG);
		}
		spin_unlock(&kdsensor_drv_lock);
		/*  */
	
		do {
			if (gI2CBusNum == SUPPORT_I2C_BUS_NUM1) {
				i4RetValue = i2c_master_send(g_pstI2Cclient, a_pSendData, a_sizeSendData);
			} else {
				i4RetValue = i2c_master_send(g_pstI2Cclient2, a_pSendData, a_sizeSendData);
			}
			if (i4RetValue != a_sizeSendData) {
				PK_DBG("[CAMERA SENSOR] I2C send failed!!, Addr = 0x%x, Data = 0x%x\n",
					a_pSendData[0], a_pSendData[1]);
			} else {
				break;
			}
			uDELAY(50);
		} while ((retry--) > 0);
		/* KD_IMGSENSOR_PROFILE("iWriteRegI2C"); */
		return 0;
	}
/****************************************************************************
功能:向从机写入数据
iWriteRegI2C 函数调用 i2c_master_send 函数来发送从机寄存器地址和要写入该寄存器的数据。
参数:
a_pSendData :要写入的数据(包括寄存器地址和写入寄存器的数据)
a_sizeSendData :发送数据字节数
i2cId :写地址,I2C地址
***************************************************************************/

接下来,追溯两个重要函数 i2c_master_send 和 i2c_master_recv 函数。
kernel-3.18/drivers/i2c/i2c-core.c
	/**
	* i2c_master_send - issue a single I2C message in master transmit mode 
	* @client: Handle to slave device
	* @buf: Data that will be written to the slave
	* @count: How many bytes to write, must be less than 64k since msg.len is u16
	*
	* Returns negative errno, or else the number of bytes written.
	*/
	int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
	{
		int ret;
		struct i2c_adapter *adap = client->adapter;
		struct i2c_msg msg;
	
		msg.addr = client->addr;
		msg.flags = client->flags & I2C_M_TEN;
		msg.len = count;
		msg.buf = (char *)buf;
	#ifdef CONFIG_MTK_I2C_EXTENSION
		msg.timing = client->timing;
		msg.ext_flag = client->ext_flag;
	#endif
	
		ret = i2c_transfer(adap, &msg, 1);
	
		/*
		* If everything went ok (i.e. 1 msg transmitted), return #bytes
		* transmitted, else error code.
		*/
		return (ret == 1) ? count : ret;
	}
	EXPORT_SYMBOL(i2c_master_send);

	/**
	* i2c_master_recv - issue a single I2C message in master receive mode
	* @client: Handle to slave device
	* @buf: Where to store data read from slave
	* @count: How many bytes to read, must be less than 64k since msg.len is u16
	*
	* Returns negative errno, or else the number of bytes read.
	*/
	int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
	{
		struct i2c_adapter *adap = client->adapter;
		struct i2c_msg msg;
		int ret;
	
		msg.addr = client->addr;
		msg.flags = client->flags & I2C_M_TEN;
		msg.flags |= I2C_M_RD;
		msg.len = count;
		msg.buf = buf;
	#ifdef CONFIG_MTK_I2C_EXTENSION
		msg.timing = client->timing;
		msg.ext_flag = client->ext_flag;
	#endif
	
		ret = i2c_transfer(adap, &msg, 1);
	
		/*
		* If everything went ok (i.e. 1 msg received), return #bytes received,
		* else error code.
		*/
		return (ret == 1) ? count : ret;
	}
	EXPORT_SYMBOL(i2c_master_recv);

从源代码中我们可以看出 i2c_master_recv 和 i2c_master_send 函数都是对 single I2C message 进行处理的,
即 msg 结构体中只有一个消息要处理。对于前面的 iReadRegI2C 函数,它读取数据需要处理两个消息(一条写消息,
一条读消息)。
可以看出 i2c_master_recv 和 i2c_master_send 函数它最终都会调用到 i2c_transfer 函数,因为所有读写消息都会传递给
i2c_transfer 处理。 i2c_transfer 函数本身不具备驱动适配器物理硬件完成消息交互的能力,
它只是寻找到 i2c_adapter 对应的 i2c_algorithm ,并使用 i2c_algorithm 的 master_xfer() 函数真正驱动硬件流程。
i2c_transfer 处理消息机制:
非 restart 模式下, i2c_transfer 函数所引发的对数据读写时序,它对每一条消息的处理都会引发开始和停止信号,
有多少条消息就会出现多少个开始和停止信号。camera imagesensor 中的i2c读写函数都是工作在非restart模式下的.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人在路上……

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值