赞
踩
和你一起终身学习,这里是程序员Android
经典好文推荐,通过阅读本文,您将收获以下知识点:
Camera
的框架分为Kernel
部分和hal
部分,其中kernel
部分主要有两块:
image sensor driver
,负责具体型号的sensor
的id
检测,上电,以及在preview
、capture
、初始化
、3A
等等功能设定时的寄存器配置;
isp driver
,通过DMA
将sensor
数据流上传;
HAL
层部分主要有三部分组成:
imageio
,主要负责数据buffer
上传的pipe
;
drv
,包含imgsensor
和isp
的hal
层控制;
feature io
,包含各种3A
等性能配置;
这篇内容主要介绍开机过程中search sensor
以及上电流程等内容。
1、CameraService
是在开机时启动的,启动后进行searchSensor
的操作,会search
系统有多少camera
,开机时的search
操作,只进行camera
支持数量的遍历,以及sensor ID
的读取操作,如下是hal
部分的ASTAH
绘制调用流程图,对应的接口的文件路径:
HalSensorList:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/HalSensorList.enumList.cpp
vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/HalSensorList.cpp
SeninfDrv:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/mt6765/seninf_drv.cpp
SensorDrv:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/imgsensor_drv.cpp
(1) 这里先看enumerateSensor_Locked
完成的工作,直接看代码:
- MUINT HalSensorList::searchSensors()
- {
- Mutex::Autolock _l(mEnumSensorMutex);
- MY_LOGD("searchSensors");
- return enumerateSensor_Locked();
- }
-
- MUINT HalSensorList::enumerateSensor_Locked()
- {
- SensorDrv *const pSensorDrv = SensorDrv::get();
- SeninfDrv *const pSeninfDrv = SeninfDrv::createInstance();
- //初始化seninf,配置ISP相关内容
- pSeninfDrv->init();
-
- //将所有的clk全部打开
- pSeninfDrv->setAllMclkOnOff(ISP_DRIVING_8MA, TRUE);
-
- pSensorDrv->init();
- for (MUINT i = IMGSENSOR_SENSOR_IDX_MIN_NUM; i <= max_index_of_camera; i++) {
- if((ret = pSensorDrv->searchSensor((IMGSENSOR_SENSOR_IDX)i)) == SENSOR_NO_ERROR){
- //query sensorinfo
- querySensorDrvInfo((IMGSENSOR_SENSOR_IDX)i);
- //fill in metadata
- buildSensorMetadata((IMGSENSOR_SENSOR_IDX)i);
- pSensorInfo = pSensorDrv->getSensorInfo((IMGSENSOR_SENSOR_IDX)i);
- addAndInitSensorEnumInfo_Locked(
- (IMGSENSOR_SENSOR_IDX)i,
- mapToSensorType(pSensorInfo->GetType()),
- pSensorInfo->getDrvMacroName());
- }
- }
- }
(2) 下面主要看下searchSensor
的流程,这里有去获取sensorList
的内容:
- MINT32 ImgSensorDrv::searchSensor(IMGSENSOR_SENSOR_IDX sensorIdx)
- {
- GetSensorInitFuncList(&pSensorInitFunc);
-
- featureControl(sensorIdx, SENSOR_FEATURE_SET_DRIVER, (MUINT8 *)&idx, &featureParaLen);
-
- NSFeature::SensorInfoBase* pSensorInfo = pSensorInitFunc[idx].pSensorInfo;
- }
GetSensorInitFuncList
是获取到配置的sensorList
的内容,此sensorList
需要与kernel
层配置的一致,不一致的话在打开camera
时会出现异常:
文件位置:vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/sensorlist.cpp
- MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
- {
- #if defined(IMX486_MIPI_RAW)
- RAW_INFO(IMX486_SENSOR_ID, SENSOR_DRVNAME_IMX486_MIPI_RAW, CAM_CALGetCalData),
- #endif
- //.....
- }
-
- UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
- {
- if (NULL == ppSensorList) {
- ALOGE("ERROR: NULL pSensorList\n");
- return MHAL_UNKNOWN_ERROR;
- }
- *ppSensorList = &SensorList[0];
- return MHAL_NO_ERROR;
- }
对应的MSDK_SENSOR_INIT_FUNCTION_STRUCT
的结构体如下:
- typedef struct
- {
- MUINT32 sensorType;
- MUINT32 SensorId;
- MUINT8 drvname[32];
- NSFeature::SensorInfoBase* pSensorInfo;
- MUINT32 (*getCameraIndexMgr)(CAMERA_DATA_TYPE_ENUM CameraDataType, MVOID *pDataBuf, MUINT32 size);
- MUINT32 (*getCameraCalData)(UINT32* pGetSensorCalData);
- } MSDK_SENSOR_INIT_FUNCTION_STRUCT, *PMSDK_SENSOR_INIT_FUNCTION_STRUCT;
(3) featureControl
的setDriver
流程:
文件位置:vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/imgsensor_drv.cpp
- MINT32 ImgSensorDrv::featureControl(
- IMGSENSOR_SENSOR_IDX sensorIdx,
- ACDK_SENSOR_FEATURE_ENUM FeatureId,
- MUINT8 *pFeaturePara,
- MUINT32 *pFeatureParaLen
- )
- {
- //结构ACDK_SENSOR_FEATURECONTROL_STRUCT和kernel中一致
- featureCtrl.InvokeCamera = sensorIdx;
- featureCtrl.FeatureId = FeatureId;//SENSOR_FEATURE_SET_DRIVER
- featureCtrl.pFeaturePara = pFeaturePara;
- featureCtrl.pFeatureParaLen = pFeatureParaLen;
-
- if (ioctl(m_fdSensor, KDIMGSENSORIOC_X_FEATURECONCTROL , &featureCtrl) < 0) {
- LOG_ERR("[featureControl] Err-ctrlCode (%s)", strerror(errno));
- return -errno;
- }
-
- return SENSOR_NO_ERROR;
- }
先来看整体的框架图如下:
- static long imgsensor_ioctl(
- struct file *a_pstFile,
- unsigned int a_u4Command,
- unsigned long a_u4Param)
- {
- case KDIMGSENSORIOC_X_SET_MCLK_PLL:
- i4RetValue = imgsensor_clk_set(
- &pgimgsensor->clk,
- (struct ACDK_SENSOR_MCLK_STRUCT *)pBuff);
- break;
- //......
- }
-
- int imgsensor_clk_set(
- struct IMGSENSOR_CLK *pclk, struct ACDK_SENSOR_MCLK_STRUCT *pmclk)
- {
- if (pmclk->on) {
- clk_prepare_enable(pclk->imgsensor_ccf[mclk_index])
- ret = clk_set_parent(
- pclk->imgsensor_ccf[pmclk->TG],
- pclk->imgsensor_ccf[mclk_index]);
- } else {
- clk_disable_unprepare(pclk->imgsensor_ccf[mclk_index]);
- }
- }
- static long imgsensor_ioctl(
- struct file *a_pstFile,
- unsigned int a_u4Command,
- unsigned long a_u4Param)
- {
- case KDIMGSENSORIOC_X_FEATURECONCTROL:
- i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
- break;
- //......
- }
-
- static inline int adopt_CAMERA_HW_FeatureControl(void *pBuf)
- {
- /* copy from user */
- switch (pFeatureCtrl->FeatureId) {
- case SENSOR_FEATURE_SET_DRIVER:
- {
- MINT32 drv_idx;
-
- psensor->inst.sensor_idx = pFeatureCtrl->InvokeCamera;
- drv_idx = imgsensor_set_driver(psensor);
-
- memcpy(pFeaturePara, &drv_idx, FeatureParaLen);
- break;
- }
- }
- }
遍历CONFIG_CUSTOM_KERNEL_IMGSENSOR
的内容,然后看sensorList
是否对应,并获取对应的下标,调用imgsensor_check_is_alive
进行上下电并读取ID 的操作:
- struct IMGSENSOR_INIT_FUNC_LIST kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR] = {
- #if defined(XXXXXX_MIPI_RAW)
- {XXXXXX_SENSOR_ID,
- SENSOR_DRVNAME_XXXXXX_MIPI_RAW,
- XXXXXX_MIPI_RAW_SensorInit},
- #endif
- //......
- }
-
- int imgsensor_set_driver(struct IMGSENSOR_SENSOR *psensor)
- {
- struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
- struct IMGSENSOR_INIT_FUNC_LIST *pSensorList = kdSensorList;
- //获取config的size
- char *sensor_configs = STRINGIZE(CONFIG_CUSTOM_KERNEL_IMGSENSOR);
- imgsensor_i2c_init(&psensor_inst->i2c_cfg,
- imgsensor_custom_config[psensor->inst.sensor_idx].i2c_dev);
-
- memcpy(psensor_list_config, sensor_configs+1, strlen(sensor_configs)-2);
- //对应config字符串进行按空格进行拆解
- driver_name = strsep(&psensor_list_config, " \0");
-
- while (driver_name != NULL) {
- for (j = 0; j < MAX_NUM_OF_SUPPORT_SENSOR; j++) {
- //判断对应的init函数是否存在
- if (pSensorList[j].init == NULL)
- break;
- else if (!strcmp(driver_name, pSensorList[j].name)) {
- //如果在config中和sensorlist中同时有定义进行赋值
- orderedSearchList[i++] = j;
- break;
- }
- }
- driver_name = strsep(&psensor_list_config, " \0");
- }
-
- for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {
- //上面获取到的sensorlist的下标
- drv_idx = orderedSearchList[i];
- if (pSensorList[drv_idx].init) {
- //调用对应驱动的init函数
- pSensorList[drv_idx].init(&psensor->pfunc);
- if (psensor->pfunc) {
- psensor_inst->psensor_name =
- (char *)pSensorList[drv_idx].name;
- //到这里是重点,进行上电读取ID的操作
- if (!imgsensor_check_is_alive(psensor)) {
- ret = drv_idx;
- }
- }
- }
- }
- }
下面看对应的上下电以及读取ID
的操作:
- static inline int imgsensor_check_is_alive(struct IMGSENSOR_SENSOR *psensor)
- {
- struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
- //上电
- err = imgsensor_hw_power(&pgimgsensor->hw,
- psensor,
- psensor_inst->psensor_name,
- IMGSENSOR_HW_POWER_STATUS_ON);
- //读取ID
- imgsensor_sensor_feature_control(
- psensor,
- SENSOR_FEATURE_CHECK_SENSOR_ID,
- (MUINT8 *)&sensorID,
- &retLen);
-
- if (sensorID == 0 || sensorID == 0xFFFFFFFF) {
- pr_info("Fail to get sensor ID %x\n", sensorID);
- err = ERROR_SENSOR_CONNECT_FAIL;
- } else {
- pr_info(" Sensor found ID = 0x%x\n", sensorID);
- err = ERROR_NONE;
- }
- //下电
- imgsensor_hw_power(&pgimgsensor->hw,
- psensor,
- psensor_inst->psensor_name,
- IMGSENSOR_HW_POWER_STATUS_OFF);
-
- return err ? -EIO:err;
- }
上电时序配置:
- struct IMGSENSOR_HW_POWER_INFO {
- enum IMGSENSOR_HW_PIN pin;
- enum IMGSENSOR_HW_PIN_STATE pin_state_on;
- u32 pin_on_delay;
- enum IMGSENSOR_HW_PIN_STATE pin_state_off;
- u32 pin_off_delay;
- };
-
- struct IMGSENSOR_HW_POWER_SEQ sensor_power_sequence[] = {
- //……
- #if defined(XXXXXX_MIPI_RAW)
- {
- SENSOR_DRVNAME_XXXXXX_MIPI_RAW,
- {
- {RST, Vol_Low, 0},
- {DVDD, Vol_1100, 1},
- {AVDD, Vol_2800, 1},
- {DOVDD, Vol_1800, 1},
- {RST, Vol_High, 1},
- {SensorMCLK, Vol_High, 0},
- },
- },
- #endif
- }
对应的控制的流程如下:
- static enum IMGSENSOR_RETURN imgsensor_hw_power_sequence(
- struct IMGSENSOR_HW *phw,
- enum IMGSENSOR_SENSOR_IDX sensor_idx,
- enum IMGSENSOR_HW_POWER_STATUS pwr_status,
- struct IMGSENSOR_HW_POWER_SEQ *ppower_sequence,
- char *pcurr_idx)
- {
- ppwr_info = ppwr_seq->pwr_info;
- // 上电
- while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE &&
- ppwr_info < ppwr_seq->pwr_info + IMGSENSOR_HW_POWER_INFO_MAX) {
-
- if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON &&
- ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
- pdev = phw->pdev[psensor_pwr->id[ppwr_info->pin]];
- if (pdev->set != NULL)
- //调用GPIO或者regulator的set 电压操作,这里的pdev在imgsensor_probe中已经设置
- pdev->set(
- pdev->pinstance,
- sensor_idx,
- ppwr_info->pin,
- ppwr_info->pin_state_on);
-
- mdelay(ppwr_info->pin_on_delay);
- }
- // 从上到下依次上电
- ppwr_info++;
- pin_cnt++;
- }
-
- // 下电操作
- if (pwr_status == IMGSENSOR_HW_POWER_STATUS_OFF) {
- while (pin_cnt) {
- //从下到上依次下电
- ppwr_info--;
- pin_cnt--;
-
- if (ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
- pdev =
- phw->pdev[psensor_pwr->id[ppwr_info->pin]];
- mdelay(ppwr_info->pin_on_delay);
-
- if (pdev->set != NULL)
- pdev->set(
- pdev->pinstance,
- sensor_idx,
- ppwr_info->pin,
- ppwr_info->pin_state_off);
- }
- }
- }
-
- /* wait for power stable */
- if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON)
- mdelay(5);
- return IMGSENSOR_RETURN_SUCCESS;
- }
通过上面的代码流程,可以知道上开机时,camera
模块先会将所有的MCLK
打开,然后对依次对对应的sensor
进行上电,读取ID
(判断I2C
是否正常通讯)。这部分调试过程中遇到的问题总结如下:
检查上电时序,3项电压(AVDD/DVDD/IOVDD
)是否正确;
I2C
地址及通道设置是否正确;
检查cfg_setting_imgsensor.cpp
中MCLK
和HW
链接配置是否正确;
检查Sensor
上电时序要求的延时,是否有偏长的情况;
去掉多余的I2C
地址,因为大部分驱动会多添加一些地址;
OTP
的加载调整到每次开机时第一次打开加载,之后不加载;
sensorInit
如果时间过长,可以调节I2C speed(400->1000)
;
检查streamOn/Off
的耗时;
preview_init
是否有较长时间的耗时
以及延时操作使用mdelay
代替msleep
;
pre_delay_frame/cap_delay_frame
丢帧操作是否合适;
检查电压是否都有下电成功,防止漏电;
对于共pin
的sensor
,在操作时是否有做好workaround
;
将I2C
寄存器单个读写,调整为连续读写的方式也有一定优化;
sensor
的PIN
是否有被其他模块占用,异常操作的行为;
友情推荐:
至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!
点个在看,方便您使用时快速查找!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。