MTK Camera 上电流程简析

一:硬件
二:Camera image sensor驱动模块驱动加载
三:上电分析

一 硬件


二 : Camera image sensor驱动模块驱动加载

分五步走:

//HAl层命令通道
static long CAMERA_HW_Ioctl(
	struct file *a_pstFile,
	unsigned int a_u4Command,
	unsigned long a_u4Param
)
{

	switch (a_u4Command) {

	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;

	}

	return i4RetValue;
}
******************************************
第五步: 汇集于IOCTL

static long CAMERA_HW_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg)
{
  ...
    /* Data in the following commands is not required to be converted to kernel 64-bit & user 32-bit */
    case KDIMGSENSORIOC_T_OPEN:
    case KDIMGSENSORIOC_T_CLOSE:
    case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
    case KDIMGSENSORIOC_X_SET_DRIVER:
    case KDIMGSENSORIOC_X_GET_SOCKET_POS:
    case KDIMGSENSORIOC_X_SET_I2CBUS:
    case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK:
    case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE:
    case KDIMGSENSORIOC_X_SET_MCLK_PLL:
    case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:
    case KDIMGSENSORIOC_X_SET_GPIO:
    case KDIMGSENSORIOC_X_GET_ISP_CLK:
    return filp->f_op->unlocked_ioctl(filp, cmd, arg);

    default:
    return -ENOIOCTLCMD;
    }
}


***********************************************************************************************

第四步 : 分别实现自己的字符设备注册函数以及fops结构体,可以注意到 两个fops指向同一个 ioctl

//主摄像头字符设备 fops
static const struct file_operations g_stCAMERA_HW_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

};

//副摄像头字符设备 fops
static const struct file_operations g_stCAMERA_HW_fops0 = {
	.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

};


//主摄像头字符设备 注册函数
static inline int RegisterCAMERA_HWCharDrv(void)
{


...常规字符设备创建过程...

	/* 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;
	}
	//创建目录 /sys/class/sensordrv/
	sensor_class = class_create(THIS_MODULE, "sensordrv");
	if (IS_ERR(sensor_class)) {
		int ret = PTR_ERR(sensor_class);
		PK_DBG("Unable to create class, err = %d\n", ret);
		return ret;
	}
	//创建目录/sys/class/sensordrv/kd_camera_hw
	sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1);

	return 0;
}

//副摄像头字符设备 注册函数
static inline int RegisterCAMERA_HWCharDrv2(void)
{
	...常规字符设备创建过程...

	/* Attatch file operation. */
	cdev_init(g_pCAMERA_HW_CharDrv2, &g_stCAMERA_HW_fops0);

	g_pCAMERA_HW_CharDrv2->owner = THIS_MODULE;

	/* Add to system */
	if (cdev_add(g_pCAMERA_HW_CharDrv2, g_CAMERA_HWdevno2, 1)) {
		PK_DBG("[mt6516_IDP] Attatch file operation failed\n");

		unregister_chrdev_region(g_CAMERA_HWdevno2, 1);

		return -EAGAIN;
	}
	//创建目录 /sys/class/sensordrv2/
	sensor2_class = class_create(THIS_MODULE, "sensordrv2");
	if (IS_ERR(sensor2_class)) {
		int ret = PTR_ERR(sensor2_class);
		PK_DBG("Unable to create class, err = %d\n", ret);
		return ret;
	}
	//创建目录/sys/class/sensordrv/kd_camera_hw_bus2
	sensor_device = device_create(sensor2_class, NULL, g_CAMERA_HWdevno2, NULL, CAMERA_HW_DRVNAME2);

	return 0;
}

***********************************************************************************************

第三步: 在i2c prob()中分别注册字符设备驱动

static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	/* Register char driver  注册字符设备驱动 */
	i4RetValue = RegisterCAMERA_HWCharDrv();
}


