blob: bcc40f6ca7308eea63dd825bd8eda69c34a5b6c3 [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"
45#define IO_IS_BUSY_PATH CPU0_INTERACTIVE_PATH "/io_is_busy"
46#define CPU0_HISPEED_FREQ_PATH CPU0_INTERACTIVE_PATH "/hispeed_freq"
47#define CPU4_HISPEED_FREQ_PATH CPU4_INTERACTIVE_PATH "/hispeed_freq"
48
49#define CPU0_MAX_FREQ_PATH CPU0_SYSFS_PATH "/cpufreq/scaling_max_freq"
50#define CPU4_MAX_FREQ_PATH CPU4_SYSFS_PATH "/cpufreq/scaling_max_freq"
51
Christopher N. Hessed9106e92017-03-04 01:05:14 +010052#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
53
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010054struct samsung_power_module {
55 struct power_module base;
56 pthread_mutex_t lock;
57 int boostpulse_fd;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010058 char cpu0_hispeed_freq[10];
59 char cpu0_max_freq[10];
60 char cpu4_hispeed_freq[10];
61 char cpu4_max_freq[10];
62 char* touchscreen_power_path;
63 char* touchkey_power_path;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010064};
65
Andreas Schneiderf15d7f42016-02-03 10:43:47 +010066enum power_profile_e {
67 PROFILE_POWER_SAVE = 0,
68 PROFILE_BALANCED,
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +010069 PROFILE_HIGH_PERFORMANCE,
70 PROFILE_MAX
Andreas Schneiderf15d7f42016-02-03 10:43:47 +010071};
Christopher N. Hesseccd970d2017-01-25 22:41:05 +010072
Andreas Schneiderf15d7f42016-02-03 10:43:47 +010073static enum power_profile_e current_power_profile = PROFILE_BALANCED;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010074
75/**********************************************************
76 *** HELPER FUNCTIONS
77 **********************************************************/
78
79static int sysfs_read(char *path, char *s, int num_bytes)
80{
81 char errno_str[64];
82 int len;
83 int ret = 0;
84 int fd;
85
86 fd = open(path, O_RDONLY);
87 if (fd < 0) {
88 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +010089 ALOGE("Error opening %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010090
91 return -1;
92 }
93
94 len = read(fd, s, num_bytes - 1);
95 if (len < 0) {
96 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +010097 ALOGE("Error reading from %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +010098
99 ret = -1;
100 } else {
101 s[len] = '\0';
102 }
103
104 close(fd);
105
106 return ret;
107}
108
109static void sysfs_write(const char *path, char *s)
110{
111 char errno_str[64];
112 int len;
113 int fd;
114
115 fd = open(path, O_WRONLY);
116 if (fd < 0) {
117 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100118 ALOGE("Error opening %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100119 return;
120 }
121
122 len = write(fd, s, strlen(s));
123 if (len < 0) {
124 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100125 ALOGE("Error writing to %s: %s", path, errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100126 }
127
128 close(fd);
129}
130
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100131static void boost(int32_t duration_us)
132{
133 int fd;
134
135 if (duration_us <= 0)
136 return;
137
138 fd = open(BOOST_PATH, O_WRONLY);
139 if (fd < 0) {
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100140 ALOGE("Error opening %s", BOOST_PATH);
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100141 return;
142 }
143
144 write(fd, "1", 1);
145 usleep(duration_us);
146 write(fd, "0", 1);
147
148 close(fd);
149}
150
Christopher N. Hessef21fbdb2017-03-04 01:41:58 +0100151static void boostpulse_open(struct samsung_power_module *samsung_pwr)
152{
153 samsung_pwr->boostpulse_fd = open(BOOSTPULSE_PATH, O_WRONLY);
154 if (samsung_pwr->boostpulse_fd < 0) {
155 ALOGE("Error opening %s: %s\n", BOOSTPULSE_PATH, strerror(errno));
156 }
157}
158
159static void send_boostpulse(int boostpulse_fd)
160{
161 int len;
162
163 if (boostpulse_fd < 0) {
164 return;
165 }
166
167 len = write(boostpulse_fd, "1", 1);
168 if (len < 0) {
169 ALOGE("Error writing to %s: %s", BOOSTPULSE_PATH, strerror(errno));
170 }
171}
172
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100173/**********************************************************
174 *** POWER FUNCTIONS
175 **********************************************************/
176
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100177static void set_power_profile(struct samsung_power_module *samsung_pwr,
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +0100178 int profile)
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100179{
180 int rc;
181 struct stat sb;
182
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +0100183 if (profile < 0 || profile >= PROFILE_MAX) {
184 return;
185 }
186
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100187 if (current_power_profile == profile) {
188 return;
189 }
190
191 ALOGV("%s: profile=%d", __func__, profile);
192
193 switch (profile) {
194 case PROFILE_POWER_SAVE:
Martin Bouchet4bf8a792017-03-28 04:00:04 -0300195 // Grab value set by init.*.rc
196 sysfs_read(CPU0_HISPEED_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq,
197 sizeof(samsung_pwr->cpu0_hispeed_freq));
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100198 // Limit to hispeed freq
199 sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq);
200 rc = stat(CPU4_MAX_FREQ_PATH, &sb);
201 if (rc == 0) {
Martin Bouchet4bf8a792017-03-28 04:00:04 -0300202 sysfs_read(CPU4_HISPEED_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq,
203 sizeof(samsung_pwr->cpu4_hispeed_freq));
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100204 sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq);
205 }
Christopher N. Hessef05f9022017-01-16 22:49:06 +0100206 ALOGV("%s: set powersave mode", __func__);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100207 break;
208 case PROFILE_BALANCED:
209 // Restore normal max freq
210 sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq);
211 rc = stat(CPU4_MAX_FREQ_PATH, &sb);
212 if (rc == 0) {
213 sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq);
214 }
Christopher N. Hessef05f9022017-01-16 22:49:06 +0100215 ALOGV("%s: set balanced mode", __func__);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100216 break;
217 case PROFILE_HIGH_PERFORMANCE:
218 // Restore normal max freq
219 sysfs_write(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq);
220 rc = stat(CPU4_MAX_FREQ_PATH, &sb);
221 if (rc == 0) {
222 sysfs_write(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq);
223 }
Christopher N. Hessef05f9022017-01-16 22:49:06 +0100224 ALOGV("%s: set performance mode", __func__);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100225 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100226 default:
227 ALOGW("%s: Unknown power profile: %d", __func__, profile);
228 return;
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100229 }
230
231 current_power_profile = profile;
232}
233
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100234static void find_input_nodes(struct samsung_power_module *samsung_pwr, char *dir)
235{
236 const char filename[] = "name";
237 char errno_str[64];
238 struct dirent *de;
239 char file_content[20];
240 char *path = NULL;
241 char *node_path = NULL;
242 size_t pathsize;
243 size_t node_pathsize;
244 DIR *d;
245
246 d = opendir(dir);
247 if (d == NULL) {
248 return;
249 }
250
251 while ((de = readdir(d)) != NULL) {
252 if (strncmp(filename, de->d_name, sizeof(filename)) == 0) {
253 pathsize = strlen(dir) + strlen(de->d_name) + 2;
254 node_pathsize = strlen(dir) + strlen("enabled") + 2;
255
256 path = malloc(pathsize);
257 node_path = malloc(node_pathsize);
258 if (path == NULL || node_path == NULL) {
259 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100260 ALOGE("Out of memory: %s", errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100261 return;
262 }
263
264 snprintf(path, pathsize, "%s/%s", dir, filename);
265 sysfs_read(path, file_content, sizeof(file_content));
266
267 snprintf(node_path, node_pathsize, "%s/%s", dir, "enabled");
268
269 if (strncmp(file_content, "sec_touchkey", 12) == 0) {
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100270 ALOGV("%s: found touchkey path: %s", __func__, node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100271 samsung_pwr->touchkey_power_path = malloc(node_pathsize);
272 if (samsung_pwr->touchkey_power_path == NULL) {
273 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100274 ALOGE("Out of memory: %s", errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100275 return;
276 }
Christopher N. Hesse22da3132016-02-01 12:36:54 +0100277 snprintf(samsung_pwr->touchkey_power_path, node_pathsize,
278 "%s", node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100279 }
280
281 if (strncmp(file_content, "sec_touchscreen", 15) == 0) {
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100282 ALOGV("%s: found touchscreen path: %s", __func__, node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100283 samsung_pwr->touchscreen_power_path = malloc(node_pathsize);
284 if (samsung_pwr->touchscreen_power_path == NULL) {
285 strerror_r(errno, errno_str, sizeof(errno_str));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100286 ALOGE("Out of memory: %s", errno_str);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100287 return;
288 }
Christopher N. Hesse22da3132016-02-01 12:36:54 +0100289 snprintf(samsung_pwr->touchscreen_power_path, node_pathsize,
290 "%s", node_path);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100291 }
292 }
293 }
294
295 if (path)
296 free(path);
297 if (node_path)
298 free(node_path);
299 closedir(d);
300}
301
302/**********************************************************
303 *** INIT FUNCTIONS
304 **********************************************************/
305
306static void init_cpufreqs(struct samsung_power_module *samsung_pwr)
307{
308 int rc;
309 struct stat sb;
310
311 sysfs_read(CPU0_HISPEED_FREQ_PATH, samsung_pwr->cpu0_hispeed_freq,
312 sizeof(samsung_pwr->cpu0_hispeed_freq));
313 sysfs_read(CPU0_MAX_FREQ_PATH, samsung_pwr->cpu0_max_freq,
314 sizeof(samsung_pwr->cpu0_max_freq));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100315 ALOGV("%s: CPU 0 hispeed freq: %s", __func__, samsung_pwr->cpu0_hispeed_freq);
316 ALOGV("%s: CPU 0 max freq: %s", __func__, samsung_pwr->cpu0_max_freq);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100317
318 rc = stat(CPU4_HISPEED_FREQ_PATH, &sb);
319 if (rc == 0) {
320 sysfs_read(CPU4_HISPEED_FREQ_PATH, samsung_pwr->cpu4_hispeed_freq,
321 sizeof(samsung_pwr->cpu4_hispeed_freq));
322 sysfs_read(CPU4_MAX_FREQ_PATH, samsung_pwr->cpu4_max_freq,
323 sizeof(samsung_pwr->cpu4_max_freq));
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100324 ALOGV("%s: CPU 4 hispeed freq: %s", __func__, samsung_pwr->cpu4_hispeed_freq);
325 ALOGV("%s: CPU 4 max freq: %s", __func__, samsung_pwr->cpu4_max_freq);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100326 }
327}
328
329static void init_touch_input_power_path(struct samsung_power_module *samsung_pwr)
330{
331 char dir[1024];
332 char errno_str[64];
333 uint32_t i;
334
335 for (i = 0; i < 20; i++) {
336 snprintf(dir, sizeof(dir), "/sys/class/input/input%d", i);
337 find_input_nodes(samsung_pwr, dir);
338 }
339}
340
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100341static void samsung_power_init(struct power_module *module)
342{
343 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
344
345 init_cpufreqs(samsung_pwr);
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100346
347 boostpulse_open(samsung_pwr);
348
Christopher N. Hesse65c65bd2017-03-07 23:01:12 +0100349 samsung_pwr->touchscreen_power_path = NULL;
350 samsung_pwr->touchkey_power_path = NULL;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100351 init_touch_input_power_path(samsung_pwr);
352}
353
Christopher N. Hessef6296722017-01-16 22:47:11 +0100354/**********************************************************
355 *** API FUNCTIONS
356 ***
357 *** Refer to power.h for documentation.
358 **********************************************************/
359
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100360static void samsung_power_set_interactive(struct power_module *module, int on)
361{
362 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
363 struct stat sb;
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100364 int panel_brightness;
365 char button_state[2];
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100366 int rc;
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100367 static bool touchkeys_blocked = false;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100368
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100369 ALOGV("power_set_interactive: %d", on);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100370
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100371 /*
372 * Do not disable any input devices if the screen is on but we are in a non-interactive
373 * state.
374 */
Christopher N. Hesse3360b092016-07-11 15:48:35 +0200375 if (!on) {
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100376 panel_brightness = get_cur_panel_brightness();
377 if (panel_brightness < 0) {
378 ALOGE("%s: Failed to read panel brightness", __func__);
379 } else if (panel_brightness > 0) {
Christopher N. Hesse3360b092016-07-11 15:48:35 +0200380 ALOGV("%s: Moving to non-interactive state, but screen is still on,"
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100381 " not disabling input devices", __func__);
Christopher N. Hesse3360b092016-07-11 15:48:35 +0200382 goto out;
383 }
384 }
385
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100386 sysfs_write(samsung_pwr->touchscreen_power_path, on ? "1" : "0");
387
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100388 /* Bail out if the device does not have touchkeys */
389 if (samsung_pwr->touchkey_power_path == NULL) {
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100390 goto out;
391 }
392
393 if (!on) {
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100394 rc = sysfs_read(samsung_pwr->touchkey_power_path, button_state, ARRAY_SIZE(button_state));
395 if (rc < 0) {
396 ALOGE("%s: Failed to read touchkey state", __func__);
397 goto out;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100398 }
Christopher N. Hessed9106e92017-03-04 01:05:14 +0100399 /*
400 * If button_state is 0, the keys have been disabled by another component
401 * (for example cmhw), which means we don't want them to be enabled when resuming
402 * from suspend.
403 */
404 if (button_state[0] == '0') {
405 touchkeys_blocked = true;
406 } else {
407 touchkeys_blocked = false;
408 }
409 }
410
411 if (!touchkeys_blocked) {
412 sysfs_write(samsung_pwr->touchkey_power_path, on ? "1" : "0");
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100413 }
414
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100415out:
Christopher N. Hesse2879c692016-07-11 15:49:49 +0200416 sysfs_write(IO_IS_BUSY_PATH, on ? "1" : "0");
Christopher N. Hesse354f7132017-03-04 01:06:22 +0100417 ALOGV("power_set_interactive: %d done", on);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100418}
419
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100420static void samsung_power_hint(struct power_module *module,
421 power_hint_t hint,
422 void *data)
423{
424 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
425 char errno_str[64];
426 int len;
427
Christopher N. Hesse15b63092017-03-12 17:04:53 +0100428 /* Bail out if low-power mode is active */
429 if (current_power_profile == PROFILE_POWER_SAVE && hint != POWER_HINT_SET_PROFILE) {
430 ALOGW("%s: PROFILE_POWER_SAVE active, ignoring hint %d", __func__, hint);
431 return;
432 }
433
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100434 switch (hint) {
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100435 case POWER_HINT_VSYNC:
436 ALOGV("%s: POWER_HINT_VSYNC", __func__);
437 break;
438 case POWER_HINT_INTERACTION:
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100439 ALOGV("%s: POWER_HINT_INTERACTION", __func__);
Christopher N. Hessef21fbdb2017-03-04 01:41:58 +0100440 send_boostpulse(samsung_pwr->boostpulse_fd);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100441 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100442 case POWER_HINT_LOW_POWER:
443 ALOGV("%s: POWER_HINT_LOW_POWER", __func__);
444 set_power_profile(samsung_pwr, PROFILE_POWER_SAVE);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100445 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100446 case POWER_HINT_LAUNCH:
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100447 case POWER_HINT_CPU_BOOST:
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100448 ALOGV("%s: POWER_HINT_LAUNCH | POWER_HINT_CPU_BOOST", __func__);
Christopher N. Hesse5fada9b2017-01-16 23:39:48 +0100449 boost((*(int32_t *)data));
450 break;
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100451 case POWER_HINT_SET_PROFILE:
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100452 ALOGV("%s: POWER_HINT_SET_PROFILE", __func__);
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100453 int profile = *((intptr_t *)data);
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100454 set_power_profile(samsung_pwr, profile);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100455 break;
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100456 default:
Christopher N. Hesse2981f792017-03-12 17:08:47 +0100457 ALOGW("%s: Unknown power hint: %d", __func__, hint);
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100458 break;
459 }
460}
461
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100462static int samsung_get_feature(struct power_module *module __unused,
463 feature_t feature)
464{
465 if (feature == POWER_FEATURE_SUPPORTED_PROFILES) {
Christopher N. Hesse58f2ca02017-01-17 00:01:15 +0100466 return PROFILE_MAX;
Andreas Schneiderf15d7f42016-02-03 10:43:47 +0100467 }
468
469 return -1;
470}
471
Christopher N. Hesse1c474662016-11-18 18:59:06 +0100472static void samsung_set_feature(struct power_module *module, feature_t feature, int state __unused)
Christopher N. Hessee480d892016-06-22 23:04:39 +0200473{
474 struct samsung_power_module *samsung_pwr = (struct samsung_power_module *) module;
475
476 switch (feature) {
ishantvivek987dcca2016-11-21 06:05:47 +0000477#ifdef TARGET_TAP_TO_WAKE_NODE
Christopher N. Hessee480d892016-06-22 23:04:39 +0200478 case POWER_FEATURE_DOUBLE_TAP_TO_WAKE:
479 ALOGV("%s: %s double tap to wake", __func__, state ? "enabling" : "disabling");
ishantvivek987dcca2016-11-21 06:05:47 +0000480 sysfs_write(TARGET_TAP_TO_WAKE_NODE, state > 0 ? "1" : "0");
Christopher N. Hessee480d892016-06-22 23:04:39 +0200481 break;
482#endif
483 default:
484 break;
485 }
486}
487
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100488static struct hw_module_methods_t power_module_methods = {
489 .open = NULL,
490};
491
492struct samsung_power_module HAL_MODULE_INFO_SYM = {
493 .base = {
494 .common = {
495 .tag = HARDWARE_MODULE_TAG,
496 .module_api_version = POWER_MODULE_API_VERSION_0_2,
497 .hal_api_version = HARDWARE_HAL_API_VERSION,
498 .id = POWER_HARDWARE_MODULE_ID,
499 .name = "Samsung Power HAL",
Christopher N. Hesseaa75be42017-01-16 22:47:59 +0100500 .author = "The LineageOS Project",
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100501 .methods = &power_module_methods,
502 },
503
504 .init = samsung_power_init,
505 .setInteractive = samsung_power_set_interactive,
506 .powerHint = samsung_power_hint,
Christopher N. Hessee480d892016-06-22 23:04:39 +0200507 .getFeature = samsung_get_feature,
508 .setFeature = samsung_set_feature
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100509 },
510
511 .lock = PTHREAD_MUTEX_INITIALIZER,
512 .boostpulse_fd = -1,
Christopher N. Hessede5e3c62015-12-21 21:28:23 +0100513};