├── Android.mk ├── README.md └── power ├── Android.mk ├── hint-data.c ├── hint-data.h ├── list.c ├── list.h ├── metadata-defs.h ├── metadata-parser.c ├── performance.h ├── power-8084.c ├── power-8226.c ├── power-8610.c ├── power-8909.c ├── power-8916.c ├── power-8937.c ├── power-8952.c ├── power-8960.c ├── power-8974.c ├── power-8992.c ├── power-8994.c ├── power-8996.c ├── power-8998.c ├── power-common.h ├── power-feature-default.c ├── power-feature.h ├── power.c ├── utils.c └── utils.h /Android.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2014 The CyanogenMod Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM))) 17 | 18 | include $(all-subdir-makefiles) 19 | 20 | endif 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Generic common qcom configuration tools 2 | =============================== 3 | 4 | Copyright 2014 - The CyanogenMod Project 5 | -------------------------------------------------------------------------------- /power/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | # Hey Mr. Make Author, DIAF PLX 4 | ifeq ($(TARGET_POWERHAL_VARIANT),qcom) 5 | USE_ME := true 6 | endif 7 | 8 | ifneq (,$(filter true,$(USE_ME) $(WITH_QC_PERF))) 9 | 10 | # HAL module implemenation stored in 11 | # hw/..so 12 | include $(CLEAR_VARS) 13 | 14 | LOCAL_MODULE_RELATIVE_PATH := hw 15 | LOCAL_PROPRIETARY_MODULE := true 16 | LOCAL_SHARED_LIBRARIES := liblog libcutils libdl 17 | LOCAL_SRC_FILES := power.c metadata-parser.c utils.c list.c hint-data.c 18 | 19 | ifneq ($(BOARD_POWER_CUSTOM_BOARD_LIB),) 20 | LOCAL_WHOLE_STATIC_LIBRARIES += $(BOARD_POWER_CUSTOM_BOARD_LIB) 21 | else 22 | 23 | # Include target-specific files. 24 | ifeq ($(call is-board-platform-in-list, msm8974), true) 25 | LOCAL_SRC_FILES += power-8974.c 26 | endif 27 | 28 | ifeq ($(call is-board-platform-in-list, msm8960), true) 29 | LOCAL_SRC_FILES += power-8960.c 30 | endif 31 | 32 | ifeq ($(call is-board-platform-in-list, msm8226), true) 33 | LOCAL_SRC_FILES += power-8226.c 34 | endif 35 | 36 | ifeq ($(call is-board-platform-in-list, msm8610), true) 37 | LOCAL_SRC_FILES += power-8610.c 38 | endif 39 | 40 | ifeq ($(call is-board-platform-in-list, msm8909), true) 41 | LOCAL_SRC_FILES += power-8909.c 42 | endif 43 | 44 | ifeq ($(call is-board-platform-in-list, msm8916), true) 45 | LOCAL_SRC_FILES += power-8916.c 46 | endif 47 | 48 | ifeq ($(call is-board-platform-in-list, msm8952), true) 49 | LOCAL_SRC_FILES += power-8952.c 50 | endif 51 | 52 | ifeq ($(call is-board-platform-in-list, msm8937 msm8953), true) 53 | LOCAL_SRC_FILES += power-8937.c 54 | LOCAL_CFLAGS += -DMPCTLV3 55 | endif 56 | 57 | ifeq ($(call is-board-platform-in-list, apq8084), true) 58 | LOCAL_SRC_FILES += power-8084.c 59 | endif 60 | 61 | ifeq ($(call is-board-platform-in-list, msm8992), true) 62 | LOCAL_SRC_FILES += power-8992.c 63 | endif 64 | 65 | ifeq ($(call is-board-platform-in-list, msm8994), true) 66 | LOCAL_SRC_FILES += power-8994.c 67 | endif 68 | 69 | ifeq ($(call is-board-platform-in-list, msm8996), true) 70 | LOCAL_SRC_FILES += power-8996.c 71 | LOCAL_CFLAGS += -DMPCTLV3 72 | endif 73 | 74 | ifeq ($(call is-board-platform-in-list, msm8998), true) 75 | LOCAL_SRC_FILES += power-8998.c 76 | LOCAL_CFLAGS += -DMPCTLV3 77 | endif 78 | 79 | endif # End of board specific list 80 | 81 | ifneq ($(TARGET_POWERHAL_SET_INTERACTIVE_EXT),) 82 | LOCAL_CFLAGS += -DSET_INTERACTIVE_EXT 83 | LOCAL_SRC_FILES += ../../../../$(TARGET_POWERHAL_SET_INTERACTIVE_EXT) 84 | endif 85 | 86 | ifneq ($(TARGET_TAP_TO_WAKE_NODE),) 87 | LOCAL_CFLAGS += -DTAP_TO_WAKE_NODE=\"$(TARGET_TAP_TO_WAKE_NODE)\" 88 | endif 89 | 90 | ifeq ($(TARGET_POWER_SET_FEATURE_LIB),) 91 | LOCAL_SRC_FILES += power-feature-default.c 92 | else 93 | LOCAL_STATIC_LIBRARIES += $(TARGET_POWER_SET_FEATURE_LIB) 94 | endif 95 | 96 | ifneq ($(CM_POWERHAL_EXTENSION),) 97 | LOCAL_MODULE := power.$(CM_POWERHAL_EXTENSION) 98 | else 99 | LOCAL_MODULE := power.$(TARGET_BOARD_PLATFORM) 100 | endif 101 | LOCAL_MODULE_TAGS := optional 102 | include $(BUILD_SHARED_LIBRARY) 103 | 104 | endif # TARGET_POWERHAL_VARIANT == qcom || WITH_QC_PERF 105 | -------------------------------------------------------------------------------- /power/hint-data.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include "hint-data.h" 31 | 32 | int hint_compare(struct hint_data *first_hint, 33 | struct hint_data *other_hint) { 34 | if (first_hint == other_hint) { 35 | return 0; 36 | } else if ((first_hint && other_hint) && 37 | (first_hint->hint_id == other_hint->hint_id)) { 38 | return 0; 39 | } else { 40 | return 1; 41 | } 42 | } 43 | 44 | void hint_dump(__attribute__((unused)) struct hint_data *hint) 45 | { 46 | /*ALOGI("hint_id: %lu", hint->hint_id);*/ 47 | } 48 | -------------------------------------------------------------------------------- /power/hint-data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /* Default use-case hint IDs */ 31 | #define DEFAULT_VIDEO_ENCODE_HINT_ID (0x0A00) 32 | #define DEFAULT_VIDEO_DECODE_HINT_ID (0x0B00) 33 | #define DISPLAY_STATE_HINT_ID (0x0C00) 34 | #define DISPLAY_STATE_HINT_ID_2 (0x0D00) 35 | #define DEFAULT_AUDIO_HINT_ID (0x0E00) 36 | #define DEFAULT_PROFILE_HINT_ID (0x0F00) 37 | #define CAM_PREVIEW_HINT_ID (0x1000) 38 | 39 | struct hint_data { 40 | unsigned long hint_id; /* This is our key. */ 41 | unsigned long perflock_handle; 42 | }; 43 | 44 | int hint_compare(struct hint_data *first_hint, 45 | struct hint_data *other_hint); 46 | void hint_dump(struct hint_data *hint); 47 | -------------------------------------------------------------------------------- /power/list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include "list.h" 35 | #include 36 | 37 | int init_list_head(struct list_node *head) 38 | { 39 | if (head == NULL) 40 | return -1; 41 | 42 | memset(head, 0, sizeof(*head)); 43 | 44 | return 0; 45 | } 46 | 47 | struct list_node *add_list_node(struct list_node *head, void *data) 48 | { 49 | /* Create a new list_node. And put 'data' into it. */ 50 | struct list_node *new_node; 51 | 52 | if (head == NULL) { 53 | return NULL; 54 | } 55 | 56 | if (!(new_node = malloc(sizeof(struct list_node)))) { 57 | return NULL; 58 | } 59 | 60 | new_node->data = data; 61 | new_node->next = head->next; 62 | new_node->compare = head->compare; 63 | new_node->dump = head->dump; 64 | head->next = new_node; 65 | 66 | return new_node; 67 | } 68 | 69 | int is_list_empty(struct list_node *head) 70 | { 71 | return (head == NULL || head->next == NULL); 72 | } 73 | 74 | /* 75 | * Delink and de-allocate 'node'. 76 | */ 77 | int remove_list_node(struct list_node *head, struct list_node *del_node) 78 | { 79 | struct list_node *current_node; 80 | struct list_node *saved_node; 81 | 82 | if (head == NULL || head->next == NULL) { 83 | return -1; 84 | } 85 | 86 | current_node = head->next; 87 | saved_node = head; 88 | 89 | while (current_node && current_node != del_node) { 90 | saved_node = current_node; 91 | current_node = current_node->next; 92 | } 93 | 94 | if (saved_node) { 95 | if (current_node) { 96 | saved_node->next = current_node->next; 97 | } else { 98 | /* Node not found. */ 99 | return -1; 100 | } 101 | } 102 | 103 | if (del_node) { 104 | free(del_node); 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | void dump_list(struct list_node *head) 111 | { 112 | struct list_node *current_node = head; 113 | 114 | if (head == NULL) 115 | return; 116 | 117 | printf("List:\n"); 118 | 119 | while ((current_node = current_node->next)) { 120 | if (current_node->dump) { 121 | current_node->dump(current_node->data); 122 | } 123 | } 124 | } 125 | 126 | struct list_node *find_node(struct list_node *head, void *comparison_data) 127 | { 128 | struct list_node *current_node = head; 129 | 130 | if (head == NULL) 131 | return NULL; 132 | 133 | while ((current_node = current_node->next)) { 134 | if (current_node->compare) { 135 | if (current_node->compare(current_node->data, 136 | comparison_data) == 0) { 137 | /* Match found. Return current_node. */ 138 | return current_node; 139 | } 140 | } 141 | } 142 | 143 | /* No match found. */ 144 | return NULL; 145 | } 146 | -------------------------------------------------------------------------------- /power/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | struct list_node { 31 | struct list_node *next; 32 | void *data; 33 | int (*compare)(void *data1, void *data2); 34 | void (*dump)(void *data); 35 | }; 36 | 37 | int init_list_head(struct list_node *head); 38 | struct list_node * add_list_node(struct list_node *head, void *data); 39 | int remove_list_node(struct list_node *head, struct list_node *del_node); 40 | void dump_list(struct list_node *head); 41 | struct list_node *find_node(struct list_node *head, void *comparison_data); 42 | -------------------------------------------------------------------------------- /power/metadata-defs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, The Linux Foundation. All rights reserved. 2 | * 3 | * Redistribution and use in source and binary forms, with or without 4 | * modification, are permitted provided that the following conditions are 5 | * met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above 9 | * copyright notice, this list of conditions and the following 10 | * disclaimer in the documentation and/or other materials provided 11 | * with the distribution. 12 | * * Neither the name of The Linux Foundation nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | */ 29 | 30 | #define ATTRIBUTE_VALUE_DELIM ('=') 31 | #define ATTRIBUTE_STRING_DELIM (";") 32 | 33 | #define METADATA_PARSING_ERR (-1) 34 | #define METADATA_PARSING_CONTINUE (0) 35 | #define METADATA_PARSING_DONE (1) 36 | 37 | #define MIN(x,y) (((x)>(y))?(y):(x)) 38 | 39 | struct video_encode_metadata_t { 40 | int hint_id; 41 | int state; 42 | }; 43 | 44 | struct video_decode_metadata_t { 45 | int hint_id; 46 | int state; 47 | }; 48 | 49 | struct audio_metadata_t { 50 | int hint_id; 51 | int state; 52 | }; 53 | 54 | struct cam_preview_metadata_t { 55 | int hint_id; 56 | int state; 57 | }; 58 | 59 | int parse_metadata(char *metadata, char **metadata_saveptr, 60 | char *attribute, int attribute_size, char *value, 61 | unsigned int value_size); 62 | int parse_video_encode_metadata(char *metadata, 63 | struct video_encode_metadata_t *video_encode_metadata); 64 | int parse_video_decode_metadata(char *metadata, 65 | struct video_decode_metadata_t *video_decode_metadata); 66 | int parse_audio_metadata(char *metadata, 67 | struct audio_metadata_t *audio_metadata); 68 | int parse_cam_preview_metadata(char *metadata, 69 | struct cam_preview_metadata_t *video_decode_metadata); 70 | -------------------------------------------------------------------------------- /power/metadata-parser.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, The Linux Foundation. All rights reserved. 2 | * 3 | * Redistribution and use in source and binary forms, with or without 4 | * modification, are permitted provided that the following conditions are 5 | * met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above 9 | * copyright notice, this list of conditions and the following 10 | * disclaimer in the documentation and/or other materials provided 11 | * with the distribution. 12 | * * Neither the name of The Linux Foundation nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include "metadata-defs.h" 35 | 36 | int parse_metadata(char *metadata, char **metadata_saveptr, 37 | char *attribute, int attribute_size, char *value, 38 | unsigned int value_size) 39 | { 40 | char *attribute_string; 41 | char *attribute_value_delim; 42 | unsigned int bytes_to_copy; 43 | 44 | attribute_string = strtok_r(metadata, ATTRIBUTE_STRING_DELIM, 45 | metadata_saveptr); 46 | 47 | if (attribute_string == NULL) 48 | return METADATA_PARSING_DONE; 49 | 50 | attribute[0] = value[0] = '\0'; 51 | 52 | if ((attribute_value_delim = strchr(attribute_string, 53 | ATTRIBUTE_VALUE_DELIM)) != NULL) { 54 | bytes_to_copy = MIN((attribute_value_delim - attribute_string), 55 | attribute_size - 1); 56 | /* Replace strncpy with strlcpy 57 | * Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */ 58 | strlcpy(attribute, attribute_string, 59 | bytes_to_copy+1); 60 | 61 | bytes_to_copy = MIN(strlen(attribute_string) - strlen(attribute) - 1, 62 | value_size - 1); 63 | /* Replace strncpy with strlcpy 64 | * Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */ 65 | strlcpy(value, attribute_value_delim + 1, 66 | bytes_to_copy+1); 67 | } 68 | 69 | return METADATA_PARSING_CONTINUE; 70 | } 71 | 72 | int parse_cam_preview_metadata(char *metadata, 73 | struct cam_preview_metadata_t *cam_preview_metadata) 74 | { 75 | char attribute[1024], value[1024], *saveptr; 76 | char *temp_metadata = metadata; 77 | int parsing_status; 78 | 79 | while ((parsing_status = parse_metadata(temp_metadata, &saveptr, 80 | attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) { 81 | if (strlen(attribute) == strlen("hint_id") && 82 | (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) { 83 | if (strlen(value) > 0) { 84 | cam_preview_metadata->hint_id = atoi(value); 85 | } 86 | } 87 | 88 | if (strlen(attribute) == strlen("state") && 89 | (strncmp(attribute, "state", strlen("state")) == 0)) { 90 | if (strlen(value) > 0) { 91 | cam_preview_metadata->state = atoi(value); 92 | } 93 | } 94 | 95 | temp_metadata = NULL; 96 | } 97 | 98 | if (parsing_status == METADATA_PARSING_ERR) 99 | return -1; 100 | 101 | return 0; 102 | } 103 | 104 | int parse_video_encode_metadata(char *metadata, 105 | struct video_encode_metadata_t *video_encode_metadata) 106 | { 107 | char attribute[1024], value[1024], *saveptr; 108 | char *temp_metadata = metadata; 109 | int parsing_status; 110 | 111 | while ((parsing_status = parse_metadata(temp_metadata, &saveptr, 112 | attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) { 113 | if (strlen(attribute) == strlen("hint_id") && 114 | (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) { 115 | if (strlen(value) > 0) { 116 | video_encode_metadata->hint_id = atoi(value); 117 | } 118 | } 119 | 120 | if (strlen(attribute) == strlen("state") && 121 | (strncmp(attribute, "state", strlen("state")) == 0)) { 122 | if (strlen(value) > 0) { 123 | video_encode_metadata->state = atoi(value); 124 | } 125 | } 126 | 127 | temp_metadata = NULL; 128 | } 129 | 130 | if (parsing_status == METADATA_PARSING_ERR) 131 | return -1; 132 | 133 | return 0; 134 | } 135 | 136 | int parse_video_decode_metadata(char *metadata, 137 | struct video_decode_metadata_t *video_decode_metadata) 138 | { 139 | char attribute[1024], value[1024], *saveptr; 140 | char *temp_metadata = metadata; 141 | int parsing_status; 142 | 143 | while ((parsing_status = parse_metadata(temp_metadata, &saveptr, 144 | attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) { 145 | if (strlen(attribute) == strlen("hint_id") && 146 | (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) { 147 | if (strlen(value) > 0) { 148 | video_decode_metadata->hint_id = atoi(value); 149 | } 150 | } 151 | 152 | if (strlen(attribute) == strlen("state") && 153 | (strncmp(attribute, "state", strlen("state")) == 0)) { 154 | if (strlen(value) > 0) { 155 | video_decode_metadata->state = atoi(value); 156 | } 157 | } 158 | 159 | temp_metadata = NULL; 160 | } 161 | 162 | if (parsing_status == METADATA_PARSING_ERR) 163 | return -1; 164 | 165 | return 0; 166 | } 167 | 168 | int parse_audio_metadata(char *metadata, 169 | struct audio_metadata_t *audio_metadata) 170 | { 171 | char attribute[1024], value[1024], *saveptr; 172 | char *temp_metadata = metadata; 173 | int parsing_status; 174 | 175 | while ((parsing_status = parse_metadata(temp_metadata, &saveptr, 176 | attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) { 177 | if (strlen(attribute) == strlen("hint_id") && 178 | (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) { 179 | if (strlen(value) > 0) { 180 | audio_metadata->hint_id = atoi(value); 181 | } 182 | } 183 | 184 | if (strlen(attribute) == strlen("state") && 185 | (strncmp(attribute, "state", strlen("state")) == 0)) { 186 | if (strlen(value) > 0) { 187 | audio_metadata->state = atoi(value); 188 | } 189 | } 190 | 191 | temp_metadata = NULL; 192 | } 193 | 194 | if (parsing_status == METADATA_PARSING_ERR) 195 | return -1; 196 | 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /power/performance.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved. 2 | * 3 | * Redistribution and use in source and binary forms, with or without 4 | * modification, are permitted provided that the following conditions are 5 | * met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above 9 | * copyright notice, this list of conditions and the following 10 | * disclaimer in the documentation and/or other materials provided 11 | * with the distribution. 12 | * * Neither the name of The Linux Foundation nor the names of its 13 | * contributors may be used to endorse or promote products derived 14 | * from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | */ 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #define FAILED -1 35 | #define SUCCESS 0 36 | #define INDEFINITE_DURATION 0 37 | 38 | enum SCREEN_DISPLAY_TYPE { 39 | DISPLAY_OFF = 0x00FF, 40 | }; 41 | 42 | enum PWR_CLSP_TYPE { 43 | #ifdef MPCTLV3 44 | ALL_CPUS_PWR_CLPS_DIS_V3 = 0x40400000, /* v3 resource */ 45 | #endif 46 | ALL_CPUS_PWR_CLPS_DIS = 0x101, 47 | }; 48 | 49 | /* For CPUx min freq, the leftmost byte 50 | * represents the CPU and the 51 | * rightmost byte represents the frequency 52 | * All intermediate frequencies on the 53 | * device are supported. The hex value 54 | * passed into PerfLock will be multiplied 55 | * by 10^5. This frequency or the next 56 | * highest frequency available will be set 57 | * 58 | * For example, if 1.4 Ghz is required on 59 | * CPU0, use 0x20E 60 | * 61 | * If the highest available frequency 62 | * on the device is required, use 63 | * CPUx_MIN_FREQ_TURBO_MAX 64 | * where x represents the CPU 65 | */ 66 | enum CPU0_MIN_FREQ_LVL { 67 | CPU0_MIN_FREQ_NONTURBO_MAX = 0x20A, 68 | CPU0_MIN_FREQ_TURBO_MAX = 0x2FE, 69 | }; 70 | 71 | enum CPU1_MIN_FREQ_LVL { 72 | CPU1_MIN_FREQ_NONTURBO_MAX = 0x30A, 73 | CPU1_MIN_FREQ_TURBO_MAX = 0x3FE, 74 | }; 75 | 76 | enum CPU2_MIN_FREQ_LVL { 77 | CPU2_MIN_FREQ_NONTURBO_MAX = 0x40A, 78 | CPU2_MIN_FREQ_TURBO_MAX = 0x4FE, 79 | }; 80 | 81 | enum CPU3_MIN_FREQ_LVL { 82 | CPU3_MIN_FREQ_NONTURBO_MAX = 0x50A, 83 | CPU3_MIN_FREQ_TURBO_MAX = 0x5FE, 84 | }; 85 | 86 | enum CPU0_MAX_FREQ_LVL { 87 | CPU0_MAX_FREQ_NONTURBO_MAX = 0x150A, 88 | }; 89 | 90 | enum CPU1_MAX_FREQ_LVL { 91 | CPU1_MAX_FREQ_NONTURBO_MAX = 0x160A, 92 | }; 93 | 94 | enum CPU2_MAX_FREQ_LVL { 95 | CPU2_MAX_FREQ_NONTURBO_MAX = 0x170A, 96 | }; 97 | 98 | enum CPU3_MAX_FREQ_LVL { 99 | CPU3_MAX_FREQ_NONTURBO_MAX = 0x180A, 100 | }; 101 | 102 | enum MIN_CPUS_ONLINE_LVL { 103 | #ifdef MPCTLV3 104 | CPUS_ONLINE_MIN_BIG = 0x41000000, /* v3 resource */ 105 | CPUS_ONLINE_MIN_LITTLE = 0x41000100, /* v3 resource */ 106 | #endif 107 | CPUS_ONLINE_MIN_2 = 0x702, 108 | CPUS_ONLINE_MIN_3 = 0x703, 109 | CPUS_ONLINE_MIN_4 = 0x704, 110 | CPUS_ONLINE_MPD_OVERRIDE = 0x777, 111 | CPUS_ONLINE_MAX = 0x7FF, 112 | }; 113 | 114 | enum MAX_CPUS_ONLINE_LVL { 115 | #ifdef MPCTLV3 116 | CPUS_ONLINE_MAX_LIMIT_BIG = 0x41004000, /* v3 resource */ 117 | CPUS_ONLINE_MAX_LIMIT_LITTLE = 0x41004100, /* v3 resource */ 118 | #endif 119 | CPUS_ONLINE_MAX_LIMIT_1 = 0x8FE, 120 | CPUS_ONLINE_MAX_LIMIT_2 = 0x8FD, 121 | CPUS_ONLINE_MAX_LIMIT_3 = 0x8FC, 122 | CPUS_ONLINE_MAX_LIMIT_4 = 0x8FB, 123 | CPUS_ONLINE_MAX_LIMIT_MAX = 0x8FB, 124 | }; 125 | 126 | enum SAMPLING_RATE_LVL { 127 | MS_500 = 0xBCD, 128 | MS_50 = 0xBFA, 129 | MS_20 = 0xBFD, 130 | }; 131 | 132 | enum ONDEMAND_IO_BUSY_LVL { 133 | IO_BUSY_OFF = 0xC00, 134 | IO_BUSY_ON = 0xC01, 135 | }; 136 | 137 | enum ONDEMAND_SAMPLING_DOWN_FACTOR_LVL { 138 | SAMPLING_DOWN_FACTOR_1 = 0xD01, 139 | SAMPLING_DOWN_FACTOR_4 = 0xD04, 140 | }; 141 | 142 | 143 | enum INTERACTIVE_TIMER_RATE_LVL { 144 | TR_MS_500 = 0xECD, 145 | TR_MS_100 = 0xEF5, 146 | TR_MS_50 = 0xEFA, 147 | TR_MS_30 = 0xEFC, 148 | TR_MS_20 = 0xEFD, 149 | }; 150 | 151 | /* This timer rate applicable to cpu0 152 | across 8939 series chipset */ 153 | enum INTERACTIVE_TIMER_RATE_LVL_CPU0_8939 { 154 | TR_MS_CPU0_500 = 0x30CD, 155 | TR_MS_CPU0_100 = 0x30F5, 156 | TR_MS_CPU0_50 = 0x30FA, 157 | TR_MS_CPU0_30 = 0x30FC, 158 | TR_MS_CPU0_20 = 0x30FD, 159 | }; 160 | 161 | /* This timer rate applicable to cpu4 162 | across 8939 series chipset */ 163 | enum INTERACTIVE_TIMER_RATE_LVL_CPU4_8939 { 164 | TR_MS_CPU4_500 = 0x3BCD, 165 | TR_MS_CPU4_100 = 0x3BF5, 166 | TR_MS_CPU4_50 = 0x3BFA, 167 | TR_MS_CPU4_30 = 0x3BFC, 168 | TR_MS_CPU4_20 = 0x3BFD, 169 | }; 170 | 171 | enum INTERACTIVE_HISPEED_FREQ_LVL { 172 | HS_FREQ_1026 = 0xF0A, 173 | HS_FREQ_800 = 0xF08, 174 | }; 175 | 176 | enum INTERACTIVE_HISPEED_LOAD_LVL { 177 | HISPEED_LOAD_90 = 0x105A, 178 | }; 179 | 180 | enum SYNC_FREQ_LVL { 181 | SYNC_FREQ_300 = 0x1103, 182 | SYNC_FREQ_600 = 0X1106, 183 | SYNC_FREQ_384 = 0x1103, 184 | SYNC_FREQ_NONTURBO_MAX = 0x110A, 185 | SYNC_FREQ_TURBO = 0x110F, 186 | }; 187 | 188 | enum OPTIMAL_FREQ_LVL { 189 | OPTIMAL_FREQ_300 = 0x1203, 190 | OPTIMAL_FREQ_600 = 0x1206, 191 | OPTIMAL_FREQ_384 = 0x1203, 192 | OPTIMAL_FREQ_NONTURBO_MAX = 0x120A, 193 | OPTIMAL_FREQ_TURBO = 0x120F, 194 | }; 195 | 196 | enum SCREEN_PWR_CLPS_LVL { 197 | PWR_CLPS_DIS = 0x1300, 198 | PWR_CLPS_ENA = 0x1301, 199 | }; 200 | 201 | enum THREAD_MIGRATION_LVL { 202 | THREAD_MIGRATION_SYNC_OFF = 0x1400, 203 | #ifdef MPCTLV3 204 | THREAD_MIGRATION_SYNC_ON_V3 = 0x4241C000 205 | #endif 206 | }; 207 | 208 | enum INTERACTIVE_IO_BUSY_LVL { 209 | INTERACTIVE_IO_BUSY_OFF = 0x1B00, 210 | INTERACTIVE_IO_BUSY_ON = 0x1B01, 211 | }; 212 | 213 | enum SCHED_BOOST_LVL { 214 | #ifdef MPCTLV3 215 | SCHED_BOOST_ON_V3 = 0x40C00000, /* v3 resource */ 216 | #endif 217 | SCHED_BOOST_ON = 0x1E01, 218 | }; 219 | 220 | enum CPU4_MIN_FREQ_LVL { 221 | CPU4_MIN_FREQ_NONTURBO_MAX = 0x1F0A, 222 | CPU4_MIN_FREQ_TURBO_MAX = 0x1FFE, 223 | }; 224 | 225 | enum CPU5_MIN_FREQ_LVL { 226 | CPU5_MIN_FREQ_NONTURBO_MAX = 0x200A, 227 | CPU5_MIN_FREQ_TURBO_MAX = 0x20FE, 228 | }; 229 | 230 | enum CPU6_MIN_FREQ_LVL { 231 | CPU6_MIN_FREQ_NONTURBO_MAX = 0x210A, 232 | CPU6_MIN_FREQ_TURBO_MAX = 0x21FE, 233 | }; 234 | 235 | enum CPU7_MIN_FREQ_LVL { 236 | CPU7_MIN_FREQ_NONTURBO_MAX = 0x220A, 237 | CPU7_MIN_FREQ_TURBO_MAX = 0x22FE, 238 | }; 239 | 240 | enum CPU4_MAX_FREQ_LVL { 241 | CPU4_MAX_FREQ_NONTURBO_MAX = 0x230A, 242 | }; 243 | 244 | enum CPU5_MAX_FREQ_LVL { 245 | CPU5_MAX_FREQ_NONTURBO_MAX = 0x240A, 246 | }; 247 | 248 | enum CPU6_MAX_FREQ_LVL { 249 | CPU6_MAX_FREQ_NONTURBO_MAX = 0x250A, 250 | }; 251 | 252 | enum CPU7_MAX_FREQ_LVL { 253 | CPU7_MAX_FREQ_NONTURBO_MAX = 0x260A, 254 | }; 255 | 256 | enum SCHED_PREFER_IDLE { 257 | #ifdef MPCTLV3 258 | SCHED_PREFER_IDLE_DIS_V3 = 0x40C04000, 259 | #endif 260 | SCHED_PREFER_IDLE_DIS = 0x3E01, 261 | }; 262 | 263 | enum SCHED_MIGRATE_COST_CHNG { 264 | SCHED_MIGRATE_COST_SET = 0x3F01, 265 | }; 266 | 267 | #ifdef MPCTLV3 268 | /** 269 | * MPCTL v3 opcodes 270 | */ 271 | enum MAX_FREQ_CLUSTER_BIG { 272 | MAX_FREQ_BIG_CORE_0 = 0x40804000, 273 | }; 274 | 275 | enum MAX_FREQ_CLUSTER_LITTLE { 276 | MAX_FREQ_LITTLE_CORE_0 = 0x40804100, 277 | }; 278 | 279 | enum MIN_FREQ_CLUSTER_BIG { 280 | MIN_FREQ_BIG_CORE_0 = 0x40800000, 281 | }; 282 | 283 | enum MIN_FREQ_CLUSTER_LITTLE { 284 | MIN_FREQ_LITTLE_CORE_0 = 0x40800100, 285 | }; 286 | 287 | enum INTERACTIVE_CLUSTER_BIG { 288 | ABOVE_HISPEED_DELAY_BIG = 0x41400000, 289 | GO_HISPEED_LOAD_BIG = 0x41410000, 290 | HISPEED_FREQ_BIG = 0x41414000, 291 | TARGET_LOADS_BIG = 0x41420000, 292 | TIMER_RATE_BIG = 0x41424000, 293 | USE_SCHED_LOAD_BIG = 0x41430000, 294 | USE_MIGRATION_NOTIF_BIG = 0x41434000, 295 | IGNORE_HISPEED_NOTIF_BIG = 0x41438000, 296 | }; 297 | 298 | enum INTERACTIVE_CLUSTER_LITTLE { 299 | ABOVE_HISPEED_DELAY_LITTLE = 0x41400100, 300 | GO_HISPEED_LOAD_LITTLE = 0x41410100, 301 | HISPEED_FREQ_LITTLE = 0x41414100, 302 | TARGET_LOADS_LITTLE = 0x41420100, 303 | TIMER_RATE_LITTLE = 0x41424100, 304 | USE_SCHED_LOAD_LITTLE = 0x41430100, 305 | USE_MIGRATION_NOTIF_LITTLE = 0x41434100, 306 | IGNORE_HISPEED_NOTIF_LITTLE = 0x41438100, 307 | }; 308 | 309 | enum CPUBW_HWMON { 310 | CPUBW_HWMON_MIN_FREQ = 0x41800000, 311 | CPUBW_HWMON_V1 = 0x4180C000, 312 | LOW_POWER_CEIL_MBPS = 0x41810000, 313 | LOW_POWER_IO_PERCENT = 0x41814000, 314 | CPUBW_HWMON_SAMPLE_MS = 0x41820000, 315 | }; 316 | 317 | enum SCHEDULER { 318 | SCHED_SMALL_TASK_DIS = 0x40C0C000, 319 | SCHED_IDLE_LOAD_DIS = 0x40C10000, 320 | SCHED_IDLE_NR_RUN_DIS = 0x40C14000, 321 | SCHED_GROUP_ON = 0x40C28000, 322 | }; 323 | 324 | enum STORAGE { 325 | STOR_CLK_SCALE_DIS = 0x42C10000, 326 | }; 327 | 328 | enum GPU { 329 | GPU_MIN_PWRLVL_BOOST = 0x42804000, 330 | }; 331 | #endif 332 | 333 | #ifdef __cplusplus 334 | } 335 | #endif 336 | -------------------------------------------------------------------------------- /power/power-8084.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "QCOM PowerHAL" 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | #include "metadata-defs.h" 46 | #include "hint-data.h" 47 | #include "performance.h" 48 | #include "power-common.h" 49 | 50 | static int first_display_off_hint; 51 | 52 | int get_number_of_profiles() { 53 | return 3; 54 | } 55 | 56 | static int current_power_profile = PROFILE_BALANCED; 57 | 58 | static void set_power_profile(int profile) { 59 | 60 | if (profile == current_power_profile) 61 | return; 62 | 63 | ALOGV("%s: profile=%d", __func__, profile); 64 | 65 | if (current_power_profile != PROFILE_BALANCED) { 66 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 67 | ALOGV("%s: hint undone", __func__); 68 | } 69 | 70 | if (profile == PROFILE_HIGH_PERFORMANCE) { 71 | int resource_values[] = { CPUS_ONLINE_MIN_4, 72 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 73 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX }; 74 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 75 | resource_values, ARRAY_SIZE(resource_values)); 76 | ALOGD("%s: set performance mode", __func__); 77 | 78 | } else if (profile == PROFILE_POWER_SAVE) { 79 | int resource_values[] = { CPUS_ONLINE_MAX_LIMIT_2, 80 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX, 81 | CPU2_MAX_FREQ_NONTURBO_MAX, CPU3_MAX_FREQ_NONTURBO_MAX }; 82 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 83 | resource_values, ARRAY_SIZE(resource_values)); 84 | ALOGD("%s: set powersave", __func__); 85 | } 86 | 87 | current_power_profile = profile; 88 | } 89 | 90 | extern void interaction(int duration, int num_args, int opt_list[]); 91 | 92 | int power_hint_override(__attribute__((unused)) struct power_module *module, 93 | power_hint_t hint, void *data) 94 | { 95 | if (hint == POWER_HINT_SET_PROFILE) { 96 | set_power_profile(*(int32_t *)data); 97 | return HINT_HANDLED; 98 | } 99 | 100 | // Skip other hints in custom power modes 101 | if (current_power_profile != PROFILE_BALANCED) { 102 | return HINT_HANDLED; 103 | } 104 | 105 | if (hint == POWER_HINT_CPU_BOOST) { 106 | int duration = *(int32_t *)data / 1000; 107 | int resources[] = { CPUS_ONLINE_MIN_2, 0x20B, 0x30B, 0x1C00}; 108 | 109 | if (duration > 0) 110 | interaction(duration, ARRAY_SIZE(resources), resources); 111 | 112 | return HINT_HANDLED; 113 | } 114 | 115 | return HINT_NONE; 116 | } 117 | 118 | int set_interactive_override(struct power_module *module, int on) 119 | { 120 | char governor[80]; 121 | 122 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 123 | ALOGE("Can't obtain scaling governor."); 124 | 125 | return HINT_NONE; 126 | } 127 | 128 | if (!on) { 129 | /* Display off. */ 130 | /* 131 | * We need to be able to identify the first display off hint 132 | * and release the current lock holder 133 | */ 134 | if (!first_display_off_hint) { 135 | undo_initial_hint_action(); 136 | first_display_off_hint = 1; 137 | } 138 | /* Used for all subsequent toggles to the display */ 139 | undo_hint_action(DISPLAY_STATE_HINT_ID_2); 140 | 141 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 142 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 143 | int resource_values[] = {MS_500, SYNC_FREQ_600, OPTIMAL_FREQ_600, THREAD_MIGRATION_SYNC_OFF}; 144 | 145 | perform_hint_action(DISPLAY_STATE_HINT_ID, 146 | resource_values, ARRAY_SIZE(resource_values)); 147 | 148 | return HINT_HANDLED; 149 | } 150 | } else { 151 | /* Display on */ 152 | int resource_values2[] = { CPUS_ONLINE_MIN_2 }; 153 | perform_hint_action(DISPLAY_STATE_HINT_ID_2, 154 | resource_values2, ARRAY_SIZE(resource_values2)); 155 | 156 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 157 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 158 | undo_hint_action(DISPLAY_STATE_HINT_ID); 159 | 160 | return HINT_HANDLED; 161 | } 162 | } 163 | 164 | return HINT_NONE; 165 | } 166 | -------------------------------------------------------------------------------- /power/power-8226.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 | * Copyright (c) 2014, The CyanogenMod Project 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following 12 | * disclaimer in the documentation and/or other materials provided 13 | * with the distribution. 14 | * * Neither the name of The Linux Foundation nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QCOM PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | int get_number_of_profiles() { 52 | return 3; 53 | } 54 | 55 | static int current_power_profile = PROFILE_BALANCED; 56 | 57 | static void set_power_profile(int profile) { 58 | 59 | if (profile == current_power_profile) 60 | return; 61 | 62 | ALOGV("%s: profile=%d", __func__, profile); 63 | 64 | if (current_power_profile != PROFILE_BALANCED) { 65 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 66 | ALOGV("%s: hint undone", __func__); 67 | } 68 | 69 | if (profile == PROFILE_HIGH_PERFORMANCE) { 70 | int resource_values[] = { CPUS_ONLINE_MIN_4, 71 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 72 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX }; 73 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 74 | resource_values, ARRAY_SIZE(resource_values)); 75 | ALOGD("%s: set performance mode", __func__); 76 | } else if (profile == PROFILE_POWER_SAVE) { 77 | int resource_values[] = { CPUS_ONLINE_MAX_LIMIT_2, 78 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX, 79 | CPU2_MAX_FREQ_NONTURBO_MAX, CPU3_MAX_FREQ_NONTURBO_MAX }; 80 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 81 | resource_values, ARRAY_SIZE(resource_values)); 82 | ALOGD("%s: set powersave", __func__); 83 | } 84 | 85 | current_power_profile = profile; 86 | } 87 | 88 | extern void interaction(int duration, int num_args, int opt_list[]); 89 | 90 | int power_hint_override(__attribute__((unused)) struct power_module *module, 91 | power_hint_t hint, void *data) 92 | { 93 | if (hint == POWER_HINT_SET_PROFILE) { 94 | set_power_profile(*(int32_t *)data); 95 | return HINT_HANDLED; 96 | } 97 | 98 | // Skip other hints in custom power modes 99 | if (current_power_profile != PROFILE_BALANCED) { 100 | return HINT_HANDLED; 101 | } 102 | 103 | if (hint == POWER_HINT_CPU_BOOST) { 104 | int duration = *(int32_t *)data / 1000; 105 | int resources[] = { CPUS_ONLINE_MIN_2, 0x20F, 0x30F}; 106 | 107 | if (duration > 0) 108 | interaction(duration, ARRAY_SIZE(resources), resources); 109 | return HINT_HANDLED; 110 | } else if (hint == POWER_HINT_INTERACTION) { 111 | int resources[] = {0x702, 0x20B, 0x30B}; 112 | int duration = 3000; 113 | 114 | interaction(duration, ARRAY_SIZE(resources), resources); 115 | return HINT_HANDLED; 116 | } 117 | 118 | return HINT_NONE; 119 | } 120 | -------------------------------------------------------------------------------- /power/power-8610.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 | * Copyright (c) 2014, The CyanogenMod Project 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following 12 | * disclaimer in the documentation and/or other materials provided 13 | * with the distribution. 14 | * * Neither the name of The Linux Foundation nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QCOM PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | int get_number_of_profiles() { 52 | return 3; 53 | } 54 | 55 | static int current_power_profile = PROFILE_BALANCED; 56 | 57 | static void set_power_profile(int profile) { 58 | 59 | if (profile == current_power_profile) 60 | return; 61 | 62 | ALOGV("%s: profile=%d", __func__, profile); 63 | 64 | if (current_power_profile != PROFILE_BALANCED) { 65 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 66 | ALOGV("%s: hint undone", __func__); 67 | } 68 | 69 | if (profile == PROFILE_HIGH_PERFORMANCE) { 70 | int resource_values[] = { CPUS_ONLINE_MIN_2, 71 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX }; 72 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 73 | resource_values, ARRAY_SIZE(resource_values)); 74 | ALOGD("%s: set performance mode", __func__); 75 | } else if (profile == PROFILE_POWER_SAVE) { 76 | int resource_values[] = { CPUS_ONLINE_MAX_LIMIT_2, 77 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX }; 78 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 79 | resource_values, ARRAY_SIZE(resource_values)); 80 | ALOGD("%s: set powersave", __func__); 81 | } 82 | 83 | current_power_profile = profile; 84 | } 85 | 86 | extern void interaction(int duration, int num_args, int opt_list[]); 87 | 88 | int power_hint_override(__attribute__((unused)) struct power_module *module, 89 | power_hint_t hint, void *data) 90 | { 91 | if (hint == POWER_HINT_SET_PROFILE) { 92 | set_power_profile(*(int32_t *)data); 93 | return HINT_HANDLED; 94 | } 95 | 96 | // Skip other hints in custom power modes 97 | if (current_power_profile != PROFILE_BALANCED) { 98 | return HINT_HANDLED; 99 | } 100 | 101 | if (hint == POWER_HINT_CPU_BOOST) { 102 | int duration = *(int32_t *)data / 1000; 103 | int resources[] = { CPUS_ONLINE_MIN_2, 0x20F, 0x30F}; 104 | 105 | if (duration > 0) 106 | interaction(duration, ARRAY_SIZE(resources), resources); 107 | return HINT_HANDLED; 108 | } else if (hint == POWER_HINT_INTERACTION) { 109 | int resources[] = {0x702, 0x20B, 0x30B}; 110 | int duration = 3000; 111 | 112 | interaction(duration, ARRAY_SIZE(resources), resources); 113 | return HINT_HANDLED; 114 | } 115 | 116 | return HINT_NONE; 117 | } 118 | -------------------------------------------------------------------------------- /power/power-8909.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "QTI PowerHAL" 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | #include "metadata-defs.h" 46 | #include "hint-data.h" 47 | #include "performance.h" 48 | #include "power-common.h" 49 | 50 | 51 | static void process_video_encode_hint(void *metadata) 52 | { 53 | char governor[80]; 54 | struct video_encode_metadata_t video_encode_metadata; 55 | char tmp_str[NODE_MAX]; 56 | 57 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 58 | ALOGE("Can't obtain scaling governor."); 59 | 60 | return; 61 | } 62 | 63 | /* Initialize encode metadata struct fields. */ 64 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 65 | video_encode_metadata.state = -1; 66 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 67 | 68 | if (metadata) { 69 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 70 | -1) { 71 | ALOGE("Error occurred while parsing metadata."); 72 | return; 73 | } 74 | } else { 75 | return; 76 | } 77 | 78 | if (video_encode_metadata.state == 1) { 79 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 80 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 81 | int resource_values[] = {HS_FREQ_800, THREAD_MIGRATION_SYNC_OFF}; 82 | perform_hint_action(video_encode_metadata.hint_id, 83 | resource_values, ARRAY_SIZE(resource_values)); 84 | } 85 | } else if (video_encode_metadata.state == 0) { 86 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 87 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 88 | undo_hint_action(video_encode_metadata.hint_id); 89 | } 90 | } 91 | } 92 | 93 | int power_hint_override(struct power_module *module, power_hint_t hint, void *data) 94 | { 95 | switch(hint) { 96 | case POWER_HINT_VIDEO_ENCODE: 97 | { 98 | process_video_encode_hint(data); 99 | return HINT_HANDLED; 100 | } 101 | default: 102 | { 103 | break; 104 | } 105 | } 106 | return HINT_NONE; 107 | } 108 | -------------------------------------------------------------------------------- /power/power-8916.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 | * Copyright (c) 2014, The CyanogenMod Project 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following 12 | * disclaimer in the documentation and/or other materials provided 13 | * with the distribution. 14 | * * Neither the name of The Linux Foundation nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QCOM PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | #define MIN_FREQ_CPU0_DISP_OFF 400000 52 | #define MIN_FREQ_CPU0_DISP_ON 960000 53 | 54 | char scaling_min_freq[4][80] ={ 55 | "sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", 56 | "sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq", 57 | "sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq", 58 | "sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq" 59 | }; 60 | 61 | static int slack_node_rw_failed = 0; 62 | 63 | int get_number_of_profiles() { 64 | return 3; 65 | } 66 | 67 | static int current_power_profile = PROFILE_BALANCED; 68 | 69 | /** 70 | * If target is 8916: 71 | * return 1 72 | * else: 73 | * return 0 74 | */ 75 | static int is_target_8916(void) 76 | { 77 | static int is_8916 = -1; 78 | int soc_id; 79 | 80 | if (is_8916 >= 0) 81 | return is_8916; 82 | 83 | soc_id = get_soc_id(); 84 | if (soc_id == 206 || (soc_id >= 247 && soc_id <= 250)) 85 | is_8916 = 1; 86 | else 87 | is_8916 = 0; 88 | 89 | return is_8916; 90 | } 91 | 92 | static int profile_high_performance_8916[3] = { 93 | 0x1C00, 0x0901, CPU0_MIN_FREQ_TURBO_MAX, 94 | }; 95 | 96 | static int profile_high_performance_8939[11] = { 97 | SCHED_BOOST_ON, 0x1C00, 0x0901, 98 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 99 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX, 100 | CPU4_MIN_FREQ_TURBO_MAX, CPU5_MIN_FREQ_TURBO_MAX, 101 | CPU6_MIN_FREQ_TURBO_MAX, CPU7_MIN_FREQ_TURBO_MAX, 102 | }; 103 | 104 | static int profile_power_save_8916[1] = { 105 | CPU0_MAX_FREQ_NONTURBO_MAX, 106 | }; 107 | 108 | static int profile_power_save_8939[5] = { 109 | CPUS_ONLINE_MAX_LIMIT_2, 110 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX, 111 | CPU2_MAX_FREQ_NONTURBO_MAX, CPU3_MAX_FREQ_NONTURBO_MAX, 112 | }; 113 | 114 | static void set_power_profile(int profile) { 115 | 116 | if (profile == current_power_profile) 117 | return; 118 | 119 | ALOGV("%s: profile=%d", __func__, profile); 120 | 121 | if (current_power_profile != PROFILE_BALANCED) { 122 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 123 | ALOGV("%s: hint undone", __func__); 124 | } 125 | 126 | if (profile == PROFILE_HIGH_PERFORMANCE) { 127 | int *resource_values = is_target_8916() ? 128 | profile_high_performance_8916 : profile_high_performance_8939; 129 | 130 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 131 | resource_values, ARRAY_SIZE(resource_values)); 132 | ALOGD("%s: set performance mode", __func__); 133 | 134 | } else if (profile == PROFILE_POWER_SAVE) { 135 | int* resource_values = is_target_8916() ? 136 | profile_power_save_8916 : profile_power_save_8939; 137 | 138 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 139 | resource_values, ARRAY_SIZE(resource_values)); 140 | ALOGD("%s: set powersave", __func__); 141 | } 142 | 143 | current_power_profile = profile; 144 | } 145 | 146 | static void process_video_decode_hint(void *metadata) 147 | { 148 | char governor[80]; 149 | struct video_decode_metadata_t video_decode_metadata; 150 | 151 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 152 | ALOGE("Can't obtain scaling governor."); 153 | 154 | return; 155 | } 156 | 157 | if (metadata) { 158 | ALOGI("Processing video decode hint. Metadata: %s", (char *)metadata); 159 | } 160 | 161 | /* Initialize encode metadata struct fields. */ 162 | memset(&video_decode_metadata, 0, sizeof(struct video_decode_metadata_t)); 163 | video_decode_metadata.state = -1; 164 | video_decode_metadata.hint_id = DEFAULT_VIDEO_DECODE_HINT_ID; 165 | 166 | if (metadata) { 167 | if (parse_video_decode_metadata((char *)metadata, &video_decode_metadata) == 168 | -1) { 169 | ALOGE("Error occurred while parsing metadata."); 170 | return; 171 | } 172 | } else { 173 | return; 174 | } 175 | 176 | if (video_decode_metadata.state == 1) { 177 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 178 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 179 | int resource_values[] = {THREAD_MIGRATION_SYNC_OFF}; 180 | 181 | perform_hint_action(video_decode_metadata.hint_id, 182 | resource_values, ARRAY_SIZE(resource_values)); 183 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 184 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 185 | int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026}; 186 | 187 | perform_hint_action(video_decode_metadata.hint_id, 188 | resource_values, ARRAY_SIZE(resource_values)); 189 | } 190 | } else if (video_decode_metadata.state == 0) { 191 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 192 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 193 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 194 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 195 | undo_hint_action(video_decode_metadata.hint_id); 196 | } 197 | } 198 | } 199 | 200 | static void process_video_encode_hint(void *metadata) 201 | { 202 | char governor[80]; 203 | struct video_encode_metadata_t video_encode_metadata; 204 | 205 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 206 | ALOGE("Can't obtain scaling governor."); 207 | 208 | return; 209 | } 210 | 211 | /* Initialize encode metadata struct fields. */ 212 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 213 | video_encode_metadata.state = -1; 214 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 215 | 216 | if (metadata) { 217 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 218 | -1) { 219 | ALOGE("Error occurred while parsing metadata."); 220 | return; 221 | } 222 | } else { 223 | return; 224 | } 225 | 226 | if (video_encode_metadata.state == 1) { 227 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 228 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 229 | int resource_values[] = {IO_BUSY_OFF, SAMPLING_DOWN_FACTOR_1, THREAD_MIGRATION_SYNC_OFF}; 230 | 231 | perform_hint_action(video_encode_metadata.hint_id, 232 | resource_values, ARRAY_SIZE(resource_values)); 233 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 234 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 235 | int resource_values[] = {HS_FREQ_800, 0x1C00}; 236 | 237 | perform_hint_action(video_encode_metadata.hint_id, 238 | resource_values, ARRAY_SIZE(resource_values)); 239 | } 240 | } else if (video_encode_metadata.state == 0) { 241 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 242 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 243 | undo_hint_action(video_encode_metadata.hint_id); 244 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 245 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 246 | undo_hint_action(video_encode_metadata.hint_id); 247 | } 248 | } 249 | } 250 | 251 | extern void interaction(int duration, int num_args, int opt_list[]); 252 | 253 | #ifdef __LP64__ 254 | typedef int64_t hintdata; 255 | #else 256 | typedef int hintdata; 257 | #endif 258 | 259 | int set_interactive_override(struct power_module *module __unused, int on) 260 | { 261 | char governor[80]; 262 | char tmp_str[NODE_MAX]; 263 | struct video_encode_metadata_t video_encode_metadata; 264 | int rc; 265 | 266 | ALOGI("Got set_interactive hint"); 267 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) { 268 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) { 269 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) { 270 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) { 271 | ALOGE("Can't obtain scaling governor."); 272 | return HINT_HANDLED; 273 | } 274 | } 275 | } 276 | } 277 | 278 | if (!on) { 279 | /* Display off. */ 280 | if (is_target_8916()) { 281 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 282 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 283 | int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF}; 284 | perform_hint_action(DISPLAY_STATE_HINT_ID, 285 | resource_values, ARRAY_SIZE(resource_values)); 286 | } /* Perf time rate set for 8916 target*/ 287 | /* End of display hint for 8916 */ 288 | } else { 289 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 290 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 291 | int resource_values[] = {TR_MS_CPU0_50,TR_MS_CPU4_50, THREAD_MIGRATION_SYNC_OFF}; 292 | 293 | /* Set CPU0 MIN FREQ to 400Mhz avoid extra peak power 294 | impact in volume key press */ 295 | snprintf(tmp_str, NODE_MAX, "%d", MIN_FREQ_CPU0_DISP_OFF); 296 | if (sysfs_write(scaling_min_freq[0], tmp_str) != 0) { 297 | if (sysfs_write(scaling_min_freq[1], tmp_str) != 0) { 298 | if (sysfs_write(scaling_min_freq[2], tmp_str) != 0) { 299 | if (sysfs_write(scaling_min_freq[3], tmp_str) != 0) { 300 | if(!slack_node_rw_failed) { 301 | ALOGE("Failed to write to %s",SCALING_MIN_FREQ ); 302 | } 303 | rc = 1; 304 | } 305 | } 306 | } 307 | } 308 | 309 | perform_hint_action(DISPLAY_STATE_HINT_ID, 310 | resource_values, ARRAY_SIZE(resource_values)); 311 | } /* Perf time rate set for CORE0,CORE4 8939 target*/ 312 | /* End of display hint for 8939 */ 313 | } 314 | 315 | } else { 316 | /* Display on. */ 317 | if (is_target_8916()) { 318 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 319 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 320 | undo_hint_action(DISPLAY_STATE_HINT_ID); 321 | } 322 | } else { 323 | 324 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 325 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 326 | 327 | /* Recovering MIN_FREQ in display ON case */ 328 | snprintf(tmp_str, NODE_MAX, "%d", MIN_FREQ_CPU0_DISP_ON); 329 | if (sysfs_write(scaling_min_freq[0], tmp_str) != 0) { 330 | if (sysfs_write(scaling_min_freq[1], tmp_str) != 0) { 331 | if (sysfs_write(scaling_min_freq[2], tmp_str) != 0) { 332 | if (sysfs_write(scaling_min_freq[3], tmp_str) != 0) { 333 | if(!slack_node_rw_failed) { 334 | ALOGE("Failed to write to %s",SCALING_MIN_FREQ ); 335 | } 336 | rc = 1; 337 | } 338 | } 339 | } 340 | } 341 | undo_hint_action(DISPLAY_STATE_HINT_ID); 342 | } 343 | 344 | } /* End of check condition during the DISPLAY ON case */ 345 | } 346 | return HINT_HANDLED; 347 | } 348 | 349 | int power_hint_override(struct power_module *module __unused, power_hint_t hint, void *data) 350 | { 351 | if (hint == POWER_HINT_SET_PROFILE) { 352 | set_power_profile(*(int32_t *)data); 353 | } 354 | 355 | // Skip other hints in custom power modes 356 | if (current_power_profile != PROFILE_BALANCED) { 357 | return HINT_HANDLED; 358 | } 359 | 360 | if (hint == POWER_HINT_INTERACTION) { 361 | int duration = 500, duration_hint = 0; 362 | static struct timespec s_previous_boost_timespec; 363 | struct timespec cur_boost_timespec; 364 | long long elapsed_time; 365 | 366 | if (data) { 367 | duration_hint = *((int *)data); 368 | } 369 | 370 | duration = duration_hint > 0 ? duration_hint : 500; 371 | 372 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 373 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 374 | if (elapsed_time > 750000) 375 | elapsed_time = 750000; 376 | // don't hint if it's been less than 250ms since last boost 377 | // also detect if we're doing anything resembling a fling 378 | // support additional boosting in case of flings 379 | else if (elapsed_time < 250000 && duration <= 750) 380 | return HINT_HANDLED; 381 | 382 | s_previous_boost_timespec = cur_boost_timespec; 383 | 384 | if (duration >= 1500) { 385 | int resources[] = { 386 | ALL_CPUS_PWR_CLPS_DIS, 387 | SCHED_BOOST_ON, 388 | SCHED_PREFER_IDLE_DIS, 389 | 0x20D 390 | }; 391 | interaction(duration, ARRAY_SIZE(resources), resources); 392 | } else { 393 | int resources[] = { 394 | ALL_CPUS_PWR_CLPS_DIS, 395 | SCHED_PREFER_IDLE_DIS, 396 | 0x20D 397 | }; 398 | interaction(duration, ARRAY_SIZE(resources), resources); 399 | } 400 | return HINT_HANDLED; 401 | } 402 | 403 | if (hint == POWER_HINT_LAUNCH) { 404 | int duration = 2000; 405 | int resources[] = { 406 | ALL_CPUS_PWR_CLPS_DIS, 407 | SCHED_BOOST_ON, 408 | SCHED_PREFER_IDLE_DIS, 409 | 0x20F, 410 | 0x1C00, 411 | 0x4001, 412 | 0x4101, 413 | 0x4201 414 | }; 415 | 416 | interaction(duration, ARRAY_SIZE(resources), resources); 417 | 418 | return HINT_HANDLED; 419 | } 420 | 421 | if (hint == POWER_HINT_CPU_BOOST) { 422 | int duration = *(int32_t *)data / 1000; 423 | int resources[] = { 424 | ALL_CPUS_PWR_CLPS_DIS, 425 | SCHED_BOOST_ON, 426 | SCHED_PREFER_IDLE_DIS, 427 | 0x20D 428 | }; 429 | 430 | if (duration > 0) 431 | interaction(duration, ARRAY_SIZE(resources), resources); 432 | 433 | return HINT_HANDLED; 434 | } 435 | 436 | if (hint == POWER_HINT_VIDEO_ENCODE) { 437 | process_video_encode_hint(data); 438 | return HINT_HANDLED; 439 | } 440 | 441 | if (hint == POWER_HINT_VIDEO_DECODE) { 442 | process_video_decode_hint(data); 443 | return HINT_HANDLED; 444 | } 445 | 446 | return HINT_NONE; 447 | } 448 | -------------------------------------------------------------------------------- /power/power-8937.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QTI PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | static int video_encode_hint_sent; 52 | static int current_power_profile = PROFILE_BALANCED; 53 | 54 | static void process_video_encode_hint(void *metadata); 55 | 56 | extern void interaction(int duration, int num_args, int opt_list[]); 57 | 58 | static int profile_high_performance[] = { 59 | SCHED_BOOST_ON_V3, 0x1, 60 | ALL_CPUS_PWR_CLPS_DIS_V3, 0x1, 61 | CPUS_ONLINE_MIN_BIG, 0x4, 62 | MIN_FREQ_BIG_CORE_0, 0xFFF, 63 | MIN_FREQ_LITTLE_CORE_0, 0xFFF, 64 | GPU_MIN_PWRLVL_BOOST, 0x1, 65 | SCHED_PREFER_IDLE_DIS_V3, 0x1, 66 | SCHED_SMALL_TASK_DIS, 0x1, 67 | SCHED_IDLE_NR_RUN_DIS, 0x1, 68 | SCHED_IDLE_LOAD_DIS, 0x1, 69 | }; 70 | 71 | static int profile_power_save[] = { 72 | CPUS_ONLINE_MAX_LIMIT_BIG, 0x1, 73 | MAX_FREQ_BIG_CORE_0, 0x3bf, 74 | MAX_FREQ_LITTLE_CORE_0, 0x300, 75 | }; 76 | 77 | static int profile_bias_power[] = { 78 | MAX_FREQ_BIG_CORE_0, 0x4B0, 79 | MAX_FREQ_LITTLE_CORE_0, 0x300, 80 | }; 81 | 82 | static int profile_bias_performance[] = { 83 | CPUS_ONLINE_MAX_LIMIT_BIG, 0x4, 84 | MIN_FREQ_BIG_CORE_0, 0x540, 85 | }; 86 | 87 | int get_number_of_profiles() { 88 | return 5; 89 | } 90 | 91 | static void set_power_profile(int profile) { 92 | 93 | if (profile == current_power_profile) 94 | return; 95 | 96 | ALOGV("%s: profile=%d", __func__, profile); 97 | 98 | if (current_power_profile != PROFILE_BALANCED) { 99 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 100 | ALOGV("%s: hint undone", __func__); 101 | } 102 | 103 | if (profile == PROFILE_HIGH_PERFORMANCE) { 104 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_high_performance, 105 | ARRAY_SIZE(profile_high_performance)); 106 | ALOGD("%s: set performance mode", __func__); 107 | 108 | } else if (profile == PROFILE_POWER_SAVE) { 109 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save, 110 | ARRAY_SIZE(profile_power_save)); 111 | ALOGD("%s: set powersave", __func__); 112 | } else if (profile == PROFILE_BIAS_POWER) { 113 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_power, 114 | ARRAY_SIZE(profile_bias_power)); 115 | ALOGD("%s: Set bias power mode", __func__); 116 | 117 | } else if (profile == PROFILE_BIAS_PERFORMANCE) { 118 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_performance, 119 | ARRAY_SIZE(profile_bias_performance)); 120 | ALOGD("%s: Set bias perf mode", __func__); 121 | } 122 | 123 | current_power_profile = profile; 124 | } 125 | 126 | int power_hint_override(__unused struct power_module *module, power_hint_t hint, 127 | void *data) 128 | { 129 | int duration, duration_hint; 130 | static struct timespec s_previous_boost_timespec; 131 | struct timespec cur_boost_timespec; 132 | long long elapsed_time; 133 | int resources_launch[] = { 134 | SCHED_BOOST_ON_V3, 0x1, 135 | MIN_FREQ_BIG_CORE_0, 0x5DC, 136 | ALL_CPUS_PWR_CLPS_DIS_V3, 0x1, 137 | CPUS_ONLINE_MIN_BIG, 0x4, 138 | GPU_MIN_PWRLVL_BOOST, 0x1, 139 | SCHED_PREFER_IDLE_DIS_V3, 0x1, 140 | SCHED_SMALL_TASK_DIS, 0x1, 141 | SCHED_IDLE_NR_RUN_DIS, 0x1, 142 | SCHED_IDLE_LOAD_DIS, 0x1, 143 | }; 144 | 145 | int resources_cpu_boost[] = { 146 | SCHED_BOOST_ON_V3, 0x1, 147 | MIN_FREQ_BIG_CORE_0, 0x44C, 148 | }; 149 | 150 | int resources_interaction_fling_boost[] = { 151 | MIN_FREQ_BIG_CORE_0, 0x514, 152 | SCHED_BOOST_ON_V3, 0x1, 153 | }; 154 | 155 | if (hint == POWER_HINT_SET_PROFILE) { 156 | set_power_profile(*(int32_t *)data); 157 | return HINT_HANDLED; 158 | } 159 | 160 | // Skip other hints in power save mode 161 | if (current_power_profile == PROFILE_POWER_SAVE) { 162 | return HINT_HANDLED; 163 | } 164 | 165 | switch (hint) { 166 | case POWER_HINT_INTERACTION: 167 | duration = 500; 168 | duration_hint = 0; 169 | 170 | if (data) { 171 | duration_hint = *((int *)data); 172 | } 173 | 174 | duration = duration_hint > 0 ? duration_hint : 500; 175 | 176 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 177 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 178 | if (elapsed_time > 750000) 179 | elapsed_time = 750000; 180 | // don't hint if it's been less than 250ms since last boost 181 | // also detect if we're doing anything resembling a fling 182 | // support additional boosting in case of flings 183 | else if (elapsed_time < 250000 && duration <= 750) 184 | return HINT_HANDLED; 185 | 186 | s_previous_boost_timespec = cur_boost_timespec; 187 | 188 | if (duration >= 1500) { 189 | interaction(duration, ARRAY_SIZE(resources_interaction_fling_boost), 190 | resources_interaction_fling_boost); 191 | } 192 | return HINT_HANDLED; 193 | case POWER_HINT_LAUNCH: 194 | duration = 2000; 195 | interaction(duration, ARRAY_SIZE(resources_launch), 196 | resources_launch); 197 | return HINT_HANDLED; 198 | case POWER_HINT_CPU_BOOST: 199 | duration = *(int32_t *)data / 1000; 200 | if (duration > 0) { 201 | interaction(duration, ARRAY_SIZE(resources_cpu_boost), 202 | resources_cpu_boost); 203 | } 204 | return HINT_HANDLED; 205 | case POWER_HINT_VIDEO_ENCODE: 206 | process_video_encode_hint(data); 207 | return HINT_HANDLED; 208 | default: 209 | break; 210 | } 211 | return HINT_NONE; 212 | } 213 | 214 | int set_interactive_override(__unused struct power_module *module, int on) 215 | { 216 | char governor[80]; 217 | 218 | ALOGI("Got set_interactive hint"); 219 | 220 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) { 221 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) { 222 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) { 223 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) { 224 | ALOGE("Can't obtain scaling governor."); 225 | return HINT_HANDLED; 226 | } 227 | } 228 | } 229 | } 230 | 231 | if (!on) { 232 | /* Display off. */ 233 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 234 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 235 | int resource_values[] = { 236 | TIMER_RATE_BIG, 0x32, 237 | TIMER_RATE_LITTLE, 0x32, 238 | THREAD_MIGRATION_SYNC_ON_V3, 0x0, 239 | }; 240 | 241 | perform_hint_action(DISPLAY_STATE_HINT_ID, 242 | resource_values, ARRAY_SIZE(resource_values)); 243 | } /* Perf time rate set for CORE0,CORE4 8952 target*/ 244 | 245 | } else { 246 | /* Display on. */ 247 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 248 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 249 | 250 | undo_hint_action(DISPLAY_STATE_HINT_ID); 251 | } 252 | } 253 | return HINT_HANDLED; 254 | } 255 | 256 | /* Video Encode Hint */ 257 | static void process_video_encode_hint(void *metadata) 258 | { 259 | char governor[80]; 260 | struct video_encode_metadata_t video_encode_metadata; 261 | 262 | ALOGI("Got process_video_encode_hint"); 263 | 264 | if (get_scaling_governor_check_cores(governor, 265 | sizeof(governor),CPU0) == -1) { 266 | if (get_scaling_governor_check_cores(governor, 267 | sizeof(governor),CPU1) == -1) { 268 | if (get_scaling_governor_check_cores(governor, 269 | sizeof(governor),CPU2) == -1) { 270 | if (get_scaling_governor_check_cores(governor, 271 | sizeof(governor),CPU3) == -1) { 272 | ALOGE("Can't obtain scaling governor."); 273 | return; 274 | } 275 | } 276 | } 277 | } 278 | 279 | /* Initialize encode metadata struct fields. */ 280 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 281 | video_encode_metadata.state = -1; 282 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 283 | 284 | if (metadata) { 285 | if (parse_video_encode_metadata((char *)metadata, 286 | &video_encode_metadata) == -1) { 287 | ALOGE("Error occurred while parsing metadata."); 288 | return; 289 | } 290 | } else { 291 | return; 292 | } 293 | 294 | if (video_encode_metadata.state == 1) { 295 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, 296 | strlen(INTERACTIVE_GOVERNOR)) == 0) && 297 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 298 | int resource_values[] = { 299 | USE_SCHED_LOAD_BIG, 0x1, 300 | USE_SCHED_LOAD_LITTLE, 0x1, 301 | USE_MIGRATION_NOTIF_BIG, 0x1, 302 | USE_MIGRATION_NOTIF_LITTLE, 0x1, 303 | TIMER_RATE_BIG, 0x28, 304 | TIMER_RATE_LITTLE, 0x28, 305 | }; 306 | if (!video_encode_hint_sent) { 307 | perform_hint_action(video_encode_metadata.hint_id, 308 | resource_values, 309 | ARRAY_SIZE(resource_values)); 310 | video_encode_hint_sent = 1; 311 | } 312 | } 313 | } else if (video_encode_metadata.state == 0) { 314 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, 315 | strlen(INTERACTIVE_GOVERNOR)) == 0) && 316 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 317 | undo_hint_action(video_encode_metadata.hint_id); 318 | video_encode_hint_sent = 0; 319 | return ; 320 | } 321 | } 322 | return; 323 | } 324 | -------------------------------------------------------------------------------- /power/power-8952.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QTI PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | static int video_encode_hint_sent; 52 | static int current_power_profile = PROFILE_BALANCED; 53 | 54 | static void process_video_encode_hint(void *metadata); 55 | 56 | extern void interaction(int duration, int num_args, int opt_list[]); 57 | 58 | static int profile_high_performance_8952[11] = { 59 | SCHED_BOOST_ON, 60 | 0x704, 0x4d04, /* Enable all CPUs */ 61 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 62 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX, 63 | CPU4_MIN_FREQ_TURBO_MAX, CPU5_MIN_FREQ_TURBO_MAX, 64 | CPU6_MIN_FREQ_TURBO_MAX, CPU7_MIN_FREQ_TURBO_MAX, 65 | }; 66 | 67 | static int profile_power_save_8952[] = { 68 | 0x8fe, 0x3dfd, /* 1 big core, 2 little cores*/ 69 | CPUS_ONLINE_MAX_LIMIT_2, 70 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX, 71 | CPU2_MAX_FREQ_NONTURBO_MAX, CPU3_MAX_FREQ_NONTURBO_MAX, 72 | }; 73 | 74 | int get_number_of_profiles() { 75 | return 3; 76 | } 77 | 78 | static void set_power_profile(int profile) { 79 | 80 | if (profile == current_power_profile) 81 | return; 82 | 83 | ALOGV("%s: profile=%d", __func__, profile); 84 | 85 | if (current_power_profile != PROFILE_BALANCED) { 86 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 87 | ALOGV("%s: hint undone", __func__); 88 | } 89 | 90 | if (profile == PROFILE_HIGH_PERFORMANCE) { 91 | int *resource_values = profile_high_performance_8952; 92 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, resource_values, 93 | ARRAY_SIZE(resource_values)); 94 | ALOGD("%s: set performance mode", __func__); 95 | 96 | } else if (profile == PROFILE_POWER_SAVE) { 97 | int *resource_values = profile_power_save_8952; 98 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, resource_values, 99 | ARRAY_SIZE(resource_values)); 100 | ALOGD("%s: set powersave", __func__); 101 | } 102 | 103 | current_power_profile = profile; 104 | } 105 | 106 | int power_hint_override(struct power_module *module, power_hint_t hint, 107 | void *data) 108 | { 109 | int duration, duration_hint; 110 | static struct timespec s_previous_boost_timespec; 111 | struct timespec cur_boost_timespec; 112 | long long elapsed_time; 113 | int resources_launch[] = { 114 | ALL_CPUS_PWR_CLPS_DIS, 115 | SCHED_BOOST_ON, 116 | SCHED_PREFER_IDLE_DIS, 117 | 0x20f, 118 | 0x4001, 119 | 0x4101, 120 | 0x4201, 121 | }; 122 | int resources_cpu_boost[] = { 123 | ALL_CPUS_PWR_CLPS_DIS, 124 | SCHED_BOOST_ON, 125 | SCHED_PREFER_IDLE_DIS, 126 | 0x20d, 127 | }; 128 | int resources_interaction_boost[] = { 129 | SCHED_PREFER_IDLE_DIS, 130 | 0x20d, 131 | 0x3d01, 132 | }; 133 | 134 | if (hint == POWER_HINT_SET_PROFILE) { 135 | set_power_profile(*(int32_t *)data); 136 | return HINT_HANDLED; 137 | } 138 | 139 | // Skip other hints in custom power modes 140 | if (current_power_profile != PROFILE_BALANCED) { 141 | return HINT_HANDLED; 142 | } 143 | 144 | switch (hint) { 145 | case POWER_HINT_INTERACTION: 146 | duration = 500; 147 | duration_hint = 0; 148 | 149 | if (data) { 150 | duration_hint = *((int *)data); 151 | } 152 | 153 | duration = duration_hint > 0 ? duration_hint : 500; 154 | 155 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 156 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 157 | if (elapsed_time > 750000) 158 | elapsed_time = 750000; 159 | // don't hint if it's been less than 250ms since last boost 160 | // also detect if we're doing anything resembling a fling 161 | // support additional boosting in case of flings 162 | else if (elapsed_time < 250000 && duration <= 750) 163 | return HINT_HANDLED; 164 | 165 | s_previous_boost_timespec = cur_boost_timespec; 166 | 167 | if (duration >= 1500) { 168 | interaction(duration, ARRAY_SIZE(resources_cpu_boost), 169 | resources_cpu_boost); 170 | } else { 171 | interaction(duration, ARRAY_SIZE(resources_interaction_boost), 172 | resources_interaction_boost); 173 | } 174 | return HINT_HANDLED; 175 | case POWER_HINT_LAUNCH: 176 | duration = 2000; 177 | interaction(duration, ARRAY_SIZE(resources_launch), 178 | resources_launch); 179 | return HINT_HANDLED; 180 | case POWER_HINT_CPU_BOOST: 181 | duration = *(int32_t *)data / 1000; 182 | if (duration > 0) { 183 | interaction(duration, ARRAY_SIZE(resources_cpu_boost), 184 | resources_cpu_boost); 185 | } 186 | return HINT_HANDLED; 187 | case POWER_HINT_VIDEO_ENCODE: 188 | process_video_encode_hint(data); 189 | return HINT_HANDLED; 190 | } 191 | return HINT_NONE; 192 | } 193 | 194 | int set_interactive_override(struct power_module *module, int on) 195 | { 196 | char governor[80]; 197 | 198 | ALOGI("Got set_interactive hint"); 199 | 200 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) { 201 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) { 202 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) { 203 | if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) { 204 | ALOGE("Can't obtain scaling governor."); 205 | return HINT_HANDLED; 206 | } 207 | } 208 | } 209 | } 210 | 211 | if (!on) { 212 | /* Display off. */ 213 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 214 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 215 | int resource_values[] = {TR_MS_CPU0_50, TR_MS_CPU4_50}; 216 | 217 | perform_hint_action(DISPLAY_STATE_HINT_ID, 218 | resource_values, ARRAY_SIZE(resource_values)); 219 | } /* Perf time rate set for CORE0,CORE4 8952 target*/ 220 | 221 | } else { 222 | /* Display on. */ 223 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 224 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 225 | 226 | undo_hint_action(DISPLAY_STATE_HINT_ID); 227 | } 228 | } 229 | return HINT_HANDLED; 230 | } 231 | 232 | /* Video Encode Hint */ 233 | static void process_video_encode_hint(void *metadata) 234 | { 235 | char governor[80]; 236 | struct video_encode_metadata_t video_encode_metadata; 237 | 238 | ALOGI("Got process_video_encode_hint"); 239 | 240 | if (get_scaling_governor_check_cores(governor, 241 | sizeof(governor),CPU0) == -1) { 242 | if (get_scaling_governor_check_cores(governor, 243 | sizeof(governor),CPU1) == -1) { 244 | if (get_scaling_governor_check_cores(governor, 245 | sizeof(governor),CPU2) == -1) { 246 | if (get_scaling_governor_check_cores(governor, 247 | sizeof(governor),CPU3) == -1) { 248 | ALOGE("Can't obtain scaling governor."); 249 | return; 250 | } 251 | } 252 | } 253 | } 254 | 255 | /* Initialize encode metadata struct fields. */ 256 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 257 | video_encode_metadata.state = -1; 258 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 259 | 260 | if (metadata) { 261 | if (parse_video_encode_metadata((char *)metadata, 262 | &video_encode_metadata) == -1) { 263 | ALOGE("Error occurred while parsing metadata."); 264 | return; 265 | } 266 | } else { 267 | return; 268 | } 269 | 270 | if (video_encode_metadata.state == 1) { 271 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, 272 | strlen(INTERACTIVE_GOVERNOR)) == 0) && 273 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 274 | int resource_values[] = {TR_MS_CPU0_30, TR_MS_CPU4_30}; 275 | if (!video_encode_hint_sent) { 276 | perform_hint_action(video_encode_metadata.hint_id, 277 | resource_values, 278 | ARRAY_SIZE(resource_values)); 279 | video_encode_hint_sent = 1; 280 | } 281 | } 282 | } else if (video_encode_metadata.state == 0) { 283 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, 284 | strlen(INTERACTIVE_GOVERNOR)) == 0) && 285 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 286 | undo_hint_action(video_encode_metadata.hint_id); 287 | video_encode_hint_sent = 0; 288 | return ; 289 | } 290 | } 291 | return; 292 | } 293 | -------------------------------------------------------------------------------- /power/power-8960.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 | * Copyright (c) 2015, The CyanogenMod Project 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following 12 | * disclaimer in the documentation and/or other materials provided 13 | * with the distribution. 14 | * * Neither the name of The Linux Foundation nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QCOM PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | static int current_power_profile = PROFILE_BALANCED; 52 | 53 | int get_number_of_profiles() { 54 | return 3; 55 | } 56 | 57 | /** 58 | * If target is 8064: 59 | * return 1 60 | * else: 61 | * return 0 62 | */ 63 | static int is_target_8064(void) 64 | { 65 | static int is_8064 = -1; 66 | int soc_id; 67 | 68 | if (is_8064 >= 0) 69 | return is_8064; 70 | 71 | soc_id = get_soc_id(); 72 | if (soc_id == 153) 73 | is_8064 = 1; 74 | else 75 | is_8064 = 0; 76 | 77 | return is_8064; 78 | } 79 | 80 | static int profile_high_performance_8960[] = { 81 | CPUS_ONLINE_MIN_2, 82 | }; 83 | 84 | static int profile_high_performance_8064[] = { 85 | CPUS_ONLINE_MIN_4, 86 | }; 87 | 88 | static int profile_power_save_8960[] = { 89 | /* Don't do anything for now */ 90 | }; 91 | 92 | static int profile_power_save_8064[] = { 93 | CPUS_ONLINE_MAX_LIMIT_2, 94 | }; 95 | 96 | static void set_power_profile(int profile) { 97 | 98 | if (profile == current_power_profile) 99 | return; 100 | 101 | ALOGV("%s: profile=%d", __func__, profile); 102 | 103 | if (current_power_profile != PROFILE_BALANCED) { 104 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 105 | ALOGV("%s: hint undone", __func__); 106 | } 107 | 108 | if (profile == PROFILE_HIGH_PERFORMANCE) { 109 | int *resource_values = is_target_8064() ? 110 | profile_high_performance_8064 : profile_high_performance_8960; 111 | 112 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 113 | resource_values, ARRAY_SIZE(resource_values)); 114 | ALOGD("%s: set performance mode", __func__); 115 | } else if (profile == PROFILE_POWER_SAVE) { 116 | int* resource_values = is_target_8064() ? 117 | profile_power_save_8064 : profile_power_save_8960; 118 | 119 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 120 | resource_values, ARRAY_SIZE(resource_values)); 121 | ALOGD("%s: set powersave", __func__); 122 | } 123 | 124 | current_power_profile = profile; 125 | } 126 | 127 | int power_hint_override(__attribute__((unused)) struct power_module *module, 128 | power_hint_t hint, void *data) 129 | { 130 | if (hint == POWER_HINT_SET_PROFILE) { 131 | set_power_profile(*(int32_t *)data); 132 | return HINT_HANDLED; 133 | } 134 | 135 | /* Skip other hints in power save mode */ 136 | if (current_power_profile == PROFILE_POWER_SAVE) { 137 | return HINT_HANDLED; 138 | } 139 | 140 | return HINT_NONE; 141 | } 142 | -------------------------------------------------------------------------------- /power/power-8974.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 | * Copyright (c) 2014, The CyanogenMod Project 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following 12 | * disclaimer in the documentation and/or other materials provided 13 | * with the distribution. 14 | * * Neither the name of The Linux Foundation nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #define LOG_NIDEBUG 0 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define LOG_TAG "QCOM PowerHAL" 41 | #include 42 | #include 43 | #include 44 | 45 | #include "utils.h" 46 | #include "metadata-defs.h" 47 | #include "hint-data.h" 48 | #include "performance.h" 49 | #include "power-common.h" 50 | 51 | static int first_display_off_hint; 52 | 53 | static int current_power_profile = PROFILE_BALANCED; 54 | 55 | int get_number_of_profiles() { 56 | return 5; 57 | } 58 | 59 | /** 60 | * If target is 8974pro: 61 | * return 1 62 | * else: 63 | * return 0 64 | */ 65 | static int is_target_8974pro(void) 66 | { 67 | static int is_8974pro = -1; 68 | int soc_id; 69 | 70 | if (is_8974pro >= 0) 71 | return is_8974pro; 72 | 73 | soc_id = get_soc_id(); 74 | if (soc_id == 194 || (soc_id >= 208 && soc_id <= 218)) 75 | is_8974pro = 1; 76 | else 77 | is_8974pro = 0; 78 | 79 | return is_8974pro; 80 | } 81 | 82 | static void set_power_profile(int profile) { 83 | 84 | if (profile == current_power_profile) 85 | return; 86 | 87 | ALOGV("%s: profile=%d", __func__, profile); 88 | 89 | if (current_power_profile != PROFILE_BALANCED) { 90 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 91 | ALOGV("%s: hint undone", __func__); 92 | } 93 | 94 | if (profile == PROFILE_HIGH_PERFORMANCE) { 95 | int resource_values[] = { CPUS_ONLINE_MIN_4, 0x0901, 96 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 97 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX }; 98 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 99 | resource_values, ARRAY_SIZE(resource_values)); 100 | ALOGD("%s: set performance mode", __func__); 101 | } else if (profile == PROFILE_BIAS_PERFORMANCE) { 102 | int resource_values[] = { 103 | CPU0_MIN_FREQ_NONTURBO_MAX + 1, CPU1_MIN_FREQ_NONTURBO_MAX + 1, 104 | CPU2_MIN_FREQ_NONTURBO_MAX + 1, CPU2_MIN_FREQ_NONTURBO_MAX + 1 }; 105 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 106 | resource_values, ARRAY_SIZE(resource_values)); 107 | ALOGD("%s: set bias perf mode", __func__); 108 | } else if (profile == PROFILE_BIAS_POWER) { 109 | int resource_values[] = { 0x0A03, 110 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX, 111 | CPU1_MAX_FREQ_NONTURBO_MAX, CPU2_MAX_FREQ_NONTURBO_MAX }; 112 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 113 | resource_values, ARRAY_SIZE(resource_values)); 114 | ALOGD("%s: set bias power mode", __func__); 115 | } else if (profile == PROFILE_POWER_SAVE) { 116 | int resource_values[] = { 0x0A03, CPUS_ONLINE_MAX_LIMIT_2, 117 | CPU0_MAX_FREQ_NONTURBO_MAX, CPU1_MAX_FREQ_NONTURBO_MAX, 118 | CPU2_MAX_FREQ_NONTURBO_MAX, CPU3_MAX_FREQ_NONTURBO_MAX }; 119 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 120 | resource_values, ARRAY_SIZE(resource_values)); 121 | ALOGD("%s: set powersave", __func__); 122 | } 123 | 124 | current_power_profile = profile; 125 | } 126 | 127 | extern void interaction(int duration, int num_args, int opt_list[]); 128 | 129 | int power_hint_override(__attribute__((unused)) struct power_module *module, 130 | power_hint_t hint, void *data) 131 | { 132 | if (hint == POWER_HINT_SET_PROFILE) { 133 | set_power_profile(*(int32_t *)data); 134 | return HINT_HANDLED; 135 | } 136 | 137 | // Skip other hints in high/low power modes 138 | if (current_power_profile == PROFILE_POWER_SAVE || 139 | current_power_profile == PROFILE_HIGH_PERFORMANCE) { 140 | return HINT_HANDLED; 141 | } 142 | 143 | if (hint == POWER_HINT_LAUNCH) { 144 | int duration = 2000; 145 | int resources[] = { CPUS_ONLINE_MIN_3, 146 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 147 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX }; 148 | 149 | interaction(duration, ARRAY_SIZE(resources), resources); 150 | 151 | return HINT_HANDLED; 152 | } 153 | 154 | if (hint == POWER_HINT_CPU_BOOST) { 155 | int duration = *(int32_t *)data / 1000; 156 | int resources[] = { CPUS_ONLINE_MIN_2, 157 | 0x20F, 0x30F, 0x40F, 0x50F }; 158 | 159 | if (duration) 160 | interaction(duration, ARRAY_SIZE(resources), resources); 161 | 162 | return HINT_HANDLED; 163 | } 164 | 165 | if (hint == POWER_HINT_INTERACTION) { 166 | int duration = 500, duration_hint = 0; 167 | static struct timespec s_previous_boost_timespec; 168 | struct timespec cur_boost_timespec; 169 | long long elapsed_time; 170 | 171 | if (data) { 172 | duration_hint = *((int *)data); 173 | } 174 | 175 | duration = duration_hint > 0 ? duration_hint : 500; 176 | 177 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 178 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 179 | if (elapsed_time > 750000) 180 | elapsed_time = 750000; 181 | // don't hint if it's been less than 250ms since last boost 182 | // also detect if we're doing anything resembling a fling 183 | // support additional boosting in case of flings 184 | else if (elapsed_time < 250000 && duration <= 750) 185 | return HINT_HANDLED; 186 | 187 | s_previous_boost_timespec = cur_boost_timespec; 188 | 189 | int resources[] = { (duration >= 2000 ? CPUS_ONLINE_MIN_3 : CPUS_ONLINE_MIN_2), 190 | 0x20F, 0x30F, 0x40F, 0x50F }; 191 | 192 | if (duration) 193 | interaction(duration, ARRAY_SIZE(resources), resources); 194 | 195 | return HINT_HANDLED; 196 | } 197 | 198 | 199 | return HINT_NONE; 200 | } 201 | 202 | int set_interactive_override(struct power_module *module __unused, int on) 203 | { 204 | char governor[80]; 205 | 206 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 207 | ALOGE("Can't obtain scaling governor."); 208 | 209 | return HINT_NONE; 210 | } 211 | 212 | if (!on) { 213 | /* Display off. */ 214 | /* 215 | * We need to be able to identify the first display off hint 216 | * and release the current lock holder 217 | */ 218 | if (is_target_8974pro()) { 219 | if (!first_display_off_hint) { 220 | undo_initial_hint_action(); 221 | first_display_off_hint = 1; 222 | } 223 | /* used for all subsequent toggles to the display */ 224 | undo_hint_action(DISPLAY_STATE_HINT_ID_2); 225 | } 226 | 227 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 228 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 229 | int resource_values[] = {MS_500, SYNC_FREQ_600, OPTIMAL_FREQ_600, THREAD_MIGRATION_SYNC_OFF}; 230 | 231 | perform_hint_action(DISPLAY_STATE_HINT_ID, 232 | resource_values, ARRAY_SIZE(resource_values)); 233 | 234 | return HINT_HANDLED; 235 | } 236 | } else { 237 | /* Display on */ 238 | if (is_target_8974pro()) { 239 | int resource_values2[] = {CPUS_ONLINE_MIN_2}; 240 | perform_hint_action(DISPLAY_STATE_HINT_ID_2, 241 | resource_values2, ARRAY_SIZE(resource_values2)); 242 | } 243 | 244 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 245 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 246 | undo_hint_action(DISPLAY_STATE_HINT_ID); 247 | 248 | return HINT_HANDLED; 249 | } 250 | } 251 | 252 | return HINT_NONE; 253 | } 254 | -------------------------------------------------------------------------------- /power/power-8992.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "QCOM PowerHAL" 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | #include "metadata-defs.h" 46 | #include "hint-data.h" 47 | #include "performance.h" 48 | #include "power-common.h" 49 | 50 | int get_number_of_profiles() { 51 | return 5; 52 | } 53 | 54 | static int current_power_profile = PROFILE_BALANCED; 55 | 56 | static void set_power_profile(int profile) { 57 | 58 | if (profile == current_power_profile) 59 | return; 60 | 61 | ALOGV("%s: profile=%d", __func__, profile); 62 | 63 | if (current_power_profile != PROFILE_BALANCED) { 64 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 65 | ALOGV("%s: hint undone", __func__); 66 | } 67 | 68 | if (profile == PROFILE_POWER_SAVE) { 69 | int resource_values[] = { CPUS_ONLINE_MPD_OVERRIDE, 0x0A03, 70 | CPU0_MAX_FREQ_NONTURBO_MAX - 2, CPU1_MAX_FREQ_NONTURBO_MAX - 2, 71 | CPU2_MAX_FREQ_NONTURBO_MAX - 2, CPU3_MAX_FREQ_NONTURBO_MAX - 2, 72 | CPU4_MAX_FREQ_NONTURBO_MAX - 2, CPU5_MAX_FREQ_NONTURBO_MAX - 2 }; 73 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 74 | resource_values, ARRAY_SIZE(resource_values)); 75 | ALOGD("%s: set powersave", __func__); 76 | } else if (profile == PROFILE_HIGH_PERFORMANCE) { 77 | int resource_values[] = { SCHED_BOOST_ON, CPUS_ONLINE_MAX, 78 | ALL_CPUS_PWR_CLPS_DIS, 0x0901, 79 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 80 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX, 81 | CPU4_MIN_FREQ_TURBO_MAX, CPU5_MIN_FREQ_TURBO_MAX }; 82 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 83 | resource_values, ARRAY_SIZE(resource_values)); 84 | ALOGD("%s: set performance mode", __func__); 85 | } else if (profile == PROFILE_BIAS_POWER) { 86 | int resource_values[] = { 0x0A03, 0x0902, 87 | CPU0_MAX_FREQ_NONTURBO_MAX - 2, CPU1_MAX_FREQ_NONTURBO_MAX - 2, 88 | CPU1_MAX_FREQ_NONTURBO_MAX - 2, CPU2_MAX_FREQ_NONTURBO_MAX - 2, 89 | CPU4_MAX_FREQ_NONTURBO_MAX, CPU5_MAX_FREQ_NONTURBO_MAX }; 90 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 91 | resource_values, ARRAY_SIZE(resource_values)); 92 | ALOGD("%s: set bias power mode", __func__); 93 | } else if (profile == PROFILE_BIAS_PERFORMANCE) { 94 | int resource_values[] = { CPUS_ONLINE_MAX_LIMIT_MAX, 95 | CPU4_MIN_FREQ_NONTURBO_MAX + 1, CPU5_MIN_FREQ_NONTURBO_MAX + 1 }; 96 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 97 | resource_values, ARRAY_SIZE(resource_values)); 98 | ALOGD("%s: set bias perf mode", __func__); 99 | } 100 | 101 | current_power_profile = profile; 102 | } 103 | 104 | extern void interaction(int duration, int num_args, int opt_list[]); 105 | 106 | static int process_video_encode_hint(void *metadata) 107 | { 108 | char governor[80]; 109 | struct video_encode_metadata_t video_encode_metadata; 110 | 111 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 112 | ALOGE("Can't obtain scaling governor."); 113 | 114 | return HINT_NONE; 115 | } 116 | 117 | /* Initialize encode metadata struct fields */ 118 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 119 | video_encode_metadata.state = -1; 120 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 121 | 122 | if (metadata) { 123 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 124 | -1) { 125 | ALOGE("Error occurred while parsing metadata."); 126 | return HINT_NONE; 127 | } 128 | } else { 129 | return HINT_NONE; 130 | } 131 | 132 | if (video_encode_metadata.state == 1) { 133 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 134 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 135 | /* sched and cpufreq params 136 | * hispeed freq - 768 MHz 137 | * target load - 90 138 | * above_hispeed_delay - 40ms 139 | * sched_small_tsk - 50 140 | */ 141 | int resource_values[] = {0x2C07, 0x2F5A, 0x2704, 0x4032}; 142 | 143 | perform_hint_action(video_encode_metadata.hint_id, 144 | resource_values, ARRAY_SIZE(resource_values)); 145 | return HINT_HANDLED; 146 | } 147 | } else if (video_encode_metadata.state == 0) { 148 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 149 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 150 | undo_hint_action(video_encode_metadata.hint_id); 151 | return HINT_HANDLED; 152 | } 153 | } 154 | return HINT_NONE; 155 | } 156 | 157 | int power_hint_override(__attribute__((unused)) struct power_module *module, 158 | power_hint_t hint, void *data) 159 | { 160 | if (hint == POWER_HINT_SET_PROFILE) { 161 | set_power_profile(*(int32_t *)data); 162 | return HINT_HANDLED; 163 | } 164 | 165 | // Skip other hints in custom power modes 166 | if (current_power_profile == PROFILE_POWER_SAVE) { 167 | return HINT_HANDLED; 168 | } 169 | 170 | if (hint == POWER_HINT_INTERACTION) { 171 | int duration = 500, duration_hint = 0; 172 | static struct timespec s_previous_boost_timespec; 173 | struct timespec cur_boost_timespec; 174 | long long elapsed_time; 175 | 176 | if (data) { 177 | duration_hint = *((int *)data); 178 | } 179 | 180 | duration = duration_hint > 0 ? duration_hint : 500; 181 | 182 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 183 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 184 | if (elapsed_time > 750000) 185 | elapsed_time = 750000; 186 | // don't hint if it's been less than 250ms since last boost 187 | // also detect if we're doing anything resembling a fling 188 | // support additional boosting in case of flings 189 | else if (elapsed_time < 250000 && duration <= 750) 190 | return HINT_HANDLED; 191 | 192 | s_previous_boost_timespec = cur_boost_timespec; 193 | 194 | if (duration >= 1500) { 195 | int resources[] = { 196 | ALL_CPUS_PWR_CLPS_DIS, 197 | SCHED_BOOST_ON, 198 | SCHED_PREFER_IDLE_DIS 199 | }; 200 | interaction(duration, ARRAY_SIZE(resources), resources); 201 | } else { 202 | int resources[] = { 203 | ALL_CPUS_PWR_CLPS_DIS, 204 | SCHED_PREFER_IDLE_DIS 205 | }; 206 | interaction(duration, ARRAY_SIZE(resources), resources); 207 | } 208 | return HINT_HANDLED; 209 | } 210 | 211 | if (hint == POWER_HINT_LAUNCH) { 212 | int duration = 2000; 213 | int resources[] = { SCHED_BOOST_ON, 0x20C }; 214 | 215 | interaction(duration, ARRAY_SIZE(resources), resources); 216 | 217 | return HINT_HANDLED; 218 | } 219 | 220 | if (hint == POWER_HINT_CPU_BOOST) { 221 | int duration = *(int32_t *)data / 1000; 222 | int resources[] = { SCHED_BOOST_ON }; 223 | 224 | if (duration > 0) 225 | interaction(duration, ARRAY_SIZE(resources), resources); 226 | 227 | return HINT_HANDLED; 228 | } 229 | 230 | if (hint == POWER_HINT_VIDEO_ENCODE) { 231 | return process_video_encode_hint(data); 232 | } 233 | 234 | return HINT_NONE; 235 | } 236 | 237 | int set_interactive_override(__attribute__((unused)) struct power_module *module, int on) 238 | { 239 | char governor[80]; 240 | 241 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 242 | ALOGE("Can't obtain scaling governor."); 243 | 244 | return HINT_NONE; 245 | } 246 | 247 | if (!on) { 248 | /* Display off */ 249 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 250 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 251 | // sched upmigrate = 99, sched downmigrate = 95 252 | // keep the big cores around, but make them very hard to use 253 | int resource_values[] = { 0x4E63, 0x4F5F }; 254 | perform_hint_action(DISPLAY_STATE_HINT_ID, 255 | resource_values, ARRAY_SIZE(resource_values)); 256 | return HINT_HANDLED; 257 | } 258 | } else { 259 | /* Display on */ 260 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 261 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 262 | undo_hint_action(DISPLAY_STATE_HINT_ID); 263 | return HINT_HANDLED; 264 | } 265 | } 266 | return HINT_NONE; 267 | } 268 | -------------------------------------------------------------------------------- /power/power-8994.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "QCOM PowerHAL" 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | #include "metadata-defs.h" 46 | #include "hint-data.h" 47 | #include "performance.h" 48 | #include "power-common.h" 49 | 50 | int get_number_of_profiles() { 51 | return 5; 52 | } 53 | 54 | static int current_power_profile = PROFILE_BALANCED; 55 | 56 | static void set_power_profile(int profile) { 57 | 58 | if (profile == current_power_profile) 59 | return; 60 | 61 | ALOGV("%s: profile=%d", __func__, profile); 62 | 63 | if (current_power_profile != PROFILE_BALANCED) { 64 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 65 | ALOGV("%s: hint undone", __func__); 66 | } 67 | 68 | if (profile == PROFILE_POWER_SAVE) { 69 | int resource_values[] = { CPUS_ONLINE_MPD_OVERRIDE, 0x0A03, 70 | CPU0_MAX_FREQ_NONTURBO_MAX - 2, CPU1_MAX_FREQ_NONTURBO_MAX - 2, 71 | CPU2_MAX_FREQ_NONTURBO_MAX - 2, CPU3_MAX_FREQ_NONTURBO_MAX - 2, 72 | CPU4_MAX_FREQ_NONTURBO_MAX - 2, CPU5_MAX_FREQ_NONTURBO_MAX - 2, 73 | CPU6_MAX_FREQ_NONTURBO_MAX - 2, CPU7_MAX_FREQ_NONTURBO_MAX - 2 }; 74 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 75 | resource_values, ARRAY_SIZE(resource_values)); 76 | ALOGD("%s: set powersave", __func__); 77 | } else if (profile == PROFILE_HIGH_PERFORMANCE) { 78 | int resource_values[] = { SCHED_BOOST_ON, CPUS_ONLINE_MAX, 79 | ALL_CPUS_PWR_CLPS_DIS, 0x0901, 80 | CPU0_MIN_FREQ_TURBO_MAX, CPU1_MIN_FREQ_TURBO_MAX, 81 | CPU2_MIN_FREQ_TURBO_MAX, CPU3_MIN_FREQ_TURBO_MAX, 82 | CPU4_MIN_FREQ_TURBO_MAX, CPU5_MIN_FREQ_TURBO_MAX, 83 | CPU6_MIN_FREQ_TURBO_MAX, CPU7_MIN_FREQ_TURBO_MAX }; 84 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 85 | resource_values, ARRAY_SIZE(resource_values)); 86 | ALOGD("%s: set performance mode", __func__); 87 | } else if (profile == PROFILE_BIAS_POWER) { 88 | int resource_values[] = { 0x0A03, 0x0902, 89 | CPU0_MAX_FREQ_NONTURBO_MAX - 2, CPU1_MAX_FREQ_NONTURBO_MAX - 2, 90 | CPU1_MAX_FREQ_NONTURBO_MAX - 2, CPU2_MAX_FREQ_NONTURBO_MAX - 2, 91 | CPU4_MAX_FREQ_NONTURBO_MAX, CPU5_MAX_FREQ_NONTURBO_MAX, 92 | CPU6_MAX_FREQ_NONTURBO_MAX, CPU7_MAX_FREQ_NONTURBO_MAX }; 93 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 94 | resource_values, ARRAY_SIZE(resource_values)); 95 | ALOGD("%s: set bias power mode", __func__); 96 | } else if (profile == PROFILE_BIAS_PERFORMANCE) { 97 | int resource_values[] = { CPUS_ONLINE_MAX_LIMIT_MAX, 98 | CPU4_MIN_FREQ_NONTURBO_MAX + 1, CPU5_MIN_FREQ_NONTURBO_MAX + 1, 99 | CPU6_MIN_FREQ_NONTURBO_MAX + 1, CPU7_MIN_FREQ_NONTURBO_MAX + 1 }; 100 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, 101 | resource_values, ARRAY_SIZE(resource_values)); 102 | ALOGD("%s: set bias perf mode", __func__); 103 | } 104 | 105 | current_power_profile = profile; 106 | } 107 | 108 | extern void interaction(int duration, int num_args, int opt_list[]); 109 | 110 | #ifdef __LP64__ 111 | typedef int64_t hintdata; 112 | #else 113 | typedef int hintdata; 114 | #endif 115 | 116 | static int process_video_encode_hint(void *metadata) 117 | { 118 | char governor[80]; 119 | struct video_encode_metadata_t video_encode_metadata; 120 | 121 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 122 | ALOGE("Can't obtain scaling governor."); 123 | 124 | return HINT_NONE; 125 | } 126 | 127 | /* Initialize encode metadata struct fields */ 128 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 129 | video_encode_metadata.state = -1; 130 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 131 | 132 | if (metadata) { 133 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 134 | -1) { 135 | ALOGE("Error occurred while parsing metadata."); 136 | return HINT_NONE; 137 | } 138 | } else { 139 | return HINT_NONE; 140 | } 141 | 142 | if (video_encode_metadata.state == 1) { 143 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 144 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 145 | /* sched and cpufreq params 146 | * hispeed freq - 768 MHz 147 | * target load - 90 148 | * above_hispeed_delay - 40ms 149 | * sched_small_tsk - 50 150 | */ 151 | int resource_values[] = {0x2C07, 0x2F5A, 0x2704, 0x4032}; 152 | 153 | perform_hint_action(video_encode_metadata.hint_id, 154 | resource_values, ARRAY_SIZE(resource_values)); 155 | return HINT_HANDLED; 156 | } 157 | } else if (video_encode_metadata.state == 0) { 158 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 159 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 160 | undo_hint_action(video_encode_metadata.hint_id); 161 | return HINT_HANDLED; 162 | } 163 | } 164 | return HINT_NONE; 165 | } 166 | 167 | int power_hint_override(__attribute__((unused)) struct power_module *module, 168 | power_hint_t hint, void *data) 169 | { 170 | if (hint == POWER_HINT_SET_PROFILE) { 171 | set_power_profile(*(int32_t *)data); 172 | return HINT_HANDLED; 173 | } 174 | 175 | // Skip other hints in custom power modes 176 | if (current_power_profile == PROFILE_POWER_SAVE) { 177 | return HINT_HANDLED; 178 | } 179 | 180 | if (hint == POWER_HINT_INTERACTION) { 181 | int duration = 500, duration_hint = 0; 182 | static struct timespec s_previous_boost_timespec; 183 | struct timespec cur_boost_timespec; 184 | long long elapsed_time; 185 | 186 | if (data) { 187 | duration_hint = *((int *)data); 188 | } 189 | 190 | duration = duration_hint > 0 ? duration_hint : 500; 191 | 192 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 193 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 194 | if (elapsed_time > 750000) 195 | elapsed_time = 750000; 196 | // don't hint if it's been less than 250ms since last boost 197 | // also detect if we're doing anything resembling a fling 198 | // support additional boosting in case of flings 199 | else if (elapsed_time < 250000 && duration <= 750) 200 | return HINT_HANDLED; 201 | 202 | s_previous_boost_timespec = cur_boost_timespec; 203 | 204 | if (duration >= 1500) { 205 | int resources[] = { 206 | ALL_CPUS_PWR_CLPS_DIS, 207 | SCHED_BOOST_ON, 208 | SCHED_PREFER_IDLE_DIS 209 | }; 210 | interaction(duration, ARRAY_SIZE(resources), resources); 211 | } else { 212 | int resources[] = { 213 | ALL_CPUS_PWR_CLPS_DIS, 214 | SCHED_PREFER_IDLE_DIS 215 | }; 216 | interaction(duration, ARRAY_SIZE(resources), resources); 217 | } 218 | return HINT_HANDLED; 219 | } 220 | 221 | if (hint == POWER_HINT_LAUNCH) { 222 | int duration = 2000; 223 | int resources[] = { SCHED_BOOST_ON, 0x20C }; 224 | 225 | interaction(duration, ARRAY_SIZE(resources), resources); 226 | 227 | return HINT_HANDLED; 228 | } 229 | 230 | if (hint == POWER_HINT_CPU_BOOST) { 231 | int duration = *(int32_t *)data / 1000; 232 | int resources[] = { SCHED_BOOST_ON }; 233 | 234 | if (duration > 0) 235 | interaction(duration, ARRAY_SIZE(resources), resources); 236 | 237 | return HINT_HANDLED; 238 | } 239 | 240 | if (hint == POWER_HINT_VIDEO_ENCODE) { 241 | return process_video_encode_hint(data); 242 | } 243 | 244 | return HINT_NONE; 245 | } 246 | 247 | int set_interactive_override(__attribute__((unused)) struct power_module *module, int on) 248 | { 249 | char governor[80]; 250 | 251 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 252 | ALOGE("Can't obtain scaling governor."); 253 | 254 | return HINT_NONE; 255 | } 256 | 257 | if (!on) { 258 | /* Display off */ 259 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 260 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 261 | // sched upmigrate = 99, sched downmigrate = 95 262 | // keep the big cores around, but make them very hard to use 263 | int resource_values[] = { 0x4E63, 0x4F5F }; 264 | perform_hint_action(DISPLAY_STATE_HINT_ID, 265 | resource_values, ARRAY_SIZE(resource_values)); 266 | return HINT_HANDLED; 267 | } 268 | } else { 269 | /* Display on */ 270 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 271 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 272 | undo_hint_action(DISPLAY_STATE_HINT_ID); 273 | return HINT_HANDLED; 274 | } 275 | } 276 | return HINT_NONE; 277 | } 278 | -------------------------------------------------------------------------------- /power/power-8996.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "QCOM PowerHAL" 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | #include "metadata-defs.h" 46 | #include "hint-data.h" 47 | #include "performance.h" 48 | #include "power-common.h" 49 | 50 | static int current_power_profile = PROFILE_BALANCED; 51 | 52 | extern void interaction(int duration, int num_args, int opt_list[]); 53 | 54 | int get_number_of_profiles() { 55 | return 5; 56 | } 57 | 58 | static int profile_high_performance[] = { 59 | SCHED_BOOST_ON_V3, 0x1, 60 | ALL_CPUS_PWR_CLPS_DIS_V3, 0x1, 61 | CPUS_ONLINE_MIN_BIG, 0x2, 62 | CPUS_ONLINE_MIN_LITTLE, 0x2, 63 | MIN_FREQ_BIG_CORE_0, 0xFFF, 64 | MIN_FREQ_LITTLE_CORE_0, 0xFFF, 65 | }; 66 | 67 | static int profile_power_save[] = { 68 | CPUS_ONLINE_MAX_LIMIT_BIG, 0x1, 69 | MAX_FREQ_BIG_CORE_0, 0x3E8, 70 | MAX_FREQ_LITTLE_CORE_0, 0x3E8, 71 | }; 72 | 73 | static int profile_bias_power[] = { 74 | MAX_FREQ_BIG_CORE_0, 0x514, 75 | MAX_FREQ_LITTLE_CORE_0, 0x3E8, 76 | }; 77 | 78 | static int profile_bias_performance[] = { 79 | CPUS_ONLINE_MAX_LIMIT_BIG, 0x2, 80 | CPUS_ONLINE_MAX_LIMIT_LITTLE, 0x2, 81 | MIN_FREQ_BIG_CORE_0, 0x578, 82 | }; 83 | 84 | static void set_power_profile(int profile) { 85 | 86 | if (profile == current_power_profile) 87 | return; 88 | 89 | ALOGV("%s: Profile=%d", __func__, profile); 90 | 91 | if (current_power_profile != PROFILE_BALANCED) { 92 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 93 | ALOGV("%s: Hint undone", __func__); 94 | } 95 | 96 | if (profile == PROFILE_POWER_SAVE) { 97 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save, 98 | ARRAY_SIZE(profile_power_save)); 99 | ALOGD("%s: Set powersave mode", __func__); 100 | 101 | } else if (profile == PROFILE_HIGH_PERFORMANCE) { 102 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_high_performance, 103 | ARRAY_SIZE(profile_high_performance)); 104 | ALOGD("%s: Set performance mode", __func__); 105 | 106 | } else if (profile == PROFILE_BIAS_POWER) { 107 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_power, 108 | ARRAY_SIZE(profile_bias_power)); 109 | ALOGD("%s: Set bias power mode", __func__); 110 | 111 | } else if (profile == PROFILE_BIAS_PERFORMANCE) { 112 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_performance, 113 | ARRAY_SIZE(profile_bias_performance)); 114 | ALOGD("%s: Set bias perf mode", __func__); 115 | 116 | } 117 | 118 | current_power_profile = profile; 119 | } 120 | 121 | static int process_video_encode_hint(void *metadata) 122 | { 123 | char governor[80]; 124 | struct video_encode_metadata_t video_encode_metadata; 125 | 126 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 127 | ALOGE("Can't obtain scaling governor."); 128 | 129 | return HINT_NONE; 130 | } 131 | 132 | /* Initialize encode metadata struct fields */ 133 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 134 | video_encode_metadata.state = -1; 135 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 136 | 137 | if (metadata) { 138 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 139 | -1) { 140 | ALOGE("Error occurred while parsing metadata."); 141 | return HINT_NONE; 142 | } 143 | } else { 144 | return HINT_NONE; 145 | } 146 | 147 | if (video_encode_metadata.state == 1) { 148 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 149 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 150 | /* 1. cpufreq params 151 | * -above_hispeed_delay for LVT - 40ms 152 | * -go hispeed load for LVT - 95 153 | * -hispeed freq for LVT - 556 MHz 154 | * -target load for LVT - 90 155 | * -above hispeed delay for sLVT - 40ms 156 | * -go hispeed load for sLVT - 95 157 | * -hispeed freq for sLVT - 806 MHz 158 | * -target load for sLVT - 90 159 | * 2. bus DCVS set to V2 config: 160 | * -low power ceil mpbs - 2500 161 | * -low power io percent - 50 162 | * 3. hysteresis optimization 163 | * -bus dcvs hysteresis tuning 164 | * -sample_ms of 10 ms 165 | */ 166 | int resource_values[] = { 167 | ABOVE_HISPEED_DELAY_BIG, 0x4, 168 | GO_HISPEED_LOAD_BIG, 0x5F, 169 | HISPEED_FREQ_BIG, 0x326, 170 | TARGET_LOADS_BIG, 0x5A, 171 | ABOVE_HISPEED_DELAY_LITTLE, 0x4, 172 | GO_HISPEED_LOAD_LITTLE, 0x5F, 173 | HISPEED_FREQ_LITTLE, 0x22C, 174 | TARGET_LOADS_LITTLE, 0x5A, 175 | LOW_POWER_CEIL_MBPS, 0x9C4, 176 | LOW_POWER_IO_PERCENT, 0x32, 177 | CPUBW_HWMON_V1, 0x0, 178 | CPUBW_HWMON_SAMPLE_MS, 0xA, 179 | }; 180 | 181 | perform_hint_action(video_encode_metadata.hint_id, 182 | resource_values, ARRAY_SIZE(resource_values)); 183 | ALOGI("Video Encode hint start"); 184 | return HINT_HANDLED; 185 | } 186 | } else if (video_encode_metadata.state == 0) { 187 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 188 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 189 | undo_hint_action(video_encode_metadata.hint_id); 190 | ALOGI("Video Encode hint stop"); 191 | return HINT_HANDLED; 192 | } 193 | } 194 | return HINT_NONE; 195 | } 196 | 197 | int power_hint_override(__unused struct power_module *module, 198 | power_hint_t hint, void *data) 199 | { 200 | static struct timespec s_previous_boost_timespec; 201 | struct timespec cur_boost_timespec; 202 | long long elapsed_time; 203 | int duration; 204 | 205 | int resources_launch[] = { 206 | SCHED_BOOST_ON_V3, 0x1, 207 | MAX_FREQ_BIG_CORE_0, 0xFFF, 208 | MAX_FREQ_LITTLE_CORE_0, 0xFFF, 209 | MIN_FREQ_BIG_CORE_0, 0xFFF, 210 | MIN_FREQ_LITTLE_CORE_0, 0xFFF, 211 | CPUBW_HWMON_MIN_FREQ, 0x8C, 212 | ALL_CPUS_PWR_CLPS_DIS_V3, 0x1, 213 | STOR_CLK_SCALE_DIS, 0x1, 214 | }; 215 | 216 | int resources_cpu_boost[] = { 217 | SCHED_BOOST_ON_V3, 0x1, 218 | MIN_FREQ_BIG_CORE_0, 0x3E8, 219 | }; 220 | 221 | int resources_interaction_fling_boost[] = { 222 | CPUBW_HWMON_MIN_FREQ, 0x33, 223 | MIN_FREQ_BIG_CORE_0, 0x3E8, 224 | MIN_FREQ_LITTLE_CORE_0, 0x3E8, 225 | SCHED_BOOST_ON_V3, 0x1, 226 | // SCHED_GROUP_ON, 0x1, 227 | }; 228 | 229 | int resources_interaction_boost[] = { 230 | MIN_FREQ_BIG_CORE_0, 0x3E8, 231 | }; 232 | 233 | if (hint == POWER_HINT_SET_PROFILE) { 234 | set_power_profile(*(int32_t *)data); 235 | return HINT_HANDLED; 236 | } 237 | 238 | /* Skip other hints in power save mode */ 239 | if (current_power_profile == PROFILE_POWER_SAVE) 240 | return HINT_HANDLED; 241 | 242 | if (hint == POWER_HINT_INTERACTION) { 243 | duration = data ? *((int *)data) : 500; 244 | 245 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 246 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 247 | if (elapsed_time > 750000) 248 | elapsed_time = 750000; 249 | /** 250 | * Don't hint if it's been less than 250ms since last boost 251 | * also detect if we're doing anything resembling a fling 252 | * support additional boosting in case of flings 253 | */ 254 | else if (elapsed_time < 250000 && duration <= 750) 255 | return HINT_HANDLED; 256 | 257 | s_previous_boost_timespec = cur_boost_timespec; 258 | 259 | if (duration >= 1500) { 260 | interaction(duration, ARRAY_SIZE(resources_interaction_fling_boost), 261 | resources_interaction_fling_boost); 262 | } else { 263 | interaction(duration, ARRAY_SIZE(resources_interaction_boost), 264 | resources_interaction_boost); 265 | } 266 | return HINT_HANDLED; 267 | } 268 | 269 | if (hint == POWER_HINT_LAUNCH) { 270 | duration = 2000; 271 | 272 | interaction(duration, ARRAY_SIZE(resources_launch), 273 | resources_launch); 274 | return HINT_HANDLED; 275 | } 276 | 277 | if (hint == POWER_HINT_CPU_BOOST) { 278 | duration = *(int32_t *)data / 1000; 279 | if (duration > 0) { 280 | interaction(duration, ARRAY_SIZE(resources_cpu_boost), 281 | resources_cpu_boost); 282 | return HINT_HANDLED; 283 | } 284 | } 285 | 286 | if (hint == POWER_HINT_VIDEO_ENCODE) 287 | return process_video_encode_hint(data); 288 | 289 | return HINT_NONE; 290 | } 291 | 292 | int set_interactive_override(__unused struct power_module *module, int on) 293 | { 294 | return HINT_HANDLED; /* Don't excecute this code path, not in use */ 295 | char governor[80]; 296 | 297 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 298 | ALOGE("Can't obtain scaling governor."); 299 | 300 | return HINT_NONE; 301 | } 302 | 303 | if (!on) { 304 | /* Display off */ 305 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 306 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 307 | int resource_values[] = {}; /* dummy node */ 308 | perform_hint_action(DISPLAY_STATE_HINT_ID, 309 | resource_values, ARRAY_SIZE(resource_values)); 310 | ALOGI("Display Off hint start"); 311 | return HINT_HANDLED; 312 | } 313 | } else { 314 | /* Display on */ 315 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 316 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 317 | undo_hint_action(DISPLAY_STATE_HINT_ID); 318 | ALOGI("Display Off hint stop"); 319 | return HINT_HANDLED; 320 | } 321 | } 322 | return HINT_NONE; 323 | } 324 | -------------------------------------------------------------------------------- /power/power-8998.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "QCOM PowerHAL" 40 | #include 41 | #include 42 | #include 43 | 44 | #include "utils.h" 45 | #include "metadata-defs.h" 46 | #include "hint-data.h" 47 | #include "performance.h" 48 | #include "power-common.h" 49 | 50 | static int current_power_profile = PROFILE_BALANCED; 51 | 52 | extern void interaction(int duration, int num_args, int opt_list[]); 53 | 54 | int get_number_of_profiles() { 55 | return 5; 56 | } 57 | 58 | static int profile_high_performance[] = { 59 | SCHED_BOOST_ON_V3, 0x1, 60 | ALL_CPUS_PWR_CLPS_DIS_V3, 0x1, 61 | CPUS_ONLINE_MIN_BIG, 0x2, 62 | CPUS_ONLINE_MIN_LITTLE, 0x2, 63 | MIN_FREQ_BIG_CORE_0, 0xFFF, 64 | MIN_FREQ_LITTLE_CORE_0, 0xFFF, 65 | }; 66 | 67 | static int profile_power_save[] = { 68 | CPUS_ONLINE_MAX_LIMIT_BIG, 0x1, 69 | MAX_FREQ_BIG_CORE_0, 0x3E8, 70 | MAX_FREQ_LITTLE_CORE_0, 0x3E8, 71 | }; 72 | 73 | static int profile_bias_power[] = { 74 | MAX_FREQ_BIG_CORE_0, 0x514, 75 | MAX_FREQ_LITTLE_CORE_0, 0x3E8, 76 | }; 77 | 78 | static int profile_bias_performance[] = { 79 | CPUS_ONLINE_MAX_LIMIT_BIG, 0x2, 80 | CPUS_ONLINE_MAX_LIMIT_LITTLE, 0x2, 81 | MIN_FREQ_BIG_CORE_0, 0x578, 82 | }; 83 | 84 | static void set_power_profile(int profile) { 85 | 86 | if (profile == current_power_profile) 87 | return; 88 | 89 | ALOGV("%s: Profile=%d", __func__, profile); 90 | 91 | if (current_power_profile != PROFILE_BALANCED) { 92 | undo_hint_action(DEFAULT_PROFILE_HINT_ID); 93 | ALOGV("%s: Hint undone", __func__); 94 | } 95 | 96 | if (profile == PROFILE_POWER_SAVE) { 97 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_power_save, 98 | ARRAY_SIZE(profile_power_save)); 99 | ALOGD("%s: Set powersave mode", __func__); 100 | 101 | } else if (profile == PROFILE_HIGH_PERFORMANCE) { 102 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_high_performance, 103 | ARRAY_SIZE(profile_high_performance)); 104 | ALOGD("%s: Set performance mode", __func__); 105 | 106 | } else if (profile == PROFILE_BIAS_POWER) { 107 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_power, 108 | ARRAY_SIZE(profile_bias_power)); 109 | ALOGD("%s: Set bias power mode", __func__); 110 | 111 | } else if (profile == PROFILE_BIAS_PERFORMANCE) { 112 | perform_hint_action(DEFAULT_PROFILE_HINT_ID, profile_bias_performance, 113 | ARRAY_SIZE(profile_bias_performance)); 114 | ALOGD("%s: Set bias perf mode", __func__); 115 | 116 | } 117 | 118 | current_power_profile = profile; 119 | } 120 | 121 | static int process_video_encode_hint(void *metadata) 122 | { 123 | char governor[80]; 124 | struct video_encode_metadata_t video_encode_metadata; 125 | 126 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 127 | ALOGE("Can't obtain scaling governor."); 128 | 129 | return HINT_NONE; 130 | } 131 | 132 | /* Initialize encode metadata struct fields */ 133 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 134 | video_encode_metadata.state = -1; 135 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 136 | 137 | if (metadata) { 138 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 139 | -1) { 140 | ALOGE("Error occurred while parsing metadata."); 141 | return HINT_NONE; 142 | } 143 | } else { 144 | return HINT_NONE; 145 | } 146 | 147 | if (video_encode_metadata.state == 1) { 148 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 149 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 150 | /* 1. cpufreq params 151 | * -above_hispeed_delay for LVT - 40ms 152 | * -go hispeed load for LVT - 95 153 | * -hispeed freq for LVT - 556 MHz 154 | * -target load for LVT - 90 155 | * -above hispeed delay for sLVT - 40ms 156 | * -go hispeed load for sLVT - 95 157 | * -hispeed freq for sLVT - 806 MHz 158 | * -target load for sLVT - 90 159 | * 2. bus DCVS set to V2 config: 160 | * -low power ceil mpbs - 2500 161 | * -low power io percent - 50 162 | * 3. hysteresis optimization 163 | * -bus dcvs hysteresis tuning 164 | * -sample_ms of 10 ms 165 | */ 166 | int resource_values[] = { 167 | ABOVE_HISPEED_DELAY_BIG, 0x4, 168 | GO_HISPEED_LOAD_BIG, 0x5F, 169 | HISPEED_FREQ_BIG, 0x326, 170 | TARGET_LOADS_BIG, 0x5A, 171 | ABOVE_HISPEED_DELAY_LITTLE, 0x4, 172 | GO_HISPEED_LOAD_LITTLE, 0x5F, 173 | HISPEED_FREQ_LITTLE, 0x22C, 174 | TARGET_LOADS_LITTLE, 0x5A, 175 | LOW_POWER_CEIL_MBPS, 0x9C4, 176 | LOW_POWER_IO_PERCENT, 0x32, 177 | CPUBW_HWMON_V1, 0x0, 178 | CPUBW_HWMON_SAMPLE_MS, 0xA, 179 | }; 180 | 181 | perform_hint_action(video_encode_metadata.hint_id, 182 | resource_values, ARRAY_SIZE(resource_values)); 183 | ALOGI("Video Encode hint start"); 184 | return HINT_HANDLED; 185 | } 186 | } else if (video_encode_metadata.state == 0) { 187 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 188 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 189 | undo_hint_action(video_encode_metadata.hint_id); 190 | ALOGI("Video Encode hint stop"); 191 | return HINT_HANDLED; 192 | } 193 | } 194 | return HINT_NONE; 195 | } 196 | 197 | int power_hint_override(__unused struct power_module *module, 198 | power_hint_t hint, void *data) 199 | { 200 | static struct timespec s_previous_boost_timespec; 201 | struct timespec cur_boost_timespec; 202 | long long elapsed_time; 203 | int duration; 204 | 205 | int resources_launch[] = { 206 | SCHED_BOOST_ON_V3, 0x1, 207 | MAX_FREQ_BIG_CORE_0, 0x939, 208 | MAX_FREQ_LITTLE_CORE_0, 0xFFF, 209 | MIN_FREQ_BIG_CORE_0, 0xFFF, 210 | MIN_FREQ_LITTLE_CORE_0, 0xFFF, 211 | CPUBW_HWMON_MIN_FREQ, 0x8C, 212 | ALL_CPUS_PWR_CLPS_DIS_V3, 0x1, 213 | STOR_CLK_SCALE_DIS, 0x1, 214 | }; 215 | 216 | int resources_cpu_boost[] = { 217 | SCHED_BOOST_ON_V3, 0x2, 218 | }; 219 | 220 | int resources_interaction_fling_boost[] = { 221 | CPUBW_HWMON_MIN_FREQ, 0x33, 222 | MIN_FREQ_BIG_CORE_0, 0x3E8, 223 | MIN_FREQ_LITTLE_CORE_0, 0x3E8, 224 | SCHED_BOOST_ON_V3, 0x2, 225 | }; 226 | 227 | int resources_interaction_boost[] = { 228 | MIN_FREQ_BIG_CORE_0, 0x3E8, 229 | }; 230 | 231 | if (hint == POWER_HINT_SET_PROFILE) { 232 | set_power_profile(*(int32_t *)data); 233 | return HINT_HANDLED; 234 | } 235 | 236 | /* Skip other hints in power save mode */ 237 | if (current_power_profile == PROFILE_POWER_SAVE) 238 | return HINT_HANDLED; 239 | 240 | if (hint == POWER_HINT_INTERACTION) { 241 | duration = data ? *((int *)data) : 500; 242 | 243 | clock_gettime(CLOCK_MONOTONIC, &cur_boost_timespec); 244 | elapsed_time = calc_timespan_us(s_previous_boost_timespec, cur_boost_timespec); 245 | if (elapsed_time > 750000) 246 | elapsed_time = 750000; 247 | /** 248 | * Don't hint if it's been less than 250ms since last boost 249 | * also detect if we're doing anything resembling a fling 250 | * support additional boosting in case of flings 251 | */ 252 | else if (elapsed_time < 250000 && duration <= 750) 253 | return HINT_HANDLED; 254 | 255 | s_previous_boost_timespec = cur_boost_timespec; 256 | 257 | if (duration >= 1500) { 258 | interaction(duration, ARRAY_SIZE(resources_interaction_fling_boost), 259 | resources_interaction_fling_boost); 260 | } else { 261 | interaction(duration, ARRAY_SIZE(resources_interaction_boost), 262 | resources_interaction_boost); 263 | } 264 | return HINT_HANDLED; 265 | } 266 | 267 | if (hint == POWER_HINT_LAUNCH) { 268 | duration = 2000; 269 | 270 | interaction(duration, ARRAY_SIZE(resources_launch), 271 | resources_launch); 272 | return HINT_HANDLED; 273 | } 274 | 275 | if (hint == POWER_HINT_CPU_BOOST) { 276 | duration = *(int32_t *)data / 1000; 277 | if (duration > 0) { 278 | interaction(duration, ARRAY_SIZE(resources_cpu_boost), 279 | resources_cpu_boost); 280 | return HINT_HANDLED; 281 | } 282 | } 283 | 284 | if (hint == POWER_HINT_VIDEO_ENCODE) 285 | return process_video_encode_hint(data); 286 | 287 | return HINT_NONE; 288 | } 289 | 290 | int set_interactive_override(__unused struct power_module *module, int on) 291 | { 292 | return HINT_HANDLED; /* Don't excecute this code path, not in use */ 293 | char governor[80]; 294 | 295 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 296 | ALOGE("Can't obtain scaling governor."); 297 | 298 | return HINT_NONE; 299 | } 300 | 301 | if (!on) { 302 | /* Display off */ 303 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 304 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 305 | int resource_values[] = {}; /* dummy node */ 306 | perform_hint_action(DISPLAY_STATE_HINT_ID, 307 | resource_values, ARRAY_SIZE(resource_values)); 308 | ALOGI("Display Off hint start"); 309 | return HINT_HANDLED; 310 | } 311 | } else { 312 | /* Display on */ 313 | if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 314 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 315 | undo_hint_action(DISPLAY_STATE_HINT_ID); 316 | ALOGI("Display Off hint stop"); 317 | return HINT_HANDLED; 318 | } 319 | } 320 | return HINT_NONE; 321 | } 322 | -------------------------------------------------------------------------------- /power/power-common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define NODE_MAX (64) 30 | 31 | #define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" 32 | #define DCVS_CPU0_SLACK_MAX_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_max_us" 33 | #define DCVS_CPU0_SLACK_MIN_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_min_us" 34 | #define MPDECISION_SLACK_MAX_NODE "/sys/module/msm_mpdecision/slack_time_max_us" 35 | #define MPDECISION_SLACK_MIN_NODE "/sys/module/msm_mpdecision/slack_time_min_us" 36 | #define SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq" 37 | 38 | #define ONDEMAND_GOVERNOR "ondemand" 39 | #define INTERACTIVE_GOVERNOR "interactive" 40 | #define MSMDCVS_GOVERNOR "msm-dcvs" 41 | 42 | #define HINT_HANDLED (0) 43 | #define HINT_NONE (-1) 44 | 45 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 46 | 47 | enum CPU_GOV_CHECK { 48 | CPU0 = 0, 49 | CPU1 = 1, 50 | CPU2 = 2, 51 | CPU3 = 3 52 | }; 53 | 54 | enum { 55 | PROFILE_POWER_SAVE = 0, 56 | PROFILE_BALANCED, 57 | PROFILE_HIGH_PERFORMANCE, 58 | PROFILE_BIAS_POWER, 59 | PROFILE_BIAS_PERFORMANCE 60 | }; 61 | -------------------------------------------------------------------------------- /power/power-feature-default.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The CyanogenMod Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include "power-feature.h" 19 | 20 | void set_device_specific_feature(struct power_module *module __unused, 21 | feature_t feature __unused, int state __unused) 22 | { 23 | } 24 | 25 | -------------------------------------------------------------------------------- /power/power-feature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The CyanogenMod Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _QCOM_POWER_FEATURE_H 18 | #define _QCOM_POWER_FEATURE_H 19 | 20 | #include 21 | 22 | void set_device_specific_feature(struct power_module *module, feature_t feature, int state); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /power/power.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 3 | * Copyright (c) 2014, The CyanogenMod Project 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following 12 | * disclaimer in the documentation and/or other materials provided 13 | * with the distribution. 14 | * * Neither the name of The Linux Foundation nor the names of its 15 | * contributors may be used to endorse or promote products derived 16 | * from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #define LOG_NIDEBUG 0 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #define LOG_TAG "QCOM PowerHAL" 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include "utils.h" 48 | #include "metadata-defs.h" 49 | #include "hint-data.h" 50 | #include "performance.h" 51 | #include "power-common.h" 52 | #include "power-feature.h" 53 | 54 | static int saved_dcvs_cpu0_slack_max = -1; 55 | static int saved_dcvs_cpu0_slack_min = -1; 56 | static int saved_mpdecision_slack_max = -1; 57 | static int saved_mpdecision_slack_min = -1; 58 | static int slack_node_rw_failed = 0; 59 | static int display_hint_sent; 60 | 61 | static pthread_mutex_t hint_mutex = PTHREAD_MUTEX_INITIALIZER; 62 | 63 | static void power_init(__attribute__((unused))struct power_module *module) 64 | { 65 | ALOGI("QCOM power HAL initing."); 66 | } 67 | 68 | static void process_video_decode_hint(void *metadata) 69 | { 70 | char governor[80]; 71 | struct video_decode_metadata_t video_decode_metadata; 72 | 73 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 74 | ALOGE("Can't obtain scaling governor."); 75 | 76 | return; 77 | } 78 | 79 | if (metadata) { 80 | ALOGI("Processing video decode hint. Metadata: %s", (char *)metadata); 81 | } 82 | 83 | /* Initialize encode metadata struct fields. */ 84 | memset(&video_decode_metadata, 0, sizeof(struct video_decode_metadata_t)); 85 | video_decode_metadata.state = -1; 86 | video_decode_metadata.hint_id = DEFAULT_VIDEO_DECODE_HINT_ID; 87 | 88 | if (metadata) { 89 | if (parse_video_decode_metadata((char *)metadata, &video_decode_metadata) == 90 | -1) { 91 | ALOGE("Error occurred while parsing metadata."); 92 | return; 93 | } 94 | } else { 95 | return; 96 | } 97 | 98 | if (video_decode_metadata.state == 1) { 99 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 100 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 101 | int resource_values[] = {THREAD_MIGRATION_SYNC_OFF}; 102 | 103 | perform_hint_action(video_decode_metadata.hint_id, 104 | resource_values, ARRAY_SIZE(resource_values)); 105 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 106 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 107 | int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF}; 108 | 109 | perform_hint_action(video_decode_metadata.hint_id, 110 | resource_values, ARRAY_SIZE(resource_values)); 111 | } 112 | } else if (video_decode_metadata.state == 0) { 113 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 114 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 115 | undo_hint_action(video_decode_metadata.hint_id); 116 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 117 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 118 | undo_hint_action(video_decode_metadata.hint_id); 119 | } 120 | } 121 | } 122 | 123 | static void process_video_encode_hint(void *metadata) 124 | { 125 | char governor[80]; 126 | struct video_encode_metadata_t video_encode_metadata; 127 | 128 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 129 | ALOGE("Can't obtain scaling governor."); 130 | 131 | return; 132 | } 133 | 134 | /* Initialize encode metadata struct fields. */ 135 | memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); 136 | video_encode_metadata.state = -1; 137 | video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; 138 | 139 | if (metadata) { 140 | if (parse_video_encode_metadata((char *)metadata, &video_encode_metadata) == 141 | -1) { 142 | ALOGE("Error occurred while parsing metadata."); 143 | return; 144 | } 145 | } else { 146 | return; 147 | } 148 | 149 | if (video_encode_metadata.state == 1) { 150 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 151 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 152 | int resource_values[] = {IO_BUSY_OFF, SAMPLING_DOWN_FACTOR_1, THREAD_MIGRATION_SYNC_OFF}; 153 | 154 | perform_hint_action(video_encode_metadata.hint_id, 155 | resource_values, ARRAY_SIZE(resource_values)); 156 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 157 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 158 | int resource_values[] = {TR_MS_30, HISPEED_LOAD_90, HS_FREQ_1026, THREAD_MIGRATION_SYNC_OFF, 159 | INTERACTIVE_IO_BUSY_OFF}; 160 | 161 | perform_hint_action(video_encode_metadata.hint_id, 162 | resource_values, ARRAY_SIZE(resource_values)); 163 | } 164 | } else if (video_encode_metadata.state == 0) { 165 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 166 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 167 | undo_hint_action(video_encode_metadata.hint_id); 168 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 169 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 170 | undo_hint_action(video_encode_metadata.hint_id); 171 | } 172 | } 173 | } 174 | 175 | int __attribute__ ((weak)) power_hint_override( 176 | __attribute__((unused)) struct power_module *module, 177 | __attribute__((unused)) power_hint_t hint, 178 | __attribute__((unused)) void *data) 179 | { 180 | return HINT_NONE; 181 | } 182 | 183 | extern void interaction(int duration, int num_args, int opt_list[]); 184 | 185 | static void power_hint(__attribute__((unused)) struct power_module *module, power_hint_t hint, 186 | void *data) 187 | { 188 | pthread_mutex_lock(&hint_mutex); 189 | 190 | /* Check if this hint has been overridden. */ 191 | if (power_hint_override(module, hint, data) == HINT_HANDLED) { 192 | /* The power_hint has been handled. We can skip the rest. */ 193 | goto out; 194 | } 195 | 196 | switch(hint) { 197 | case POWER_HINT_VSYNC: 198 | case POWER_HINT_INTERACTION: 199 | case POWER_HINT_CPU_BOOST: 200 | case POWER_HINT_SET_PROFILE: 201 | case POWER_HINT_LOW_POWER: 202 | break; 203 | case POWER_HINT_VIDEO_ENCODE: 204 | process_video_encode_hint(data); 205 | break; 206 | case POWER_HINT_VIDEO_DECODE: 207 | process_video_decode_hint(data); 208 | break; 209 | default: 210 | break; 211 | } 212 | 213 | out: 214 | pthread_mutex_unlock(&hint_mutex); 215 | } 216 | 217 | int __attribute__ ((weak)) set_interactive_override( 218 | __attribute__((unused)) struct power_module *module, 219 | __attribute__((unused)) int on) 220 | { 221 | return HINT_NONE; 222 | } 223 | 224 | int __attribute__ ((weak)) get_number_of_profiles() 225 | { 226 | return 0; 227 | } 228 | 229 | #ifdef SET_INTERACTIVE_EXT 230 | extern void cm_power_set_interactive_ext(int on); 231 | #endif 232 | 233 | void set_interactive(struct power_module *module, int on) 234 | { 235 | char governor[80]; 236 | char tmp_str[NODE_MAX]; 237 | struct video_encode_metadata_t video_encode_metadata; 238 | int rc = 0; 239 | 240 | pthread_mutex_lock(&hint_mutex); 241 | 242 | /** 243 | * Ignore consecutive display-off hints 244 | * Consecutive display-on hints are already handled 245 | */ 246 | if (display_hint_sent && !on) 247 | goto out; 248 | 249 | display_hint_sent = !on; 250 | 251 | #ifdef SET_INTERACTIVE_EXT 252 | cm_power_set_interactive_ext(on); 253 | #endif 254 | 255 | if (set_interactive_override(module, on) == HINT_HANDLED) { 256 | goto out; 257 | } 258 | 259 | ALOGI("Got set_interactive hint"); 260 | 261 | if (get_scaling_governor(governor, sizeof(governor)) == -1) { 262 | ALOGE("Can't obtain scaling governor."); 263 | goto out; 264 | } 265 | 266 | if (!on) { 267 | /* Display off. */ 268 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 269 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 270 | int resource_values[] = { MS_500, THREAD_MIGRATION_SYNC_OFF }; 271 | 272 | perform_hint_action(DISPLAY_STATE_HINT_ID, 273 | resource_values, ARRAY_SIZE(resource_values)); 274 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 275 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 276 | int resource_values[] = {TR_MS_50, THREAD_MIGRATION_SYNC_OFF}; 277 | 278 | perform_hint_action(DISPLAY_STATE_HINT_ID, 279 | resource_values, ARRAY_SIZE(resource_values)); 280 | } else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) && 281 | (strlen(governor) == strlen(MSMDCVS_GOVERNOR))) { 282 | /* Display turned off. */ 283 | if (sysfs_read(DCVS_CPU0_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) { 284 | if (!slack_node_rw_failed) { 285 | ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MAX_NODE); 286 | } 287 | 288 | rc = 1; 289 | } else { 290 | saved_dcvs_cpu0_slack_max = atoi(tmp_str); 291 | } 292 | 293 | if (sysfs_read(DCVS_CPU0_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) { 294 | if (!slack_node_rw_failed) { 295 | ALOGE("Failed to read from %s", DCVS_CPU0_SLACK_MIN_NODE); 296 | } 297 | 298 | rc = 1; 299 | } else { 300 | saved_dcvs_cpu0_slack_min = atoi(tmp_str); 301 | } 302 | 303 | if (sysfs_read(MPDECISION_SLACK_MAX_NODE, tmp_str, NODE_MAX - 1)) { 304 | if (!slack_node_rw_failed) { 305 | ALOGE("Failed to read from %s", MPDECISION_SLACK_MAX_NODE); 306 | } 307 | 308 | rc = 1; 309 | } else { 310 | saved_mpdecision_slack_max = atoi(tmp_str); 311 | } 312 | 313 | if (sysfs_read(MPDECISION_SLACK_MIN_NODE, tmp_str, NODE_MAX - 1)) { 314 | if(!slack_node_rw_failed) { 315 | ALOGE("Failed to read from %s", MPDECISION_SLACK_MIN_NODE); 316 | } 317 | 318 | rc = 1; 319 | } else { 320 | saved_mpdecision_slack_min = atoi(tmp_str); 321 | } 322 | 323 | /* Write new values. */ 324 | if (saved_dcvs_cpu0_slack_max != -1) { 325 | snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_max); 326 | 327 | if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) { 328 | if (!slack_node_rw_failed) { 329 | ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE); 330 | } 331 | 332 | rc = 1; 333 | } 334 | } 335 | 336 | if (saved_dcvs_cpu0_slack_min != -1) { 337 | snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_dcvs_cpu0_slack_min); 338 | 339 | if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) { 340 | if(!slack_node_rw_failed) { 341 | ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE); 342 | } 343 | 344 | rc = 1; 345 | } 346 | } 347 | 348 | if (saved_mpdecision_slack_max != -1) { 349 | snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_max); 350 | 351 | if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) { 352 | if(!slack_node_rw_failed) { 353 | ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE); 354 | } 355 | 356 | rc = 1; 357 | } 358 | } 359 | 360 | if (saved_mpdecision_slack_min != -1) { 361 | snprintf(tmp_str, NODE_MAX, "%d", 10 * saved_mpdecision_slack_min); 362 | 363 | if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) { 364 | if(!slack_node_rw_failed) { 365 | ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE); 366 | } 367 | 368 | rc = 1; 369 | } 370 | } 371 | 372 | slack_node_rw_failed = rc; 373 | } 374 | } else { 375 | /* Display on. */ 376 | if ((strncmp(governor, ONDEMAND_GOVERNOR, strlen(ONDEMAND_GOVERNOR)) == 0) && 377 | (strlen(governor) == strlen(ONDEMAND_GOVERNOR))) { 378 | undo_hint_action(DISPLAY_STATE_HINT_ID); 379 | } else if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && 380 | (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { 381 | undo_hint_action(DISPLAY_STATE_HINT_ID); 382 | } else if ((strncmp(governor, MSMDCVS_GOVERNOR, strlen(MSMDCVS_GOVERNOR)) == 0) && 383 | (strlen(governor) == strlen(MSMDCVS_GOVERNOR))) { 384 | /* Display turned on. Restore if possible. */ 385 | if (saved_dcvs_cpu0_slack_max != -1) { 386 | snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_max); 387 | 388 | if (sysfs_write(DCVS_CPU0_SLACK_MAX_NODE, tmp_str) != 0) { 389 | if (!slack_node_rw_failed) { 390 | ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MAX_NODE); 391 | } 392 | 393 | rc = 1; 394 | } 395 | } 396 | 397 | if (saved_dcvs_cpu0_slack_min != -1) { 398 | snprintf(tmp_str, NODE_MAX, "%d", saved_dcvs_cpu0_slack_min); 399 | 400 | if (sysfs_write(DCVS_CPU0_SLACK_MIN_NODE, tmp_str) != 0) { 401 | if (!slack_node_rw_failed) { 402 | ALOGE("Failed to write to %s", DCVS_CPU0_SLACK_MIN_NODE); 403 | } 404 | 405 | rc = 1; 406 | } 407 | } 408 | 409 | if (saved_mpdecision_slack_max != -1) { 410 | snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_max); 411 | 412 | if (sysfs_write(MPDECISION_SLACK_MAX_NODE, tmp_str) != 0) { 413 | if (!slack_node_rw_failed) { 414 | ALOGE("Failed to write to %s", MPDECISION_SLACK_MAX_NODE); 415 | } 416 | 417 | rc = 1; 418 | } 419 | } 420 | 421 | if (saved_mpdecision_slack_min != -1) { 422 | snprintf(tmp_str, NODE_MAX, "%d", saved_mpdecision_slack_min); 423 | 424 | if (sysfs_write(MPDECISION_SLACK_MIN_NODE, tmp_str) != 0) { 425 | if (!slack_node_rw_failed) { 426 | ALOGE("Failed to write to %s", MPDECISION_SLACK_MIN_NODE); 427 | } 428 | 429 | rc = 1; 430 | } 431 | } 432 | 433 | slack_node_rw_failed = rc; 434 | } 435 | } 436 | 437 | out: 438 | pthread_mutex_unlock(&hint_mutex); 439 | } 440 | 441 | void set_feature(struct power_module *module, feature_t feature, int state) 442 | { 443 | #ifdef TAP_TO_WAKE_NODE 444 | char tmp_str[NODE_MAX]; 445 | if (feature == POWER_FEATURE_DOUBLE_TAP_TO_WAKE) { 446 | snprintf(tmp_str, NODE_MAX, "%d", state); 447 | sysfs_write(TAP_TO_WAKE_NODE, tmp_str); 448 | return; 449 | } 450 | #endif 451 | set_device_specific_feature(module, feature, state); 452 | } 453 | 454 | int get_feature(struct power_module *module __unused, feature_t feature) 455 | { 456 | if (feature == POWER_FEATURE_SUPPORTED_PROFILES) { 457 | return get_number_of_profiles(); 458 | } 459 | return -1; 460 | } 461 | 462 | static int power_open(const hw_module_t* module, const char* name, 463 | hw_device_t** device) 464 | { 465 | ALOGD("%s: enter; name=%s", __FUNCTION__, name); 466 | int retval = 0; /* 0 is ok; -1 is error */ 467 | 468 | if (strcmp(name, POWER_HARDWARE_MODULE_ID) == 0) { 469 | power_module_t *dev = (power_module_t *)calloc(1, 470 | sizeof(power_module_t)); 471 | 472 | if (dev) { 473 | /* Common hw_device_t fields */ 474 | dev->common.tag = HARDWARE_DEVICE_TAG; 475 | dev->common.module_api_version = POWER_MODULE_API_VERSION_0_3; 476 | dev->common.hal_api_version = HARDWARE_HAL_API_VERSION; 477 | 478 | dev->init = power_init; 479 | dev->powerHint = power_hint; 480 | dev->setInteractive = set_interactive; 481 | dev->setFeature = set_feature; 482 | dev->getFeature = get_feature; 483 | dev->get_number_of_platform_modes = NULL; 484 | dev->get_platform_low_power_stats = NULL; 485 | dev->get_voter_list = NULL; 486 | 487 | *device = (hw_device_t*)dev; 488 | } else 489 | retval = -ENOMEM; 490 | } else { 491 | retval = -EINVAL; 492 | } 493 | 494 | ALOGD("%s: exit %d", __FUNCTION__, retval); 495 | return retval; 496 | } 497 | 498 | static struct hw_module_methods_t power_module_methods = { 499 | .open = power_open, 500 | }; 501 | 502 | struct power_module HAL_MODULE_INFO_SYM = { 503 | .common = { 504 | .tag = HARDWARE_MODULE_TAG, 505 | .module_api_version = POWER_MODULE_API_VERSION_0_3, 506 | .hal_api_version = HARDWARE_HAL_API_VERSION, 507 | .id = POWER_HARDWARE_MODULE_ID, 508 | .name = "QCOM Power HAL", 509 | .author = "Qualcomm/CyanogenMod", 510 | .methods = &power_module_methods, 511 | }, 512 | 513 | .init = power_init, 514 | .powerHint = power_hint, 515 | .setInteractive = set_interactive, 516 | .setFeature = set_feature, 517 | .getFeature = get_feature 518 | }; 519 | -------------------------------------------------------------------------------- /power/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #define LOG_NIDEBUG 0 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "utils.h" 39 | #include "list.h" 40 | #include "hint-data.h" 41 | #include "power-common.h" 42 | 43 | #define LOG_TAG "QCOM PowerHAL" 44 | #include 45 | 46 | #define USINSEC 1000000L 47 | #define NSINUS 1000L 48 | 49 | #define SOC_ID_0 "/sys/devices/soc0/soc_id" 50 | #define SOC_ID_1 "/sys/devices/system/soc/soc0/id" 51 | 52 | char scaling_gov_path[4][80] ={ 53 | "sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", 54 | "sys/devices/system/cpu/cpu1/cpufreq/scaling_governor", 55 | "sys/devices/system/cpu/cpu2/cpufreq/scaling_governor", 56 | "sys/devices/system/cpu/cpu3/cpufreq/scaling_governor" 57 | }; 58 | 59 | static void *qcopt_handle; 60 | static void *iop_handle; 61 | static int (*perf_lock_acq)(unsigned long handle, int duration, 62 | int list[], int numArgs); 63 | static int (*perf_lock_rel)(unsigned long handle); 64 | static int (*perf_lock_use_profile)(unsigned long handle, int profile); 65 | static int (*perf_io_prefetch_start)(int, const char*); 66 | static int (*perf_io_prefetch_stop)(); 67 | static struct list_node active_hint_list_head; 68 | static int profile_handle = 0; 69 | 70 | static void *get_qcopt_handle() 71 | { 72 | char qcopt_lib_path[PATH_MAX] = {0}; 73 | void *handle = NULL; 74 | 75 | dlerror(); 76 | 77 | if (property_get("ro.vendor.extension_library", qcopt_lib_path, 78 | NULL)) { 79 | handle = dlopen(qcopt_lib_path, RTLD_NOW); 80 | if (!handle) { 81 | ALOGE("Unable to open %s: %s\n", qcopt_lib_path, 82 | dlerror()); 83 | } 84 | } 85 | 86 | return handle; 87 | } 88 | 89 | static void *get_iop_handle() 90 | { 91 | char iop_lib_path[PATH_MAX] = {0}; 92 | void *handle = NULL; 93 | 94 | dlerror(); 95 | 96 | handle = dlopen("libqti-iop-client.so", RTLD_NOW | RTLD_LOCAL); 97 | if (!handle) { 98 | ALOGE("Unable to open prefetcher: %s\n", dlerror()); 99 | } 100 | 101 | return handle; 102 | } 103 | 104 | static void __attribute__ ((constructor)) initialize(void) 105 | { 106 | qcopt_handle = get_qcopt_handle(); 107 | 108 | if (!qcopt_handle) { 109 | ALOGE("Failed to get qcopt handle.\n"); 110 | } else { 111 | /* 112 | * qc-opt handle obtained. Get the perflock acquire/release 113 | * function pointers. 114 | */ 115 | perf_lock_acq = dlsym(qcopt_handle, "perf_lock_acq"); 116 | if (!perf_lock_acq) { 117 | goto fail_qcopt; 118 | } 119 | 120 | perf_lock_rel = dlsym(qcopt_handle, "perf_lock_rel"); 121 | if (!perf_lock_rel) { 122 | goto fail_qcopt; 123 | } 124 | 125 | // optional 126 | perf_lock_use_profile = dlsym(qcopt_handle, "perf_lock_use_profile"); 127 | } 128 | 129 | iop_handle = get_iop_handle(); 130 | 131 | if (!iop_handle) { 132 | ALOGE("Failed to get prefetcher handle.\n"); 133 | } else { 134 | perf_io_prefetch_start = (int(*)(int, const char *))dlsym( 135 | iop_handle, "perf_io_prefetch_start"); 136 | if (!perf_io_prefetch_start) { 137 | goto fail_iop; 138 | } 139 | 140 | perf_io_prefetch_stop = (int(*)())dlsym( 141 | iop_handle, "perf_io_prefetch_stop"); 142 | if (!perf_io_prefetch_stop) { 143 | goto fail_iop; 144 | } 145 | } 146 | return; 147 | 148 | fail_qcopt: 149 | perf_lock_acq = NULL; 150 | perf_lock_rel = NULL; 151 | if (qcopt_handle) { 152 | dlclose(qcopt_handle); 153 | qcopt_handle = NULL; 154 | } 155 | 156 | fail_iop: 157 | perf_io_prefetch_start = NULL; 158 | perf_io_prefetch_stop = NULL; 159 | if (iop_handle) { 160 | dlclose(iop_handle); 161 | iop_handle = NULL; 162 | } 163 | } 164 | 165 | static void __attribute__ ((destructor)) cleanup(void) 166 | { 167 | if (qcopt_handle) { 168 | if (dlclose(qcopt_handle)) 169 | ALOGE("Error occurred while closing qc-opt library."); 170 | } 171 | if (iop_handle) { 172 | if (dlclose(iop_handle)) 173 | ALOGE("Error occurred while closing prefetcher library."); 174 | } 175 | } 176 | 177 | int sysfs_read(char *path, char *s, int num_bytes) 178 | { 179 | char buf[80]; 180 | int count; 181 | int ret = 0; 182 | int fd = open(path, O_RDONLY); 183 | 184 | if (fd < 0) { 185 | strerror_r(errno, buf, sizeof(buf)); 186 | ALOGE("Error opening %s: %s\n", path, buf); 187 | 188 | return -1; 189 | } 190 | 191 | if ((count = read(fd, s, num_bytes - 1)) < 0) { 192 | strerror_r(errno, buf, sizeof(buf)); 193 | ALOGE("Error writing to %s: %s\n", path, buf); 194 | 195 | ret = -1; 196 | } else { 197 | s[count] = '\0'; 198 | } 199 | 200 | close(fd); 201 | 202 | return ret; 203 | } 204 | 205 | int sysfs_write(char *path, char *s) 206 | { 207 | char buf[80]; 208 | int len; 209 | int ret = 0; 210 | int fd = open(path, O_WRONLY); 211 | 212 | if (fd < 0) { 213 | strerror_r(errno, buf, sizeof(buf)); 214 | ALOGE("Error opening %s: %s\n", path, buf); 215 | return -1 ; 216 | } 217 | 218 | len = write(fd, s, strlen(s)); 219 | if (len < 0) { 220 | strerror_r(errno, buf, sizeof(buf)); 221 | ALOGE("Error writing to %s: %s\n", path, buf); 222 | 223 | ret = -1; 224 | } 225 | 226 | close(fd); 227 | 228 | return ret; 229 | } 230 | 231 | int get_scaling_governor(char governor[], int size) 232 | { 233 | if (sysfs_read(SCALING_GOVERNOR_PATH, governor, 234 | size) == -1) { 235 | // Can't obtain the scaling governor. Return. 236 | return -1; 237 | } else { 238 | // Strip newline at the end. 239 | int len = strlen(governor); 240 | 241 | len--; 242 | 243 | while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r')) 244 | governor[len--] = '\0'; 245 | } 246 | 247 | return 0; 248 | } 249 | 250 | int get_scaling_governor_check_cores(char governor[], int size,int core_num) 251 | { 252 | if (sysfs_read(scaling_gov_path[core_num], governor, 253 | size) == -1) { 254 | // Can't obtain the scaling governor. Return. 255 | return -1; 256 | } 257 | 258 | // Strip newline at the end. 259 | int len = strlen(governor); 260 | len--; 261 | while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r')) 262 | governor[len--] = '\0'; 263 | return 0; 264 | } 265 | 266 | void interaction(int duration, int num_args, int opt_list[]) 267 | { 268 | static int lock_handle = 0; 269 | 270 | if (duration <= 0 || num_args < 1 || opt_list[0] == 0) 271 | return; 272 | 273 | if (qcopt_handle) { 274 | if (perf_lock_acq) { 275 | lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args); 276 | if (lock_handle == -1) 277 | ALOGE("Failed to acquire lock."); 278 | } 279 | } 280 | } 281 | 282 | void perform_hint_action(int hint_id, int resource_values[], int num_resources) 283 | { 284 | if (qcopt_handle) { 285 | if (perf_lock_acq) { 286 | /* Acquire an indefinite lock for the requested resources. */ 287 | int lock_handle = perf_lock_acq(0, 0, resource_values, 288 | num_resources); 289 | 290 | if (lock_handle == -1) { 291 | ALOGE("Failed to acquire lock."); 292 | } else { 293 | /* Add this handle to our internal hint-list. */ 294 | struct hint_data *new_hint = 295 | (struct hint_data *)malloc(sizeof(struct hint_data)); 296 | 297 | if (new_hint) { 298 | if (!active_hint_list_head.compare) { 299 | active_hint_list_head.compare = 300 | (int (*)(void *, void *))hint_compare; 301 | active_hint_list_head.dump = (void (*)(void *))hint_dump; 302 | } 303 | 304 | new_hint->hint_id = hint_id; 305 | new_hint->perflock_handle = lock_handle; 306 | 307 | if (add_list_node(&active_hint_list_head, new_hint) == NULL) { 308 | free(new_hint); 309 | /* Can't keep track of this lock. Release it. */ 310 | if (perf_lock_rel) 311 | perf_lock_rel(lock_handle); 312 | 313 | ALOGE("Failed to process hint."); 314 | } 315 | } else { 316 | /* Can't keep track of this lock. Release it. */ 317 | if (perf_lock_rel) 318 | perf_lock_rel(lock_handle); 319 | 320 | ALOGE("Failed to process hint."); 321 | } 322 | } 323 | } 324 | } 325 | } 326 | 327 | void undo_hint_action(int hint_id) 328 | { 329 | if (qcopt_handle) { 330 | if (perf_lock_rel) { 331 | /* Get hint-data associated with this hint-id */ 332 | struct list_node *found_node; 333 | struct hint_data temp_hint_data = { 334 | .hint_id = hint_id 335 | }; 336 | 337 | found_node = find_node(&active_hint_list_head, 338 | &temp_hint_data); 339 | 340 | if (found_node) { 341 | /* Release this lock. */ 342 | struct hint_data *found_hint_data = 343 | (struct hint_data *)(found_node->data); 344 | 345 | if (found_hint_data) { 346 | if (perf_lock_rel(found_hint_data->perflock_handle) == -1) 347 | ALOGE("Perflock release failed."); 348 | } 349 | 350 | if (found_node->data) { 351 | /* We can free the hint-data for this node. */ 352 | free(found_node->data); 353 | } 354 | 355 | remove_list_node(&active_hint_list_head, found_node); 356 | } else { 357 | ALOGE("Invalid hint ID."); 358 | } 359 | } 360 | } 361 | } 362 | 363 | /* 364 | * Used to release initial lock holding 365 | * two cores online when the display is on 366 | */ 367 | void undo_initial_hint_action() 368 | { 369 | if (qcopt_handle) { 370 | if (perf_lock_rel) { 371 | perf_lock_rel(1); 372 | } 373 | } 374 | } 375 | 376 | /* Set a static profile */ 377 | void set_profile(int profile) 378 | { 379 | if (qcopt_handle) { 380 | if (perf_lock_use_profile) { 381 | profile_handle = perf_lock_use_profile(profile_handle, profile); 382 | if (profile_handle == -1) 383 | ALOGE("Failed to set profile."); 384 | if (profile < 0) 385 | profile_handle = 0; 386 | } 387 | } 388 | } 389 | 390 | void start_prefetch(int pid, const char* packageName) { 391 | if (iop_handle) { 392 | if (perf_io_prefetch_start) { 393 | perf_io_prefetch_start(pid, packageName); 394 | } 395 | } 396 | } 397 | 398 | long long calc_timespan_us(struct timespec start, struct timespec end) 399 | { 400 | long long diff_in_us = 0; 401 | diff_in_us += (end.tv_sec - start.tv_sec) * USINSEC; 402 | diff_in_us += (end.tv_nsec - start.tv_nsec) / NSINUS; 403 | return diff_in_us; 404 | } 405 | 406 | int get_soc_id(void) 407 | { 408 | int fd; 409 | int soc_id = -1; 410 | char buf[10] = { 0 }; 411 | 412 | if (!access(SOC_ID_0, F_OK)) 413 | fd = open(SOC_ID_0, O_RDONLY); 414 | else 415 | fd = open(SOC_ID_1, O_RDONLY); 416 | 417 | if (fd >= 0) { 418 | if (read(fd, buf, sizeof(buf) - 1) == -1) 419 | ALOGW("Unable to read soc_id"); 420 | else 421 | soc_id = atoi(buf); 422 | } 423 | 424 | close(fd); 425 | return soc_id; 426 | } 427 | -------------------------------------------------------------------------------- /power/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above 10 | * copyright notice, this list of conditions and the following 11 | * disclaimer in the documentation and/or other materials provided 12 | * with the distribution. 13 | * * Neither the name of The Linux Foundation nor the names of its 14 | * contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | 32 | int sysfs_read(char *path, char *s, int num_bytes); 33 | int sysfs_write(char *path, char *s); 34 | int get_scaling_governor(char governor[], int size); 35 | int get_scaling_governor_check_cores(char governor[], int size,int core_num); 36 | 37 | void vote_ondemand_io_busy_off(); 38 | void unvote_ondemand_io_busy_off(); 39 | void vote_ondemand_sdf_low(); 40 | void unvote_ondemand_sdf_low(); 41 | void perform_hint_action(int hint_id, int resource_values[], 42 | int num_resources); 43 | void undo_hint_action(int hint_id); 44 | void undo_initial_hint_action(); 45 | void set_profile(int profile); 46 | void start_prefetch(int pid, const char *packageName); 47 | 48 | long long calc_timespan_us(struct timespec start, struct timespec end); 49 | int get_soc_id(void); 50 | --------------------------------------------------------------------------------