]>
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 | ||
dd4f99b4 PM |
30 | #define PGDR 0xa400012c |
31 | ||
0a9b0db1 | 32 | static void hp6x0_apm_get_power_status(struct apm_power_info *info) |
3aa770e7 | 33 | { |
0a9b0db1 | 34 | int battery, backup, charging, percentage; |
3aa770e7 | 35 | u8 pgdr; |
3aa770e7 | 36 | |
0a9b0db1 PM |
37 | battery = adc_single(ADC_CHANNEL_BATTERY); |
38 | backup = adc_single(ADC_CHANNEL_BACKUP); | |
39 | charging = adc_single(ADC_CHANNEL_CHARGE); | |
3aa770e7 AS |
40 | |
41 | percentage = 100 * (battery - HP680_BATTERY_MIN) / | |
42 | (HP680_BATTERY_MAX - HP680_BATTERY_MIN); | |
43 | ||
8b03c040 KE |
44 | /* % of full battery */ |
45 | info->battery_life = percentage; | |
46 | ||
47 | /* We want our estimates in minutes */ | |
48 | info->units = 0; | |
49 | ||
50 | /* Extremely(!!) rough estimate, we will replace this with a datalist later on */ | |
51 | info->time = (2 * battery); | |
52 | ||
0a9b0db1 | 53 | info->ac_line_status = (battery > HP680_BATTERY_AC_ON) ? |
3aa770e7 AS |
54 | APM_AC_ONLINE : APM_AC_OFFLINE; |
55 | ||
8b03c040 | 56 | pgdr = ctrl_inb(PGDR); |
3aa770e7 | 57 | if (pgdr & PGDR_MAIN_BATTERY_OUT) { |
0a9b0db1 PM |
58 | info->battery_status = APM_BATTERY_STATUS_NOT_PRESENT; |
59 | info->battery_flag = 0x80; | |
60 | } else if (charging < 8) { | |
61 | info->battery_status = APM_BATTERY_STATUS_CHARGING; | |
62 | info->battery_flag = 0x08; | |
8b03c040 | 63 | info->ac_line_status = 0x01; |
3aa770e7 | 64 | } else if (percentage <= APM_CRITICAL) { |
0a9b0db1 PM |
65 | info->battery_status = APM_BATTERY_STATUS_CRITICAL; |
66 | info->battery_flag = 0x04; | |
3aa770e7 | 67 | } else if (percentage <= APM_LOW) { |
0a9b0db1 PM |
68 | info->battery_status = APM_BATTERY_STATUS_LOW; |
69 | info->battery_flag = 0x02; | |
3aa770e7 | 70 | } else { |
0a9b0db1 PM |
71 | info->battery_status = APM_BATTERY_STATUS_HIGH; |
72 | info->battery_flag = 0x01; | |
3aa770e7 | 73 | } |
3aa770e7 AS |
74 | } |
75 | ||
35f3c518 | 76 | static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev) |
3aa770e7 | 77 | { |
8c8ee825 | 78 | if (!APM_DISABLED) |
3aa770e7 AS |
79 | apm_queue_event(APM_USER_SUSPEND); |
80 | ||
81 | return IRQ_HANDLED; | |
82 | } | |
83 | ||
84 | static int __init hp6x0_apm_init(void) | |
85 | { | |
86 | int ret; | |
87 | ||
88 | ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt, | |
0a9b0db1 | 89 | IRQF_DISABLED, MODNAME, NULL); |
3aa770e7 AS |
90 | if (unlikely(ret < 0)) { |
91 | printk(KERN_ERR MODNAME ": IRQ %d request failed\n", | |
92 | HP680_BTN_IRQ); | |
93 | return ret; | |
94 | } | |
95 | ||
0a9b0db1 | 96 | apm_get_power_status = hp6x0_apm_get_power_status; |
3aa770e7 AS |
97 | |
98 | return ret; | |
99 | } | |
100 | ||
101 | static void __exit hp6x0_apm_exit(void) | |
102 | { | |
103 | free_irq(HP680_BTN_IRQ, 0); | |
3aa770e7 AS |
104 | } |
105 | ||
106 | module_init(hp6x0_apm_init); | |
107 | module_exit(hp6x0_apm_exit); | |
108 | ||
109 | MODULE_AUTHOR("Adriy Skulysh"); | |
110 | MODULE_DESCRIPTION("hp6xx Advanced Power Management"); | |
111 | MODULE_LICENSE("GPL"); |