drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / kernel / power / sbsuspend.c
CommitLineData
6fa3eb70
S
1/* kernel/power/sbsuspend.c
2 *
3 * This software is licensed under the terms of the GNU General Public
4 * License version 2, as published by the Free Software Foundation, and
5 * may be copied, distributed, and modified under those terms.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/sbsuspend.h>
15#include <linux/module.h>
16#include <linux/mutex.h>
17#include <linux/rtc.h>
18//#include <linux/leds-mt65xx.h>
19
20
21enum {
22 DEBUG_USER_STATE = 1U << 0,
23 DEBUG_SUSPEND = 1U << 2,
24 DEBUG_VERBOSE = 1U << 3,
25};
26int sbsuspend_debug_mask = DEBUG_USER_STATE | DEBUG_SUSPEND | DEBUG_VERBOSE;;
27module_param_named(sbsuspend_debug_mask, sbsuspend_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
28
29#define _TAG_PM_M "SB_PM"
30#define pm_warn(fmt, ...) \
31 if (sbsuspend_debug_mask) pr_warn("[%s][%s]" fmt, _TAG_PM_M, __func__, ##__VA_ARGS__);
32
33#define sb_attr(_name) \
34static struct kobj_attribute _name##_attr = { \
35 .attr = { \
36 .name = __stringify(_name), \
37 .mode = 0644, \
38 }, \
39 .show = _name##_show, \
40 .store = _name##_store, \
41}
42
43
44
45//sb_state_t sb_state = SB_STATE_DISABLE;
46static DEFINE_MUTEX(sb_mutex);
47static LIST_HEAD(sb_handlers);
48static int sb_bypass = 0;
49int sb_handler_count = 0;
50int sb_handler_forbid_id = 0x0;
51const char *const sb_states[SB_STATE_MAX] = {
52 [SB_STATE_DISABLE] = "disable",
53 [SB_STATE_ENABLE] = "enable",
54 [SB_STATE_SUSPEND] = "suspend",
55 [SB_STATE_RESUME] = "resume",
56};
57
58
59
60extern struct kobject *power_kobj;
61
62
63
64void register_sb_handler(struct sb_handler *handler)
65{
66 struct list_head *pos;
67
68 mutex_lock(&sb_mutex);
69
70 list_for_each(pos, &sb_handlers) {
71 struct sb_handler *e;
72 e = list_entry(pos, struct sb_handler, link);
73 if (e->level > handler->level)
74 break;
75 }
76 list_add_tail(&handler->link, pos);
77 sb_handler_count++;
78
79 //if ((state & SUSPENDED) && handler->suspend)
80 // handler->suspend(handler);
81
82 mutex_unlock(&sb_mutex);
83}
84EXPORT_SYMBOL(register_sb_handler);
85
86void unregister_sb_handler(struct sb_handler *handler)
87{
88 mutex_lock(&sb_mutex);
89
90 list_del(&handler->link);
91 sb_handler_count--;
92
93 mutex_unlock(&sb_mutex);
94}
95EXPORT_SYMBOL(unregister_sb_handler);
96
97void sb_enable(void)
98{
99 struct sb_handler *pos;
100 int count = 0;
101
102 pr_warn("@@@@@@@@@@@@@@@@@@@\n@@@__sb_enable__@@@\n@@@@@@@@@@@@@@@@@@@\n");
103
104 mutex_lock(&sb_mutex);
105
106 //pm_warn("turn backlight off\n");
107 //mt65xx_leds_brightness_set(MT65XX_LED_TYPE_BUTTON, 0);
108 //mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, 0);
109
110 pm_warn("sb_handler_count = %d, sb_handler_forbid_id = 0x%x\n", sb_handler_count, sb_handler_forbid_id);
111 list_for_each_entry(pos, &sb_handlers, link) {
112 if (pos->enable != NULL) {
113 if (!(sb_handler_forbid_id & (0x1 << count))) {
114 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
115 pm_warn("sb enable handler %d: [%pf], level: %d\n", count, pos->enable, pos->level);
116 pos->enable(pos);
117 }
118 count++;
119 }
120 }
121
122 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
123 pm_warn("sb enable handler done\n");
124
125 mutex_unlock(&sb_mutex);
126
127}
128EXPORT_SYMBOL(sb_enable);
129
130void sb_disable(void)
131{
132 struct sb_handler *pos;
133 int count = 0;
134
135 pr_warn("@@@@@@@@@@@@@@@@@@@@\n@@@__sb_disable__@@@\n@@@@@@@@@@@@@@@@@@@@\n");
136
137 mutex_lock(&sb_mutex);
138
139 pm_warn("sb_handler_count = %d, sb_handler_forbid_id = 0x%x\n", sb_handler_count, sb_handler_forbid_id);
140 list_for_each_entry_reverse(pos, &sb_handlers, link) {
141 if (pos->disable != NULL) {
142 if (!(sb_handler_forbid_id & (0x1 << (sb_handler_count - 1 - count)))) {
143 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
144 pm_warn("sb disable handler %d: [%pf], level: %d\n", count, pos->disable, pos->level);
145 pos->disable(pos);
146 }
147 count++;
148 }
149 }
150
151 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
152 pm_warn("sb disable handler done\n");
153
154 //pm_warn("turn backlight on\n");
155 //mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, 255);
156 //we don't need to turn keypad light on when SmartBook plug-out
157 //mt65xx_leds_brightness_set(MT65XX_LED_TYPE_BUTTON, 255);
158
159 mutex_unlock(&sb_mutex);
160}
161EXPORT_SYMBOL(sb_disable);
162
163void sb_suspend(void)
164{
165 struct sb_handler *pos;
166 int count = 0;
167
168 pr_warn("@@@@@@@@@@@@@@@@@@@\n@@@__sb_suspend__@@@\n@@@@@@@@@@@@@@@@@@@\n");
169
170 mutex_lock(&sb_mutex);
171
172 pm_warn("sb_handler_count = %d, sb_handler_forbid_id = 0x%x\n", sb_handler_count, sb_handler_forbid_id);
173 list_for_each_entry(pos, &sb_handlers, link) {
174 if (pos->suspend != NULL) {
175 if (!(sb_handler_forbid_id & (0x1 << count))) {
176 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
177 pm_warn("sb enable handler %d: [%pf], level: %d\n", count, pos->suspend, pos->level);
178 pos->suspend(pos);
179 }
180 count++;
181 }
182 }
183
184 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
185 pm_warn("sb enable handler done\n");
186
187 mutex_unlock(&sb_mutex);
188
189}
190EXPORT_SYMBOL(sb_suspend);
191
192void sb_resume(void)
193{
194 struct sb_handler *pos;
195 int count = 0;
196
197 pr_warn("@@@@@@@@@@@@@@@@@@@@\n@@@__sb_resume__@@@\n@@@@@@@@@@@@@@@@@@@@\n");
198
199 mutex_lock(&sb_mutex);
200
201 pm_warn("sb_handler_count = %d, sb_handler_forbid_id = 0x%x\n", sb_handler_count, sb_handler_forbid_id);
202 list_for_each_entry_reverse(pos, &sb_handlers, link) {
203 if (pos->resume != NULL) {
204 if (!(sb_handler_forbid_id & (0x1 << (sb_handler_count - 1 - count)))) {
205 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
206 pm_warn("sb disable handler %d: [%pf], level: %d\n", count, pos->resume, pos->level);
207 pos->resume(pos);
208 }
209 count++;
210 }
211 }
212
213 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
214 pm_warn("sb disable handler done\n");
215
216 mutex_unlock(&sb_mutex);
217}
218EXPORT_SYMBOL(sb_resume);
219
220void sb_plug_in(void)
221{
222 struct sb_handler *pos;
223 int count = 0;
224
225 if (sb_bypass)
226 return;
227
228 pr_warn("@@@@@@@@@@@@@@@@@@@\n@@@__sb_plug_in__@@@\n@@@@@@@@@@@@@@@@@@@\n");
229
230 mutex_lock(&sb_mutex);
231
232 pm_warn("sb_handler_count = %d, sb_handler_forbid_id = 0x%x\n", sb_handler_count, sb_handler_forbid_id);
233 list_for_each_entry(pos, &sb_handlers, link) {
234 if (pos->plug_in != NULL) {
235 if (!(sb_handler_forbid_id & (0x1 << count))) {
236 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
237 pm_warn("sb plug_in handler %d: [%pf], level: %d\n", count, pos->plug_in, pos->level);
238 pos->plug_in(pos);
239 }
240 count++;
241 }
242 }
243
244 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
245 pm_warn("sb plug_in handler done\n");
246
247 mutex_unlock(&sb_mutex);
248
249}
250EXPORT_SYMBOL(sb_plug_in);
251
252void sb_plug_out(void)
253{
254 struct sb_handler *pos;
255 int count = 0;
256
257 if (sb_bypass)
258 return;
259
260 pr_warn("@@@@@@@@@@@@@@@@@@@@\n@@@__sb_plug_out__@@@\n@@@@@@@@@@@@@@@@@@@@\n");
261
262 mutex_lock(&sb_mutex);
263
264 pm_warn("sb_handler_count = %d, sb_handler_forbid_id = 0x%x\n", sb_handler_count, sb_handler_forbid_id);
265 list_for_each_entry_reverse(pos, &sb_handlers, link) {
266 if (pos->plug_out != NULL) {
267 if (!(sb_handler_forbid_id & (0x1 << (sb_handler_count - 1 - count)))) {
268 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
269 pm_warn("sb plug_out handler %d: [%pf], level: %d\n", count, pos->plug_out, pos->level);
270 pos->plug_out(pos);
271 }
272 count++;
273 }
274 }
275
276 if (sbsuspend_debug_mask & DEBUG_SUSPEND)
277 pm_warn("sb plug_out handler done\n");
278
279 mutex_unlock(&sb_mutex);
280}
281EXPORT_SYMBOL(sb_plug_out);
282
283/*
284void sb_event(sb_event_t event)
285{
286 mutex_lock(&sb_mutex);
287
288 if (sbsuspend_debug_mask & DEBUG_USER_STATE) {
289 struct timespec ts;
290 struct rtc_time tm;
291 getnstimeofday(&ts);
292 rtc_time_to_tm(ts.tv_sec, &tm);
293 pm_warn("%s (%d->%d) at %lld "
294 "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
295 event != PM_SUSPEND_ON ? "sleep" : "wakeup",
296 sb_state, event,
297 ktime_to_ns(ktime_get()),
298 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
299 tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
300 }
301
302 switch (sb_state)
303 {
304 case SB_STATE_DISABLE:
305
306 case SB_STATE_ENABLE:
307
308 if (!old_sleep && new_state != PM_SUSPEND_ON) {
309 state |= SUSPEND_REQUESTED;
310 sb_enable();
311 } else if (old_sleep && new_state == PM_SUSPEND_ON) {
312 state &= ~SUSPEND_REQUESTED;
313 sb_disable();
314 }
315 sb_state = new_state;
316
317 mutex_unlock(&sb_mutex);
318
319}
320*/
321
322/**
323 * state - control system power state.
324 *
325 * show() returns what states are supported, which is hard-coded to
326 * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
327 * 'disk' (Suspend-to-Disk).
328 *
329 * store() accepts one of those strings, translates it into the
330 * proper enumerated value, and initiates a suspend transition.
331 */
332static ssize_t sb_state_show(struct kobject *kobj, struct kobj_attribute *attr,
333 char *buf)
334{
335 char *s = buf;
336 int i;
337
338 for (i = 0; i < SB_STATE_MAX; i++) {
339 if (sb_states[i])
340 s += sprintf(s,"%s ", sb_states[i]);
341 }
342 if (s != buf)
343 /* convert the last space to a newline */
344 *(s-1) = '\n';
345
346 return (s - buf);
347}
348
349static sb_state_t decode_sb_state(const char *buf, size_t n)
350{
351 sb_state_t state = SB_STATE_DISABLE;
352 const char * const *s;
353 char *p;
354 int len;
355
356 p = memchr(buf, '\n', n);
357 len = p ? p - buf : n;
358
359 for (s = &sb_states[state]; state < SB_STATE_MAX; s++, state++)
360 if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
361 return state;
362
363 return SB_STATE_MAX;
364}
365
366static ssize_t sb_state_store(struct kobject *kobj, struct kobj_attribute *attr,
367 const char *buf, size_t n)
368{
369 sb_state_t state;
370 int error = 0;
371 char cmd[32];
372 int param;
373
374 if (sscanf(buf, "%s %d", cmd, &param) == 2)
375 {
376 if (!strcmp(cmd, "bypass"))
377 sb_bypass = param;
378 }
379 else
380 {
381 if (!sb_bypass)
382 {
383 state = decode_sb_state(buf, n);
384
385 switch (state)
386 {
387 case SB_STATE_DISABLE:
388 sb_disable();
389 break;
390 case SB_STATE_ENABLE:
391 sb_enable();
392 break;
393 case SB_STATE_SUSPEND:
394 sb_suspend();
395 break;
396 case SB_STATE_RESUME:
397 sb_resume();
398 break;
399 default:
400 error = -EINVAL;
401 break;
402 }
403 }
404 }
405
406 return error ? error : n;
407}
408
409sb_attr(sb_state);
410
411
412
413
414static int __init sbsuspend_init(void)
415{
416 int err = 0;
417
418 err |= sysfs_create_file(power_kobj, &sb_state_attr.attr);
419 if (err) {
420 printk("[%s]: fail to create sysfs\n", __func__);
421 }
422 return 0;
423}
424
425static void __exit sbsuspend_exit(void)
426{
427}
428
429core_initcall(sbsuspend_init);
430module_exit(sbsuspend_exit);