static int CAMERA_HW_i2c_probe2(struct i2c_client *client, const struct i2c_device_id *id)
{
	/* Register char driver 注册字符设备驱动*/
	i4RetValue = RegisterCAMERA_HWCharDrv2();
}


*************************************************************************************************

第二步:在平台prob()中分别注册自己的I2C驱动,匹配cust_i2c.dtsi 中的i2c设备 mediatek,camera_main 以及 mediatek,camera_sub ,成功则调用各自的 i2c prob()


//主摄像头I2C设备
    static const struct of_device_id CAMERA_HW_i2c_of_ids[] = {
	    { .compatible = "mediatek,camera_main", },
	    {}
    };

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,
		.of_match_table = CAMERA_HW_i2c_of_ids,
	},
	.id_table = CAMERA_HW_i2c_id,
};


//副摄像头I2C设备
    static const struct of_device_id CAMERA_HW2_i2c_driver_of_ids[] = {
	{ .compatible = "mediatek,camera_sub", },
	{}
    };


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,
    .of_match_table = CAMERA_HW2_i2c_driver_of_ids,
    },
    .id_table = CAMERA_HW_i2c_id2,
};


static int CAMERA_HW_probe(struct platform_device *pdev)
{

    return i2c_add_driver(&CAMERA_HW_i2c_driver);
}


static int CAMERA_HW_probe2(struct platform_device *pdev)
{
	return i2c_add_driver(&CAMERA_HW_i2c_driver2);
}

***************************************************************************************************

第一步 :CAMERA_HW_i2C_init中初始化,注册平台驱动,并且匹配dts mt6735.dtsi 中的平台设备 mediatek,camera_hw 以及 mediatek,camera_hw2,成功则调用 prob()

//主摄像头平台驱动 以及 匹配设备
static const struct of_device_id CAMERA_HW_of_ids[] = {
	{ .compatible = "mediatek,camera_hw", },
	{}
};
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
	}
};

//副像头平台驱动 以及 匹配设备
static const struct of_device_id CAMERA_HW2_of_ids[] = {
    { .compatible = "mediatek,camera_hw2", },
    {}
};
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

	}
};

static int __init CAMERA_HW_i2C_init(void)
{
	//注册i2c设备
    i2c_register_board_info(SUPPORT_I2C_BUS_NUM1, &i2c_devs1, 1);
    i2c_register_board_info(SUPPORT_I2C_BUS_NUM2, &i2c_devs2, 1);

	//注册平台驱动
	platform_driver_register(&g_stCAMERA_HW_Driver)) 
	platform_driver_register(&g_stCAMERA_HW_Driver2)) 
}



module_init(CAMERA_HW_i2C_init);
module_exit(CAMERA_HW_i2C_exit);

cust_i2c.dtsi
	{

		&i2c0 {
			camera_main@10 {
				compatible = "mediatek,camera_main";
				reg = <0x10>;
			};

			camera_sub@3c {
				compatible = "mediatek,camera_sub";
				reg = <0x3c>;
			};

		};


	}





mt6735.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_vcam_af_ldo_reg>;
		                vcamio-supply = <&mt_pmic_vcam_io_ldo_reg>;
		                /* Camera Common Clock Framework (CCF) */
		                clocks = <&topckgen TOP_MUX_CAMTG>,
		                <&topckgen TOP_UNIVPLL_D26>,
		                <&topckgen TOP_UNIVPLL2_D2>;
		                clock-names = "TOP_CAMTG_SEL","TOP_UNIVPLL_D26","TOP_UNIVPLL2_D2";
		        };

		        kd_camera_hw2:kd_camera_hw2@15008000 {
		                compatible = "mediatek,camera_hw2";
		                reg = <0x15008000 0x1000>;  /* SENINF_ADDR */
		        };


	}



