当前位置:   article > 正文

Android 相机启动流程笔记

Android 相机启动流程笔记

90300989cb7a97628191282627f2690b.gif

和你一起终身学习,这里是程序员Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一、Camera 框架介绍:

Camera的框架分为Kernel部分和hal部分,其中kernel部分主要有两块:

  • image sensor driver,负责具体型号的sensorid检测,上电,以及在previewcapture初始化3A等等功能设定时的寄存器配置;

  • isp driver,通过DMAsensor数据流上传;

HAL层部分主要有三部分组成:

  • imageio,主要负责数据buffer上传的pipe

  • drv,包含imgsensorisphal层控制;

  • feature io,包含各种3A等性能配置;

这篇内容主要介绍开机过程中search sensor以及上电流程等内容。

二、Camera 启动流程

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

08bb682884c86c6c3fb7725e88d01f78.png

(1) 这里先看enumerateSensor_Locked完成的工作,直接看代码:

  1. MUINT HalSensorList::searchSensors()
  2. {
  3. Mutex::Autolock _l(mEnumSensorMutex);
  4. MY_LOGD("searchSensors");
  5. return enumerateSensor_Locked();
  6. }
  7. MUINT HalSensorList::enumerateSensor_Locked()
  8. {
  9. SensorDrv *const pSensorDrv = SensorDrv::get();
  10. SeninfDrv *const pSeninfDrv = SeninfDrv::createInstance();
  11. //初始化seninf,配置ISP相关内容
  12. pSeninfDrv->init();
  13. //将所有的clk全部打开
  14. pSeninfDrv->setAllMclkOnOff(ISP_DRIVING_8MA, TRUE);
  15. pSensorDrv->init();
  16. for (MUINT i = IMGSENSOR_SENSOR_IDX_MIN_NUM; i <= max_index_of_camera; i++) {
  17. if((ret = pSensorDrv->searchSensor((IMGSENSOR_SENSOR_IDX)i)) == SENSOR_NO_ERROR){
  18. //query sensorinfo
  19. querySensorDrvInfo((IMGSENSOR_SENSOR_IDX)i);
  20. //fill in metadata
  21. buildSensorMetadata((IMGSENSOR_SENSOR_IDX)i);
  22. pSensorInfo = pSensorDrv->getSensorInfo((IMGSENSOR_SENSOR_IDX)i);
  23. addAndInitSensorEnumInfo_Locked(
  24. (IMGSENSOR_SENSOR_IDX)i,
  25. mapToSensorType(pSensorInfo->GetType()),
  26. pSensorInfo->getDrvMacroName());
  27. }
  28. }
  29. }

(2) 下面主要看下searchSensor的流程,这里有去获取sensorList的内容:

  1. MINT32 ImgSensorDrv::searchSensor(IMGSENSOR_SENSOR_IDX sensorIdx)
  2. {
  3. GetSensorInitFuncList(&pSensorInitFunc);
  4. featureControl(sensorIdx, SENSOR_FEATURE_SET_DRIVER, (MUINT8 *)&idx, &featureParaLen);
  5. NSFeature::SensorInfoBase* pSensorInfo = pSensorInitFunc[idx].pSensorInfo;
  6. }

GetSensorInitFuncList是获取到配置的sensorList的内容,此sensorList需要与kernel层配置的一致,不一致的话在打开camera时会出现异常:
文件位置:
vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/sensorlist.cpp

  1. MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
  2. {
  3. #if defined(IMX486_MIPI_RAW)
  4. RAW_INFO(IMX486_SENSOR_ID, SENSOR_DRVNAME_IMX486_MIPI_RAW, CAM_CALGetCalData),
  5. #endif
  6. //.....
  7. }
  8. UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT **ppSensorList)
  9. {
  10. if (NULL == ppSensorList) {
  11. ALOGE("ERROR: NULL pSensorList\n");
  12. return MHAL_UNKNOWN_ERROR;
  13. }
  14. *ppSensorList = &SensorList[0];
  15. return MHAL_NO_ERROR;
  16. }

