hh.org updates
[hh.org.git] / arch / arm / mach-pxa / h1900 / h1900_buttons.c
blob1e5abad7d748996c2746393e6ac04e27b14e3604
1 /*
2 * Buttons driver for iPAQ h1910/h1915
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive for
6 * more details.
8 * Copyright (C) 2005 Pawel Kolodziejski
9 * Copyright (C) 2003 Joshua Wise
13 #include <linux/input.h>
14 #include <linux/input_pda.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18 #include <asm/irq.h>
19 #include <asm/mach/arch.h>
20 #include <asm/mach/map.h>
21 #include <asm/mach-types.h>
22 #include <asm/hardware.h>
23 #include <asm/arch/pxa-regs.h>
24 #include <asm/arch/irqs.h>
25 #include <asm/hardware/ipaq-asic3.h>
26 #include <asm/arch/h1900-gpio.h>
27 #include <asm/arch/h1900-asic.h>
28 #include <linux/fb.h>
29 #include <linux/soc/asic3_base.h>
30 #include <linux/platform_device.h>
32 extern struct platform_device h1900_asic3;
33 #define asic3 &h1900_asic3.dev
34 static struct input_dev *button_dev;
36 struct keys {
37 int keyno;
38 int gpio;
39 char *desc;
42 static struct keys pxa_button_tab[] = {
43 { _KEY_POWER, GPIO_NR_H1900_POWER_BUTTON_N, "Power button" },
44 { KEY_ENTER, GPIO_NR_H1900_ACTION_BUTTON_N, "Action button" },
45 { KEY_UP, GPIO_NR_H1900_UP_BUTTON_N, "Up button" },
46 { KEY_DOWN, GPIO_NR_H1900_DOWN_BUTTON_N, "Down button" },
47 { KEY_LEFT, GPIO_NR_H1900_LEFT_BUTTON_N, "Left button" },
48 { KEY_RIGHT, GPIO_NR_H1900_RIGHT_BUTTON_N, "Right button" },
51 struct kpad {
52 int keybit;
53 int keyno;
54 int irq;
55 char *desc;
58 #define BIT_RECORD 0x04
59 #define BIT_HOME 0x08
60 #define BIT_MAIL 0x10
61 #define BIT_CONTACTS 0x20
62 #define BIT_CALENDAR 0x40
64 static struct kpad button_tab[] = {
65 { BIT_RECORD, _KEY_RECORD, H1900_RECORD_BTN_IRQ, "Record button" },
66 { BIT_HOME, _KEY_HOMEPAGE, H1900_HOME_BTN_IRQ, "Home button" },
67 { BIT_MAIL, _KEY_MAIL, H1900_MAIL_BTN_IRQ, "Mail button" },
68 { BIT_CONTACTS, _KEY_CONTACTS, H1900_CONTACTS_BTN_IRQ, "Contacts button" },
69 { BIT_CALENDAR, _KEY_CALENDAR, H1900_CALENDAR_BTN_IRQ, "Calendar button" },
72 static irqreturn_t h1900_buttons_asic_handle(int irq, void *data, struct pt_regs *regs)
74 int i, pressed, base_irq;
76 base_irq = asic3_irq_base(asic3);
77 for (i = 0; i < ARRAY_SIZE(button_tab); i++) {
78 if ((base_irq + button_tab[i].irq) == irq) {
79 pressed = !(asic3_get_gpio_status_d(asic3) & button_tab[i].keybit);
80 if (pressed == 0)
81 set_irq_type(irq, IRQT_FALLING);
82 else
83 set_irq_type(irq, IRQT_RISING);
85 input_report_key(button_dev, button_tab[i].keyno, pressed);
86 input_sync(button_dev);
90 return IRQ_HANDLED;
93 static irqreturn_t h1900_buttons_handle(int irq, void* data, struct pt_regs *regs)
95 int button, down;
97 for (button = 0; button < ARRAY_SIZE(pxa_button_tab); button++)
98 if (IRQ_GPIO(pxa_button_tab[button].gpio) == irq)
99 break;
101 if (likely(button < ARRAY_SIZE(pxa_button_tab))) {
102 down = GPLR(pxa_button_tab[button].gpio) & GPIO_bit(pxa_button_tab[button].gpio) ? 0 : 1;
103 input_report_key(button_dev, pxa_button_tab[button].keyno, down);
104 input_sync(button_dev);
107 return IRQ_HANDLED;
110 static int __init h1900_buttons_probe(struct device *dev)
112 int i, base_irq;
114 if (!machine_is_h1900())
115 return -ENODEV;
117 button_dev = input_allocate_device();
118 if (!button_dev)
119 return -ENOMEM;
121 button_dev->name = "hp iPAQ h1910/h1915 buttons driver";
122 set_bit(EV_KEY, button_dev->evbit);
124 base_irq = asic3_irq_base(asic3);
126 for (i = 0; i < ARRAY_SIZE(pxa_button_tab); i++) {
127 set_bit(pxa_button_tab[i].keyno, button_dev->keybit);
128 request_irq(IRQ_GPIO(pxa_button_tab[i].gpio), h1900_buttons_handle, SA_SAMPLE_RANDOM, pxa_button_tab[i].desc, NULL);
129 set_irq_type(IRQ_GPIO(pxa_button_tab[i].gpio), IRQT_BOTHEDGE);
132 for (i = 0; i < ARRAY_SIZE(button_tab); i++) {
133 set_bit(button_tab[i].keyno, button_dev->keybit);
134 request_irq(base_irq + button_tab[i].irq, h1900_buttons_asic_handle, SA_SAMPLE_RANDOM, button_tab[i].desc, NULL);
135 set_irq_type(base_irq + button_tab[i].irq, IRQT_FALLING);
138 input_register_device(button_dev);
140 return 0;
143 #ifdef CONFIG_PM
144 static int h1900_buttons_suspend(struct device *dev, pm_message_t state)
146 int i, base_irq;
148 base_irq = asic3_irq_base(asic3);
150 for (i = 0; i < ARRAY_SIZE(pxa_button_tab); i++) {
151 disable_irq(IRQ_GPIO(pxa_button_tab[i].gpio));
154 for (i = 0; i < ARRAY_SIZE(button_tab); i++) {
155 disable_irq(base_irq + button_tab[i].irq);
158 return 0;
161 static int h1900_buttons_resume(struct device *dev)
163 int i, base_irq;
165 base_irq = asic3_irq_base(asic3);
167 for (i = 0; i < ARRAY_SIZE(pxa_button_tab); i++) {
168 enable_irq(IRQ_GPIO(pxa_button_tab[i].gpio));
171 for (i = 0; i < ARRAY_SIZE(button_tab); i++) {
172 enable_irq(base_irq + button_tab[i].irq);
175 return 0;
177 #endif
179 static struct device_driver h1900_buttons_driver = {
180 .name = "h1900-buttons",
181 .bus = &platform_bus_type,
182 .probe = h1900_buttons_probe,
183 #ifdef CONFIG_PM
184 .suspend = h1900_buttons_suspend,
185 .resume = h1900_buttons_resume,
186 #endif
189 static int __init h1900_buttons_init(void)
191 if (!machine_is_h1900())
192 return -ENODEV;
194 return driver_register(&h1900_buttons_driver);
197 static void __exit h1900_buttons_exit(void)
199 int i, base_irq;
201 input_unregister_device(button_dev);
203 for (i = 0; i < ARRAY_SIZE(pxa_button_tab); i++) {
204 free_irq(IRQ_GPIO(pxa_button_tab[i].gpio), NULL);
207 base_irq = asic3_irq_base(asic3);
208 for (i = 0; i < ARRAY_SIZE(button_tab); i++) {
209 free_irq(base_irq + button_tab[i].irq, NULL);
212 driver_unregister(&h1900_buttons_driver);
215 module_init(h1900_buttons_init);
216 module_exit(h1900_buttons_exit);
218 MODULE_AUTHOR ("Joshua Wise, Pawel Kolodziejski");
219 MODULE_DESCRIPTION ("Button support for iPAQ h1910/h1915");
220 MODULE_LICENSE ("GPL");