xxxxx.dts
	{

		&kd_camera_hw1 {
			pinctrl-names = "default", "cam0_rst0", "cam0_rst1", "cam0_pnd0", "cam0_pnd1",
			"cam1_rst0", "cam1_rst1", "cam1_pnd0", "cam1_pnd1",
			"cam_ldo0_0", "cam_ldo0_1";
			pinctrl-0 = <&camera_pins_default>;
			pinctrl-1 = <&camera_pins_cam0_rst0>;
			pinctrl-2 = <&camera_pins_cam0_rst1>;
			pinctrl-3 = <&camera_pins_cam0_pnd0>;
			pinctrl-4 = <&camera_pins_cam0_pnd1>;
			pinctrl-5 = <&camera_pins_cam1_rst0>;
			pinctrl-6 = <&camera_pins_cam1_rst1>;
			pinctrl-7 = <&camera_pins_cam1_pnd0>;
			pinctrl-8 = <&camera_pins_cam1_pnd1>;
			pinctrl-9 = <&camera_pins_cam_ldo0_0>;
			pinctrl-10 = <&camera_pins_cam_ldo0_1>;
			status = "okay";

		};

	}

三 上电分析

MTK Camera驱动 kernel 中的部分 大致分为两层,核心层和设备层。

核心层又分为两小部分:

  1. 核心逻辑 :
    kernel/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.c //与HAL层通信交互
    kernel/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.h
    kernel/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_define.h

  2. 设备上电 :
    kernel/drivers/misc/mediatek/imgsensor/src/mt6735/camera_hw/kd_camera_hw.c //抽象出来的上电操作

设备层:sensor 驱动,寄存器操作
如:kernel/drivers/misc/mediatek/imgsensor/src/mt6735/camera_project/xxx/gc2023_mipi_raw/gc2023mipi_Sensor.c

关键数据结构之间的关系:

kernel-3.18/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_define.h 中定义了 

struct MULTI_SENSOR_FUNCTION_STRUCT2: 用于保存系统中的Sensor的操作方法,如 open 等等
struct SENSOR_FUNCTION_STRUCT : 用于保存系统中的Sensor的操作方法,如 open 等等
struct ACDK_KD_SENSOR_INIT_FUNCTION_STRU : 用于保存系统中Sensor 的 Name、ID、Init()信息

问题:SENSOR_FUNCTION_STRUCT 和 MULTI_SENSOR_FUNCTION_STRUCT2 是一样的,为什么要重复定义呢?

答案:

MULTI_SENSOR_FUNCTION_STRUCT2 主要用于 核心层 kd_sensorlist.c中,kd_sensorlist.c中同样封装了一个新的 MULTI_SENSOR_FUNCTION_STRUCT2,用于保存系统中的Sensor的操作方法,如 open。只是这些操作是核心层的操作,是整个系统的所有Camera 共用的,在这里面可以打开底层各个设备的 SENSOR_FUNCTION_STRUC操作方法集合。SENSOR_FUNCTION_STRUCT 主要用于 设备层,设备层用SENSOR_FUNCTION_STRUCT封装操作自己的方法,供上层调用,这里指的上层就是 核心层。

kd_sensorlist.c : MULTI_SENSOR_FUNCTION_STRUCT2.open
		 调用
gc2023mipi_Sensor.c : SENSOR_FUNCTION_STRUCT sensor_func.open

kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.h 中定义了

ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
{
	...
#if defined(GC2023_MIPI_YUV)
    {GC2023MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2023_MIPI_YUV,GC2023MIPISensorInit},
#endif
	...
}

ACDK_KD_SENSOR_INIT_FUNCTION_STRUC定义于 kd_imgsensor_define.h。用于保存 Sensor ID Name Init函数 等信息。这里的定义的结构体数组包含了系统所有的Camera的 名称 ID 初始化函数的集合是系统 camera 信息表。如 : {GC2023MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2023_MIPI_YUV,GC2023MIPISensorInit},该数组元素的第一个项表示ID,第二项表示名称,第三项表示初始化函数。