对应的MSDK_SENSOR_INIT_FUNCTION_STRUCT的结构体如下:

  1. typedef struct
  2. {
  3. MUINT32 sensorType;
  4. MUINT32 SensorId;
  5. MUINT8 drvname[32];
  6. NSFeature::SensorInfoBase* pSensorInfo;
  7. MUINT32 (*getCameraIndexMgr)(CAMERA_DATA_TYPE_ENUM CameraDataType, MVOID *pDataBuf, MUINT32 size);
  8. MUINT32 (*getCameraCalData)(UINT32* pGetSensorCalData);
  9. } MSDK_SENSOR_INIT_FUNCTION_STRUCT, *PMSDK_SENSOR_INIT_FUNCTION_STRUCT;

(3) featureControlsetDriver流程:
文件位置:
vendor/mediatek/proprietary/hardware/mtkcam/drv/src/sensor/common/v1/imgsensor_drv.cpp

  1. MINT32 ImgSensorDrv::featureControl(
  2. IMGSENSOR_SENSOR_IDX sensorIdx,
  3. ACDK_SENSOR_FEATURE_ENUM FeatureId,
  4. MUINT8 *pFeaturePara,
  5. MUINT32 *pFeatureParaLen
  6. )
  7. {
  8. //结构ACDK_SENSOR_FEATURECONTROL_STRUCT和kernel中一致
  9. featureCtrl.InvokeCamera = sensorIdx;
  10. featureCtrl.FeatureId = FeatureId;//SENSOR_FEATURE_SET_DRIVER
  11. featureCtrl.pFeaturePara = pFeaturePara;
  12. featureCtrl.pFeatureParaLen = pFeatureParaLen;
  13. if (ioctl(m_fdSensor, KDIMGSENSORIOC_X_FEATURECONCTROL , &featureCtrl) < 0) {
  14. LOG_ERR("[featureControl] Err-ctrlCode (%s)", strerror(errno));
  15. return -errno;
  16. }
  17. return SENSOR_NO_ERROR;
  18. }

三、kernel 启动流程

先来看整体的框架图如下:

66ee089ccc96a81d935ae69e4cb1fe8b.png

1、set clock 设置时钟

  1. static long imgsensor_ioctl(
  2. struct file *a_pstFile,
  3. unsigned int a_u4Command,
  4. unsigned long a_u4Param)
  5. {
  6. case KDIMGSENSORIOC_X_SET_MCLK_PLL:
  7. i4RetValue = imgsensor_clk_set(
  8. &pgimgsensor->clk,
  9. (struct ACDK_SENSOR_MCLK_STRUCT *)pBuff);
  10. break;
  11. //......
  12. }
  13. int imgsensor_clk_set(
  14. struct IMGSENSOR_CLK *pclk, struct ACDK_SENSOR_MCLK_STRUCT *pmclk)
  15. {
  16. if (pmclk->on) {
  17. clk_prepare_enable(pclk->imgsensor_ccf[mclk_index])
  18. ret = clk_set_parent(
  19. pclk->imgsensor_ccf[pmclk->TG],
  20. pclk->imgsensor_ccf[mclk_index]);
  21. } else {
  22. clk_disable_unprepare(pclk->imgsensor_ccf[mclk_index]);
  23. }
  24. }

2、set driver

  1. static long imgsensor_ioctl(
  2. struct file *a_pstFile,
  3. unsigned int a_u4Command,
  4. unsigned long a_u4Param)
  5. {
  6. case KDIMGSENSORIOC_X_FEATURECONCTROL:
  7. i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
  8. break;
  9. //......
  10. }
  11. static inline int adopt_CAMERA_HW_FeatureControl(void *pBuf)
  12. {
  13. /* copy from user */
  14. switch (pFeatureCtrl->FeatureId) {
  15. case SENSOR_FEATURE_SET_DRIVER:
  16. {
  17. MINT32 drv_idx;
  18. psensor->inst.sensor_idx = pFeatureCtrl->InvokeCamera;
  19. drv_idx = imgsensor_set_driver(psensor);
  20. memcpy(pFeaturePara, &drv_idx, FeatureParaLen);
  21. break;
  22. }
  23. }
  24. }

