拍照时闪光灯调用HAL层到driver层流程

文章目录

    • @[toc]
  • HAL层
    • HAL层闪光灯调用具体函数执行流程
      • Hal3AIf::getInstance的实现
      • Hal3AFlowCtrl::getInstance的实现
      • Hal3AFlowCtrl::init的实现
      • IThread3A::createInstance的实现
      • Thread3AImp::createInstance的实现
      • Thread3AImp::Thread3AImp的实现
      • Thread3AImp::createThread的实现
      • Thread3AImp::onThreadLoop的实现
      • Thread3AImp::getCommand的实现
      • Hal3AFlowCtrl::doUpdateCmd的实现
      • Hal3AFlowCtrl::postCommand的实现
      • Hal3ARawImp::chkPreFlashOnCond的实现
      • Hal3AFlowCtrl::notifyP1Done的实现
      • Hal3ARawImp::setFlashLightOnOff的实现
      • FlashHal::setOnOff的实现
      • StrobeDrvFlashlight::setOnOff 的实现
      • StrobeDrvFlashlightFops::sendCommand的实现
  • KERNEL层
    • flash驱动加载流程
      • flashlight_init的实现
      • flashlight_platform_driver结构体的实现
      • flashlight_probe的实现
      • flashlight_led191_init的实现
      • led191_probe的实现
      • led191_pinctrl_init的实现
      • led191_parse_dt的实现
      • flashlight_dev_register_by_device_id的实现
      • led191_ops结构体的实现
      • led191_ioctl的实现
      • led191_enable和led191_disable的实现
      • led191_pinctrl_set的实现
      • led191_strobe_store的实现
      • led191_set_driver的实现
      • led191_init的实现
平台 MT6739
版本 Android 9.0

HAL层

HAL层闪光灯调用具体函数执行流程

Hal3AIf::getInstance的实现

打开相机APK时调用的初始化函数

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/aaa_hal_if.cpp

Hal3AIf::getInstanceMINT32 const i4SensorOpenIndex, E_FlowControl_Type eType, MINT32 i4SubsampleCount)
{CAM_LOGD"[%s] sensoridx%d)", __FUNCTION__, i4SensorOpenIndex);switch eType){case Hal3AIf::E_FlowControl_Type_SMVR:return Hal3AFlowCtrl_SMVR::getInstancei4SensorOpenIndex, i4SubsampleCount);case Hal3AIf::E_FlowControl_Type_NORMAL:return Hal3AFlowCtrl::getInstancei4SensorOpenIndex);default:return NULL;}
}

Hal3AFlowCtrl::getInstance的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Hal3AFlowCtrl.cpp

Hal3AIf*
Hal3AFlowCtrl::
getInstanceMINT32 i4SensorOpenIndex)
{IHalSensorList* const pHalSensorList = MAKE_HalSensorList);if !pHalSensorList) return NULL;MINT32 i4SensorDev = pHalSensorList->querySensorDevIdxi4SensorOpenIndex);switch i4SensorDev){case SENSOR_DEV_MAIN:{static Hal3AFlowCtrl _singletonSENSOR_DEV_MAIN);_singleton.initi4SensorOpenIndex);return &_singleton;}case SENSOR_DEV_SUB:{static Hal3AFlowCtrl _singletonSENSOR_DEV_SUB);_singleton.initi4SensorOpenIndex);return &_singleton;}case SENSOR_DEV_MAIN_2:{static Hal3AFlowCtrl _singletonSENSOR_DEV_MAIN_2);_singleton.initi4SensorOpenIndex);return &_singleton;}case SENSOR_DEV_SUB_2:{static Hal3AFlowCtrl _singletonSENSOR_DEV_SUB_2);_singleton.initi4SensorOpenIndex);return &_singleton;}case SENSOR_DEV_MAIN_3:{static Hal3AFlowCtrl _singletonSENSOR_DEV_MAIN_3);_singleton.initi4SensorOpenIndex);return &_singleton;}default:CAM_LOGE"Unsupport sensor device ID: %d\n", i4SensorDev);AEE_ASSERT_3A_HAL"Unsupport sensor device.");return MNULL;}
}

Hal3AFlowCtrl::init的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Hal3AFlowCtrl.cpp

MRESULT
Hal3AFlowCtrl::
initMINT32 i4SensorOpenIndex) //can be called only once by RAW or YUV, no user count
{MY_LOGD"[%s] +", __FUNCTION__);m_fgLogEn = ::property_get_int32"vendor.debug.camera.log", 0);if  m_fgLogEn == 0 ) {m_fgLogEn = ::property_get_int32"vendor.debug.camera.log.hal3a", 0);}m_u4FrmIdFreeze = ::property_get_int32"vendor.debug.3a.freeze", 0);m_bRRZDump = 0;m_fgDebugLogWEn = DebugUtil::getDebugLevelDBG_3A);IHalSensorList*const pHalSensorList = MAKE_HalSensorList);if !pHalSensorList) return 0;#if CAM3_3ATESTLVL <= CAM3_3AUT)I3AWrapper::E_TYPE_T eType = I3AWrapper::E_TYPE_DFT;
#elseMINT32 eSensorType = pHalSensorList->queryTypei4SensorOpenIndex);I3AWrapper::E_TYPE_T eType = I3AWrapper::E_TYPE_RAW;switch eSensorType){case NSSensorType::eRAW:eType = I3AWrapper::E_TYPE_RAW;break;case NSSensorType::eYUV:eType = I3AWrapper::E_TYPE_YUV;break;default:eType = I3AWrapper::E_TYPE_DFT;break;}
#endifm_i4SensorOpenIdx = i4SensorOpenIndex;// create 3A wrapperif m_p3AWrap == NULL){m_p3AWrap = I3AWrapper::getInstanceeType, i4SensorOpenIndex);if m_p3AWrap){MY_LOGD_IFm_fgLogEn, "[%s] m_p3AWrapper%p) created OK", __FUNCTION__, m_p3AWrap);}else{CAM_LOGE"m_p3AWrapper created fail!");AEE_ASSERT_3A_HAL"m_p3AWrapper created fail!");}}// create Vsync event//IEventIrq::ConfigParam IrqConfigi4SensorDev, i4SensorOpenIndex, 5000, IEventIrq::E_Event_Vsync);//m_pEventIrq = IEventIrq::createInstanceIrqConfig, "VSIrq");m_SttBufQEnable = property_get_int32"vendor.debug.camera.SttBufQ.enable", 0);if m_SttBufQEnable) {ISttBufQ::createSingletonm_i4SensorDev, LOG_TAG);}// create statistic control
#if CAM3_3ATESTLVL >= CAM3_3ASTTUT)if m_p3ASttCtrl == NULL  && eType == I3AWrapper::E_TYPE_RAW){m_p3ASttCtrl = Hal3ASttCtrl::createInstancem_i4SensorDev, i4SensorOpenIndex);if m_p3ASttCtrl){MY_LOGD_IFm_fgLogEn, "[%s] m_p3ASttCtrl%p) created OK", __FUNCTION__, m_p3ASttCtrl);}else{CAM_LOGE"m_p3ASttCtrl created fail!");AEE_ASSERT_3A_HAL"m_p3ASttCtrl created fail!");}}
#endif// create AA threadif m_pThread == NULL){/* 闪光灯的相关操作在这个线程中实现 */m_pThread = IThread3A::createInstancethis);if m_pThread){MY_LOGD_IFm_fgLogEn, "[%s] m_pThread%p) created OK", __FUNCTION__, m_pThread);}else{CAM_LOGE"m_pThread created fail!");AEE_ASSERT_3A_HAL"m_pThread created fail!");}}// ResultPool - Get result pool objectifm_pResultPoolObj == NULL)m_pResultPoolObj = IResultPool::getInstancem_i4SensorDev);ifm_pResultPoolObj == NULL)CAM_LOGE"ResultPool getInstance fail");MY_LOGD"[%s] - eType%d), sensor%d), sensorIdx%d)", __FUNCTION__, eType, m_i4SensorDev, i4SensorOpenIndex);return S_3A_OK;
}

