2 * Keyboard driver for Openmoko Freerunner GSM phone
4 * (C) 2006-2007 by Openmoko, Inc.
5 * Author: Harald Welte <laforge@openmoko.org>
8 * inspired by corkgbd.c by Richard Purdie
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
16 #include <linux/delay.h>
17 #include <linux/platform_device.h>
18 #include <linux/init.h>
19 #include <linux/input.h>
20 #include <linux/interrupt.h>
21 #include <linux/jiffies.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/workqueue.h>
26 #include <mach/gpio.h>
27 #include <asm/mach-types.h>
30 extern int global_inside_suspend
;
32 #define global_inside_suspend 0
36 struct platform_device
*pdev
;
37 struct input_dev
*input
;
39 struct work_struct work
;
42 int hp_irq_count_in_work
;
47 static struct class *gta02kbd_switch_class
;
57 irqreturn_t (*isr
)(int irq
, void *dev_id
);
62 static irqreturn_t
gta02kbd_aux_irq(int irq
, void *dev_id
);
63 static irqreturn_t
gta02kbd_headphone_irq(int irq
, void *dev_id
);
64 static irqreturn_t
gta02kbd_default_key_irq(int irq
, void *dev_id
);
67 static struct gta02kbd_key keys
[] = {
69 .name
= "GTA02 AUX button",
70 .isr
= gta02kbd_aux_irq
,
71 .input_key
= KEY_PHONE
,
74 .name
= "GTA02 HOLD button",
75 .isr
= gta02kbd_default_key_irq
,
76 .input_key
= KEY_PAUSE
,
79 .name
= "GTA02 Headphone jack",
80 .isr
= gta02kbd_headphone_irq
,
84 /* This timer section filters AUX button IRQ bouncing */
86 static void aux_key_timer_f(unsigned long data
);
88 static struct timer_list aux_key_timer
=
89 TIMER_INITIALIZER(aux_key_timer_f
, 0, 0);
91 #define AUX_TIMER_TIMEOUT (HZ >> 7)
92 #define AUX_TIMER_ALLOWED_NOOP 2
93 #define AUX_TIMER_CONSECUTIVE_EVENTS 5
95 struct gta02kbd
*timer_kbd
;
97 static void aux_key_timer_f(unsigned long data
)
99 static int noop_counter
;
100 static int last_key
= -1;
101 static int last_count
;
105 gpio_get_value(timer_kbd
->pdev
->resource
[GTA02_KEY_AUX
].start
);
107 if (likely(key_pressed
== last_key
))
111 last_key
= key_pressed
;
114 if (unlikely(last_count
>= AUX_TIMER_CONSECUTIVE_EVENTS
)) {
115 if (timer_kbd
->aux_state
!= last_key
) {
116 input_report_key(timer_kbd
->input
, KEY_PHONE
, last_key
);
117 input_sync(timer_kbd
->input
);
119 timer_kbd
->aux_state
= last_key
;
123 if (unlikely(++noop_counter
> AUX_TIMER_ALLOWED_NOOP
)) {
129 mod_timer(&aux_key_timer
, jiffies
+ AUX_TIMER_TIMEOUT
);
132 static irqreturn_t
gta02kbd_aux_irq(int irq
, void *dev
)
134 mod_timer(&aux_key_timer
, jiffies
+ AUX_TIMER_TIMEOUT
);
139 static irqreturn_t
gta02kbd_default_key_irq(int irq
, void *dev_id
)
141 struct gta02kbd
*kbd
= dev_id
;
144 for (n
= 0; n
< ARRAY_SIZE(keys
); n
++) {
146 if (irq
!= keys
[n
].irq
)
149 input_report_key(kbd
->input
, keys
[n
].input_key
,
150 gpio_get_value(kbd
->pdev
->resource
[n
].start
));
151 input_sync(kbd
->input
);
158 static const char *event_array_jack
[2][4] = {
160 "SWITCH_NAME=headset",
166 "SWITCH_NAME=headset",
173 static void gta02kbd_jack_event(struct device
*dev
, int num
)
175 kobject_uevent_env(&dev
->kobj
, KOBJ_CHANGE
, (char **)event_array_jack
[!!num
]);
179 static void gta02kbd_debounce_jack(struct work_struct
*work
)
181 struct gta02kbd
*kbd
= container_of(work
, struct gta02kbd
, work
);
188 * we wait out any multiple interrupt
189 * stuttering in 100ms lumps
192 kbd
->hp_irq_count_in_work
= kbd
->hp_irq_count
;
194 } while (kbd
->hp_irq_count
!= kbd
->hp_irq_count_in_work
);
196 * no new interrupts on jack for 100ms...
197 * ok we will report it
199 level
= gpio_get_value(kbd
->pdev
->resource
[GTA02_KEY_JACK
].start
);
200 input_report_switch(kbd
->input
, SW_HEADPHONE_INSERT
, level
);
201 input_sync(kbd
->input
);
202 gta02kbd_jack_event(kbd
->cdev
, level
);
204 * we go around the outer loop again if we detect that more
205 * interrupts came while we are servicing here. But we have
206 * to sequence it carefully with interrupts off
208 local_save_flags(flags
);
209 /* no interrupts during this work means we can exit the work */
210 loop
= !!(kbd
->hp_irq_count
!= kbd
->hp_irq_count_in_work
);
212 kbd
->work_in_progress
= 0;
213 local_irq_restore(flags
);
215 * interrupt that comes here will either queue a new work action
216 * since work_in_progress is cleared now, or be dealt with
223 static irqreturn_t
gta02kbd_headphone_irq(int irq
, void *dev_id
)
225 struct gta02kbd
*gta02kbd_data
= dev_id
;
228 * this interrupt is prone to bouncing and userspace doesn't like
229 * to have to deal with that kind of thing. So we do not accept
230 * that a jack interrupt is equal to a jack event. Instead we fire
231 * some work on the first interrupt, and it hangs about in 100ms units
232 * until no more interrupts come. Then it accepts the state it finds
233 * for jack insert and reports it once
236 gta02kbd_data
->hp_irq_count
++;
238 * the first interrupt we see for a while, we fire the work item
239 * and record the interrupt count when we did that. If more interrupts
240 * come in the meanwhile, we can tell by the difference in that
241 * stored count and hp_irq_count which increments every interrupt
243 if (!gta02kbd_data
->work_in_progress
) {
244 gta02kbd_data
->jack_irq
= irq
;
245 gta02kbd_data
->hp_irq_count_in_work
=
246 gta02kbd_data
->hp_irq_count
;
247 if (!schedule_work(>a02kbd_data
->work
))
249 "Unable to schedule headphone debounce\n");
251 gta02kbd_data
->work_in_progress
= 1;
258 static int gta02kbd_suspend(struct platform_device
*dev
, pm_message_t state
)
260 disable_irq(keys
[GTA02_KEY_AUX
].irq
);
261 del_timer_sync(&aux_key_timer
);
265 static int gta02kbd_resume(struct platform_device
*dev
)
267 enable_irq(keys
[GTA02_KEY_AUX
].irq
);
271 #define gta02kbd_suspend NULL
272 #define gta02kbd_resume NULL
275 static ssize_t
gta02kbd_switch_name_show(struct device
*dev
,
276 struct device_attribute
*attr
, char *buf
)
278 return sprintf(buf
, "%s\n", "gta02 Headset Jack");
281 static ssize_t
gta02kbd_switch_state_show(struct device
*dev
,
282 struct device_attribute
*attr
, char *buf
)
284 struct gta02kbd
*kbd
= dev_get_drvdata(dev
);
285 return sprintf(buf
, "%d\n",
286 gpio_get_value(kbd
->pdev
->resource
[GTA02_KEY_JACK
].start
));
289 static DEVICE_ATTR(name
, S_IRUGO
, gta02kbd_switch_name_show
, NULL
);
290 static DEVICE_ATTR(state
, S_IRUGO
, gta02kbd_switch_state_show
, NULL
);
292 static int gta02kbd_probe(struct platform_device
*pdev
)
294 struct gta02kbd
*gta02kbd
;
295 struct input_dev
*input_dev
;
300 gta02kbd
= kzalloc(sizeof(struct gta02kbd
), GFP_KERNEL
);
301 input_dev
= input_allocate_device();
302 if (!gta02kbd
|| !input_dev
) {
304 input_free_device(input_dev
);
308 gta02kbd
->pdev
= pdev
;
309 timer_kbd
= gta02kbd
;
311 if (pdev
->resource
[0].flags
!= 0)
314 platform_set_drvdata(pdev
, gta02kbd
);
316 gta02kbd
->input
= input_dev
;
318 INIT_WORK(>a02kbd
->work
, gta02kbd_debounce_jack
);
320 input_dev
->name
= "GTA02 Buttons";
321 input_dev
->phys
= "gta02kbd/input0";
322 input_dev
->id
.bustype
= BUS_HOST
;
323 input_dev
->id
.vendor
= 0x0001;
324 input_dev
->id
.product
= 0x0001;
325 input_dev
->id
.version
= 0x0100;
326 input_dev
->dev
.parent
= &pdev
->dev
;
328 input_dev
->evbit
[0] = BIT(EV_KEY
) | BIT(EV_SW
);
329 set_bit(SW_HEADPHONE_INSERT
, input_dev
->swbit
);
330 set_bit(KEY_PHONE
, input_dev
->keybit
);
331 set_bit(KEY_PAUSE
, input_dev
->keybit
);
333 rc
= input_register_device(gta02kbd
->input
);
337 gta02kbd
->cdev
= device_create(gta02kbd_switch_class
,
338 &pdev
->dev
, 0, gta02kbd
, "headset");
339 if (unlikely(IS_ERR(gta02kbd
->cdev
))) {
340 rc
= PTR_ERR(gta02kbd
->cdev
);
341 goto out_device_create
;
344 rc
= device_create_file(gta02kbd
->cdev
, &dev_attr_name
);
346 goto out_device_create_file
;
348 rc
= device_create_file(gta02kbd
->cdev
, &dev_attr_state
);
350 goto out_device_create_file
;
352 /* register GPIO IRQs */
353 for(n
= 0; n
< min(pdev
->num_resources
, ARRAY_SIZE(keys
)); n
++) {
355 if (!pdev
->resource
[0].start
)
358 irq
= gpio_to_irq(pdev
->resource
[n
].start
);
362 if (request_irq(irq
, keys
[n
].isr
, IRQF_DISABLED
|
363 IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING
,
364 keys
[n
].name
, gta02kbd
)) {
365 dev_err(&pdev
->dev
, "Can't get IRQ %u\n", irq
);
367 /* unwind any irq registrations and fail */
371 free_irq(gpio_to_irq(pdev
->resource
[n
].start
),
374 goto out_device_create_file
;
380 enable_irq_wake(keys
[GTA02_KEY_JACK
].irq
);
384 out_device_create_file
:
385 device_unregister(gta02kbd
->cdev
);
387 input_unregister_device(gta02kbd
->input
);
389 input_free_device(gta02kbd
->input
);
390 platform_set_drvdata(pdev
, NULL
);
396 static int gta02kbd_remove(struct platform_device
*pdev
)
398 struct gta02kbd
*gta02kbd
= platform_get_drvdata(pdev
);
400 free_irq(gpio_to_irq(pdev
->resource
[2].start
), gta02kbd
);
401 free_irq(gpio_to_irq(pdev
->resource
[1].start
), gta02kbd
);
402 free_irq(gpio_to_irq(pdev
->resource
[0].start
), gta02kbd
);
404 device_unregister(gta02kbd
->cdev
);
405 input_unregister_device(gta02kbd
->input
);
406 input_free_device(gta02kbd
->input
);
407 platform_set_drvdata(pdev
, NULL
);
413 static struct platform_driver gta02kbd_driver
= {
414 .probe
= gta02kbd_probe
,
415 .remove
= gta02kbd_remove
,
416 .suspend
= gta02kbd_suspend
,
417 .resume
= gta02kbd_resume
,
419 .name
= "gta02-button",
423 static int __devinit
gta02kbd_init(void)
425 gta02kbd_switch_class
= class_create(THIS_MODULE
, "switch");
426 if (IS_ERR(gta02kbd_switch_class
))
427 return PTR_ERR(gta02kbd_switch_class
);
428 return platform_driver_register(>a02kbd_driver
);
431 static void __exit
gta02kbd_exit(void)
433 platform_driver_unregister(>a02kbd_driver
);
434 class_destroy(gta02kbd_switch_class
);
437 module_init(gta02kbd_init
);
438 module_exit(gta02kbd_exit
);
440 MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
441 MODULE_DESCRIPTION("Openmoko Freerunner buttons input driver");
442 MODULE_LICENSE("GPL");