diff --git a/BoardConfig.mk b/BoardConfig.mk index a39876d..e812593 100644 --- a/BoardConfig.mk +++ b/BoardConfig.mk @@ -208,6 +208,7 @@ BOARD_USERDATAIMAGE_PARTITION_SIZE := 25614597120 # 25014255 * 1024 mmcblk0p54 TARGET_PER_MGR_ENABLED := true # Power +TARGET_PROVIDES_POWERHAL := true TARGET_HAS_NO_WLAN_STATS := true # QC flags diff --git a/device.mk b/device.mk index a09cbdd..2059249 100644 --- a/device.mk +++ b/device.mk @@ -317,8 +317,9 @@ PRODUCT_ENFORCE_RRO_TARGETS := \ # Power PRODUCT_PACKAGES += \ + android.hardware.power@1.0-impl \ - android.hardware.power@1.0-service \ + android.hardware.power@1.2-service \ power.qcom # Powerhint configuration file diff --git a/power/Android.bp b/power/Android.bp new file mode 100644 index 0000000..3b024a1 --- /dev/null +++ b/power/Android.bp @@ -0,0 +1,5 @@ +cc_library_headers { + name: "qti_powerhal_headers", + vendor_available: true, + export_include_dirs: ["."], +} diff --git a/power/Android.mk b/power/Android.mk new file mode 100644 index 0000000..34042ed --- /dev/null +++ b/power/Android.mk @@ -0,0 +1,27 @@ +LOCAL_PATH := $(call my-dir) + +# HAL module implemenation stored in +# hw/..so +include $(CLEAR_VARS) + +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libdl libxml2 libbase libhidlbase libhidltransport libutils android.hardware.power@1.2 +LOCAL_HEADER_LIBRARIES += libutils_headers +LOCAL_HEADER_LIBRARIES += libhardware_headers +LOCAL_SRC_FILES := power-common.c metadata-parser.c utils.c list.c hint-data.c powerhintparser.c service.cpp Power.cpp +LOCAL_C_INCLUDES := external/libxml2/include \ + external/icu/icu4c/source/common + +LOCAL_SRC_FILES += power-8953.c + +ifeq ($(TARGET_USES_INTERACTION_BOOST),true) + LOCAL_CFLAGS += -DINTERACTION_BOOST +endif + +LOCAL_MODULE := android.hardware.power@1.2-service +LOCAL_INIT_RC := android.hardware.power@1.2-service.rc +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Wno-unused-parameter -Wno-unused-variable +LOCAL_VENDOR_MODULE := true +include $(BUILD_EXECUTABLE) + diff --git a/power/NOTICE b/power/NOTICE new file mode 100644 index 0000000..26f0cc8 --- /dev/null +++ b/power/NOTICE @@ -0,0 +1,32 @@ +Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the +disclaimer below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE +GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT +HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/power/Power.cpp b/power/Power.cpp new file mode 100644 index 0000000..81c0a85 --- /dev/null +++ b/power/Power.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "QTI PowerHAL" + +#include +#include +#include "Power.h" +#include "power-common.h" + +namespace android { +namespace hardware { +namespace power { +namespace V1_2 { +namespace implementation { + +using ::android::hardware::power::V1_0::Feature; +using ::android::hardware::power::V1_0::PowerHint; +using ::android::hardware::power::V1_0::PowerStatePlatformSleepState; +using ::android::hardware::power::V1_0::Status; +using ::android::hardware::power::V1_1::PowerStateSubsystem; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; + +Power::Power() { + power_init(); +} + +Return Power::setInteractive(bool interactive) { + set_interactive(interactive ? 1:0); + return Void(); +} + +Return Power::powerHint(PowerHint_1_0 hint, int32_t data) { + + power_hint(static_cast(hint), data ? (&data) : NULL); + return Void(); +} + +Return Power::setFeature(Feature feature, bool activate) { + return Void(); +} + +Return Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) { + + hidl_vec states; + states.resize(0); + + _hidl_cb(states, Status::SUCCESS); + return Void(); +} + +Return Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) { + + hidl_vec subsystems; + + _hidl_cb(subsystems, Status::SUCCESS); + return Void(); +} + +Return Power::powerHintAsync(PowerHint_1_0 hint, int32_t data) { + + return powerHint(hint, data); +} + +Return Power::powerHintAsync_1_2(PowerHint_1_2 hint, int32_t data) { + + return powerHint(static_cast (hint), data); +} + +} // namespace implementation +} // namespace V1_2 +} // namespace power +} // namespace hardware +} // namespace android diff --git a/power/Power.h b/power/Power.h new file mode 100644 index 0000000..a787590 --- /dev/null +++ b/power/Power.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANDROID_HARDWARE_POWER_V1_2_POWER_H +#define ANDROID_HARDWARE_POWER_V1_2_POWER_H + +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace power { +namespace V1_2 { +namespace implementation { + +using ::android::hardware::power::V1_0::Feature; +using PowerHint_1_0 = ::android::hardware::power::V1_0::PowerHint; +using PowerHint_1_2 = ::android::hardware::power::V1_2::PowerHint; +using ::android::hardware::power::V1_2::IPower; +using ::android::hardware::Return; +using ::android::hardware::Void; + +struct Power : public IPower { + // Methods from ::android::hardware::power::V1_0::IPower follow. + + Power(); + + Return setInteractive(bool interactive) override; + Return powerHint(PowerHint_1_0 hint, int32_t data) override; + Return setFeature(Feature feature, bool activate) override; + Return getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) override; + + // Methods from ::android::hardware::power::V1_1::IPower follow + Return getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) override; + Return powerHintAsync(PowerHint_1_0 hint, int32_t data) override; + // Methods from ::android::hardware::power::V1_2::IPower follow + Return powerHintAsync_1_2(PowerHint_1_2 hint, int32_t data) override; +}; + +} // namespace implementation +} // namespace V1_2 +} // namespace power +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_POWER_V1_2_POWER_H diff --git a/power/android.hardware.power@1.2-service.rc b/power/android.hardware.power@1.2-service.rc new file mode 100644 index 0000000..8a1c347 --- /dev/null +++ b/power/android.hardware.power@1.2-service.rc @@ -0,0 +1,4 @@ +service vendor.power-hal-1-2 /vendor/bin/hw/android.hardware.power@1.2-service + class hal + user system + group system diff --git a/power/hint-data.c b/power/hint-data.c new file mode 100644 index 0000000..67da77a --- /dev/null +++ b/power/hint-data.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "hint-data.h" + +int hint_compare(struct hint_data *first_hint, + struct hint_data *other_hint) { + if (first_hint == other_hint) { + return 0; + } else if ((first_hint && other_hint) && + (first_hint->hint_id == other_hint->hint_id)) { + return 0; + } else { + return 1; + } +} + +void hint_dump(struct hint_data *hint) +{ + /*ALOGI("hint_id: %lu", hint->hint_id);*/ +} diff --git a/power/hint-data.h b/power/hint-data.h new file mode 100644 index 0000000..48909c7 --- /dev/null +++ b/power/hint-data.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 2013, 2015, 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Default use-case hint IDs */ +#define DEFAULT_VIDEO_ENCODE_HINT_ID (0x0A00) +#define DEFAULT_VIDEO_DECODE_HINT_ID (0x0B00) +#define DISPLAY_STATE_HINT_ID (0x0C00) +#define DISPLAY_STATE_HINT_ID_2 (0x0D00) +#define CAM_PREVIEW_HINT_ID (0x0E00) +#define SUSTAINED_PERF_HINT_ID (0x0F00) +#define VR_MODE_HINT_ID (0x1000) +#define VR_MODE_SUSTAINED_PERF_HINT_ID (0x1001) + +#define AOSP_DELTA (0x1200) + +#define VSYNC_HINT AOSP_DELTA + POWER_HINT_VSYNC +#define INTERACTION_HINT AOSP_DELTA + POWER_HINT_INTERACTION +#define VIDEO_DECODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_DECODE +#define VIDEO_ENCODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_ENCODE +#define LOW_POWER_HINT AOSP_DELTA + POWER_HINT_LOW_POWER +#define SUSTAINED_PERF_HINT AOSP_DELTA + POWER_HINT_SUSTAINED_PERFORMANCE +#define VR_MODE_HINT AOSP_DELTA + POWER_HINT_VR_MODE +#define LAUNCH_HINT AOSP_DELTA + POWER_HINT_LAUNCH +#define DISABLE_TOUCH_HINT AOSP_DELTA + POWER_HINT_DISABLE_TOUCH + +//update NUM_HINTS if hints are added to AOSP +#define NUM_HINTS (POWER_HINT_DISABLE_TOUCH +1) + +#define VR_MODE_SUSTAINED_PERF_HINT (0x1301) + +struct hint_handles{ + int handle; + int ref_count; +}; + +struct hint_data { + unsigned long hint_id; /* This is our key. */ + unsigned long perflock_handle; +}; + +int hint_compare(struct hint_data *first_hint, + struct hint_data *other_hint); +void hint_dump(struct hint_data *hint); diff --git a/power/list.c b/power/list.c new file mode 100644 index 0000000..0fe8de2 --- /dev/null +++ b/power/list.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "list.h" +#include + +int init_list_head(struct list_node *head) +{ + if (head == NULL) + return -1; + + memset(head, 0, sizeof(*head)); + + return 0; +} + +struct list_node *add_list_node(struct list_node *head, void *data) +{ + /* Create a new list_node. And put 'data' into it. */ + struct list_node *new_node; + + if (head == NULL) { + return NULL; + } + + if (!(new_node = malloc(sizeof(struct list_node)))) { + return NULL; + } + + new_node->data = data; + new_node->next = head->next; + new_node->compare = head->compare; + new_node->dump = head->dump; + head->next = new_node; + + return new_node; +} + +int is_list_empty(struct list_node *head) +{ + return (head == NULL || head->next == NULL); +} + +/* + * Delink and de-allocate 'node'. + */ +int remove_list_node(struct list_node *head, struct list_node *del_node) +{ + struct list_node *current_node; + struct list_node *saved_node; + + if (head == NULL || head->next == NULL) { + return -1; + } + + current_node = head->next; + saved_node = head; + + while (current_node && current_node != del_node) { + saved_node = current_node; + current_node = current_node->next; + } + + if (saved_node) { + if (current_node) { + saved_node->next = current_node->next; + } else { + /* Node not found. */ + return -1; + } + } + + if (del_node) { + free(del_node); + } + + return 0; +} + +void dump_list(struct list_node *head) +{ + struct list_node *current_node = head; + + if (head == NULL) + return; + + printf("List:\n"); + + while ((current_node = current_node->next)) { + if (current_node->dump) { + current_node->dump(current_node->data); + } + } +} + +struct list_node *find_node(struct list_node *head, void *comparison_data) +{ + struct list_node *current_node = head; + + if (head == NULL) + return NULL; + + while ((current_node = current_node->next)) { + if (current_node->compare) { + if (current_node->compare(current_node->data, + comparison_data) == 0) { + /* Match found. Return current_node. */ + return current_node; + } + } + } + + /* No match found. */ + return NULL; +} diff --git a/power/list.h b/power/list.h new file mode 100644 index 0000000..d68c3df --- /dev/null +++ b/power/list.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +struct list_node { + struct list_node *next; + void *data; + int (*compare)(void *data1, void *data2); + void (*dump)(void *data); +}; + +int init_list_head(struct list_node *head); +struct list_node * add_list_node(struct list_node *head, void *data); +int remove_list_node(struct list_node *head, struct list_node *del_node); +void dump_list(struct list_node *head); +struct list_node *find_node(struct list_node *head, void *comparison_data); diff --git a/power/metadata-defs.h b/power/metadata-defs.h new file mode 100644 index 0000000..c464900 --- /dev/null +++ b/power/metadata-defs.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define ATTRIBUTE_VALUE_DELIM ('=') +#define ATTRIBUTE_STRING_DELIM (";") + +#define METADATA_PARSING_ERR (-1) +#define METADATA_PARSING_CONTINUE (0) +#define METADATA_PARSING_DONE (1) + +#define MIN(x,y) (((x)>(y))?(y):(x)) + +struct video_encode_metadata_t { + int hint_id; + int state; +}; + +struct video_decode_metadata_t { + int hint_id; + int state; +}; + +int parse_metadata(char *metadata, char **metadata_saveptr, + char *attribute, int attribute_size, char *value, int value_size); +int parse_video_encode_metadata(char *metadata, + struct video_encode_metadata_t *video_encode_metadata); +int parse_video_decode_metadata(char *metadata, + struct video_decode_metadata_t *video_decode_metadata); diff --git a/power/metadata-parser.c b/power/metadata-parser.c new file mode 100644 index 0000000..c9122a4 --- /dev/null +++ b/power/metadata-parser.c @@ -0,0 +1,133 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include "metadata-defs.h" + +int parse_metadata(char *metadata, char **metadata_saveptr, + char *attribute, int attribute_size, char *value, int value_size) +{ + char *attribute_string; + char *attribute_value_delim; + unsigned int bytes_to_copy; + + attribute_string = strtok_r(metadata, ATTRIBUTE_STRING_DELIM, + metadata_saveptr); + + if (attribute_string == NULL) + return METADATA_PARSING_DONE; + + attribute[0] = value[0] = '\0'; + + if ((attribute_value_delim = strchr(attribute_string, + ATTRIBUTE_VALUE_DELIM)) != NULL) { + bytes_to_copy = MIN((attribute_value_delim - attribute_string), + attribute_size - 1); + /* Replace strncpy with strlcpy + * Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */ + strlcpy(attribute, attribute_string, + bytes_to_copy+1); + + bytes_to_copy = MIN(strlen(attribute_string) - strlen(attribute) - 1, + value_size - 1); + /* Replace strncpy with strlcpy + * Add +1 to bytes_to_copy as strlcpy copies size-1 bytes */ + strlcpy(value, attribute_value_delim + 1, + bytes_to_copy+1); + } + + return METADATA_PARSING_CONTINUE; +} + +int parse_video_encode_metadata(char *metadata, + struct video_encode_metadata_t *video_encode_metadata) +{ + char attribute[1024], value[1024], *saveptr; + char *temp_metadata = metadata; + int parsing_status; + + while ((parsing_status = parse_metadata(temp_metadata, &saveptr, + attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) { + if (strlen(attribute) == strlen("hint_id") && + (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) { + if (strlen(value) > 0) { + video_encode_metadata->hint_id = atoi(value); + } + } + + if (strlen(attribute) == strlen("state") && + (strncmp(attribute, "state", strlen("state")) == 0)) { + if (strlen(value) > 0) { + video_encode_metadata->state = atoi(value); + } + } + + temp_metadata = NULL; + } + + if (parsing_status == METADATA_PARSING_ERR) + return -1; + + return 0; +} + +int parse_video_decode_metadata(char *metadata, + struct video_decode_metadata_t *video_decode_metadata) +{ + char attribute[1024], value[1024], *saveptr; + char *temp_metadata = metadata; + int parsing_status; + + while ((parsing_status = parse_metadata(temp_metadata, &saveptr, + attribute, sizeof(attribute), value, sizeof(value))) == METADATA_PARSING_CONTINUE) { + if (strlen(attribute) == strlen("hint_id") && + (strncmp(attribute, "hint_id", strlen("hint_id")) == 0)) { + if (strlen(value) > 0) { + video_decode_metadata->hint_id = atoi(value); + } + } + + if (strlen(attribute) == strlen("state") && + (strncmp(attribute, "state", strlen("state")) == 0)) { + if (strlen(value) > 0) { + video_decode_metadata->state = atoi(value); + } + } + + temp_metadata = NULL; + } + + if (parsing_status == METADATA_PARSING_ERR) + return -1; + + return 0; +} diff --git a/power/performance.h b/power/performance.h new file mode 100644 index 0000000..b7bf34b --- /dev/null +++ b/power/performance.h @@ -0,0 +1,265 @@ +/* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define FAILED -1 +#define SUCCESS 0 +#define INDEFINITE_DURATION 0 + +/* Hints sent to perf HAL from power HAL + * These have to be kept in sync with Perf HAL side definitions + */ +#define VENDOR_HINT_DISPLAY_OFF 0x00001040 +#define VENDOR_HINT_DISPLAY_ON 0x00001041 + +enum SCREEN_DISPLAY_TYPE { + DISPLAY_OFF = 0x00FF, +}; + +enum PWR_CLSP_TYPE { + ALL_CPUS_PWR_CLPS_DIS = 0x101, +}; + +/* For CPUx min freq, the leftmost byte + * represents the CPU and the + * rightmost byte represents the frequency + * All intermediate frequencies on the + * device are supported. The hex value + * passed into PerfLock will be multiplied + * by 10^5. This frequency or the next + * highest frequency available will be set + * + * For example, if 1.4 Ghz is required on + * CPU0, use 0x20E + * + * If the highest available frequency + * on the device is required, use + * CPUx_MIN_FREQ_TURBO_MAX + * where x represents the CPU + */ +enum CPU0_MIN_FREQ_LVL { + CPU0_MIN_FREQ_NONTURBO_MAX = 0x20A, + CPU0_MIN_FREQ_TURBO_MAX = 0x2FE, +}; + +enum CPU1_MIN_FREQ_LVL { + CPU1_MIN_FREQ_NONTURBO_MAX = 0x30A, + CPU1_MIN_FREQ_TURBO_MAX = 0x3FE, +}; + +enum CPU2_MIN_FREQ_LVL { + CPU2_MIN_FREQ_NONTURBO_MAX = 0x40A, + CPU2_MIN_FREQ_TURBO_MAX = 0x4FE, +}; + +enum CPU3_MIN_FREQ_LVL { + CPU3_MIN_FREQ_NONTURBO_MAX = 0x50A, + CPU3_MIN_FREQ_TURBO_MAX = 0x5FE, +}; + +enum CPU0_MAX_FREQ_LVL { + CPU0_MAX_FREQ_NONTURBO_MAX = 0x150A, +}; + +enum CPU1_MAX_FREQ_LVL { + CPU1_MAX_FREQ_NONTURBO_MAX = 0x160A, +}; + +enum CPU2_MAX_FREQ_LVL { + CPU2_MAX_FREQ_NONTURBO_MAX = 0x170A, +}; + +enum CPU3_MAX_FREQ_LVL { + CPU3_MAX_FREQ_NONTURBO_MAX = 0x180A, +}; + +enum MIN_CPUS_ONLINE_LVL { + CPUS_ONLINE_MIN_2 = 0x702, + CPUS_ONLINE_MIN_3 = 0x703, + CPUS_ONLINE_MIN_4 = 0x704, + CPUS_ONLINE_MPD_OVERRIDE = 0x777, + CPUS_ONLINE_MAX = 0x7FF, +}; + +enum MAX_CPUS_ONLINE_LVL { + CPUS_ONLINE_MAX_LIMIT_1 = 0x8FE, + CPUS_ONLINE_MAX_LIMIT_2 = 0x8FD, + CPUS_ONLINE_MAX_LIMIT_3 = 0x8FC, + CPUS_ONLINE_MAX_LIMIT_4 = 0x8FB, + CPUS_ONLINE_MAX_LIMIT_MAX = 0x8FB, +}; + +enum SAMPLING_RATE_LVL { + MS_500 = 0xBCD, + MS_50 = 0xBFA, + MS_20 = 0xBFD, +}; + +enum ONDEMAND_IO_BUSY_LVL { + IO_BUSY_OFF = 0xC00, + IO_BUSY_ON = 0xC01, +}; + +enum ONDEMAND_SAMPLING_DOWN_FACTOR_LVL { + SAMPLING_DOWN_FACTOR_1 = 0xD01, + SAMPLING_DOWN_FACTOR_4 = 0xD04, +}; + +enum INTERACTIVE_TIMER_RATE_LVL { + TR_MS_500 = 0xECD, + TR_MS_100 = 0xEF5, + TR_MS_50 = 0xEFA, + TR_MS_30 = 0xEFC, + TR_MS_20 = 0xEFD, +}; + +/* This timer rate applicable to cpu0 + across 8939 series chipset */ +enum INTERACTIVE_TIMER_RATE_LVL_CPU0_8939 { + TR_MS_CPU0_500 = 0x30CD, + TR_MS_CPU0_100 = 0x30F5, + TR_MS_CPU0_50 = 0x30FA, + TR_MS_CPU0_30 = 0x30FC, + TR_MS_CPU0_20 = 0x30FD, +}; + +/* This timer rate applicable to cpu4 + across 8939 series chipset */ +enum INTERACTIVE_TIMER_RATE_LVL_CPU4_8939 { + TR_MS_CPU4_500 = 0x3BCD, + TR_MS_CPU4_100 = 0x3BF5, + TR_MS_CPU4_50 = 0x3BFA, + TR_MS_CPU4_30 = 0x3BFC, + TR_MS_CPU4_20 = 0x3BFD, +}; + +/* This timer rate applicable to big.little arch */ +enum INTERACTIVE_TIMER_RATE_LVL_BIG_LITTLE { + BIG_LITTLE_TR_MS_100 = 0x64, + BIG_LITTLE_TR_MS_50 = 0x32, + BIG_LITTLE_TR_MS_40 = 0x28, + BIG_LITTLE_TR_MS_30 = 0x1E, + BIG_LITTLE_TR_MS_20 = 0x14, +}; + +/* INTERACTIVE opcodes */ +enum INTERACTIVE_OPCODES { + INT_OP_CLUSTER0_TIMER_RATE = 0x41424000, + INT_OP_CLUSTER1_TIMER_RATE = 0x41424100, + INT_OP_CLUSTER0_USE_SCHED_LOAD = 0x41430000, + INT_OP_CLUSTER1_USE_SCHED_LOAD = 0x41430100, + INT_OP_CLUSTER0_USE_MIGRATION_NOTIF = 0x41434000, + INT_OP_CLUSTER1_USE_MIGRATION_NOTIF = 0x41434100, + INT_OP_NOTIFY_ON_MIGRATE = 0x4241C000 +}; + +enum INTERACTIVE_HISPEED_FREQ_LVL { + HS_FREQ_1026 = 0xF0A, +}; + +enum INTERACTIVE_HISPEED_LOAD_LVL { + HISPEED_LOAD_90 = 0x105A, +}; + +enum SYNC_FREQ_LVL { + SYNC_FREQ_300 = 0x1103, + SYNC_FREQ_600 = 0X1106, + SYNC_FREQ_384 = 0x1103, + SYNC_FREQ_NONTURBO_MAX = 0x110A, + SYNC_FREQ_TURBO = 0x110F, +}; + +enum OPTIMAL_FREQ_LVL { + OPTIMAL_FREQ_300 = 0x1203, + OPTIMAL_FREQ_600 = 0x1206, + OPTIMAL_FREQ_384 = 0x1203, + OPTIMAL_FREQ_NONTURBO_MAX = 0x120A, + OPTIMAL_FREQ_TURBO = 0x120F, +}; + +enum SCREEN_PWR_CLPS_LVL { + PWR_CLPS_DIS = 0x1300, + PWR_CLPS_ENA = 0x1301, +}; + +enum THREAD_MIGRATION_LVL { + THREAD_MIGRATION_SYNC_OFF = 0x1400, +}; + +enum INTERACTIVE_IO_BUSY_LVL { + INTERACTIVE_IO_BUSY_OFF = 0x1B00, + INTERACTIVE_IO_BUSY_ON = 0x1B01, +}; + +enum SCHED_BOOST_LVL { + SCHED_BOOST_ON = 0x1E01, +}; + +enum CPU4_MIN_FREQ_LVL { + CPU4_MIN_FREQ_NONTURBO_MAX = 0x1F0A, + CPU4_MIN_FREQ_TURBO_MAX = 0x1FFE, +}; + +enum CPU5_MIN_FREQ_LVL { + CPU5_MIN_FREQ_NONTURBO_MAX = 0x200A, + CPU5_MIN_FREQ_TURBO_MAX = 0x20FE, +}; + +enum CPU6_MIN_FREQ_LVL { + CPU6_MIN_FREQ_NONTURBO_MAX = 0x210A, + CPU6_MIN_FREQ_TURBO_MAX = 0x21FE, +}; + +enum CPU7_MIN_FREQ_LVL { + CPU7_MIN_FREQ_NONTURBO_MAX = 0x220A, + CPU7_MIN_FREQ_TURBO_MAX = 0x22FE, +}; + +enum CPU4_MAX_FREQ_LVL { + CPU4_MAX_FREQ_NONTURBO_MAX = 0x230A, +}; + +enum CPU5_MAX_FREQ_LVL { + CPU5_MAX_FREQ_NONTURBO_MAX = 0x240A, +}; + +enum CPU6_MAX_FREQ_LVL { + CPU6_MAX_FREQ_NONTURBO_MAX = 0x250A, +}; + +enum CPU7_MAX_FREQ_LVL { + CPU7_MAX_FREQ_NONTURBO_MAX = 0x260A, +}; + +#ifdef __cplusplus +} +#endif diff --git a/power/power-8953.c b/power/power-8953.c new file mode 100644 index 0000000..d0750e4 --- /dev/null +++ b/power/power-8953.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_NIDEBUG 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#include "utils.h" +#include "metadata-defs.h" +#include "hint-data.h" +#include "performance.h" +#include "power-common.h" + +#define MIN_VAL(X,Y) ((X>Y)?(Y):(X)) + +static int saved_interactive_mode = -1; +static int display_hint_sent; +static int video_encode_hint_sent; +static int cam_preview_hint_sent; + +pthread_mutex_t camera_hint_mutex = PTHREAD_MUTEX_INITIALIZER; +static int camera_hint_ref_count; +static void process_video_encode_hint(void *metadata); +//static void process_cam_preview_hint(void *metadata); + +static int display_fd; +#define SYS_DISPLAY_PWR "/sys/kernel/hbtp/display_pwr" + +static bool is_target_SDM632() /* Returns value=632 if target is SDM632 else value 0 */ +{ + int fd; + bool is_target_SDM632 = false; + char buf[10] = {0}; + fd = open("/sys/devices/soc0/soc_id", O_RDONLY); + if (fd >= 0) { + if (read(fd, buf, sizeof(buf) - 1) == -1) { + ALOGW("Unable to read soc_id"); + is_target_SDM632 = false; + } else { + int soc_id = atoi(buf); + if (soc_id == 349 || soc_id == 350) { + is_target_SDM632 = true; /* Above SOCID for SDM632 */ + } + } + } + close(fd); + return is_target_SDM632; +} + +int power_hint_override(struct power_module *module, power_hint_t hint, + void *data) +{ + + switch(hint) { + case POWER_HINT_VSYNC: + break; + case POWER_HINT_VIDEO_ENCODE: + { + process_video_encode_hint(data); + return HINT_HANDLED; + } + } + return HINT_NONE; +} + +int set_interactive_override(struct power_module *module, int on) +{ + char governor[80]; + char tmp_str[NODE_MAX]; + struct video_encode_metadata_t video_encode_metadata; + int rc = 0; + + static const char *display_on = "1"; + static const char *display_off = "0"; + char err_buf[80]; + static int init_interactive_hint = 0; + static int set_i_count = 0; + + ALOGI("Got set_interactive hint"); + + if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU0) == -1) { + if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU1) == -1) { + if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU2) == -1) { + if (get_scaling_governor_check_cores(governor, sizeof(governor),CPU3) == -1) { + ALOGE("Can't obtain scaling governor."); + return HINT_HANDLED; + } + } + } + } + + if (!on) { + /* Display off. */ + if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && + (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { + /* timer rate - 40mS*/ + int resource_values[] = {0x41424000, 0x28, + }; + if (!display_hint_sent) { + perform_hint_action(DISPLAY_STATE_HINT_ID, + resource_values, sizeof(resource_values)/sizeof(resource_values[0])); + display_hint_sent = 1; + } + } /* Perf time rate set for CORE0,CORE4 8952 target*/ + + } else { + /* Display on. */ + if ((strncmp(governor, INTERACTIVE_GOVERNOR, strlen(INTERACTIVE_GOVERNOR)) == 0) && + (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { + + undo_hint_action(DISPLAY_STATE_HINT_ID); + display_hint_sent = 0; + } + } + saved_interactive_mode = !!on; + + set_i_count ++; + ALOGI("Got set_interactive hint on= %d, count= %d\n", on, set_i_count); + + if (init_interactive_hint == 0) + { + //First time the display is turned off + display_fd = TEMP_FAILURE_RETRY(open(SYS_DISPLAY_PWR, O_RDWR)); + if (display_fd < 0) { + strerror_r(errno,err_buf,sizeof(err_buf)); + ALOGE("Error opening %s: %s\n", SYS_DISPLAY_PWR, err_buf); + return HINT_HANDLED; + } + else + init_interactive_hint = 1; + } + else + if (!on ) { + /* Display off. */ + rc = TEMP_FAILURE_RETRY(write(display_fd, display_off, strlen(display_off))); + if (rc < 0) { + strerror_r(errno,err_buf,sizeof(err_buf)); + ALOGE("Error writing %s to %s: %s\n", display_off, SYS_DISPLAY_PWR, err_buf); + } + } + else { + /* Display on */ + rc = TEMP_FAILURE_RETRY(write(display_fd, display_on, strlen(display_on))); + if (rc < 0) { + strerror_r(errno,err_buf,sizeof(err_buf)); + ALOGE("Error writing %s to %s: %s\n", display_on, SYS_DISPLAY_PWR, err_buf); + } + } + + return HINT_HANDLED; +} + + +/* Video Encode Hint */ +static void process_video_encode_hint(void *metadata) +{ + char governor[80] = {0}; + int resource_values[20] = {0}; + int num_resources = 0; + struct video_encode_metadata_t video_encode_metadata; + + ALOGI("Got process_video_encode_hint"); + + if (get_scaling_governor_check_cores(governor, + sizeof(governor),CPU0) == -1) { + if (get_scaling_governor_check_cores(governor, + sizeof(governor),CPU1) == -1) { + if (get_scaling_governor_check_cores(governor, + sizeof(governor),CPU2) == -1) { + if (get_scaling_governor_check_cores(governor, + sizeof(governor),CPU3) == -1) { + ALOGE("Can't obtain scaling governor."); + // return HINT_HANDLED; + } + } + } + } + + /* Initialize encode metadata struct fields. */ + memset(&video_encode_metadata, 0, sizeof(struct video_encode_metadata_t)); + video_encode_metadata.state = -1; + video_encode_metadata.hint_id = DEFAULT_VIDEO_ENCODE_HINT_ID; + + if (metadata) { + if (parse_video_encode_metadata((char *)metadata, + &video_encode_metadata) == -1) { + ALOGE("Error occurred while parsing metadata."); + return; + } + } else { + return; + } + + if (video_encode_metadata.state == 1) { + if((strncmp(governor, SCHEDUTIL_GOVERNOR, + strlen(SCHEDUTIL_GOVERNOR)) == 0) && + (strlen(governor) == strlen(SCHEDUTIL_GOVERNOR))) { + if(is_target_SDM632()) { + /* sample_ms = 10mS + * SLB for Core0 = -6 + * SLB for Core1 = -6 + * SLB for Core2 = -6 + * SLB for Core3 = -6 + * hispeed load = 95 + * hispeed freq = 1036 */ + int res[] = {0x41820000, 0xa, + 0x40c68100, 0xfffffffa, + 0x40c68110, 0xfffffffa, + 0x40c68120, 0xfffffffa, + 0x40c68130, 0xfffffffa, + 0x41440100, 0x5f, + 0x4143c100, 0x40c, + }; + memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res))); + num_resources = sizeof(res)/sizeof(res[0]); + pthread_mutex_lock(&camera_hint_mutex); + camera_hint_ref_count++; + if (camera_hint_ref_count == 1) { + if (!video_encode_hint_sent) { + perform_hint_action(video_encode_metadata.hint_id, + resource_values, num_resources); + video_encode_hint_sent = 1; + } + } + pthread_mutex_unlock(&camera_hint_mutex); + } + else { + /* sample_ms = 10mS */ + int res[] = {0x41820000, 0xa, + }; + memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res))); + num_resources = sizeof(res)/sizeof(res[0]); + pthread_mutex_lock(&camera_hint_mutex); + camera_hint_ref_count++; + if (camera_hint_ref_count == 1) { + if (!video_encode_hint_sent) { + perform_hint_action(video_encode_metadata.hint_id, + resource_values, num_resources); + video_encode_hint_sent = 1; + } + } + pthread_mutex_unlock(&camera_hint_mutex); + } + } + else if ((strncmp(governor, INTERACTIVE_GOVERNOR, + strlen(INTERACTIVE_GOVERNOR)) == 0) && + (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) { + /* Sched_load and migration_notification disable + * timer rate - 40mS*/ + int res[] = {0x41430000, 0x1, + 0x41434000, 0x1, + 0x41424000, 0x28, + }; + memcpy(resource_values, res, MIN_VAL(sizeof(resource_values), sizeof(res))); + num_resources = sizeof(res)/sizeof(res[0]); + pthread_mutex_lock(&camera_hint_mutex); + camera_hint_ref_count++; + if (camera_hint_ref_count == 1) { + if (!video_encode_hint_sent) { + perform_hint_action(video_encode_metadata.hint_id, + resource_values, num_resources); + video_encode_hint_sent = 1; + } + } + pthread_mutex_unlock(&camera_hint_mutex); + } + } else if (video_encode_metadata.state == 0) { + if (((strncmp(governor, INTERACTIVE_GOVERNOR, + strlen(INTERACTIVE_GOVERNOR)) == 0) && + (strlen(governor) == strlen(INTERACTIVE_GOVERNOR))) || + ((strncmp(governor, SCHEDUTIL_GOVERNOR, + strlen(SCHEDUTIL_GOVERNOR)) == 0) && + (strlen(governor) == strlen(SCHEDUTIL_GOVERNOR)))) { + pthread_mutex_lock(&camera_hint_mutex); + camera_hint_ref_count--; + if (!camera_hint_ref_count) { + undo_hint_action(video_encode_metadata.hint_id); + video_encode_hint_sent = 0; + } + pthread_mutex_unlock(&camera_hint_mutex); + return ; + } + } + return; +} + + diff --git a/power/power-common.c b/power/power-common.c new file mode 100644 index 0000000..0101bea --- /dev/null +++ b/power/power-common.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_NIDEBUG 0 + +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#include "utils.h" +#include "hint-data.h" +#include "performance.h" +#include "power-common.h" + +static struct hint_handles handles[NUM_HINTS]; + +void power_init() +{ + ALOGI("Initing"); + + for (int i=0; i 0) + handles[hint].ref_count++; + } + else + if (handles[hint].handle > 0) + if (--handles[hint].ref_count == 0) { + release_request(handles[hint].handle); + handles[hint].handle = 0; + } + else + ALOGE("Lock for hint: %X was not acquired, cannot be released", hint); + break; + } +} + +int __attribute__ ((weak)) set_interactive_override(int on) +{ + return HINT_NONE; +} + +void set_interactive(int on) +{ + if (!on) { + /* Send Display OFF hint to perf HAL */ + perf_hint_enable(VENDOR_HINT_DISPLAY_OFF, 0); + } else { + /* Send Display ON hint to perf HAL */ + perf_hint_enable(VENDOR_HINT_DISPLAY_ON, 0); + } + + if (set_interactive_override(on) == HINT_HANDLED) { + return; + } + + ALOGI("Got set_interactive hint"); +} diff --git a/power/power-common.h b/power/power-common.h new file mode 100644 index 0000000..697302a --- /dev/null +++ b/power/power-common.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, 2018-2019 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __POWER_COMMON_H__ +#define __POWER_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NODE_MAX (64) + +#define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" +#define DCVS_CPU0_SLACK_MAX_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_max_us" +#define DCVS_CPU0_SLACK_MIN_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_min_us" +#define MPDECISION_SLACK_MAX_NODE "/sys/module/msm_mpdecision/slack_time_max_us" +#define MPDECISION_SLACK_MIN_NODE "/sys/module/msm_mpdecision/slack_time_min_us" +#define SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq" +#define ONDEMAND_GOVERNOR "ondemand" +#define INTERACTIVE_GOVERNOR "interactive" +#define MSMDCVS_GOVERNOR "msm-dcvs" +#define SCHEDUTIL_GOVERNOR "schedutil" + +#define HINT_HANDLED (0) +#define HINT_NONE (-1) + +#include + +enum CPU_GOV_CHECK { + CPU0 = 0, + CPU1 = 1, + CPU2 = 2, + CPU3 = 3 +}; + +void power_init(void); +void power_hint(power_hint_t hint, void *data); +void set_interactive(int on); + +#ifdef __cplusplus +} +#endif + +#endif //__POWER_COMMON_H___ diff --git a/power/power-msmnile.c b/power/power-msmnile.c new file mode 100644 index 0000000..7000079 --- /dev/null +++ b/power/power-msmnile.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#define LOG_NIDEBUG 0 + +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "QTI PowerHAL" +#include +#include +#include + +#include "power-common.h" + +static int display_fd; +#define SYS_DISPLAY_PWR "/sys/kernel/hbtp/display_pwr" + +int set_interactive_override(int on) +{ + static const char *display_on = "1"; + static const char *display_off = "0"; + char err_buf[80]; + static int init_interactive_hint = 0; + static int set_i_count = 0; + int rc = 0; + + set_i_count ++; + ALOGI("Got set_interactive hint on= %d, count= %d\n", on, set_i_count); + + if (init_interactive_hint == 0) + { + //First time the display is turned off + display_fd = TEMP_FAILURE_RETRY(open(SYS_DISPLAY_PWR, O_RDWR)); + if (display_fd < 0) { + strerror_r(errno,err_buf,sizeof(err_buf)); + ALOGE("Error opening %s: %s\n", SYS_DISPLAY_PWR, err_buf); + } + else + init_interactive_hint = 1; + } + else + if (!on ) { + /* Display off. */ + rc = TEMP_FAILURE_RETRY(write(display_fd, display_off, strlen(display_off))); + if (rc < 0) { + strerror_r(errno,err_buf,sizeof(err_buf)); + ALOGE("Error writing %s to %s: %s\n", display_off, SYS_DISPLAY_PWR, err_buf); + } + } + else { + /* Display on */ + rc = TEMP_FAILURE_RETRY(write(display_fd, display_on, strlen(display_on))); + if (rc < 0) { + strerror_r(errno,err_buf,sizeof(err_buf)); + ALOGE("Error writing %s to %s: %s\n", display_on, SYS_DISPLAY_PWR, err_buf); + } + } + + return HINT_HANDLED; +} + +void interaction(int duration, int num_args, int opt_list[]); + +int power_hint_override(power_hint_t hint, void *data) +{ + int ret_val = HINT_NONE; + switch(hint) { + case POWER_HINT_INTERACTION: + { + int resources[] = {0x40800100, 0x514}; + int duration = 100; + interaction(duration, sizeof(resources)/sizeof(resources[0]), resources); + ret_val = HINT_HANDLED; + } + default: + break; + } + return ret_val; +} diff --git a/power/powerhintparser.c b/power/powerhintparser.c new file mode 100644 index 0000000..6d8646f --- /dev/null +++ b/power/powerhintparser.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "powerhintparser.h" +#define LOG_TAG "QTI PowerHAL" + +int parsePowerhintXML() { + + xmlDocPtr doc; + xmlNodePtr currNode; + const char *opcode_str, *value_str, *type_str; + int opcode = 0, value = 0, type = 0; + int numParams = 0; + static int hintCount; + + if(access(POWERHINT_XML, F_OK) < 0) { + return -1; + } + + doc = xmlReadFile(POWERHINT_XML, "UTF-8", XML_PARSE_RECOVER); + if(!doc) { + ALOGE("Document not parsed successfully"); + return -1; + } + + currNode = xmlDocGetRootElement(doc); + if(!currNode) { + ALOGE("Empty document"); + xmlFreeDoc(doc); + xmlCleanupParser(); + return -1; + } + + // Confirm the root-element of the tree + if(xmlStrcmp(currNode->name, BAD_CAST "Powerhint")) { + ALOGE("document of the wrong type, root node != root"); + xmlFreeDoc(doc); + xmlCleanupParser(); + return -1; + } + + currNode = currNode->xmlChildrenNode; + + for(; currNode != NULL; currNode=currNode->next) { + + if(currNode->type != XML_ELEMENT_NODE) + continue; + + xmlNodePtr node = currNode; + + if(hintCount == MAX_HINT) { + ALOGE("Number of hints exceeded the max count of %d\n",MAX_HINT); + break; + } + + if(!xmlStrcmp(node->name, BAD_CAST "Hint")) { + if(xmlHasProp(node, BAD_CAST "type")) { + type_str = (const char*)xmlGetProp(node, BAD_CAST "type"); + if (type_str == NULL) + { + ALOGE("xmlGetProp failed on type"); + xmlFreeDoc(doc); + xmlCleanupParser(); + return -1; + } + type = strtol(type_str, NULL, 16); + } + + node = node->children; + while(node != NULL) { + if(!xmlStrcmp(node->name, BAD_CAST "Resource")) { + + if(xmlHasProp(node, BAD_CAST "opcode")) { + opcode_str = (const char*)xmlGetProp(node, BAD_CAST "opcode"); + if (opcode_str == NULL) + { + ALOGE("xmlGetProp failed on opcode"); + xmlFreeDoc(doc); + xmlCleanupParser(); + return -1; + } + opcode = strtol(opcode_str, NULL, 16); + } + if(xmlHasProp(node, BAD_CAST "value")) { + value_str = (const char*)xmlGetProp(node, BAD_CAST "value"); + if (value_str == NULL) + { + ALOGE("xmlGetProp failed on value"); + xmlFreeDoc(doc); + xmlCleanupParser(); + return -1; + } + value = strtol(value_str, NULL, 16); + } + if(opcode > 0) { + if(numParams < (MAX_PARAM-1)) { + powerhint[hintCount].paramList[numParams++] = opcode; + powerhint[hintCount].paramList[numParams++] = value; + } else { + ALOGE("Maximum parameters exceeded for Hint ID %x\n",type); + opcode = value = 0; + break; + } + } + + opcode = value = 0; + } + node = node->next; + } + powerhint[hintCount].type = type; + powerhint[hintCount].numParams = numParams; + numParams = 0; + } + hintCount++; + } + + xmlFreeDoc(doc); + xmlCleanupParser(); + return 0; +} + +int* getPowerhint(int hint_id, int *params) { + + int *result = NULL; + + if(!hint_id) + return result; + + ALOGI("Powerhal hint received=%x\n",hint_id); + + if(!powerhint[0].numParams) { + parsePowerhintXML(); + } + + for(int i = 0; i < MAX_HINT; i++) { + if(hint_id == powerhint[i].type) { + *params = powerhint[i].numParams; + result = powerhint[i].paramList; + break; + } + } + + /*for (int j = 0; j < *params; j++) + ALOGI("Powerhal resource again%x = \n", result[j]);*/ + + return result; +} diff --git a/power/powerhintparser.h b/power/powerhintparser.h new file mode 100644 index 0000000..5f9cbe6 --- /dev/null +++ b/power/powerhintparser.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __POWERHINTPARSER__ +#define __POWERHINTPARSER__ + +#define POWERHINT_XML "/vendor/etc/powerhint.xml" +#define MAX_HINT 6 +#define MAX_PARAM 30 + +typedef struct perflock_param_t { + int type; + int numParams; + int paramList[MAX_PARAM];//static limit on number of hints - 15 +}perflock_param_t; + +static perflock_param_t powerhint[MAX_HINT]; + +int parsePowerhintXML(); +int *getPowerhint(int, int*); + +#endif /* __POWERHINTPARSER__ */ diff --git a/power/service.cpp b/power/service.cpp new file mode 100644 index 0000000..902c661 --- /dev/null +++ b/power/service.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "android.hardware.power@1.2-service" + +#include +#include +#include +#include "Power.h" + +using android::sp; +using android::status_t; +using android::OK; + +// libhwbinder: +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; + +// Generated HIDL files +using android::hardware::power::V1_2::IPower; +using android::hardware::power::V1_2::implementation::Power; + +int main() { + + status_t status; + android::sp service = nullptr; + + ALOGI("Power HAL Service 1.2 is starting."); + + service = new Power(); + if (service == nullptr) { + ALOGE("Can not create an instance of Power HAL interface."); + + goto shutdown; + } + + configureRpcThreadpool(1, true /*callerWillJoin*/); + + status = service->registerAsService(); + if (status != OK) { + ALOGE("Could not register service for Power HAL(%d).", status); + goto shutdown; + } + + ALOGI("Power Service is ready"); + joinRpcThreadpool(); + //Should not pass this line + +shutdown: + // In normal operation, we don't expect the thread pool to exit + + ALOGE("Power Service is shutting down"); + return 1; +} + diff --git a/power/utils.c b/power/utils.c new file mode 100644 index 0000000..66c45e0 --- /dev/null +++ b/power/utils.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2012-2013,2015-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define LOG_NIDEBUG 0 + +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "list.h" +#include "hint-data.h" +#include "power-common.h" + +#define LOG_TAG "QTI PowerHAL" +#include + +char scaling_gov_path[4][80] ={ + "sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", + "sys/devices/system/cpu/cpu1/cpufreq/scaling_governor", + "sys/devices/system/cpu/cpu2/cpufreq/scaling_governor", + "sys/devices/system/cpu/cpu3/cpufreq/scaling_governor" +}; + +#define PERF_HAL_PATH "libqti-perfd-client.so" +static void *qcopt_handle; +static int (*perf_lock_acq)(unsigned long handle, int duration, + int list[], int numArgs); +static int (*perf_lock_rel)(unsigned long handle); +static int (*perf_hint)(int, char *, int, int); +static struct list_node active_hint_list_head; + +static void *get_qcopt_handle() +{ + void *handle = NULL; + + dlerror(); + + handle = dlopen(PERF_HAL_PATH, RTLD_NOW); + if (!handle) { + ALOGE("Unable to open %s: %s\n", PERF_HAL_PATH, + dlerror()); + } + + return handle; +} + +static void __attribute__ ((constructor)) initialize(void) +{ + qcopt_handle = get_qcopt_handle(); + + if (!qcopt_handle) { + ALOGE("Failed to get qcopt handle.\n"); + } else { + /* + * qc-opt handle obtained. Get the perflock acquire/release + * function pointers. + */ + perf_lock_acq = dlsym(qcopt_handle, "perf_lock_acq"); + + if (!perf_lock_acq) { + ALOGE("Unable to get perf_lock_acq function handle.\n"); + } + + perf_lock_rel = dlsym(qcopt_handle, "perf_lock_rel"); + + if (!perf_lock_rel) { + ALOGE("Unable to get perf_lock_rel function handle.\n"); + } + + perf_hint = dlsym(qcopt_handle, "perf_hint"); + + if (!perf_hint) { + ALOGE("Unable to get perf_hint function handle.\n"); + } + } +} + +static void __attribute__ ((destructor)) cleanup(void) +{ + if (qcopt_handle) { + if (dlclose(qcopt_handle)) + ALOGE("Error occurred while closing qc-opt library."); + } +} + +int sysfs_read(char *path, char *s, int num_bytes) +{ + char buf[80]; + int count; + int ret = 0; + int fd = open(path, O_RDONLY); + + if (fd < 0) { + strerror_r(errno, buf, sizeof(buf)); + ALOGE("Error opening %s: %s\n", path, buf); + + return -1; + } + + if ((count = read(fd, s, num_bytes - 1)) < 0) { + strerror_r(errno, buf, sizeof(buf)); + ALOGE("Error writing to %s: %s\n", path, buf); + + ret = -1; + } else { + s[count] = '\0'; + } + + close(fd); + + return ret; +} + +int sysfs_write(char *path, char *s) +{ + char buf[80]; + int len; + int ret = 0; + int fd = open(path, O_WRONLY); + + if (fd < 0) { + strerror_r(errno, buf, sizeof(buf)); + ALOGE("Error opening %s: %s\n", path, buf); + return -1 ; + } + + len = write(fd, s, strlen(s)); + if (len < 0) { + strerror_r(errno, buf, sizeof(buf)); + ALOGE("Error writing to %s: %s\n", path, buf); + + ret = -1; + } + + close(fd); + + return ret; +} + +int get_scaling_governor(char governor[], int size) +{ + if (sysfs_read(SCALING_GOVERNOR_PATH, governor, + size) == -1) { + // Can't obtain the scaling governor. Return. + return -1; + } else { + // Strip newline at the end. + int len = strlen(governor); + + len--; + + while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r')) + governor[len--] = '\0'; + } + + return 0; +} + +int get_scaling_governor_check_cores(char governor[], int size,int core_num) +{ + + if (sysfs_read(scaling_gov_path[core_num], governor, + size) == -1) { + // Can't obtain the scaling governor. Return. + return -1; + } + + // Strip newline at the end. + int len = strlen(governor); + len--; + while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r')) + governor[len--] = '\0'; + + return 0; +} + +int is_interactive_governor(char* governor) { + if (strncmp(governor, INTERACTIVE_GOVERNOR, (strlen(INTERACTIVE_GOVERNOR)+1)) == 0) + return 1; + return 0; +} + +void interaction(int duration, int num_args, int opt_list[]) +{ +#ifdef INTERACTION_BOOST + static int lock_handle = 0; + + if (duration < 0 || num_args < 1 || opt_list[0] == NULL) + return; + + if (qcopt_handle) { + if (perf_lock_acq) { + lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args); + if (lock_handle == -1) + ALOGE("Failed to acquire lock."); + } + } +#endif +} + +int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]) +{ + if (duration < 0 || num_args < 1 || opt_list[0] == NULL) + return 0; + + if (qcopt_handle) { + if (perf_lock_acq) { + lock_handle = perf_lock_acq(lock_handle, duration, opt_list, num_args); + if (lock_handle == -1) + ALOGE("Failed to acquire lock."); + } + } + return lock_handle; +} + +//this is interaction_with_handle using perf_hint instead of +//perf_lock_acq +int perf_hint_enable(int hint_id , int duration) +{ + int lock_handle = 0; + + if (duration < 0) + return 0; + + if (qcopt_handle) { + if (perf_hint) { + lock_handle = perf_hint(hint_id, NULL, duration, -1); + if (lock_handle == -1) + ALOGE("Failed to acquire lock for hint_id: %X.", hint_id); + } + } + return lock_handle; +} + + +void release_request(int lock_handle) { + if (qcopt_handle && perf_lock_rel) + perf_lock_rel(lock_handle); +} + +void perform_hint_action(int hint_id, int resource_values[], int num_resources) +{ + if (qcopt_handle) { + if (perf_lock_acq) { + /* Acquire an indefinite lock for the requested resources. */ + int lock_handle = perf_lock_acq(0, 0, resource_values, + num_resources); + + if (lock_handle == -1) { + ALOGE("Failed to acquire lock."); + } else { + /* Add this handle to our internal hint-list. */ + struct hint_data *new_hint = + (struct hint_data *)malloc(sizeof(struct hint_data)); + + if (new_hint) { + if (!active_hint_list_head.compare) { + active_hint_list_head.compare = + (int (*)(void *, void *))hint_compare; + active_hint_list_head.dump = (void (*)(void *))hint_dump; + } + + new_hint->hint_id = hint_id; + new_hint->perflock_handle = lock_handle; + + if (add_list_node(&active_hint_list_head, new_hint) == NULL) { + free(new_hint); + /* Can't keep track of this lock. Release it. */ + if (perf_lock_rel) + perf_lock_rel(lock_handle); + + ALOGE("Failed to process hint."); + } + } else { + /* Can't keep track of this lock. Release it. */ + if (perf_lock_rel) + perf_lock_rel(lock_handle); + + ALOGE("Failed to process hint."); + } + } + } + } +} + +void undo_hint_action(int hint_id) +{ + if (qcopt_handle) { + if (perf_lock_rel) { + /* Get hint-data associated with this hint-id */ + struct list_node *found_node; + struct hint_data temp_hint_data = { + .hint_id = hint_id + }; + + found_node = find_node(&active_hint_list_head, + &temp_hint_data); + + if (found_node) { + /* Release this lock. */ + struct hint_data *found_hint_data = + (struct hint_data *)(found_node->data); + + if (found_hint_data) { + if (perf_lock_rel(found_hint_data->perflock_handle) == -1) + ALOGE("Perflock release failed."); + } + + if (found_node->data) { + /* We can free the hint-data for this node. */ + free(found_node->data); + } + + remove_list_node(&active_hint_list_head, found_node); + } else { + ALOGE("Invalid hint ID."); + } + } + } +} + +/* + * Used to release initial lock holding + * two cores online when the display is on + */ +void undo_initial_hint_action() +{ + if (qcopt_handle) { + if (perf_lock_rel) { + perf_lock_rel(1); + } + } +} diff --git a/power/utils.h b/power/utils.h new file mode 100644 index 0000000..4c3dc7f --- /dev/null +++ b/power/utils.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012-2013,2015-2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +int sysfs_read(char *path, char *s, int num_bytes); +int sysfs_write(char *path, char *s); +int get_scaling_governor(char governor[], int size); +int get_scaling_governor_check_cores(char governor[], int size,int core_num); +int is_interactive_governor(char*); + +void vote_ondemand_io_busy_off(); +void unvote_ondemand_io_busy_off(); +void vote_ondemand_sdf_low(); +void unvote_ondemand_sdf_low(); +void perform_hint_action(int hint_id, int resource_values[], + int num_resources); +void undo_hint_action(int hint_id); +void release_request(int lock_handle); +int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]); +int perf_hint_enable(int hint_id, int duration); diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts index f4745ce..3ed607c 100644 --- a/sepolicy/vendor/file_contexts +++ b/sepolicy/vendor/file_contexts @@ -114,7 +114,7 @@ /data/oemnvitems(/.*)? u:object_r:nv_data_file:s0 /system/vendor/bin/perfd u:object_r:perfd_exec:s0 -/system/vendor/bin/hw/android\.hardware\.power@1\.1-service-qti u:object_r:hal_power_default_exec:s0 +/system/vendor/bin/hw/android\.hardware\.power@1\.2-service u:object_r:hal_power_default_exec:s0 /system/vendor/radio(/.*)? u:object_r:radio_data_file:s0 /system/vendor/bin/qmi_motext_hook u:object_r:rild_exec:s0