summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhao Wei Liew <zhaoweiliew@gmail.com>2016-02-15 22:04:01 +0800
committerZhao Wei Liew <zhaoweiliew@gmail.com>2016-02-23 19:26:56 +0800
commitddc24160a940a6145a2a0ae76b6f03ec4399dd1b (patch)
tree4c3877275cc20acd1b0e28d02e2809b43c246987
parentde533683b48475778b6e6293b2a764acb2396b9e (diff)
flo: Add performance profile support
Refactor low power mode hint to use performance profiles. Currently we only limit the minimum and maximum frequency. More testing has to be done as to further tuning. Thanks for fixing crash & incorrect locking: @keepcalm444 (Simon Shields) Change-Id: I198b59e12278431afc77108ffae95cd36b2812e9
-rw-r--r--power/power_flo.c98
1 files changed, 77 insertions, 21 deletions
diff --git a/power/power_flo.c b/power/power_flo.c
index 654bfb5..d9f6360 100644
--- a/power/power_flo.c
+++ b/power/power_flo.c
@@ -40,9 +40,10 @@
#define MAX_LENGTH 50
#define BOOST_SOCKET "/dev/socket/pb"
-#define LOW_POWER_MAX_FREQ 1026000
-#define LOW_POWER_MIN_FREQ 384000
+#define POWERSAVE_MAX_FREQ 1026000
+#define BIAS_POWER_MAX_FREQ 1134000
#define NORMAL_MAX_FREQ 1512000
+#define NORMAL_MIN_FREQ 384000
#define MAX_FREQ_LIMIT_PATH "/sys/kernel/cpufreq_limit/limited_max_freq"
#define MIN_FREQ_LIMIT_PATH "/sys/kernel/cpufreq_limit/limited_min_freq"
@@ -51,8 +52,18 @@ static int client_sockfd;
static struct sockaddr_un client_addr;
static int last_state = -1;
-static bool low_power_mode = false;
-static pthread_mutex_t low_power_mode_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t profile_lock = PTHREAD_MUTEX_INITIALIZER;
+
+enum {
+ PROFILE_POWER_SAVE = 0,
+ PROFILE_BALANCED,
+ PROFILE_HIGH_PERFORMANCE,
+ PROFILE_BIAS_POWER,
+ PROFILE_BIAS_PERFORMANCE,
+ PROFILE_MAX
+};
+
+static int current_power_profile = PROFILE_BALANCED;
static void socket_init()
{
@@ -91,6 +102,13 @@ static int sysfs_write(const char *path, char *s)
return 0;
}
+static int sysfs_write_int(char *path, int value)
+{
+ char buf[80];
+ snprintf(buf, 80, "%d", value);
+ return sysfs_write(path, buf);
+}
+
static void power_init(__attribute__((unused)) struct power_module *module)
{
ALOGI("%s", __func__);
@@ -177,7 +195,6 @@ static void process_video_encode_hint(void *metadata)
}
}
-
static void touch_boost()
{
int rc;
@@ -215,10 +232,52 @@ static void power_set_interactive(__attribute__((unused)) struct power_module *m
}
}
+static void set_power_profile(int profile) {
+ int min_freq, max_freq;
+
+ ALOGV("%s: profile=%d", __func__, profile);
+
+ if (profile == PROFILE_BALANCED) {
+ min_freq = NORMAL_MIN_FREQ;
+ max_freq = NORMAL_MAX_FREQ;
+ ALOGD("%s: set balanced mode", __func__);
+ } else if (profile == PROFILE_HIGH_PERFORMANCE) {
+ min_freq = NORMAL_MAX_FREQ;
+ max_freq = NORMAL_MAX_FREQ;
+ ALOGD("%s: set performance mode", __func__);
+ } else if (profile == PROFILE_BIAS_PERFORMANCE) {
+ min_freq = BIAS_POWER_MAX_FREQ;
+ max_freq = NORMAL_MAX_FREQ;
+ ALOGD("%s: set bias perf mode", __func__);
+ } else if (profile == PROFILE_BIAS_POWER) {
+ min_freq = NORMAL_MIN_FREQ;
+ max_freq = BIAS_POWER_MAX_FREQ;
+ ALOGD("%s: set bias power mode", __func__);
+ } else if (profile == PROFILE_POWER_SAVE) {
+ min_freq = NORMAL_MIN_FREQ;
+ max_freq = POWERSAVE_MAX_FREQ;
+ ALOGD("%s: set powersave mode", __func__);
+ }
+
+ sysfs_write_int(MIN_FREQ_LIMIT_PATH, min_freq);
+ sysfs_write_int(MAX_FREQ_LIMIT_PATH, max_freq);
+
+ current_power_profile = profile;
+}
+
static void power_hint( __attribute__((unused)) struct power_module *module,
- power_hint_t hint, __attribute__((unused)) void *data)
+ power_hint_t hint, void *data)
{
- int cpu, ret;
+ if (hint == POWER_HINT_SET_PROFILE) {
+ pthread_mutex_lock(&profile_lock);
+ set_power_profile(*(int32_t *)data);
+ pthread_mutex_unlock(&profile_lock);
+ return;
+ }
+
+ // Skip other hints in powersave mode
+ if (current_power_profile == PROFILE_POWER_SAVE)
+ return;
switch (hint) {
case POWER_HINT_LAUNCH_BOOST:
@@ -229,19 +288,6 @@ static void power_hint( __attribute__((unused)) struct power_module *module,
case POWER_HINT_VIDEO_ENCODE:
process_video_encode_hint(data);
break;
-
- case POWER_HINT_LOW_POWER:
- pthread_mutex_lock(&low_power_mode_lock);
- if (data) {
- low_power_mode = true;
- sysfs_write(MIN_FREQ_LIMIT_PATH, LOW_POWER_MIN_FREQ);
- sysfs_write(MAX_FREQ_LIMIT_PATH, LOW_POWER_MAX_FREQ);
- } else {
- low_power_mode = false;
- sysfs_write(MAX_FREQ_LIMIT_PATH, NORMAL_MAX_FREQ);
- }
- pthread_mutex_unlock(&low_power_mode_lock);
- break;
default:
break;
}
@@ -251,6 +297,15 @@ static struct hw_module_methods_t power_module_methods = {
.open = NULL,
};
+static int get_feature(__attribute__((unused)) struct power_module *module,
+ feature_t feature)
+{
+ if (feature == POWER_FEATURE_SUPPORTED_PROFILES)
+ return PROFILE_MAX;
+
+ return -1;
+}
+
struct power_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
@@ -258,11 +313,12 @@ struct power_module HAL_MODULE_INFO_SYM = {
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = POWER_HARDWARE_MODULE_ID,
.name = "Flo/Deb Power HAL",
- .author = "The Android Open Source Project",
+ .author = "The CyanogenMod Project",
.methods = &power_module_methods,
},
.init = power_init,
.setInteractive = power_set_interactive,
.powerHint = power_hint,
+ .getFeature = get_feature
};