您的位置:首页 > 其它

MTK6577---camera驱动分析

2015-03-04 11:32 190 查看
MTK6577---camera驱动分析 2013-11-21
15:34:31

分类: Android平台

一.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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: