hh.org updates
[hh.org.git] / arch / arm / mach-pxa / aximx5 / aximx5_buttons.c
blob035e54cbec2f00796409d580c3c366619f767975
1 /*
2 * Input driver for Dell Axim X5.
3 * Creates input events for the buttons on the device
5 * Copyright 2004 Matthew Garrett
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
12 #include <linux/input.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <asm/irq.h>
18 #include <asm/mach/arch.h>
19 #include <asm/mach/map.h>
20 #include <asm/mach-types.h>
21 #include <asm/hardware.h>
22 #include <asm/arch/pxa-regs.h>
23 #include <asm/arch/irqs.h>
24 #include <asm/arch/aximx5-gpio.h>
26 #define GET_GPIO(gpio) (GPLR(gpio) & GPIO_bit(gpio))
28 struct input_dev button_dev;
29 static volatile int joypad_event_count;
30 static wait_queue_head_t joypad_event;
31 struct completion thread_comp;
32 static volatile int must_die;
33 /* Current joystick state bits: ENTER (bit 0), UP (1), RIGHT, DOWN, LEFT */
34 static u32 joystate;
36 static struct {
37 u16 keyno;
38 u8 irq;
39 u8 gpio;
40 char *desc;
41 } buttontab [] = {
42 #define KEY_DEF(x) AXIMX5_IRQ (x), GPIO_NR_AXIMX5_##x
43 { KEY_POWER, KEY_DEF (POWER_BUTTON_N), "Sleep button" },
44 { KEY_RECORD, KEY_DEF (BUTTON_RECORD), "Record button" },
45 { KEY_CALENDAR, KEY_DEF (BUTTON_CALENDAR), "Calendar button" },
46 { KEY_CONTACTS, KEY_DEF (BUTTON_CONTACTS), "Contacts button" },
47 { KEY_MAIL, KEY_DEF (BUTTON_MAILBOX), "Mailbox button" },
48 { KEY_HOMEPAGE, KEY_DEF (BUTTON_HOME), "Home button" },
49 { KEY_SCROLLDOWN, KEY_DEF (SCROLL_DOWN), "Scroll down" },
50 { KEY_SELECT, KEY_DEF (SCROLL_PUSH), "Scroll push" },
51 { KEY_SCROLLUP, KEY_DEF (SCROLL_UP), "Scroll up" },
52 #undef KEY_DEF
55 static u8 joyirq [] = {
56 AXIMX5_IRQ (JOY_PRESSED),
57 AXIMX5_IRQ (JOY_NW),
58 AXIMX5_IRQ (JOY_NE),
59 AXIMX5_IRQ (JOY_SE),
60 AXIMX5_IRQ (JOY_SW),
63 static char *joyirqdesc [] =
65 "Joystick pressed",
66 "Joystick NW",
67 "Joystick NE",
68 "Joystick SE",
69 "Joystick SW"
72 /* This table is used to convert 4-bit joystick state into key indices.
73 * If the bit combination have no logical meaning (say NW/SE are set at
74 * the same time), we default to 0 (e.g. KEY_SELECT). At any given time
75 * joystick cannot generate more than two pressed keys. So we're using
76 * the lower nibble for key index 1 and upper nibble for key index 2
77 * (if upper nibble is f, the particular bit combination generates just
78 * one key press). Also note that a bit value of '0' means key is pressed,
79 * while '1' means key is not pressed.
81 static u8 joydecode [16] = {
82 0xff, /* 0000 */
83 0x14, /* 0001 */
84 0x12, /* 0010 */
85 0xf3, /* 0011 */
86 0x34, /* 0100 */
87 0xff, /* 0101 */
88 0xf4, /* 0110 */
89 0x34, /* 0111 */
90 0x23, /* 1000 */
91 0xf2, /* 1001 */
92 0xff, /* 1010 */
93 0x23, /* 1011 */
94 0xf1, /* 1100 */
95 0x12, /* 1101 */
96 0x14, /* 1110 */
97 0xf0, /* 1111 */
100 /* This table is used to convert key indices into actual key codes.
102 static u16 joykeycode [5] = {
103 KEY_ENTER, /* 0 */
104 KEY_UP, /* 1 */
105 KEY_RIGHT, /* 2 */
106 KEY_DOWN, /* 3 */
107 KEY_LEFT /* 4 */
110 irqreturn_t aximx5_button_handle (int irq, void *dev_id, struct pt_regs *regs)
112 int button, down;
114 /* look up the keyno */
115 for (button = 0; button < ARRAY_SIZE (buttontab); button++)
116 if (buttontab [button].irq == irq)
117 break;
119 /* This happens with 100% probability */
120 if (likely (button < ARRAY_SIZE (buttontab))) {
121 down = GET_GPIO (buttontab [button].gpio) ? 1 : 0;
122 if (buttontab [button].keyno == KEY_SLEEP)
123 down ^= 1;
124 input_report_key (&button_dev, buttontab [button].keyno, down);
125 input_sync (&button_dev);
128 return IRQ_HANDLED;
131 irqreturn_t aximx5_joy_handle (int irq, void* dev_id, struct pt_regs *regs)
133 joypad_event_count++;
134 wake_up_interruptible (&joypad_event);
135 return IRQ_HANDLED;
138 static void joypad_decode (void)
140 u32 i, code, newstate;
142 /* Decode current joystick bit combination */
143 code = joydecode [GPIO_JOY_DIR];
145 newstate = GET_AXIMX5_GPIO (JOY_PRESSED) ? 0 :
146 ((1 << (code & 15)) | (1 << (code >> 4)));
147 /* We're not interested in other bits (e.g. 1 << 0xf) */
148 newstate &= 0x1f;
150 /* Find out which bits have changed */
151 joystate ^= newstate;
152 for (i = 0; i <= 5; i++)
153 if (joystate & (1 << i)) {
154 int down = (newstate & (1 << i)) ? 1 : 0;
155 input_report_key (&button_dev, joykeycode [i], down);
156 input_sync (&button_dev);
158 joystate = newstate;
161 static int joypad_thread (void *arg)
163 int old_count;
165 daemonize ("kjoypad");
166 set_user_nice (current, 5);
168 for (;;) {
169 if (must_die)
170 break;
172 joypad_decode ();
174 old_count = joypad_event_count;
175 wait_event_interruptible (joypad_event, old_count != joypad_event_count);
177 if (must_die)
178 break;
180 do {
181 old_count = joypad_event_count;
182 set_current_state (TASK_INTERRUPTIBLE);
183 schedule_timeout (HZ/50);
184 } while (old_count != joypad_event_count);
187 complete_and_exit (&thread_comp, 0);
190 static int __init aximx5_button_init (void)
192 int i;
194 must_die = 0;
195 joystate = 0;
197 set_bit (EV_KEY, button_dev.evbit);
199 /* Joystick emmits UP/DOWN/LEFT/RIGHT/SELECT key events */
200 button_dev.keybit [LONG (KEY_UP)] |= BIT (KEY_UP);
201 button_dev.keybit [LONG (KEY_DOWN)] |= BIT (KEY_DOWN);
202 button_dev.keybit [LONG (KEY_LEFT)] |= BIT (KEY_LEFT);
203 button_dev.keybit [LONG (KEY_RIGHT)] |= BIT (KEY_RIGHT);
204 button_dev.keybit [LONG (KEY_SELECT)] |= BIT (KEY_SELECT);
206 for (i = 0; i < ARRAY_SIZE (buttontab); i++) {
207 request_irq (buttontab [i].irq, aximx5_button_handle,
208 SA_SAMPLE_RANDOM, buttontab [i].desc, NULL);
209 set_irq_type (buttontab [i].irq, IRQT_BOTHEDGE);
210 button_dev.keybit [LONG (buttontab [i].keyno)] =
211 BIT (buttontab[i].keyno);
214 for (i = 0; i < ARRAY_SIZE (joyirq); i++) {
215 request_irq (joyirq [i], aximx5_joy_handle,
216 SA_SAMPLE_RANDOM, joyirqdesc [i], NULL);
217 set_irq_type (joyirq [i], IRQT_BOTHEDGE);
220 button_dev.name = "Dell Axim X5 buttons driver";
221 input_register_device (&button_dev);
223 init_waitqueue_head (&joypad_event);
224 init_completion (&thread_comp);
225 kernel_thread (joypad_thread, NULL, 0);
227 printk (KERN_INFO "%s installed\n", button_dev.name);
229 return 0;
232 static void __exit aximx5_button_exit (void)
234 int i;
236 /* First of all, kill kthread */
237 must_die = 1;
238 joypad_event_count++;
239 wake_up_interruptible (&joypad_event);
240 wait_for_completion (&thread_comp);
242 input_unregister_device (&button_dev);
244 for (i = 0; i < ARRAY_SIZE (joyirq); i++)
245 free_irq (joyirq [i], NULL);
247 for (i = 0; i < ARRAY_SIZE (buttontab); i++)
248 free_irq (buttontab [i].irq, NULL);
251 module_init (aximx5_button_init);
252 module_exit (aximx5_button_exit);
254 MODULE_AUTHOR ("Matthew Garrett <mjg59@srcf.ucam.org>");
255 MODULE_DESCRIPTION ("Button support for Dell Axim X5");
256 MODULE_LICENSE ("GPL");