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 30 struct tuna_power_module { 31 struct power_module base; 32 pthread_mutex_t lock; 33 int boostpulse_fd; 34 int boostpulse_warned; 35 }; 36 37 static 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 58 static void tuna_power_init(struct power_module *module) 59 { 60 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate", 61 "20000"); 62 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time", 63 "60000"); 64 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", 65 "700000"); 66 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/target_loads", 67 "70 920000:80 1200000:99"); 68 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load", 69 "99"); 70 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", 71 "80000"); 72 } 73 74 static int boostpulse_open(struct tuna_power_module *tuna) 75 { 76 char buf[80]; 77 78 pthread_mutex_lock(&tuna->lock); 79 80 if (tuna->boostpulse_fd < 0) { 81 tuna->boostpulse_fd = open(BOOSTPULSE_PATH, O_WRONLY); 82 83 if (tuna->boostpulse_fd < 0) { 84 if (!tuna->boostpulse_warned) { 85 strerror_r(errno, buf, sizeof(buf)); 86 ALOGE("Error opening %s: %s\n", BOOSTPULSE_PATH, buf); 87 tuna->boostpulse_warned = 1; 88 } 89 } 90 } 91 92 pthread_mutex_unlock(&tuna->lock); 93 return tuna->boostpulse_fd; 94 } 95 96 static void tuna_power_set_interactive(struct power_module *module, int on) 97 { 98 /* 99 * Lower maximum frequency when screen is off. CPU 0 and 1 share a 100 * cpufreq policy. 101 */ 102 103 sysfs_write("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", 104 on ? "1200000" : "700000"); 105 } 106 107 static void tuna_power_hint(struct power_module *module, power_hint_t hint, 108 void *data) 109 { 110 struct tuna_power_module *tuna = (struct tuna_power_module *) module; 111 char buf[80]; 112 int len; 113 114 switch (hint) { 115 case POWER_HINT_INTERACTION: 116 if (boostpulse_open(tuna) >= 0) { 117 len = write(tuna->boostpulse_fd, "1", 1); 118 119 if (len < 0) { 120 strerror_r(errno, buf, sizeof(buf)); 121 ALOGE("Error writing to %s: %s\n", BOOSTPULSE_PATH, buf); 122 } 123 } 124 break; 125 126 case POWER_HINT_VSYNC: 127 break; 128 129 default: 130 break; 131 } 132 } 133 134 static struct hw_module_methods_t power_module_methods = { 135 .open = NULL, 136 }; 137 138 struct tuna_power_module HAL_MODULE_INFO_SYM = { 139 base: { 140 common: { 141 tag: HARDWARE_MODULE_TAG, 142 module_api_version: POWER_MODULE_API_VERSION_0_2, 143 hal_api_version: HARDWARE_HAL_API_VERSION, 144 id: POWER_HARDWARE_MODULE_ID, 145 name: "Tuna Power HAL", 146 author: "The Android Open Source Project", 147 methods: &power_module_methods, 148 }, 149 150 init: tuna_power_init, 151 setInteractive: tuna_power_set_interactive, 152 powerHint: tuna_power_hint, 153 }, 154 155 lock: PTHREAD_MUTEX_INITIALIZER, 156 boostpulse_fd: -1, 157 boostpulse_warned: 0, 158 }; 159