IThread3A::createInstance的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Thread3AImp.cpp

IThread3A*
IThread3A::createInstanceHal3AIf* pHal3A)
{return Thread3AImp::createInstancepHal3A);
}

Thread3AImp::createInstance的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Thread3AImp.cpp

IThread3A*
Thread3AImp::
createInstanceHal3AIf* pHal3A)
{//static Thread3AImp singletonpHal3A);//singleton.createThread);   // user count protected//return &singleton;Thread3AImp* pThd3A = new Thread3AImppHal3A);//if pThd3A)//pThd3A->createThread);return pThd3A;
}

Thread3AImp::Thread3AImp的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Thread3AImp.cpp

Thread3AImp::
Thread3AImpHal3AIf* pHal3A): mpHal3ApHal3A), mu4LogEnMFALSE), mbListenUpdateMFALSE), mbSetFromP1MFALSE), mLock)
{MY_LOGD"[%s] Enter %d)", __FUNCTION__, pHal3A->getSensorDev));createThread);
}

Thread3AImp::createThread的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Thread3AImp.cpp

MVOID
Thread3AImp::createThread)
{//Mutex::Autolock lockmLock);  // Nelson : mutual exclusive by atomic_flagGET_PROP"vendor.debug.3a.log", 0, mu4LogEn);mu4DebugLogWEn = DebugUtil::getDebugLevelDBG_3A);if !thread_alive.test_and_set)){MY_LOGD"[%s] +", __FUNCTION__);sem_init&mSem, 0, 0);//pthread_create&mThread, NULL, onThreadLoop, this);create3Athread = threadonThreadLoop, this);MY_LOGD"[%s] -", __FUNCTION__);}
}

在打开相机APK后,会通过 Thread3AImp::createThread) 函数创建并执行了线程 create3Athread ,它最终会调用 Thread3AImp::onThreadLoop) 方法

Thread3AImp::onThreadLoop的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Thread3AImp.cpp

MVOID*
Thread3AImp::onThreadLoopMVOID *arg)
{MY_LOGD"+");CmdQ_T rCmdECmd_Update, ParamIspProfile_T));Thread3AImp *_this = reinterpret_cast<Thread3AImp*>arg);
//    AaaTimer ccTimer;MBOOL bGetCmd;MBOOL fgLogEn = _this->mu4LogEn & EN_LOG_3A_THREAD) ? MTRUE : MFALSE;MUINT32 cmdQSize = 0;// 1) change thread setting_this->changeThreadSetting);// 2) thread-in-loopwhile _this->getCommandrCmd, bGetCmd, MFALSE)) /* 从 getCommand) 中获取rCmd的值 */{//MY_LOGD_IF1, "rCmd%d)+", rCmd);//DebugUtil::getInstance_this->mpHal3A->getSensorDev))->updateLOG_TAG, "onThreadLoop", 0);switch rCmd.eCmd){case ECmd_Update:if !_this->mbListenUpdate){MY_LOGD"[%s] Exit 3A thread", __FUNCTION__);break;}MY_LOGD_IFfgLogEn, "rCmd%d)+", rCmd.eCmd);DebugUtil::getInstance_this->mpHal3A->getSensorDev))->updateLOG_TAG, "onThreadLoop", 1);/* 在这函数里不断通过 post_commnad 发送 ECmd_Update 命令 */if !_this->mpHal3A->doUpdateCmd&rCmd.rParamIspProfile))//on3aprocfinish{char strErr[512] = {'\0'};sprintfstrErr, "ECmd_Update failed #%d)", rCmd.rParamIspProfile.i4MagicNum);CAM_LOGE"%s", strErr);AEE_ASSERT_3A_HALstrErr);}if !_this->mbSetFromP1) //only check before first set from MW{if rCmd.rParamIspProfile.iValidateOpt != ParamIspProfile_T::EParamValidate_None){MY_LOGD"[%s] First command from P1",__FUNCTION__);_this->mbSetFromP1 = MTRUE;}}DebugUtil::getInstance_this->mpHal3A->getSensorDev))->updateLOG_TAG, "onThreadLoop", 2);_this->mpHal3A->on3AProcSet_this->mbSetFromP1);//vsync callbackDebugUtil::getInstance_this->mpHal3A->getSensorDev))->updateLOG_TAG, "onThreadLoop", 3);{Mutex::Autolock autoLock_this->mModuleMtx);cmdQSize = _this->mCmdQ.size);}if cmdQSize){MY_LOGD_IFfgLogEn, "[%s] Cmd from P1", __FUNCTION__);}else{if _this->mbSetFromP1){_this->mpHal3A->doUpdateCmdDummy);MY_LOGD_IFfgLogEn, "[%s] Dummy cmd from 3A Thread", __FUNCTION__);}}MY_LOGD_IFfgLogEn, "rCmd%d), magic#%d)-", rCmd.eCmd, rCmd.rParamIspProfile.i4MagicNum);break;default:AAA_TRACE_HALThread3A_CmdDefault);MY_LOGD_IFfgLogEn, "rCmd%d)+", rCmd.eCmd);//DebugUtil::getInstance_this->mpHal3A->getSensorDev))->updateLOG_TAG, "onThreadLoop", 4);if  ! _this->mpHal3A->postCommandrCmd.eCmd, &rCmd.rParamIspProfile)){CAM_LOGE"Cmd%d) failed", rCmd.eCmd);AEE_ASSERT_3A_HAL"onThreadLoop postCommand fail2).");}//if rCmd.eCmd != ECmd_PrecaptureStart && rCmd.eCmd != ECmd_PrecaptureEnd){::sem_post&_this->mSem);}MY_LOGD_IFfgLogEn, "rCmd%d), magic#%d)-", rCmd.eCmd, rCmd.rParamIspProfile.i4MagicNum);AAA_TRACE_END_HAL;break;}DebugUtil::getInstance_this->mpHal3A->getSensorDev))->updateLOG_TAG, "onThreadLoop", -1);//}MY_LOGD"-");return NULL;
}

onThreadLoop 这个函数名就可以知道,在这个线程内会不断的进行循环操作,直到退出相机APK。具体的循环操作是在 while _this->getCommandrCmd, bGetCmd, MFALSE)) 中实现的。由上述代码可知,当从 _this->getCommand) 中获取的 rCmd.eCmd 等于 ECmd_Update 时,会一直处于拍照前的预览状态,并不断的调用 if !_this->mpHal3A->doUpdateCmd&rCmd.rParamIspProfile)) 刷新预览界面,而当发生其他操作,比如开始拍照,则会调用 default 下的 if ! _this->mpHal3A->postCommandrCmd.eCmd, &rCmd.rParamIspProfile))ECmd_Update 切换成其他的状态。

Thread3AImp::getCommand的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Thread3AImp.cpp

