问题:【相机】33%电量开启闪光灯录制视频,大约6分钟左右,手机自动关机,再开机,电量为4%
分析过程:
开闪光灯录制视频的情况下导致掉电,手机关机。经过跟测试沟通之后,发现正常模式下录制视频的话,没有这个问题,那么我们就把问题点定位到闪光灯上了,由于闪光灯有Flash模式和Torch模式,在拍照时,我们用的是Flash模式,该模式瞬间曝光,一般电压在300mV ~ 75mV 之间,这个是跟连接的RSET有关,我们电路接的是139kΩ,那么根据公式VFB = (1.26V/ RSET) ×10.2kΩ (Flash Mode),算出VFB=92.5mV。而Torch模式的话就只有VFB = 47mV (Torch Mode)。然后看了一下拍视频时闪光灯的亮度,跟拍照时的亮度是一样的,那么就肯定是我们拍视频的时候闪光灯的模式错误的设置为Flash模式了;
问题定位后就是代码分析了。首先分析的是驱动leds_strobe.c文件
- 129 ssize_t gpio_FL_Enable(void)
- 130 {
- 131 /*Enable*/
- 132 printk("FlashLight: %s:%d: called g_torch_mode:%d\n",__func__,__LINE__,g_torch_mode);
- 133 if(0 == g_torch_mode){
- 134 if(mt_set_gpio_out(GPIO_CAMERA_FLASH_ENM_PIN,GPIO_OUT_ONE)){PK_DBG("[constant_flashlight] enable flashlight failed!! \n");}
- 135 if(mt_set_gpio_out(GPIO_CAMERA_FLASH_ENF_PIN,GPIO_OUT_ONE)){PK_DBG("[constant_flashlight] open flashlight failed! ! \n");}
- 136 }else{
- 137 if(mt_set_gpio_out(GPIO_CAMERA_FLASH_ENM_PIN,GPIO_OUT_ONE)){PK_DBG("[constant_flashlight] set gpio failed!! \n"); }
- 138 }
- 139 return 0;
- 140 }
- 141
- 142 ssize_t gpio_FL_Disable(void)
- 143 {
- 144 /*Disable*/
- 145 printk("FlashLight: %s:%d: called g_torch_mode:%d\n",__func__,__LINE__,g_torch_mode);
- 146 if(0 == g_torch_mode){
- 147 if(mt_set_gpio_out(GPIO_CAMERA_FLASH_ENF_PIN,GPIO_OUT_ZERO)){PK_DBG("[constant_flashlight] close flashlight failed!! \n");}
- 148 if(mt_set_gpio_out(GPIO_CAMERA_FLASH_ENM_PIN,GPIO_OUT_ZERO)){PK_DBG("[constant_flashlight] enable flashlight fail ed!! \n");}
- 149 }else{
- 150 if(mt_set_gpio_out(GPIO_CAMERA_FLASH_ENM_PIN,GPIO_OUT_ZERO)){PK_DBG("[constant_flashlight] set gpio failed!! \n") ;}
- 151 }
- 152 return 0;
- 153 }
然后我们再查看torch模式和flash模式是什么情况下设置的:
- 155 ssize_t gpio_FL_dim_duty(kal_uint8 duty)
- 156 {
- 157 if (duty == 0)
- 158 g_torch_mode = 1;
- 159 else
- 160 g_torch_mode = 0;
- 161 printk("FlashLight: %s:%d: called duty:%d\n",__func__,__LINE__,duty);
- 162 return 0;
- 163 }
170 #define FL_dim_duty gpio_FL_dim_duty
继续看看调用FL_dim_duty的地方:
- 201 static int constant_flashlight_ioctl(MUINT32 cmd, MUINT32 arg)
- 202 {
- 203 int i4RetValue = 0;
- 204 int ior_shift;
- 205 int iow_shift;
- 206 int iowr_shift;
- 207 ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC,0, int));
- 208 iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC,0, int));
- 209 iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC,0, int));
- 210 PK_DBG("constant_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n",__LINE__, ior_shift, i
- ow_shift, iowr_shift, arg);
- 211 switch(cmd)
- 212 {
- 213 case FLASH_IOC_SET_TIME_OUT_TIME_MS:
- 214 PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n",arg);
- 215 g_timeOutTimeMs=arg;
- 216 break;
- 217
- 218 case FLASH_IOC_SET_DUTY :
- 219 PK_DBG("FLASHLIGHT_DUTY: %d\n",arg);
- 220 FL_dim_duty(arg);
- 221 break;
好吧,那么就是跟到Ioctl,我们继续查看哪里有调用FLASH_IOC_SET_DUTY,搜索了一下,发现在
mediatek/platform/mt6592/hardware/mtkcam/core/featureio/drv/strobe/flashlight_drv.cpp中
- 284 int FlashlightDrv::setDuty(int duty)
- 285 {
- 286 DRV_DBG("setDuty() duty = %d\n",duty);
- 287 int err = 0;
- 288 if (m_fdSTROBE < 0)
- 289 {
- 290 DRV_DBG("setDuty() m_fdSTROBE < 0\n");
- 291 return StrobeDrv::STROBE_UNKNOWN_ERROR;
- 292 }
- 293 err = ioctl(m_fdSTROBE,FLASH_IOC_SET_DUTY,duty);
- 294 if (err < 0)
- 295 {
- 296 DRV_ERR("setDuty() err=%d\n", err);
- 297 return err;
- 298 }
- 299 m_duty = duty;
- 300 return err;
- 301 }
m_duty的值初始化时为0,SetDuty对duty 进行设置,讲duty的值传给m_duty,而getDuty则进行获取直接获取m_duty的值
- 1021 int FlashlightDrv::getDuty(int* duty)
- 1022 {
- 1023 DRV_DBG("getDuty()\n");
- 1024 int err = 0;
- 1025 if (m_fdSTROBE < 0)
- 1026 {
- 1027 DRV_DBG("getDuty() m_fdSTROBE < 0\n");
- 1028 return StrobeDrv::STROBE_UNKNOWN_ERROR;
- 1029 }
- 1030 *duty = m_duty;
- 1031 return err;
- 1032
- 1033 }
最后setDuty被文件mediatek /hardware/mtkcam/core/featureio/pipe/aaa/flash_mgr/flash_mgr.cpp调用:
- 210 void turnOnTorch()
- 211 {
- 212 int bOn;
- 213 int step;
- 214 int duty;
- 215 g_pStrobe->isOn(&bOn);
- 216 g_pStrobe->getDuty(&duty);
- 217 g_pStrobe->getStep(&step);
- 218
- 219 FLASH_PROJECT_PARA prjPara;
- 220 int aeMode;
- 221 aeMode = AeMgr::getInstance().getAEMode();
- 222 prjPara = FlashMgr::getInstance()->getFlashProjectPara(aeMode);
- 223 LogInfo("turnOnTorch line=%d isOn=%d",__LINE__,bOn);
- 224 if(bOn==0 || prjPara.engLevel.torchDuty!=duty || prjPara.engLevel.torchStep!=step)
- 225 {
- 226 LogInfo("turnOnTorch duty,step=%d %d",prjPara.engLevel.torchDuty, prjPara.engLevel.torchStep);
- 227 g_pStrobe->setDuty(prjPara.engLevel.torchDuty);
- 228 g_pStrobe->setStep(prjPara.engLevel.torchStep);
- 229 g_pStrobe->setTimeOutTime(0);
- 230 hwSetFlashOn();
- 231 }
- 232 }
其中:prjPara= FlashMgr::getInstance()->getFlashProjectPara(aeMode);调用:
- 297 FLASH_PROJECT_PARA&FlashMgr::getFlashProjectPara(int aeMode)
- 298{
- 299 NVRAM_CAMERA_STROBE_STRUCT* pNv;
- 300 int err;
- 301 err = nvGetBuf(pNv);
- 302 if(err!=0)
- 303 LogError("nvGetBuf err");
- 304 //loadNvram();
- 305 FLASH_PROJECT_PARA para;
- 306if(m_sensorType==DUAL_CAMERA_MAIN_SENSOR)
- 307 return cust_getFlashProjectPara(aeMode, pNv);
- 308else
- 309 return cust_getFlashProjectPara_sub(aeMode, pNv);
- 310}
接着是cust_getFlashProjectPara(aeMode,pNv);代用下面文件,
mediatek/custom/out/huaqin92_wet_b2a_tdd/hal/camera/flash_tuning_custom.cpp中的- 118 FLASH_PROJECT_PARA& cust_getFlashProjectPara(int aeMode, NVRAM_CAMERA_STROBE_STRUCT* nvrame)
- 119 {
- 120 static FLASH_PROJECT_PARA para;
- 121
- 122 para.dutyNum = 10;
- 123 para.stepNum = 1;
- 124
- 125 if(nvrame!=0)
- 126 {
- 127 XLOGD("cust_getFlashProjectPara nvrame->tuningPara[0].yTar=%d", nvrame->tuningPara[0].yTar);
- 128 switch(aeMode)
- 129 {
- 130 case LIB3A_AE_MODE_OFF:
- 131 case LIB3A_AE_MODE_AUTO:
- 132 copyTuningPara(¶.tuningPara, &nvrame->tuningPara[0]);
- 133 break;
- 134 case LIB3A_AE_MODE_NIGHT:
- 135 case LIB3A_AE_MODE_CANDLELIGHT:
- 136 case LIB3A_AE_MODE_FIREWORKS:
- 137 case LIB3A_AE_MODE_NIGHT_PORTRAIT:
- 138 copyTuningPara(¶.tuningPara, &nvrame->tuningPara[1]);
- 139 break;
- 140 case LIB3A_AE_MODE_ACTION:
- 141 case LIB3A_AE_MODE_SPORTS:
- 142 case LIB3A_AE_MODE_ISO_ANTI_SHAKE:
- 143 copyTuningPara(¶.tuningPara, &nvrame->tuningPara[2]);
- 144 break;
- 145 case LIB3A_AE_MODE_PORTRAIT:
- 146 copyTuningPara(¶.tuningPara, &nvrame->tuningPara[3]);
- 147 break;
- 148 default:
- 149 copyTuningPara(¶.tuningPara, &nvrame->tuningPara[0]);
- 150 break;
- 151 }
- 152 }
- 153 //--------------------
- 154 //eng level
- 155 //index mode
- 156 //torch
- 157 para.engLevel.torchEngMode = ENUM_FLASH_ENG_INDEX_MODE;
- 158 para.engLevel.torchDuty = 0;
- 159 para.engLevel.torchStep = 0;
这个函数的160-162行可以看到:
160 para.engLevel.torchEngMode = ENUM_FLASH_ENG_INDEX_MODE;
161 para.engLevel.torchDuty= 1;
162 para.engLevel.torchStep = 0;
好了,所以我们的duty就被设置为1了,导致走的驱动层的Flash模式。
修改完成编译后,将libcameracustom.so 文件push到/system/lib/reboot后就搞定了!