diff options
Diffstat (limited to 'drivers/input/touchscreen/mainstone-wm97xx.c')
| -rw-r--r-- | drivers/input/touchscreen/mainstone-wm97xx.c | 91 |
1 files changed, 50 insertions, 41 deletions
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 1d11e2be9ef..0786010d7ed 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -14,7 +14,7 @@ * * Notes: * This is a wm97xx extended touch driver to capture touch - * data in a continuous manner on the Intel XScale archictecture + * data in a continuous manner on the Intel XScale architecture * * Features: * - codecs supported:- WM9705, WM9712, WM9713 @@ -25,15 +25,16 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/wm97xx.h> #include <linux/io.h> +#include <linux/gpio.h> + #include <mach/regs-ac97.h> -#define VERSION "0.13" +#include <asm/mach-types.h> struct continuous { u16 id; /* codec id */ @@ -62,6 +63,7 @@ static const struct continuous cinfo[] = { /* continuous speed index */ static int sp_idx; static u16 last, tries; +static int irq; /* * Pen sampling frequency (Hz) in continuous mode. @@ -111,13 +113,12 @@ static void wm97xx_acc_pen_up(struct wm97xx *wm) #else static void wm97xx_acc_pen_up(struct wm97xx *wm) { - int count = 16; + unsigned int count; + schedule_timeout_uninterruptible(1); - while (count < 16) { + for (count = 0; count < 16; count++) MODR; - count--; - } } #endif @@ -129,7 +130,7 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) /* When the AC97 queue has been drained we need to allow time * to buffer up samples otherwise we end up spinning polling * for samples. The controller can't have a suitably low - * threashold set to use the notifications it gives. + * threshold set to use the notifications it gives. */ schedule_timeout_uninterruptible(1); @@ -151,10 +152,13 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) if (pressure) p = MODR; + dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n", + x, y, p); + /* are samples valid */ - if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || - (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || - (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) + if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X || + (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y || + (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES) goto up; /* coordinate is good */ @@ -162,6 +166,7 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) input_report_abs(wm->input_dev, ABS_X, x & 0xfff); input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); + input_report_key(wm->input_dev, BTN_TOUCH, (p != 0)); input_sync(wm->input_dev); reads++; } while (reads < cinfo[sp_idx].reads); @@ -171,7 +176,7 @@ up: static int wm97xx_acc_startup(struct wm97xx *wm) { - int idx = 0; + int idx = 0, ret = 0; /* check we have a codec */ if (wm->ac97 == NULL) @@ -191,18 +196,40 @@ static int wm97xx_acc_startup(struct wm97xx *wm) "mainstone accelerated touchscreen driver, %d samples/sec\n", cinfo[sp_idx].speed); + /* IRQ driven touchscreen is used on Palm hardware */ + if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) { + pen_int = 1; + irq = 27; + /* There is some obscure mutant of WM9712 interbred with WM9713 + * used on Palm HW */ + wm->variant = WM97xx_WM1613; + } else if (machine_is_mainstone() && pen_int) + irq = 4; + + if (irq) { + ret = gpio_request(irq, "Touchscreen IRQ"); + if (ret) + goto out; + + ret = gpio_direction_input(irq); + if (ret) { + gpio_free(irq); + goto out; + } + + wm->pen_irq = gpio_to_irq(irq); + irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); + } else /* pen irq not supported */ + pen_int = 0; + /* codec specific irq config */ if (pen_int) { switch (wm->id) { case WM9705_ID2: - wm->pen_irq = IRQ_GPIO(4); - set_irq_type(IRQ_GPIO(4), IRQ_TYPE_EDGE_BOTH); break; case WM9712_ID2: case WM9713_ID2: - /* enable pen down interrupt */ /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ - wm->pen_irq = MAINSTONE_AC97_IRQ; wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, WM97XX_GPIO_POL_HIGH, WM97XX_GPIO_STICKY, @@ -220,23 +247,17 @@ static int wm97xx_acc_startup(struct wm97xx *wm) } } - return 0; +out: + return ret; } static void wm97xx_acc_shutdown(struct wm97xx *wm) { /* codec specific deconfig */ if (pen_int) { - switch (wm->id & 0xffff) { - case WM9705_ID2: - wm->pen_irq = 0; - break; - case WM9712_ID2: - case WM9713_ID2: - /* disable interrupt */ - wm->pen_irq = 0; - break; - } + if (irq) + gpio_free(irq); + wm->pen_irq = 0; } } @@ -245,7 +266,7 @@ static void wm97xx_irq_enable(struct wm97xx *wm, int enable) if (enable) enable_irq(wm->pen_irq); else - disable_irq(wm->pen_irq); + disable_irq_nosync(wm->pen_irq); } static struct wm97xx_mach_ops mainstone_mach_ops = { @@ -280,19 +301,7 @@ static struct platform_driver mainstone_wm97xx_driver = { .name = "wm97xx-touch", }, }; - -static int __init mainstone_wm97xx_init(void) -{ - return platform_driver_register(&mainstone_wm97xx_driver); -} - -static void __exit mainstone_wm97xx_exit(void) -{ - platform_driver_unregister(&mainstone_wm97xx_driver); -} - -module_init(mainstone_wm97xx_init); -module_exit(mainstone_wm97xx_exit); +module_platform_driver(mainstone_wm97xx_driver); /* Module information */ MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>"); |