MBOOL
Thread3AImp::getCommandIThread3A::CmdQ_T &rCmd, MBOOL &bGetCmd, MBOOL en_timeout)
{//returning MFALSE means break onThreadLoopMBOOL fgLogEn = mu4LogEn & EN_LOG_3A_THREAD) ? MTRUE : MFALSE;MY_LOGD_IFfgLogEn, "[%s] +", __FUNCTION__);Mutex::Autolock autoLockmModuleMtx);MY_LOGD_IFfgLogEn, "[%s] mCmdQ.size)=%d, en_timeout%d)", __FUNCTION__, MINT32)mCmdQ.size), en_timeout);if mCmdQ.size) == 0){if en_timeout){MY_LOGD_IFfgLogEn, "[%s] mCmdQCond.waitRelative +", __FUNCTION__);mCmdQCond.waitRelativemModuleMtx, long long int)27000000);MY_LOGD_IFfgLogEn, "[%s] mCmdQCond.waitRelative -", __FUNCTION__);}else{MY_LOGD_IFfgLogEn, "[%s] mCmdQCond.wait +", __FUNCTION__);mCmdQCond.waitmModuleMtx);MY_LOGD_IFfgLogEn, "[%s] mCmdQCond.wait -", __FUNCTION__);}}if mCmdQ.size) == 0) //this is only for en_timeout == 1 & timeout case{MY_LOGD_IFfgLogEn, "[%s] mCmdQ.size) = %d after mCmdQCond.wait/waitRelative\n", __FUNCTION__, MINT32)mCmdQ.size));bGetCmd = MFALSE; // timeout, no command receivedreturn MTRUE;}bGetCmd = MTRUE;// two cases: 1. en_timeout == 1, but get command in time//                 2. en_timeout == 0, finally get commandrCmd = *mCmdQ.begin);MY_LOGD_IFfgLogEn, "CmdQ-size%d), todo%d, %d)", MINT32)mCmdQ.size), rCmd.eCmd, rCmd.rParamIspProfile.i4MagicNum);mCmdQ.erasemCmdQ.begin));return rCmd.eCmd != ECmd_Uninit;
}

相机APK所处状态的更新最终是由 *rCmd = mCmdQ.begin); 获取的,然后通过 return rCmd.eCmd != ECmd_Uninit; 输出返回值。当相机APK退出的时候,rCmd.eCmd 的值为10,此时等于 ECmd_Uninit ,所以 rCmd.eCmd != ECmd_Uninitfalse,此时跳出 while _this->getCommandrCmd, bGetCmd, MFALSE)) 循环。

Hal3AFlowCtrl::doUpdateCmd的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Hal3AFlowCtrl.cpp

MBOOL
Hal3AFlowCtrl::
doUpdateCmdconst ParamIspProfile_T* pParam)
{MINT32 i4MagicNum = pParam->i4MagicNum;if m_pThread->isEnd) || m_fgPreStop){MY_LOGD"[%s] Stop updating #%d)", __FUNCTION__, i4MagicNum);return MTRUE;}//call notifyResult4TG APIifm_bTgIntAEEn){// ResultPool - Get HistoryMINT32 rHistoryReqMagic[HistorySize] = {0,0,0};m_pResultPoolObj->getHistoryrHistoryReqMagic);MY_LOGD_IFm_fgLogEn, "[%s] History Req0, Req1, Req2) = #%d, #%d, #%d)", __FUNCTION__, rHistoryReqMagic[0], rHistoryReqMagic[1], rHistoryReqMagic[2]);//call notifyResult4TG APIMY_LOGD_IFm_fgLogEn, "[%s] notifyResult4TG Previous Req #%d) New Req #%d) bTgIntAEEn%d)",__FUNCTION__, rHistoryReqMagic[1], i4MagicNum, m_bTgIntAEEn);ifrHistoryReqMagic[1] != 0)notifyResult4TGrHistoryReqMagic[1]);}AAA_TRACE_D"3A_Update #%d)", i4MagicNum);/* 这里发送的命令会更新状态 */MBOOL fgRet = postCommandECmd_Update, pParam);AAA_TRACE_END_D;if !fgRet){CAM_LOGE"ECmd_Update failed");return MFALSE;}ifm_fgPreStop){MY_LOGD"[%s] Stop wait vsirq #%d)", __FUNCTION__, i4MagicNum);return MTRUE;}IEventIrq::Duration duration;MY_LOGD_IFm_fgLogEn, "[%s] start waitVSirq.", __FUNCTION__);AAA_TRACE_D"3A_WaitVSync #%d)", i4MagicNum);AAA_TRACE_DRVWaitVSync);m_pEventIrq->waitduration);
#if CAM3_3A_ISP_30_EN)// Apply 3A ISP info at the time after Vsync isp 3.0 only)m_p3AWrap->set3AISPInfo);
#endif//AAA_TRACE_END_DRV;AAA_TRACE_END_D;return MTRUE;
}

当进入相机APK,但还没有开始拍照时,会不断调用 doUpdateCmd) 函数更新相机闪光灯的状态,即不断的执行 MBOOL fgRet = postCommandECmd_Update, pParam); 这条代码直到退出相机APK。

打开闪光灯

Hal3AFlowCtrl::postCommand的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Hal3AFlowCtrl.cpp

MBOOL
Hal3AFlowCtrl::
postCommandECmd_T const eCmd, const ParamIspProfile_T* pParam)
{MY_LOGD_IFm_fgLogEn, "[%s] enter%d)", __FUNCTION__, eCmd);MINT32 i4MagicNum = 0;MINT32 i4MagicNumCur = 0;MBOOL bMainFlash = MFALSE;MBOOL bPre = MFALSE;ParamIspProfile_T rParamIspProf = *pParam;m_rCapParam.u4CapType = E_CAPTURE_NORMAL;if eCmd == ECmd_CameraPreviewStart) /* 刚打开相机APK以及拍完照后条件会成立,但只会调用一次 */{MY_LOGD"[%s] Clear ResultPool", __FUNCTION__);// ResultPool - preview start to clear ResultPoolm_pResultPoolObj->clearAllResultPool);m_rParam.i8ExposureTime = 0;if m_pEventIrq == NULL){IEventIrq::ConfigParam IrqConfigm_i4SensorDev, m_i4SensorOpenIdx, 5000000, IEventIrq::E_Event_Vsync);IrqConfig.i4TgInfo = m_i4TgInfo;m_pEventIrq = IEventIrq::createInstanceIrqConfig, "VSIrq");}
#if CAM3_3ATESTLVL >= CAM3_3ASTTUT)ifm_p3ASttCtrl)m_p3ASttCtrl->startStt);
#endifm_p3AWrap->start);}if eCmd == ECmd_Update){MY_LOGD"[%s] m_rParam.u4AeMode%d), m_rParam.i8ExposureTime%lld), iValidateOpt%d)", __FUNCTION__, MINT32)m_rParam.u4AeMode, long long)m_rParam.i8ExposureTime, rParamIspProf.iValidateOpt);/* rParamIspProf.iValidateOpt 的值默认是1,但需要开启闪光灯时会切换成0 */if rParamIspProf.iValidateOpt != ParamIspProfile_T::EParamValidate_None){i4MagicNum = rParamIspProf.i4MagicNum;i4MagicNumCur = rParamIspProf.i4MagicNumCur;bMainFlash = m_p3AWrap->chkMainFlashOnCond);bPre = m_p3AWrap->chkPreFlashOnCond);rParamIspProf.bMainFlash = bMainFlash;MY_LOGD_IFm_fgLogEn, "[%s] bMainFlash,bPre):%d,%d)", __FUNCTION__, bMainFlash,bPre);if bMainFlash||bPre) && i4MagicNum != 0){m_u4FlashOnIdx = i4MagicNum;m_fgFlashOn = 1;}if bMainFlash) /* bMainFlash 需要为 true */{/* 这里开启闪光灯 */m_p3AWrap->setFlashLightOnOff1, 1);m_i4MainFlashOnIdx = i4MagicNum;m_fgInternalFlashOn = MFALSE;}if bPre) {m_p3AWrap->setFlashLightOnOff1, 0);m_fgInternalFlashOn = MFALSE;}m_p3AWrap->postCommandeCmd, &rParamIspProf);if m_p3AWrap->chkCapFlash)){m_rCapParam.u4CapType = E_CAPTURE_HIGH_QUALITY_CAPTURE;}MY_LOGD_IFm_fgLogEn, "[%s][HQC] inform p1 capture type %d)", __FUNCTION__, m_rCapParam.u4CapType);i4MagicNumCur = m_p3AWrap->queryMagicNumber);MY_LOGD_IFm_fgLogEn, "[%s] Req, Stt) = #%d, #%d)", __FUNCTION__, i4MagicNum, i4MagicNumCur);// ResultPool - must update u4MagicNumCur to resultPool i4StatiticMagicMBOOL ret = m_pResultPoolObj->updateResultCFGi4MagicNum, i4MagicNumCur); //update ReqResult i4StatiticMagic of CFGif!ret)MY_LOGE"[%s] update MagicNumCur to resultPool i4StatiticMagic fail", __FUNCTION__);// i4StatiticMagic for high qualityAAA_TRACE_HALon3AProcFinish);on3AProcFinishi4MagicNum, i4MagicNumCur);AAA_TRACE_END_HAL;}else {if m_rParam.u4AeMode == 0 && m_rParam.i8ExposureTime >= 400000000){m_p3AWrap->postCommandeCmd, &rParamIspProf);}else{// dummy frame  need to enqueueHwBufHal3ASttCtrl* p3ASttCtrl = Hal3ASttCtrl::getInstancem_i4SensorDev);// enque AAOIBufMgr* pAAOBufMgr = p3ASttCtrl->getBufMgrBUF_AAO);ifpAAOBufMgr) pAAOBufMgr->enqueueHwBuf);}}IspTuningBufCtrl::getInstancem_i4SensorDev)->clearP1Buffer);}else{m_p3AWrap->postCommandeCmd, &rParamIspProf);}/* 拍照结束或者退出相机APK时,会调用 */if eCmd == ECmd_CameraPreviewEnd){MY_LOGD"[%s] reset bMainFlash", __FUNCTION__);m_u4FlashOnIdx = -1;#if CAM3_3ATESTLVL >= CAM3_3ASTTUT)ifm_p3ASttCtrl)m_p3ASttCtrl->stopStt);
#endifm_p3AWrap->stop);#if CAM3_3ATESTLVL >= CAM3_3ASTTUT)ifm_p3ASttCtrl)m_p3ASttCtrl->uninitStt);
#endifif m_pEventIrq){m_pEventIrq->destroyInstance"VSIrq");m_pEventIrq = NULL;}m_fgPreStop = MFALSE;}return MTRUE;
}

