一、Camera驱动的初始化
1. 支持的摄像头列表
在-->ProjectConfig.mk 配置文件中 可查看所支持的摄像头驱动:
CUSTOM_HAL_IMGSENSOR =sp2518_yuv sp0a19_yuv gc2155_yuvgc0328_yuv gc03091_yuv gc0309_yuvgc2035_yuv
CUSTOM_HAL_MAIN_IMGSENSOR =sp2518_yuv gc2155_yuv gc03091_yuvgc2035_yuv
CUSTOM_HAL_SUB_IMGSENSOR = sp0a19_yuv gc0328_yuv gc0309_yuv
CUSTOM_KERNEL_IMGSENSOR =sp2518_yuv sp0a19_yuv gc2155_yuvgc0328_yuv gc03091_yuv gc0309_yuvgc2035_yuv
CUSTOM_KERNEL_MAIN_IMGSENSOR = sp2518_yuv gc2155_yuv gc03091_yuvgc2035_yuv
CUSTOM_KERNEL_SUB_IMGSENSOR = sp0a19_yuv gc0328_yuv gc0309_yuv
在-->kd_sensorlist.h 文件中添加的Sensor会在开机启动时扫描
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR+1] =
{
#if defined(GC2035_YUV) //jiang add
{GC2035_SENSOR_ID, SENSOR_DRVNAME_GC2035_YUV,GC2035_YUV_SensorInit},-->此参数为驱动的操作函数接口初始化
#endif
#if defined(GC0328_YUV)
{GC0328_SENSOR_ID, SENSOR_DRVNAME_GC0328_YUV,GC0328_YUV_SensorInit},
#endif
...
{0,{0},NULL}, //end of list
}
我们添加Sensor时一般添加在数组的开头, 这样不会出现kenel 层与 hal 层数组Sensor顺序不一致的情况
2. 插入模块
在--> kd_sensorlist.c
由这两函数来实现模块的插拔,驱动流程的分析也从此函数开始
module_init(CAMERA_HW_i2C_init); -->模块插入
module_exit(CAMERA_HW_i2C_exit); -->模块拔出
1)、CAMERA_HW_i2C_init
static int __init CAMERA_HW_i2C_init(void)
{
i2c_register_board_info(SUPPORT_I2C_BUS_NUM1, &i2c_devs1, 1); -->注册一个i2c_device
platform_driver_register(&g_stCAMERA_HW_Driver); -->注册一个platform_driver --> 调用probe函数
}
2)、CAMERA_HW_probe
static int CAMERA_HW_probe(struct platform_device *pdev)
{
return i2c_add_driver(&CAMERA_HW_i2c_driver);-->注册一个i2c驱动 --> 调用i2c驱动的probe函数
}
3)、CAMERA_HW_i2c_probe
static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
spin_lock(&kdsensor_drv_lock); --> 加锁
g_pstI2Cclient = client; --> 获取client
g_pstI2Cclient->timing = 200; -->设置clock 200k
spin_unlock(&kdsensor_drv_lock); -->解锁
i4RetValue = RegisterCAMERA_HWCharDrv(); -->字符设备初始化
}
4)、字符设备初始化
inline static int RegisterCAMERA_HWCharDrv(void)
{
struct device* sensor_device = NULL;
#if CAMERA_HW_DYNAMIC_ALLOCATE_DEVNO
alloc_chrdev_region(&g_CAMERA_HWdevno, 0, 1,CAMERA_HW_DRVNAME1) ; -->动态分配 dev_no
#else
register_chrdev_region( g_CAMERA_HWdevno , 1 , CAMERA_HW_DRVNAME1) ;
#endif
g_pCAMERA_HW_CharDrv = cdev_alloc();-->分配设备内存
cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops); -->初始化设备
g_pCAMERA_HW_CharDrv->owner = THIS_MODULE;
cdev_add(g_pCAMERA_HW_CharDrv, g_CAMERA_HWdevno, 1);-->注册设备
sensor_class = class_create(THIS_MODULE, "sensordrv");-->创建设备节点
sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME1);
}
static const struct file_operations g_stCAMERA_HW_fops= -->字符设备的文件操作
{
.owner = THIS_MODULE,
.open = CAMERA_HW_Open, --> 只是把计数加1
.release = CAMERA_HW_Release,
.unlocked_ioctl = CAMERA_HW_Ioctl
};
5)、给上层提供硬件操作的接口
static long CAMERA_HW_Ioctl( struct file * a_pstFile,unsigned int a_u4Command, unsigned long a_u4Param)
{
pBuff = kmalloc(_IOC_SIZE(a_u4Command),GFP_KERNEL); -->给指针分配空间
copy_from_user(pBuff , (void *) a_u4Param, _IOC_SIZE(a_u4Command)
pIdx = (u32*)pBuff;
switch(a_u4Command) {
case KDIMGSENSORIOC_X_SET_DRIVER:
i4RetValue = kdSetDriver((unsigned int*)pBuff); -->通过name和ID匹配具体的sensor型号的驱动,区分主摄、次摄并初始化, 参数pDrvIndex是一个数组,他有两个成员,数组的前16位为后摄,前摄的下标(目前1、2)后16位为sensor的索引
break;
case KDIMGSENSORIOC_T_OPEN:
i4RetValue = adopt_CAMERA_HW_Open();
break;
case KDIMGSENSORIOC_X_FEATURECONCTROL:
i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff); -->在pBuff中调用具体的sensor的GetsensorID函数,存在就记录
break;
case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
i4RetValue = adopt_CAMERA_HW_CheckIsAlive(); -->读取器件的sensor ID来判断是否有硬件连上,给camera上电
break;
...
}
int kdSetDriver(unsigned int* pDrvIndex)
{
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
u32 drvIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0,0};
g_invokeSocketIdx[i] = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((pDrvIndex[i]& KDIMGSENSOR_DUAL_MASK_MSB)>>KDIMGSENSOR_DUAL_SHIFT);
drvIdx[i] = (pDrvIndex[i] & KDIMGSENSOR_DUAL_MASK_LSB); --> 位操作获取sensor的ID
pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]); -->调用init获取具体驱动的函数指针
}