<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          MTK camera啟動流程

          共 11702字,需瀏覽 24分鐘

           ·

          2021-03-26 07:59

          和你一起終身學(xué)習(xí),這里是程序員Android

          經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識點:

          一、Camera 框架介紹:

          Camera的框架分為Kernel部分和hal部分,其中kernel部分主要有兩塊:

          • image sensor driver,負(fù)責(zé)具體型號的sensorid檢測,上電,以及在previewcapture初始化3A等等功能設(shè)定時的寄存器配置;

          • isp driver,通過DMAsensor數(shù)據(jù)流上傳;

          HAL層部分主要有三部分組成:

          • imageio,主要負(fù)責(zé)數(shù)據(jù)buffer上傳的pipe

          • drv,包含imgsensorisphal層控制;

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

          這篇內(nèi)容主要介紹開機過程中search sensor以及上電流程等內(nèi)容。

          二、Camera 啟動流程

          1、CameraService是在開機時啟動的,啟動后進(jìn)行searchSensor的操作,會search系統(tǒng)有多少camera,開機時的search操作,只進(jìn)行camera支持?jǐn)?shù)量的遍歷,以及sensor ID的讀取操作,如下是hal部分的ASTAH繪制調(diào)用流程圖,對應(yīng)的接口的文件路徑:

          • 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相關(guān)內(nèi)容
          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的內(nèi)容:

          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的內(nèi)容,此sensorList需要與kernel層配置的一致,不一致的話在打開camera時會出現(xiàn)異常:
          文件位置:
          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;
          }

          對應(yīng)的MSDK_SENSOR_INIT_FUNCTION_STRUCT的結(jié)構(gòu)體如下:

          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) featureControlsetDriver流程:
          文件位置:
          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
          )
          {
          //結(jié)構(gòu)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;
          }

          三、kernel 啟動流程

          先來看整體的框架圖如下:



            

          1、set clock 設(shè)置時鐘

          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]);
          }
          }

          2、set driver

          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的內(nèi)容,然后看sensorList是否對應(yīng),并獲取對應(yīng)的下標(biāo),調(diào)用imgsensor_check_is_alive進(jìn)行上下電并讀取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);
          //對應(yīng)config字符串進(jìn)行按空格進(jìn)行拆解
          driver_name = strsep(&psensor_list_config, " \0");

          while (driver_name != NULL) {
          for (j = 0; j < MAX_NUM_OF_SUPPORT_SENSOR; j++) {
          //判斷對應(yīng)的init函數(shù)是否存在
          if (pSensorList[j].init == NULL)
          break;
          else if (!strcmp(driver_name, pSensorList[j].name)) {
          //如果在config中和sensorlist中同時有定義進(jìn)行賦值
          orderedSearchList[i++] = j;
          break;
          }
          }
          driver_name = strsep(&psensor_list_config, " \0");
          }

          for (i = 0; i < MAX_NUM_OF_SUPPORT_SENSOR; i++) {
          //上面獲取到的sensorlist的下標(biāo)
          drv_idx = orderedSearchList[i];
          if (pSensorList[drv_idx].init) {
          //調(diào)用對應(yīng)驅(qū)動的init函數(shù)
          pSensorList[drv_idx].init(&psensor->pfunc);
          if (psensor->pfunc) {
          psensor_inst->psensor_name =
          (char *)pSensorList[drv_idx].name;
          //到這里是重點,進(jìn)行上電讀取ID的操作
          if (!imgsensor_check_is_alive(psensor)) {
          ret = drv_idx;
          }
          }
          }
          }
          }

          下面看對應(yīng)的上下電以及讀取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;
          }

          3、上電相關(guān)

          上電時序配置:

          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
          }

          對應(yīng)的控制的流程如下:

          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)
          //調(diào)用GPIO或者regulator的set 電壓操作,這里的pdev在imgsensor_probe中已經(jīng)設(shè)置
          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;
          }

          四、總結(jié)

          通過上面的代碼流程,可以知道上開機時,camera模塊先會將所有的MCLK打開,然后對依次對對應(yīng)的sensor進(jìn)行上電,讀取ID(判斷I2C是否正常通訊)。這部分調(diào)試過程中遇到的問題總結(jié)如下:

          1、ID讀取不到,I2C不通

          • 檢查上電時序,3項電壓(AVDD/DVDD/IOVDD)是否正確;

          • I2C地址及通道設(shè)置是否正確;

          • 檢查cfg_setting_imgsensor.cppMCLKHW鏈接配置是否正確;

          2、Camera 啟動時間過長

          • 檢查Sensor上電時序要求的延時,是否有偏長的情況;

          • 去掉多余的I2C地址,因為大部分驅(qū)動會多添加一些地址;

          • OTP的加載調(diào)整到每次開機時第一次打開加載,之后不加載;

          • sensorInit如果時間過長,可以調(diào)節(jié)I2C speed(400->1000)

          3、preview 階段耗時

          • 檢查streamOn/Off的耗時;

          • preview_init是否有較長時間的耗時

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

          • pre_delay_frame/cap_delay_frame丟幀操作是否合適;

          4、低電流、功耗相關(guān)問題

          • 檢查電壓是否都有下電成功,防止漏電;

          • 對于共pinsensor,在操作時是否有做好workaround

          • I2C寄存器單個讀寫,調(diào)整為連續(xù)讀寫的方式也有一定優(yōu)化;

          • sensorPIN是否有被其他模塊占用,異常操作的行為;

          友情推薦:

          Android 開發(fā)干貨集錦

          至此,本篇已結(jié)束。轉(zhuǎn)載網(wǎng)絡(luò)的文章,小編覺得很優(yōu)秀,歡迎點擊閱讀原文,支持原創(chuàng)作者,如有侵權(quán),懇請聯(lián)系小編刪除,歡迎您的建議與指正。同時期待您的關(guān)注,感謝您的閱讀,謝謝!

          點個在看,方便您使用時快速查找!

          瀏覽 102
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲色图成人网站 | 丁香花五月激情 | 爱爱短视频电影无码免费 | 欧美操逼视频在线观看 | 免费黄色国产在线 |