想要调用到 **m_p3AWrap->setFlashLightOnOff1, 1); ** 开启闪光灯,需要 bMainFlash 变量为 true , 而 bMainFlash 是通过 bMainFlash = m_p3AWrap->chkMainFlashOnCond); 这条代码进行赋值的。chkMainFlashOnCond) 在文件 Hal3ARawImp.cpp 中定义,具体代码如下:

Hal3ARawImp::chkPreFlashOnCond的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/isp_30/wrapper/Hal3ARawImp.cpp

MBOOL
Hal3ARawImp::
chkPreFlashOnCond) const
{// TorchFlashPolicy_T rFlashPolicy;rFlashPolicy.bIsFlashOnCapture = isFlashOnCapture);rFlashPolicy.bIsFlashCharging = FlashMgr::getInstancem_i4SensorDev)->getFlashState) == MTK_FLASH_STATE_CHARGING);FlashHal::getInstancem_i4SensorDev)->hasHwrFlashPolicy.i4HWSuppportFlash);CAM_LOGD_IFm_3ALogEnable, "[%s] bIsFlashOnCapture%d), bIsFlashCharging%d), i4HWSuppportFlash%d)", __FUNCTION__,rFlashPolicy.bIsFlashOnCapture,rFlashPolicy.bIsFlashCharging,rFlashPolicy.i4HWSuppportFlash);return HAL3A_POLICY_TORCH_ONOFFm_i4SensorDev, m_rParam, rFlashPolicy);
}
MBOOL
Hal3ARawImp::
chkMainFlashOnCond) const
{// Main FlashFlashPolicy_T rFlashPolicy;rFlashPolicy.bIsFlashOnCapture = isFlashOnCapture);rFlashPolicy.bIsFlashCharging = FlashMgr::getInstancem_i4SensorDev)->getFlashState) == MTK_FLASH_STATE_CHARGING);FlashHal::getInstancem_i4SensorDev)->hasHwrFlashPolicy.i4HWSuppportFlash);CAM_LOGD_IFm_3ALogEnable, "[%s] bIsFlashOnCapture%d), bIsFlashCharging%d), i4HWSuppportFlash%d)", __FUNCTION__,rFlashPolicy.bIsFlashOnCapture,rFlashPolicy.bIsFlashCharging,rFlashPolicy.i4HWSuppportFlash);return HAL3A_POLICY_MAIN_FLASH_ONOFFm_i4SensorDev, m_rParam, rFlashPolicy);
}

Hal3ARawImp::chkMainFlashOnCond)Hal3ARawImp::chkPreFlashOnCond) 函数会不断的被调用直到退出相机APK。同理,关闭闪光灯实际也会调用到这两个函数,相应的条件成立后才会调用 m_p3AWrap->setFlashLightOnOff0, 1); 关闭闪光灯。

关闭闪光灯

Hal3AFlowCtrl::notifyP1Done的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/hal3a/v1.0/Hal3AFlowCtrl.cpp

MVOID
Hal3AFlowCtrl::
notifyP1DoneMINT32 i4MagicNum, MVOID* /*pvArg*/)
{MBOOL bMainFlash = m_p3AWrap->chkMainFlashOnCond);MBOOL bPre = m_p3AWrap->chkPreFlashOnCond);MBOOL bMagicNum = i4MagicNum >= MINT32)m_u4FlashOnIdx);MY_LOGD_IFm_fgLogEn, "[%s] i4MagicNum%d), m_u4FlashOnIdx%d), bMagicNum%d), bMainFlash%d), bPre%d), m_fgFlashOn%d)", __FUNCTION__, i4MagicNum, m_u4FlashOnIdx, bMagicNum, bMainFlash, bPre, m_fgFlashOn);if  bMagicNum && !bMainFlash && !bPre && m_fgFlashOn){/* 这里关闭闪光灯 */m_p3AWrap->setFlashLightOnOff0, 1); // don't care main or prem_u4FlashOnIdx = -1;m_fgFlashOn = 0;}if bMagicNum && m_i4MainFlashOnIdx != -1){m_i4MainFlashOnIdx = -1;}MBOOL isNeedTurnOnPreFlash = m_p3AWrap->isNeedTurnOnPreFlash);MY_LOGD_IFm_fgLogEn,"[%s] isNeedTurnOnPreFlash%d)", __FUNCTION__, isNeedTurnOnPreFlash);ifm_fgInternalFlashOn != isNeedTurnOnPreFlash){m_fgInternalFlashOn = isNeedTurnOnPreFlash;MY_LOG"[%s] setPreFlashOnOff%d)", __FUNCTION__, m_fgInternalFlashOn);m_p3AWrap->setPreFlashOnOffisNeedTurnOnPreFlash);}if m_u4FrmIdFreeze != 0) && static_cast<MUINT32>i4MagicNum) == m_u4FrmIdFreeze)){MY_LOGD"[%s]+ one-shot dump @%d", __FUNCTION__, i4MagicNum);m_p3AWrap->dumpP1Paramsi4MagicNum);::property_set"vendor.debug.rrz.dump", 0);m_u4FrmIdFreeze = 0;MY_LOGD"[%s]- one-shot dump @%d", __FUNCTION__, i4MagicNum);}
}

