From ee7c4c58319f0d081f5a684a97faa33b8614206f Mon Sep 17 00:00:00 2001 From: David Ng Date: Thu, 22 Mar 2018 23:49:12 -0700 Subject: 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 --- Android.mk | 76 ++++++++ NOTICE | 32 ++++ hint-data.c | 47 +++++ hint-data.h | 62 +++++++ list.c | 145 ++++++++++++++++ list.h | 41 +++++ metadata-defs.h | 54 ++++++ metadata-parser.c | 133 ++++++++++++++ performance.h | 265 ++++++++++++++++++++++++++++ power-660.c | 291 +++++++++++++++++++++++++++++++ power-8084.c | 114 ++++++++++++ power-8226.c | 65 +++++++ power-845.c | 272 +++++++++++++++++++++++++++++ power-8610.c | 65 +++++++ power-8952.c | 195 +++++++++++++++++++++ power-8953.c | 202 ++++++++++++++++++++++ power-8974.c | 114 ++++++++++++ power-8994.c | 149 ++++++++++++++++ power-8996.c | 179 +++++++++++++++++++ power-8998.c | 224 ++++++++++++++++++++++++ power-common.h | 49 ++++++ power.c | 508 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ powerhintparser.c | 178 +++++++++++++++++++ powerhintparser.h | 48 ++++++ utils.c | 361 ++++++++++++++++++++++++++++++++++++++ utils.h | 47 +++++ 26 files changed, 3916 insertions(+) create mode 100644 Android.mk create mode 100644 NOTICE create mode 100644 hint-data.c create mode 100644 hint-data.h create mode 100644 list.c create mode 100644 list.h create mode 100644 metadata-defs.h create mode 100644 metadata-parser.c create mode 100644 performance.h create mode 100644 power-660.c create mode 100644 power-8084.c create mode 100644 power-8226.c create mode 100644 power-845.c create mode 100644 power-8610.c create mode 100644 power-8952.c create mode 100644 power-8953.c create mode 100644 power-8974.c create mode 100644 power-8994.c create mode 100644 power-8996.c create mode 100644 power-8998.c create mode 100644 power-common.h create mode 100644 power.c create mode 100644 powerhintparser.c create mode 100644 powerhintparser.h create mode 100644 utils.c create mode 100644 utils.h 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/..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 +#include +#include + +#include "list.h" +#include + +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 +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include + +#include "utils.h" +#include "list.h" +#include "hint-data.h" +#include "power-common.h" + +#define LOG_TAG "QTI PowerHAL" +#include + +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 + +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); -- cgit v1.2.3