From 519f68e658ab7b8a053ff281de3d0f42e67f0d77 Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Wed, 19 Jul 2017 10:26:51 -0700 Subject: Implemantation of VR HAL Moving files from /device/qcom/commom/vr to hardware/qcom/vr Change-Id: Idff688e2ce3d4ee2b69e211a4af1b14c6c55f1cc --- Android.mk | 29 +++++ vr-8998.c | 53 +++++++++ vr.c | 390 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vr_int.h | 37 ++++++ 4 files changed, 509 insertions(+) create mode 100644 Android.mk create mode 100644 vr-8998.c create mode 100644 vr.c create mode 100644 vr_int.h diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..89f2915 --- /dev/null +++ b/Android.mk @@ -0,0 +1,29 @@ +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../device/qcom/common/thermal-engine +LOCAL_MODULE := vr.msm8998 +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_PROPRIETARY_MODULE := true +LOCAL_SRC_FILES := vr.c +LOCAL_SRC_FILES += vr-8998.c +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Wno-unused-parameter + +include $(BUILD_SHARED_LIBRARY) diff --git a/vr-8998.c b/vr-8998.c new file mode 100644 index 0000000..9c6e5a3 --- /dev/null +++ b/vr-8998.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Not a contribution + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "vr_int.h" + +// List thermal configs in format {name, algo_type} +// This list is manually synced with the thermal config + +#define THERMAL_CONFIG_SYNCED 1 + +#if THERMAL_CONFIG_SYNCED + +#define NUM_NON_VR_CONFIGS 4 +static thermal_algo_info_t non_vr_thermal_configs[NUM_NON_VR_CONFIGS] = + {{.config_name = "SKIN-HIGH-FLOOR", .algo_name = "ss"}, + {.config_name = "SKIN-MID-FLOOR", .algo_name = "ss"}, + {.config_name = "SKIN-LOW-FLOOR", .algo_name = "ss"}, + {.config_name = "VIRTUAL-SS-GPU-SKIN", .algo_name = "ss"}}; + +#define NUM_VR_CONFIGS 1 +static thermal_algo_info_t vr_thermal_configs[NUM_VR_CONFIGS] = + {{.config_name = "VR-EMMC", .algo_name = "monitor"}}; + +int load_thermal_cfg_info(thermal_cfg_info_t *non_vr, thermal_cfg_info_t *vr) { + + if(!non_vr || !vr) + return -1; + + non_vr->num_cfgs = NUM_NON_VR_CONFIGS; + non_vr->cfgs = &non_vr_thermal_configs[0]; + + vr->num_cfgs = NUM_VR_CONFIGS; + vr->cfgs = &vr_thermal_configs[0]; + + return 0; +} + +#endif diff --git a/vr.c b/vr.c new file mode 100644 index 0000000..4ba87e6 --- /dev/null +++ b/vr.c @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "VrHALImpl" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "thermal_client.h" +#include "vr_int.h" + + +static void *dlhandle; +static int (*p_thermal_client_config_query)(char *, struct config_instance **); +static int (*p_thermal_client_config_set)(struct config_instance *, unsigned int); +static void (*p_thermal_client_config_cleanup)(struct config_instance *, unsigned int); + +static int max_string_size = 36; +static int error_state = 0; //global error state - don't do anything if set! + +#define DEBUG 1 + +static thermal_cfg_info_t non_vr_thermal_cfgs; +static thermal_cfg_info_t vr_thermal_cfgs; + +int __attribute__ ((weak)) load_thermal_cfg_info(thermal_cfg_info_t *non_vr, + thermal_cfg_info_t *vr) { + + non_vr->num_cfgs = 0; + vr->num_cfgs = 0; + + return 0; +} + +/** + * Debug function for printing out a log instance + */ +static void log_config_instance(struct config_instance *instance ){ + ALOGI("logging config_instance 0x%p", instance); + ALOGI("config_instance: cfg_desc = %s", instance->cfg_desc); + ALOGI("config_instance: algo_type = %s", instance->algo_type); + ALOGI("config_instance: fields_mask = 0x%x", instance->fields_mask); + ALOGI("config_instance: num_fields = %u", instance->num_fields); + for (uint32_t i = 0; i < instance->num_fields; i++) { + ALOGI("config_instance: field_data[%d]", i); + ALOGI("\tfield_name = %s", instance->fields[i].field_name); + ALOGI("\tdata_type = %u", instance->fields[i].data_type); + ALOGI("\tnum_data = %u", instance->fields[i].num_data); + switch (instance->fields[i].data_type){ + case FIELD_INT: ALOGI("\tdata = %d", *(int*)(instance->fields[i].data)); + break; + case FIELD_STR: ALOGI("\tdata = %s", (char*)(instance->fields[i].data)); + break; + default: ALOGI("\tdata = 0x%p", instance->fields[i].data); + break; + } + } +} + +/** + * Debug function for printing out all instances of "ss" and "monitor" algos + */ +static void query_thermal_config(){ + struct config_instance *instances; + + int num_configs = (*p_thermal_client_config_query)("ss", &instances); + if (num_configs <= 0) { + return; + } + for (int i = 0; i < num_configs; i++) { + log_config_instance(&(instances[i])); + } + if (num_configs > 0) { + (*p_thermal_client_config_cleanup)(instances, num_configs); + } + + num_configs = (*p_thermal_client_config_query)("monitor", &instances); + if (num_configs <= 0) { + return; + } + for (int i = 0; i < num_configs; i++) { + log_config_instance(&(instances[i])); + } + if (num_configs > 0) { + (*p_thermal_client_config_cleanup)(instances, num_configs); + } +} + +/** + * Load the thermal client library + * returns 0 on success + */ +static int load_thermal_client(void) +{ + char *thermal_client_so = "vendor/lib64/libthermalclient.so"; + + dlhandle = dlopen(thermal_client_so, RTLD_NOW | RTLD_LOCAL); + if (dlhandle) { + dlerror(); + p_thermal_client_config_query = (int (*) (char *, struct config_instance **)) + dlsym(dlhandle, "thermal_client_config_query"); + if (dlerror()) { + ALOGE("Unable to load thermal_client_config_query"); + goto error_handle; + } + + p_thermal_client_config_set = (int (*) (struct config_instance *, unsigned int)) + dlsym(dlhandle, "thermal_client_config_set"); + if (dlerror()) { + ALOGE("Unable to load thermal_client_config_set"); + goto error_handle; + } + + p_thermal_client_config_cleanup = (void (*) (struct config_instance *, unsigned int)) + dlsym(dlhandle, "thermal_client_config_cleanup"); + if (dlerror()) { + ALOGE("Unable to load thermal_client_config_cleanup"); + goto error_handle; + } + } else { + ALOGE("unable to open %s", thermal_client_so); + return -1; + } + return 0; + +error_handle: + ALOGE("Error opening functions from %s", thermal_client_so); + p_thermal_client_config_query = NULL; + p_thermal_client_config_set = NULL; + p_thermal_client_config_cleanup = NULL; + dlclose(dlhandle); + dlhandle = NULL; + return -1; +} + +/** + * Allocate a new struct config_instance for modifying the disable field + */ +static struct config_instance *allocate_config_instance(){ + struct config_instance *config = (struct config_instance *)malloc(sizeof(struct config_instance)); + memset(config, 0, sizeof(*config)); + + config->cfg_desc = (char *)malloc(sizeof(char) * max_string_size); + memset(config->cfg_desc, 0, sizeof(char)*max_string_size); + + config->algo_type = (char *)malloc(sizeof(char) * max_string_size); + memset(config->algo_type, 0, sizeof(char) * max_string_size); + + config->fields = (struct field_data *)malloc(sizeof(struct field_data)); + memset(config->fields, 0, sizeof(*config->fields)); + + config->fields[0].field_name = (char*)malloc(sizeof(char) * max_string_size); + memset(config->fields[0].field_name, 0, sizeof(char) * max_string_size); + + config->fields[0].data = (void*)malloc(sizeof(int)); + + return config; +} +/** + * Free the config_instance as allocated in allocate_config_instance + */ +static void free_config_instance(struct config_instance *config){ + + free(config->fields[0].data); + free(config->fields[0].field_name); + free(config->fields); + free(config->algo_type); + free(config->cfg_desc); + free(config); +} + +/** + * disable a thermal config + * returns 1 on success, anything else is a failure + */ +static int disable_config(char *config_name, char *algo_type){ + int result = 0; + if (error_state) { + return 0; + } + struct config_instance *config = allocate_config_instance(); + strlcpy(config->cfg_desc, config_name, max_string_size); + strlcpy(config->algo_type, algo_type, max_string_size); + strlcpy(config->fields[0].field_name, "disable", max_string_size); + + config->fields_mask |= DISABLE_FIELD; + config->num_fields = 1; + config->fields[0].data_type = FIELD_INT; + config->fields[0].num_data = 1; + *(int*)(config->fields[0].data) = 1; //DISABLE + + + result = (*p_thermal_client_config_set)(config, 1); + if (DEBUG) { + ALOGE("disable profile: name = %s, algo_type = %s, success = %d", config_name, algo_type, result); + } + free_config_instance(config); + + return result; +} + +/** + * enable a thermal config + * returns 1 on success, anything else is failure + */ +static int enable_config(char *config_name, char *algo_type){ + int result = 0; + if (error_state) { + return 0; + } + struct config_instance *config = allocate_config_instance(); + strlcpy(config->cfg_desc, config_name, max_string_size); + strlcpy(config->algo_type, algo_type, max_string_size); + strlcpy(config->fields[0].field_name, "disable", max_string_size); + + config->fields_mask |= DISABLE_FIELD; + config->num_fields = 1; + config->fields[0].data_type = FIELD_INT; + config->fields[0].num_data = 1; + *(int*)(config->fields[0].data) = 0; //ENABLE + + result = (*p_thermal_client_config_set)(config, 1); + if (DEBUG) { + ALOGE("enable profile: name = %s, algo_type = %s, success = %d", + config_name, algo_type, result); + } + + free_config_instance(config); + + return result; +} + +/** + * Call this if there is a compoenent-fatal error + * Attempts to clean up any outstanding thermal config state + */ +static void error_cleanup(){ + //disable VR configs, best-effort so ignore return values + for (unsigned int i = 0; i < vr_thermal_cfgs.num_cfgs; i++) { + disable_config(vr_thermal_cfgs.cfgs[i].config_name, vr_thermal_cfgs.cfgs[i].algo_name); + } + + // enable non-VR profile, best-effort so ignore return values + for (unsigned int i = 0; i < non_vr_thermal_cfgs.num_cfgs; i++) { + enable_config(non_vr_thermal_cfgs.cfgs[i].config_name, non_vr_thermal_cfgs.cfgs[i].algo_name); + } + + // set global error flag + error_state = 1; +} + +/* + * Set global display/GPU/scheduler configuration to used for VR apps. + */ +static void set_vr_thermal_configuration() { + int result = 1; + if (error_state) { + return; + } + //disable non-VR configs + for (unsigned int i = 0; i < non_vr_thermal_cfgs.num_cfgs; i++) { + result = disable_config(non_vr_thermal_cfgs.cfgs[i].config_name, non_vr_thermal_cfgs.cfgs[i].algo_name); + if (result != 1) + { + goto error; + } + } + + //enable VR configs + for (unsigned int i = 0; i < vr_thermal_cfgs.num_cfgs; i++) { + result = enable_config(vr_thermal_cfgs.cfgs[i].config_name, vr_thermal_cfgs.cfgs[i].algo_name); + if (result != 1) + { + goto error; + } + } + + if (DEBUG) { + query_thermal_config(); + } + + return; + +error: + error_cleanup(); + return; +} + +/* + * Reset to default global display/GPU/scheduler configuration. + */ +static void unset_vr_thermal_configuration() { + int result = 1; + if (error_state) { + return; + } + + //disable VR configs + for (unsigned int i = 0; i < vr_thermal_cfgs.num_cfgs; i++) { + result = disable_config(vr_thermal_cfgs.cfgs[i].config_name, vr_thermal_cfgs.cfgs[i].algo_name); + if (result != 1) { + goto error; + } + } + + // enable non-VR profile + for (unsigned int i = 0; i < non_vr_thermal_cfgs.num_cfgs; i++) { + result = enable_config(non_vr_thermal_cfgs.cfgs[i].config_name, non_vr_thermal_cfgs.cfgs[i].algo_name); + if (result != 1) { + goto error; + } + } + + if (DEBUG) { + query_thermal_config(); + } + + return; + +error: + error_cleanup(); + return; +} + +static void vr_init(struct vr_module *module) +{ + int success = load_thermal_client(); + if (success != 0) { + ALOGE("failed to load thermal client"); + error_state = 1; + } + success = load_thermal_cfg_info(&non_vr_thermal_cfgs, &vr_thermal_cfgs); + if (success != 0) { + ALOGE("failed to load thermal configs"); + error_state = 1; + } + +} + +static void vr_set_vr_mode(struct vr_module *module, bool enabled) +{ + if (enabled) { + set_vr_thermal_configuration(); + } else { + unset_vr_thermal_configuration(); + } +} + +static struct hw_module_methods_t vr_module_methods = { + .open = NULL, // There are no devices for this HAL interface. +}; + + +vr_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = VR_MODULE_API_VERSION_1_0, + .hal_api_version = HARDWARE_HAL_API_VERSION, + .id = VR_HARDWARE_MODULE_ID, + .name = "VR HAL", + .author = "Code Aurora Forum", + .methods = &vr_module_methods, + }, + + .init = vr_init, + .set_vr_mode = vr_set_vr_mode, +}; diff --git a/vr_int.h b/vr_int.h new file mode 100644 index 0000000..b7e0d26 --- /dev/null +++ b/vr_int.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +typedef struct _thermal_algo_info{ + char * config_name; + char * algo_name; +}thermal_algo_info_t; +typedef struct _thermal_cfg_info { + unsigned int num_cfgs; + thermal_algo_info_t * cfgs; +}thermal_cfg_info_t; -- cgit v1.2.3