控制闪光灯开启和关闭的方法

Hal3ARawImp::setFlashLightOnOff的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/isp_30/wrapper/Hal3ARawImp.cpp

MBOOL
Hal3ARawImp::
setFlashLightOnOffMBOOL bOnOff, MBOOL bMainPre)
{
#if CAM3_FLASH_FEATURE_ENCAM_LOGD_IFm_3ALogEnable, "[%s] bOnOff%d) + ", __FUNCTION__, bOnOff);if m_bIsFlashOpened == bOnOff){CAM_LOGD"[%s] flashlight unchanged, bOnOff%d)", __FUNCTION__, bOnOff);}else if !bOnOff){//modified to update strobe state after capture for ae managerIAeMgr::getInstance).setStrobeModem_i4SensorDev, MFALSE);IAwbMgr::getInstance).setStrobeModem_i4SensorDev, AWB_STROBE_MODE_OFF);if bMainPre)FlashHal::getInstancem_i4SensorDev)->setOnOffMFALSE, FLASH_HAL_SCENARIO_MAIN_FLASH);elseFlashHal::getInstancem_i4SensorDev)->setOnOffMFALSE, FLASH_HAL_SCENARIO_VIDEO_TORCH);}else //flash on{if bMainPre){FlashHal::getInstancem_i4SensorDev)->setOnOffMTRUE, FLASH_HAL_SCENARIO_MAIN_FLASH);IAwbMgr::getInstance).SetMainFlashInfom_i4SensorDev, MTRUE);}else{FlashHal::getInstancem_i4SensorDev)->setOnOffMTRUE, FLASH_HAL_SCENARIO_VIDEO_TORCH);IAwbMgr::getInstance).setStrobeModem_i4SensorDev, AWB_STROBE_MODE_ON);}}ifm_bIsFlashOpened != bOnOff){CAM_LOGD"[%s] flashlight is changed %d->%d), and assign bOnOff to m_bIsFlashOpened", __FUNCTION__, m_bIsFlashOpened, bOnOff);m_bIsFlashOpened = bOnOff;handleBadPicturem_rParam.i4MagicNum);}CAM_LOGD_IFm_3ALogEnable, "[%s] - ", __FUNCTION__);
#endifreturn MTRUE;
}

FlashHal::setOnOff的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/flash_mgr/flash_hal.cpp

int FlashHal::setOnOffint enable, FLASH_HAL_SCENARIO_ENUM scenario)
{logI"setOnOff): type%d), enable%d), scenario%d).", mStrobeTypeId, enable, scenario);/* verify arguments */if verifyScenarioscenario)) {logE"setOnOff): invalid arguments.");return -1;}if !isAvailable)) {logI"setOnOff): sensorDev%d) not available.", mSensorDev);return -1;}if scenario == FLASH_HAL_SCENARIO_MAIN_FLASH) {/* get timeout */int currentTime = getMs);if enable) {mFlashHalTimeInfo.mfStartTime = currentTime;mFlashHalTimeInfo.mfIsTimeout = 0;mFlashHalTimeInfo.mfTimeout = mFlashHalInfo[FLASH_HAL_SCENARIO_MAIN_FLASH].timeout;if mStrobeCtNum > 1)mFlashHalTimeInfo.mfTimeoutLt = mFlashHalInfo[FLASH_HAL_SCENARIO_MAIN_FLASH].timeoutLt;} else {mFlashHalTimeInfo.mfEndTime = currentTime;int flashOnPeriod = mFlashHalTimeInfo.mfEndTime - mFlashHalTimeInfo.mfStartTime;if flashOnPeriod > mFlashHalTimeInfo.mfTimeout &&mFlashHalTimeInfo.mfTimeout)mFlashHalTimeInfo.mfIsTimeout = 1;if mStrobeCtNum > 1)if flashOnPeriod > mFlashHalTimeInfo.mfTimeoutLt &&mFlashHalTimeInfo.mfTimeoutLt)mFlashHalTimeInfo.mfIsTimeout = 1;}}/* set flash info to ISP */ // TODO: moveoutif scenario != FLASH_HAL_SCENARIO_TORCH) {FLASH_INFO_T finfo;finfo.flashMode = FLASHLIGHT_FORCE_OFF; // TODO: not usefinfo.isFlash = enable;//IspTuningMgr::getInstance).setFlashInfomSensorDev, finfo);}if enable)return setFlashOnmFlashHalInfo[scenario]);elsereturn setFlashOff);
}

开启闪光灯

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/flash_mgr/flash_hal.cpp

int FlashHal::setFlashOnFlashHalInfo info)
{Mutex::Autolock lockmLock);logI"setFlashOn): duty%d), timeout%d), lt duty%d), lt timeout%d).",info.duty, info.timeout, info.dutyLt, info.timeoutLt);int isLow = 0;isLowPower&isLow);if isLow) {logI"setFlashOn): is low power.");return 0;}/* set duty */int dutyCur;int dutyCurLt;{mpStrobe->getDuty&dutyCur);if dutyCur != info.duty)mpStrobe->setDutyinfo.duty);}if mStrobeCtNum > 1) {mpStrobe2->getDuty&dutyCurLt);if dutyCurLt != info.dutyLt)mpStrobe2->setDutyinfo.dutyLt);}/* set on/off */int bOn;{mpStrobe->isOn&bOn);if info.duty < 0) {/* 实际调用的是 StrobeDrvFlashlight::setOnOff */mpStrobe->setOnOff0); } else {mpStrobe->setTimeOutTimeinfo.timeout);mpStrobe->setOnOff1);}}if mStrobeCtNum > 1) {mpStrobe2->isOn&bOn);if info.dutyLt < 0) {mpStrobe2->setOnOff0);} else {mpStrobe2->setTimeOutTimeinfo.timeoutLt);mpStrobe2->setOnOff1);}}return 0;
}

关闭闪光灯

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/flash_mgr/flash_hal.cpp

int FlashHal::setFlashOff)
{Mutex::Autolock lockmLock);logI"setFlashOff).");mpStrobe->setOnOff0); /* 实际调用的是 StrobeDrvFlashlight::setOnOff */if mStrobeCtNum > 1)mpStrobe2->setOnOff0);mpStrobe->getHwFault&mDriverFault);return 0;
}

StrobeDrvFlashlight 继承于类 StrobeDrvStrobeDrvFlashlight::setOnOff 是对 StrobeDrv 中虚函数 setOnOff 的覆写。

StrobeDrvFlashlight::setOnOff 的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/strobe/strobe_drv_flashlight.cpp

