blob: 9352ae81a1ed653d497fa1352deaa5e50861d2fe [file] [log] [blame]
Christopher N. Hessede5e3c62015-12-21 21:28:23 +01001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 * Copyright (C) 2014 The CyanogenMod Project
4 * Copyright (C) 2014-2015 Andreas Schneider <asn@cryptomilk.org>
Christopher N. Hessef05f9022017-01-16 22:49:06 +01005 * Copyright (C) 2014-2017 Christopher N. Hesse <raymanfx@gmail.com>
Christopher N. Hessede5e3c62015-12-21 21:28:23 +01006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
Christopher N. Hesse3360b092016-07-11 15:48:35 +020020#include <ctype.h>
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010021#include <dirent.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <malloc.h>
25#include <stdbool.h>
Christopher N. Hessee1434192016-11-18 18:56:17 +010026#include <stdlib.h>
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010027#include <string.h>
28#include <unistd.h>
29
30#include <sys/types.h>
31#include <sys/stat.h>
32
33#define LOG_TAG "SamsungPowerHAL"
34/* #define LOG_NDEBUG 0 */
35#include <utils/Log.h>
36
37#include <hardware/hardware.h>
38#include <hardware/power.h>
Christopher N. Hesse12263502016-12-07 12:18:20 +010039#include <liblights/samsung_lights_helper.h>
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010040
Christopher N. Hesse4139d852016-12-07 12:21:44 +010041#include "samsung_power.h"
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010042
Christopher N. Hesse81f714d2017-03-12 17:11:04 +010043#define BOOST_PATH CPU0_INTERACTIVE_PATH "/boost"
44#define BOOSTPULSE_PATH CPU0_INTERACTIVE_PATH "/boostpulse"
Christopher N. Hesse63b5bd72017-05-29 20:45:14 +020045#define CPU0_IO_IS_BUSY_PATH CPU0_INTERACTIVE_PATH "/io_is_busy"
46#define CPU4_IO_IS_BUSY_PATH CPU4_INTERACTIVE_PATH "/io_is_busy"
Christopher N. Hesse81f714d2017-03-12 17:11:04 +010047#define CPU0_HISPEED_FREQ_PATH CPU0_INTERACTIVE_PATH "/hispeed_freq"
48#define CPU4_HISPEED_FREQ_PATH CPU4_INTERACTIVE_PATH "/hispeed_freq"
49
50#define CPU0_MAX_FREQ_PATH CPU0_SYSFS_PATH "/cpufreq/scaling_max_freq"
51#define CPU4_MAX_FREQ_PATH CPU4_SYSFS_PATH "/cpufreq/scaling_max_freq"
52
Christopher N. Hessed9106e92017-03-04 01:05:14 +010053#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
54
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010055struct samsung_power_module {
56 struct power_module base;
57 pthread_mutex_t lock;
58 int boostpulse_fd;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010059 char cpu0_hispeed_freq[10];
60 char cpu0_max_freq[10];
61 char cpu4_hispeed_freq[10];
62 char cpu4_max_freq[10];
63 char* touchscreen_power_path;
64 char* touchkey_power_path;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010065};
66
Andreas Schneiderf15d7f42016-02-03 10:43:47 +010067enum power_profile_e {
68 PROFILE_POWER_SAVE = 0,
69 PROFILE_BALANCED,
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +010070 PROFILE_HIGH_PERFORMANCE,
71 PROFILE_MAX
Andreas Schneiderf15d7f42016-02-03 10:43:47 +010072};
Christopher N. Hesseccd970d2017-01-25 22:41:05 +010073
Andreas Schneiderf15d7f42016-02-03 10:43:47 +010074static enum power_profile_e current_power_profile = PROFILE_BALANCED;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010075
76/**********************************************************
77 *** HELPER FUNCTIONS
78 **********************************************************/
79
80static int sysfs_read(char *path, char *s, int num_bytes)
81{
82 char errno_str[64];
83 int len;
84 int ret = 0;
85 int fd;
86
87 fd = open(path, O_RDONLY);
88 if (fd < 0) {
89 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +010090 ALOGE("Error opening %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010091
92 return -1;
93 }
94
95 len = read(fd, s, num_bytes - 1);
96 if (len < 0) {
97 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +010098 ALOGE("Error reading from %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010099
100 ret = -1;
101 } else {
Christopher N. Hesse0da5fbf2017-07-08 13:56:25 +0200102 // do not store newlines, but terminate the string instead
103 if (s[len-1] == '\n') {
104 s[len-1] = '\0';
105 } else {
106 s[len] = '\0';
107 }
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100108 }
109
110 close(fd);
111
112 return ret;
113}
114
115static void sysfs_write(const char *path, char *s)
116{
117 char errno_str[64];
118 int len;
119 int fd;
120
121 fd = open(path, O_WRONLY);
122 if (fd < 0) {
123 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100124 ALOGE("Error opening %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100125 return;
126 }
127
128 len = write(fd, s, strlen(s));
129 if (len < 0) {
130 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100131 ALOGE("Error writing to %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100132 }
133
134 close(fd);
135}
136
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100137static void boost(int32_t duration_us)
138{
139 int fd;
140
141 if (duration_us <= 0)
142 return;
143
144 fd = open(BOOST_PATH, O_WRONLY);
145 if (fd < 0) {
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100146 ALOGE("Error opening %s", BOOST_PATH);
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100147 return;
148 }
149
150 write(fd, "1", 1);
151 usleep(duration_us);
152 write(fd, "0", 1);
153
154 close(fd);
155}
156
Christopher N. Hessef21fbdb2017-03-04 01:41:58 +0100157static void boostpulse_open(struct samsung_power_module *samsung_pwr)
158{
159 samsung_pwr->boostpulse_fd = open(BOOSTPULSE_PATH, O_WRONLY);
160 if (samsung_pwr->boostpulse_fd < 0) {
161 ALOGE("Error opening %s: %s\n", BOOSTPULSE_PATH, strerror(errno));
162 }
163}
164
165static void send_boostpulse(int boostpulse_fd)
166{
167 int len;
168
169 if (boostpulse_fd < 0) {
170 return;
171 }
172
173 len = write(boostpulse_fd, "1", 1);
174 if (len < 0) {
175 ALOGE("Error writing to %s: %s", BOOSTPULSE_PATH, strerror(errno));
176 }
177}
178
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100179/**********************************************************
180 *** POWER FUNCTIONS
181 **********************************************************/
182
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100183static void set_power_profile(struct samsung_power_module *samsung_pwr,
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +0100184 int profile)
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100185{
186 int rc;
187 struct stat sb;
188
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +0100189 if (profile < 0 || profile >= PROFILE_MAX) {
190 return;
191 }
192
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100193 if (current_power_profile == profile) {
194 return;
195 }
196
197 ALOGV("%s: profile=%d", __func__, profile);
198
199 switch (profile) {
200 case PROFILE_POWER_SAVE:
Martin Bouchet4bf8a792017-03-28 04:00:04 -0300201 // Grab value set by init.*.rc
202 sysfs_read(CPU0_HISPEED_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq,
203 sizeof(samsung_pwr->cpu0_hispeed_freq));
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100204 // Limit to hispeed freq
205 sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq);
206 rc = stat(CPU4_MAX_FREQ_PATH, &sb);
207 if (rc == 0) {
Martin Bouchet4bf8a792017-03-28 04:00:04 -0300208 sysfs_read(CPU4_HISPEED_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq,
209 sizeof(samsung_pwr->cpu4_hispeed_freq));
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100210 sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq);
211 }
Christopher N. Hessef05f9022017-01-16 22:49:06 +0100212 ALOGV("%s: set powersave mode", __func__);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100213 break;
214 case PROFILE_BALANCED:
215 // Restore normal max freq
216 sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq);
217 rc = stat(CPU4_MAX_FREQ_PATH, &sb);
218 if (rc == 0) {
219 sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq);
220 }
Christopher N. Hessef05f9022017-01-16 22:49:06 +0100221 ALOGV("%s: set balanced mode", __func__);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100222 break;
223 case PROFILE_HIGH_PERFORMANCE:
224 // Restore normal max freq
225 sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq);
226 rc = stat(CPU4_MAX_FREQ_PATH, &sb);
227 if (rc == 0) {
228 sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq);
229 }
Christopher N. Hessef05f9022017-01-16 22:49:06 +0100230 ALOGV("%s: set performance mode", __func__);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100231 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100232 default:
233 ALOGW("%s: Unknown power profile: %d", __func__, profile);
234 return;
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100235 }
236
237 current_power_profile = profile;
238}
239
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100240static void find_input_nodes(struct samsung_power_module *samsung_pwr, char *dir)
241{
242 const char filename[] = "name";
243 char errno_str[64];
244 struct dirent *de;
245 char file_content[20];
246 char *path = NULL;
247 char *node_path = NULL;
248 size_t pathsize;
249 size_t node_pathsize;
250 DIR *d;
251
252 d = opendir(dir);
253 if (d == NULL) {
254 return;
255 }
256
257 while ((de = readdir(d)) != NULL) {
258 if (strncmp(filename, de->d_name, sizeof(filename)) == 0) {
259 pathsize = strlen(dir) + strlen(de->d_name) + 2;
260 node_pathsize = strlen(dir) + strlen("enabled") + 2;
261
262 path = malloc(pathsize);
263 node_path = malloc(node_pathsize);
264 if (path == NULL || node_path == NULL) {
265 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100266 ALOGE("Out of memory: %s", errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100267 return;
268 }
269
270 snprintf(path, pathsize, "%s/%s", dir, filename);
271 sysfs_read(path, file_content, sizeof(file_content));
272
273 snprintf(node_path, node_pathsize, "%s/%s", dir, "enabled");
274
275 if (strncmp(file_content, "sec_touchkey", 12) == 0) {
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100276 ALOGV("%s: found touchkey path: %s", __func__, node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100277 samsung_pwr->touchkey_power_path = malloc(node_pathsize);
278 if (samsung_pwr->touchkey_power_path == NULL) {
279 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100280 ALOGE("Out of memory: %s", errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100281 return;
282 }
Christopher N. Hesse22da3132016-02-01 12:36:54 +0100283 snprintf(samsung_pwr->touchkey_power_path, node_pathsize,
284 "%s", node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100285 }
286
287 if (strncmp(file_content, "sec_touchscreen", 15) == 0) {
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100288 ALOGV("%s: found touchscreen path: %s", __func__, node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100289 samsung_pwr->touchscreen_power_path = malloc(node_pathsize);
290 if (samsung_pwr->touchscreen_power_path == NULL) {
291 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100292 ALOGE("Out of memory: %s", errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100293 return;
294 }
Christopher N. Hesse22da3132016-02-01 12:36:54 +0100295 snprintf(samsung_pwr->touchscreen_power_path, node_pathsize,
296 "%s", node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100297 }
298 }
299 }
300
301 if (path)
302 free(path);
303 if (node_path)
304 free(node_path);
305 closedir(d);
306}
307
308/**********************************************************
309 *** INIT FUNCTIONS
310 **********************************************************/
311
312static void init_cpufreqs(struct samsung_power_module *samsung_pwr)
313{
314 int rc;
315 struct stat sb;
316
317 sysfs_read(CPU0_HISPEED_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq,
318 sizeof(samsung_pwr->cpu0_hispeed_freq));
319 sysfs_read(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq,
320 sizeof(samsung_pwr->cpu0_max_freq));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100321 ALOGV("%s: CPU 0 hispeed freq: %s", __func__, samsung_pwr->cpu0_hispeed_freq);
322 ALOGV("%s: CPU 0 max freq: %s", __func__, samsung_pwr->cpu0_max_freq);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100323
324 rc = stat(CPU4_HISPEED_FREQ_PATH, &sb);
325 if (rc == 0) {
326 sysfs_read(CPU4_HISPEED_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq,
327 sizeof(samsung_pwr->cpu4_hispeed_freq));
328 sysfs_read(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq,
329 sizeof(samsung_pwr->cpu4_max_freq));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100330 ALOGV("%s: CPU 4 hispeed freq: %s", __func__, samsung_pwr->cpu4_hispeed_freq);
331 ALOGV("%s: CPU 4 max freq: %s", __func__, samsung_pwr->cpu4_max_freq);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100332 }
333}
334
335static void init_touch_input_power_path(struct samsung_power_module *samsung_pwr)
336{
337 char dir[1024];
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100338 uint32_t i;
339
340 for (i = 0; i < 20; i++) {
341 snprintf(dir, sizeof(dir), "/sys/class/input/input%d", i);
342 find_input_nodes(samsung_pwr, dir);
343 }
344}
345
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100346static void samsung_power_init(struct power_module *module)
347{
348 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
349
350 init_cpufreqs(samsung_pwr);
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100351
352 boostpulse_open(samsung_pwr);
353
Christopher N. Hesse65c65bd2017-03-07 23:01:12 +0100354 samsung_pwr->touchscreen_power_path = NULL;
355 samsung_pwr->touchkey_power_path = NULL;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100356 init_touch_input_power_path(samsung_pwr);
357}
358
Christopher N. Hessef6296722017-01-16 22:47:11 +0100359/**********************************************************
360 *** API FUNCTIONS
361 ***
362 *** Refer to power.h for documentation.
363 **********************************************************/
364
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100365static void samsung_power_set_interactive(struct power_module *module, int on)
366{
367 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
368 struct stat sb;
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100369 int panel_brightness;
370 char button_state[2];
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100371 int rc;
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100372 static bool touchkeys_blocked = false;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100373
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100374 ALOGV("power_set_interactive: %d", on);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100375
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100376 /*
377 * Do not disable any input devices if the screen is on but we are in a non-interactive
378 * state.
379 */
Christopher N. Hesse3360b092016-07-11 15:48:35 +0200380 if (!on) {
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100381 panel_brightness = get_cur_panel_brightness();
382 if (panel_brightness < 0) {
383 ALOGE("%s: Failed to read panel brightness", __func__);
384 } else if (panel_brightness > 0) {
Christopher N. Hesse3360b092016-07-11 15:48:35 +0200385 ALOGV("%s: Moving to non-interactive state, but screen is still on,"
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100386 " not disabling input devices", __func__);
Christopher N. Hesse3360b092016-07-11 15:48:35 +0200387 goto out;
388 }
389 }
390
Paul Keith5e4fbe02017-04-21 21:34:17 -0500391 /* Sanity check the touchscreen path */
392 if (samsung_pwr->touchscreen_power_path) {
393 sysfs_write(samsung_pwr->touchscreen_power_path, on ? "1" : "0");
394 }
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100395
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100396 /* Bail out if the device does not have touchkeys */
397 if (samsung_pwr->touchkey_power_path == NULL) {
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100398 goto out;
399 }
400
401 if (!on) {
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100402 rc = sysfs_read(samsung_pwr->touchkey_power_path, button_state, ARRAY_SIZE(button_state));
403 if (rc < 0) {
404 ALOGE("%s: Failed to read touchkey state", __func__);
405 goto out;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100406 }
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100407 /*
408 * If button_state is 0, the keys have been disabled by another component
409 * (for example cmhw), which means we don't want them to be enabled when resuming
410 * from suspend.
411 */
412 if (button_state[0] == '0') {
413 touchkeys_blocked = true;
414 } else {
415 touchkeys_blocked = false;
416 }
417 }
418
419 if (!touchkeys_blocked) {
420 sysfs_write(samsung_pwr->touchkey_power_path, on ? "1" : "0");
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100421 }
422
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100423out:
Christopher N. Hesse63b5bd72017-05-29 20:45:14 +0200424 sysfs_write(CPU0_IO_IS_BUSY_PATH, on ? "1" : "0");
425 rc = stat(CPU4_IO_IS_BUSY_PATH, &sb);
426 if (rc == 0) {
427 sysfs_write(CPU4_IO_IS_BUSY_PATH, on ? "1" : "0");
428 }
429
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100430 ALOGV("power_set_interactive: %d done", on);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100431}
432
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100433static void samsung_power_hint(struct power_module *module,
434 power_hint_t hint,
435 void *data)
436{
437 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100438 int len;
439
Christopher N. Hesse15b63092017-03-12 17:04:53 +0100440 /* Bail out if low-power mode is active */
Christopher N. Hesse5eca5aa2017-04-26 21:42:10 +0200441 if (current_power_profile == PROFILE_POWER_SAVE && hint != POWER_HINT_LOW_POWER
442 && hint != POWER_HINT_SET_PROFILE) {
Christopher N. Hesse15b63092017-03-12 17:04:53 +0100443 ALOGW("%s: PROFILE_POWER_SAVE active, ignoring hint %d", __func__, hint);
444 return;
445 }
446
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100447 switch (hint) {
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100448 case POWER_HINT_VSYNC:
449 ALOGV("%s: POWER_HINT_VSYNC", __func__);
450 break;
451 case POWER_HINT_INTERACTION:
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100452 ALOGV("%s: POWER_HINT_INTERACTION", __func__);
Christopher N. Hessef21fbdb2017-03-04 01:41:58 +0100453 send_boostpulse(samsung_pwr->boostpulse_fd);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100454 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100455 case POWER_HINT_LOW_POWER:
456 ALOGV("%s: POWER_HINT_LOW_POWER", __func__);
Christopher N. Hesse3fa2b692017-04-05 18:52:48 +0200457 set_power_profile(samsung_pwr, data ? PROFILE_POWER_SAVE : PROFILE_BALANCED);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100458 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100459 case POWER_HINT_LAUNCH:
Christopher N. Hesse3fa2b692017-04-05 18:52:48 +0200460 ALOGV("%s: POWER_HINT_LAUNCH", __func__);
461 send_boostpulse(samsung_pwr->boostpulse_fd);
462 break;
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100463 case POWER_HINT_CPU_BOOST:
Christopher N. Hesse3fa2b692017-04-05 18:52:48 +0200464 ALOGV("%s: POWER_HINT_CPU_BOOST", __func__);
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100465 boost((*(int32_t *)data));
466 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100467 case POWER_HINT_SET_PROFILE:
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100468 ALOGV("%s: POWER_HINT_SET_PROFILE", __func__);
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100469 int profile = *((intptr_t *)data);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100470 set_power_profile(samsung_pwr, profile);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100471 break;
Christopher N. Hessef9b8e832017-01-17 00:04:45 +0100472 case POWER_HINT_DISABLE_TOUCH:
473 ALOGV("%s: POWER_HINT_DISABLE_TOUCH", __func__);
Christopher N. Hesse3fa2b692017-04-05 18:52:48 +0200474 sysfs_write(samsung_pwr->touchscreen_power_path, data ? "0" : "1");
Christopher N. Hessef9b8e832017-01-17 00:04:45 +0100475 break;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100476 default:
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100477 ALOGW("%s: Unknown power hint: %d", __func__, hint);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100478 break;
479 }
480}
481
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100482static int samsung_get_feature(struct power_module *module __unused,
483 feature_t feature)
484{
485 if (feature == POWER_FEATURE_SUPPORTED_PROFILES) {
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +0100486 return PROFILE_MAX;
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100487 }
488
489 return -1;
490}
491
Christopher N. Hesse1c474662016-11-18 18:59:06 +0100492static void samsung_set_feature(struct power_module *module, feature_t feature, int state __unused)
Christopher N. Hessee480d892016-06-22 23:04:39 +0200493{
494 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
495
496 switch (feature) {
ishantvivek987dcca2016-11-21 06:05:47 +0000497#ifdef TARGET_TAP_TO_WAKE_NODE
Christopher N. Hessee480d892016-06-22 23:04:39 +0200498 case POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
499 ALOGV("%s: %s double tap to wake", __func__, state ? "enabling" : "disabling");
ishantvivek987dcca2016-11-21 06:05:47 +0000500 sysfs_write(TARGET_TAP_TO_WAKE_NODE, state > 0 ? "1" : "0");
Christopher N. Hessee480d892016-06-22 23:04:39 +0200501 break;
502#endif
503 default:
504 break;
505 }
506}
507
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100508static struct hw_module_methods_t power_module_methods = {
509 .open = NULL,
510};
511
512struct samsung_power_module HAL_MODULE_INFO_SYM = {
513 .base = {
514 .common = {
515 .tag = HARDWARE_MODULE_TAG,
516 .module_api_version = POWER_MODULE_API_VERSION_0_2,
517 .hal_api_version = HARDWARE_HAL_API_VERSION,
518 .id = POWER_HARDWARE_MODULE_ID,
519 .name = "Samsung Power HAL",
Christopher N. Hesseaa75be42017-01-16 22:47:59 +0100520 .author = "The LineageOS Project",
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100521 .methods = &power_module_methods,
522 },
523
524 .init = samsung_power_init,
525 .setInteractive = samsung_power_set_interactive,
526 .powerHint = samsung_power_hint,
Christopher N. Hessee480d892016-06-22 23:04:39 +0200527 .getFeature = samsung_get_feature,
528 .setFeature = samsung_set_feature
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100529 },
530
531 .lock = PTHREAD_MUTEX_INITIALIZER,
532 .boostpulse_fd = -1,
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100533};