遍历CONFIG_CUSTOM_KERNEL_IMGSENSOR的内容,然后看sensorList是否对应,并获取对应的下标,调用imgsensor_check_is_alive进行上下电并读取ID 的操作:

  1. struct IMGSENSOR_INIT_FUNC_LIST kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR] = {
  2. #if defined(XXXXXX_MIPI_RAW)
  3. {XXXXXX_SENSOR_ID,
  4. SENSOR_DRVNAME_XXXXXX_MIPI_RAW,
  5. XXXXXX_MIPI_RAW_SensorInit},
  6. #endif
  7. //......
  8. }
  9. int imgsensor_set_driver(struct IMGSENSOR_SENSOR *psensor)
  10. {
  11. struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
  12. struct IMGSENSOR_INIT_FUNC_LIST *pSensorList = kdSensorList;
  13. //获取config的size
  14. char *sensor_configs = STRINGIZE(CONFIG_CUSTOM_KERNEL_IMGSENSOR);
  15. imgsensor_i2c_init(&psensor_inst->i2c_cfg,
  16. imgsensor_custom_config[psensor->inst.sensor_idx].i2c_dev);
  17. memcpy(psensor_list_config, sensor_configs+1, strlen(sensor_configs)-2);
  18. //对应config字符串进行按空格进行拆解
  19. driver_name = strsep(&psensor_list_config, " \0");
  20. while (driver_name != NULL) {
  21. for (j = 0; j < MAX_NUM_OF_SUPPORT_SENSOR; j++) {
  22. //判断对应的init函数是否存在
  23. if (pSensorList[j].init == NULL)
  24. break;
  25. else if (!strcmp(driver_name, pSensorList[j].name)) {
  26. //如果在config中和sensorlist中同时有定义进行赋值
  27. orderedSearchList[i++] = j;
  28. break;
  29. }
  30. }
  31. driver_name = strsep(&psensor_list_config, " \0");
  32. }
  33. for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {
  34. //上面获取到的sensorlist的下标
  35. drv_idx = orderedSearchList[i];
  36. if (pSensorList[drv_idx].init) {
  37. //调用对应驱动的init函数
  38. pSensorList[drv_idx].init(&psensor->pfunc);
  39. if (psensor->pfunc) {
  40. psensor_inst->psensor_name =
  41. (char *)pSensorList[drv_idx].name;
  42. //到这里是重点,进行上电读取ID的操作
  43. if (!imgsensor_check_is_alive(psensor)) {
  44. ret = drv_idx;
  45. }
  46. }
  47. }
  48. }
  49. }

下面看对应的上下电以及读取ID的操作:

  1. static inline int imgsensor_check_is_alive(struct IMGSENSOR_SENSOR *psensor)
  2. {
  3. struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
  4. //上电
  5. err = imgsensor_hw_power(&pgimgsensor->hw,
  6. psensor,
  7. psensor_inst->psensor_name,
  8. IMGSENSOR_HW_POWER_STATUS_ON);
  9. //读取ID
  10. imgsensor_sensor_feature_control(
  11. psensor,
  12. SENSOR_FEATURE_CHECK_SENSOR_ID,
  13. (MUINT8 *)&sensorID,
  14. &retLen);
  15. if (sensorID == 0 || sensorID == 0xFFFFFFFF) {
  16. pr_info("Fail to get sensor ID %x\n", sensorID);
  17. err = ERROR_SENSOR_CONNECT_FAIL;
  18. } else {
  19. pr_info(" Sensor found ID = 0x%x\n", sensorID);
  20. err = ERROR_NONE;
  21. }
  22. //下电
  23. imgsensor_hw_power(&pgimgsensor->hw,
  24. psensor,
  25. psensor_inst->psensor_name,
  26. IMGSENSOR_HW_POWER_STATUS_OFF);
  27. return err ? -EIO:err;
  28. }

3、上电相关

上电时序配置:

  1. struct IMGSENSOR_HW_POWER_INFO {
  2. enum IMGSENSOR_HW_PIN pin;
  3. enum IMGSENSOR_HW_PIN_STATE pin_state_on;
  4. u32 pin_on_delay;
  5. enum IMGSENSOR_HW_PIN_STATE pin_state_off;
  6. u32 pin_off_delay;
  7. };
  8. struct IMGSENSOR_HW_POWER_SEQ sensor_power_sequence[] = {
  9. //……
  10. #if defined(XXXXXX_MIPI_RAW)
  11. {
  12. SENSOR_DRVNAME_XXXXXX_MIPI_RAW,
  13. {
  14. {RST, Vol_Low, 0},
  15. {DVDD, Vol_1100, 1},
  16. {AVDD, Vol_2800, 1},
  17. {DOVDD, Vol_1800, 1},
  18. {RST, Vol_High, 1},
  19. {SensorMCLK, Vol_High, 0},
  20. },
  21. },
  22. #endif
  23. }

