power: Support power profiles on legacy platforms

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Mon Mar 26 01:52:03 2018 +0300

    power: apq8084: Add support for power profile & boost

    * Based on msm8974 HAL.

    Change-Id: I88ce707b022f7b122ad7a2fcfc67fde0075d7e7a

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Fri May 25 21:30:28 2018 +0300

    power: Spring cleanup

    * Cleanup SoC specific files:
     - Fix code spacing and indentation
     - Remove dead code
     - Remove useless comments
     - Remove useless logs
     - Make code uniform between the files so it's easier to diff
     - Use declared enums when possible for power hints

    Change-Id: Ie1378c94c53b33299927c5eb1bfc19f1a42b8743

Author: Stefan Assmann <sassmann@kpanic.de>
Date:   Mon Jul 23 18:42:02 2018 +0200

    power-8084: rework power profiles

    profile_power_save: 2 cores max freq 1,2GHz
    profile_bias_power: 2 cores max freq 2,4GHz
    profile_bias_performance: 4 cores min freq 1,2GHz (2 active)
    profile_high_performance: 4 cores min freq 1,5GHz (4 active)

    - rearranged profiles in ascending order
    - fixed typo in profile_bias_performance

    Change-Id: I6f5d34e797c4f1f7ce9f7344f7f489c40debd094

Author: Corinna Vinschen <xda@vinschen.de>
Date:   Thu Aug 9 12:51:12 2018 +0200

    power-8084: document performance settings

    Change-Id: Ic6dbe8511d694be0c0883f3052c612aa0a30c581
    Signed-off-by: Corinna Vinschen <xda@vinschen.de>

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Mon Mar 26 02:07:03 2018 +0300

    power: msm8226: Add support for power profile & boost

    * Based on legacy HAL implementation

    Change-Id: Ifb93945e4e4005ef922cacee95e51bb95d5df9e3

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Mon Mar 26 02:13:51 2018 +0300

    power: msm8610: Add support for power profile & boost

    * Based on legacy HAL implementation

    Change-Id: If778938b9703fd01185c2448bc83a09f04348333

Author: dianlujitao <dianlujitao@lineageos.org>
Date:   Sun Mar 25 18:08:45 2018 +0800

    power: msm8916: Add support for power profile & boost

    * Based on legacy HAL implementation

    Change-Id: I20225ae9244023555724c76df5e208fd60eb3841

Author: Corinna Vinschen <xda@vinschen.de>
Date:   Wed Aug 29 14:18:03 2018 +0200

    power-8916: fix using wrong array size in perform_hint_action

    * Fix a copy/paste bug using the wrong array size

    Change-Id: I07172b8e857ad3e6ad7761b3e090b518005ba26b

Author: Ethan Chen <intervigil@gmail.com>
Date:   Sun Feb 25 20:46:37 2018 -0800

    msm8952: Support power profiles

    * Add support for power profiles

    Change-Id: I0ce3578530dd8618468fd97b1e49ba512cb8fa83

Author: Zhao Wei Liew <zhaoweiliew@gmail.com>
Date:   Tue Nov 17 17:45:03 2015 +0800

    power: msm8960: Implement performance profiles

    * Based on legacy HAL implementation

    Change-Id: Id7d16f97c177a790427d848e8ccea3286cf37a4e

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Mon Jan 22 02:30:25 2018 +0200

    power: msm8974: Add support for power profile

     * Based on Steve Kondik's and Zhao Wei Liew's implementation
       from the legacy HAL.

    Change-Id: Ie2a28b589537349cbcefc5b64e5404d346edf2c2

Author: dianlujitao <dianlujitao@lineageos.org>
Date:   Fri Mar 2 12:40:04 2018 +0800

    power: Don't advertise power profile when interaction boost disabled

     * Power profile is fake news without interaction boost.

    Change-Id: Iceea885e6cb176f0620e76cfc335b7da500a0c2b

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Mon Mar 26 03:00:15 2018 +0300

    power: msm8992: Add support for power profile & boost

    * Based on legacy HAL implementation

    Change-Id: I9ebb44c1e215a76a95180a6188e80cb24f0b03ba

Author: Michael Bestas <mkbestas@lineageos.org>
Date:   Mon Mar 26 03:00:30 2018 +0300

    power: msm8994: Add support for power profile & boost

    * Based on legacy HAL implementation

    Change-Id: I5aa0b75b493825f2d87ce6eea0f3c3b1c3bba135