int StrobeDrvFlashlight::setOnOffint enable)
{int ret = 0;/* verify arguments */if verifyTypeCtmTypeId, mCtId)) {logE"setOnOff): error type/ct%d,%d).", mTypeId, mCtId);return -1;}if enable != MTRUE && enable != MFALSE && enable != 2) {logE"setOnOff): error enable%d).", enable);return -1;}logI"setOnOff): enable%d).", enable);/* get strobe fops handler */StrobeDrvFlashlightFops *pStrobeDrvFlashlightFops = StrobeDrvFlashlightFops::getInstance);if enable == MTRUE) {/* record time at turning on */if mIsOn == MFALSE)mOnTime = getMs);/* get pre-on time from driver */int needPreOnTime = 0;getPreOnTimeMsDutymDuty, &needPreOnTime);needPreOnTime = minneedPreOnTime, MAX_NEED_PRE_ON_TIME);/* sleep for pre-on */if needPreOnTime > 0) {if mPreOnTime == -1) {setPreOn);logI"setOnOff): needs pre-on time%d ms).", needPreOnTime);sleepMsneedPreOnTime);} else {long int curTime = getMs);int sleepTimeMs = needPreOnTime - curTime - mPreOnTime);sleepTimeMs = minsleepTimeMs, needPreOnTime);if sleepTimeMs > 0) {logI"setOnOff): still needs pre-on time%d ms).", sleepTimeMs);sleepMssleepTimeMs);}}}/* enable strobe */ret = pStrobeDrvFlashlightFops->sendCommandFLASH_IOC_SET_ONOFF, mTypeId, mCtId, MTRUE);logI"setOnOff): on time%ld).", mOnTime);} else if enable == MFALSE) {if mIsOn == MTRUE) {mOffTime = getMs);if mTimeOutTime && mOffTime - mOnTime > mTimeOutTime))logI"setOnOff): timeout.");}/* clear set pre-on time */mPreOnTime = -1;/* disable strobe */ret = pStrobeDrvFlashlightFops->sendCommandFLASH_IOC_SET_ONOFF, mTypeId, mCtId, MFALSE);logI"setOnOff): off time%ld).", mOffTime);}else if enable == 2) {/* enable strobe */ret = pStrobeDrvFlashlightFops->sendCommandFLASH_IOC_SET_ONOFF, mTypeId, mCtId, 2);logI"setOnOff): on time%ld).", mOnTime);}if !ret)mIsOn = enable;elselogE"setOnOff): failed to ioctl.");return ret;
}

StrobeDrvFlashlightFops::sendCommand的实现

./vendor/mediatek/proprietary/hardware/mtkcam/aaa/source/common/strobe/strobe_drv_flashlight_fops.cpp

int StrobeDrvFlashlightFops::sendCommandint cmd, int typeId, int ctId, int arg)
{Mutex::Autolock lockmLock);if mStrobeHandle < 0) {logD"sendCommandRet): failed with no strobe handler.");return -1;}/* setup arguments */struct flashlight_user_arg strobeArg;strobeArg.type_id = typeId;strobeArg.ct_id = ctId;strobeArg.arg = arg;/* send ioctl */int ret = ioctlmStrobeHandle, cmd, &strobeArg); /* 调用kernel中的ioctl */logD"Send command: type/ct%d,%d), cmd%d).", typeId, ctId, cmd);return ret;
}

KERNEL层

flash驱动加载流程

flashlight_init的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-core.c

module_initflashlight_init);static int __init flashlight_initvoid)
{int ret;pr_debug"Init start\n");...... /* 省略部分代码 */ret = platform_driver_register&flashlight_platform_driver);if ret) {pr_err"Failed to register platform driver\n");return ret;}#ifdef CONFIG_MTK_FLASHLIGHT_PTregister_low_battery_notify&pt_low_vol_callback, LOW_BATTERY_PRIO_FLASHLIGHT);register_battery_percent_notify&pt_low_bat_callback, BATTERY_PERCENT_PRIO_FLASHLIGHT);register_battery_oc_notify&pt_oc_callback, BATTERY_OC_PRIO_FLASHLIGHT);
#endifpr_debug"Init done\n");return 0;
}

flashlight_platform_driver结构体的实现

#ifdef CONFIG_OF
static const struct of_device_id flashlight_of_match[] = {{.compatible = "mediatek,flashlight_core"},{},
};
MODULE_DEVICE_TABLEof, flashlight_of_match);
#else..... /* 省略部分代码 */
#endifstatic struct platform_driver flashlight_platform_driver = {.probe = flashlight_probe,.remove = flashlight_remove,.shutdown = flashlight_shutdown,.driver = {.name = FLASHLIGHT_DEVNAME,.owner = THIS_MODULE,
#ifdef CONFIG_OF.of_match_table = flashlight_of_match, /* "mediatek,flashlight_core" */
#endif},
};

./kernel-4.4/arch/arm/boot/dts/mt6739.dts

flashlight_core: flashlight_core {compatible = "mediatek,flashlight_core";
};

flashlight_probe的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-core.c

static int flashlight_probestruct platform_device *dev)
{pr_debug"Probe start\n");/* allocate char device number */alloc_chrdev_region&flashlight_devno, 0, 1, FLASHLIGHT_DEVNAME);pr_debug"Allocate major number and minor number: %d, %d)\n",MAJORflashlight_devno),MINORflashlight_devno));/* allocate char device */flashlight_cdev = cdev_alloc);flashlight_cdev->ops = &flashlight_fops;flashlight_cdev->owner = THIS_MODULE;/* add char device to the system */cdev_addflashlight_cdev, flashlight_devno, 1);/* create class */flashlight_class = class_createTHIS_MODULE, FLASHLIGHT_CORE);/* create device */flashlight_device = device_createflashlight_class, NULL, flashlight_devno,NULL, FLASHLIGHT_DEVNAME);/* create device file */device_create_fileflashlight_device, &dev_attr_flashlight_strobe);device_create_fileflashlight_device, &dev_attr_flashlight_pt);device_create_fileflashlight_device, &dev_attr_flashlight_charger);device_create_fileflashlight_device, &dev_attr_flashlight_capability);device_create_fileflashlight_device, &dev_attr_flashlight_current);device_create_fileflashlight_device, &dev_attr_flashlight_fault);device_create_fileflashlight_device, &dev_attr_flashlight_sw_disable);/* init flashlight */fl_init);pr_debug"Probe done\n");return 0;...... /* 省略部分代码 */
}

flashlight_led191_init的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

module_initflashlight_led191_init);static int __init flashlight_led191_initvoid)
{int ret;PK_DBG"Init start.\n");#ifndef CONFIG_OF...... /* 省略部分代码 */
#endifret = platform_driver_register&led191_platform_driver);if ret) {PK_ERR"Failed to register platform driver\n");return ret;}PK_DBG"Init done.\n");return 0;
}
/* define device tree */
#ifndef LED191_DTNAME
#define LED191_DTNAME "mediatek,flashlights_led191"
#endif#ifdef CONFIG_OF
static const struct of_device_id led191_gpio_of_match[] = {{.compatible = LED191_DTNAME},{},
};
MODULE_DEVICE_TABLEof, led191_gpio_of_match);
#else...... /* 省略部分代码 */
#endifstatic struct platform_driver led191_platform_driver = {.probe = led191_probe,.remove = led191_remove,.driver = {.name = LED191_NAME,.owner = THIS_MODULE,
#ifdef CONFIG_OF.of_match_table = led191_gpio_of_match, /* "mediatek,flashlights_led191" */
#endif},
};

./kernel-4.4/arch/arm/boot/dts/x006_k39tv1_bsp_1g.dtsi

flashlights_led191: flashlights_led191 {compatible = "mediatek,flashlights_led191";decouple = <0>;channel@1 {type = <0>;ct = <0>;part = <0>;};
};

led191_probe的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static int led191_probestruct platform_device *pdev)
{struct led191_platform_data *pdata = dev_get_platdata&pdev->dev);int err;int i;PK_DBG"Probe start.\n");/* init pinctrl */if led191_pinctrl_initpdev)) {PK_DBG"Failed to init pinctrl.\n");err = -EFAULT;goto err;}/* init platform data */if !pdata) {pdata = devm_kzalloc&pdev->dev, sizeof*pdata), GFP_KERNEL);if !pdata) {err = -ENOMEM;goto err;}pdev->dev.platform_data = pdata;err = led191_parse_dt&pdev->dev, pdata);if err)goto err;}/* init work queue */INIT_WORK&led191_work, led191_work_disable);/* init timer */hrtimer_init&led191_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);led191_timer.function = led191_timer_func;led191_timeout_ms = 100;/* 为了降低功耗,led191芯片的初始化放到了“set_driver”中实现。这里直接return 0 *//* init chip hw */led191_chip_init);/* clear usage count */use_count = 0;/* register flashlight device */if pdata->channel_num) {for i = 0; i < pdata->channel_num; i++)if flashlight_dev_register_by_device_id&pdata->dev_id[i], &led191_ops)) {err = -EFAULT;goto err;}} else {if flashlight_dev_registerLED191_NAME, &led191_ops)) {err = -EFAULT;goto err;}}PK_DBG"Probe done.\n");return 0;
err:return err;
}