总结:

系统首先是发送 IOCTL: KDIMGSENSORIOC_X_SET_DRIVER。这里面主要的工作是 定义一个 ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT指针 然后调用 kdGetSensorInitFuncList()获取 kd_sensorlist.h中
定义的 kdSensorList[]系统 camera 信息表,接着便利该表,根据SensorID 绑定 核心层的SENSOR_FUNCTION_STRUCT *g_pInvokeSensorFunc 与 设备层的 SENSOR_FUNCTION_STRUCT sensor_func,这样就可以直接操作设备层的SENSOR_FUNCTION_STRUCT中的方法了。

然后发送 IOCTL: KDIMGSENSORIOC_T_OPEN 等一些列 IOCTL(),此时可以直接操作设备层中的方法了

我们主要分析 KDIMGSENSORIOC_T_OPEN和 KDIMGSENSORIOC_X_SET_DRIVER两个ioctl:


KDIMGSENSORIOC_X_SET_DRIVER 流程:

1 Hal层发送 ioctl(m_fdSensor, KDIMGSENSORIOC_X_SET_DRIVER, &sensorIdx); 

2 Kernel 接受 KDIMGSENSORIOC_X_SET_DRIVER指令,调用 kdSetDriver((unsigned int *)pBuff)

3 
	3.1 在本地创建 ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
		说明:结构体 ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT 定义在 kernel-3.18/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_define.h中,用于保存Camera的 ID、Name、Init函数 等信息
			该结构体于 kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.h 创建  ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1]
			结构体数组,理解为系统Camera信息表,用于保存整个系统的 Camera 的 ID、Name、Init函数 等信息。
		
	3.2 kdGetSensorInitFuncList(&pSensorList) : 
		说明:获得 dSensorList[] 数组首地址,将 pSensorList指针 指向 src/kd_sensorlist.h里面 ,获取 kd_sensorlist.h中定义的系统Camera信息表。
			ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] 变量的首地址。即获取初始化列表地址

	3.3 g_bEnableDriver[i] = FALSE; 
		说明:先将 g_bEnableDriver[i]设置为 false

	3.4 g_invokeSocketIdx[i] = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_MSB) >> KDIMGSENSOR_DUAL_SHIFT);
		说明:保存 camera的sensorId
		
	3.5 if (NULL == pSensorList[drvIdx[i]].SensorInit)
		说明:判断模块驱动的init函数是否为NULL

	3.6 pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);
		说明:传递 &g_pInvokeSensorFunc[i] 为参数,其中还是传递的地址,这就将g_pInvokeSensorFunc的首地址指向了模块驱动函数中的UINT32 GC2023MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)这个函数
			调用模块驱动中的init函数,将 g_pInvokeSensorFunc[sensor]指针指向 sensor模组的 SENSOR_FUNCTION_STRUCT。即绑定 sensor模组的 SENSOR_FUNCTION_STRUCT。

	3.7 g_bEnableDriver[i] = TRUE;
		说明:将 g_bEnableDrive[i] 设置为TRUE,表示与该g_bEnableDriver[i]对应的 sensor 可用。

KDIMGSENSORIOC_T_OPEN 流程:

1 Hal层发送 ioctl(m_fdSensor, KDIMGSENSORIOC_T_OPEN, &sensorIdx); 

2 Kernel 接受 KDIMGSENSORIOC_X_SET_DRIVER指令,调用 adopt_CAMERA_HW_Open()

3 adopt_CAMERA_HW_Open()中
	
	3.1 if (g_pSensorFunc) 
	说明:判断我们 imagesensor 操作函数指针是否为NULL,如果为NULL,报错,因为我们就是靠这个操作函数集合去操作imagesensor 的 
	
	3.2 err = g_pSensorFunc->SensorOpen();
	说明:会调用到 kd_MultiSensorFunc 里面的 kd_MultiSensorOpen 函数

