1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include <errno.h> 17#include <string.h> 18#include <sys/types.h> 19#include <sys/stat.h> 20#include <fcntl.h> 21 22#define LOG_TAG "Tuna PowerHAL" 23#include <utils/Log.h> 24 25#include <hardware/hardware.h> 26#include <hardware/power.h> 27 28#define BOOSTPULSE_PATH "/sys/devices/system/cpu/cpufreq/interactive/boostpulse" 29 30struct tuna_power_module { 31 struct power_module base; 32 pthread_mutex_t lock; 33 int boostpulse_fd; 34 int boostpulse_warned; 35}; 36 37static void sysfs_write(char *path, char *s) 38{ 39 char buf[80]; 40 int len; 41 int fd = open(path, O_WRONLY); 42 43 if (fd < 0) { 44 strerror_r(errno, buf, sizeof(buf)); 45 ALOGE("Error opening %s: %s\n", path, buf); 46 return; 47 } 48 49 len = write(fd, s, strlen(s)); 50 if (len < 0) { 51 strerror_r(errno, buf, sizeof(buf)); 52 ALOGE("Error writing to %s: %s\n", path, buf); 53 } 54 55 close(fd); 56} 57 58static void tuna_power_init(struct power_module *module) 59{ 60 /* 61 * cpufreq interactive governor: timer 20ms, min sample 60ms, 62 * hispeed 700MHz at load 50%. 63 */ 64 65 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate", 66 "20000"); 67 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time", 68 "60000"); 69 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", 70 "700000"); 71 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", 72 "50"); 73 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", 74 "100000"); 75} 76 77static int boostpulse_open(struct tuna_power_module *tuna) 78{ 79 char buf[80]; 80 81 pthread_mutex_lock(&tuna->lock); 82 83 if (tuna->boostpulse_fd < 0) { 84 tuna->boostpulse_fd = open(BOOSTPULSE_PATH, O_WRONLY); 85 86 if (tuna->boostpulse_fd < 0) { 87 if (!tuna->boostpulse_warned) { 88 strerror_r(errno, buf, sizeof(buf)); 89 ALOGE("Error opening %s: %s\n", BOOSTPULSE_PATH, buf); 90 tuna->boostpulse_warned = 1; 91 } 92 } 93 } 94 95 pthread_mutex_unlock(&tuna->lock); 96 return tuna->boostpulse_fd; 97} 98 99static void tuna_power_set_interactive(struct power_module *module, int on) 100{ 101 /* 102 * Lower maximum frequency when screen is off. CPU 0 and 1 share a 103 * cpufreq policy. 104 */ 105 106 sysfs_write("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", 107 on ? "1200000" : "700000"); 108} 109 110static void tuna_power_hint(struct power_module *module, power_hint_t hint, 111 void *data) 112{ 113 struct tuna_power_module *tuna = (struct tuna_power_module *) module; 114 char buf[80]; 115 int len; 116 117 switch (hint) { 118 case POWER_HINT_INTERACTION: 119 if (boostpulse_open(tuna) >= 0) { 120 len = write(tuna->boostpulse_fd, "1", 1); 121 122 if (len < 0) { 123 strerror_r(errno, buf, sizeof(buf)); 124 ALOGE("Error writing to %s: %s\n", BOOSTPULSE_PATH, buf); 125 } 126 } 127 break; 128 129 case POWER_HINT_VSYNC: 130 break; 131 132 default: 133 break; 134 } 135} 136 137static struct hw_module_methods_t power_module_methods = { 138 .open = NULL, 139}; 140 141struct tuna_power_module HAL_MODULE_INFO_SYM = { 142 base: { 143 common: { 144 tag: HARDWARE_MODULE_TAG, 145 module_api_version: POWER_MODULE_API_VERSION_0_2, 146 hal_api_version: HARDWARE_HAL_API_VERSION, 147 id: POWER_HARDWARE_MODULE_ID, 148 name: "Tuna Power HAL", 149 author: "The Android Open Source Project", 150 methods: &power_module_methods, 151 }, 152 153 init: tuna_power_init, 154 setInteractive: tuna_power_set_interactive, 155 powerHint: tuna_power_hint, 156 }, 157 158 lock: PTHREAD_MUTEX_INITIALIZER, 159 boostpulse_fd: -1, 160 boostpulse_warned: 0, 161}; 162