sync hh.org
[hh.org.git] / arch / arm / mach-pxa / rover / roverp1_buttons.c
blobffdf7904b9fd04388d9f67c2bdd416a812efc8c0
1 /*
2 * Input driver for Rover P1.
3 * Based on Input driver for Dell Axim X5.
4 * Creates input events for the buttons on the device
6 * Copyright 2004 Matthew Garrett
7 * Konstantine A. Beklemishev
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
11 * more details.
14 #include <linux/input.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/irqs.h>
24 #include <asm/arch/roverp1-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) ROVERP1_IRQ (x), GPIO_NR_ROVERP1_##x
43 { KEY_SLEEP, KEY_DEF (POWER_BTN), "Sleep button" },
44 { KEY_RECORD, KEY_DEF (REC_BTN), "Record button" },
45 { KEY_CALENDAR, KEY_DEF (CALENDAR), "Calendar button" },
46 { KEY_CONTACTS, KEY_DEF (CONTACTS), "Contacts button" },
47 { KEY_MEMO, KEY_DEF (MEMO), "Memo button" },
48 { KEY_TASK, KEY_DEF (TASK), "Task button" },
49 #undef KEY_DEF
52 static u8 joyirq [] = {
53 ROVERP1_IRQ (JOG_ENTER),
54 ROVERP1_IRQ (JOG_UP),
55 ROVERP1_IRQ (JOG_DOWN),
56 ROVERP1_IRQ (JOG_LEFT),
57 ROVERP1_IRQ (JOG_RIGHT),
60 static char *joyirqdesc [] =
62 "Joystick pressed",
63 "Joystick up",
64 "Joystick down",
65 "Joystick left",
66 "Joystick right"
69 /* This table is used to convert 4-bit joystick state into key indices.
70 * If the bit combination have no logical meaning (say NW/SE are set at
71 * the same time), we default to 0 (e.g. KEY_SELECT). At any given time
72 * joystick cannot generate more than two pressed keys. So we're using
73 * the lower nibble for key index 1 and upper nibble for key index 2
74 * (if upper nibble is f, the particular bit combination generates just
75 * one key press). Also note that a bit value of '0' means key is pressed,
76 * while '1' means key is not pressed.
78 static u8 joydecode [16] = {
79 0xff, /* 0000 */
80 0x14, /* 0001 */
81 0x12, /* 0010 */
82 0xf3, /* 0011 */
83 0x34, /* 0100 */
84 0xff, /* 0101 */
85 0xf4, /* 0110 */
86 0x34, /* 0111 */
87 0x23, /* 1000 */
88 0xf2, /* 1001 */
89 0xff, /* 1010 */
90 0x23, /* 1011 */
91 0xf1, /* 1100 */
92 0x12, /* 1101 */
93 0x14, /* 1110 */
94 0xf0, /* 1111 */
97 /* This table is used to convert key indices into actual key codes.
99 static u16 joykeycode [5] = {
100 KEY_SELECT, /* 0 */
101 KEY_UP, /* 1 */
102 KEY_RIGHT, /* 2 */
103 KEY_DOWN, /* 3 */
104 KEY_LEFT /* 4 */
107 irqreturn_t roverp1_button_handle (int irq, void *dev_id, struct pt_regs *regs)
109 int button, down;
111 /* look up the keyno */
112 for (button = 0; button < ARRAY_SIZE (buttontab); button++)
113 if (buttontab [button].irq == irq)
114 break;
116 /* This happens with 100% probability */
117 if (likely (button < ARRAY_SIZE (buttontab))) {
118 down = GET_GPIO (buttontab [button].gpio) ? 1 : 0;
119 if (buttontab [button].keyno == KEY_SLEEP)
120 down ^= 1;
121 input_report_key (&button_dev, buttontab [button].keyno, down);
122 /* printk(KERN_INFO "%s button %d\n", (down ? "Pushed" : "Released"), button ); */
123 input_sync (&button_dev);
126 return IRQ_HANDLED;
129 irqreturn_t roverp1_joy_handle (int irq, void* dev_id, struct pt_regs *regs)
131 joypad_event_count++;
132 wake_up_interruptible (&joypad_event);
133 return IRQ_HANDLED;
136 static void joypad_decode (void)
138 u32 i, code, newstate;
140 /* Decode current joystick bit combination */
141 code = joydecode [GPIO_JOY_DIR];
143 newstate = GET_ROVERP1_GPIO (JOG_ENTER) ? 0 :
144 ((1 << (code & 15)) | (1 << (code >> 4)));
145 /* We're not interested in other bits (e.g. 1 << 0xf) */
146 newstate &= 0x1f;
148 /* Find out which bits have changed */
149 joystate ^= newstate;
150 for (i = 0; i <= 5; i++)
151 if (joystate & (1 << i)) {
152 int down = (newstate & (1 << i)) ? 1 : 0;
153 input_report_key (&button_dev, joykeycode [i], down);
154 input_sync (&button_dev);
156 joystate = newstate;
157 /* printk(KERN_INFO "Keys state: %02x\n", joystate); */
160 static int joypad_thread (void *arg)
162 int old_count;
164 daemonize ("kjoypad");
165 set_user_nice (current, 5);
167 for (;;) {
168 if (must_die)
169 break;
171 joypad_decode ();
173 old_count = joypad_event_count;
174 wait_event_interruptible (joypad_event, old_count != joypad_event_count);
176 if (must_die)
177 break;
179 do {
180 old_count = joypad_event_count;
181 set_current_state (TASK_INTERRUPTIBLE);
182 schedule_timeout (HZ/50);
183 } while (old_count != joypad_event_count);
186 complete_and_exit (&thread_comp, 0);
189 static int __init roverp1_button_init (void)
191 int i;
193 must_die = 0;
194 joystate = 0;
196 set_bit (EV_KEY, button_dev.evbit);
198 /* Joystick emmits UP/DOWN/LEFT/RIGHT/SELECT key events */
199 button_dev.keybit [LONG (KEY_UP)] |= BIT (KEY_UP);
200 button_dev.keybit [LONG (KEY_DOWN)] |= BIT (KEY_DOWN);
201 button_dev.keybit [LONG (KEY_LEFT)] |= BIT (KEY_LEFT);
202 button_dev.keybit [LONG (KEY_RIGHT)] |= BIT (KEY_RIGHT);
203 button_dev.keybit [LONG (KEY_SELECT)] |= BIT (KEY_SELECT);
205 for (i = 0; i < ARRAY_SIZE (buttontab); i++) {
206 request_irq (buttontab [i].irq, roverp1_button_handle,
207 SA_SAMPLE_RANDOM, buttontab [i].desc, NULL);
208 set_irq_type (buttontab [i].irq, IRQT_BOTHEDGE);
209 button_dev.keybit [LONG (buttontab [i].keyno)] =
210 BIT (buttontab[i].keyno);
213 for (i = 0; i < ARRAY_SIZE (joyirq); i++) {
214 request_irq (joyirq [i], roverp1_joy_handle,
215 SA_SAMPLE_RANDOM, joyirqdesc [i], NULL);
216 set_irq_type (joyirq [i], IRQT_BOTHEDGE);
219 button_dev.name = "Rover P1 buttons driver";
220 input_register_device (&button_dev);
222 init_waitqueue_head (&joypad_event);
223 init_completion (&thread_comp);
224 kernel_thread (joypad_thread, NULL, 0);
226 printk (KERN_INFO "%s installed\n", button_dev.name);
228 return 0;
231 static void __exit roverp1_button_exit (void)
233 int i;
235 /* First of all, kill kthread */
236 must_die = 1;
237 joypad_event_count++;
238 wake_up_interruptible (&joypad_event);
239 wait_for_completion (&thread_comp);
241 input_unregister_device (&button_dev);
243 for (i = 0; i < ARRAY_SIZE (joyirq); i++)
244 free_irq (joyirq [i], NULL);
246 for (i = 0; i < ARRAY_SIZE (buttontab); i++)
247 free_irq (buttontab [i].irq, NULL);
250 module_init (roverp1_button_init);
251 module_exit (roverp1_button_exit);
253 MODULE_AUTHOR ("Konstantine A. Beklemishev <konstantine .at. r66 .dot. ru>");
254 MODULE_DESCRIPTION ("Button support for Rover P1");
255 MODULE_LICENSE ("GPL");