blob: 552c098ae7e99fbeeeda35ec0cfd6f1a3b4a3ccf [file] [log] [blame]
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +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
jt113488fda932012-10-19 23:17:48 -050023#define LOG_TAG "S5PC110 PowerHAL"
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +070024#include <utils/Log.h>
25
26#include <hardware/hardware.h>
27#include <hardware/power.h>
28
jt113488fda932012-10-19 23:17:48 -050029#define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
30#define BOOSTPULSE_ONDEMAND "/sys/devices/system/cpu/cpufreq/ondemand/boostpulse"
31#define BOOSTPULSE_INTERACTIVE "/sys/devices/system/cpu/cpufreq/interactive/boostpulse"
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +070032
33struct s5pc110_power_module {
34 struct power_module base;
35 pthread_mutex_t lock;
36 int boostpulse_fd;
37 int boostpulse_warned;
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +070038};
39
jt113488fda932012-10-19 23:17:48 -050040static int sysfs_read(char *path, char *s, int num_bytes)
41{
42 char buf[80];
43 int count;
44 int ret = 0;
45 int fd = open(path, O_RDONLY);
46
47 if (fd < 0) {
48 strerror_r(errno, buf, sizeof(buf));
49 ALOGE("Error opening %s: %s\n", path, buf);
50
51 return -1;
52 }
53
54 if ((count = read(fd, s, num_bytes - 1)) < 0) {
55 strerror_r(errno, buf, sizeof(buf));
56 ALOGE("Error writing to %s: %s\n", path, buf);
57
58 ret = -1;
59 } else {
60 s[count] = '\0';
61 }
62
63 close(fd);
64
65 return ret;
66}
67
68static int get_scaling_governor(char governor[], int size) {
69 if (sysfs_read(SCALING_GOVERNOR_PATH, governor,
70 size) == -1) {
71 // Can't obtain the scaling governor. Return.
72 return -1;
73 } else {
74 // Strip newline at the end.
75 int len = strlen(governor);
76
77 len--;
78
79 while (len >= 0 && (governor[len] == '\n' || governor[len] == '\r'))
80 governor[len--] = '\0';
81 }
82
83 return 0;
84}
85
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +070086static int boostpulse_open(struct s5pc110_power_module *s5pc110)
87{
88 char buf[80];
jt113488fda932012-10-19 23:17:48 -050089 char governor[80];
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +070090
91 pthread_mutex_lock(&s5pc110->lock);
92
93 if (s5pc110->boostpulse_fd < 0) {
jt113488fda932012-10-19 23:17:48 -050094 if (get_scaling_governor(governor, sizeof(governor)) < 0) {
95 ALOGE("Can't read scaling governor.");
96 s5pc110->boostpulse_warned = 1;
97 } else {
98 if (strncmp(governor, "ondemand", 8) == 0)
99 s5pc110->boostpulse_fd = open(BOOSTPULSE_ONDEMAND, O_WRONLY);
100 else if (strncmp(governor, "interactive", 11) == 0)
101 s5pc110->boostpulse_fd = open(BOOSTPULSE_INTERACTIVE, O_WRONLY);
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700102
jt113488fda932012-10-19 23:17:48 -0500103 if (s5pc110->boostpulse_fd < 0 && !s5pc110->boostpulse_warned) {
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700104 strerror_r(errno, buf, sizeof(buf));
jt113488fda932012-10-19 23:17:48 -0500105 ALOGE("Error opening %s boostpulse interface: %s\n", governor, buf);
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700106 s5pc110->boostpulse_warned = 1;
jt113488fda932012-10-19 23:17:48 -0500107 } else if (s5pc110->boostpulse_fd > 0)
108 ALOGD("Opened %s boostpulse interface", governor);
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700109 }
110 }
111
112 pthread_mutex_unlock(&s5pc110->lock);
113 return s5pc110->boostpulse_fd;
114}
115
116static void s5pc110_power_hint(struct power_module *module, power_hint_t hint,
117 void *data)
118{
119 struct s5pc110_power_module *s5pc110 = (struct s5pc110_power_module *) module;
120 char buf[80];
121 int len;
122 int duration = 1;
123
124 switch (hint) {
125 case POWER_HINT_INTERACTION:
126 case POWER_HINT_CPU_BOOST:
127 if (boostpulse_open(s5pc110) >= 0) {
128 if (data != NULL)
129 duration = (int) data;
130
131 snprintf(buf, sizeof(buf), "%d", duration);
132 len = write(s5pc110->boostpulse_fd, buf, strlen(buf));
133
134 if (len < 0) {
135 strerror_r(errno, buf, sizeof(buf));
jt113488fda932012-10-19 23:17:48 -0500136 ALOGE("Error writing to boostpulse: %s\n", buf);
137
138 pthread_mutex_lock(&s5pc110->lock);
139 close(s5pc110->boostpulse_fd);
140 s5pc110->boostpulse_fd = -1;
141 s5pc110->boostpulse_warned = 0;
142 pthread_mutex_unlock(&s5pc110->lock);
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700143 }
144 }
145 break;
146
147 case POWER_HINT_VSYNC:
148 break;
149
150 default:
151 break;
152 }
153}
154
155static void s5pc110_power_set_interactive(struct power_module *module, int on)
156{
Pawit Pornkitprasan76a153a2012-09-30 18:24:57 +0700157 return;
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700158}
159
160static void s5pc110_power_init(struct power_module *module)
161{
Pawit Pornkitprasan76a153a2012-09-30 18:24:57 +0700162 return;
Pawit Pornkitprasan5bff9ac2012-09-25 21:17:58 +0700163}
164
165static struct hw_module_methods_t power_module_methods = {
166 .open = NULL,
167};
168
169struct s5pc110_power_module HAL_MODULE_INFO_SYM = {
170 base: {
171 common: {
172 tag: HARDWARE_MODULE_TAG,
173 module_api_version: POWER_MODULE_API_VERSION_0_2,
174 hal_api_version: HARDWARE_HAL_API_VERSION,
175 id: POWER_HARDWARE_MODULE_ID,
176 name: "S5PC110 Power HAL",
177 author: "The Android Open Source Project",
178 methods: &power_module_methods,
179 },
180 init: s5pc110_power_init,
181 setInteractive: s5pc110_power_set_interactive,
182 powerHint: s5pc110_power_hint,
183 },
184
185 lock: PTHREAD_MUTEX_INITIALIZER,
186 boostpulse_fd: -1,
187 boostpulse_warned: 0,
188};