diff options
author | Michael Bestas <mkbestas@lineageos.org> | 2018-01-22 02:30:25 +0200 |
---|---|---|
committer | Luca Stefani <luca.stefani.ge1@gmail.com> | 2018-02-08 14:32:37 +0000 |
commit | c1a9261db0dcda82781d085dcc068f0662a2afff (patch) | |
tree | e138adf993a8fce03a872c2f01f0f10aef91f4cf | |
parent | 5584ebb6980f275b3e875ba25196a767d85188fd (diff) | |
download | android_hardware_qcom_power-staging/lineage-15.1.tar.gz android_hardware_qcom_power-staging/lineage-15.1.tar.bz2 android_hardware_qcom_power-staging/lineage-15.1.zip |
power: msm8974: Add support for power profilestaging/lineage-15.1
* Based on Steve Kondik's and Zhao Wei Liew's implementation
from the legacy HAL.
Change-Id: Ie2a28b589537349cbcefc5b64e5404d346edf2c2
-rw-r--r-- | power-8974.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/power-8974.c b/power-8974.c index fbf40d8..81c22b8 100644 --- a/power-8974.c +++ b/power-8974.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (C) 2018 The LineageOS Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -52,6 +53,144 @@ static int display_hint2_sent; static int first_display_off_hint; extern int display_boost; +static int current_power_profile = PROFILE_BALANCED; + +static int profile_high_performance[] = { + CPUS_ONLINE_MIN_4, + 0x0901, + CPU0_MIN_FREQ_TURBO_MAX, + CPU1_MIN_FREQ_TURBO_MAX, + CPU2_MIN_FREQ_TURBO_MAX, + CPU3_MIN_FREQ_TURBO_MAX +}; + +static int profile_power_save[] = { + 0x0A03, + CPUS_ONLINE_MAX_LIMIT_2, + CPU0_MAX_FREQ_NONTURBO_MAX, + CPU1_MAX_FREQ_NONTURBO_MAX, + CPU2_MAX_FREQ_NONTURBO_MAX, + CPU3_MAX_FREQ_NONTURBO_MAX +}; + +static int profile_bias_power[] = { + 0x0A03, + CPU0_MAX_FREQ_NONTURBO_MAX, + CPU1_MAX_FREQ_NONTURBO_MAX, + CPU1_MAX_FREQ_NONTURBO_MAX, + CPU2_MAX_FREQ_NONTURBO_MAX +}; + +static int profile_bias_performance[] = { + CPU0_MIN_FREQ_NONTURBO_MAX + 1, + CPU1_MIN_FREQ_NONTURBO_MAX + 1, + CPU2_MIN_FREQ_NONTURBO_MAX + 1, + CPU2_MIN_FREQ_NONTURBO_MAX + 1 +}; + +int get_number_of_profiles() { + return 5; +} + +static void set_power_profile(int profile) { + + if (profile == current_power_profile) + return; + + ALOGV("%s: Profile=%d", __func__, profile); + + if (current_power_profile != PROFILE_BALANCED) { + undo_hint_action(DEFAULT_PROFILE_HINT_ID); + ALOGV("%s: Hint undone", __func__); + } + + if (profile == PROFILE_POWER_SAVE) { + perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save, + ARRAY_SIZE(profile_power_save)); + ALOGD("%s: Set powersave mode", __func__); + + } else if (profile == PROFILE_HIGH_PERFORMANCE) { + perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_high_performance, + ARRAY_SIZE(profile_high_performance)); + ALOGD("%s: Set performance mode", __func__); + + } else if (profile == PROFILE_BIAS_POWER) { + perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_power, + ARRAY_SIZE(profile_bias_power)); + ALOGD("%s: Set bias power mode", __func__); + + } else if (profile == PROFILE_BIAS_PERFORMANCE) { + perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_performance, + ARRAY_SIZE(profile_bias_performance)); + ALOGD("%s: Set bias perf mode", __func__); + + } + + current_power_profile = profile; +} + +void interaction(int duration, int num_args, int opt_list[]); + +int power_hint_override(power_hint_t hint, void *data) +{ + if (hint == POWER_HINT_SET_PROFILE) { + set_power_profile(*(int32_t *)data); + return HINT_HANDLED; + } + + // Skip other hints in high/low power modes + if (current_power_profile == PROFILE_POWER_SAVE || + current_power_profile == PROFILE_HIGH_PERFORMANCE) { + return HINT_HANDLED; + } + + if (hint == POWER_HINT_LAUNCH) { + int duration = 2000; + int resources[] = { CPUS_ONLINE_MIN_3, + CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, + CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX }; + + interaction(duration, ARRAY_SIZE(resources), resources); + + return HINT_HANDLED; + } + + if (hint == POWER_HINT_INTERACTION) { + int duration = 500, duration_hint = 0; + static struct timespec s_previous_boost_timespec; + struct timespec cur_boost_timespec; + long long elapsed_time; + + if (data) { + duration_hint = *((int *)data); + } + + duration = duration_hint > 0 ? duration_hint : 500; + + clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); + elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); + if (elapsed_time > 750000) + elapsed_time = 750000; + // don't hint if it's been less than 250ms since last boost + // also detect if we're doing anything resembling a fling + // support additional boosting in case of flings + else if (elapsed_time < 250000 && duration <= 750) + return HINT_HANDLED; + + s_previous_boost_timespec = cur_boost_timespec; + + int resources[] = { (duration >= 2000 ? CPUS_ONLINE_MIN_3 : CPUS_ONLINE_MIN_2), + 0x20F, 0x30F, 0x40F, 0x50F }; + + if (duration) + interaction(duration, ARRAY_SIZE(resources), resources); + + return HINT_HANDLED; + } + + return HINT_NONE; +} + int set_interactive_override(int on) { char governor[80]; |