4 MUINT32 kd_MultiSensorOpen(void)中
	4.1 if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) 
	说明:
		4.1.1 g_bEnableDriver g_pInvokeSensorFunc[i] 这两个变量都为true时,就对sensor进行上电,然后就通过ret =g_pInvokeSensorFunc[i]->SensorOpen()进入到了模块sensor驱动中的open函数。

		4.1.2 这里可以看出hal调用ioctl命令时不可能先走 KDIMGSENSORIOC_T_OPEN 这个命令,因为此时 g_pInvokeSensorFunc 为 NULL,还没有绑定到模组的 SENSOR_FUNCTION_STRUCT sensor_func。
		所以这里代码无法执行,由后面的代码可以看到,ioctl先走的cmd命令是 KDIMGSENSORIOC_X_SET_DRIVER,在 KDIMGSENSORIOC_X_SET_DRIVER里面对 g_pInvokeSensorFunc进行初始化。

		4.1.3 于上电跟掉电函数 kdCISModulePowerOn,在 kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/camera_project/xxxx/camera_hw/kd_camera_hw.c文件中,其实上电跟掉电时序就是
			配置一些GPIO口,然后在把camera的三路电压按dateshell配置一下上掉电的时间。
	
	4.2 ret = kdCISModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_invokeSocketIdx[i], (char *)g_invokeSensorNameStr[i], true, CAMERA_HW_DRVNAME1); 
	说明:上电

	4.3 ret = g_pInvokeSensorFunc[i]->SensorOpen();
	说明:调用到模块驱动中的open函数,g_pInvokeSensorFunc[i]保存的值为模块驱动中的static SENSOR_FUNCTION_STRUCT sensor_func这个结构体的指针(地址)

分析代码如下:罗列了主要的代码和数据结构。

kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.c

/*
MULTI_SENSOR_FUNCTION_STRUCT2 和 SENSOR_FUNCTION_STRUCT一样,只不过为了把驱动抽象出来,核心层用MULTI_SENSOR_FUNCTION_STRUCT2。模组驱动层用MULTI_SENSOR_FUNCTION_STRUCT,
上电时会将这两个结构体绑定
*/
MULTI_SENSOR_FUNCTION_STRUCT2  kd_MultiSensorFunc = {
	kd_MultiSensorOpen,
	kd_MultiSensorGetInfo,
	kd_MultiSensorGetResolution,
	kd_MultiSensorFeatureControl,
	kd_MultiSensorControl,
	kd_MultiSensorClose
};


extern MULTI_SENSOR_FUNCTION_STRUCT2 kd_MultiSensorFunc;//imagesensor 操作函数集合
static MULTI_SENSOR_FUNCTION_STRUCT2 *g_pSensorFunc = &kd_MultiSensorFunc;//imagesensor 操作函数指针


