Android 亮屏速度分析
前面聊的
最近在調試項目的亮屏速度,我們希望在按下power鍵后到亮屏這個時間能達到500MS以內,在Rockchip 3399和3288上面的時間都不能達到要求,因此引發了一系列的調試之路。
計算按下power鍵到亮屏的時間
Android 喚醒時間統計
剛開始的時候,我只在android階段統計時間,也能看到時間的差異,但是不是最準確的,我統計的時間日志如下
01-18?09:13:45.304?683?772?D?SurfaceControl:?Excessive?delay?in?setPowerMode():?757ms
01-18?09:13:49.559?683?772?D?SurfaceControl:?Excessive?delay?in?setPowerMode():?725ms
01-18?09:18:27.461?683?772?D?SurfaceControl:?Excessive?delay?in?setPowerMode():?741ms
01-18?09:18:32.766?683?772?D?SurfaceControl:?Excessive?delay?in?setPowerMode():?743ms
01-18?09:18:35.861?683?772?D?SurfaceControl:?Excessive?delay?in?setPowerMode():?745ms
01-18?09:18:38.345?683?772?D?SurfaceControl:?Excessive?delay?in?setPowerMode():?733ms
Kernel從Power到亮屏的時間統計
后來同事中的精英古總在他的代碼上加入了從按下Power鍵到亮屏的時間,直接通過printk打印,代碼如下
old?mode?100644
new?mode?100755
index?17c3b94..2b39662
---?a/drivers/gpu/drm/panel/panel-simple.c
+++?b/drivers/gpu/drm/panel/panel-simple.c
@@?-504,6?+504,7?@@?static?int?panel_simple_enable(struct?drm_panel?*panel)
????????}
????????p->enabled?=?true;
+???????printk("%s?exit\n",?__func__);
????????return?0;
?}
diff?--git?a/drivers/input/keyboard/rk_keys.c?b/drivers/input/keyboard/rk_keys.c
old?mode?100644
new?mode?100755
index?fed5ced..537b599
---?a/drivers/input/keyboard/rk_keys.c
+++?b/drivers/input/keyboard/rk_keys.c
@@?-134,6?+134,10?@@?static?void?keys_timer(unsigned?long?_data)
????????????????key_dbg(pdata,?"%skey[%s]:?report?event[%d]?state[%d]\n",
????????????????????????button->type?==?TYPE_ADC???"adc"?:?"gpio",
????????????????????????button->desc,?button->code,?button->state);
+???????????????if(strcmp(button->desc,?"power")?==?0)
+???????????????printk("%skey[%s]:?report?event[%d]?state[%d]\n",
+???????????????????????button->type?==?TYPE_ADC???"adc"?:?"gpio",
+???????????????????????button->desc,?button->code,?button->state);
????????????????input_event(input,?EV_KEY,?button->code,?button->state);
????????????????input_sync(input);
????????}
統計每個驅動的resume函數調用時間
上面的時間對我們調試非常有用,然后就需要細分到每個驅動的resume函數執行的時間,用的方法是我之前寫過的,大概統計了下TP,LCD,sensor的resume時間,發現TP和LCD占用的時間非常多,然后跟同事一起看了下,同事把TP resume里面的代碼用工作隊列實現后速度明顯有了提升。
然后有很長一段時間不知道干嘛,想打印其他每個驅動的resume時間,一直沒找到方法,后面看到一個代碼,非常有用。
kernel/drivers/base/power/main.c
{????????????????
????ktime_t?calltime;
????u64?usecs64;
????int?usecs;
????calltime?=?ktime_get();
????usecs64?=?ktime_to_ns(ktime_sub(calltime,?starttime));
????do_div(usecs64,?NSEC_PER_USEC);
????usecs?=?usecs64;
????if?(usecs?==?0)
????????usecs?=?1;?
????pr_info("PM:?%s%s%s?of?devices?complete?after?%ld.%03ld?msecs\n",
????????info??:?"",?info???"?"?:?"",?pm_verb(state.event),
????????usecs?/?USEC_PER_MSEC,?usecs?%?USEC_PER_MSEC);
}???
這個函數用來打印resume的函數消耗的時間,但是如何去觸發打印這個函數呢?
一定保證設備進入深度睡眠,串口也進入深度睡眠,沒有任何打印后。
執行以下命令
//使控制臺在suspend最后才關閉,這樣可以打印出休眠過程完整信息
echo?1?>?/sys/power/pm_print_times
//使能調試變量
打印的LOG類似下面的
[?37.031413]?bcmsdh_sdmmc_resume?Exit[?37.082174]?PM:?resume?of?devices?complete?after?78.589?msecs
[?37.085277]?[BT_RFKILL]:?**?disable?irq
[?37.087645]?Restarting?tasks?...?
修改Lcd配置減小resume時間
古總在調試過程中展現了非常厲害的功底,第一步就是修改了LCD的參數,讓亮屏時間加快。修改如下
---?a/arch/arm/boot/dts/rk3288-pad.dts+++?b/arch/arm/boot/dts/rk3288-pad.dts
@@?-169,10?+169,10?@@
????????????????dsi,lanes?=?<4>;
????????????????prepare-delay-ms?=?<20>;
-???????????????init-delay-ms?=?<20>;
-???????????????enable-delay-ms?=?<100>;
-???????????????disable-delay-ms?=?<20>;
-???????????????unprepare-delay-ms?=?<20>;
+???????????????//init-delay-ms?=?<20>;
+???????????????enable-delay-ms?=?<1>;
+???????????????disable-delay-ms?=?<1>;
+???????????????unprepare-delay-ms?=?<1>;
????????????????panel-init-sequence?=?[
????????????????????????15?32?02?8F?A5
????????????????????????15?01?02?83?00
修改DRM 超時時間減小喚醒時間
這是最關鍵的,DRM框架非常復雜,RK也是從開源的DRM移植過來使用,在DRM部分有個時間超時導致問題,最終跟RK拿到最新的patch讓喚醒時間直接加速500MS.
我們在日志下發現問題,并給詢問了RK,最終發現這部分代碼沒有更新到最新的部分。
hi rk:
為什么亮屏的時候有時候會打印這句VOP等待超時?請問下這是什么意思。
[ 1211.293492] rockchip-vop ff930000.vop: wait win close timeout
[ 1211.293514] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 1200*1920, close all win
有時候卻不會打印。
[ 1216.423283] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 12001920, close all win [ 1223.899741] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 12001920, close all win
[ 1234.386252] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 1200*1920, close all win
patch代碼如下
---?a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c+++?b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@?-139,6?+139,9?@@
?
?
+/*add?by?VENDOR_PATCH?for?seep?up?the?drm?vop?driver?at?2018/1/18?for?RK?Defect?#191554,?VENDOR_PATCH?PAD100-193*/
+
+
?struct?vop_zpos?{
????????int?win_id;
????????int?zpos;
@@?-868,9?+871,15?@@?static?void?vop_disable_all_planes(struct?vop?*vop)
????????vop_disable_allwin(vop);
????????vop_cfg_done(vop);
+
????????ret?=?readx_poll_timeout_atomic(vop_is_allwin_disabled,
????????????????????????????????????????vop,?active,?active,
+???????????????????????????????????????0,?100?*?1000);
+
+???????ret?=?readx_poll_timeout_atomic(vop_is_allwin_disabled,
+???????????????????????????????vop,?active,?active,
????????????????????????????????????????0,?500?*?1000);
+
????????if?(ret)
????????????????dev_err(vop->dev,?"wait?win?close?timeout\n");
?}
@@?-2215,20?+2224,36?@@?static?size_t?vop_crtc_bandwidth(struct?drm_crtc?*crtc,
????????u16?htotal?=?adjusted_mode->crtc_htotal;
????????u16?vdisplay?=?adjusted_mode->crtc_vdisplay;
????????int?clock?=?adjusted_mode->crtc_clock;
+#ifndef?VENDOR_PATCH
????????struct?vop?*vop?=?to_vop(crtc);
????????const?struct?vop_data?*vop_data?=?vop->data;
+
????????struct?vop_plane_state?*vop_plane_state;
????????struct?drm_plane_state?*pstate;
????????struct?vop_bandwidth?*pbandwidth;
????????struct?drm_plane?*plane;
????????u64?bandwidth;
????????int?i,?cnt?=?0;
+
+???????int?plane_num?=?0;
+
????????if?(!htotal?||?!vdisplay)
????????????????return?0;
+
????????pbandwidth?=?kmalloc_array(vop_data->win_size,?sizeof(*pbandwidth),
???????????????????????????????????GFP_KERNEL);
+
+???????for_each_plane_in_state(state,?plane,?pstate,?i)?{
+???????????????if?(pstate->crtc?!=?crtc?||?!pstate->fb)
+???????????????????????continue;
+???????????????plane_num++;
+???????}
+???????pbandwidth?=?kmalloc_array(plane_num,?sizeof(*pbandwidth),
+??????????????????????????????????GFP_KERNEL);
+
+
????????if?(!pbandwidth)
????????????????return?-ENOMEM;
@@?-2421,7?+2446,10?@@?static?void?vop_crtc_enable(struct?drm_crtc?*crtc)
????????rockchip_set_system_status(sys_status);
????????mutex_lock(&vop->vop_lock);
????????vop_initial(crtc);
-
+
+???????vop_disable_allwin(vop);
+???????VOP_CTRL_SET(vop,?standby,?0);
+
????????VOP_CTRL_SET(vop,?dclk_pol,?1);
????????val?=?(adjusted_mode->flags?&?DRM_MODE_FLAG_NHSYNC)??
???????????????????0?:?BIT(HSYNC_POSITIVE);
@@?-2549,8?+2577,9?@@?static?void?vop_crtc_enable(struct?drm_crtc?*crtc)
????????/*
?????????*?enable?vop,?all?the?register?would?take?effect?when?vop?exit?standby
?????????*/
+#ifndef?VENDOR_PATCH
????????VOP_CTRL_SET(vop,?standby,?0);
-
+
????????enable_irq(vop->irq);
????????drm_crtc_vblank_on(crtc);
????????mutex_unlock(&vop->vop_lock);
修改QOS相關代碼
QOS為Quality Of Service(服務質量)的簡稱,對PM QoS而言,表示Linux kernel電源管理相關的服務質量。那到底什么是服務質量呢?
我們知道,Linux PM的主要功能,是節省功耗,但同時,會付出一定的性能代價,例如延遲(latency)增加、吞吐量(throughput)下降??梢园裀M當作一種服務,把它對性能的影響,類比為服務的質量(QoS)。對性能的影響越大,QoS越低,反之越高。
我們可以這么認為,我們在某個時候需要增加代碼的執行速度,就通過這個去控制CPU的運行策略,這樣確保代碼可以快速執行。
不過這個方法沒有使用到,如果對某個resume時間不是十分滿意,可以嘗試這個方法。
休眠喚醒流程圖
從網上拷貝了個休眠喚醒的流程圖,如果以后有問題需要分析的話,可以跟進這個流程去排查。
參考
https://www.spinics.net/lists/linux-pm/msg24063.html
http://eeepage.info/pm-failed-suspend-wakeup_event/
https://blog.csdn.net/qq_695538007/article/details/41208135
https://blog.csdn.net/jacobywu/article/details/24735521
當你看到這里的時候,說明你已經閱讀完上面的內容,不管怎樣,感謝您有心或者無意的關注和支持,
覺得不錯,請幫忙轉發,點好看,您的每一次支持,我都將銘記于心
公眾號接入了AI功能,隨意回復任意消息哦(比如笑話,天氣)
想獲取學習資料,請點擊狀態欄公眾號福利按鈕
總結
以上是生活随笔為你收集整理的Android 亮屏速度分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我同学
- 下一篇: c语言乐谱提取软件,SmartScore