led191_pinctrl_init的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static int led191_pinctrl_initstruct platform_device *pdev)
{int ret = 0;/* get pinctrl */led191_pinctrl = devm_pinctrl_get&pdev->dev);if IS_ERRled191_pinctrl)) {PK_ERR"Failed to get flashlight pinctrl.\n");ret = PTR_ERRled191_pinctrl);}/*  Flashlight pin initialization */led191_hw_ch0_high = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH0_HIGH);if IS_ERRled191_hw_ch0_high)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH0_HIGH);ret = PTR_ERRled191_hw_ch0_high);}led191_hw_ch0_low = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH0_LOW);if IS_ERRled191_hw_ch0_low)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH0_LOW);ret = PTR_ERRled191_hw_ch0_low);}if flashlight_device_num == 2)	{led191_hw_ch1_high = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH1_HIGH);if IS_ERRled191_hw_ch1_high)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH1_HIGH);ret = PTR_ERRled191_hw_ch1_high);}led191_hw_ch1_low = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH1_LOW);if IS_ERRled191_hw_ch1_low)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH1_LOW);ret = PTR_ERRled191_hw_ch1_low);}}// sgm3785 flash ic,#if definedUSING_SGM3785_FLASH)/*  sgm3785 flash ENM pin initialization */led191_hw_ch01_high = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH01_HIGH);if IS_ERRled191_hw_ch01_high)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH01_HIGH);ret = PTR_ERRled191_hw_ch01_high);}led191_hw_ch01_low = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH01_LOW);if IS_ERRled191_hw_ch01_low)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH01_LOW);ret = PTR_ERRled191_hw_ch01_low);}led191_hw_ch01_pwm = pinctrl_lookup_stateled191_pinctrl, LED191_PINCTRL_STATE_HW_CH01_PWM);if IS_ERRled191_hw_ch01_pwm)) {PK_ERR"Failed to init %s)\n", LED191_PINCTRL_STATE_HW_CH01_PWM);ret = PTR_ERRled191_hw_ch01_pwm);}// init state, ENF = 0 && ENM = 0if !IS_ERRled191_hw_ch0_low)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_ch0_low);// ENF = 0}if !IS_ERRled191_hw_ch01_low)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_ch01_low);// ENM = 0}pwm_setting.pwm_no = 3;pwm_setting.mode = PWM_MODE_OLD;pwm_setting.clk_div = CLK_DIV1;pwm_setting.clk_src = PWM_CLK_OLD_MODE_32K;pwm_setting.pmic_pad = 0;pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE = 0;pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE = 0;pwm_setting.PWM_MODE_OLD_REGS.GDURATION = 0;pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM = 0;pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 7;	/* 7 level */pwm_setting.PWM_MODE_OLD_REGS.THRESH = 0; // level to set.#endif// end +++return ret;
}

led191_parse_dt的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static int led191_parse_dtstruct device *dev,struct led191_platform_data *pdata)
{struct device_node *np, *cnp;u32 decouple = 0;int i = 0;if !dev || !dev->of_node || !pdata)return -ENODEV;np = dev->of_node;pdata->channel_num = of_get_child_countnp);if !pdata->channel_num) {PK_LOG"Parse no dt, node.\n");return 0;}PK_LOG"Channel number%d).\n", pdata->channel_num);if of_property_read_u32np, "decouple", &decouple))PK_LOG"Parse no dt, decouple.\n");pdata->dev_id = devm_kzallocdev,pdata->channel_num * sizeofstruct flashlight_device_id),GFP_KERNEL);if !pdata->dev_id)return -ENOMEM;for_each_child_of_nodenp, cnp) {if of_property_read_u32cnp, "type", &pdata->dev_id[i].type))goto err_node_put;if of_property_read_u32cnp, "ct", &pdata->dev_id[i].ct))goto err_node_put;if of_property_read_u32cnp, "part", &pdata->dev_id[i].part))goto err_node_put;snprintfpdata->dev_id[i].name, FLASHLIGHT_NAME_SIZE, LED191_NAME);pdata->dev_id[i].channel = i;pdata->dev_id[i].decouple = decouple;PK_LOG"Parse dt type,ct,part,name,channel,decouple)=%d,%d,%d,%s,%d,%d).\n",pdata->dev_id[i].type, pdata->dev_id[i].ct,pdata->dev_id[i].part, pdata->dev_id[i].name,pdata->dev_id[i].channel, pdata->dev_id[i].decouple);i++;}return 0;err_node_put:of_node_putcnp);return -EINVAL;
}

flashlight_dev_register_by_device_id的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-core.c

/** Register devices** Please DO NOT register flashlight device driver,* until success to probe hardware.*/
int flashlight_dev_register_by_device_idstruct flashlight_device_id *dev_id,struct flashlight_operations *dev_ops)
{struct flashlight_dev *fdev;if !dev_id || !dev_ops)return -EINVAL;if flashlight_verify_indexdev_id->type, dev_id->ct, dev_id->part)) {pr_err"Failed to register device %d,%d,%d)\n",dev_id->type, dev_id->ct, dev_id->part);return -EINVAL;}pr_info"Register device %d,%d,%d)\n",dev_id->type, dev_id->ct, dev_id->part);mutex_lock&fl_mutex);fdev = kzallocsizeof*fdev), GFP_KERNEL);if !fdev) {mutex_unlock&fl_mutex);return -ENOMEM;}fdev->ops = dev_ops;fdev->dev_id = *dev_id;fdev->low_pt_level = -1;fdev->charger_status = FLASHLIGHT_CHARGER_READY;list_add_tail&fdev->node, &flashlight_list);mutex_unlock&fl_mutex);return 0;
}
EXPORT_SYMBOLflashlight_dev_register_by_device_id);

led191_ops结构体的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static struct flashlight_operations led191_ops = {/************************************************************** 为了降低功耗,led191芯片的 open 和 release 都放到了“set_driver”* 中实现。这里直接return 0 *************************************************************/led191_open, led191_release, led191_ioctl,led191_strobe_store,led191_set_driver
};

led191_ioctl的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

/****************************************************************************** Flashlight operations*****************************************************************************/
static int led191_ioctlunsigned int cmd, unsigned long arg)
{struct flashlight_dev_arg *fl_arg;int channel;ktime_t ktime;fl_arg = struct flashlight_dev_arg *)arg;channel = fl_arg->channel;g_flash_channel_idx = channel;switch cmd) {case FLASH_IOC_SET_TIME_OUT_TIME_MS:PK_DBG"FLASH_IOC_SET_TIME_OUT_TIME_MS%d): %d\n",channel, int)fl_arg->arg);led191_timeout_ms = fl_arg->arg;break;case FLASH_IOC_SET_DUTY:PK_DBG"FLASH_IOC_SET_DUTY%d): %d\n",channel, int)fl_arg->arg);led191_set_levelfl_arg->arg);break;case FLASH_IOC_SET_ONOFF:PK_DBG"FLASH_IOC_SET_ONOFF%d): %d\n",channel, int)fl_arg->arg);if fl_arg->arg == 1) {if led191_timeout_ms) {ktime = ktime_setled191_timeout_ms / 1000,led191_timeout_ms % 1000) * 1000000);hrtimer_start&led191_timer, ktime, HRTIMER_MODE_REL);}led191_enablechannel);} else {led191_disablechannel);hrtimer_cancel&led191_timer);}break;default:PK_LOG"No such command and arg%d): %d, %d)\n",channel, _IOC_NRcmd), int)fl_arg->arg);return -ENOTTY;}return 0;
}

