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
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>
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 */
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" },
55 static u8 joyirq
[] = {
56 AXIMX5_IRQ (JOY_PRESSED
),
63 static char *joyirqdesc
[] =
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] = {
100 /* This table is used to convert key indices into actual key codes.
102 static u16 joykeycode
[5] = {
110 irqreturn_t
aximx5_button_handle (int irq
, void *dev_id
, struct pt_regs
*regs
)
114 /* look up the keyno */
115 for (button
= 0; button
< ARRAY_SIZE (buttontab
); button
++)
116 if (buttontab
[button
].irq
== irq
)
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
)
124 input_report_key (&button_dev
, buttontab
[button
].keyno
, down
);
125 input_sync (&button_dev
);
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
);
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) */
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
);
161 static int joypad_thread (void *arg
)
165 daemonize ("kjoypad");
166 set_user_nice (current
, 5);
174 old_count
= joypad_event_count
;
175 wait_event_interruptible (joypad_event
, old_count
!= joypad_event_count
);
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)
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
);
232 static void __exit
aximx5_button_exit (void)
236 /* First of all, kill kthread */
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");