Author: Han Wang <wanghan1995315@gmail.com>
Date:   Tue Jul 24 17:12:14 2018 +0200

    power: Fix several typos in power profiles

    Change-Id: I8302d41a902a037548ab52dc68ab8a0d7ca47861

Author: Corinna Vinschen <xda@vinschen.de>
Date:   Sun Aug 26 22:11:49 2018 +0200

    power: set_power_profile: handle errors

    * Make sure current_power_profile reflects actual setting.
    * Propagate error condition up to caller.
    * Handle error from set_power_profile in power_hint_override.

    Change-Id: I8518d921a94c912c75f59fbf993a8f44116bdca9
    Signed-off-by: Corinna Vinschen <xda@vinschen.de>

Author: dianlujitao <dianlujitao@lineageos.org>
Date:   Sat Feb 23 20:24:57 2019 +0800

    power: Pass NULL parameter in powerHint if data is zero

     * This restores the behavior in AOSP and CAF power HAL to avoid
       confusion.

    Change-Id: I72f5bb9286e2f57121e39eea82d2fe8854989393

Change-Id: Ic483c0aa5e095f29f5de450472a6243d663468b6
diff --git a/power-8960.c b/power-8960.c
index 6c29b06..6ea0568 100644
--- a/power-8960.c
+++ b/power-8960.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2018-2019 The LineageOS Project
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -48,6 +49,92 @@
 #include "power-common.h"
 #include "utils.h"
 
+/**
+ * Returns true if the target is APQ8064.
+ */
+static bool is_target_8064(void) {
+    static int is_8064 = -1;
+    int soc_id;
+
+    if (is_8064 >= 0) return is_8064;
+
+    soc_id = get_soc_id();
+    is_8064 = soc_id == 153;
+
+    return is_8064;
+}
+
+static int current_power_profile = PROFILE_BALANCED;
+
+// clang-format off
+static int profile_high_performance_8960[] = {
+    CPUS_ONLINE_MIN_2,
+};
+
+static int profile_high_performance_8064[] = {
+    CPUS_ONLINE_MIN_4,
+};
+
+static int profile_power_save_8960[] = {
+    /* Don't do anything for now */
+};
+
+static int profile_power_save_8064[] = {
+    CPUS_ONLINE_MAX_LIMIT_2,
+};
+// clang-format on
+
+#ifdef INTERACTION_BOOST
+int get_number_of_profiles() {
+    return 3;
+}
+#endif
+
+static int set_power_profile(void* data) {
+    int profile = data ? *((int*)data) : 0;
+    int ret = -EINVAL;
+    const char* profile_name = NULL;
+
+    if (profile == current_power_profile) return 0;
+
+    ALOGV("%s: Profile=%d", __func__, profile);
+
+    if (current_power_profile != PROFILE_BALANCED) {
+        undo_hint_action(DEFAULT_PROFILE_HINT_ID);
+        ALOGV("%s: Hint undone", __func__);
+        current_power_profile = PROFILE_BALANCED;
+    }
+
+    if (profile == PROFILE_POWER_SAVE) {
+        if (is_target_8064()) {
+            ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save_8064,
+                                      ARRAY_SIZE(profile_power_save_8064));
+        } else {
+            ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save_8960,
+                                      ARRAY_SIZE(profile_power_save_8960));
+        }
+        profile_name = "powersave";
+    } else if (profile == PROFILE_HIGH_PERFORMANCE) {
+        if (is_target_8064()) {
+            ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_high_performance_8064,
+                                      ARRAY_SIZE(profile_high_performance_8064));
+        } else {
+            ret = perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_high_performance_8960,
+                                      ARRAY_SIZE(profile_high_performance_8960));
+        }
+        profile_name = "performance";
+    } else if (profile == PROFILE_BALANCED) {
+        ret = 0;
+        profile_name = "balanced";
+    }
+
+    if (ret == 0) {
+        current_power_profile = profile;
+        ALOGD("%s: Set %s mode", __func__, profile_name);
+    }
+    return ret;
+}
+
 static int process_video_encode_hint(void* metadata) {
     char governor[80];
     struct video_encode_metadata_t video_encode_metadata;
@@ -126,6 +213,18 @@
 
 int power_hint_override(power_hint_t hint, void* data) {
     int ret_val = HINT_NONE;
+
+    if (hint == POWER_HINT_SET_PROFILE) {
+        if (set_power_profile(data) < 0) ALOGE("Setting power profile failed. perfd not started?");
+        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;
+    }
+
     switch (hint) {
         case POWER_HINT_VIDEO_ENCODE:
             ret_val = process_video_encode_hint(data);