/*
1 g_bEnableDriver 定义为一个bool型的变量
2 g_pInvokeSensorFunc 地址跟模块驱动中的 static SENSOR_FUNCTION_STRUCT sensor_func 这个地址指向是相同的,他是作为一个参数传递来被调用的.
3 这两个变量都为true时,就对sensor进行上电,然后就通过ret =g_pInvokeSensorFunc[i]->SensorOpen()进入到了模块sensor驱动中的open函数。
	至于上电跟掉电函数 kdCISModulePowerOn,在 kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/camera_project/xxxx/camera_hw/kd_camera_hw.c文件中,其实上电跟掉电时序就是
	配置一些GPIO口,然后在把camera的三路电压按dateshell配置一下上掉电的时间。
*/
BOOL g_bEnableDriver[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {FALSE, FALSE};
SENSOR_FUNCTION_STRUCT *g_pInvokeSensorFunc[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {NULL, NULL};

CAMERA_DUAL_CAMERA_SENSOR_ENUM g_invokeSocketIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {DUAL_CAMERA_NONE_SENSOR, DUAL_CAMERA_NONE_SENSOR};


MUINT32 kd_MultiSensorOpen(void)
{
	MUINT32 ret = ERROR_NONE;
	MINT32 i = 0;

	/* 计算当前时间 */
	KD_MULTI_FUNCTION_ENTRY();

	for (i = (KDIMGSENSOR_MAX_INVOKE_DRIVERS - 1); i >= KDIMGSENSOR_INVOKE_DRIVER_0; i--) {

		/*
		1 g_bEnableDriver g_pInvokeSensorFunc[i] 这两个变量都为true时,就对sensor进行上电,然后就通过ret =g_pInvokeSensorFunc[i]->SensorOpen()进入到了模块sensor驱动中的open函数。
		2 于上电跟掉电函数 kdCISModulePowerOn,在 kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/camera_project/xxxx/camera_hw/kd_camera_hw.c文件中,其实上电跟掉电时序就是
			配置一些GPIO口,然后在把camera的三路电压按dateshell配置一下上掉电的时间。

		3.这里可以看出hal调用ioctl命令时不可能先走 KDIMGSENSORIOC_T_OPEN 这个命令,因为此时 g_pInvokeSensorFunc 为 NULL,还没有绑定到模组的 SENSOR_FUNCTION_STRUCT sensor_func。
		所以这里代码无法执行,由后面的代码可以看到,ioctl先走的cmd命令是 KDIMGSENSORIOC_X_SET_DRIVER,在 KDIMGSENSORIOC_X_SET_DRIVER里面对 g_pInvokeSensorFunc进行初始化。

		*/
		if (g_bEnableDriver[i] && g_pInvokeSensorFunc[i]) {
			if (0 != (g_CurrentSensorIdx & g_invokeSocketIdx[i])) {
#ifndef CONFIG_FPGA_EARLY_PORTING

				/*上电*/
				ret = kdCISModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_invokeSocketIdx[i], (char *)g_invokeSensorNameStr[i], true, CAMERA_HW_DRVNAME1);
#endif
	
				/* wait for power stable 等待电源稳定*/
				mDELAY(10);

				//调用到模块驱动中的open函数,g_pInvokeSensorFunc[i]保存的值为模块驱动中的static SENSOR_FUNCTION_STRUCT sensor_func这个结构体的指针(地址)
				ret = g_pInvokeSensorFunc[i]->SensorOpen();
				if (ERROR_NONE != ret) {
#ifndef CONFIG_FPGA_EARLY_PORTING
					/*掉电*/
					kdCISModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_invokeSocketIdx[i], (char *)g_invokeSensorNameStr[i], false, CAMERA_HW_DRVNAME1);
#endif
					PK_ERR("SensorOpen");
					return ret;
				}

			}
		}
	}
	KD_MULTI_FUNCTION_EXIT();
	return ERROR_NONE;
}


static inline int adopt_CAMERA_HW_Open(void)
{
	UINT32 err = 0;

	/*
	1.判断我们 imagesensor 操作函数指针是否为NULL,如果为NULL,报错,因为我们就是靠这个操作函数集合去操作imagesensor 的 
	*/
	if (g_pSensorFunc) {
		err = g_pSensorFunc->SensorOpen();// 会调用到 kd_MultiSensorFunc 里面的 kd_MultiSensorOpen 函数
	} 
} 


UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
{
	/* 获取 kdSensorList[] 数组首地址  kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.h  
	如:

	UINT32 GC2023MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc);
	...
	ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] = {

		...

		#if defined(GC2023_MIPI_YUV)
		    {GC2023MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2023_MIPI_YUV,GC2023MIPISensorInit},
		...
	}

	*/
	/*
	 kdSensorList在kd_sensorlist.h文件里面,就是保存 cameraId,cameraNmae,模块驱动人口函数的结构体
	*/
	*ppSensorList = &kdSensorList[0];
	return 0;
}



