summaryrefslogtreecommitdiff
path: root/power/power_flo.c
diff options
context:
space:
mode:
Diffstat (limited to 'power/power_flo.c')
-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
};