Commit | Line | Data |
---|---|---|
3aa770e7 AS |
1 | /* |
2 | * bios-less APM driver for hp680 | |
3 | * | |
4 | * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com> | |
8b03c040 | 5 | * Copyright 2008 (c) Kristoffer Ericson <kristoffer.ericson@gmail.com> |
3aa770e7 AS |
6 | * |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License. | |
9 | */ | |
3aa770e7 | 10 | #include <linux/module.h> |
3aa770e7 AS |
11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> | |
13 | #include <linux/interrupt.h> | |
0a9b0db1 PM |
14 | #include <linux/apm-emulation.h> |
15 | #include <linux/io.h> | |
3aa770e7 | 16 | #include <asm/adc.h> |
082c44d2 | 17 | #include <asm/hp6xx.h> |
3aa770e7 | 18 | |
8b03c040 | 19 | /* percentage values */ |
3aa770e7 AS |
20 | #define APM_CRITICAL 10 |
21 | #define APM_LOW 30 | |
22 | ||
8b03c040 | 23 | /* resonably sane values */ |
8c8ee825 KE |
24 | #define HP680_BATTERY_MAX 898 |
25 | #define HP680_BATTERY_MIN 486 | |
26 | #define HP680_BATTERY_AC_ON 1023 | |
3aa770e7 AS |
27 | |
28 | #define MODNAME "hp6x0_apm" | |
29 | ||
0a9b0db1 | 30 | static void hp6x0_apm_get_power_status(struct apm_power_info *info) |
3aa770e7 | 31 | { |
0a9b0db1 | 32 | int battery, backup, charging, percentage; |
3aa770e7 | 33 | u8 pgdr; |
3aa770e7 | 34 | |
0a9b0db1 PM |
35 | battery = adc_single(ADC_CHANNEL_BATTERY); |
36 | backup = adc_single(ADC_CHANNEL_BACKUP); | |
37 | charging = adc_single(ADC_CHANNEL_CHARGE); | |
3aa770e7 AS |
38 | |
39 | percentage = 100 * (battery - HP680_BATTERY_MIN) / | |
40 | (HP680_BATTERY_MAX - HP680_BATTERY_MIN); | |
41 | ||
8b03c040 KE |
42 | /* % of full battery */ |
43 | info->battery_life = percentage; | |
44 | ||
45 | /* We want our estimates in minutes */ | |
46 | info->units = 0; | |
47 | ||
48 | /* Extremely(!!) rough estimate, we will replace this with a datalist later on */ | |
49 | info->time = (2 * battery); | |
50 | ||
0a9b0db1 | 51 | info->ac_line_status = (battery > HP680_BATTERY_AC_ON) ? |
3aa770e7 AS |
52 | APM_AC_ONLINE : APM_AC_OFFLINE; |
53 | ||
8b03c040 | 54 | pgdr = ctrl_inb(PGDR); |
3aa770e7 | 55 | if (pgdr & PGDR_MAIN_BATTERY_OUT) { |
0a9b0db1 PM |
56 | info->battery_status = APM_BATTERY_STATUS_NOT_PRESENT; |
57 | info->battery_flag = 0x80; | |
58 | } else if (charging < 8) { | |
59 | info->battery_status = APM_BATTERY_STATUS_CHARGING; | |
60 | info->battery_flag = 0x08; | |
8b03c040 | 61 | info->ac_line_status = 0x01; |
3aa770e7 | 62 | } else if (percentage <= APM_CRITICAL) { |
0a9b0db1 PM |
63 | info->battery_status = APM_BATTERY_STATUS_CRITICAL; |
64 | info->battery_flag = 0x04; | |
3aa770e7 | 65 | } else if (percentage <= APM_LOW) { |
0a9b0db1 PM |
66 | info->battery_status = APM_BATTERY_STATUS_LOW; |
67 | info->battery_flag = 0x02; | |
3aa770e7 | 68 | } else { |
0a9b0db1 PM |
69 | info->battery_status = APM_BATTERY_STATUS_HIGH; |
70 | info->battery_flag = 0x01; | |
3aa770e7 | 71 | } |
3aa770e7 AS |
72 | } |
73 | ||
35f3c518 | 74 | static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev) |
3aa770e7 | 75 | { |
8c8ee825 | 76 | if (!APM_DISABLED) |
3aa770e7 AS |
77 | apm_queue_event(APM_USER_SUSPEND); |
78 | ||
79 | return IRQ_HANDLED; | |
80 | } | |
81 | ||
82 | static int __init hp6x0_apm_init(void) | |
83 | { | |
84 | int ret; | |
85 | ||
86 | ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt, | |
0a9b0db1 | 87 | IRQF_DISABLED, MODNAME, NULL); |
3aa770e7 AS |
88 | if (unlikely(ret < 0)) { |
89 | printk(KERN_ERR MODNAME ": IRQ %d request failed\n", | |
90 | HP680_BTN_IRQ); | |
91 | return ret; | |
92 | } | |
93 | ||
0a9b0db1 | 94 | apm_get_power_status = hp6x0_apm_get_power_status; |
3aa770e7 AS |
95 | |
96 | return ret; | |
97 | } | |
98 | ||
99 | static void __exit hp6x0_apm_exit(void) | |
100 | { | |
101 | free_irq(HP680_BTN_IRQ, 0); | |
3aa770e7 AS |
102 | } |
103 | ||
104 | module_init(hp6x0_apm_init); | |
105 | module_exit(hp6x0_apm_exit); | |
106 | ||
107 | MODULE_AUTHOR("Adriy Skulysh"); | |
108 | MODULE_DESCRIPTION("hp6xx Advanced Power Management"); | |
109 | MODULE_LICENSE("GPL"); |