int kdSetDriver(unsigned int *pDrvIndex)
{
	/* ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList 保存 Sensor的 ID Name Init函数信息 */
	ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;

	u32 drvIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0, 0};
	u32 i;


	/* Camera information */
	gDrvIndex = pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0];

	/* 
	首先获得dSensorList[]数组首地址,将 pSensorList指针 指向 src/kd_sensorlist.h里面 
	ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] 变量的首地址。即获取初始化列表地址
	*/	
	if (0 != kdGetSensorInitFuncList(&pSensorList)) {
		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_bEnableDriver[i] = FALSE;

		// 保存camera的sensorId
		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 (MAX_NUM_OF_SUPPORT_SENSOR > drvIdx[i]) {
			/*
			判断模块驱动的init函数是否为NULL	
			*/
			if (NULL == pSensorList[drvIdx[i]].SensorInit) {
				PK_ERR("ERROR:kdSetDriver()\n");
				return -EIO;
			}

			/*
			传递 &g_pInvokeSensorFunc[i] 为参数,其中还是传递的地址,这就将g_pInvokeSensorFunc的首地址指向了模块驱动函数中的UINT32 GC2023MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)这个函数
			调用模块驱动中的init函数,将 g_pInvokeSensorFunc[sensor]指针指向 sensor模组的 SENSOR_FUNCTION_STRUCT。即绑定 sensor模组的 SENSOR_FUNCTION_STRUCT。
			*/
			pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);

			/*
			将 g_bEnableDrive[i] 设置为TRUE,表示与该g_bEnableDriver[i]对应的 sensor 可用。
			*/
			g_bEnableDriver[i] = TRUE;

			/* 获取Sensor Name */
			memcpy((char *)g_invokeSensorNameStr[i], (char *)pSensorList[drvIdx[i]].drvname, sizeof(pSensorList[drvIdx[i]].drvname));

		}
	}
	return 0;
}



int kdSetCurrentSensorIdx(unsigned int idx)
{
	g_CurrentSensorIdx = idx;
	return 0;
}



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

	switch (a_u4Command) {
		//open
	case KDIMGSENSORIOC_T_OPEN:
		i4RetValue = adopt_CAMERA_HW_Open();
		break;

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

	case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:
		i4RetValue = kdSetCurrentSensorIdx(*pIdx);
		break;

}




static long CAMERA_HW_Ioctl_Compat(struct file *filp, unsigned int cmd, unsigned long arg)
{
   

    case KDIMGSENSORIOC_T_OPEN://开
    case KDIMGSENSORIOC_T_CLOSE:
    case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
    case KDIMGSENSORIOC_X_SET_DRIVER:
    case KDIMGSENSORIOC_X_GET_SOCKET_POS:
    case KDIMGSENSORIOC_X_SET_I2CBUS:
    case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK:
    case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE:
    case KDIMGSENSORIOC_X_SET_MCLK_PLL:
    case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:
    case KDIMGSENSORIOC_X_SET_GPIO:
    case KDIMGSENSORIOC_X_GET_ISP_CLK:
    return filp->f_op->unlocked_ioctl(filp, cmd, arg);

    default:
    return -ENOIOCTLCMD;
    }
}


//主摄像头字符设备 fops
static const struct file_operations g_stCAMERA_HW_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

};

//副摄像头字符设备 fops
static const struct file_operations g_stCAMERA_HW_fops0 = {
	.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

};

kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/kd_sensorlist.h

	...
UINT32 GC2023MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc);
	...
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
{
	...
#if defined(GC2023_MIPI_YUV)
    {GC2023MIPI_SENSOR_ID, SENSOR_DRVNAME_GC2023_MIPI_YUV,GC2023MIPISensorInit},
#endif
	...
}
	...

kernel-3.18/drivers/misc/mediatek/imgsensor/inc/kd_imgsensor_define.h