对应的控制的流程如下:

  1. static enum IMGSENSOR_RETURN imgsensor_hw_power_sequence(
  2. struct IMGSENSOR_HW *phw,
  3. enum IMGSENSOR_SENSOR_IDX sensor_idx,
  4. enum IMGSENSOR_HW_POWER_STATUS pwr_status,
  5. struct IMGSENSOR_HW_POWER_SEQ *ppower_sequence,
  6. char *pcurr_idx)
  7. {
  8. ppwr_info = ppwr_seq->pwr_info;
  9. // 上电
  10. while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE &&
  11. ppwr_info < ppwr_seq->pwr_info + IMGSENSOR_HW_POWER_INFO_MAX) {
  12. if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON &&
  13. ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
  14. pdev = phw->pdev[psensor_pwr->id[ppwr_info->pin]];
  15. if (pdev->set != NULL)
  16. //调用GPIO或者regulator的set 电压操作,这里的pdev在imgsensor_probe中已经设置
  17. pdev->set(
  18. pdev->pinstance,
  19. sensor_idx,
  20. ppwr_info->pin,
  21. ppwr_info->pin_state_on);
  22. mdelay(ppwr_info->pin_on_delay);
  23. }
  24. // 从上到下依次上电
  25. ppwr_info++;
  26. pin_cnt++;
  27. }
  28. // 下电操作
  29. if (pwr_status == IMGSENSOR_HW_POWER_STATUS_OFF) {
  30. while (pin_cnt) {
  31. //从下到上依次下电
  32. ppwr_info--;
  33. pin_cnt--;
  34. if (ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
  35. pdev =
  36. phw->pdev[psensor_pwr->id[ppwr_info->pin]];
  37. mdelay(ppwr_info->pin_on_delay);
  38. if (pdev->set != NULL)
  39. pdev->set(
  40. pdev->pinstance,
  41. sensor_idx,
  42. ppwr_info->pin,
  43. ppwr_info->pin_state_off);
  44. }
  45. }
  46. }
  47. /* wait for power stable */
  48. if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON)
  49. mdelay(5);
  50. return IMGSENSOR_RETURN_SUCCESS;
  51. }

四、总结

通过上面的代码流程,可以知道上开机时,camera模块先会将所有的MCLK打开,然后对依次对对应的sensor进行上电,读取ID(判断I2C是否正常通讯)。这部分调试过程中遇到的问题总结如下:

1、ID读取不到,I2C不通

  • 检查上电时序,3项电压(AVDD/DVDD/IOVDD)是否正确;

  • I2C地址及通道设置是否正确;

  • 检查cfg_setting_imgsensor.cppMCLKHW链接配置是否正确;

2、Camera 启动时间过长

  • 检查Sensor上电时序要求的延时,是否有偏长的情况;

  • 去掉多余的I2C地址,因为大部分驱动会多添加一些地址;

  • OTP的加载调整到每次开机时第一次打开加载,之后不加载;

  • sensorInit如果时间过长,可以调节I2C speed(400->1000)

3、preview 阶段耗时

  • 检查streamOn/Off的耗时;

  • preview_init是否有较长时间的耗时

  • 以及延时操作使用mdelay代替msleep

  • pre_delay_frame/cap_delay_frame丢帧操作是否合适;

4、低电流、功耗相关问题

  • 检查电压是否都有下电成功,防止漏电;

  • 对于共pinsensor,在操作时是否有做好workaround

  • I2C寄存器单个读写,调整为连续读写的方式也有一定优化;

  • sensorPIN是否有被其他模块占用,异常操作的行为;

友情推荐:

Android 开发干货集锦

至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

03b38985121e177bac9804493fb63001.jpeg

点个在看,方便您使用时快速查找!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/138938
推荐阅读
相关标签
  

闽ICP备14008679号