diff options
Diffstat (limited to 'power')
-rw-r--r-- | power/Android.mk | 2 | ||||
-rw-r--r-- | power/power.c | 80 | ||||
-rw-r--r-- | power/power.h | 27 |
3 files changed, 98 insertions, 11 deletions
diff --git a/power/Android.mk b/power/Android.mk index 0cb4890..af65a3c 100644 --- a/power/Android.mk +++ b/power/Android.mk @@ -18,6 +18,8 @@ ifeq ($(TARGET_POWERHAL_VARIANT),pegasusq) include $(CLEAR_VARS) +LOCAL_CFLAGS += -DUSE_PEGASUSQ_BOOSTING + LOCAL_MODULE := power.$(TARGET_BOOTLOADER_BOARD_NAME) LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SHARED_LIBRARIES := liblog libcutils diff --git a/power/power.c b/power/power.c index f5df011..278994e 100644 --- a/power/power.c +++ b/power/power.c @@ -35,10 +35,13 @@ #define PEGASUSQ_PATH "/sys/devices/system/cpu/cpufreq/pegasusq/" #define MINMAX_CPU_PATH "/sys/power/" +#define US_TO_NS (1000L) + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static int current_power_profile = -1; static bool is_low_power = false; +static bool is_vsync_active = false; static int sysfs_write_str(char *path, char *s) { char buf[80]; @@ -70,6 +73,13 @@ static int sysfs_write_int(char *path, int value) { snprintf(buf, 80, "%d", value); return sysfs_write_str(path, buf); } + +static int sysfs_write_long(char *path, long value) { + char buf[80]; + snprintf(buf, 80, "%ld", value); + return sysfs_write_str(path, buf); +} + #ifdef LOG_NDEBUG #define WRITE_PEGASUSQ_PARAM(profile, param) do { \ ALOGV("%s: WRITE_PEGASUSQ_PARAM(profile=%d, param=%s): new val => %d", __func__, profile, #param, profiles[profile].param); \ @@ -136,6 +146,8 @@ static void set_power_profile(int profile) { WRITE_PEGASUSQ_PARAM(profile, cpu_down_rate); WRITE_PEGASUSQ_PARAM(profile, sampling_rate); WRITE_PEGASUSQ_PARAM(profile, io_is_busy); + WRITE_PEGASUSQ_PARAM(profile, boost_freq); + WRITE_PEGASUSQ_PARAM(profile, boost_mincpus); current_power_profile = profile; @@ -143,6 +155,24 @@ static void set_power_profile(int profile) { } +static void boost(long boost_time) { +#ifdef USE_PEGASUSQ_BOOSTING + if (is_vsync_active) return; + if (boost_time == -1) { + sysfs_write_int(PEGASUSQ_PATH "boost_lock_time", -1); + } else { + sysfs_write_long(PEGASUSQ_PATH "boost_lock_time", boost_time); + } +#endif +} + +static void end_boost() { +#ifdef USE_PEGASUSQ_BOOSTING + if (is_vsync_active) return; + sysfs_write_int(PEGASUSQ_PATH "boost_lock_time", 0); +#endif +} + static void set_low_power(bool low_power) { if (!is_profile_valid(current_power_profile)) { ALOGV("%s: current_power_profile not set yet", __func__); @@ -154,6 +184,8 @@ static void set_low_power(bool low_power) { if (is_low_power == low_power) return; if (low_power) { + end_boost(); + WRITE_LOW_POWER_PARAM(current_power_profile, hotplug_freq_1_1); WRITE_LOW_POWER_PARAM(current_power_profile, hotplug_freq_2_0); WRITE_LOW_POWER_PARAM(current_power_profile, hotplug_freq_2_1); @@ -198,6 +230,9 @@ static void set_low_power(bool low_power) { WRITE_PEGASUSQ_PARAM(current_power_profile, cpu_down_rate); WRITE_PEGASUSQ_PARAM(current_power_profile, sampling_rate); WRITE_PEGASUSQ_PARAM(current_power_profile, io_is_busy); + WRITE_PEGASUSQ_PARAM(current_power_profile, boost_freq); + WRITE_PEGASUSQ_PARAM(current_power_profile, boost_mincpus); + is_low_power = false; } } @@ -288,21 +323,44 @@ static void power_set_interactive(__attribute__((unused)) struct power_module *m * integer value of the boost duration in microseconds. */ static void power_hint(__attribute__((unused)) struct power_module *module, power_hint_t hint, void *data) { + if (hint == POWER_HINT_SET_PROFILE) { + ALOGV("%s: set profile %d", __func__, *(int32_t *)data); + pthread_mutex_lock(&lock); + if (is_vsync_active) { + is_vsync_active = false; + end_boost(); + } + set_power_profile(*(int32_t *)data); + pthread_mutex_unlock(&lock); + } + + if (current_power_profile == PROFILE_POWER_SAVE) return; + + pthread_mutex_lock(&lock); + switch (hint) { - case POWER_HINT_SET_PROFILE: - ALOGV("%s: set profile %d", __func__, *(int32_t *)data); - pthread_mutex_lock(&lock); - set_power_profile(*(int32_t *)data); - pthread_mutex_unlock(&lock); - break; case POWER_HINT_INTERACTION: - case POWER_HINT_VSYNC: + case POWER_HINT_LAUNCH_BOOST: + ALOGV("%s: interaction/launch", __func__); + boost(profiles[current_power_profile].interaction_boost_time); + break; +/* case POWER_HINT_VSYNC: + if (*(int32_t *)data) { + ALOGV("%s: vsync", __func__); + boost(-1); + is_vsync_active = true; + } else { + is_vsync_active = false; + end_boost(); + } + break;*/ + case POWER_HINT_CPU_BOOST: + ALOGV("%s: cpu_boost", __func__); + boost((*(int32_t *)data) * US_TO_NS); break; - case POWER_HINT_LOW_POWER: - break; - default: - break; } + + pthread_mutex_unlock(&lock); } /* diff --git a/power/power.h b/power/power.h index db031cf..08ceb51 100644 --- a/power/power.h +++ b/power/power.h @@ -14,6 +14,8 @@ * limitations under the License. */ +#define MS_TO_NS (1000000L) + enum { PROFILE_POWER_SAVE = 0, PROFILE_BALANCED, @@ -50,6 +52,10 @@ typedef struct governor_settings { int cpu_down_rate; int sampling_rate; // in microseconds int io_is_busy; + // boosting + int boost_freq; + int boost_mincpus; + long interaction_boost_time; } power_profile; static power_profile profiles[PROFILE_MAX] = { @@ -75,6 +81,10 @@ static power_profile profiles[PROFILE_MAX] = { .cpu_down_rate = 5, .sampling_rate = 200000, .io_is_busy = 0, + // nb: boosting power hints are ignored for PROFILE_POWER_SAVE + .boost_freq = 0, + .boost_mincpus = 0, + .interaction_boost_time = 0, }, [PROFILE_BALANCED] = { .hotplug_freq_1_1 = 500000, @@ -98,6 +108,9 @@ static power_profile profiles[PROFILE_MAX] = { .cpu_down_rate = 10, .sampling_rate = 200000, .io_is_busy = 0, + .boost_freq = 700000, + .boost_mincpus = 0, + .interaction_boost_time = 60 * (MS_TO_NS), }, [PROFILE_PERFORMANCE] = { .hotplug_freq_1_1 = 500000, @@ -121,9 +134,14 @@ static power_profile profiles[PROFILE_MAX] = { .cpu_down_rate = 20, .sampling_rate = 200000, .io_is_busy = 1, + .boost_freq = 900000, + .boost_mincpus = 2, + .interaction_boost_time = 90 * (MS_TO_NS), }, }; +// for non-interactive profiles we don't need to worry about +// boosting as it (should) only occur while the screen is on static power_profile profiles_low_power[PROFILE_MAX] = { [PROFILE_POWER_SAVE] = { .hotplug_freq_1_1 = 800000, @@ -147,6 +165,9 @@ static power_profile profiles_low_power[PROFILE_MAX] = { .cpu_down_rate = 5, .sampling_rate = 200000, .io_is_busy = 0, + .boost_freq = 0, + .boost_mincpus = 0, + .interaction_boost_time = 0, }, [PROFILE_BALANCED] = { .hotplug_freq_1_1 = 700000, @@ -170,6 +191,9 @@ static power_profile profiles_low_power[PROFILE_MAX] = { .cpu_down_rate = 8, .sampling_rate = 200000, .io_is_busy = 0, + .boost_freq = 0, + .boost_mincpus = 0, + .interaction_boost_time = 0, }, [PROFILE_PERFORMANCE] = { .hotplug_freq_1_1 = 800000, @@ -193,6 +217,9 @@ static power_profile profiles_low_power[PROFILE_MAX] = { .cpu_down_rate = 15, .sampling_rate = 200000, .io_is_busy = 1, + .boost_freq = 0, + .boost_mincpus = 0, + .interaction_boost_time = 0, }, }; |