【android睡眠唤醒 一】MTK 唤醒时间分析

一、唤醒流程:
  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
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文无所谓版权,欢迎转载。

猜你喜欢

转载自blog.csdn.net/frank_zyp/article/details/64123416