• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
sysfs_write(char * path,char * s)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 
tuna_power_init(struct power_module * module)58 static 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 
boostpulse_open(struct tuna_power_module * tuna)77 static 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 
tuna_power_set_interactive(struct power_module * module,int on)99 static 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 
tuna_power_hint(struct power_module * module,power_hint_t hint,void * data)110 static 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 
137 static struct hw_module_methods_t power_module_methods = {
138     .open = NULL,
139 };
140 
141 struct 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