原文地址:http://blog.chinaunix.net/uid-26009923-id-3999723.html
一.camera驱动的初始化
1. 支持的摄像头列表
在./mediatek/config/mobitek77_m01_ics2/ProjectConfig.mk中,
配置支持的摄像头驱动
-
CUSTOM_HAL_IMGSENSOR=ov5640_yuv s5k4e1ga_raw ov5647_raw gc2035_yuv gc0329_yuv
-
CUSTOM_HAL_MAIN_IMGSENSOR=ov5640_yuv s5k4e1ga_raw ov5647_raw #gc2035_yuv
-
CUSTOM_HAL_SUB_IMGSENSOR=gc2035_yuv gc0329_yuv
-
CUSTOM_KERNEL_IMGSENSOR=ov5640_yuv s5k4e1ga_raw ov5647_raw gc2035_yuv gc0329_yuv
-
CUSTOM_KERNEL_SUB_IMGSENSOR=gc2035_yuv gc0329_yuv
在 custom/common/kernel/imgsensor/src/kd_sensorlist.h或
在source/external/mhal/src/custom/common/kernel/imgsensor/kd_sensorlist.h 中
-
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT kdSensorList[] =
-
{
-
#if defined(GC2035_YUV)
-
{GC2035_SENSOR_ID, SENSOR_DRVNAME_GC2035_YUV, GC2035_YUV_SensorInit},
-
#endif
-
#if defined(OV5640_YUV)
-
{OV5640_SENSOR_ID, SENSOR_DRVNAME_OV5640_YUV, OV5640_YUV_SensorInit},
-
#endif
-
{0,{0},NULL},
-
};
2. module_init
在mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c中
module_init(CAMERA_HW_i2C_init);
//文件的开头,先声明I2C信息
static struct i2c_board_info __initdata kd_camera_dev={ I2C_BOARD_INFO("kd_camera_hw", 0xfe>>1)};
-
static int __init CAMERA_HW_i2C_init(void)
-
{
-
//注册i2c信息,下一步就可以调用i2c_add_driver
-
i2c_register_board_info(CAMERA_I2C_BUSNUM, &kd_camera_dev, 1);
-
//注册platform_driver然后调用probe函数CAMERA_HW_probe
-
platform_driver_register(&g_stCAMERA_HW_Driver);
-
//在proc目录中创建/proc/driver/camsensor调试信息
-
prEntry = create_proc_entry("driver/camsensor", 0, NULL);
-
prEntry->read_proc = CAMERA_HW_DumpReg_To_Proc;
-
prEntry->write_proc = CAMERA_HW_Reg_Debug;
-
-
//全局变量的初始化
-
atomic_set(&g_CamHWOpend, 0);
-
atomic_set(&g_CamDrvOpenCnt, 0);
-
atomic_set(&g_CamHWOpening, 0);
-
}
3. Camera_hw_p
CAMERA_HW_i2C_init
--> platform_driver_register
--> CAMERA_HW_probe
--> i2c_add_driver
在mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c中
-
static int CAMERA_HW_probe(struct platform_device *pdev)
-
{
-
//创建一个等侍队列
-
init_waitqueue_head(&kd_sensor_wait_queue);
-
//注册一个i2c驱动,然后调用i2c驱动的probe函数CAMERA_HW_i2c_probe
-
return i2c_add_driver(&CAMERA_HW_i2c_driver);
-
}
4. Camera_hw_i2c_probe
CAMERA_HW_i2C_init
--> platform_driver_register
--> CAMERA_HW_probe
--> i2c_add_driver
--> CAMERA_HW_i2c_probe
在mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c中
static DEFINE_SPINLOCK(kdsensor_drv_lock); //spin_lock的初始化是在全局变量中初始化的
-
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.1 字符设备初始化
#define CAMERA_HW_DRVNAME "kd_camera_hw"
static dev_t g_CAMERA_HWdevno = MKDEV(250,0);
-
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_DRVNAME); //动态分配dev_no
-
#else
-
register_chrdev_region( g_CAMERA_HWdevno , 1 , CAMERA_HW_DRVNAME);
-
#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)) //注册设备
-
//这样就创建了结点/dev/kd_camera_hw
-
sensor_class = class_create(THIS_MODULE, "sensordrv"); //与下一句一起创建设备结点
-
sensor_device = device_create(sensor_class, NULL, g_CAMERA_HWdevno, NULL, CAMERA_HW_DRVNAME);
-
-
}
字符设备的文件操作
-
static const struct file_operations g_stCAMERA_HW_fops =
-
{
-
.owner = THIS_MODULE,
-
.open = CAMERA_HW_Open,
-
.release = CAMERA_HW_Release,
-
#ifdef HAL_CAMERA_COMPATIBLE
-
.read = device_read,
-
#endif
-
#ifdef USE_NEW_IOCTL
-
.unlocked_ioctl = CAMERA_HW_Ioctl
-
#else
-
.ioctl = CAMERA_HW_Ioctl
-
#endif
-
};
5. 字符设备的open与relase
open与relase函数啥也不作,只是把计数加1或减1
-
static int CAMERA_HW_Open(struct inode * a_pstInode, struct file * a_pstFile)
-
{
-
dbmsg("open");
-
atomic_inc(&g_CamDrvOpenCnt);
-
return 0;
-
}
release:
-
static int CAMERA_HW_Release(struct inode * a_pstInode, struct file * a_pstFile)
-
{
-
atomic_dec(&g_CamDrvOpenCnt);
-
-
return 0;
-
}
5. 字符设备的read过程
在./mediatek/config/mobitek77_m01_ics2/ProjectConfig.mk中
CUSTOM_HAL_IMGSENSOR=ov5640_yuv s5k4e1ga_raw ov5647_raw gc2035_yuv gc0329_yuv
在mediatek\custom\common\hal\imgsensor\src\sensorlist.cpp中
-
MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
-
{
-
#if defined(OV5640_YUV)
-
YUV_INFO(OV5640_SENSOR_ID, SENSOR_DRVNAME_OV5640_YUV, NULL),
-
#endif
-
#if defined(S5K4E1GA_RAW)
-
RAW_INFO(S5K4E1GA_SENSOR_ID, SENSOR_DRVNAME_S5K4E1GA_RAW, NULL),
-
#endif
-
#if defined(OV5647_RAW)
-
RAW_INFO(OV5647_SENSOR_ID, SENSOR_DRVNAME_OV5647_RAW, NULL),
-
#endif
-
#if defined(GC2035_YUV)
-
YUV_INFO(GC2035_SENSOR_ID, SENSOR_DRVNAME_GC2035_YUV,NULL),
-
#endif
-
#if defined(GC0329_YUV)
-
YUV_INFO(GC0329_SENSOR_ID, SENSOR_DRVNAME_GC0329_YUV, NULL),
-
#endif
-
{0,{0},NULL, NULL, NULL}//end of list
-
};
在mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c
-
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
-
{
-
int bytes_read = 0;
-
char i,k,j,g,err;
-
char msg[2]={0};//"pangfei read test program";
-
-
//查看sensorList中的支持的驱动数目
-
k = sizeof(kdSensorList)/sizeof(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT) - 1;
-
//寻找主摄像头
-
for(i=0;i<k;i++)
-
{
-
kdSearchCameraDriver(i,DUAL_CAMERA_MAIN_SENSOR); //5.1检查是否有这个驱动的硬件
-
msg[0] = i;
-
MainCameraDrvIdx = i; //如果有将全局变量MainCameraDrvIdx设为找到的值,这儿为0
-
break; //这儿为0,即主摄像头是在SensorList中的第0项:ov5640_yuv
-
}
-
//寻找次摄像头
-
for(j=k-1;j>msg[0];j--)
-
{
-
err=kdSearchCameraDriver(j,DUAL_CAMERA_SUB_SENSOR); //检查是否有这个驱动的硬件
-
msg[1] = j;
-
SubCameraDrvIdx = j; //如果有将全局变量SubCameraDrvIdx设为找到的值,这儿为3
break; //这儿为0,即次摄像头是在SensorList中的第3项:gc2035_yuv
-
}
-
}
5.1 寻找驱动
-
static int kdSearchCameraDriver(char drvIdx,char index)
-
{
-
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
-
kdGetSensorInitFuncList(&pSensorList)); //5.1.1由pSensorList获取首地址
-
pSensorList[drvIdx].SensorInit(&g_pSensorFunc); //调用具体硬件的SensorInit
-
CAMERA_HW_CheckIsAlive(index); //5.1.2读取sensorID是否正历来判断是否有这个驱动的硬件连上
-
}
5.1.1获取sensorList的首地址
-
UINT32 kdGetSensorInitFuncList(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
-
{
-
*ppSensorList = &kdSensorList[0];
-
return 0;
-
}
5.1.2读取器件的SensorID来判断是否有硬件连上
-
static int CAMERA_HW_CheckIsAlive(char index)
-
{
-
g_currDualSensorIdx = index; //power on main or sub sensor
-
kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) g_currDualSensorIdx, g_currSensorName,true, CAMERA_HW_DRVNAME);
-
mDELAY(10);
-
//读取SensorID
-
g_pSensorFunc->SensorFeatureControl(SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8*)&sensorID, &retLen);
-
if (sensorID == 0) { //如果读取失败,还有可能是没有实现这个接口,再用SensorOpen试试
-
err = g_pSensorFunc->SensorOpen();
-
}
-
else if (sensorID == 0xFFFFFFFF) {
-
err = ERROR_SENSOR_CONNECT_FAIL;
-
}
-
else {
-
err = ERROR_NONE;
-
}
-
kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) g_currDualSensorIdx, NULL, false, CAMERA_HW_DRVNAME);
-
}
-
int kdSetDriver(unsigned int* pDrvIndex)
-
{
-
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
-
unsigned int drvIdx = (*pDrvIndex & KDIMGSENSOR_DUAL_MASK_LSB);
-
spin_lock(&kdsensor_drv_lock);
-
g_currDualSensorIdx = (CAMERA_DUAL_CAMERA_SENSOR_ENUM)((*pDrvIndex & KDIMGSENSOR_DUAL_MASK_MSB)>>KDIMGSENSOR_DUAL_SHIFT);
-
spin_unlock(&kdsensor_drv_lock);
-
kdGetSensorInitFuncList(&pSensorList);
-
k = sizeof(kdSensorList)/sizeof(ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT) - 1;
-
if (drvIdx == 0)
-
{
-
drvIdx = MainCameraDrvIdx;
-
pSensorList[drvIdx].SensorInit(&g_pSensorFunc); //调用init获取具体驱动的函数指针
-
memcpy((char*)g_currSensorName,(char*)pSensorList[drvIdx].drvname,sizeof(pSensorList[drvIdx].drvname));
-
*pDrvIndex = (unsigned int)pSensorList[drvIdx].SensorId;
-
}
-
else
-
{
-
drvIdx = SubCameraDrvIdx;
-
pSensorList[drvIdx].SensorInit(&g_pSensorFunc); //调用init获取具体驱动的函数指针
-
memcpy((char*)g_currSensorName,(char*)pSensorList[drvIdx].drvname,sizeof(pSensorList[drvIdx].drvname));
-
*pDrvIndex = (unsigned int)pSensorList[drvIdx].SensorId;
-
}
-
}
阅读(1402) | 评论(0) | 转发(0) |