summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ng <dave@codeaurora.org>2018-03-22 23:49:12 -0700
committerDavid Ng <dave@codeaurora.org>2018-05-24 00:32:16 -0700
commitee7c4c58319f0d081f5a684a97faa33b8614206f (patch)
tree347465f294d5df8465f29c5bac9755cc4f3094f3
parentdda2692d71cdb4b4bceb93406a6163506becc116 (diff)
downloadvendor_qcom_opensource_power-ee7c4c58319f0d081f5a684a97faa33b8614206f.tar.gz
vendor_qcom_opensource_power-ee7c4c58319f0d081f5a684a97faa33b8614206f.tar.bz2
vendor_qcom_opensource_power-ee7c4c58319f0d081f5a684a97faa33b8614206f.zip
Relocate power HAL from device/qcom/common
Split module from combined device/qcom/common project into its own project. Relocation of some files from device/qcom/common at b5ce80cb1f60759a142a9338104d3adf3303ec0c. Change-Id: I6c13729a822f6fb9b5574b759ae9ec12154be464
-rw-r--r--Android.mk76
-rw-r--r--NOTICE32
-rw-r--r--hint-data.c47
-rw-r--r--hint-data.h62
-rw-r--r--list.c145
-rw-r--r--list.h41
-rw-r--r--metadata-defs.h54
-rw-r--r--metadata-parser.c133
-rw-r--r--performance.h265
-rw-r--r--power-660.c291
-rw-r--r--power-8084.c114
-rw-r--r--power-8226.c65
-rw-r--r--power-845.c272
-rw-r--r--power-8610.c65
-rw-r--r--power-8952.c195
-rw-r--r--power-8953.c202
-rw-r--r--power-8974.c114
-rw-r--r--power-8994.c149
-rw-r--r--power-8996.c179
-rw-r--r--power-8998.c224
-rw-r--r--power-common.h49
-rw-r--r--power.c508
-rw-r--r--powerhintparser.c178
-rw-r--r--powerhintparser.h48
-rw-r--r--utils.c361
-rw-r--r--utils.h47
26 files changed, 3916 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..748030b
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,76 @@
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(TARGET_USES_QSSI),true)
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+
+# HAL module implemenation stored in
+# hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libdl libxml2
+LOCAL_SRC_FILES := power.c metadata-parser.c utils.c list.c hint-data.c powerhintparser.c
+LOCAL_C_INCLUDES := external/libxml2/include \
+ external/icu/icu4c/source/common
+
+# Include target-specific files.
+ifeq ($(call is-board-platform-in-list, msm8974), true)
+LOCAL_SRC_FILES += power-8974.c
+endif
+
+ifeq ($(call is-board-platform-in-list, msm8226), true)
+LOCAL_SRC_FILES += power-8226.c
+endif
+
+ifeq ($(call is-board-platform-in-list, msm8610), true)
+LOCAL_SRC_FILES += power-8610.c
+endif
+
+ifeq ($(call is-board-platform-in-list, apq8084), true)
+LOCAL_SRC_FILES += power-8084.c
+endif
+
+ifeq ($(call is-board-platform-in-list, msm8994), true)
+LOCAL_SRC_FILES += power-8994.c
+endif
+
+ifeq ($(call is-board-platform-in-list, msm8996), true)
+LOCAL_SRC_FILES += power-8996.c
+endif
+
+ifeq ($(call is-board-platform-in-list,msm8937), true)
+LOCAL_SRC_FILES += power-8952.c
+endif
+
+ifeq ($(call is-board-platform-in-list,msm8952), true)
+LOCAL_SRC_FILES += power-8952.c
+endif
+
+ifeq ($(call is-board-platform-in-list,msm8953), true)
+LOCAL_SRC_FILES += power-8953.c
+endif
+
+ifeq ($(call is-board-platform-in-list,msm8998 apq8098_latv), true)
+LOCAL_SRC_FILES += power-8998.c
+endif
+
+ifeq ($(call is-board-platform-in-list,sdm660), true)
+LOCAL_SRC_FILES += power-660.c
+endif
+
+ifeq ($(call is-board-platform-in-list,sdm845), true)
+LOCAL_SRC_FILES += power-845.c
+endif
+
+ifeq ($(TARGET_USES_INTERACTION_BOOST),true)
+ LOCAL_CFLAGS += -DINTERACTION_BOOST
+endif
+
+LOCAL_MODULE := power.qcom
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-variable
+LOCAL_VENDOR_MODULE := true
+include $(BUILD_SHARED_LIBRARY)
+
+endif
+endif
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..26f0cc8
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,32 @@
+Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted (subject to the limitations in the
+disclaimer below) provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/hint-data.c b/hint-data.c
new file mode 100644
index 0000000..67da77a
--- /dev/null
+++ b/hint-data.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hint-data.h"
+
+int hint_compare(struct hint_data *first_hint,
+ struct hint_data *other_hint) {
+ if (first_hint == other_hint) {
+ return 0;
+ } else if ((first_hint && other_hint) &&
+ (first_hint->hint_id == other_hint->hint_id)) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+void hint_dump(struct hint_data *hint)
+{
+ /*ALOGI("hint_id: %lu", hint->hint_id);*/
+}
diff --git a/hint-data.h b/hint-data.h
new file mode 100644
index 0000000..0cb54c2
--- /dev/null
+++ b/hint-data.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2013, 2015, 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Default use-case hint IDs */
+#define DEFAULT_VIDEO_ENCODE_HINT_ID (0x0A00)
+#define DEFAULT_VIDEO_DECODE_HINT_ID (0x0B00)
+#define DISPLAY_STATE_HINT_ID (0x0C00)
+#define DISPLAY_STATE_HINT_ID_2 (0x0D00)
+#define CAM_PREVIEW_HINT_ID (0x0E00)
+#define SUSTAINED_PERF_HINT_ID (0x0F00)
+#define VR_MODE_HINT_ID (0x1000)
+#define VR_MODE_SUSTAINED_PERF_HINT_ID (0x1001)
+
+#define AOSP_DELTA (0x1200)
+
+#define VSYNC_HINT AOSP_DELTA + POWER_HINT_VSYNC
+#define INTERACTION_HINT AOSP_DELTA + POWER_HINT_INTERACTION
+#define VIDEO_DECODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_DECODE
+#define VIDEO_ENCODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_ENCODE
+#define LOW_POWER_HINT AOSP_DELTA + POWER_HINT_LOW_POWER
+#define SUSTAINED_PERF_HINT AOSP_DELTA + POWER_HINT_SUSTAINED_PERFORMANCE
+#define VR_MODE_HINT AOSP_DELTA + POWER_HINT_VR_MODE
+#define LAUNCH_HINT AOSP_DELTA + POWER_HINT_LAUNCH
+#define DISABLE_TOUCH_HINT AOSP_DELTA + POWER_HINT_DISABLE_TOUCH
+
+#define VR_MODE_SUSTAINED_PERF_HINT (0x1301)
+
+
+struct hint_data {
+ unsigned long hint_id; /* This is our key. */
+ unsigned long perflock_handle;
+};
+
+int hint_compare(struct hint_data *first_hint,
+ struct hint_data *other_hint);
+void hint_dump(struct hint_data *hint);
diff --git a/list.c b/list.c
new file mode 100644
index 0000000..0fe8de2
--- /dev/null
+++ b/list.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "list.h"
+#include <utils/Log.h>
+
+int init_list_head(struct list_node *head)
+{
+ if (head == NULL)
+ return -1;
+
+ memset(head, 0, sizeof(*head));
+
+ return 0;
+}
+
+struct list_node *add_list_node(struct list_node *head, void *data)
+{
+ /* Create a new list_node. And put 'data' into it. */
+ struct list_node *new_node;
+
+ if (head == NULL) {
+ return NULL;
+ }
+
+ if (!(new_node = malloc(sizeof(struct list_node)))) {
+ return NULL;
+ }
+
+ new_node->data = data;
+ new_node->next = head->next;
+ new_node->compare = head->compare;
+ new_node->dump = head->dump;
+ head->next = new_node;
+
+ return new_node;
+}
+
+int is_list_empty(struct list_node *head)
+{
+ return (head == NULL || head->next == NULL);
+}
+
+/*
+ * Delink and de-allocate 'node'.
+ */
+int remove_list_node(struct list_node *head, struct list_node *del_node)
+{
+ struct list_node *current_node;
+ struct list_node *saved_node;
+
+ if (head == NULL || head->next == NULL) {
+ return -1;
+ }
+
+ current_node = head->next;
+ saved_node = head;
+
+ while (current_node && current_node != del_node) {
+ saved_node = current_node;
+ current_node = current_node->next;
+ }
+
+ if (saved_node) {
+ if (current_node) {
+ saved_node->next = current_node->next;
+ } else {
+ /* Node not found. */
+ return -1;
+ }
+ }
+
+ if (del_node) {
+ free(del_node);
+ }
+
+ return 0;
+}
+
+void dump_list(struct list_node *head)
+{
+ struct list_node *current_node = head;
+
+ if (head == NULL)
+ return;
+
+ printf("List:\n");
+
+ while ((current_node = current_node->next)) {
+ if (current_node->dump) {
+ current_node->dump(current_node->data);
+ }
+ }
+}
+
+struct list_node *find_node(struct list_node *head, void *comparison_data)
+{
+ struct list_node *current_node = head;
+
+ if (head == NULL)
+ return NULL;
+
+ while ((current_node = current_node->next)) {
+ if (current_node->compare) {
+ if (current_node->compare(current_node->data,
+ comparison_data) == 0) {
+ /* Match found. Return current_node. */
+ return current_node;
+ }
+ }
+ }
+
+ /* No match found. */
+ return NULL;
+}
diff --git a/list.h b/list.h
new file mode 100644
index 0000000..d68c3df
--- /dev/null
+++ b/list.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct list_node {
+ struct list_node *next;
+ void *data;
+ int (*compare)(void *data1, void *data2);
+ void (*dump)(void *data);
+};
+
+int init_list_head(struct list_node *head);
+struct list_node * add_list_node(struct list_node *head, void *data);
+int remove_list_node(struct list_node *head, struct list_node *del_node);
+void dump_list(struct list_node *head);
+struct list_node *find_node(struct list_node *head, void *comparison_data);
diff --git a/metadata-defs.h b/metadata-defs.h
new file mode 100644
index 0000000..c464900
--- /dev/null
+++ b/metadata-defs.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define ATTRIBUTE_VALUE_DELIM ('=')
+#define ATTRIBUTE_STRING_DELIM (";")
+
+#define METADATA_PARSING_ERR (-1)
+#define METADATA_PARSING_CONTINUE (0)
+#define METADATA_PARSING_DONE (1)
+
+#define MIN(x,y) (((x)>(y))?(y):(x))
+
+struct video_encode_metadata_t {
+ int hint_id;
+ int state;
+};
+
+struct video_decode_metadata_t {
+ int hint_id;
+ int state;
+};
+
+int parse_metadata(char *metadata, char **metadata_saveptr,
+ char *attribute, int attribute_size, char *value, int value_size);
+int parse_video_encode_metadata(char *metadata,
+ struct video_encode_metadata_t *video_encode_metadata);
+int parse_video_decode_metadata(char *metadata,
+ struct video_decode_metadata_t *video_decode_metadata);
diff --git a/metadata-parser.c b/metadata-parser.c
new file mode 100644
index 0000000..c9122a4
--- /dev/null
+++ b/metadata-parser.c
@@ -0,0 +1,133 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "metadata-defs.h"
+
+int parse_metadata(char *metadata, char **metadata_saveptr,
+ char *attribute, int attribute_size, char *value, int value_size)
+{
+ char *attribute_string;
+ char *attribute_value_delim;
+ unsigned int bytes_to_copy;
+
+ attribute_string = strtok_r(metadata, ATTRIBUTE_STRING_DELIM,
+ metadata_saveptr);
+
+ if (attribute_string == NULL)
+ return METADATA_PARSING_DONE;
+
+ attribute[0] = value[0] = '\0';
+
+ if ((attribute_value_delim = strchr(attribute_string,
+ ATTRIBUTE_VALUE_DELIM)) != NULL) {
+ bytes_to_copy = MIN((attribute_value_delim - attribute_string),
+ attribute_size - 1);
+ /* Replace strncpy with strlcpy
+ * Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */
+ strlcpy(attribute, attribute_string,
+ bytes_to_copy+1);
+
+ bytes_to_copy = MIN(strlen(attribute_string) - strlen(attribute) - 1,
+ value_size - 1);
+ /* Replace strncpy with strlcpy
+ * Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */
+ strlcpy(value, attribute_value_delim + 1,
+ bytes_to_copy+1);
+ }
+
+ return METADATA_PARSING_CONTINUE;
+}
+
+int parse_video_encode_metadata(char *metadata,
+ struct video_encode_metadata_t *video_encode_metadata)
+{
+ char attribute[1024], value[1024], *saveptr;
+ char *temp_metadata = metadata;
+ int parsing_status;
+
+ while ((parsing_status = parse_metadata(temp_metadata, &saveptr,
+ attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) {
+ if (strlen(attribute) == strlen("hint_id") &&
+ (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) {
+ if (strlen(value) > 0) {
+ video_encode_metadata->hint_id = atoi(value);
+ }
+ }
+
+ if (strlen(attribute) == strlen("state") &&
+ (strncmp(attribute, "state", strlen("state")) == 0)) {
+ if (strlen(value) > 0) {
+ video_encode_metadata->state = atoi(value);
+ }
+ }
+
+ temp_metadata = NULL;
+ }
+
+ if (parsing_status == METADATA_PARSING_ERR)
+ return -1;
+
+ return 0;
+}
+
+int parse_video_decode_metadata(char *metadata,
+ struct video_decode_metadata_t *video_decode_metadata)
+{
+ char attribute[1024], value[1024], *saveptr;
+ char *temp_metadata = metadata;
+ int parsing_status;
+
+ while ((parsing_status = parse_metadata(temp_metadata, &saveptr,
+ attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) {
+ if (strlen(attribute) == strlen("hint_id") &&
+ (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) {
+ if (strlen(value) > 0) {
+ video_decode_metadata->hint_id = atoi(value);
+ }
+ }
+
+ if (strlen(attribute) == strlen("state") &&
+ (strncmp(attribute, "state", strlen("state")) == 0)) {
+ if (strlen(value) > 0) {
+ video_decode_metadata->state = atoi(value);
+ }
+ }
+
+ temp_metadata = NULL;
+ }
+
+ if (parsing_status == METADATA_PARSING_ERR)
+ return -1;
+
+ return 0;
+}
diff --git a/performance.h b/performance.h
new file mode 100644
index 0000000..b7bf34b
--- /dev/null
+++ b/performance.h
@@ -0,0 +1,265 @@
+/* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FAILED -1
+#define SUCCESS 0
+#define INDEFINITE_DURATION 0
+
+/* Hints sent to perf HAL from power HAL
+ * These have to be kept in sync with Perf HAL side definitions
+ */
+#define VENDOR_HINT_DISPLAY_OFF 0x00001040
+#define VENDOR_HINT_DISPLAY_ON 0x00001041
+
+enum SCREEN_DISPLAY_TYPE {
+ DISPLAY_OFF = 0x00FF,
+};
+
+enum PWR_CLSP_TYPE {
+ ALL_CPUS_PWR_CLPS_DIS = 0x101,
+};
+
+/* For CPUx min freq, the leftmost byte
+ * represents the CPU and the
+ * rightmost byte represents the frequency
+ * All intermediate frequencies on the
+ * device are supported. The hex value
+ * passed into PerfLock will be multiplied
+ * by 10^5. This frequency or the next
+ * highest frequency available will be set
+ *
+ * For example, if 1.4 Ghz is required on
+ * CPU0, use 0x20E
+ *
+ * If the highest available frequency
+ * on the device is required, use
+ * CPUx_MIN_FREQ_TURBO_MAX
+ * where x represents the CPU
+ */
+enum CPU0_MIN_FREQ_LVL {
+ CPU0_MIN_FREQ_NONTURBO_MAX = 0x20A,
+ CPU0_MIN_FREQ_TURBO_MAX = 0x2FE,
+};
+
+enum CPU1_MIN_FREQ_LVL {
+ CPU1_MIN_FREQ_NONTURBO_MAX = 0x30A,
+ CPU1_MIN_FREQ_TURBO_MAX = 0x3FE,
+};
+
+enum CPU2_MIN_FREQ_LVL {
+ CPU2_MIN_FREQ_NONTURBO_MAX = 0x40A,
+ CPU2_MIN_FREQ_TURBO_MAX = 0x4FE,
+};
+
+enum CPU3_MIN_FREQ_LVL {
+ CPU3_MIN_FREQ_NONTURBO_MAX = 0x50A,
+ CPU3_MIN_FREQ_TURBO_MAX = 0x5FE,
+};
+
+enum CPU0_MAX_FREQ_LVL {
+ CPU0_MAX_FREQ_NONTURBO_MAX = 0x150A,
+};
+
+enum CPU1_MAX_FREQ_LVL {
+ CPU1_MAX_FREQ_NONTURBO_MAX = 0x160A,
+};
+
+enum CPU2_MAX_FREQ_LVL {
+ CPU2_MAX_FREQ_NONTURBO_MAX = 0x170A,
+};
+
+enum CPU3_MAX_FREQ_LVL {
+ CPU3_MAX_FREQ_NONTURBO_MAX = 0x180A,
+};
+
+enum MIN_CPUS_ONLINE_LVL {
+ CPUS_ONLINE_MIN_2 = 0x702,
+ CPUS_ONLINE_MIN_3 = 0x703,
+ CPUS_ONLINE_MIN_4 = 0x704,
+ CPUS_ONLINE_MPD_OVERRIDE = 0x777,
+ CPUS_ONLINE_MAX = 0x7FF,
+};
+
+enum MAX_CPUS_ONLINE_LVL {
+ CPUS_ONLINE_MAX_LIMIT_1 = 0x8FE,
+ CPUS_ONLINE_MAX_LIMIT_2 = 0x8FD,
+ CPUS_ONLINE_MAX_LIMIT_3 = 0x8FC,
+ CPUS_ONLINE_MAX_LIMIT_4 = 0x8FB,
+ CPUS_ONLINE_MAX_LIMIT_MAX = 0x8FB,
+};
+
+enum SAMPLING_RATE_LVL {
+ MS_500 = 0xBCD,
+ MS_50 = 0xBFA,
+ MS_20 = 0xBFD,
+};
+
+enum ONDEMAND_IO_BUSY_LVL {
+ IO_BUSY_OFF = 0xC00,
+ IO_BUSY_ON = 0xC01,
+};
+
+enum ONDEMAND_SAMPLING_DOWN_FACTOR_LVL {
+ SAMPLING_DOWN_FACTOR_1 = 0xD01,
+ SAMPLING_DOWN_FACTOR_4 = 0xD04,
+};
+
+enum INTERACTIVE_TIMER_RATE_LVL {
+ TR_MS_500 = 0xECD,
+ TR_MS_100 = 0xEF5,
+ TR_MS_50 = 0xEFA,
+ TR_MS_30 = 0xEFC,
+ TR_MS_20 = 0xEFD,
+};
+
+/* This timer rate applicable to cpu0
+ across 8939 series chipset */
+enum INTERACTIVE_TIMER_RATE_LVL_CPU0_8939 {
+ TR_MS_CPU0_500 = 0x30CD,
+ TR_MS_CPU0_100 = 0x30F5,
+ TR_MS_CPU0_50 = 0x30FA,
+ TR_MS_CPU0_30 = 0x30FC,
+ TR_MS_CPU0_20 = 0x30FD,
+};
+
+/* This timer rate applicable to cpu4
+ across 8939 series chipset */
+enum INTERACTIVE_TIMER_RATE_LVL_CPU4_8939 {
+ TR_MS_CPU4_500 = 0x3BCD,
+ TR_MS_CPU4_100 = 0x3BF5,
+ TR_MS_CPU4_50 = 0x3BFA,
+ TR_MS_CPU4_30 = 0x3BFC,
+ TR_MS_CPU4_20 = 0x3BFD,
+};
+
+/* This timer rate applicable to big.little arch */
+enum INTERACTIVE_TIMER_RATE_LVL_BIG_LITTLE {
+ BIG_LITTLE_TR_MS_100 = 0x64,
+ BIG_LITTLE_TR_MS_50 = 0x32,
+ BIG_LITTLE_TR_MS_40 = 0x28,
+ BIG_LITTLE_TR_MS_30 = 0x1E,
+ BIG_LITTLE_TR_MS_20 = 0x14,
+};
+
+/* INTERACTIVE opcodes */
+enum INTERACTIVE_OPCODES {
+ INT_OP_CLUSTER0_TIMER_RATE = 0x41424000,
+ INT_OP_CLUSTER1_TIMER_RATE = 0x41424100,
+ INT_OP_CLUSTER0_USE_SCHED_LOAD = 0x41430000,
+ INT_OP_CLUSTER1_USE_SCHED_LOAD = 0x41430100,
+ INT_OP_CLUSTER0_USE_MIGRATION_NOTIF = 0x41434000,
+ INT_OP_CLUSTER1_USE_MIGRATION_NOTIF = 0x41434100,
+ INT_OP_NOTIFY_ON_MIGRATE = 0x4241C000
+};
+
+enum INTERACTIVE_HISPEED_FREQ_LVL {
+ HS_FREQ_1026 = 0xF0A,
+};
+
+enum INTERACTIVE_HISPEED_LOAD_LVL {
+ HISPEED_LOAD_90 = 0x105A,
+};
+
+enum SYNC_FREQ_LVL {
+ SYNC_FREQ_300 = 0x1103,
+ SYNC_FREQ_600 = 0X1106,
+ SYNC_FREQ_384 = 0x1103,
+ SYNC_FREQ_NONTURBO_MAX = 0x110A,
+ SYNC_FREQ_TURBO = 0x110F,
+};
+
+enum OPTIMAL_FREQ_LVL {
+ OPTIMAL_FREQ_300 = 0x1203,
+ OPTIMAL_FREQ_600 = 0x1206,
+ OPTIMAL_FREQ_384 = 0x1203,
+ OPTIMAL_FREQ_NONTURBO_MAX = 0x120A,
+ OPTIMAL_FREQ_TURBO = 0x120F,
+};
+
+enum SCREEN_PWR_CLPS_LVL {
+ PWR_CLPS_DIS = 0x1300,
+ PWR_CLPS_ENA = 0x1301,
+};
+
+enum THREAD_MIGRATION_LVL {
+ THREAD_MIGRATION_SYNC_OFF = 0x1400,
+};
+
+enum INTERACTIVE_IO_BUSY_LVL {
+ INTERACTIVE_IO_BUSY_OFF = 0x1B00,
+ INTERACTIVE_IO_BUSY_ON = 0x1B01,
+};
+
+enum SCHED_BOOST_LVL {
+ SCHED_BOOST_ON = 0x1E01,
+};
+
+enum CPU4_MIN_FREQ_LVL {
+ CPU4_MIN_FREQ_NONTURBO_MAX = 0x1F0A,
+ CPU4_MIN_FREQ_TURBO_MAX = 0x1FFE,
+};
+
+enum CPU5_MIN_FREQ_LVL {
+ CPU5_MIN_FREQ_NONTURBO_MAX = 0x200A,
+ CPU5_MIN_FREQ_TURBO_MAX = 0x20FE,
+};
+
+enum CPU6_MIN_FREQ_LVL {
+ CPU6_MIN_FREQ_NONTURBO_MAX = 0x210A,
+ CPU6_MIN_FREQ_TURBO_MAX = 0x21FE,
+};
+
+enum CPU7_MIN_FREQ_LVL {
+ CPU7_MIN_FREQ_NONTURBO_MAX = 0x220A,
+ CPU7_MIN_FREQ_TURBO_MAX = 0x22FE,
+};
+
+enum CPU4_MAX_FREQ_LVL {
+ CPU4_MAX_FREQ_NONTURBO_MAX = 0x230A,
+};
+
+enum CPU5_MAX_FREQ_LVL {
+ CPU5_MAX_FREQ_NONTURBO_MAX = 0x240A,
+};
+
+enum CPU6_MAX_FREQ_LVL {
+ CPU6_MAX_FREQ_NONTURBO_MAX = 0x250A,
+};
+
+enum CPU7_MAX_FREQ_LVL {
+ CPU7_MAX_FREQ_NONTURBO_MAX = 0x260A,
+};
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/power-660.c b/power-660.c
new file mode 100644
index 0000000..a0b81f9
--- /dev/null
+++ b/power-660.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+#define MIN_VAL(X,Y) ((X>Y)?(Y):(X))
+
+static int saved_interactive_mode = -1;
+static int display_hint_sent;
+static int video_encode_hint_sent;
+static int cam_preview_hint_sent;
+
+pthread_mutex_t camera_hint_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int camera_hint_ref_count;
+static void process_video_encode_hint(void *metadata);
+//static void process_cam_preview_hint(void *metadata);
+
+static bool is_target_SDM630() /* Returns value=630 if target is SDM630 else value 0 */
+{
+ int fd;
+ bool is_target_SDM630=false;
+ char buf[10] = {0};
+ fd = open("/sys/devices/soc0/soc_id", O_RDONLY);
+ if (fd >= 0) {
+ if (read(fd, buf, sizeof(buf) - 1) == -1) {
+ ALOGW("Unable to read soc_id");
+ is_target_SDM630 = false;
+ } else {
+ int soc_id = atoi(buf);
+ if (soc_id == 318 || soc_id== 327) {
+ is_target_SDM630 = true; /* Above SOCID for SDM630 */
+ }
+ }
+ }
+ close(fd);
+ return is_target_SDM630;
+}
+
+int power_hint_override(struct power_module *module, power_hint_t hint,
+ void *data)
+{
+
+ switch(hint) {
+ case POWER_HINT_VSYNC:
+ break;
+ case POWER_HINT_VIDEO_ENCODE:
+ {
+ process_video_encode_hint(data);
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ char governor[80];
+ char tmp_str[NODE_MAX];
+ int resource_values[20];
+ int num_resources;
+ struct video_encode_metadata_t video_encode_metadata;
+ int rc;
+
+ ALOGI("Got set_interactive hint");
+
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+ return HINT_HANDLED;
+ }
+ }
+ }
+ }
+
+ if (!on) {
+ /* Display off. */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /*
+ 1. CPUfreq params
+ - hispeed freq for big - 1113Mhz
+ - go hispeed load for big - 95
+ - above_hispeed_delay for big - 40ms
+ 2. BusDCVS V2 params
+ - Sample_ms of 10ms
+ */
+ if(is_target_SDM630()){
+ int res[] = { 0x41414000, 0x459,
+ 0x41410000, 0x5F,
+ 0x41400000, 0x4,
+ 0x41820000, 0xA };
+ memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
+ num_resources = sizeof(res)/sizeof(res[0]);
+ }
+ /*
+ 1. CPUfreq params
+ - hispeed freq for little - 902Mhz
+ - go hispeed load for little - 95
+ - above_hispeed_delay for little - 40ms
+ 2. BusDCVS V2 params
+ - Sample_ms of 10ms
+ 3. Sched group upmigrate - 500
+ */
+ else{
+ int res[] = { 0x41414100, 0x386,
+ 0x41410100, 0x5F,
+ 0x41400100, 0x4,
+ 0x41820000, 0xA,
+ 0x40C54000, 0x1F4};
+ memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
+ num_resources = sizeof(res)/sizeof(res[0]);
+
+ }
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, num_resources);
+ display_hint_sent = 1;
+ }
+ }
+
+ } else {
+ /* Display on. */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ }
+ }
+ saved_interactive_mode = !!on;
+ return HINT_HANDLED;
+}
+
+
+/* Video Encode Hint */
+static void process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ int resource_values[20];
+ int num_resources;
+ struct video_encode_metadata_t video_encode_metadata;
+
+ ALOGI("Got process_video_encode_hint");
+
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU0) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU1) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU2) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU3) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+ // return HINT_HANDLED;
+ }
+ }
+ }
+ }
+
+ /* Initialize encode metadata struct fields. */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+ video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_encode_metadata((char *)metadata,
+ &video_encode_metadata) == -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR,
+ strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /*
+ 1. CPUfreq params
+ - hispeed freq for big - 1113Mhz
+ - go hispeed load for big - 95
+ - above_hispeed_delay for big - 40ms
+ - target loads - 95
+ - nr_run - 5
+ 2. BusDCVS V2 params
+ - Sample_ms of 10ms
+ */
+ if(is_target_SDM630()){
+ int res[] = { 0x41414000, 0x459,
+ 0x41410000, 0x5F,
+ 0x41400000, 0x4,
+ 0x41420000, 0x5F,
+ 0x40C2C000, 0X5,
+ 0x41820000, 0xA};
+ memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
+ num_resources = sizeof(res)/sizeof(res[0]);
+
+ }
+ /*
+ 1. CPUfreq params
+ - hispeed freq for little - 902Mhz
+ - go hispeed load for little - 95
+ - above_hispeed_delay for little - 40ms
+ 2. BusDCVS V2 params
+ - Sample_ms of 10ms
+ */
+ else{
+ int res[] = { 0x41414100, 0x386,
+ 0x41410100, 0x5F,
+ 0x41400100, 0x4,
+ 0x41820000, 0xA};
+ memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res)));
+ num_resources = sizeof(res)/sizeof(res[0]);
+ }
+ pthread_mutex_lock(&camera_hint_mutex);
+ camera_hint_ref_count++;
+ if (camera_hint_ref_count == 1) {
+ if (!video_encode_hint_sent) {
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values, num_resources);
+ video_encode_hint_sent = 1;
+ }
+ }
+ pthread_mutex_unlock(&camera_hint_mutex);
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR,
+ strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ pthread_mutex_lock(&camera_hint_mutex);
+ camera_hint_ref_count--;
+ if (!camera_hint_ref_count) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ video_encode_hint_sent = 0;
+ }
+ pthread_mutex_unlock(&camera_hint_mutex);
+ return ;
+ }
+ }
+ return;
+}
+
+
diff --git a/power-8084.c b/power-8084.c
new file mode 100644
index 0000000..5d4b6bf
--- /dev/null
+++ b/power-8084.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int display_hint_sent;
+static int display_hint2_sent;
+static int first_display_off_hint;
+extern int display_boost;
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ char governor[80];
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ if (!on) {
+ /* Display off. */
+ /*
+ * We need to be able to identify the first display off hint
+ * and release the current lock holder
+ */
+ if (display_boost) {
+ if (!first_display_off_hint) {
+ undo_initial_hint_action();
+ first_display_off_hint = 1;
+ }
+ /* used for all subsequent toggles to the display */
+ if (!display_hint2_sent) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID_2);
+ display_hint2_sent = 1;
+ }
+ }
+
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ int resource_values[] = {MS_500, SYNC_FREQ_600, OPTIMAL_FREQ_600, THREAD_MIGRATION_SYNC_OFF};
+
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ }
+
+ return HINT_HANDLED;
+ }
+ } else {
+ /* Display on */
+ if (display_boost && display_hint2_sent) {
+ int resource_values2[] = {CPUS_ONLINE_MIN_2};
+ perform_hint_action(DISPLAY_STATE_HINT_ID_2,
+ resource_values2, sizeof(resource_values2)/sizeof(resource_values2[0]));
+ display_hint2_sent = 0;
+ }
+
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+
+ return HINT_HANDLED;
+ }
+ }
+
+ return HINT_NONE;
+}
diff --git a/power-8226.c b/power-8226.c
new file mode 100644
index 0000000..9f14645
--- /dev/null
+++ b/power-8226.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int display_hint_sent;
+
+int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
+{
+ switch(hint) {
+ case POWER_HINT_INTERACTION:
+ {
+ int resources[] = {0x702, 0x20B, 0x30B};
+ int duration = 3000;
+
+ interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
diff --git a/power-845.c b/power-845.c
new file mode 100644
index 0000000..ca6f421
--- /dev/null
+++ b/power-845.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int display_fd;
+#define SYS_DISPLAY_PWR "/sys/kernel/hbtp/display_pwr"
+
+#define CHECK_HANDLE(x) ((x)>0)
+#define NUM_PERF_MODES 3
+
+typedef enum {
+ NORMAL_MODE = 0,
+ SUSTAINED_MODE = 1,
+ VR_MODE = 2,
+ VR_SUSTAINED_MODE = (SUSTAINED_MODE|VR_MODE),
+ INVALID_MODE = 0xFF
+}perf_mode_type_t;
+
+typedef struct perf_mode {
+ perf_mode_type_t type;
+ int perf_hint_id;
+}perf_mode_t;
+
+perf_mode_t perf_modes[NUM_PERF_MODES] = { { SUSTAINED_MODE, SUSTAINED_PERF_HINT },
+ { VR_MODE, VR_MODE_HINT },
+ { VR_SUSTAINED_MODE, VR_MODE_SUSTAINED_PERF_HINT } };
+
+static pthread_mutex_t perf_mode_switch_lock = PTHREAD_MUTEX_INITIALIZER;
+static int current_mode = NORMAL_MODE;
+
+static inline int get_perfd_hint_id(perf_mode_type_t type) {
+ int i;
+ for(i=0; i<NUM_PERF_MODES; i++) {
+ if (perf_modes[i].type == type) {
+ ALOGD("Hint id is 0x%x for mode 0x%x", perf_modes[i].perf_hint_id, type);
+ return perf_modes[i].perf_hint_id;
+ }
+ }
+ ALOGD("Couldn't find the hint for mode 0x%x", type);
+ return 0;
+}
+
+static int switch_mode(perf_mode_type_t mode) {
+
+ int hint_id = 0;
+ static int perfd_mode_handle = -1;
+
+ // release existing mode if any
+ if (CHECK_HANDLE(perfd_mode_handle)) {
+ ALOGD("Releasing handle 0x%x", perfd_mode_handle);
+ release_request(perfd_mode_handle);
+ perfd_mode_handle = -1;
+ }
+ // switch to a perf mode
+ hint_id = get_perfd_hint_id(mode);
+ if(hint_id != 0) {
+ perfd_mode_handle = perf_hint_enable(hint_id, 0);
+ if (!CHECK_HANDLE(perfd_mode_handle)) {
+ ALOGE("Failed perf_hint_interaction for mode: 0x%x", mode);
+ return -1;
+ }
+ ALOGD("Acquired handle 0x%x", perfd_mode_handle);
+ }
+ return 0;
+}
+
+static int process_perf_hint(void *data, perf_mode_type_t mode) {
+
+ pthread_mutex_lock(&perf_mode_switch_lock);
+
+ // enable
+ if (data){
+ ALOGI("Enable request for mode: 0x%x", mode);
+ // check if mode is current mode
+ if ( current_mode & mode ) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGD("Mode 0x%x already enabled", mode);
+ return HINT_HANDLED;
+ }
+ // enable requested mode
+ if ( 0 != switch_mode(current_mode | mode)) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGE("Couldn't enable mode 0x%x", mode);
+ return HINT_NONE;
+ }
+ current_mode |= mode;
+ ALOGI("Current mode is 0x%x", current_mode);
+ // disable
+ } else {
+ ALOGI("Disable request for mode: 0x%x", mode);
+ // check if mode is enabled
+ if ( !(current_mode & mode) ) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGD("Mode 0x%x already disabled", mode);
+ return HINT_HANDLED;
+ }
+ //disable requested mode
+ if ( 0 != switch_mode(current_mode & ~mode)) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGE("Couldn't disable mode 0x%x", mode);
+ return HINT_NONE;
+ }
+ current_mode &= ~mode;
+ ALOGI("Current mode is 0x%x", current_mode);
+ }
+
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ return HINT_HANDLED;
+}
+
+static int process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+ static int video_encode_handle = 0;
+
+ if(!metadata)
+ return HINT_NONE;
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ /* Initialize encode metadata struct fields */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+
+ if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
+ -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return HINT_NONE;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if (is_interactive_governor(governor)) {
+ video_encode_handle = perf_hint_enable(
+ VIDEO_ENCODE_HINT, 0);
+ ALOGI("Video encode hint start");
+ return HINT_HANDLED;
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if (is_interactive_governor(governor)) {
+ release_request(video_encode_handle);
+ ALOGI("Video Encode hint stop");
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+/* Declare function before use */
+void interaction(int duration, int num_args, int opt_list[]);
+
+int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
+{
+ int ret_val = HINT_NONE;
+ switch(hint) {
+ case POWER_HINT_VIDEO_ENCODE:
+ ret_val = process_video_encode_hint(data);
+ break;
+ case POWER_HINT_SUSTAINED_PERFORMANCE:
+ ret_val = process_perf_hint(data, SUSTAINED_MODE);
+ break;
+ case POWER_HINT_VR_MODE:
+ ret_val = process_perf_hint(data, VR_MODE);
+ break;
+ case POWER_HINT_INTERACTION:
+ {
+ int resources[] = {0x40800100, 0x514};
+ int duration = 100;
+ interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
+ ret_val = HINT_HANDLED;
+ }
+ break;
+ default:
+ break;
+ }
+ return ret_val;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ static const char *display_on = "1";
+ static const char *display_off = "0";
+ char err_buf[80];
+ static int init_interactive_hint = 0;
+ static int set_i_count = 0;
+ int rc = 0;
+
+ set_i_count ++;
+ ALOGI("Got set_interactive hint on= %d, count= %d\n", on, set_i_count);
+
+ if (init_interactive_hint == 0)
+ {
+ //First time the display is turned off
+ display_fd = TEMP_FAILURE_RETRY(open(SYS_DISPLAY_PWR, O_RDWR));
+ if (display_fd < 0) {
+ strerror_r(errno,err_buf,sizeof(err_buf));
+ ALOGE("Error opening %s: %s\n", SYS_DISPLAY_PWR, err_buf);
+ }
+ else
+ init_interactive_hint = 1;
+ }
+ else
+ if (!on ) {
+ /* Display off. */
+ rc = TEMP_FAILURE_RETRY(write(display_fd, display_off, strlen(display_off)));
+ if (rc < 0) {
+ strerror_r(errno,err_buf,sizeof(err_buf));
+ ALOGE("Error writing %s to %s: %s\n", display_off, SYS_DISPLAY_PWR, err_buf);
+ }
+ }
+ else {
+ /* Display on */
+ rc = TEMP_FAILURE_RETRY(write(display_fd, display_on, strlen(display_on)));
+ if (rc < 0) {
+ strerror_r(errno,err_buf,sizeof(err_buf));
+ ALOGE("Error writing %s to %s: %s\n", display_on, SYS_DISPLAY_PWR, err_buf);
+ }
+ }
+
+ return HINT_HANDLED; /* Don't excecute this code path, not in use */
+}
diff --git a/power-8610.c b/power-8610.c
new file mode 100644
index 0000000..9f14645
--- /dev/null
+++ b/power-8610.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int display_hint_sent;
+
+int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
+{
+ switch(hint) {
+ case POWER_HINT_INTERACTION:
+ {
+ int resources[] = {0x702, 0x20B, 0x30B};
+ int duration = 3000;
+
+ interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
diff --git a/power-8952.c b/power-8952.c
new file mode 100644
index 0000000..8a87c27
--- /dev/null
+++ b/power-8952.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int saved_interactive_mode = -1;
+static int display_hint_sent;
+static int video_encode_hint_sent;
+
+static void process_video_encode_hint(void *metadata);
+
+int power_hint_override(struct power_module *module, power_hint_t hint,
+ void *data)
+{
+
+ switch(hint) {
+ case POWER_HINT_VSYNC:
+ break;
+ case POWER_HINT_VIDEO_ENCODE:
+ {
+ process_video_encode_hint(data);
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ char governor[80];
+ char tmp_str[NODE_MAX];
+ struct video_encode_metadata_t video_encode_metadata;
+ int rc;
+
+ ALOGI("Got set_interactive hint");
+
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+ return HINT_HANDLED;
+ }
+ }
+ }
+ }
+
+ if (!on) {
+ /* Display off. */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ int resource_values[] = {INT_OP_CLUSTER0_TIMER_RATE, BIG_LITTLE_TR_MS_50,
+ INT_OP_CLUSTER1_TIMER_RATE, BIG_LITTLE_TR_MS_50,
+ INT_OP_NOTIFY_ON_MIGRATE, 0x00};
+
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ }
+ } /* Perf time rate set for CORE0,CORE4 8952 target*/
+
+ } else {
+ /* Display on. */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ }
+ }
+ saved_interactive_mode = !!on;
+ return HINT_HANDLED;
+}
+
+/* Video Encode Hint */
+static void process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+
+ ALOGI("Got process_video_encode_hint");
+
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU0) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU1) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU2) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU3) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+ return;
+ }
+ }
+ }
+ }
+
+ /* Initialize encode metadata struct fields. */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+ video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_encode_metadata((char *)metadata,
+ &video_encode_metadata) == -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR,
+ strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /* Sched_load and migration_notif*/
+ int resource_values[] = {INT_OP_CLUSTER0_USE_SCHED_LOAD,
+ 0x1,
+ INT_OP_CLUSTER1_USE_SCHED_LOAD,
+ 0x1,
+ INT_OP_CLUSTER0_USE_MIGRATION_NOTIF,
+ 0x1,
+ INT_OP_CLUSTER1_USE_MIGRATION_NOTIF,
+ 0x1,
+ INT_OP_CLUSTER0_TIMER_RATE,
+ BIG_LITTLE_TR_MS_40,
+ INT_OP_CLUSTER1_TIMER_RATE,
+ BIG_LITTLE_TR_MS_40
+ };
+ if (!video_encode_hint_sent) {
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values,
+ sizeof(resource_values)/sizeof(resource_values[0]));
+ video_encode_hint_sent = 1;
+ }
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR,
+ strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ video_encode_hint_sent = 0;
+ return ;
+ }
+ }
+ return;
+}
+
diff --git a/power-8953.c b/power-8953.c
new file mode 100644
index 0000000..09df941
--- /dev/null
+++ b/power-8953.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int saved_interactive_mode = -1;
+static int display_hint_sent;
+static int video_encode_hint_sent;
+static int cam_preview_hint_sent;
+
+pthread_mutex_t camera_hint_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int camera_hint_ref_count;
+static void process_video_encode_hint(void *metadata);
+//static void process_cam_preview_hint(void *metadata);
+
+int power_hint_override(struct power_module *module, power_hint_t hint,
+ void *data)
+{
+
+ switch(hint) {
+ case POWER_HINT_VSYNC:
+ break;
+ case POWER_HINT_VIDEO_ENCODE:
+ {
+ process_video_encode_hint(data);
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ char governor[80];
+ char tmp_str[NODE_MAX];
+ struct video_encode_metadata_t video_encode_metadata;
+ int rc;
+
+ ALOGI("Got set_interactive hint");
+
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) {
+ if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+ return HINT_HANDLED;
+ }
+ }
+ }
+ }
+
+ if (!on) {
+ /* Display off. */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /* timer rate - 40mS*/
+ int resource_values[] = {0x41424000, 0x28,
+ };
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ }
+ } /* Perf time rate set for CORE0,CORE4 8952 target*/
+
+ } else {
+ /* Display on. */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ }
+ }
+ saved_interactive_mode = !!on;
+ return HINT_HANDLED;
+}
+
+
+/* Video Encode Hint */
+static void process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+
+ ALOGI("Got process_video_encode_hint");
+
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU0) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU1) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU2) == -1) {
+ if (get_scaling_governor_check_cores(governor,
+ sizeof(governor),CPU3) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+ // return HINT_HANDLED;
+ }
+ }
+ }
+ }
+
+ /* Initialize encode metadata struct fields. */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+ video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_encode_metadata((char *)metadata,
+ &video_encode_metadata) == -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR,
+ strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /* Sched_load and migration_notification disable
+ * timer rate - 40mS*/
+ int resource_values[] = {0x41430000, 0x1,
+ 0x41434000, 0x1,
+ 0x41424000, 0x28,
+ };
+ pthread_mutex_lock(&camera_hint_mutex);
+ camera_hint_ref_count++;
+ if (camera_hint_ref_count == 1) {
+ if (!video_encode_hint_sent) {
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values,
+ sizeof(resource_values)/sizeof(resource_values[0]));
+ video_encode_hint_sent = 1;
+ }
+ }
+ pthread_mutex_unlock(&camera_hint_mutex);
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR,
+ strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ pthread_mutex_lock(&camera_hint_mutex);
+ camera_hint_ref_count--;
+ if (!camera_hint_ref_count) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ video_encode_hint_sent = 0;
+ }
+ pthread_mutex_unlock(&camera_hint_mutex);
+ return ;
+ }
+ }
+ return;
+}
+
+
diff --git a/power-8974.c b/power-8974.c
new file mode 100644
index 0000000..1e56cc3
--- /dev/null
+++ b/power-8974.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int display_hint_sent;
+static int display_hint2_sent;
+static int first_display_off_hint;
+extern int display_boost;
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ char governor[80];
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ if (!on) {
+ /* Display off. */
+ /*
+ * We need to be able to identify the first display off hint
+ * and release the current lock holder
+ */
+ if (display_boost) {
+ if (!first_display_off_hint) {
+ undo_initial_hint_action();
+ first_display_off_hint = 1;
+ }
+ /* used for all subsequent toggles to the display */
+ if (!display_hint2_sent) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID_2);
+ display_hint2_sent = 1;
+ }
+ }
+
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ int resource_values[] = {MS_500, SYNC_FREQ_600, OPTIMAL_FREQ_600, THREAD_MIGRATION_SYNC_OFF};
+
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ }
+
+ return HINT_HANDLED;
+ }
+ } else {
+ /* Display on */
+ if (display_boost && display_hint2_sent) {
+ int resource_values2[] = {CPUS_ONLINE_MIN_2};
+ perform_hint_action(DISPLAY_STATE_HINT_ID_2,
+ resource_values2, sizeof(resource_values2)/sizeof(resource_values2[0]));
+ display_hint2_sent = 0;
+ }
+
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+
+ return HINT_HANDLED;
+ }
+ }
+
+ return HINT_NONE;
+}
diff --git a/power-8994.c b/power-8994.c
new file mode 100644
index 0000000..ddde1d8
--- /dev/null
+++ b/power-8994.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int display_hint_sent;
+
+static int process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ /* Initialize encode metadata struct fields */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+ video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
+ -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return HINT_NONE;
+ }
+ } else {
+ return HINT_NONE;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /* sched and cpufreq params
+ * hispeed freq - 768 MHz
+ * target load - 90
+ * above_hispeed_delay - 40ms
+ * sched_small_tsk - 50
+ */
+ int resource_values[] = {0x2C07, 0x2F5A, 0x2704, 0x4032};
+
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ return HINT_HANDLED;
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
+{
+ int ret_val = HINT_NONE;
+ switch(hint) {
+ case POWER_HINT_VIDEO_ENCODE:
+ ret_val = process_video_encode_hint(data);
+ break;
+ default:
+ break;
+ }
+ return ret_val;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ return HINT_NONE; /* Don't excecute this code path, not in use */
+ char governor[80];
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ if (!on) {
+ /* Display off */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ int resource_values[] = {}; /* dummy node */
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ return HINT_HANDLED;
+ }
+ }
+ } else {
+ /* Display on */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
diff --git a/power-8996.c b/power-8996.c
new file mode 100644
index 0000000..0b1c362
--- /dev/null
+++ b/power-8996.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+pthread_mutex_t camera_hint_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int display_hint_sent;
+static int camera_hint_ref_count;
+
+static int process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ /* Initialize encode metadata struct fields */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+ video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
+ -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return HINT_NONE;
+ }
+ } else {
+ return HINT_NONE;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ /* 1. cpufreq params
+ * -above_hispeed_delay for LVT - 40ms
+ * -go hispeed load for LVT - 95
+ * -hispeed freq for LVT - 556 MHz
+ * -target load for LVT - 90
+ * -above hispeed delay for sLVT - 40ms
+ * -go hispeed load for sLVT - 95
+ * -hispeed freq for sLVT - 806 MHz
+ * -target load for sLVT - 90
+ * 2. bus DCVS set to V2 config:
+ * -low power ceil mpbs - 2500
+ * -low power io percent - 50
+ * 3. hysteresis optimization
+ * -bus dcvs hysteresis tuning
+ * -sample_ms of 10 ms
+ * -sLVT hispeed freq to 806MHz
+ */
+ int resource_values[] = {0x41400000, 0x4, 0x41410000, 0x5F, 0x41414000, 0x326,
+ 0x41420000, 0x5A, 0x41400100, 0x4, 0x41410100, 0x5F, 0x41414100, 0x22C, 0x41420100, 0x5A,
+ 0x41810000, 0x9C4, 0x41814000, 0x32, 0x4180C000, 0x0, 0x41820000, 0xA};
+
+ pthread_mutex_lock(&camera_hint_mutex);
+ camera_hint_ref_count++;
+ if (camera_hint_ref_count == 1) {
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ }
+ pthread_mutex_unlock(&camera_hint_mutex);
+ ALOGI("Video Encode hint start");
+ return HINT_HANDLED;
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ pthread_mutex_lock(&camera_hint_mutex);
+ camera_hint_ref_count--;
+ if (!camera_hint_ref_count) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ }
+ pthread_mutex_unlock(&camera_hint_mutex);
+
+ ALOGI("Video Encode hint stop");
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
+{
+ int ret_val = HINT_NONE;
+ switch(hint) {
+ case POWER_HINT_VIDEO_ENCODE:
+ ret_val = process_video_encode_hint(data);
+ break;
+ default:
+ break;
+ }
+ return ret_val;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ return HINT_HANDLED; /* Don't excecute this code path, not in use */
+ char governor[80];
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ if (!on) {
+ /* Display off */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ int resource_values[] = {}; /* dummy node */
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ ALOGI("Display Off hint start");
+ return HINT_HANDLED;
+ }
+ }
+ } else {
+ /* Display on */
+ if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ ALOGI("Display Off hint stop");
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
diff --git a/power-8998.c b/power-8998.c
new file mode 100644
index 0000000..e51991b
--- /dev/null
+++ b/power-8998.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+#include "powerhintparser.h"
+
+#define CHECK_HANDLE(x) ((x)>0)
+#define NUM_PERF_MODES 3
+
+typedef enum {
+ NORMAL_MODE = 0,
+ SUSTAINED_MODE = 1,
+ VR_MODE = 2,
+ VR_SUSTAINED_MODE = (SUSTAINED_MODE|VR_MODE),
+ INVALID_MODE = 0xFF
+}perf_mode_type_t;
+
+typedef struct perf_mode {
+ perf_mode_type_t type;
+ int perf_hint_id;
+}perf_mode_t;
+
+perf_mode_t perf_modes[NUM_PERF_MODES] = { { SUSTAINED_MODE, SUSTAINED_PERF_HINT },
+ { VR_MODE, VR_MODE_HINT },
+ { VR_SUSTAINED_MODE, VR_MODE_SUSTAINED_PERF_HINT } };
+
+static pthread_mutex_t perf_mode_switch_lock = PTHREAD_MUTEX_INITIALIZER;
+static int current_mode = NORMAL_MODE;
+
+static inline int get_perfd_hint_id(perf_mode_type_t type) {
+ int i;
+ for(i=0; i<NUM_PERF_MODES; i++) {
+ if (perf_modes[i].type == type) {
+ ALOGD("Hint id is 0x%x for mode 0x%x", perf_modes[i].perf_hint_id, type);
+ return perf_modes[i].perf_hint_id;
+ }
+ }
+ ALOGD("Couldn't find the hint for mode 0x%x", type);
+ return 0;
+}
+
+static int switch_mode(perf_mode_type_t mode) {
+
+ int hint_id = 0;
+ static int perfd_mode_handle = -1;
+
+ // release existing mode if any
+ if (CHECK_HANDLE(perfd_mode_handle)) {
+ ALOGD("Releasing handle 0x%x", perfd_mode_handle);
+ release_request(perfd_mode_handle);
+ perfd_mode_handle = -1;
+ }
+ // switch to a perf mode
+ hint_id = get_perfd_hint_id(mode);
+ if(hint_id != 0) {
+ perfd_mode_handle = perf_hint_enable(hint_id, 0);
+ if (!CHECK_HANDLE(perfd_mode_handle)) {
+ ALOGE("Failed perf_hint_interaction for mode: 0x%x", mode);
+ return -1;
+ }
+ ALOGD("Acquired handle 0x%x", perfd_mode_handle);
+ }
+ return 0;
+}
+
+static int process_perf_hint(void *data, perf_mode_type_t mode) {
+
+ pthread_mutex_lock(&perf_mode_switch_lock);
+
+ // enable
+ if (data){
+ ALOGI("Enable request for mode: 0x%x", mode);
+ // check if mode is current mode
+ if ( current_mode & mode ) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGD("Mode 0x%x already enabled", mode);
+ return HINT_HANDLED;
+ }
+ // enable requested mode
+ if ( 0 != switch_mode(current_mode | mode)) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGE("Couldn't enable mode 0x%x", mode);
+ return HINT_NONE;
+ }
+ current_mode |= mode;
+ ALOGI("Current mode is 0x%x", current_mode);
+ // disable
+ } else {
+ ALOGI("Disable request for mode: 0x%x", mode);
+ // check if mode is enabled
+ if ( !(current_mode & mode) ) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGD("Mode 0x%x already disabled", mode);
+ return HINT_HANDLED;
+ }
+ //disable requested mode
+ if ( 0 != switch_mode(current_mode & ~mode)) {
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ ALOGE("Couldn't disable mode 0x%x", mode);
+ return HINT_NONE;
+ }
+ current_mode &= ~mode;
+ ALOGI("Current mode is 0x%x", current_mode);
+ }
+
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ return HINT_HANDLED;
+}
+
+static int process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+ static int video_encode_handle = 0;
+
+ if(!metadata)
+ return HINT_NONE;
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return HINT_NONE;
+ }
+
+ /* Initialize encode metadata struct fields */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+
+ if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
+ -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return HINT_NONE;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if (is_interactive_governor(governor)) {
+ video_encode_handle = perf_hint_enable(
+ VIDEO_ENCODE_HINT, 0);
+ return HINT_HANDLED;
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if (is_interactive_governor(governor)) {
+ release_request(video_encode_handle);
+ ALOGI("Video Encode hint stop");
+ return HINT_HANDLED;
+ }
+ }
+ return HINT_NONE;
+}
+
+int power_hint_override(struct power_module *module, power_hint_t hint, void *data)
+{
+ int ret_val = HINT_NONE;
+ switch(hint) {
+ case POWER_HINT_VIDEO_ENCODE:
+ ret_val = process_video_encode_hint(data);
+ break;
+ case POWER_HINT_SUSTAINED_PERFORMANCE:
+ ret_val = process_perf_hint(data, SUSTAINED_MODE);
+ break;
+ case POWER_HINT_VR_MODE:
+ ret_val = process_perf_hint(data, VR_MODE);
+ break;
+ case POWER_HINT_INTERACTION:
+ pthread_mutex_lock(&perf_mode_switch_lock);
+ if (current_mode != NORMAL_MODE) {
+ ret_val = HINT_HANDLED;
+ }
+ pthread_mutex_unlock(&perf_mode_switch_lock);
+ break;
+ default:
+ break;
+ }
+ return ret_val;
+}
+
+int set_interactive_override(struct power_module *module, int on)
+{
+ return HINT_HANDLED; /* Don't excecute this code path, not in use */
+}
diff --git a/power-common.h b/power-common.h
new file mode 100644
index 0000000..5ba5e81
--- /dev/null
+++ b/power-common.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define NODE_MAX (64)
+
+#define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
+#define DCVS_CPU0_SLACK_MAX_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_max_us"
+#define DCVS_CPU0_SLACK_MIN_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_min_us"
+#define MPDECISION_SLACK_MAX_NODE "/sys/module/msm_mpdecision/slack_time_max_us"
+#define MPDECISION_SLACK_MIN_NODE "/sys/module/msm_mpdecision/slack_time_min_us"
+#define SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
+#define ONDEMAND_GOVERNOR "ondemand"
+#define INTERACTIVE_GOVERNOR "interactive"
+#define MSMDCVS_GOVERNOR "msm-dcvs"
+
+#define HINT_HANDLED (0)
+#define HINT_NONE (-1)
+
+enum CPU_GOV_CHECK {
+ CPU0 = 0,
+ CPU1 = 1,
+ CPU2 = 2,
+ CPU3 = 3
+};
diff --git a/power.c b/power.c
new file mode 100644
index 0000000..05a09ba
--- /dev/null
+++ b/power.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_NIDEBUG 0
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "utils.h"
+#include "metadata-defs.h"
+#include "hint-data.h"
+#include "performance.h"
+#include "power-common.h"
+
+static int saved_dcvs_cpu0_slack_max = -1;
+static int saved_dcvs_cpu0_slack_min = -1;
+static int saved_mpdecision_slack_max = -1;
+static int saved_mpdecision_slack_min = -1;
+static int saved_interactive_mode = -1;
+static int slack_node_rw_failed = 0;
+static int display_hint_sent;
+int display_boost;
+
+static int power_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device);
+
+static struct hw_module_methods_t power_module_methods = {
+ .open = power_device_open,
+};
+
+static void power_init(struct power_module *module)
+{
+ ALOGI("QTI power HAL initing.");
+
+ int fd;
+ char buf[10] = {0};
+
+ fd = open("/sys/devices/soc0/soc_id", O_RDONLY);
+ if (fd >= 0) {
+ if (read(fd, buf, sizeof(buf) - 1) == -1) {
+ ALOGW("Unable to read soc_id");
+ } else {
+ int soc_id = atoi(buf);
+ if (soc_id == 194 || (soc_id >= 208 && soc_id <= 218) || soc_id == 178) {
+ display_boost = 1;
+ }
+ }
+ close(fd);
+ }
+}
+
+static void process_video_decode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_decode_metadata_t video_decode_metadata;
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return;
+ }
+
+ if (metadata) {
+ ALOGI("Processing video decode hint. Metadata: %s", (char *)metadata);
+ }
+
+ /* Initialize encode metadata struct fields. */
+ memset(&video_decode_metadata, 0, sizeof(struct video_decode_metadata_t));
+ video_decode_metadata.state = -1;
+ video_decode_metadata.hint_id = DEFAULT_VIDEO_DECODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_decode_metadata((char *)metadata, &video_decode_metadata) ==
+ -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if (video_decode_metadata.state == 1) {
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ int resource_values[] = {THREAD_MIGRATION_SYNC_OFF};
+
+ perform_hint_action(video_decode_metadata.hint_id,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF};
+
+ perform_hint_action(video_decode_metadata.hint_id,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ }
+ } else if (video_decode_metadata.state == 0) {
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(video_decode_metadata.hint_id);
+ }
+ }
+}
+
+static void process_video_encode_hint(void *metadata)
+{
+ char governor[80];
+ struct video_encode_metadata_t video_encode_metadata;
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return;
+ }
+
+ /* Initialize encode metadata struct fields. */
+ memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t));
+ video_encode_metadata.state = -1;
+ video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID;
+
+ if (metadata) {
+ if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) ==
+ -1) {
+ ALOGE("Error occurred while parsing metadata.");
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if (video_encode_metadata.state == 1) {
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ int resource_values[] = {IO_BUSY_OFF, SAMPLING_DOWN_FACTOR_1, THREAD_MIGRATION_SYNC_OFF};
+
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF,
+ INTERACTIVE_IO_BUSY_OFF};
+
+ perform_hint_action(video_encode_metadata.hint_id,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ }
+ } else if (video_encode_metadata.state == 0) {
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(video_encode_metadata.hint_id);
+ }
+ }
+}
+
+int __attribute__ ((weak)) power_hint_override(struct power_module *module, power_hint_t hint,
+ void *data)
+{
+ return HINT_NONE;
+}
+
+/* Declare function before use */
+void interaction(int duration, int num_args, int opt_list[]);
+
+static void power_hint(struct power_module *module, power_hint_t hint,
+ void *data)
+{
+ /* Check if this hint has been overridden. */
+ if (power_hint_override(module, hint, data) == HINT_HANDLED) {
+ /* The power_hint has been handled. We can skip the rest. */
+ return;
+ }
+
+ switch(hint) {
+ case POWER_HINT_VSYNC:
+ break;
+ case POWER_HINT_SUSTAINED_PERFORMANCE:
+ ALOGI("Sustained perf power hint not handled in power_hint_override");
+ break;
+ case POWER_HINT_VR_MODE:
+ ALOGI("VR mode power hint not handled in power_hint_override");
+ break;
+ case POWER_HINT_INTERACTION:
+ {
+ int resources[] = {0x702, 0x20F, 0x30F};
+ int duration = 3000;
+
+ interaction(duration, sizeof(resources)/sizeof(resources[0]), resources);
+ }
+ break;
+ case POWER_HINT_VIDEO_ENCODE:
+ process_video_encode_hint(data);
+ break;
+ case POWER_HINT_VIDEO_DECODE:
+ process_video_decode_hint(data);
+ break;
+ }
+}
+
+int __attribute__ ((weak)) set_interactive_override(struct power_module *module, int on)
+{
+ return HINT_NONE;
+}
+
+void set_interactive(struct power_module *module, int on)
+{
+ char governor[80];
+ char tmp_str[NODE_MAX];
+ struct video_encode_metadata_t video_encode_metadata;
+ int rc = 0;
+
+ if (!on) {
+ /* Send Display OFF hint to perf HAL */
+ perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0);
+ } else {
+ /* Send Display ON hint to perf HAL */
+ perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0);
+ }
+
+ if (set_interactive_override(module, on) == HINT_HANDLED) {
+ return;
+ }
+
+ ALOGI("Got set_interactive hint");
+
+ if (get_scaling_governor(governor, sizeof(governor)) == -1) {
+ ALOGE("Can't obtain scaling governor.");
+
+ return;
+ }
+
+ if (!on) {
+ /* Display off. */
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ int resource_values[] = {DISPLAY_OFF, MS_500, THREAD_MIGRATION_SYNC_OFF};
+
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ }
+ } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF};
+
+ if (!display_hint_sent) {
+ perform_hint_action(DISPLAY_STATE_HINT_ID,
+ resource_values, sizeof(resource_values)/sizeof(resource_values[0]));
+ display_hint_sent = 1;
+ }
+ } else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(MSMDCVS_GOVERNOR))) {
+ if (saved_interactive_mode == 1){
+ /* Display turned off. */
+ if (sysfs_read(DCVS_CPU0_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MAX_NODE);
+ }
+
+ rc = 1;
+ } else {
+ saved_dcvs_cpu0_slack_max = atoi(tmp_str);
+ }
+
+ if (sysfs_read(DCVS_CPU0_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MIN_NODE);
+ }
+
+ rc = 1;
+ } else {
+ saved_dcvs_cpu0_slack_min = atoi(tmp_str);
+ }
+
+ if (sysfs_read(MPDECISION_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to read from %s", MPDECISION_SLACK_MAX_NODE);
+ }
+
+ rc = 1;
+ } else {
+ saved_mpdecision_slack_max = atoi(tmp_str);
+ }
+
+ if (sysfs_read(MPDECISION_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) {
+ if(!slack_node_rw_failed) {
+ ALOGE("Failed to read from %s", MPDECISION_SLACK_MIN_NODE);
+ }
+
+ rc = 1;
+ } else {
+ saved_mpdecision_slack_min = atoi(tmp_str);
+ }
+
+ /* Write new values. */
+ if (saved_dcvs_cpu0_slack_max != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_max);
+
+ if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+
+ if (saved_dcvs_cpu0_slack_min != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_min);
+
+ if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) {
+ if(!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+
+ if (saved_mpdecision_slack_max != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_max);
+
+ if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) {
+ if(!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+
+ if (saved_mpdecision_slack_min != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_min);
+
+ if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) {
+ if(!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+ }
+
+ slack_node_rw_failed = rc;
+ }
+ } else {
+ /* Display on. */
+ if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) {
+ undo_hint_action(DISPLAY_STATE_HINT_ID);
+ display_hint_sent = 0;
+ } else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) &&
+ (strlen(governor) == strlen(MSMDCVS_GOVERNOR))) {
+ if (saved_interactive_mode == -1 || saved_interactive_mode == 0) {
+ /* Display turned on. Restore if possible. */
+ if (saved_dcvs_cpu0_slack_max != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_max);
+
+ if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+
+ if (saved_dcvs_cpu0_slack_min != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_min);
+
+ if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+
+ if (saved_mpdecision_slack_max != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_max);
+
+ if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+
+ if (saved_mpdecision_slack_min != -1) {
+ snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_min);
+
+ if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) {
+ if (!slack_node_rw_failed) {
+ ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE);
+ }
+
+ rc = 1;
+ }
+ }
+ }
+
+ slack_node_rw_failed = rc;
+ }
+ }
+
+ saved_interactive_mode = !!on;
+}
+
+static int power_device_open(const hw_module_t* module, const char* name,
+ hw_device_t** device)
+{
+ int status = -EINVAL;
+ if (module && name && device) {
+ if (!strcmp(name, POWER_HARDWARE_MODULE_ID)) {
+ power_module_t *dev = (power_module_t *)malloc(sizeof(*dev));
+
+ if(dev) {
+ memset(dev, 0, sizeof(*dev));
+
+ if(dev) {
+ /* initialize the fields */
+ dev->common.module_api_version = POWER_MODULE_API_VERSION_0_2;
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->init = power_init;
+ dev->powerHint = power_hint;
+ dev->setInteractive = set_interactive;
+ /* At the moment we support 0.2 APIs */
+ dev->setFeature = NULL,
+ dev->get_number_of_platform_modes = NULL,
+ dev->get_platform_low_power_stats = NULL,
+ dev->get_voter_list = NULL,
+ *device = (hw_device_t*)dev;
+ status = 0;
+ } else {
+ status = -ENOMEM;
+ }
+ }
+ else {
+ status = -ENOMEM;
+ }
+ }
+ }
+
+ return status;
+}
+
+struct power_module HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = POWER_MODULE_API_VERSION_0_2,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = POWER_HARDWARE_MODULE_ID,
+ .name = "QTI Power HAL",
+ .author = "QTI",
+ .methods = &power_module_methods,
+ },
+
+ .init = power_init,
+ .powerHint = power_hint,
+ .setInteractive = set_interactive,
+};
diff --git a/powerhintparser.c b/powerhintparser.c
new file mode 100644
index 0000000..7dd5be2
--- /dev/null
+++ b/powerhintparser.c
@@ -0,0 +1,178 @@
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <cutils/log.h>
+#include <fcntl.h>
+#include <string.h>
+#include <cutils/properties.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include "powerhintparser.h"
+#define LOG_TAG "QTI PowerHAL"
+
+int parsePowerhintXML() {
+
+ xmlDocPtr doc;
+ xmlNodePtr currNode;
+ const char *opcode_str, *value_str, *type_str;
+ int opcode = 0, value = 0, type = 0;
+ int numParams = 0;
+ static int hintCount;
+
+ if(access(POWERHINT_XML, F_OK) < 0) {
+ return -1;
+ }
+
+ doc = xmlReadFile(POWERHINT_XML, "UTF-8", XML_PARSE_RECOVER);
+ if(!doc) {
+ ALOGE("Document not parsed successfully");
+ return -1;
+ }
+
+ currNode = xmlDocGetRootElement(doc);
+ if(!currNode) {
+ ALOGE("Empty document");
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return -1;
+ }
+
+ // Confirm the root-element of the tree
+ if(xmlStrcmp(currNode->name, BAD_CAST "Powerhint")) {
+ ALOGE("document of the wrong type, root node != root");
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return -1;
+ }
+
+ currNode = currNode->xmlChildrenNode;
+
+ for(; currNode != NULL; currNode=currNode->next) {
+
+ if(currNode->type != XML_ELEMENT_NODE)
+ continue;
+
+ xmlNodePtr node = currNode;
+
+ if(hintCount == MAX_HINT) {
+ ALOGE("Number of hints exceeded the max count of %d\n",MAX_HINT);
+ break;
+ }
+
+ if(!xmlStrcmp(node->name, BAD_CAST "Hint")) {
+ if(xmlHasProp(node, BAD_CAST "type")) {
+ type_str = (const char*)xmlGetProp(node, BAD_CAST "type");
+ if (type_str == NULL)
+ {
+ ALOGE("xmlGetProp failed on type");
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return -1;
+ }
+ type = strtol(type_str, NULL, 16);
+ }
+
+ node = node->children;
+ while(node != NULL) {
+ if(!xmlStrcmp(node->name, BAD_CAST "Resource")) {
+
+ if(xmlHasProp(node, BAD_CAST "opcode")) {
+ opcode_str = (const char*)xmlGetProp(node, BAD_CAST "opcode");
+ if (opcode_str == NULL)
+ {
+ ALOGE("xmlGetProp failed on opcode");
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return -1;
+ }
+ opcode = strtol(opcode_str, NULL, 16);
+ }
+ if(xmlHasProp(node, BAD_CAST "value")) {
+ value_str = (const char*)xmlGetProp(node, BAD_CAST "value");
+ if (value_str == NULL)
+ {
+ ALOGE("xmlGetProp failed on value");
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return -1;
+ }
+ value = strtol(value_str, NULL, 16);
+ }
+ if(opcode > 0) {
+ if(numParams < (MAX_PARAM-1)) {
+ powerhint[hintCount].paramList[numParams++] = opcode;
+ powerhint[hintCount].paramList[numParams++] = value;
+ } else {
+ ALOGE("Maximum parameters exceeded for Hint ID %x\n",type);
+ opcode = value = 0;
+ break;
+ }
+ }
+
+ opcode = value = 0;
+ }
+ node = node->next;
+ }
+ powerhint[hintCount].type = type;
+ powerhint[hintCount].numParams = numParams;
+ numParams = 0;
+ }
+ hintCount++;
+ }
+
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return 0;
+}
+
+int* getPowerhint(int hint_id, int *params) {
+
+ int *result = NULL;
+
+ if(!hint_id)
+ return result;
+
+ ALOGI("Powerhal hint received=%x\n",hint_id);
+
+ if(!powerhint[0].numParams) {
+ parsePowerhintXML();
+ }
+
+ for(int i = 0; i < MAX_HINT; i++) {
+ if(hint_id == powerhint[i].type) {
+ *params = powerhint[i].numParams;
+ result = powerhint[i].paramList;
+ break;
+ }
+ }
+
+ /*for (int j = 0; j < *params; j++)
+ ALOGI("Powerhal resource again%x = \n", result[j]);*/
+
+ return result;
+}
diff --git a/powerhintparser.h b/powerhintparser.h
new file mode 100644
index 0000000..5f9cbe6
--- /dev/null
+++ b/powerhintparser.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __POWERHINTPARSER__
+#define __POWERHINTPARSER__
+
+#define POWERHINT_XML "/vendor/etc/powerhint.xml"
+#define MAX_HINT 6
+#define MAX_PARAM 30
+
+typedef struct perflock_param_t {
+ int type;
+ int numParams;
+ int paramList[MAX_PARAM];//static limit on number of hints - 15
+}perflock_param_t;
+
+static perflock_param_t powerhint[MAX_HINT];
+
+int parsePowerhintXML();
+int *getPowerhint(int, int*);
+
+#endif /* __POWERHINTPARSER__ */
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..e1e436c
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2012-2013,2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_NIDEBUG 0
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+#include "list.h"
+#include "hint-data.h"
+#include "power-common.h"
+
+#define LOG_TAG "QTI PowerHAL"
+#include <utils/Log.h>
+
+char scaling_gov_path[4][80] ={
+ "sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
+ "sys/devices/system/cpu/cpu1/cpufreq/scaling_governor",
+ "sys/devices/system/cpu/cpu2/cpufreq/scaling_governor",
+ "sys/devices/system/cpu/cpu3/cpufreq/scaling_governor"
+};
+
+#define PERF_HAL_PATH "libqti-perfd-client.so"
+static void *qcopt_handle;
+static int (*perf_lock_acq)(unsigned long handle, int duration,
+ int list[], int numArgs);
+static int (*perf_lock_rel)(unsigned long handle);
+static int (*perf_hint)(int, char *, int, int);
+static struct list_node active_hint_list_head;
+
+static void *get_qcopt_handle()
+{
+ void *handle = NULL;
+
+ dlerror();
+
+ handle = dlopen(PERF_HAL_PATH, RTLD_NOW);
+ if (!handle) {
+ ALOGE("Unable to open %s: %s\n", PERF_HAL_PATH,
+ dlerror());
+ }
+
+ return handle;
+}
+
+static void __attribute__ ((constructor)) initialize(void)
+{
+ qcopt_handle = get_qcopt_handle();
+
+ if (!qcopt_handle) {
+ ALOGE("Failed to get qcopt handle.\n");
+ } else {
+ /*
+ * qc-opt handle obtained. Get the perflock acquire/release
+ * function pointers.
+ */
+ perf_lock_acq = dlsym(qcopt_handle, "perf_lock_acq");
+
+ if (!perf_lock_acq) {
+ ALOGE("Unable to get perf_lock_acq function handle.\n");
+ }
+
+ perf_lock_rel = dlsym(qcopt_handle, "perf_lock_rel");
+
+ if (!perf_lock_rel) {
+ ALOGE("Unable to get perf_lock_rel function handle.\n");
+ }
+
+ perf_hint = dlsym(qcopt_handle, "perf_hint");
+
+ if (!perf_hint) {
+ ALOGE("Unable to get perf_hint function handle.\n");
+ }
+ }
+}
+
+static void __attribute__ ((destructor)) cleanup(void)
+{
+ if (qcopt_handle) {
+ if (dlclose(qcopt_handle))
+ ALOGE("Error occurred while closing qc-opt library.");
+ }
+}
+
+int sysfs_read(char *path, char *s, int num_bytes)
+{
+ char buf[80];
+ int count;
+ int ret = 0;
+ int fd = open(path, O_RDONLY);
+
+ if (fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", path, buf);
+
+ return -1;
+ }
+
+ if ((count = read(fd, s, num_bytes - 1)) < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", path, buf);
+
+ ret = -1;
+ } else {
+ s[count] = '\0';
+ }
+
+ close(fd);
+
+ return ret;
+}
+
+int sysfs_write(char *path, char *s)
+{
+ char buf[80];
+ int len;
+ int ret = 0;
+ int fd = open(path, O_WRONLY);
+
+ if (fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", path, buf);
+ return -1 ;
+ }
+
+ len = write(fd, s, strlen(s));
+ if (len < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", path, buf);
+
+ ret = -1;
+ }
+
+ close(fd);
+
+ return ret;
+}
+
+int get_scaling_governor(char governor[], int size)
+{
+ if (sysfs_read(SCALING_GOVERNOR_PATH, governor,
+ size) == -1) {
+ // Can't obtain the scaling governor. Return.
+ return -1;
+ } else {
+ // Strip newline at the end.
+ int len = strlen(governor);
+
+ len--;
+
+ while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r'))
+ governor[len--] = '\0';
+ }
+
+ return 0;
+}
+
+int get_scaling_governor_check_cores(char governor[], int size,int core_num)
+{
+
+ if (sysfs_read(scaling_gov_path[core_num], governor,
+ size) == -1) {
+ // Can't obtain the scaling governor. Return.
+ return -1;
+ }
+
+ // Strip newline at the end.
+ int len = strlen(governor);
+ len--;
+ while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r'))
+ governor[len--] = '\0';
+
+ return 0;
+}
+
+int is_interactive_governor(char* governor) {
+ if (strncmp(governor, INTERACTIVE_GOVERNOR, (strlen(INTERACTIVE_GOVERNOR)+1)) == 0)
+ return 1;
+ return 0;
+}
+
+void interaction(int duration, int num_args, int opt_list[])
+{
+#ifdef INTERACTION_BOOST
+ static int lock_handle = 0;
+
+ if (duration < 0 || num_args < 1 || opt_list[0] == NULL)
+ return;
+
+ if (qcopt_handle) {
+ if (perf_lock_acq) {
+ lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args);
+ if (lock_handle == -1)
+ ALOGE("Failed to acquire lock.");
+ }
+ }
+#endif
+}
+
+int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[])
+{
+ if (duration < 0 || num_args < 1 || opt_list[0] == NULL)
+ return 0;
+
+ if (qcopt_handle) {
+ if (perf_lock_acq) {
+ lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args);
+ if (lock_handle == -1)
+ ALOGE("Failed to acquire lock.");
+ }
+ }
+ return lock_handle;
+}
+
+//this is interaction_with_handle using perf_hint instead of
+//perf_lock_acq
+int perf_hint_enable(int hint_id , int duration)
+{
+ int lock_handle = 0;
+
+ if (duration < 0)
+ return 0;
+
+ if (qcopt_handle) {
+ if (perf_hint) {
+ lock_handle = perf_hint(hint_id, NULL, duration, -1);
+ if (lock_handle == -1)
+ ALOGE("Failed to acquire lock.");
+ }
+ }
+ return lock_handle;
+}
+
+
+void release_request(int lock_handle) {
+ if (qcopt_handle && perf_lock_rel)
+ perf_lock_rel(lock_handle);
+}
+
+void perform_hint_action(int hint_id, int resource_values[], int num_resources)
+{
+ if (qcopt_handle) {
+ if (perf_lock_acq) {
+ /* Acquire an indefinite lock for the requested resources. */
+ int lock_handle = perf_lock_acq(0, 0, resource_values,
+ num_resources);
+
+ if (lock_handle == -1) {
+ ALOGE("Failed to acquire lock.");
+ } else {
+ /* Add this handle to our internal hint-list. */
+ struct hint_data *new_hint =
+ (struct hint_data *)malloc(sizeof(struct hint_data));
+
+ if (new_hint) {
+ if (!active_hint_list_head.compare) {
+ active_hint_list_head.compare =
+ (int (*)(void *, void *))hint_compare;
+ active_hint_list_head.dump = (void (*)(void *))hint_dump;
+ }
+
+ new_hint->hint_id = hint_id;
+ new_hint->perflock_handle = lock_handle;
+
+ if (add_list_node(&active_hint_list_head, new_hint) == NULL) {
+ free(new_hint);
+ /* Can't keep track of this lock. Release it. */
+ if (perf_lock_rel)
+ perf_lock_rel(lock_handle);
+
+ ALOGE("Failed to process hint.");
+ }
+ } else {
+ /* Can't keep track of this lock. Release it. */
+ if (perf_lock_rel)
+ perf_lock_rel(lock_handle);
+
+ ALOGE("Failed to process hint.");
+ }
+ }
+ }
+ }
+}
+
+void undo_hint_action(int hint_id)
+{
+ if (qcopt_handle) {
+ if (perf_lock_rel) {
+ /* Get hint-data associated with this hint-id */
+ struct list_node *found_node;
+ struct hint_data temp_hint_data = {
+ .hint_id = hint_id
+ };
+
+ found_node = find_node(&active_hint_list_head,
+ &temp_hint_data);
+
+ if (found_node) {
+ /* Release this lock. */
+ struct hint_data *found_hint_data =
+ (struct hint_data *)(found_node->data);
+
+ if (found_hint_data) {
+ if (perf_lock_rel(found_hint_data->perflock_handle) == -1)
+ ALOGE("Perflock release failed.");
+ }
+
+ if (found_node->data) {
+ /* We can free the hint-data for this node. */
+ free(found_node->data);
+ }
+
+ remove_list_node(&active_hint_list_head, found_node);
+ } else {
+ ALOGE("Invalid hint ID.");
+ }
+ }
+ }
+}
+
+/*
+ * Used to release initial lock holding
+ * two cores online when the display is on
+ */
+void undo_initial_hint_action()
+{
+ if (qcopt_handle) {
+ if (perf_lock_rel) {
+ perf_lock_rel(1);
+ }
+ }
+}
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..4c3dc7f
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012-2013,2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cutils/properties.h>
+
+int sysfs_read(char *path, char *s, int num_bytes);
+int sysfs_write(char *path, char *s);
+int get_scaling_governor(char governor[], int size);
+int get_scaling_governor_check_cores(char governor[], int size,int core_num);
+int is_interactive_governor(char*);
+
+void vote_ondemand_io_busy_off();
+void unvote_ondemand_io_busy_off();
+void vote_ondemand_sdf_low();
+void unvote_ondemand_sdf_low();
+void perform_hint_action(int hint_id, int resource_values[],
+ int num_resources);
+void undo_hint_action(int hint_id);
+void release_request(int lock_handle);
+int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]);
+int perf_hint_enable(int hint_id, int duration);