camera汇总.docx
- 文档编号:11515004
- 上传时间:2023-03-02
- 格式:DOCX
- 页数:21
- 大小:21.51KB
camera汇总.docx
《camera汇总.docx》由会员分享,可在线阅读,更多相关《camera汇总.docx(21页珍藏版)》请在冰豆网上搜索。
camera汇总
camera_sensor_driver
image_sensr首先要进行板极设备的初始化的工作:
代码路径是在:
/mediatek/platform/mt6577/kernel/core/mt6577_devs.c里面
#if1///defined(CONFIG_VIDEO_CAPTURE_DRIVERS)
retval=platform_device_register(&sensor_dev);
if(retval!
=0){
returnretval;
}
sensor_dev的实现如下:
staticstructplatform_devicesensor_dev={
.name="image_sensor",
.id=-1,
};
上面是以platformbus 方式进行注册设备的,platformbus 的match的规则是名字相同,所以我们要找到imagesensor的driver就要找到以Platform方式进行注册,名字是”image_sensor”的驱动。
我们下grepcmd,找到了driver的路径:
/mediatek/custom/common/kernel/imgsensor/src/kd_sensorlist.c文件中:
staticstructplatform_driverg_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,
}
};
发现没有,上面的name是image_sensor,看下driver在哪里进行注册的?
/*=======================================================================
*CAMERA_HW_i2C_init()
*=======================================================================*/
staticint__initCAMERA_HW_i2C_init(void)
{
structproc_dir_entry*prEntry;
i2c_register_board_info(CAMERA_I2C_BUSNUM,&kd_camera_dev,1);//这里是注册一个i2c设备
if(platform_driver_register(&g_stCAMERA_HW_Driver)){//这里就是我们以platform方式注册的驱动函数
PK_ERR("failedtoregisterCAMERA_HWdriver\n");
return-ENODEV;
}
//Registerprocfileforsensorregisterdebug
prEntry=create_proc_entry("driver/camsensor",0,NULL);//这里是注册Image_sensor的proc口,主要用于调试。
if(prEntry){
prEntry->read_proc=CAMERA_HW_DumpReg_To_Proc;
prEntry->write_proc=CAMERA_HW_Reg_Debug;
}
else{
PK_ERR("add/proc/driver/camsensorentryfail\n");
}
atomic_set(&g_CamHWOpend,0);
atomic_set(&g_CamDrvOpenCnt,0);
atomic_set(&g_CamHWOpening,0);
return0;
}
当我们platformbus 的deivice和drivermatch 成功后,就会调用drver的probe函数。
.probe=CAMERA_HW_probe,
staticintCAMERA_HW_probe(structplatform_device*pdev)
{
init_waitqueue_head(&kd_sensor_wait_queue);
returni2c_add_driver(&CAMERA_HW_i2c_driver);//这里是以i2c的方式进行注册cameradriver 整好和上上面的i2c方式注册设备一样。
}
其实image_sensor以platform方式注册,只是一个虚拟的方式进行注册的,主要好是以i2c方式进行注册的,下面就进入我们的主角,我们的i2c方式注册的driver
和platformbus一样,i2c同样有自己的一套匹配方式,他的匹配方式就是匹配id_table里面的名字和以i2c_register_board_info(CAMERA_I2C_BUSNUM,&kd_camera_dev,1);方式进行注册到i2c上面的设备的名字进行匹配,匹配成功后,同样也会调用对应的probe函数:
*I2CDriverstructure
********************************************************************************/
structi2c_driverCAMERA_HW_i2c_driver={
.probe=CAMERA_HW_i2c_probe,
.remove=CAMERA_HW_i2c_remove,
.driver.name=CAMERA_HW_DRVNAME,
.id_table=CAMERA_HW_i2c_id,
};
看下这个Probe函数的实现:
staticintCAMERA_HW_i2c_probe(structi2c_client*client,conststructi2c_device_id*id)
{
inti4RetValue=0;
PK_DBG("[CAMERA_HW]AttachI2C\n");
//getsensori2cclient
spin_lock(&kdsensor_drv_lock);
g_pstI2Cclient=client;//这里是获得我们的clientdevice,并且以platform方式进行注册
//setI2Cclockrate
g_pstI2Cclient->timing=200;//200k
spin_unlock(&kdsensor_drv_lock);
//Registerchardriver
i4RetValue=RegisterCAMERA_HWCharDrv();
if(i4RetValue){
PK_ERR("[CAMERA_HW]registerchardevicefailed!
\n");//调用这个函数进行注册char类型的设备,下面trace下这个函数是如何实现的
returni4RetValue;
}
//spin_lock_init(&g_CamHWLock);
PK_DBG("[CAMERA_HW]Attached!
!
\n");
return0;
}
trace下registerCAMERA_HWCharDrv函数的实现:
*RegisterCAMERA_HWCharDrv
********************************************************************************/
inlinestaticintRegisterCAMERA_HWCharDrv(void)
{
structdevice*sensor_device=NULL;
#ifCAMERA_HW_DYNAMIC_ALLOCATE_DEVNO
if(alloc_chrdev_region(&g_CAMERA_HWdevno,0,1,CAMERA_HW_DRVNAME))//分配一个字符设备
{
PK_DBG("[CAMERASENSOR]Allocatedevicenofailed\n");
return-EAGAIN;
}
#else
if(register_chrdev_region(g_CAMERA_HWdevno,1,CAMERA_HW_DRVNAME))//注册一个字符设备
{
PK_DBG("[CAMERASENSOR]Registerdevicenofailed\n");
return-EAGAIN;
}
#endif
//Allocatedriver
g_pCAMERA_HW_CharDrv=cdev_alloc();
if(NULL==g_pCAMERA_HW_CharDrv)
{
unregister_chrdev_region(g_CAMERA_HWdevno,1);
PK_DBG("[CAMERASENSOR]Allocatememforkobjectfailed\n");
return-ENOMEM;
}
//Attatchfileoperation.
cdev_init(g_pCAMERA_HW_CharDrv,&g_stCAMERA_HW_fops);//关联到file_operation进入字符设备
g_pCAMERA_HW_CharDrv->owner=THIS_MODULE;
//Addtosystem
if(cdev_add(g_pCAMERA_HW_CharDrv,g_CAMERA_HWdevno,1))//将我们分配的字符设备,attach上file_operation添加到system
{
PK_DBG("[mt6516_IDP]Attatchfileoperationfailed\n");
unregister_chrdev_region(g_CAMERA_HWdevno,1);
return-EAGAIN;
}
sensor_class=class_create(THIS_MODULE,"sensordrv");//创建一个sensordrv类
if(IS_ERR(sensor_class)){
intret=PTR_ERR(sensor_class);
PK_DBG("Unabletocreateclass,err=%d\n",ret);
returnret;
}
sensor_device=device_create(sensor_class,NULL,g_CAMERA_HWdevno,NULL,CAMERA_HW_DRVNAME);在sensordrv类里面创建一个CAMERA_HW_DRVNAME设备文件。
return0;
}
上面只是一个虚拟的注册过程,我们还没有真正的到到我们的image_sensor设备。
看这个image_sensor的file_operation是如何实现的:
staticconststructfile_operationsg_stCAMERA_HW_fops=
{
.owner=THIS_MODULE,
.open=CAMERA_HW_Open,
.release=CAMERA_HW_Release,
#ifdefUSE_NEW_IOCTL
.unlocked_ioctl=CAMERA_HW_Ioctl
#else
.ioctl=CAMERA_HW_Ioctl
#endif
};
其实我最关注的就是我们手机上面有很多很多的driver,代码中是在哪里判断我们使用的是什么IC厂商的imagesensor。
我找了很多代码,在mediatek的代码中我并没找到。
上层在操作设备的时候都是先open设备,获得文件指针以后就可以进行接下来的事情。
我们先分析open函数:
1、.open=CAMERA_HW_Open,
********************************************************************************/
staticintCAMERA_HW_Open(struct inode*a_pstInode,struct file*a_pstFile)
{
//
atomic_inc(&g_CamDrvOpenCnt);
return 0;
}//open函数里面没有进行任何的操作,就只是一个锁,防止多个
既然我们的open函数里面没有进行别的操作,而我们的file_operation里面就只有open和ioctl成员函数,所以说我们的任何操作imagesensor 的操作函数都是通过ioctl进行操作设备的。
2、.unlocked_ioctl=CAMERA_HW_Ioctl
看下unlocked_ioctl:
上面的两种ioctl的函数都是CAMERA_HW_Ioctl
看下CAMERA_HW_Ioctl函数的实现:
staticintCAMERA_HW_Ioctl(structinode*a_pstInode,
structfile*a_pstFile,
unsignedinta_u4Command,
unsignedlonga_u4Param)
#endif
{
inti4RetValue=0;
void*pBuff=NULL;
u32*pIdx=NULL;
//PK_DBG("%x,%x\n",a_u4Command,a_u4Param);
mutex_lock(&kdCam_Mutex);
if(_IOC_NONE==_IOC_DIR(a_u4Command))
{
}
else
{
pBuff=kmalloc(_IOC_SIZE(a_u4Command),GFP_KERNEL);//分配一个buffer,
if(NULL==pBuff)
{
PK_DBG("[CAMERASENSOR]ioctlallocatememfailed\n");
i4RetValue=-ENOMEM;
gotoCAMERA_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("[CAMERASENSOR]ioctlcopyfromuserfailed\n");
i4RetValue=-EFAULT;
gotoCAMERA_HW_Ioctl_EXIT;
}
}
}
pIdx=(u32*)pBuff;
switch(a_u4Command)
{
#if0
caseKDIMGSENSORIOC_X_POWER_ON:
i4RetValue=kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)*pIdx,true,CAMERA_HW_DRVNAME);//进行imagesensor 上电的工作,具体如何上电,我们会在下面进行讲解。
break;
caseKDIMGSENSORIOC_X_POWER_OFF:
i4RetValue=kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)*pIdx,false,CAMERA_HW_DRVNAME);//进行imagesensorpoweroff 的动作
break;
#endif
caseKDIMGSENSORIOC_X_SET_DRIVER:
i4RetValue=kdSetDriver((unsignedint*)pBuff);//执行到这个cmd,将会调用kdSetDriver
//其实这个函数很重要,就是为我们对应的imagesensor 设置driver,就是设置提供给上层操作底层的interface
…....................
…......................
default:
PK_DBG("Nosuchcommand\n");
i4RetValue=-EPERM;
break;
}
上层就是通过下ioctl的cmd进行操作底层的,我们就选几个cmd进行讲解下。
caseKDIMGSENSORIOC_T_OPEN:
i4RetValue=adopt_CAMERA_HW_Open();//当执行上面的cmd的时候,我们就会执行这个函数
inlinestatic intadopt_CAMERA_HW_Open(void)
{
UINT32err=0;
#ifdefCONFIG_ARCH_MT6577
intret=0;
//DDR2DRAMclockbugworkaround
if(2==get_ddr_type()){//DDR2
ret=set_dram_clk_gating
(1);//设置dram寄存器
if(-1==ret){
PK_ERR("ERROR:
DRAMCLOCKGATINGERROR\n");
}
}
#endif
KD_IMGSENSOR_PROFILE_INIT();//返回当前的时间
//poweronsensor
if(atomic_read(&g_CamHWOpend)==0){
//turnonpower
atomic_set(&g_CamHWOpening,1);
kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_currDualSensorIdx,g_currSensorName,true,CAMERA_HW_DRVNAME);//为sensor上电,这个上电函数我们在下面进行讲解
//waitforpowerstable
mDELAY(10);
KD_IMGSENSOR_PROFILE("kdModulePowerOn");
//
if(g_pSensorFunc){//判断我们imagesensor 操作函数指针是否为NULL,如果为NULL,报错,因为我们就是靠这个操作函数集合去操作imagesensor 的,
//如果上层先下这个cmd的话,那么肯定是不行的,因为我们的g_pSensorFunc是NULL,并没有赋值,通过查询代码,发现是caseKDIMGSENSORIOC_X_SET_DRIVER:
这个case;里面在做,所以上层肯定是先下这个cmd,然后才能执行我们现在讲解的cmd.这个cmd我们下面会进行讲解。
err=g_pSensorFunc->SensorOpen();//调用使用的imagesensor 的open函数,我们会对一个imagesensor 的接口函数进行举例讲解。
if(ERROR_NONE!
=err){
PK_DBG("ERROR:
SensorOpen(),turnoffpower\n");
kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_currDualSensorIdx,NULL,false,CAMERA_HW_DRVNAME);
}
//kaka_12_0112_2add
else//AddforsensorproviderHWinfomodule
{
if(DUAL_CAMERA_MAIN_SENSOR==g_currDualSensorIdx){
memcpy(mainCameraName,g_currSensorName,CAM_NAME_LEN);
g_main_camera=mainCameraName;
}
elseif(DUAL_CAMERA_SUB_SENSOR==g_currDualSensorIdx){
memcpy(subCameraName,g_currSensorName,CAM_NAME_LEN);
g_sub_camera=subCameraName;
}
}
//kaka_12_0112_2end
}
else{
PK_DBG("ERROR:
NULLg_pSensorFunc\n");
}
KD_IMGSENSOR_PROFILE("SensorOpen");
}
if(err==0){
atomic_set(&g_CamHWOpend,1);
}
returnerr?
-EIO:
err;
} /*adopt_CAMERA_HW_Open()*/
2.1、kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM)g_currDualSensorIdx,g_currSensorName,true,CAMERA_HW_DRVNAME);
--------->kdCISModulePowerOn(SensorIdx,currSensorName,On,mode_name)//这个就是camera的上电函数,函数定义在/mediatek/custom/common/kernel/camera/camera/kd_camera_hw.c里面。
这个文件里面就是camera的上电函数,在mediatek平台下都共用这个函数。
3、Case:
KDIMGSENSORIOC_X_SET_DRIVER
kdSetDriver函数的实现如下:
intkdSetDriver(unsigned int*pDrvIndex)
{
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT*pSensorList=NULL;
unsignedintdrvIdx=(*pDrvIndex&KDIMGSENSOR_DUAL_MASK_LSB);//这里根据我们用户传递进来的参数转化为drvIdx,就是driverindex的选择
//setdriverforMAINorSUBsensor
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);
if(0!
=kdGetSensorInitFuncList(&pSensorList))//调
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- camera 汇总
![提示](https://static.bdocx.com/images/bang_tan.gif)