* a hidl replacement exist Change-Id: I2df55148c1492a93f321e3b3a31f0704c071b9aatirimbino
parent
eeb666cf00
commit
9a8c691ced
@ -1,39 +0,0 @@ |
|||||||
# Copyright (C) 2015 The CyanogenMod 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.
|
|
||||||
|
|
||||||
ifeq ($(TARGET_POWERHAL_VARIANT),samsung) |
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS) |
|
||||||
|
|
||||||
LOCAL_SRC_FILES := power.c
|
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := \
|
|
||||||
$(LOCAL_PATH)/include \
|
|
||||||
$(LOCAL_PATH)/../hidl/light/include
|
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := liblog libcutils
|
|
||||||
|
|
||||||
LOCAL_MODULE := power.$(TARGET_BOOTLOADER_BOARD_NAME)
|
|
||||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
|
||||||
LOCAL_MODULE_TAGS := optional
|
|
||||||
|
|
||||||
ifneq ($(TARGET_TAP_TO_WAKE_NODE),) |
|
||||||
LOCAL_CFLAGS := -DTARGET_TAP_TO_WAKE_NODE=\"$(TARGET_TAP_TO_WAKE_NODE)\"
|
|
||||||
endif |
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY) |
|
||||||
|
|
||||||
endif |
|
@ -1,38 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (C) 2016 The CyanogenMod 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. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef SAMSUNG_POWER_H |
|
||||||
#define SAMSUNG_POWER_H |
|
||||||
|
|
||||||
/*
|
|
||||||
* Board specific nodes |
|
||||||
* |
|
||||||
* If your kernel exposes these controls in another place, you can either |
|
||||||
* symlink to the locations given here, or override this header in your |
|
||||||
* device tree. |
|
||||||
*/ |
|
||||||
|
|
||||||
static const char* CPU_SYSFS_PATHS[2] = { |
|
||||||
"/sys/devices/system/cpu/cpu0", |
|
||||||
"/sys/devices/system/cpu/cpu4" |
|
||||||
}; |
|
||||||
|
|
||||||
static const char* CPU_INTERACTIVE_PATHS[2] = { |
|
||||||
"/sys/devices/system/cpu/cpu0/cpufreq/interactive", |
|
||||||
"/sys/devices/system/cpu/cpu4/cpufreq/interactive" |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // SAMSUNG_POWER_H
|
|
@ -1,585 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (C) 2012 The Android Open Source Project |
|
||||||
* Copyright (C) 2014 The CyanogenMod Project |
|
||||||
* Copyright (C) 2014-2015 Andreas Schneider <asn@cryptomilk.org> |
|
||||||
* Copyright (C) 2014-2017 Christopher N. Hesse <raymanfx@gmail.com> |
|
||||||
* |
|
||||||
* 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 <ctype.h> |
|
||||||
#include <dirent.h> |
|
||||||
#include <errno.h> |
|
||||||
#include <fcntl.h> |
|
||||||
#include <malloc.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
#include <unistd.h> |
|
||||||
|
|
||||||
#include <sys/types.h> |
|
||||||
|
|
||||||
#define LOG_TAG "SamsungPowerHAL" |
|
||||||
/* #define LOG_NDEBUG 0 */ |
|
||||||
#include <utils/Log.h> |
|
||||||
|
|
||||||
#include <hardware/hardware.h> |
|
||||||
#include <hardware/power.h> |
|
||||||
#include "samsung_lights.h" |
|
||||||
|
|
||||||
#include "samsung_power.h" |
|
||||||
|
|
||||||
#define BOOST_PATH "/boost" |
|
||||||
#define BOOSTPULSE_PATH "/boostpulse" |
|
||||||
|
|
||||||
#define IO_IS_BUSY_PATH "/io_is_busy" |
|
||||||
#define HISPEED_FREQ_PATH "/hispeed_freq" |
|
||||||
|
|
||||||
#define MAX_FREQ_PATH "/cpufreq/scaling_max_freq" |
|
||||||
|
|
||||||
#define CLUSTER_COUNT ARRAY_SIZE(CPU_SYSFS_PATHS) |
|
||||||
#define PARAM_MAXLEN 10 |
|
||||||
|
|
||||||
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) |
|
||||||
|
|
||||||
struct samsung_power_module { |
|
||||||
struct power_module base; |
|
||||||
pthread_mutex_t lock; |
|
||||||
int boost_fd; |
|
||||||
int boostpulse_fd; |
|
||||||
char hispeed_freqs[CLUSTER_COUNT][PARAM_MAXLEN]; |
|
||||||
char max_freqs[CLUSTER_COUNT][PARAM_MAXLEN]; |
|
||||||
char* touchscreen_power_path; |
|
||||||
char* touchkey_power_path; |
|
||||||
}; |
|
||||||
|
|
||||||
enum power_profile_e { |
|
||||||
PROFILE_POWER_SAVE = 0, |
|
||||||
PROFILE_BALANCED, |
|
||||||
PROFILE_HIGH_PERFORMANCE, |
|
||||||
PROFILE_MAX |
|
||||||
}; |
|
||||||
|
|
||||||
static enum power_profile_e current_power_profile = PROFILE_BALANCED; |
|
||||||
|
|
||||||
// Custom Lineage hints
|
|
||||||
const static power_hint_t POWER_HINT_CPU_BOOST = (power_hint_t)0x00000110; |
|
||||||
const static power_hint_t POWER_HINT_SET_PROFILE = (power_hint_t)0x00000111; |
|
||||||
|
|
||||||
/**********************************************************
|
|
||||||
*** HELPER FUNCTIONS |
|
||||||
**********************************************************/ |
|
||||||
|
|
||||||
static int sysfs_read(char *path, char *s, int num_bytes) |
|
||||||
{ |
|
||||||
char errno_str[64]; |
|
||||||
int len; |
|
||||||
int ret = 0; |
|
||||||
int fd; |
|
||||||
|
|
||||||
fd = open(path, O_RDONLY); |
|
||||||
if (fd < 0) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Error opening %s: %s", path, errno_str); |
|
||||||
|
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
len = read(fd, s, num_bytes - 1); |
|
||||||
if (len < 0) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Error reading from %s: %s", path, errno_str); |
|
||||||
|
|
||||||
ret = -1; |
|
||||||
} else { |
|
||||||
// do not store newlines, but terminate the string instead
|
|
||||||
if (s[len-1] == '\n') { |
|
||||||
s[len-1] = '\0'; |
|
||||||
} else { |
|
||||||
s[len] = '\0'; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
close(fd); |
|
||||||
|
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
static void sysfs_write(const char *path, char *s) |
|
||||||
{ |
|
||||||
char errno_str[64]; |
|
||||||
int len; |
|
||||||
int fd; |
|
||||||
|
|
||||||
fd = open(path, O_WRONLY); |
|
||||||
if (fd < 0) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Error opening %s: %s", path, errno_str); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
len = write(fd, s, strlen(s)); |
|
||||||
if (len < 0) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Error writing to %s: %s", path, errno_str); |
|
||||||
} |
|
||||||
|
|
||||||
close(fd); |
|
||||||
} |
|
||||||
|
|
||||||
static void cpu_sysfs_read(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN]) |
|
||||||
{ |
|
||||||
char path[PATH_MAX]; |
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(CPU_SYSFS_PATHS); i++) { |
|
||||||
sprintf(path, "%s%s", CPU_SYSFS_PATHS[i], param); |
|
||||||
sysfs_read(path, s[i], PARAM_MAXLEN); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void cpu_sysfs_write(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN]) |
|
||||||
{ |
|
||||||
char path[PATH_MAX]; |
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(CPU_SYSFS_PATHS); i++) { |
|
||||||
sprintf(path, "%s%s", CPU_SYSFS_PATHS[i], param); |
|
||||||
sysfs_write(path, s[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void cpu_interactive_read(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN]) |
|
||||||
{ |
|
||||||
char path[PATH_MAX]; |
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(CPU_INTERACTIVE_PATHS); i++) { |
|
||||||
sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[i], param); |
|
||||||
sysfs_read(path, s[i], PARAM_MAXLEN); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void cpu_interactive_write(const char *param, char s[CLUSTER_COUNT][PARAM_MAXLEN]) |
|
||||||
{ |
|
||||||
char path[PATH_MAX]; |
|
||||||
|
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(CPU_INTERACTIVE_PATHS); i++) { |
|
||||||
sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[i], param); |
|
||||||
sysfs_write(path, s[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void send_boost(int boost_fd, int32_t duration_us) |
|
||||||
{ |
|
||||||
int len; |
|
||||||
|
|
||||||
if (boost_fd < 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
len = write(boost_fd, "1", 1); |
|
||||||
if (len < 0) { |
|
||||||
ALOGE("Error writing to %s%s: %s", CPU_INTERACTIVE_PATHS[0], BOOST_PATH, strerror(errno)); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
usleep(duration_us); |
|
||||||
len = write(boost_fd, "0", 1); |
|
||||||
} |
|
||||||
|
|
||||||
static void send_boostpulse(int boostpulse_fd) |
|
||||||
{ |
|
||||||
int len; |
|
||||||
|
|
||||||
if (boostpulse_fd < 0) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
len = write(boostpulse_fd, "1", 1); |
|
||||||
if (len < 0) { |
|
||||||
ALOGE("Error writing to %s%s: %s", CPU_INTERACTIVE_PATHS[0], BOOSTPULSE_PATH, |
|
||||||
strerror(errno)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static int get_cur_panel_brightness() { |
|
||||||
int ret = 0; |
|
||||||
int read_status; |
|
||||||
// brightness can range from 0 to 255, so max. 3 chars + '\0'
|
|
||||||
char panel_brightness[4]; |
|
||||||
// for strtol
|
|
||||||
char *dummy; |
|
||||||
const int base = 10; |
|
||||||
|
|
||||||
read_status = sysfs_read(PANEL_BRIGHTNESS_NODE, panel_brightness, sizeof(PANEL_BRIGHTNESS_NODE)); |
|
||||||
if (read_status < 0) { |
|
||||||
ALOGE("%s: Failed to read panel brightness from %s!\n", __func__, PANEL_BRIGHTNESS_NODE); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
ret = strtol(panel_brightness, &dummy, base); |
|
||||||
ALOGV("%s: Panel brightness is: %d", __func__, ret); |
|
||||||
|
|
||||||
return ret; |
|
||||||
} |
|
||||||
|
|
||||||
/**********************************************************
|
|
||||||
*** POWER FUNCTIONS |
|
||||||
**********************************************************/ |
|
||||||
|
|
||||||
static void set_power_profile(struct samsung_power_module *samsung_pwr, |
|
||||||
int profile) |
|
||||||
{ |
|
||||||
if (profile < 0 || profile >= PROFILE_MAX) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (current_power_profile == profile) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
ALOGV("%s: profile=%d", __func__, profile); |
|
||||||
|
|
||||||
switch (profile) { |
|
||||||
case PROFILE_POWER_SAVE: |
|
||||||
// Grab value set by init.*.rc
|
|
||||||
cpu_interactive_read(HISPEED_FREQ_PATH, samsung_pwr->hispeed_freqs); |
|
||||||
// Limit to hispeed freq
|
|
||||||
cpu_sysfs_write(MAX_FREQ_PATH, samsung_pwr->hispeed_freqs); |
|
||||||
ALOGV("%s: set powersave mode", __func__); |
|
||||||
break; |
|
||||||
case PROFILE_BALANCED: |
|
||||||
// Restore normal max freq
|
|
||||||
cpu_sysfs_write(MAX_FREQ_PATH, samsung_pwr->max_freqs); |
|
||||||
ALOGV("%s: set balanced mode", __func__); |
|
||||||
break; |
|
||||||
case PROFILE_HIGH_PERFORMANCE: |
|
||||||
// Restore normal max freq
|
|
||||||
cpu_sysfs_write(MAX_FREQ_PATH, samsung_pwr->max_freqs); |
|
||||||
ALOGV("%s: set performance mode", __func__); |
|
||||||
break; |
|
||||||
default: |
|
||||||
ALOGW("%s: Unknown power profile: %d", __func__, profile); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
current_power_profile = profile; |
|
||||||
} |
|
||||||
|
|
||||||
static void find_input_nodes(struct samsung_power_module *samsung_pwr, char *dir) |
|
||||||
{ |
|
||||||
const char filename[] = "name"; |
|
||||||
char errno_str[64]; |
|
||||||
struct dirent *de; |
|
||||||
char file_content[20]; |
|
||||||
char *path = NULL; |
|
||||||
char *node_path = NULL; |
|
||||||
size_t pathsize; |
|
||||||
size_t node_pathsize; |
|
||||||
DIR *d; |
|
||||||
|
|
||||||
d = opendir(dir); |
|
||||||
if (d == NULL) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
while ((de = readdir(d)) != NULL) { |
|
||||||
if (strncmp(filename, de->d_name, sizeof(filename)) == 0) { |
|
||||||
pathsize = strlen(dir) + strlen(de->d_name) + 2; |
|
||||||
node_pathsize = strlen(dir) + strlen("enabled") + 2; |
|
||||||
|
|
||||||
path = malloc(pathsize); |
|
||||||
node_path = malloc(node_pathsize); |
|
||||||
if (path == NULL || node_path == NULL) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Out of memory: %s", errno_str); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
snprintf(path, pathsize, "%s/%s", dir, filename); |
|
||||||
sysfs_read(path, file_content, sizeof(file_content)); |
|
||||||
|
|
||||||
snprintf(node_path, node_pathsize, "%s/%s", dir, "enabled"); |
|
||||||
|
|
||||||
if (strncmp(file_content, "sec_touchkey", 12) == 0) { |
|
||||||
ALOGV("%s: found touchkey path: %s", __func__, node_path); |
|
||||||
samsung_pwr->touchkey_power_path = malloc(node_pathsize); |
|
||||||
if (samsung_pwr->touchkey_power_path == NULL) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Out of memory: %s", errno_str); |
|
||||||
return; |
|
||||||
} |
|
||||||
snprintf(samsung_pwr->touchkey_power_path, node_pathsize, |
|
||||||
"%s", node_path); |
|
||||||
} |
|
||||||
|
|
||||||
if (strncmp(file_content, "sec_touchscreen", 15) == 0) { |
|
||||||
ALOGV("%s: found touchscreen path: %s", __func__, node_path); |
|
||||||
samsung_pwr->touchscreen_power_path = malloc(node_pathsize); |
|
||||||
if (samsung_pwr->touchscreen_power_path == NULL) { |
|
||||||
strerror_r(errno, errno_str, sizeof(errno_str)); |
|
||||||
ALOGE("Out of memory: %s", errno_str); |
|
||||||
return; |
|
||||||
} |
|
||||||
snprintf(samsung_pwr->touchscreen_power_path, node_pathsize, |
|
||||||
"%s", node_path); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (path) |
|
||||||
free(path); |
|
||||||
if (node_path) |
|
||||||
free(node_path); |
|
||||||
closedir(d); |
|
||||||
} |
|
||||||
|
|
||||||
/**********************************************************
|
|
||||||
*** INIT FUNCTIONS |
|
||||||
**********************************************************/ |
|
||||||
|
|
||||||
static void init_cpufreqs(struct samsung_power_module *samsung_pwr) |
|
||||||
{ |
|
||||||
cpu_interactive_read(HISPEED_FREQ_PATH, samsung_pwr->hispeed_freqs); |
|
||||||
cpu_sysfs_read(MAX_FREQ_PATH, samsung_pwr->max_freqs); |
|
||||||
} |
|
||||||
|
|
||||||
static void init_touch_input_power_path(struct samsung_power_module *samsung_pwr) |
|
||||||
{ |
|
||||||
char dir[1024]; |
|
||||||
uint32_t i; |
|
||||||
|
|
||||||
for (i = 0; i < 20; i++) { |
|
||||||
snprintf(dir, sizeof(dir), "/sys/class/input/input%d", i); |
|
||||||
find_input_nodes(samsung_pwr, dir); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void boost_open(struct samsung_power_module *samsung_pwr) |
|
||||||
{ |
|
||||||
char path[PATH_MAX]; |
|
||||||
|
|
||||||
// the boost node is only valid for the LITTLE cluster
|
|
||||||
sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[0], BOOST_PATH); |
|
||||||
|
|
||||||
samsung_pwr->boost_fd = open(path, O_WRONLY); |
|
||||||
if (samsung_pwr->boost_fd < 0) { |
|
||||||
ALOGE("Error opening %s: %s\n", path, strerror(errno)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void boostpulse_open(struct samsung_power_module *samsung_pwr) |
|
||||||
{ |
|
||||||
char path[PATH_MAX]; |
|
||||||
|
|
||||||
// the boostpulse node is only valid for the LITTLE cluster
|
|
||||||
sprintf(path, "%s%s", CPU_INTERACTIVE_PATHS[0], BOOSTPULSE_PATH); |
|
||||||
|
|
||||||
samsung_pwr->boostpulse_fd = open(path, O_WRONLY); |
|
||||||
if (samsung_pwr->boostpulse_fd < 0) { |
|
||||||
ALOGE("Error opening %s: %s\n", path, strerror(errno)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void samsung_power_init(struct power_module *module) |
|
||||||
{ |
|
||||||
struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module; |
|
||||||
|
|
||||||
init_cpufreqs(samsung_pwr); |
|
||||||
|
|
||||||
// keep interactive boost fds opened
|
|
||||||
boost_open(samsung_pwr); |
|
||||||
boostpulse_open(samsung_pwr); |
|
||||||
|
|
||||||
samsung_pwr->touchscreen_power_path = NULL; |
|
||||||
samsung_pwr->touchkey_power_path = NULL; |
|
||||||
init_touch_input_power_path(samsung_pwr); |
|
||||||
|
|
||||||
ALOGI("Initialized settings:"); |
|
||||||
char max_freqs[PATH_MAX]; |
|
||||||
sprintf(max_freqs, "max_freqs: cluster[0]: %s", samsung_pwr->max_freqs[0]); |
|
||||||
for (unsigned int i = 1; i < CLUSTER_COUNT; i++) { |
|
||||||
sprintf(max_freqs, "%s, %s[%d]: %s", max_freqs, "cluster", i, samsung_pwr->max_freqs[i]); |
|
||||||
} |
|
||||||
ALOGI("%s", max_freqs); |
|
||||||
char hispeed_freqs[PATH_MAX]; |
|
||||||
sprintf(hispeed_freqs, "hispeed_freqs: cluster[0]: %s", samsung_pwr->hispeed_freqs[0]); |
|
||||||
for (unsigned int i = 1; i < CLUSTER_COUNT; i++) { |
|
||||||
sprintf(hispeed_freqs, "%s, %s[%d]: %s", hispeed_freqs, "cluster", i, |
|
||||||
samsung_pwr->hispeed_freqs[i]); |
|
||||||
} |
|
||||||
ALOGI("%s", hispeed_freqs); |
|
||||||
ALOGI("boostpulse_fd: %d", samsung_pwr->boostpulse_fd); |
|
||||||
ALOGI("touchscreen_power_path: %s", |
|
||||||
samsung_pwr->touchscreen_power_path ? samsung_pwr->touchscreen_power_path : "NULL"); |
|
||||||
ALOGI("touchkey_power_path: %s", |
|
||||||
samsung_pwr->touchkey_power_path ? samsung_pwr->touchkey_power_path : "NULL"); |
|
||||||
} |
|
||||||
|
|
||||||
/**********************************************************
|
|
||||||
*** API FUNCTIONS |
|
||||||
*** |
|
||||||
*** Refer to power.h for documentation. |
|
||||||
**********************************************************/ |
|
||||||
|
|
||||||
static void samsung_power_set_interactive(struct power_module *module, int on) |
|
||||||
{ |
|
||||||
struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module; |
|
||||||
int panel_brightness; |
|
||||||
char button_state[2]; |
|
||||||
int rc; |
|
||||||
static bool touchkeys_blocked = false; |
|
||||||
char ON[CLUSTER_COUNT][PARAM_MAXLEN] = {"1", "1"}; |
|
||||||
char OFF[CLUSTER_COUNT][PARAM_MAXLEN] = {"0", "0"}; |
|
||||||
|
|
||||||
ALOGV("power_set_interactive: %d", on); |
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not disable any input devices if the screen is on but we are in a non-interactive |
|
||||||
* state. |
|
||||||
*/ |
|
||||||
if (!on) { |
|
||||||
panel_brightness = get_cur_panel_brightness(); |
|
||||||
if (panel_brightness < 0) { |
|
||||||
ALOGE("%s: Failed to read panel brightness", __func__); |
|
||||||
} else if (panel_brightness > 0) { |
|
||||||
ALOGV("%s: Moving to non-interactive state, but screen is still on," |
|
||||||
" not disabling input devices", __func__); |
|
||||||
goto out; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Sanity check the touchscreen path */ |
|
||||||
if (samsung_pwr->touchscreen_power_path) { |
|
||||||
sysfs_write(samsung_pwr->touchscreen_power_path, on ? "1" : "0"); |
|
||||||
} |
|
||||||
|
|
||||||
/* Bail out if the device does not have touchkeys */ |
|
||||||
if (samsung_pwr->touchkey_power_path == NULL) { |
|
||||||
goto out; |
|
||||||
} |
|
||||||
|
|
||||||
if (!on) { |
|
||||||
rc = sysfs_read(samsung_pwr->touchkey_power_path, button_state, ARRAY_SIZE(button_state)); |
|
||||||
if (rc < 0) { |
|
||||||
ALOGE("%s: Failed to read touchkey state", __func__); |
|
||||||
goto out; |
|
||||||
} |
|
||||||
/*
|
|
||||||
* If button_state is 0, the keys have been disabled by another component |
|
||||||
* (for example cmhw), which means we don't want them to be enabled when resuming |
|
||||||
* from suspend. |
|
||||||
*/ |
|
||||||
if (button_state[0] == '0') { |
|
||||||
touchkeys_blocked = true; |
|
||||||
} else { |
|
||||||
touchkeys_blocked = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (!touchkeys_blocked) { |
|
||||||
sysfs_write(samsung_pwr->touchkey_power_path, on ? "1" : "0"); |
|
||||||
} |
|
||||||
|
|
||||||
out: |
|
||||||
cpu_interactive_write(IO_IS_BUSY_PATH, on ? ON : OFF); |
|
||||||
|
|
||||||
ALOGV("power_set_interactive: %d done", on); |
|
||||||
} |
|
||||||
|
|
||||||
static void samsung_power_hint(struct power_module *module, |
|
||||||
power_hint_t hint, |
|
||||||
void *data) |
|
||||||
{ |
|
||||||
struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module; |
|
||||||
|
|
||||||
/* Bail out if low-power mode is active */ |
|
||||||
if (current_power_profile == PROFILE_POWER_SAVE && hint != POWER_HINT_LOW_POWER |
|
||||||
&& hint != POWER_HINT_SET_PROFILE && hint != POWER_HINT_DISABLE_TOUCH) { |
|
||||||
ALOGV("%s: PROFILE_POWER_SAVE active, ignoring hint %d", __func__, hint); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
switch (hint) { |
|
||||||
case POWER_HINT_VSYNC: |
|
||||||
ALOGV("%s: POWER_HINT_VSYNC", __func__); |
|
||||||
break; |
|
||||||
case POWER_HINT_INTERACTION: |
|
||||||
ALOGV("%s: POWER_HINT_INTERACTION", __func__); |
|
||||||
send_boostpulse(samsung_pwr->boostpulse_fd); |
|
||||||
break; |
|
||||||
case POWER_HINT_LOW_POWER: |
|
||||||
ALOGV("%s: POWER_HINT_LOW_POWER", __func__); |
|
||||||
set_power_profile(samsung_pwr, data ? PROFILE_POWER_SAVE : PROFILE_BALANCED); |
|
||||||
break; |
|
||||||
case POWER_HINT_LAUNCH: |
|
||||||
ALOGV("%s: POWER_HINT_LAUNCH", __func__); |
|
||||||
send_boostpulse(samsung_pwr->boostpulse_fd); |
|
||||||
break; |
|
||||||
case POWER_HINT_CPU_BOOST: |
|
||||||
ALOGV("%s: POWER_HINT_CPU_BOOST", __func__); |
|
||||||
int32_t duration_us = *((int32_t *)data); |
|
||||||
send_boost(samsung_pwr->boost_fd, duration_us); |
|
||||||
break; |
|
||||||
case POWER_HINT_SET_PROFILE: |
|
||||||
ALOGV("%s: POWER_HINT_SET_PROFILE", __func__); |
|
||||||
int profile = *((intptr_t *)data); |
|
||||||
set_power_profile(samsung_pwr, profile); |
|
||||||
break; |
|
||||||
case POWER_HINT_DISABLE_TOUCH: |
|
||||||
ALOGV("%s: POWER_HINT_DISABLE_TOUCH", __func__); |
|
||||||
sysfs_write(samsung_pwr->touchscreen_power_path, data ? "0" : "1"); |
|
||||||
break; |
|
||||||
default: |
|
||||||
ALOGW("%s: Unknown power hint: %d", __func__, hint); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static void samsung_set_feature(struct power_module *module __unused, feature_t feature, int state __unused) |
|
||||||
{ |
|
||||||
switch (feature) { |
|
||||||
#ifdef TARGET_TAP_TO_WAKE_NODE |
|
||||||
case POWER_FEATURE_DOUBLE_TAP_TO_WAKE: |
|
||||||
ALOGV("%s: %s double tap to wake", __func__, state ? "enabling" : "disabling"); |
|
||||||
sysfs_write(TARGET_TAP_TO_WAKE_NODE, state > 0 ? "1" : "0"); |
|
||||||
break; |
|
||||||
#endif |
|
||||||
default: |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static struct hw_module_methods_t power_module_methods = { |
|
||||||
.open = NULL, |
|
||||||
}; |
|
||||||
|
|
||||||
struct samsung_power_module HAL_MODULE_INFO_SYM = { |
|
||||||
.base = { |
|
||||||
.common = { |
|
||||||
.tag = HARDWARE_MODULE_TAG, |
|
||||||
.module_api_version = POWER_MODULE_API_VERSION_0_2, |
|
||||||
.hal_api_version = HARDWARE_HAL_API_VERSION, |
|
||||||
.id = POWER_HARDWARE_MODULE_ID, |
|
||||||
.name = "Samsung Power HAL", |
|
||||||
.author = "The LineageOS Project", |
|
||||||
.methods = &power_module_methods, |
|
||||||
}, |
|
||||||
|
|
||||||
.init = samsung_power_init, |
|
||||||
.setInteractive = samsung_power_set_interactive, |
|
||||||
.powerHint = samsung_power_hint, |
|
||||||
.setFeature = samsung_set_feature |
|
||||||
}, |
|
||||||
|
|
||||||
.lock = PTHREAD_MUTEX_INITIALIZER, |
|
||||||
.boostpulse_fd = -1, |
|
||||||
}; |
|
Loading…
Reference in new issue