一、唤醒流程:
MTK平台唤醒流程是从power键或者其他按键按下开始,本文以mt6753n平台为例,通过分析kernel log来看驱动中整个唤醒的流程,上层的唤醒流程后续再分析。
1、按键按下
当按键按下时会出发中断,从而回调中断的处理函数,从kernel log从会有以下log吐出:
01-02 12:27:04.500571 70 70 E [ 940.825599]: (3)[70:pmic_thread][name:pmic&][PMIC] [pwrkey_int_handler] Press pwrkey 0
01-02 12:27:04.500593 70 70 E [ 940.825621](3)[70:pmic_thread][name:kpd&]: Power Key generate, pressed=1
01-02 12:27:04.500694 70 70 E [ 940.825722](3)[70:pmic_thread][name:hal_kpd&]: kpd: (pressed) HW keycode =116 using PMIC
在代码中体现如下:
./kernel-3.18/drivers/misc/mediatek/power/mt6735/pmic.c
void pwrkey_int_handler(void)
{
PMICLOG("[pwrkey_int_handler] Press pwrkey %d\n", pmic_get_register_value(PMIC_PWRKEY_DEB));
#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)
if (get_boot_mode() == KERNEL_POWER_OFF_CHARGING_BOOT)
timer_pre = sched_clock();
#endif
#if defined(CONFIG_MTK_FPGA)
#else
kpd_pwrkey_pmic_handler(0x1);
#endif
}
接下来调用kpd_pwrkey_pmic_handler:
void kpd_pwrkey_pmic_handler(unsigned long pressed)
{
kpd_print("Power Key generate, pressed=%ld\n", pressed);
if (!kpd_input_dev) {
kpd_print("KPD input device not ready\n");
return;
}
kpd_pmic_pwrkey_hal(pressed);
#if (defined(CONFIG_ARCH_MT8173) || defined(CONFIG_ARCH_MT8163))
if (pressed) /* keep the lock while the button in held pushed */
wake_lock(&pwrkey_lock);
else /* keep the lock for extra 500ms after the button is released */
wake_lock_timeout(&pwrkey_lock, HZ/2);
#endif
}
接下来调用kpd_pmic_pwrkey_hal:
void kpd_pmic_pwrkey_hal(unsigned long pressed)
{
#ifdef CONFIG_KPD_PWRKEY_USE_PMIC
if (!kpd_sb_enable) {
//通过input子系统向上层上报键值
input_report_key(kpd_input_dev, kpd_dts_data.kpd_sw_pwrkey, pressed);
input_sync(kpd_input_dev);
if (kpd_show_hw_keycode) {
kpd_print(KPD_SAY "(%s) HW keycode =%d using PMIC\n",
pressed ? "pressed" : "released", kpd_dts_data.kpd_sw_pwrkey);
}
/*ZH CHEN*/
/*aee_powerkey_notify_press(pressed);*/
}
#endif
}
到这里从按键按下触发中断到回调中断函数,最后通过input子系统向上层上报键值。
2、进程解冻,系统开始唤醒
当按键按下后,系统开始唤醒,一些sensor(gsensor/psensor/lsensor/gyro/msensor等)会开始进入resume流程,log如下:
01-02 12:27:04.518694 873 873 W [ 940.843722]: (0)[873:system_server]MSENSOR af7133e_af8133i_resume
01-02 12:27:04.522326 873 873 W [ 940.847354]: (2)[873:system_server][Gsensor] bmi160_acc_resume
01-02 12:27:04.534504 873 873 D [ 940.859532]: (2)[873:system_server][name:ltr579&][ALS/PS] ltr579_i2c_resume
......
当这些进程解冻完成后,在kernel log中会有标志性的log吐出:
01-02 12:27:04.544117 401 401 W [ 940.869145]: (0)[401:fuelgauged]Restarting tasks ...
3、LCM开始唤醒:
当系统唤醒完成后,LCM也会开始进入唤醒状态,当LCM唤醒完成之后会退出唤醒状态,这个过程都有标志性的log吐出:
......
01-02 12:27:05.076832 272 272 W [ 940.936520]: (4)[272:surfaceflinger][name:mtkfb&]DISP/MTKFB [FB Driver] enter late_resume
......
01-02 12:27:05.413783 272 272 W [ 941.273471]: (0)[272:surfaceflinger][name:mtkfb&]DISP/MTKFB [FB Driver] leave late_resume
......
其中在enter late_resume和leave late_resume中会执行LCM的唤醒操作,这部分的耗时与屏的时序有关,当屏上电和下参数的时间越短,手机唤醒亮屏的时间也就越短,代码如下:
//./kernel-3.18/drivers/misc/mediatek/video/common/mtkfb.c
static void mtkfb_blank_resume(void)
{
int ret = 0;
MSG_FUNC_ENTER();
if (disp_helper_get_stage() != DISP_HELPER_STAGE_NORMAL)
return;
PRNWARN("[FB Driver] enter late_resume\n");
#ifdef CONFIG_SINGLE_PANEL_OUTPUT
is_early_suspended = false;
#endif
ret = primary_display_resume();
if (ret) {
DISPERR("primary display resume failed\n");
return;
}
PRNWARN("[FB Driver] leave late_resume\n");
}
primary_display_resume()函数比较多,包含显示模块的上电、初始化、lcm的上电、resume等的过程:
int primary_display_resume(void)
{
......
DISPMSG("dpmanager path power on[begin]\n");
dpmgr_path_power_on(pgc->dpmgr_handle, CMDQ_DISABLE);
DISPMSG("dpmanager path power on[end]\n");
......
DISPMSG("[POWER]dpmanager re-init[begin]\n");
dpmgr_init...
DISPMSG("[POWER]dpmanager re-init[end]\n");
......
DISPMSG("[POWER]lcm resume[begin]\n");
disp_lcm_resume(pgc->plcm);
DISPMSG("[POWER]lcm resume[end]\n");
......
}
下面重点看disp_lcm_resume:
int disp_lcm_resume(disp_lcm_handle *plcm)
{
LCM_DRIVER *lcm_drv = NULL;
DISPFUNC();
if (_is_lcm_inited(plcm)) {
lcm_drv = plcm->drv;
//调用lcm驱动代码中的resume_power
if (lcm_drv->resume_power)
lcm_drv->resume_power();
//调用lcm驱动代码中的lcm_resume
if (lcm_drv->resume) {
lcm_drv->resume();
} else {
DISPERR("FATAL ERROR, lcm_drv->resume is null\n");
return -1;
}
return 0;
}
DISPERR("lcm_drv is null\n");
return -1;
}
4、背光亮
当LCM初始化完成后会调用背光的驱动,通过上层传入的level_1024来设置背光的亮度,从而亮屏
01-02 12:27:05.527109 487 487 W [ 941.386797]: (4)[487:AALServiceMain][name:ddp_pwm&][PWM] disp_pwm_set_backlight_cmdq(id = 0x1, level_1024 = 358), old = 0
从上面kernel log的唤醒流程中可以看出,整个唤醒的流程主要包括:power键按下、进程解冻、late_resume、背光亮这几步,所以优化唤醒的时间可以从这几个方面出发优化。
作者:frank_zyp
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文无所谓版权,欢迎转载。