mtk android tv软件架构,MTK 平台Camera 驱动架构
Platform_driver 这个结构体包含 Probe()、 Remove()等函数来完成驱动的填充。
b)设备的注册:
对 platform_device 的定义通常在 BSP 的板级文件( kernel\arch\sh\boards\mach-ap325rxa\Setup.c)中实现,在板级文件中,将 platform_device归纳为一个数组,最终通过 platform_add_device()函数统一注册:
c)总线的匹配:
既 然 是 驱 动 Platform_device 那 对 应 的 设 备 必 然 是 挂 载 Platform 总 线 上 的Platform_device, Platform 总线是 Linux 系统提供的一种机制,不同于 I2C、 I2S 等总线,它是一种虚拟的总线。Linux 系统为 Platform 总线定义了一个 bus_type 的实例 Platform_bus_type:( Kernel\drivers\base\platform.c)
Platform 总线通过 platform_match 这个成员函数来确定 platform_device 与 platform_driver 如
何进行匹配:
Camera驱动工作流程:
从上图可以清晰的了解到 Camera 的一个工作流程主要分为这么七步:
1. 打开 Camera Power LDO,让 Camera 有能量保证。
2. 打开 IIC,设置 PDN 引脚,使 Camera 退出出 Standby 模式,按照要求让 Reset 脚做一个复位动作。
3. 读一下 sensor 的版本 ID,这样可以让你确认是否连接上你想要的 sensor。
4. 对 Sensor 进行初始化下载最基本的参数让 Sensor 工作起来,可能包括软复位。
5. 下载 preview 的参数,为预览动作准备。
6. 下载 Capture 的参数,为拍照动作准备。
7. 设置 PDN 引脚,使 Sensor 进入 Standby 模式,或者关掉 LDO 等动作,退出 Camera。
我们都知道, Linux 内核是通过模块的机制来加载设备驱动的,那么接下来我们就从设备模块加载的角度来看下 Camera 工作流程的驱动代码是如何工作的。在-alps\mediatek\custom\common\kernel\imgsensor\src\kd_sensorlist.c 中可以看到:
module_init(CAMERA_HW_i2C_init);
module_exit(CAMERA_HW_i2C_exit);
在这里 Linux 内核加载和卸载 Camera 模块
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,
}
};Camera 模块初始化开始向总线注册驱动,在 Platform_driver 的成员函数.probe()中, 通过 i2c_add_driver(&CAMERA_HW_i2c_driver)向 I2C 申请,而 CAMERA_HW_i2c_driver 这个结构体里填充的是将 Camera 作为一个字符设备在 I2C 上进行注册:
struct i2c_driver CAMERA_HW_i2c_driver = {
.probe = CAMERA_HW_i2c_probe,
.remove = CAMERA_HW_i2c_remove,
.driver.name = CAMERA_HW_DRVNAME1,
.id_table = CAMERA_HW_i2c_id,
};
/*******************************************************************************
* i2c relative start
********************************************************************************/
/*******************************************************************************
* CAMERA_HW_i2c_probe
********************************************************************************/
static int CAMERA_HW_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int i4RetValue = 0;
PK_DBG("[CAMERA_HW] Attach I2C \n");
//get sensor i2c client
spin_lock(&kdsensor_drv_lock);
g_pstI2Cclient = client;
//set I2C clock rate
g_pstI2Cclient->timing = 300;//200k
spin_unlock(&kdsensor_drv_lock);
//Register char driver
i4RetValue = RegisterCAMERA_HWCharDrv();
if(i4RetValue){
PK_ERR("[CAMERA_HW] register char device failed!\n");
return i4RetValue;
}
//spin_lock_init(&g_CamHWLock);
PK_DBG("[CAMERA_HW] Attached!! \n");
return 0;
}
在 RegisterCAMERA_HWCharDrv() 中
cdev_init(g_pCAMERA_HW_CharDrv, &g_stCAMERA_HW_fops);对设备进行初始化,并将g_stCAMERA_HW_fops 这个文件操作函数作为上层对 Camera 设备操作的接口留给上层进行调用:
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
};
其中成员函数 open()只是初始化一个原子变量留给系统调用。 ioctl()才是整个 Camera驱动的入口:CAMERA_HW_Ioctl()是上层文件操作系统操作底层硬件的方法,它先对 Camera 需要的Buffer 做一个初始化,然后建立对 Cameraopen、 getinfo 等操作的接口:
/*******************************************************************************
* CAMERA_HW_Ioctl
********************************************************************************/
static long CAMERA_HW_Ioctl(
struct file * a_pstFile,
unsigned int a_u4Command,
unsigned long a_u4Param
)
{
int i4RetValue = 0;
void * pBuff = NULL;
u32 *pIdx = NULL;
mutex_lock(&kdCam_Mutex);
if(_IOC_NONE == _IOC_DIR(a_u4Command)) {
}
else {
pBuff = kmalloc(_IOC_SIZE(a_u4Command),GFP_KERNEL);
if(NULL == pBuff) {
PK_DBG("[CAMERA SENSOR] ioctl allocate mem failed\n");
i4RetValue = -ENOMEM;
goto CAMERA_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("[CAMERA SENSOR] ioctl copy from user failed\n");
i4RetValue = -EFAULT;
goto CAMERA_HW_Ioctl_EXIT;
}
}
}
pIdx = (u32*)pBuff;
switch(a_u4Command) {
#if 0
case KDIMGSENSORIOC_X_POWER_ON:
i4RetValue = kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, true, CAMERA_HW_DRVNAME);
break;
case KDIMGSENSORIOC_X_POWER_OFF:
i4RetValue = kdModulePowerOn((CAMERA_DUAL_CAMERA_SENSOR_ENUM) *pIdx, false, CAMERA_HW_DRVNAME);
break;
#endif
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_GETRESOLUTION:
i4RetValue = adopt_CAMERA_HW_GetResolution(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;
default :
PK_DBG("No such command \n");
i4RetValue = -EPERM;
break;
}
if(_IOC_READ & _IOC_DIR(a_u4Command)) {
if(copy_to_user((void __user *) a_u4Param , pBuff , _IOC_SIZE(a_u4Command))) {
kfree(pBuff);
PK_DBG("[CAMERA SENSOR] ioctl copy to user failed\n");
i4RetValue = -EFAULT;
goto CAMERA_HW_Ioctl_EXIT;
}
}
kfree(pBuff);
CAMERA_HW_Ioctl_EXIT:
mutex_unlock(&kdCam_Mutex);
return i4RetValue;
}
通过判断 Sensor 状态的逻辑值来进行具体的操作, 对于这个值的定义在:
Mediatek\custom\common\kernel\imgsensor\inc\Kd_imgsensor.h 中
//sensorOpen
//This command will TBD
#define KDIMGSENSORIOC_T_OPEN _IO(IMGSENSORMAGIC,0)
//sensorGetInfo
//This command will TBD
#define KDIMGSENSORIOC_X_GETINFO _IOWR(IMGSENSORMAGIC,5,ACDK_SENSOR_GETINFO_STRUCT)
//sensorGetResolution
//This command will TBD
#define KDIMGSENSORIOC_X_GETRESOLUTION _IOWR(IMGSENSORMAGIC,10,ACDK_SENSOR_RESOLUTION_INFO_STRUCT)
//sensorFeatureControl
//This command will TBD
#define KDIMGSENSORIOC_X_FEATURECONCTROL _IOWR(IMGSENSORMAGIC,15,ACDK_SENSOR_FEATURECONTROL_STRUCT)
//sensorControl
//This command will TBD
#define KDIMGSENSORIOC_X_CONTROL _IOWR(IMGSENSORMAGIC,20,ACDK_SENSOR_CONTROL_STRUCT)
//sensorClose
//This command will TBD
#define KDIMGSENSORIOC_T_CLOSE _IO(IMGSENSORMAGIC,25)
//sensorSearch
#define KDIMGSENSORIOC_T_CHECK_IS_ALIVE _IO(IMGSENSORMAGIC, 30)
//set sensor driver
#define KDIMGSENSORIOC_X_SET_DRIVER _IOWR(IMGSENSORMAGIC,35,SENSOR_DRIVER_INDEX_STRUCT)
//get socket postion
#define KDIMGSENSORIOC_X_GET_SOCKET_POS _IOWR(IMGSENSORMAGIC,40,u32)
//set I2C bus
#define KDIMGSENSORIOC_X_SET_I2CBUS _IOWR(IMGSENSORMAGIC,45,u32)
//set I2C bus
#define KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK _IO(IMGSENSORMAGIC,50)
//Set Shutter Gain Wait Done
#define KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE _IOWR(IMGSENSORMAGIC,55,u32)//HDR
//set mclk
#define KDIMGSENSORIOC_X_SET_MCLK_PLL _IOWR(IMGSENSORMAGIC,60,ACDK_SENSOR_MCLK_STRUCT)
在 KdSetDriver()中通过判断 name 和 ID 匹配具体型号的 sensor 的驱动,判断它是主摄还
是次摄,并对它进行初始化:
/*******************************************************************************
* kdSetDriver
********************************************************************************/
int kdSetDriver(unsigned int* pDrvIndex)
{
ACDK_KD_SENSOR_INIT_FUNCTION_STRUCT *pSensorList = NULL;
u32 drvIdx[KDIMGSENSOR_MAX_INVOKE_DRIVERS] = {0,0};
u32 i;
PK_XLOG_INFO("pDrvIndex:0x%08x/0x%08x \n",pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_0],pDrvIndex[KDIMGSENSOR_INVOKE_DRIVER_1]);
//set driver for MAIN or SUB sensor
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_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 ( DUAL_CAMERA_NONE_SENSOR == g_invokeSocketIdx[i] ) { continue; }
/*if( DUAL_CAMERA_MAIN_2_SENSOR == g_invokeSocketIdx[i] ) {
spin_lock(&kdsensor_drv_lock);
gI2CBusNum = SUPPORT_I2C_BUS_NUM2;
spin_unlock(&kdsensor_drv_lock);
PK_XLOG_INFO("kdSetDriver: switch I2C BUS2\n");
}
else {
spin_lock(&kdsensor_drv_lock);
gI2CBusNum = SUPPORT_I2C_BUS_NUM1;
spin_unlock(&kdsensor_drv_lock);
PK_XLOG_INFO("kdSetDriver: switch I2C BUS1\n");
}*/
//ToDo: remove print information
PK_XLOG_INFO("[kdSetDriver] i,g_invokeSocketIdx[%d] = %d :\n",i,i,drvIdx[i]);
PK_XLOG_INFO("[kdSetDriver] i,drvIdx[%d] = %d :\n",i,i,drvIdx[i]);
//
if ( MAX_NUM_OF_SUPPORT_SENSOR > drvIdx[i] ) {
if (NULL == pSensorList[drvIdx[i]].SensorInit) {
PK_ERR("ERROR:kdSetDriver()\n");
return -EIO;
}
pSensorList[drvIdx[i]].SensorInit(&g_pInvokeSensorFunc[i]);
if (NULL == g_pInvokeSensorFunc[i]) {
PK_ERR("ERROR:NULL g_pSensorFunc[%d]\n",i);
return -EIO;
}
//
spin_lock(&kdsensor_drv_lock);
g_bEnableDriver[i] = TRUE;
g_CurrentInvokeCam = g_invokeSocketIdx[i];
spin_unlock(&kdsensor_drv_lock);
//get sensor name
memcpy((char*)g_invokeSensorNameStr[i],(char*)pSensorList[drvIdx[i]].drvname,sizeof(pSensorList[drvIdx[i]].drvname));
//return sensor ID
//pDrvIndex[0] = (unsigned int)pSensorList[drvIdx].SensorId;
PK_XLOG_INFO("[kdSetDriver] :[%d][%d][%d][%s][%d]\n",i,g_bEnableDriver[i],g_invokeSocketIdx[i],g_invokeSensorNameStr[i],sizeof(pSensorList[drvIdx[i]].drvname));
}
}
return 0;
}
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;
通过 NAME 和 ID 匹配完成后会将 PSENSOR_FUNCTION_STRUCT *pfFunc 这个结构体匹配到具体型号的驱动代码中:
SENSOR_FUNCTION_STRUCTSensorFuncGC0329YUV=
{
GC0329Open,
GC0329GetInfo,
GC0329GetResolution,
GC0329FeatureControl,
GC0329Control,
GC0329Close
};
到这里,整个 Camera 驱动从总线注册到完成具体 sensor 的初始化的流程就完成了,CAMERA_HW_Ioctl()中其他的 ioctl 操作函数最后都会在$sensor$_sensor.c 中实现。
mtk android tv软件架构,MTK 平台Camera 驱动架构相关推荐
- Android高通平台调试Camera驱动全纪录
项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...
- 请把Camera hold住 - Android高通平台调试Camera驱动全纪录
项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...
- android camera2 qcom,Qcom平台 Camera的一些知识点 之MCLK
前言 MCLK 是平台 baseband 提供给 cam sensor的正常工作的频率, Qcom 平台一般未24MHz,由其他时钟源分频而来,实测在23.8MHz左右. 在打开相机的时候,才可以测到 ...
- android camera2 qcom,Qcom平台 camera的一些知识点 之RAW图抓取
前言 介绍camera sensor 输出的 raw 图,用于验证cam显示效果问题. 参考文档 : KBA-161204073328 目录 的 mask bit 定义 参数解释: /** * 参数解 ...
- mtk android 编译过程,MTK android 快速编译方法.doc
. . [FAQ10625] 提升Android编译速度 Platform: MT6572 MT6582 MT6588 MT6589 MT6592 MT6595 MT6571 MT6582/92+MT ...
- 全志平台camera驱动开发(4)NVP6134芯片4路模拟视频BT656输入
前言 1. 调试平台: 全志V5/T7等有BT656或BT1120的并行接口,理论有DVP接口的一般都支持 2. NVP6134可使用多路视频同时输入 硬件连接 模拟camera1 模拟camera2 ...
- 全志平台camera驱动开发(5)NVP6134芯片8路模拟视频BT1120输入
前言 1. 调试平台: 全志V5/T7等有BT1120的并行接口,理论有DVP接口的一般都支持 2. NVP6134可使用多路视频同时输入 硬件连接 模拟camera1 模拟camera2 模拟cam ...
- mtk android关机铃声,mtk android power key 长按8s 关机功能实现
该功能是系统启动后,在任何情况下,长按power key 8s都能做到直接关机.因此在kernel中实现. 所有修改都在keypad driver中,如下文件. mediatek\platform\m ...
- android tv闹钟_Android 平台有哪些闹钟应用值得推荐?
哇真是一篇充满年代感的问题,不知道咋点进来的. 既然点进来,就得留下点什么,这是我的一贯风格(装一下 -_-!) 楼主提到的睡眠周期,我不是特别理解,就按照我的习惯碎碎念一下吧 ----------- ...
最新文章
- MySQL触发器的使用规则
- DASH直播平台的搭建
- 【HDU - 5890】Eighty seven(bitset优化背包)
- openssh升级后无法登陆解决方案
- 关于obs的录制时黑屏问题
- android 接收SDCcard插拔的广播
- 取消浏览器的默认样式
- Git版本管理工具的使用方法
- JAVA 随机数学习
- 「一本通 4.5 例 1」树的统计(树链剖分)
- 珠宝订货(订单)系统与ERP实现库存信息同步的实现方案分享
- dir_recurse是 php函数,dir_recurse是一个函数么?
- 火车票查询软件测试自学,火车票订购系统的测试报告.doc
- 【机器学习7】决策树
- 做戴威式的管理者,还是雷军式的管理者?
- java计算移动平均值_多种移动平均计算总结(MA,EMA,SMA,DMA,TMA,WMA)
- java se和java_Java SE 9非常适合灵活,可扩展和无服务器的未来
- Anaconda使用教程(一)——下载、安装及环境配置
- Python实现TOPSIS分析法(优劣解距离法)
- 痛心!华为高管丁耘去世,享年 53 岁
热门文章
- 中软培训 day01 sublime安装及使用
- Geoserver学习笔记-3、服务标准(WFS)
- 9月份杂谈-如何戒掉坏习惯
- 基于RT-THREAD nano的平衡车--上位机软件
- Excel AI - 推出 AI 智能函数,太过强大
- Python学习笔记(9)采集图片网址并下载图片——以途牛旅游网为例
- Ubuntu 与Windows共享文件夹的操作
- 北京信息科技大学计算机科学与技术怎么样,北京信息科技大学怎么样 ,是211的学校吗...
- Golang基础——统计字符串中汉字的数量
- 使用git pull的时候未能对git remote进行身份验证?