led191_enable和led191_disable的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

/* flashlight enable function */
static int led191_enableint channel)
{int pin = LED191_PINCTRL_PIN_HWEN;PK_LOG"g_flash_duty = %d, channel:%d\n", g_flash_duty, channel);led191_pinctrl_setchannel, 1);return 0;if g_flash_duty == 1) {led191_pinctrl_setpin, 1);} else {led191_pinctrl_setpin, 1);led191_pinctrl_setpin, 0);}led191_pinctrl_setpin, 1);return 0;
}/* flashlight disable function */
static int led191_disableint channel)
{int pin = 0, state = 0;PK_LOG"no use pin:%d, channel:%d, state:%d\n", pin, channel, state);return led191_pinctrl_setchannel, state);
}

led191_pinctrl_set的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static int led191_pinctrl_setint pin, int state)
{int ret = 0;struct pinctrl_state *led191_hw_chx_low = led191_hw_ch0_low;struct pinctrl_state *led191_hw_chx_high = led191_hw_ch0_high;struct pinctrl_state *led191_hw_chx1_low = led191_hw_ch1_low;struct pinctrl_state *led191_hw_chx1_high = led191_hw_ch1_high;#if definedUSING_SGM3785_FLASH)struct pinctrl_state *led191_hw_chx_enm_low = led191_hw_ch01_low;struct pinctrl_state *led191_hw_chx_enm_high = led191_hw_ch01_high;struct pinctrl_state *led191_hw_chx_pwm = led191_hw_ch01_pwm;
#endifif IS_ERRled191_pinctrl)) {PK_ERR"pinctrl is not available\n");return -1;}PK_DBG"g_flash_channel_idx = %d\n", g_flash_channel_idx);if pin == 0) {led191_hw_chx_low = led191_hw_ch0_low;led191_hw_chx_high = led191_hw_ch0_high;#if definedUSING_SGM3785_FLASH)led191_hw_chx_enm_low = led191_hw_ch01_low;led191_hw_chx_enm_high = led191_hw_ch01_high;led191_hw_chx_pwm = led191_hw_ch01_pwm;#endif} else if pin == 1 && flashlight_device_num == 2)) {led191_hw_chx1_low = led191_hw_ch1_low;led191_hw_chx1_high = led191_hw_ch1_high;} else {PK_DBG"please check g_flash_channel_idx!!!\n");}switch pin) {case LED191_PINCTRL_PIN_HWEN:PK_DBG"LED191_PINCTRL_PIN_HWEN\n");#if definedUSING_SGM3785_FLASH)if state == LED191_PINCTRL_PINSTATE_HIGH) { // enableif led191_is_flashg_flash_duty)) { // FlashPK_LOG"goto flash mode on\n");// 1. enter Active Mode, ENF = 0 && ENM = PWM && PWM high time <= 2.5msif !IS_ERRled191_hw_chx_low)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_low);}// ENM PWM config// a. config GPIO28 to PWM modeif !IS_ERRled191_hw_chx_pwm)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_pwm);}// b. set PWMpwm_setting.PWM_MODE_OLD_REGS.THRESH = g_flash_duty;ret = pwm_set_spec_config&pwm_setting);PK_LOG"set PWM return value:%d\n", ret);udelay400);// delay 400us// 2. enter Flash Mode, ENF = 1 && ENM = PWMif !IS_ERRled191_hw_chx_high)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_high);}} else { // TorchPK_LOG"goto torch mode on\n");// 1. enter Movie/Torch Mode, ENF = 0 && ENM = 1 && time >= 5msif !IS_ERRled191_hw_chx_low)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_low);}if !IS_ERRled191_hw_chx_enm_high)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_enm_high);}mdelay5);// delay 5ms}} else { // disablePK_LOG"exit Flash/Torch[Movie] mode, transit to Shutdown Mode\n");// 1. exit flash Mode or Torch[Movie] mode, ENF = 0 && ENM = 0 && time >= 5msif !IS_ERRled191_hw_chx_low)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_low);}if !IS_ERRled191_hw_chx_enm_low)) {ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_enm_low);}mdelay5);// delay 5ms}
#elseif state == LED191_PINCTRL_PINSTATE_LOW && !IS_ERRled191_hw_chx_low))ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_low);else if state == LED191_PINCTRL_PINSTATE_HIGH && !IS_ERRled191_hw_chx_high))ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx_high);elsePK_ERR"set err, pin%d) state%d)\n", pin, state);
#endifbreak;case LED191_PINCTRL_PIN_HWEN1:PK_DBG"LED191_PINCTRL_PIN_HWEN1\n");if flashlight_device_num == 2) {#if definedCONFIG_P32A_PROJECT) || definedCONFIG_P33A_PROJECT) || definedCONFIG_A95C_PROJECT) || definedCONFIG_H33E_PROJECT)// flash control level is inverseif state == LED191_PINCTRL_PINSTATE_LOW && !IS_ERRled191_hw_chx1_high))ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx1_high);else if state == LED191_PINCTRL_PINSTATE_HIGH && !IS_ERRled191_hw_chx1_low))ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx1_low);elsePK_ERR"set err, pin%d) state%d)\n", pin, state);#elseif state == LED191_PINCTRL_PINSTATE_LOW && !IS_ERRled191_hw_chx1_low))ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx1_low);else if state == LED191_PINCTRL_PINSTATE_HIGH && !IS_ERRled191_hw_chx1_high))ret = pinctrl_select_stateled191_pinctrl, led191_hw_chx1_high);elsePK_ERR"set err, pin%d) state%d)\n", pin, state);#endif}break;// end +++default:PK_ERR"set err, pin%d) state%d)\n", pin, state);break;}PK_DBG"pin%d) state%d), ret:%d\n", pin, state, ret);return ret;
}

led191_strobe_store的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static ssize_t led191_strobe_storestruct flashlight_arg arg)
{led191_set_driver1);led191_set_levelarg.level);led191_timeout_ms = 0;g_flash_channel_idx = arg.channel;// optimise the channel idif arg.level < 0) // optimiseled191_disablearg.channel);elseled191_enablearg.channel);msleeparg.dur);led191_disablearg.channel);led191_set_driver0);return 0;
}

led191_set_driver的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

static int led191_set_driverint set)
{int ret = 0;/* set chip and usage count */mutex_lock&led191_mutex);if set) {if !use_count)ret = led191_init);use_count++;PK_DBG"Set driver: %d\n", use_count);} else {use_count--;if !use_count)ret = led191_uninit);if use_count < 0)use_count = 0;PK_DBG"Unset driver: %d\n", use_count);}mutex_unlock&led191_mutex);return ret;
}

led191_init的实现

./kernel-4.4/drivers/misc/mediatek/flashlight/flashlight-led191.c

/* flashlight init */
static int led191_initvoid)
{int pin = 0, state = 0;PK_LOG"g_flash_channel_idx:%d\n", g_flash_channel_idx);g_flash_duty = -1; // init flash dutyif g_flash_channel_idx == -1) {led191_pinctrl_setLED191_PINCTRL_PIN_HWEN, LED191_PINCTRL_PINSTATE_LOW);led191_pinctrl_setLED191_PINCTRL_PIN_HWEN1, LED191_PINCTRL_PINSTATE_LOW);return 0;}return led191_pinctrl_setpin, state);
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注