blob: 55b34693ad91c183da40d338f7701fcb2a8da4dd [file] [log] [blame]
Steve Kondik0e9f0192012-09-24 02:12:49 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 * Copyright (c) 2012 The CyanogenMod Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#include <errno.h>
18#include <string.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22
23#define LOG_TAG "CM PowerHAL"
24#include <utils/Log.h>
25
26#include <hardware/hardware.h>
27#include <hardware/power.h>
28
Anurag Singhb2adeec2012-12-14 10:23:03 -080029#define ONDEMAND_GOVERNOR "ondemand"
30#define INTERACTIVE_GOVERNOR "interactive"
Steve Kondik0e9f0192012-09-24 02:12:49 -070031#define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
32#define BOOSTPULSE_ONDEMAND "/sys/devices/system/cpu/cpufreq/ondemand/boostpulse"
33#define BOOSTPULSE_INTERACTIVE "/sys/devices/system/cpu/cpufreq/interactive/boostpulse"
Steve Kondik0e9f0192012-09-24 02:12:49 -070034#define SAMPLING_RATE_SCREEN_ON "50000"
35#define SAMPLING_RATE_SCREEN_OFF "500000"
Steve Kondike29bcbf2013-02-07 21:21:52 -080036#define TIMER_RATE_SCREEN_ON "30000"
37#define TIMER_RATE_SCREEN_OFF "500000"
Steve Kondik0e9f0192012-09-24 02:12:49 -070038
39struct cm_power_module {
40 struct power_module base;
41 pthread_mutex_t lock;
42 int boostpulse_fd;
43 int boostpulse_warned;
44};
45
Steve Kondike29bcbf2013-02-07 21:21:52 -080046static char governor[20];
47
Steve Kondik0e9f0192012-09-24 02:12:49 -070048static int sysfs_read(char *path, char *s, int num_bytes)
49{
50 char buf[80];
51 int count;
52 int ret = 0;
53 int fd = open(path, O_RDONLY);
54
55 if (fd < 0) {
56 strerror_r(errno, buf, sizeof(buf));
57 ALOGE("Error opening %s: %s\n", path, buf);
58
59 return -1;
60 }
61
62 if ((count = read(fd, s, num_bytes - 1)) < 0) {
63 strerror_r(errno, buf, sizeof(buf));
64 ALOGE("Error writing to %s: %s\n", path, buf);
65
66 ret = -1;
67 } else {
68 s[count] = '\0';
69 }
70
71 close(fd);
72
73 return ret;
74}
75
76static void sysfs_write(char *path, char *s)
77{
78 char buf[80];
79 int len;
80 int fd = open(path, O_WRONLY);
81
82 if (fd < 0) {
83 strerror_r(errno, buf, sizeof(buf));
84 ALOGE("Error opening %s: %s\n", path, buf);
85 return;
86 }
87
88 len = write(fd, s, strlen(s));
89 if (len < 0) {
90 strerror_r(errno, buf, sizeof(buf));
91 ALOGE("Error writing to %s: %s\n", path, buf);
92 }
93
94 close(fd);
95}
96
Steve Kondike29bcbf2013-02-07 21:21:52 -080097static int get_scaling_governor() {
Steve Kondik0e9f0192012-09-24 02:12:49 -070098 if (sysfs_read(SCALING_GOVERNOR_PATH, governor,
Steve Kondike29bcbf2013-02-07 21:21:52 -080099 sizeof(governor)) == -1) {
Steve Kondik0e9f0192012-09-24 02:12:49 -0700100 return -1;
101 } else {
102 // Strip newline at the end.
103 int len = strlen(governor);
104
105 len--;
106
107 while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r'))
108 governor[len--] = '\0';
109 }
110
111 return 0;
112}
113
Steve Kondike29bcbf2013-02-07 21:21:52 -0800114static void cm_power_set_interactive(struct power_module *module, int on)
115{
116 if (strncmp(governor, ONDEMAND_GOVERNOR, 8) == 0)
117 sysfs_write("/sys/devices/system/cpu/cpufreq/ondemand/sampling_rate",
118 on ? SAMPLING_RATE_SCREEN_ON : SAMPLING_RATE_SCREEN_OFF);
119 else if (strncmp(governor, INTERACTIVE_GOVERNOR, 11) == 0)
120 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate",
121 on ? TIMER_RATE_SCREEN_ON : TIMER_RATE_SCREEN_OFF);
122}
123
124
125static void configure_governor()
126{
127 cm_power_set_interactive(NULL, 1);
128
129 if (strncmp(governor, ONDEMAND_GOVERNOR, 8) == 0) {
130 sysfs_write("/sys/devices/system/cpu/cpufreq/ondemand/up_threshold", "90");
131 sysfs_write("/sys/devices/system/cpu/cpufreq/ondemand/io_is_busy", "1");
132 sysfs_write("/sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor", "4");
133 sysfs_write("/sys/devices/system/cpu/cpufreq/ondemand/down_differential", "10");
134
135 } else if (strncmp(governor, INTERACTIVE_GOVERNOR, 11) == 0) {
136 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time", "90000");
Steve Kondik25ddb282013-03-22 06:26:38 -0700137 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/io_is_busy", "1");
Steve Kondike29bcbf2013-02-07 21:21:52 -0800138 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq", "1134000");
139 sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay", "30000");
140 }
141}
142
Steve Kondik0e9f0192012-09-24 02:12:49 -0700143static int boostpulse_open(struct cm_power_module *cm)
144{
145 char buf[80];
Steve Kondik0e9f0192012-09-24 02:12:49 -0700146
147 pthread_mutex_lock(&cm->lock);
148
149 if (cm->boostpulse_fd < 0) {
Steve Kondike29bcbf2013-02-07 21:21:52 -0800150 if (get_scaling_governor() < 0) {
Steve Kondik0e9f0192012-09-24 02:12:49 -0700151 ALOGE("Can't read scaling governor.");
152 cm->boostpulse_warned = 1;
153 } else {
Anurag Singhb2adeec2012-12-14 10:23:03 -0800154 if (strncmp(governor, ONDEMAND_GOVERNOR, 8) == 0)
Steve Kondik0e9f0192012-09-24 02:12:49 -0700155 cm->boostpulse_fd = open(BOOSTPULSE_ONDEMAND, O_WRONLY);
Anurag Singhb2adeec2012-12-14 10:23:03 -0800156 else if (strncmp(governor, INTERACTIVE_GOVERNOR, 11) == 0)
Steve Kondik0e9f0192012-09-24 02:12:49 -0700157 cm->boostpulse_fd = open(BOOSTPULSE_INTERACTIVE, O_WRONLY);
158
159 if (cm->boostpulse_fd < 0 && !cm->boostpulse_warned) {
160 strerror_r(errno, buf, sizeof(buf));
Steve Kondike29bcbf2013-02-07 21:21:52 -0800161 ALOGV("Error opening boostpulse: %s\n", buf);
Steve Kondik0e9f0192012-09-24 02:12:49 -0700162 cm->boostpulse_warned = 1;
Steve Kondike29bcbf2013-02-07 21:21:52 -0800163 } else if (cm->boostpulse_fd > 0) {
164 configure_governor();
Steve Kondik0e9f0192012-09-24 02:12:49 -0700165 ALOGD("Opened %s boostpulse interface", governor);
Steve Kondike29bcbf2013-02-07 21:21:52 -0800166 }
Steve Kondik0e9f0192012-09-24 02:12:49 -0700167 }
168 }
169
170 pthread_mutex_unlock(&cm->lock);
171 return cm->boostpulse_fd;
172}
173
174static void cm_power_hint(struct power_module *module, power_hint_t hint,
175 void *data)
176{
177 struct cm_power_module *cm = (struct cm_power_module *) module;
178 char buf[80];
179 int len;
180 int duration = 1;
181
182 switch (hint) {
183 case POWER_HINT_INTERACTION:
184 case POWER_HINT_CPU_BOOST:
185 if (boostpulse_open(cm) >= 0) {
186 if (data != NULL)
187 duration = (int) data;
188
189 snprintf(buf, sizeof(buf), "%d", duration);
190 len = write(cm->boostpulse_fd, buf, strlen(buf));
191
192 if (len < 0) {
193 strerror_r(errno, buf, sizeof(buf));
194 ALOGE("Error writing to boostpulse: %s\n", buf);
195
196 pthread_mutex_lock(&cm->lock);
197 close(cm->boostpulse_fd);
198 cm->boostpulse_fd = -1;
199 cm->boostpulse_warned = 0;
200 pthread_mutex_unlock(&cm->lock);
201 }
202 }
203 break;
204
205 case POWER_HINT_VSYNC:
206 break;
207
208 default:
209 break;
210 }
211}
212
Steve Kondik0e9f0192012-09-24 02:12:49 -0700213static void cm_power_init(struct power_module *module)
214{
Steve Kondike29bcbf2013-02-07 21:21:52 -0800215 get_scaling_governor();
216 configure_governor();
Steve Kondik0e9f0192012-09-24 02:12:49 -0700217}
218
219static struct hw_module_methods_t power_module_methods = {
220 .open = NULL,
221};
222
223struct cm_power_module HAL_MODULE_INFO_SYM = {
224 base: {
225 common: {
226 tag: HARDWARE_MODULE_TAG,
227 module_api_version: POWER_MODULE_API_VERSION_0_2,
228 hal_api_version: HARDWARE_HAL_API_VERSION,
229 id: POWER_HARDWARE_MODULE_ID,
230 name: "CM Power HAL",
231 author: "The CyanogenMod Project",
232 methods: &power_module_methods,
233 },
234 init: cm_power_init,
235 setInteractive: cm_power_set_interactive,
236 powerHint: cm_power_hint,
237 },
238
239 lock: PTHREAD_MUTEX_INITIALIZER,
240 boostpulse_fd: -1,
241 boostpulse_warned: 0,
242};