[MTK] Boost CPU/DDR/GPU in android code
文摘 Kernel MediaTek 2020-05-29 阅读:10751[DESCRIPTION]
为了追求性能,客户有时候想在特定场景中拉满CPU/DDR/GPU,比如亮屏/解锁等场景。以下提供一种在代码中boost CPU/DDR/GPU的方法。
[SOLUTION]
1. Kernel 代码里拉CPU频率
可以参考 kernel-4.*/drivers/misc/mediatek/usb_boost/v1/usb_boost_plat.c
1). 包含头文件
#include "mtk_ppm_api.h"
#include "cpu_ctrl.h"
#define BSP_CERVINO_CLUSTER_NUMBERS 2
2). 在您的 driver 问中添加
struct ppm_limit_data fingerprint_freq_to_set[BSP_CERVINO_CLUSTER_NUMBERS];
struct ppm_limit_data fingerprint_freq_to_release[BSP_CERVINO_CLUSTER_NUMBERS];
static int fingerprint_freq_set(void)
{
int i, cluster_num;
cluster_num = arch_get_nr_clusters();
if(cluster_num > BSP_CERVINO_CLUSTER_NUMBERS)
cluster_num = BSP_CERVINO_CLUSTER_NUMBERS;
for (i = 0; i < BSP_CERVINO_CLUSTER_NUMBERS; i++) {
fingerprint_freq_to_set[i].min = 2001000;
fingerprint_freq_to_set[i].max = -1;
}
if(cluster_num > 0){
update_userlimit_cpu_freq(CPU_KIR_FINGERPRINT, cluster_num, fingerprint_freq_to_set);
return 0;
}
return -1;
}
static int fingerprint_freq_release(void)
{
int i,cluster_num;
cluster_num = arch_get_nr_clusters();
if(cluster_num > BSP_CERVINO_CLUSTER_NUMBERS)
cluster_num = BSP_CERVINO_CLUSTER_NUMBERS;
for (i = 0; i < BSP_CERVINO_CLUSTER_NUMBERS; i++) {
fingerprint_freq_to_release[i].min = -1;
fingerprint_freq_to_release[i].max = -1;
}
if(cluster_num > 0){
update_userlimit_cpu_freq(CPU_KIR_FINGERPRINT, cluster_num, fingerprint_freq_to_release);
return 0;
}
return -1;
}
在您需要的地方 调 fingerprint_freq_set() 去拉 CPU频率;
不需要拉的时候,必须恢复默认配置,释放拉的动作:调 fingerprint_freq_release() 去释放 CPU频率。
set 和 release 必须要对比,否则会引起功耗问题。
3). 在 kernel-4.×/drivers/misc/mediatek/include/mt-plat/cpu_ctrl.h 中添加
enum {
CPU_KIR_PERF = 0,
CPU_KIR_FPSGO,
CPU_KIR_WIFI,
CPU_KIR_BOOT,
CPU_KIR_TOUCH,
CPU_KIR_PERFTOUCH,
CPU_KIR_USB,
+ CPU_KIR_FINGERPRINT,
CPU_MAX_KIR
};
2. 拉DDR频率也可以参考刚刚这个文件 kernel-4.14/drivers/misc/mediatek/usb_boost/v1/usb_boost_plat.c
1) Makefile:
ccflags-y += -I$(srctree)/drivers/devfreq/
2) kernel usage:
#include <linux/pm_qos.h>
#include "helio-dvfsrc-opp.h"
static struct pm_qos_request xxx_ddr_req;
pm_qos_add_request(&xxx_ddr_req, PM_QOS_DDR_OPP_DEFAULT_VALUE);
pm_qos_update_request(&xxx_ddr_req, DDR_OPP_0); //LP4-3200, LP3-1866, 最高檔
pm_qos_update_request(&xxx_ddr_req, DDR_OPP_1); //LP4-2400, LP3-1600 or above
pm_qos_update_request(&xxx_ddr_req, DDR_OPP_3); //LP4-1600, LP3-1200 or above
pm_qos_update_request(&xxx_ddr_req, DDR_OPP_UNREQ); //un-request, or PM_QOS_DDR_OPP_DEFAULT_VALUE
可以参考:
static int vcorefs_hold(struct act_arg_obj *arg)
{
pm_qos_update_request(&pm_qos_ddr_req, DDR_OPP_0);
return 0;
}
static int vcorefs_release(struct act_arg_obj *arg)
{
pm_qos_update_request(&pm_qos_ddr_req, DDR_OPP_UNREQ);
return 0;
}
vcorefs_hold 和 vcorefs_release要对应起来,否则会有power问题。
3. kernel中暂时不提供拉GPU的接口,但在HAL/JNI/Java等上层代码可以boost GPU,见第4条。
4. 如果要在HAL/JNI/Java等上层代码boost CPU/GPU/DDR,请自行在MTK-online上搜Power Hal文档参考修改,里面有完整的 .cpp/.java修改说明。
android Q: MTK_PowerHal_Q0_Porting_Guide
android P: MTK_P0_BSP+_PowerHalService_Programming_Guide
android O: MTK_O1_BSP+_PowerHalService_Programming_Guide
每个android版本对应的API接口是一样,请下载对应版本的文档来参考。
1) 以android Q0为例,如何在 HAL/JNI/等上层代码上boost CPU/GPU/DDR
you can refer to "MTK_PowerHal_Q0_Porting_Guide" about powerHAl customization, you can search this document on MTK-ON-LINE
a. int perf_lock_acq(int handle, int duration, int list[], int numArgs)
handle:
user handle
If handle is 0 or invalid value => register a new handle. Please always check return value.
duration:
boost duration: unit: ms
Set duration to 0 for infinite time
list[]:
opcode value list
Please refer to vendor/mediatek/proprietary/hardware/power/include/mtkperf_resource.h
numArgs:
Length of list[]
It should be (resource size * 2)
b. int perf_lock_rel(int handle)
Handle:
handle to release
c. Please refer to vendor/mediatek/proprietary/hardware/power/test/test_v_1_0
int perf_lock_rsc1[] = {PERF_RES_CPUFREQ_MIN_CLUSTER_0, 1000000, PERF_RES_CPUFREQ_MIN_CLUSTER_1, 3000000, PERF_RES_DRAM_OPP_MIN, 0};
int perf_lock_rsc2[] = {PERF_RES_CPUFREQ_MIN_CLUSTER_0, 3000000, PERF_RES_CPUFREQ_MIN_CLUSTER_1, 1000000, PERF_RES_DRAM_OPP_MIN, 0};
/* such as sample 1*/
int perf_lock_opts[4] = {PERF_RES_CPUFREQ_PERF_MODE, 1, PERF_RES_DRAM_OPP_MIN, 0}; // force all cpu run at the highest freq and DRAM max
perf_lock_hdl = 0; // perf_lock_hdl should be 0 when allocate a new lock
perf_lock_hdl = perf_lock_acq(perf_lock_hdl, 3000, perf_lock_opts, 4); // boost time 3000ms
//............
perf_lock_rel(perf_lock_hdl);
/* sample 2*/
android::hardware::hidl_vec<int32_t> perf_lock_rsc[6] = {PERF_RES_CPUFREQ_MIN_CLUSTER_0, 4, PERF_RES_CPUFREQ_MIN_CLUSTER_1, 4, PERF_RES_DRAM_VCORE_MIN, 0}; // CPU freq index 4, Dram index 0, 0 is the max feq
perf_lock_hdl = gMtkPerf->perfLockAcquire (perf_lock_hdl, 3000, perf_lock_opts, debug_info); // duration: 3000ms
//...........
gMtkPerf->perfLockRelease (perf_lock_hdl);
2) 默认代码你可以参考:
vendor/mediatek/proprietary/hardware/power/test/test_v_1_0/power_native_test.cpp
PERF_RES_GPU_FREQ_MIN //GPU最低档位
PERF_RES_CPUCORE_MIN_CLUSTER_0 //CPU online数
// 设置4个CPU online + GPU频率最高
int perf_lock_opts[4] = {PERF_RES_CPUFREQ_MIN_CLUSTER_0, 4, PERF_RES_GPU_FREQ_MIN, 0};
// GPU频率配置为0,表示最高档位,即配置GPU频率最高。 你需要看GPU的频率500500对应的是什么档,如果是最高档位,设置为0即可
................
perf_lock_hdl = perf_lock_acq(perf_lock_hdl, 3000, perf_lock_opts, 4); // duration timeout: 3000ms
//...................
perf_lock_rel(perf_lock_hdl);
// 如果你要设置 CPU频率也是最高,可以这样配置:
int perf_lock_opts[4] = {PERF_RES_CPUFREQ_MIN_CLUSTER_0, 4, PERF_RES_CPUFREQ_MIN_CLUSTER_0, 3000000, PERF_RES_GPU_FREQ_MIN, 0};
................
perf_lock_hdl = perf_lock_acq(perf_lock_hdl, 3000, perf_lock_opts, 6);
...................
perf_lock_rel(perf_lock_hdl);