typedef struct {
	MUINT32(*SensorOpen)(void);
	MUINT32(*SensorGetInfo)(MUINT32 *pScenarioId[2], MSDK_SENSOR_INFO_STRUCT * pSensorInfo[2], MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData[2]);
	MUINT32(*SensorGetResolution)(MSDK_SENSOR_RESOLUTION_INFO_STRUCT * pSensorResolution[2]);
	MUINT32(*SensorFeatureControl)(CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera, MSDK_SENSOR_FEATURE_ENUM FeatureId, MUINT8 *pFeaturePara, MUINT32 *pFeatureParaLen);
	MUINT32(*SensorControl)(CAMERA_DUAL_CAMERA_SENSOR_ENUM InvokeCamera, MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData);
	MUINT32(*SensorClose)(void);
} MULTI_SENSOR_FUNCTION_STRUCT2, *PMULTI_SENSOR_FUNCTION_STRUCT2;


typedef struct {
        MUINT32(*SensorOpen)(void);
        MUINT32(*SensorGetInfo)(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_INFO_STRUCT *pSensorInfo,
                                MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData);
        MUINT32(*SensorGetResolution)(MSDK_SENSOR_RESOLUTION_INFO_STRUCT *pSensorResolution);
        MUINT32(*SensorFeatureControl)(MSDK_SENSOR_FEATURE_ENUM FeatureId, MUINT8 *pFeaturePara, MUINT32 *pFeatureParaLen);
        MUINT32(*SensorControl)(MSDK_SCENARIO_ID_ENUM ScenarioId, MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT *pImageWindow, MSDK_SENSOR_CONFIG_STRUCT *pSensorConfigData);
        MUINT32(*SensorClose)(void);
#if 1 /* isp suspend resume patch */
        MSDK_SCENARIO_ID_ENUM ScenarioId;
        MSDK_SENSOR_EXPOSURE_WINDOW_STRUCT imageWindow;
        MSDK_SENSOR_CONFIG_STRUCT sensorConfigData;
#endif
} SENSOR_FUNCTION_STRUCT, *PSENSOR_FUNCTION_STRUCT;


//保存 Sensor ID Name Init函数 等信息
typedef struct {
        MUINT32 SensorId;
        MUINT8 drvname[32];
        MUINT32(*SensorInit)(PSENSOR_FUNCTION_STRUCT *pfFunc);
} ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT, *PACDK_KD_SENSOR_INIT_FUNCTION_STRUCT;

kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/camera_hw/kd_camera_hw.c

int kdCISModulePowerOn(CAMERA_DUAL_CAMERA_SENSOR_ENUM SensorIdx, char *currSensorName, bool On, char *mode_name)
{

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

	...

	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;


	//通过DriverName来区分SensorIC ...
		如: currSensorName && (0 == strcmp(SENSOR_DRVNAME_IMX258_MIPI_RAW, currSensorName)
	//上电操作 ...
}

kernel-3.18/drivers/misc/mediatek/imgsensor/src/mt6735/camera_project/xxxx/gc2023_mipi_raw/gc2023mipi_Sensor.c

static SENSOR_FUNCTION_STRUCT sensor_func = {
    open,
    get_info,
    get_resolution,
    feature_control,
    control,
    close
};

//将 GC2023驱动指针 赋值给  static SENSOR_FUNCTION_STRUCT sensor_func。同理就是后面在通用驱动中可以直接凭借pfun指针调用sensorlist中的驱动中的各个功能函数
UINT32 GC2023MIPISensorInit(PSENSOR_FUNCTION_STRUCT *pfFunc)
{
    /* To Do : Check Sensor status here */
    if (pfFunc!=NULL)
        *pfFunc=&sensor_func;
    return ERROR_NONE;
}    /*    GC2023MIPI_RAW_SensorInit    */
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Linux老A

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

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

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

打赏作者

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

抵扣说明:

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

余额充值