diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 22:52:01 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-09 22:52:01 -0500 |
| commit | fa395aaec823b9d1a5800913a6b5d0e6d1c5ced2 (patch) | |
| tree | d599abe9f4f48f1737da50fa9a48dadfd08100e3 /drivers/input/touchscreen | |
| parent | 3e7468313758913c5e4d372f35b271b96bad1298 (diff) | |
| parent | 1f26978afd123deb22dd3c7dc75771a02f6e03f6 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (51 commits)
Input: appletouch - give up maintainership
Input: dm355evm_kbd - switch to using sparse keymap library
Input: wistron_btns - switch to using sparse keymap library
Input: add generic support for sparse keymaps
Input: fix memory leak in force feedback core
Input: wistron - remove identification strings from DMI table
Input: psmouse - remove identification strings from DMI tables
Input: atkbd - remove identification strings from DMI table
Input: i8042 - remove identification strings from DMI tables
DMI: allow omitting ident strings in DMI tables
Input: psmouse - do not carry DMI data around
Input: matrix-keypad - switch to using dev_pm_ops
Input: keyboard - fix lack of locking when traversing handler->h_list
Input: gpio_keys - scan gpio state at probe and resume time
Input: keyboard - add locking around event handling
Input: usbtouchscreen - add support for ET&T TC5UH touchscreen controller
Input: xpad - add two new Xbox 360 devices
Input: polled device - do not start polling if interval is zero
Input: polled device - schedule first poll immediately
Input: add S3C24XX touchscreen driver
...
Diffstat (limited to 'drivers/input/touchscreen')
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 37 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 4 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ads7846.c | 25 | ||||
| -rw-r--r-- | drivers/input/touchscreen/atmel_tsadcc.c | 47 | ||||
| -rw-r--r-- | drivers/input/touchscreen/dynapro.c | 206 | ||||
| -rw-r--r-- | drivers/input/touchscreen/s3c2410_ts.c | 457 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ucb1400_ts.c | 11 | ||||
| -rw-r--r-- | drivers/input/touchscreen/usbtouchscreen.c | 104 |
8 files changed, 855 insertions, 36 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8cc453c85ea7..32fc8ba039aa 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -111,6 +111,18 @@ config TOUCHSCREEN_DA9034 | |||
| 111 | Say Y here to enable the support for the touchscreen found | 111 | Say Y here to enable the support for the touchscreen found |
| 112 | on Dialog Semiconductor DA9034 PMIC. | 112 | on Dialog Semiconductor DA9034 PMIC. |
| 113 | 113 | ||
| 114 | config TOUCHSCREEN_DYNAPRO | ||
| 115 | tristate "Dynapro serial touchscreen" | ||
| 116 | select SERIO | ||
| 117 | help | ||
| 118 | Say Y here if you have a Dynapro serial touchscreen connected to | ||
| 119 | your system. | ||
| 120 | |||
| 121 | If unsure, say N. | ||
| 122 | |||
| 123 | To compile this driver as a module, choose M here: the | ||
| 124 | module will be called dynapro. | ||
| 125 | |||
| 114 | config TOUCHSCREEN_EETI | 126 | config TOUCHSCREEN_EETI |
| 115 | tristate "EETI touchscreen panel support" | 127 | tristate "EETI touchscreen panel support" |
| 116 | depends on I2C | 128 | depends on I2C |
| @@ -133,6 +145,18 @@ config TOUCHSCREEN_FUJITSU | |||
| 133 | To compile this driver as a module, choose M here: the | 145 | To compile this driver as a module, choose M here: the |
| 134 | module will be called fujitsu-ts. | 146 | module will be called fujitsu-ts. |
| 135 | 147 | ||
| 148 | config TOUCHSCREEN_S3C2410 | ||
| 149 | tristate "Samsung S3C2410 touchscreen input driver" | ||
| 150 | depends on ARCH_S3C2410 | ||
| 151 | select S3C24XX_ADC | ||
| 152 | help | ||
| 153 | Say Y here if you have the s3c2410 touchscreen. | ||
| 154 | |||
| 155 | If unsure, say N. | ||
| 156 | |||
| 157 | To compile this driver as a module, choose M here: the | ||
| 158 | module will be called s3c2410_ts. | ||
| 159 | |||
| 136 | config TOUCHSCREEN_GUNZE | 160 | config TOUCHSCREEN_GUNZE |
| 137 | tristate "Gunze AHL-51S touchscreen" | 161 | tristate "Gunze AHL-51S touchscreen" |
| 138 | select SERIO | 162 | select SERIO |
| @@ -297,7 +321,7 @@ config TOUCHSCREEN_TOUCHWIN | |||
| 297 | 321 | ||
| 298 | config TOUCHSCREEN_ATMEL_TSADCC | 322 | config TOUCHSCREEN_ATMEL_TSADCC |
| 299 | tristate "Atmel Touchscreen Interface" | 323 | tristate "Atmel Touchscreen Interface" |
| 300 | depends on ARCH_AT91SAM9RL | 324 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
| 301 | help | 325 | help |
| 302 | Say Y here if you have a 4-wire touchscreen connected to the | 326 | Say Y here if you have a 4-wire touchscreen connected to the |
| 303 | ADC Controller on your Atmel SoC (such as the AT91SAM9RL). | 327 | ADC Controller on your Atmel SoC (such as the AT91SAM9RL). |
| @@ -418,6 +442,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 418 | - IdealTEK URTC1000 | 442 | - IdealTEK URTC1000 |
| 419 | - GoTop Super_Q2/GogoPen/PenPower tablets | 443 | - GoTop Super_Q2/GogoPen/PenPower tablets |
| 420 | - JASTEC USB Touch Controller/DigiTech DTR-02U | 444 | - JASTEC USB Touch Controller/DigiTech DTR-02U |
| 445 | - Zytronic controllers | ||
| 421 | 446 | ||
| 422 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 447 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
| 423 | a usage description and the required user-space stuff. | 448 | a usage description and the required user-space stuff. |
| @@ -490,6 +515,16 @@ config TOUCHSCREEN_USB_E2I | |||
| 490 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | 515 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" |
| 491 | depends on TOUCHSCREEN_USB_COMPOSITE | 516 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 492 | 517 | ||
| 518 | config TOUCHSCREEN_USB_ZYTRONIC | ||
| 519 | default y | ||
| 520 | bool "Zytronic controller" if EMBEDDED | ||
| 521 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 522 | |||
| 523 | config TOUCHSCREEN_USB_ETT_TC5UH | ||
| 524 | default y | ||
| 525 | bool "ET&T TC5UH touchscreen controler support" if EMBEDDED | ||
| 526 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 527 | |||
| 493 | config TOUCHSCREEN_TOUCHIT213 | 528 | config TOUCHSCREEN_TOUCHIT213 |
| 494 | tristate "Sahara TouchIT-213 touchscreen" | 529 | tristate "Sahara TouchIT-213 touchscreen" |
| 495 | select SERIO | 530 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 15fa62cffc77..f1f59c9e1211 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | |||
| 12 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 12 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
| 13 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 13 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
| 14 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 14 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
| 15 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | ||
| 15 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 16 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 16 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
| 17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 18 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
| @@ -25,7 +26,9 @@ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | |||
| 25 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o | 26 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o |
| 26 | obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o | 27 | obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o |
| 27 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | 28 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o |
| 29 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | ||
| 28 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 30 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
| 31 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | ||
| 29 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 32 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
| 30 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 33 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
| 31 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 34 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
| @@ -41,4 +44,3 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | |||
| 41 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 44 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
| 42 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 45 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
| 43 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 46 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
| 44 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | ||
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 09c810999b92..52d2ca147d8f 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -29,10 +29,9 @@ | |||
| 29 | #include <linux/spi/ads7846.h> | 29 | #include <linux/spi/ads7846.h> |
| 30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
| 31 | 31 | ||
| 32 | |||
| 33 | /* | 32 | /* |
| 34 | * This code has been heavily tested on a Nokia 770, and lightly | 33 | * This code has been heavily tested on a Nokia 770, and lightly |
| 35 | * tested on other ads7846 devices (OSK/Mistral, Lubbock). | 34 | * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz). |
| 36 | * TSC2046 is just newer ads7846 silicon. | 35 | * TSC2046 is just newer ads7846 silicon. |
| 37 | * Support for ads7843 tested on Atmel at91sam926x-EK. | 36 | * Support for ads7843 tested on Atmel at91sam926x-EK. |
| 38 | * Support for ads7845 has only been stubbed in. | 37 | * Support for ads7845 has only been stubbed in. |
| @@ -43,7 +42,7 @@ | |||
| 43 | * have to maintain our own SW IRQ disabled status. This should be | 42 | * have to maintain our own SW IRQ disabled status. This should be |
| 44 | * removed as soon as the affected platform's IRQ handling is fixed. | 43 | * removed as soon as the affected platform's IRQ handling is fixed. |
| 45 | * | 44 | * |
| 46 | * app note sbaa036 talks in more detail about accurate sampling... | 45 | * App note sbaa036 talks in more detail about accurate sampling... |
| 47 | * that ought to help in situations like LCDs inducing noise (which | 46 | * that ought to help in situations like LCDs inducing noise (which |
| 48 | * can also be helped by using synch signals) and more generally. | 47 | * can also be helped by using synch signals) and more generally. |
| 49 | * This driver tries to utilize the measures described in the app | 48 | * This driver tries to utilize the measures described in the app |
| @@ -566,10 +565,8 @@ static void ads7846_rx(void *ads) | |||
| 566 | * once more the measurement | 565 | * once more the measurement |
| 567 | */ | 566 | */ |
| 568 | if (packet->tc.ignore || Rt > ts->pressure_max) { | 567 | if (packet->tc.ignore || Rt > ts->pressure_max) { |
| 569 | #ifdef VERBOSE | 568 | dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n", |
| 570 | pr_debug("%s: ignored %d pressure %d\n", | 569 | packet->tc.ignore, Rt); |
| 571 | dev_name(&ts->spi->dev), packet->tc.ignore, Rt); | ||
| 572 | #endif | ||
| 573 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 570 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
| 574 | HRTIMER_MODE_REL); | 571 | HRTIMER_MODE_REL); |
| 575 | return; | 572 | return; |
| @@ -598,9 +595,7 @@ static void ads7846_rx(void *ads) | |||
| 598 | if (!ts->pendown) { | 595 | if (!ts->pendown) { |
| 599 | input_report_key(input, BTN_TOUCH, 1); | 596 | input_report_key(input, BTN_TOUCH, 1); |
| 600 | ts->pendown = 1; | 597 | ts->pendown = 1; |
| 601 | #ifdef VERBOSE | 598 | dev_vdbg(&ts->spi->dev, "DOWN\n"); |
| 602 | dev_dbg(&ts->spi->dev, "DOWN\n"); | ||
| 603 | #endif | ||
| 604 | } | 599 | } |
| 605 | 600 | ||
| 606 | if (ts->swap_xy) | 601 | if (ts->swap_xy) |
| @@ -608,12 +603,10 @@ static void ads7846_rx(void *ads) | |||
| 608 | 603 | ||
| 609 | input_report_abs(input, ABS_X, x); | 604 | input_report_abs(input, ABS_X, x); |
| 610 | input_report_abs(input, ABS_Y, y); | 605 | input_report_abs(input, ABS_Y, y); |
| 611 | input_report_abs(input, ABS_PRESSURE, Rt); | 606 | input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt); |
| 612 | 607 | ||
| 613 | input_sync(input); | 608 | input_sync(input); |
| 614 | #ifdef VERBOSE | 609 | dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); |
| 615 | dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); | ||
| 616 | #endif | ||
| 617 | } | 610 | } |
| 618 | 611 | ||
| 619 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 612 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
| @@ -723,9 +716,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) | |||
| 723 | input_sync(input); | 716 | input_sync(input); |
| 724 | 717 | ||
| 725 | ts->pendown = 0; | 718 | ts->pendown = 0; |
| 726 | #ifdef VERBOSE | 719 | dev_vdbg(&ts->spi->dev, "UP\n"); |
| 727 | dev_dbg(&ts->spi->dev, "UP\n"); | ||
| 728 | #endif | ||
| 729 | } | 720 | } |
| 730 | 721 | ||
| 731 | /* measurement cycle ended */ | 722 | /* measurement cycle ended */ |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 9c7fce4d74d0..3d9b5166ebe9 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <mach/board.h> | ||
| 26 | #include <mach/cpu.h> | ||
| 25 | 27 | ||
| 26 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ | 28 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ |
| 27 | 29 | ||
| @@ -36,7 +38,9 @@ | |||
| 36 | #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ | 38 | #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ |
| 37 | #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ | 39 | #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ |
| 38 | #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ | 40 | #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ |
| 41 | #define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */ | ||
| 39 | #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ | 42 | #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ |
| 43 | #define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */ | ||
| 40 | #define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ | 44 | #define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ |
| 41 | #define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ | 45 | #define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ |
| 42 | #define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ | 46 | #define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ |
| @@ -84,7 +88,13 @@ | |||
| 84 | #define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ | 88 | #define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ |
| 85 | #define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ | 89 | #define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ |
| 86 | 90 | ||
| 87 | #define ADC_CLOCK 1000000 | 91 | #define ATMEL_TSADCC_XPOS 0x50 |
| 92 | #define ATMEL_TSADCC_Z1DAT 0x54 | ||
| 93 | #define ATMEL_TSADCC_Z2DAT 0x58 | ||
| 94 | |||
| 95 | #define PRESCALER_VAL(x) ((x) >> 8) | ||
| 96 | |||
| 97 | #define ADC_DEFAULT_CLOCK 100000 | ||
| 88 | 98 | ||
| 89 | struct atmel_tsadcc { | 99 | struct atmel_tsadcc { |
| 90 | struct input_dev *input; | 100 | struct input_dev *input; |
| @@ -172,6 +182,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 172 | struct atmel_tsadcc *ts_dev; | 182 | struct atmel_tsadcc *ts_dev; |
| 173 | struct input_dev *input_dev; | 183 | struct input_dev *input_dev; |
| 174 | struct resource *res; | 184 | struct resource *res; |
| 185 | struct at91_tsadcc_data *pdata = pdev->dev.platform_data; | ||
| 175 | int err = 0; | 186 | int err = 0; |
| 176 | unsigned int prsc; | 187 | unsigned int prsc; |
| 177 | unsigned int reg; | 188 | unsigned int reg; |
| @@ -242,31 +253,49 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 242 | input_dev->phys = ts_dev->phys; | 253 | input_dev->phys = ts_dev->phys; |
| 243 | input_dev->dev.parent = &pdev->dev; | 254 | input_dev->dev.parent = &pdev->dev; |
| 244 | 255 | ||
| 245 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 256 | __set_bit(EV_ABS, input_dev->evbit); |
| 246 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 247 | |||
| 248 | input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); | 257 | input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); |
| 249 | input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); | 258 | input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); |
| 250 | 259 | ||
| 260 | input_set_capability(input_dev, EV_KEY, BTN_TOUCH); | ||
| 261 | |||
| 251 | /* clk_enable() always returns 0, no need to check it */ | 262 | /* clk_enable() always returns 0, no need to check it */ |
| 252 | clk_enable(ts_dev->clk); | 263 | clk_enable(ts_dev->clk); |
| 253 | 264 | ||
| 254 | prsc = clk_get_rate(ts_dev->clk); | 265 | prsc = clk_get_rate(ts_dev->clk); |
| 255 | dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); | 266 | dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); |
| 256 | 267 | ||
| 257 | prsc = prsc / ADC_CLOCK / 2 - 1; | 268 | if (!pdata) |
| 269 | goto err_fail; | ||
| 270 | |||
| 271 | if (!pdata->adc_clock) | ||
| 272 | pdata->adc_clock = ADC_DEFAULT_CLOCK; | ||
| 273 | |||
| 274 | prsc = (prsc / (2 * pdata->adc_clock)) - 1; | ||
| 275 | |||
| 276 | /* saturate if this value is too high */ | ||
| 277 | if (cpu_is_at91sam9rl()) { | ||
| 278 | if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL)) | ||
| 279 | prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL); | ||
| 280 | } else { | ||
| 281 | if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL)) | ||
| 282 | prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL); | ||
| 283 | } | ||
| 284 | |||
| 285 | dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc); | ||
| 258 | 286 | ||
| 259 | reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | | 287 | reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | |
| 260 | ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ | 288 | ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ |
| 261 | ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ | 289 | ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ |
| 262 | ((prsc << 8) & ATMEL_TSADCC_PRESCAL) | /* PRESCAL */ | 290 | (prsc << 8) | |
| 263 | ((0x13 << 16) & ATMEL_TSADCC_STARTUP) | /* STARTUP */ | 291 | ((0x26 << 16) & ATMEL_TSADCC_STARTUP) | |
| 264 | ((0x0F << 28) & ATMEL_TSADCC_PENDBC); /* PENDBC */ | 292 | ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC); |
| 265 | 293 | ||
| 266 | atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); | 294 | atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); |
| 267 | atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); | 295 | atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); |
| 268 | atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); | 296 | atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); |
| 269 | atmel_tsadcc_write(ATMEL_TSADCC_TSR, (0x3 << 24) & ATMEL_TSADCC_TSSHTIM); | 297 | atmel_tsadcc_write(ATMEL_TSADCC_TSR, |
| 298 | (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); | ||
| 270 | 299 | ||
| 271 | atmel_tsadcc_read(ATMEL_TSADCC_SR); | 300 | atmel_tsadcc_read(ATMEL_TSADCC_SR); |
| 272 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); | 301 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); |
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c new file mode 100644 index 000000000000..455353908bdf --- /dev/null +++ b/drivers/input/touchscreen/dynapro.c | |||
| @@ -0,0 +1,206 @@ | |||
| 1 | /* | ||
| 2 | * Dynapro serial touchscreen driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Tias Guns | ||
| 5 | * Based on the inexio driver (c) Vojtech Pavlik and Dan Streetman and | ||
| 6 | * Richard Lemon | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License version 2 as published by | ||
| 13 | * the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | /* | ||
| 17 | * 2009/09/19 Tias Guns <tias@ulyssis.org> | ||
| 18 | * Copied inexio.c and edited for Dynapro protocol (from retired Xorg module) | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/errno.h> | ||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/serio.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | |||
| 29 | #define DRIVER_DESC "Dynapro serial touchscreen driver" | ||
| 30 | |||
| 31 | MODULE_AUTHOR("Tias Guns <tias@ulyssis.org>"); | ||
| 32 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Definitions & global arrays. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #define DYNAPRO_FORMAT_TOUCH_BIT 0x40 | ||
| 40 | #define DYNAPRO_FORMAT_LENGTH 3 | ||
| 41 | #define DYNAPRO_RESPONSE_BEGIN_BYTE 0x80 | ||
| 42 | |||
| 43 | #define DYNAPRO_MIN_XC 0 | ||
| 44 | #define DYNAPRO_MAX_XC 0x3ff | ||
| 45 | #define DYNAPRO_MIN_YC 0 | ||
| 46 | #define DYNAPRO_MAX_YC 0x3ff | ||
| 47 | |||
| 48 | #define DYNAPRO_GET_XC(data) (data[1] | ((data[0] & 0x38) << 4)) | ||
| 49 | #define DYNAPRO_GET_YC(data) (data[2] | ((data[0] & 0x07) << 7)) | ||
| 50 | #define DYNAPRO_GET_TOUCHED(data) (DYNAPRO_FORMAT_TOUCH_BIT & data[0]) | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Per-touchscreen data. | ||
| 54 | */ | ||
| 55 | |||
| 56 | struct dynapro { | ||
| 57 | struct input_dev *dev; | ||
| 58 | struct serio *serio; | ||
| 59 | int idx; | ||
| 60 | unsigned char data[DYNAPRO_FORMAT_LENGTH]; | ||
| 61 | char phys[32]; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static void dynapro_process_data(struct dynapro *pdynapro) | ||
| 65 | { | ||
| 66 | struct input_dev *dev = pdynapro->dev; | ||
| 67 | |||
| 68 | if (DYNAPRO_FORMAT_LENGTH == ++pdynapro->idx) { | ||
| 69 | input_report_abs(dev, ABS_X, DYNAPRO_GET_XC(pdynapro->data)); | ||
| 70 | input_report_abs(dev, ABS_Y, DYNAPRO_GET_YC(pdynapro->data)); | ||
| 71 | input_report_key(dev, BTN_TOUCH, | ||
| 72 | DYNAPRO_GET_TOUCHED(pdynapro->data)); | ||
| 73 | input_sync(dev); | ||
| 74 | |||
| 75 | pdynapro->idx = 0; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | static irqreturn_t dynapro_interrupt(struct serio *serio, | ||
| 80 | unsigned char data, unsigned int flags) | ||
| 81 | { | ||
| 82 | struct dynapro *pdynapro = serio_get_drvdata(serio); | ||
| 83 | |||
| 84 | pdynapro->data[pdynapro->idx] = data; | ||
| 85 | |||
| 86 | if (DYNAPRO_RESPONSE_BEGIN_BYTE & pdynapro->data[0]) | ||
| 87 | dynapro_process_data(pdynapro); | ||
| 88 | else | ||
| 89 | dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", | ||
| 90 | pdynapro->data[0]); | ||
| 91 | |||
| 92 | return IRQ_HANDLED; | ||
| 93 | } | ||
| 94 | |||
| 95 | static void dynapro_disconnect(struct serio *serio) | ||
| 96 | { | ||
| 97 | struct dynapro *pdynapro = serio_get_drvdata(serio); | ||
| 98 | |||
| 99 | input_get_device(pdynapro->dev); | ||
| 100 | input_unregister_device(pdynapro->dev); | ||
| 101 | serio_close(serio); | ||
| 102 | serio_set_drvdata(serio, NULL); | ||
| 103 | input_put_device(pdynapro->dev); | ||
| 104 | kfree(pdynapro); | ||
| 105 | } | ||
| 106 | |||
| 107 | /* | ||
| 108 | * dynapro_connect() is the routine that is called when someone adds a | ||
| 109 | * new serio device that supports dynapro protocol and registers it as | ||
| 110 | * an input device. This is usually accomplished using inputattach. | ||
| 111 | */ | ||
| 112 | |||
| 113 | static int dynapro_connect(struct serio *serio, struct serio_driver *drv) | ||
| 114 | { | ||
| 115 | struct dynapro *pdynapro; | ||
| 116 | struct input_dev *input_dev; | ||
| 117 | int err; | ||
| 118 | |||
| 119 | pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL); | ||
| 120 | input_dev = input_allocate_device(); | ||
| 121 | if (!pdynapro || !input_dev) { | ||
| 122 | err = -ENOMEM; | ||
| 123 | goto fail1; | ||
| 124 | } | ||
| 125 | |||
| 126 | pdynapro->serio = serio; | ||
| 127 | pdynapro->dev = input_dev; | ||
| 128 | snprintf(pdynapro->phys, sizeof(pdynapro->phys), | ||
| 129 | "%s/input0", serio->phys); | ||
| 130 | |||
| 131 | input_dev->name = "Dynapro Serial TouchScreen"; | ||
| 132 | input_dev->phys = pdynapro->phys; | ||
| 133 | input_dev->id.bustype = BUS_RS232; | ||
| 134 | input_dev->id.vendor = SERIO_DYNAPRO; | ||
| 135 | input_dev->id.product = 0; | ||
| 136 | input_dev->id.version = 0x0001; | ||
| 137 | input_dev->dev.parent = &serio->dev; | ||
| 138 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 139 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 140 | input_set_abs_params(pdynapro->dev, ABS_X, | ||
| 141 | DYNAPRO_MIN_XC, DYNAPRO_MAX_XC, 0, 0); | ||
| 142 | input_set_abs_params(pdynapro->dev, ABS_Y, | ||
| 143 | DYNAPRO_MIN_YC, DYNAPRO_MAX_YC, 0, 0); | ||
| 144 | |||
| 145 | serio_set_drvdata(serio, pdynapro); | ||
| 146 | |||
| 147 | err = serio_open(serio, drv); | ||
| 148 | if (err) | ||
| 149 | goto fail2; | ||
| 150 | |||
| 151 | err = input_register_device(pdynapro->dev); | ||
| 152 | if (err) | ||
| 153 | goto fail3; | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | |||
| 157 | fail3: serio_close(serio); | ||
| 158 | fail2: serio_set_drvdata(serio, NULL); | ||
| 159 | fail1: input_free_device(input_dev); | ||
| 160 | kfree(pdynapro); | ||
| 161 | return err; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * The serio driver structure. | ||
| 166 | */ | ||
| 167 | |||
| 168 | static struct serio_device_id dynapro_serio_ids[] = { | ||
| 169 | { | ||
| 170 | .type = SERIO_RS232, | ||
| 171 | .proto = SERIO_DYNAPRO, | ||
| 172 | .id = SERIO_ANY, | ||
| 173 | .extra = SERIO_ANY, | ||
| 174 | }, | ||
| 175 | { 0 } | ||
| 176 | }; | ||
| 177 | |||
| 178 | MODULE_DEVICE_TABLE(serio, dynapro_serio_ids); | ||
| 179 | |||
| 180 | static struct serio_driver dynapro_drv = { | ||
| 181 | .driver = { | ||
| 182 | .name = "dynapro", | ||
| 183 | }, | ||
| 184 | .description = DRIVER_DESC, | ||
| 185 | .id_table = dynapro_serio_ids, | ||
| 186 | .interrupt = dynapro_interrupt, | ||
| 187 | .connect = dynapro_connect, | ||
| 188 | .disconnect = dynapro_disconnect, | ||
| 189 | }; | ||
| 190 | |||
| 191 | /* | ||
| 192 | * The functions for inserting/removing us as a module. | ||
| 193 | */ | ||
| 194 | |||
| 195 | static int __init dynapro_init(void) | ||
| 196 | { | ||
| 197 | return serio_register_driver(&dynapro_drv); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void __exit dynapro_exit(void) | ||
| 201 | { | ||
| 202 | serio_unregister_driver(&dynapro_drv); | ||
| 203 | } | ||
| 204 | |||
| 205 | module_init(dynapro_init); | ||
| 206 | module_exit(dynapro_exit); | ||
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c new file mode 100644 index 000000000000..6386b441ef85 --- /dev/null +++ b/drivers/input/touchscreen/s3c2410_ts.c | |||
| @@ -0,0 +1,457 @@ | |||
| 1 | /* | ||
| 2 | * Samsung S3C24XX touchscreen driver | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the term of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 17 | * | ||
| 18 | * Copyright 2004 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
| 19 | * Copyright 2008 Ben Dooks <ben-linux@fluff.org> | ||
| 20 | * Copyright 2009 Simtec Electronics <linux@simtec.co.uk> | ||
| 21 | * | ||
| 22 | * Additional work by Herbert Pötzl <herbert@13thfloor.at> and | ||
| 23 | * Harald Welte <laforge@openmoko.org> | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/gpio.h> | ||
| 31 | #include <linux/input.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/delay.h> | ||
| 34 | #include <linux/interrupt.h> | ||
| 35 | #include <linux/platform_device.h> | ||
| 36 | #include <linux/clk.h> | ||
| 37 | #include <linux/io.h> | ||
| 38 | |||
| 39 | #include <plat/adc.h> | ||
| 40 | #include <plat/regs-adc.h> | ||
| 41 | |||
| 42 | #include <mach/regs-gpio.h> | ||
| 43 | #include <mach/ts.h> | ||
| 44 | |||
| 45 | #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) | ||
| 46 | |||
| 47 | #define INT_DOWN (0) | ||
| 48 | #define INT_UP (1 << 8) | ||
| 49 | |||
| 50 | #define WAIT4INT (S3C2410_ADCTSC_YM_SEN | \ | ||
| 51 | S3C2410_ADCTSC_YP_SEN | \ | ||
| 52 | S3C2410_ADCTSC_XP_SEN | \ | ||
| 53 | S3C2410_ADCTSC_XY_PST(3)) | ||
| 54 | |||
| 55 | #define AUTOPST (S3C2410_ADCTSC_YM_SEN | \ | ||
| 56 | S3C2410_ADCTSC_YP_SEN | \ | ||
| 57 | S3C2410_ADCTSC_XP_SEN | \ | ||
| 58 | S3C2410_ADCTSC_AUTO_PST | \ | ||
| 59 | S3C2410_ADCTSC_XY_PST(0)) | ||
| 60 | |||
| 61 | /* Per-touchscreen data. */ | ||
| 62 | |||
| 63 | /** | ||
| 64 | * struct s3c2410ts - driver touchscreen state. | ||
| 65 | * @client: The ADC client we registered with the core driver. | ||
| 66 | * @dev: The device we are bound to. | ||
| 67 | * @input: The input device we registered with the input subsystem. | ||
| 68 | * @clock: The clock for the adc. | ||
| 69 | * @io: Pointer to the IO base. | ||
| 70 | * @xp: The accumulated X position data. | ||
| 71 | * @yp: The accumulated Y position data. | ||
| 72 | * @irq_tc: The interrupt number for pen up/down interrupt | ||
| 73 | * @count: The number of samples collected. | ||
| 74 | * @shift: The log2 of the maximum count to read in one go. | ||
| 75 | */ | ||
| 76 | struct s3c2410ts { | ||
| 77 | struct s3c_adc_client *client; | ||
| 78 | struct device *dev; | ||
| 79 | struct input_dev *input; | ||
| 80 | struct clk *clock; | ||
| 81 | void __iomem *io; | ||
| 82 | unsigned long xp; | ||
| 83 | unsigned long yp; | ||
| 84 | int irq_tc; | ||
| 85 | int count; | ||
| 86 | int shift; | ||
| 87 | }; | ||
| 88 | |||
| 89 | static struct s3c2410ts ts; | ||
| 90 | |||
| 91 | /** | ||
| 92 | * s3c2410_ts_connect - configure gpio for s3c2410 systems | ||
| 93 | * | ||
| 94 | * Configure the GPIO for the S3C2410 system, where we have external FETs | ||
| 95 | * connected to the device (later systems such as the S3C2440 integrate | ||
| 96 | * these into the device). | ||
| 97 | */ | ||
| 98 | static inline void s3c2410_ts_connect(void) | ||
| 99 | { | ||
| 100 | s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); | ||
| 101 | s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); | ||
| 102 | s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); | ||
| 103 | s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * get_down - return the down state of the pen | ||
| 108 | * @data0: The data read from ADCDAT0 register. | ||
| 109 | * @data1: The data read from ADCDAT1 register. | ||
| 110 | * | ||
| 111 | * Return non-zero if both readings show that the pen is down. | ||
| 112 | */ | ||
| 113 | static inline bool get_down(unsigned long data0, unsigned long data1) | ||
| 114 | { | ||
| 115 | /* returns true if both data values show stylus down */ | ||
| 116 | return (!(data0 & S3C2410_ADCDAT0_UPDOWN) && | ||
| 117 | !(data1 & S3C2410_ADCDAT0_UPDOWN)); | ||
| 118 | } | ||
| 119 | |||
| 120 | static void touch_timer_fire(unsigned long data) | ||
| 121 | { | ||
| 122 | unsigned long data0; | ||
| 123 | unsigned long data1; | ||
| 124 | bool down; | ||
| 125 | |||
| 126 | data0 = readl(ts.io + S3C2410_ADCDAT0); | ||
| 127 | data1 = readl(ts.io + S3C2410_ADCDAT1); | ||
| 128 | |||
| 129 | down = get_down(data0, data1); | ||
| 130 | |||
| 131 | if (ts.count == (1 << ts.shift)) { | ||
| 132 | ts.xp >>= ts.shift; | ||
| 133 | ts.yp >>= ts.shift; | ||
| 134 | |||
| 135 | dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n", | ||
| 136 | __func__, ts.xp, ts.yp, ts.count); | ||
| 137 | |||
| 138 | input_report_abs(ts.input, ABS_X, ts.xp); | ||
| 139 | input_report_abs(ts.input, ABS_Y, ts.yp); | ||
| 140 | |||
| 141 | input_report_key(ts.input, BTN_TOUCH, 1); | ||
| 142 | input_sync(ts.input); | ||
| 143 | |||
| 144 | ts.xp = 0; | ||
| 145 | ts.yp = 0; | ||
| 146 | ts.count = 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (down) { | ||
| 150 | s3c_adc_start(ts.client, 0, 1 << ts.shift); | ||
| 151 | } else { | ||
| 152 | ts.count = 0; | ||
| 153 | |||
| 154 | input_report_key(ts.input, BTN_TOUCH, 0); | ||
| 155 | input_sync(ts.input); | ||
| 156 | |||
| 157 | writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | static DEFINE_TIMER(touch_timer, touch_timer_fire, 0, 0); | ||
| 162 | |||
| 163 | /** | ||
| 164 | * stylus_irq - touchscreen stylus event interrupt | ||
| 165 | * @irq: The interrupt number | ||
| 166 | * @dev_id: The device ID. | ||
| 167 | * | ||
| 168 | * Called when the IRQ_TC is fired for a pen up or down event. | ||
| 169 | */ | ||
| 170 | static irqreturn_t stylus_irq(int irq, void *dev_id) | ||
| 171 | { | ||
| 172 | unsigned long data0; | ||
| 173 | unsigned long data1; | ||
| 174 | bool down; | ||
| 175 | |||
| 176 | data0 = readl(ts.io + S3C2410_ADCDAT0); | ||
| 177 | data1 = readl(ts.io + S3C2410_ADCDAT1); | ||
| 178 | |||
| 179 | down = get_down(data0, data1); | ||
| 180 | |||
| 181 | /* TODO we should never get an interrupt with down set while | ||
| 182 | * the timer is running, but maybe we ought to verify that the | ||
| 183 | * timer isn't running anyways. */ | ||
| 184 | |||
| 185 | if (down) | ||
| 186 | s3c_adc_start(ts.client, 0, 1 << ts.shift); | ||
| 187 | else | ||
| 188 | dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); | ||
| 189 | |||
| 190 | return IRQ_HANDLED; | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * s3c24xx_ts_conversion - ADC conversion callback | ||
| 195 | * @client: The client that was registered with the ADC core. | ||
| 196 | * @data0: The reading from ADCDAT0. | ||
| 197 | * @data1: The reading from ADCDAT1. | ||
| 198 | * @left: The number of samples left. | ||
| 199 | * | ||
| 200 | * Called when a conversion has finished. | ||
| 201 | */ | ||
| 202 | static void s3c24xx_ts_conversion(struct s3c_adc_client *client, | ||
| 203 | unsigned data0, unsigned data1, | ||
| 204 | unsigned *left) | ||
| 205 | { | ||
| 206 | dev_dbg(ts.dev, "%s: %d,%d\n", __func__, data0, data1); | ||
| 207 | |||
| 208 | ts.xp += data0; | ||
| 209 | ts.yp += data1; | ||
| 210 | |||
| 211 | ts.count++; | ||
| 212 | |||
| 213 | /* From tests, it seems that it is unlikely to get a pen-up | ||
| 214 | * event during the conversion process which means we can | ||
| 215 | * ignore any pen-up events with less than the requisite | ||
| 216 | * count done. | ||
| 217 | * | ||
| 218 | * In several thousand conversions, no pen-ups where detected | ||
| 219 | * before count completed. | ||
| 220 | */ | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 224 | * s3c24xx_ts_select - ADC selection callback. | ||
| 225 | * @client: The client that was registered with the ADC core. | ||
| 226 | * @select: The reason for select. | ||
| 227 | * | ||
| 228 | * Called when the ADC core selects (or deslects) us as a client. | ||
| 229 | */ | ||
| 230 | static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select) | ||
| 231 | { | ||
| 232 | if (select) { | ||
| 233 | writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, | ||
| 234 | ts.io + S3C2410_ADCTSC); | ||
| 235 | } else { | ||
| 236 | mod_timer(&touch_timer, jiffies+1); | ||
| 237 | writel(WAIT4INT | INT_UP, ts.io + S3C2410_ADCTSC); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | |||
| 241 | /** | ||
| 242 | * s3c2410ts_probe - device core probe entry point | ||
| 243 | * @pdev: The device we are being bound to. | ||
| 244 | * | ||
| 245 | * Initialise, find and allocate any resources we need to run and then | ||
| 246 | * register with the ADC and input systems. | ||
| 247 | */ | ||
| 248 | static int __devinit s3c2410ts_probe(struct platform_device *pdev) | ||
| 249 | { | ||
| 250 | struct s3c2410_ts_mach_info *info; | ||
| 251 | struct device *dev = &pdev->dev; | ||
| 252 | struct input_dev *input_dev; | ||
| 253 | struct resource *res; | ||
| 254 | int ret = -EINVAL; | ||
| 255 | |||
| 256 | /* Initialise input stuff */ | ||
| 257 | memset(&ts, 0, sizeof(struct s3c2410ts)); | ||
| 258 | |||
| 259 | ts.dev = dev; | ||
| 260 | |||
| 261 | info = pdev->dev.platform_data; | ||
| 262 | if (!info) { | ||
| 263 | dev_err(dev, "no platform data, cannot attach\n"); | ||
| 264 | return -EINVAL; | ||
| 265 | } | ||
| 266 | |||
| 267 | dev_dbg(dev, "initialising touchscreen\n"); | ||
| 268 | |||
| 269 | ts.clock = clk_get(dev, "adc"); | ||
| 270 | if (IS_ERR(ts.clock)) { | ||
| 271 | dev_err(dev, "cannot get adc clock source\n"); | ||
| 272 | return -ENOENT; | ||
| 273 | } | ||
| 274 | |||
| 275 | clk_enable(ts.clock); | ||
| 276 | dev_dbg(dev, "got and enabled clocks\n"); | ||
| 277 | |||
| 278 | ts.irq_tc = ret = platform_get_irq(pdev, 0); | ||
| 279 | if (ret < 0) { | ||
| 280 | dev_err(dev, "no resource for interrupt\n"); | ||
| 281 | goto err_clk; | ||
| 282 | } | ||
| 283 | |||
| 284 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 285 | if (!res) { | ||
| 286 | dev_err(dev, "no resource for registers\n"); | ||
| 287 | ret = -ENOENT; | ||
| 288 | goto err_clk; | ||
| 289 | } | ||
| 290 | |||
| 291 | ts.io = ioremap(res->start, resource_size(res)); | ||
| 292 | if (ts.io == NULL) { | ||
| 293 | dev_err(dev, "cannot map registers\n"); | ||
| 294 | ret = -ENOMEM; | ||
| 295 | goto err_clk; | ||
| 296 | } | ||
| 297 | |||
| 298 | /* Configure the touchscreen external FETs on the S3C2410 */ | ||
| 299 | if (!platform_get_device_id(pdev)->driver_data) | ||
| 300 | s3c2410_ts_connect(); | ||
| 301 | |||
| 302 | ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, | ||
| 303 | s3c24xx_ts_conversion, 1); | ||
| 304 | if (IS_ERR(ts.client)) { | ||
| 305 | dev_err(dev, "failed to register adc client\n"); | ||
| 306 | ret = PTR_ERR(ts.client); | ||
| 307 | goto err_iomap; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* Initialise registers */ | ||
| 311 | if ((info->delay & 0xffff) > 0) | ||
| 312 | writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); | ||
| 313 | |||
| 314 | writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); | ||
| 315 | |||
| 316 | input_dev = input_allocate_device(); | ||
| 317 | if (!input_dev) { | ||
| 318 | dev_err(dev, "Unable to allocate the input device !!\n"); | ||
| 319 | ret = -ENOMEM; | ||
| 320 | goto err_iomap; | ||
| 321 | } | ||
| 322 | |||
| 323 | ts.input = input_dev; | ||
| 324 | ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 325 | ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 326 | input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0); | ||
| 327 | input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0); | ||
| 328 | |||
| 329 | ts.input->name = "S3C24XX TouchScreen"; | ||
| 330 | ts.input->id.bustype = BUS_HOST; | ||
| 331 | ts.input->id.vendor = 0xDEAD; | ||
| 332 | ts.input->id.product = 0xBEEF; | ||
| 333 | ts.input->id.version = 0x0102; | ||
| 334 | |||
| 335 | ts.shift = info->oversampling_shift; | ||
| 336 | |||
| 337 | ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, | ||
| 338 | "s3c2410_ts_pen", ts.input); | ||
| 339 | if (ret) { | ||
| 340 | dev_err(dev, "cannot get TC interrupt\n"); | ||
| 341 | goto err_inputdev; | ||
| 342 | } | ||
| 343 | |||
| 344 | dev_info(dev, "driver attached, registering input device\n"); | ||
| 345 | |||
| 346 | /* All went ok, so register to the input system */ | ||
| 347 | ret = input_register_device(ts.input); | ||
| 348 | if (ret < 0) { | ||
| 349 | dev_err(dev, "failed to register input device\n"); | ||
| 350 | ret = -EIO; | ||
| 351 | goto err_tcirq; | ||
| 352 | } | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | |||
| 356 | err_tcirq: | ||
| 357 | free_irq(ts.irq_tc, ts.input); | ||
| 358 | err_inputdev: | ||
| 359 | input_unregister_device(ts.input); | ||
| 360 | err_iomap: | ||
| 361 | iounmap(ts.io); | ||
| 362 | err_clk: | ||
| 363 | del_timer_sync(&touch_timer); | ||
| 364 | clk_put(ts.clock); | ||
| 365 | return ret; | ||
| 366 | } | ||
| 367 | |||
| 368 | /** | ||
| 369 | * s3c2410ts_remove - device core removal entry point | ||
| 370 | * @pdev: The device we are being removed from. | ||
| 371 | * | ||
| 372 | * Free up our state ready to be removed. | ||
| 373 | */ | ||
| 374 | static int __devexit s3c2410ts_remove(struct platform_device *pdev) | ||
| 375 | { | ||
| 376 | free_irq(ts.irq_tc, ts.input); | ||
| 377 | del_timer_sync(&touch_timer); | ||
| 378 | |||
| 379 | clk_disable(ts.clock); | ||
| 380 | clk_put(ts.clock); | ||
| 381 | |||
| 382 | input_unregister_device(ts.input); | ||
| 383 | iounmap(ts.io); | ||
| 384 | |||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | #ifdef CONFIG_PM | ||
| 389 | static int s3c2410ts_suspend(struct device *dev) | ||
| 390 | { | ||
| 391 | writel(TSC_SLEEP, ts.io + S3C2410_ADCTSC); | ||
| 392 | disable_irq(ts.irq_tc); | ||
| 393 | clk_disable(ts.clock); | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | |||
| 398 | static int s3c2410ts_resume(struct device *dev) | ||
| 399 | { | ||
| 400 | struct platform_device *pdev = to_platform_device(dev); | ||
| 401 | struct s3c2410_ts_mach_info *info = pdev->dev.platform_data; | ||
| 402 | |||
| 403 | clk_enable(ts.clock); | ||
| 404 | |||
| 405 | /* Initialise registers */ | ||
| 406 | if ((info->delay & 0xffff) > 0) | ||
| 407 | writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); | ||
| 408 | |||
| 409 | writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 414 | static struct dev_pm_ops s3c_ts_pmops = { | ||
| 415 | .suspend = s3c2410ts_suspend, | ||
| 416 | .resume = s3c2410ts_resume, | ||
| 417 | }; | ||
| 418 | #endif | ||
| 419 | |||
| 420 | static struct platform_device_id s3cts_driver_ids[] = { | ||
| 421 | { "s3c2410-ts", 0 }, | ||
| 422 | { "s3c2440-ts", 1 }, | ||
| 423 | { } | ||
| 424 | }; | ||
| 425 | MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); | ||
| 426 | |||
| 427 | static struct platform_driver s3c_ts_driver = { | ||
| 428 | .driver = { | ||
| 429 | .name = "s3c24xx-ts", | ||
| 430 | .owner = THIS_MODULE, | ||
| 431 | #ifdef CONFIG_PM | ||
| 432 | .pm = &s3c_ts_pmops, | ||
| 433 | #endif | ||
| 434 | }, | ||
| 435 | .id_table = s3cts_driver_ids, | ||
| 436 | .probe = s3c2410ts_probe, | ||
| 437 | .remove = __devexit_p(s3c2410ts_remove), | ||
| 438 | }; | ||
| 439 | |||
| 440 | static int __init s3c2410ts_init(void) | ||
| 441 | { | ||
| 442 | return platform_driver_register(&s3c_ts_driver); | ||
| 443 | } | ||
| 444 | |||
| 445 | static void __exit s3c2410ts_exit(void) | ||
| 446 | { | ||
| 447 | platform_driver_unregister(&s3c_ts_driver); | ||
| 448 | } | ||
| 449 | |||
| 450 | module_init(s3c2410ts_init); | ||
| 451 | module_exit(s3c2410ts_exit); | ||
| 452 | |||
| 453 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " | ||
| 454 | "Ben Dooks <ben@simtec.co.uk>, " | ||
| 455 | "Simtec Electronics <linux@simtec.co.uk>"); | ||
| 456 | MODULE_DESCRIPTION("S3C24XX Touchscreen driver"); | ||
| 457 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 095f84b1f56e..89dcbe7b4b02 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -355,10 +355,13 @@ static int ucb1400_ts_probe(struct platform_device *dev) | |||
| 355 | goto err; | 355 | goto err; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | error = ucb1400_ts_detect_irq(ucb); | 358 | /* Only in case the IRQ line wasn't supplied, try detecting it */ |
| 359 | if (error) { | 359 | if (ucb->irq < 0) { |
| 360 | printk(KERN_ERR "UCB1400: IRQ probe failed\n"); | 360 | error = ucb1400_ts_detect_irq(ucb); |
| 361 | goto err_free_devs; | 361 | if (error) { |
| 362 | printk(KERN_ERR "UCB1400: IRQ probe failed\n"); | ||
| 363 | goto err_free_devs; | ||
| 364 | } | ||
| 362 | } | 365 | } |
| 363 | 366 | ||
| 364 | init_waitqueue_head(&ucb->ts_wait); | 367 | init_waitqueue_head(&ucb->ts_wait); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 68ece5801a58..09a5e7341bd5 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | * - General Touch | 14 | * - General Touch |
| 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets | 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
| 16 | * - JASTEC USB touch controller/DigiTech DTR-02U | 16 | * - JASTEC USB touch controller/DigiTech DTR-02U |
| 17 | * - Zytronic capacitive touchscreen | ||
| 17 | * | 18 | * |
| 18 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 19 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
| 19 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 20 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
| @@ -73,6 +74,15 @@ struct usbtouch_device_info { | |||
| 73 | int min_press, max_press; | 74 | int min_press, max_press; |
| 74 | int rept_size; | 75 | int rept_size; |
| 75 | 76 | ||
| 77 | /* | ||
| 78 | * Always service the USB devices irq not just when the input device is | ||
| 79 | * open. This is useful when devices have a watchdog which prevents us | ||
| 80 | * from periodically polling the device. Leave this unset unless your | ||
| 81 | * touchscreen device requires it, as it does consume more of the USB | ||
| 82 | * bandwidth. | ||
| 83 | */ | ||
| 84 | bool irq_always; | ||
| 85 | |||
| 76 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); | 86 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); |
| 77 | 87 | ||
| 78 | /* | 88 | /* |
| @@ -121,6 +131,8 @@ enum { | |||
| 121 | DEVTYPE_GOTOP, | 131 | DEVTYPE_GOTOP, |
| 122 | DEVTYPE_JASTEC, | 132 | DEVTYPE_JASTEC, |
| 123 | DEVTYPE_E2I, | 133 | DEVTYPE_E2I, |
| 134 | DEVTYPE_ZYTRONIC, | ||
| 135 | DEVTYPE_TC5UH, | ||
| 124 | }; | 136 | }; |
| 125 | 137 | ||
| 126 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 138 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
| @@ -201,6 +213,15 @@ static struct usb_device_id usbtouch_devices[] = { | |||
| 201 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | 213 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I |
| 202 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | 214 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, |
| 203 | #endif | 215 | #endif |
| 216 | |||
| 217 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | ||
| 218 | {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, | ||
| 219 | #endif | ||
| 220 | |||
| 221 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | ||
| 222 | {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC5UH}, | ||
| 223 | #endif | ||
| 224 | |||
| 204 | {} | 225 | {} |
| 205 | }; | 226 | }; |
| 206 | 227 | ||
| @@ -538,6 +559,19 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 538 | } | 559 | } |
| 539 | #endif | 560 | #endif |
| 540 | 561 | ||
| 562 | /***************************************************************************** | ||
| 563 | * ET&T TC5UH part | ||
| 564 | */ | ||
| 565 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | ||
| 566 | static int tc5uh_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 567 | { | ||
| 568 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | ||
| 569 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | ||
| 570 | dev->touch = pkt[0] & 0x01; | ||
| 571 | |||
| 572 | return 1; | ||
| 573 | } | ||
| 574 | #endif | ||
| 541 | 575 | ||
| 542 | /***************************************************************************** | 576 | /***************************************************************************** |
| 543 | * IdealTEK URTC1000 Part | 577 | * IdealTEK URTC1000 Part |
| @@ -621,6 +655,39 @@ static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 621 | } | 655 | } |
| 622 | #endif | 656 | #endif |
| 623 | 657 | ||
| 658 | /***************************************************************************** | ||
| 659 | * Zytronic Part | ||
| 660 | */ | ||
| 661 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | ||
| 662 | static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 663 | { | ||
| 664 | switch (pkt[0]) { | ||
| 665 | case 0x3A: /* command response */ | ||
| 666 | dbg("%s: Command response %d", __func__, pkt[1]); | ||
| 667 | break; | ||
| 668 | |||
| 669 | case 0xC0: /* down */ | ||
| 670 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | ||
| 671 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | ||
| 672 | dev->touch = 1; | ||
| 673 | dbg("%s: down %d,%d", __func__, dev->x, dev->y); | ||
| 674 | return 1; | ||
| 675 | |||
| 676 | case 0x80: /* up */ | ||
| 677 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | ||
| 678 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | ||
| 679 | dev->touch = 0; | ||
| 680 | dbg("%s: up %d,%d", __func__, dev->x, dev->y); | ||
| 681 | return 1; | ||
| 682 | |||
| 683 | default: | ||
| 684 | dbg("%s: Unknown return %d", __func__, pkt[0]); | ||
| 685 | break; | ||
| 686 | } | ||
| 687 | |||
| 688 | return 0; | ||
| 689 | } | ||
| 690 | #endif | ||
| 624 | 691 | ||
| 625 | /***************************************************************************** | 692 | /***************************************************************************** |
| 626 | * the different device descriptors | 693 | * the different device descriptors |
| @@ -783,6 +850,29 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 783 | .read_data = e2i_read_data, | 850 | .read_data = e2i_read_data, |
| 784 | }, | 851 | }, |
| 785 | #endif | 852 | #endif |
| 853 | |||
| 854 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | ||
| 855 | [DEVTYPE_ZYTRONIC] = { | ||
| 856 | .min_xc = 0x0, | ||
| 857 | .max_xc = 0x03ff, | ||
| 858 | .min_yc = 0x0, | ||
| 859 | .max_yc = 0x03ff, | ||
| 860 | .rept_size = 5, | ||
| 861 | .read_data = zytronic_read_data, | ||
| 862 | .irq_always = true, | ||
| 863 | }, | ||
| 864 | #endif | ||
| 865 | |||
| 866 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | ||
| 867 | [DEVTYPE_TC5UH] = { | ||
| 868 | .min_xc = 0x0, | ||
| 869 | .max_xc = 0x0fff, | ||
| 870 | .min_yc = 0x0, | ||
| 871 | .max_yc = 0x0fff, | ||
| 872 | .rept_size = 5, | ||
| 873 | .read_data = tc5uh_read_data, | ||
| 874 | }, | ||
| 875 | #endif | ||
| 786 | }; | 876 | }; |
| 787 | 877 | ||
| 788 | 878 | ||
| @@ -933,8 +1023,10 @@ static int usbtouch_open(struct input_dev *input) | |||
| 933 | 1023 | ||
| 934 | usbtouch->irq->dev = usbtouch->udev; | 1024 | usbtouch->irq->dev = usbtouch->udev; |
| 935 | 1025 | ||
| 936 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) | 1026 | if (!usbtouch->type->irq_always) { |
| 937 | return -EIO; | 1027 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) |
| 1028 | return -EIO; | ||
| 1029 | } | ||
| 938 | 1030 | ||
| 939 | return 0; | 1031 | return 0; |
| 940 | } | 1032 | } |
| @@ -943,7 +1035,8 @@ static void usbtouch_close(struct input_dev *input) | |||
| 943 | { | 1035 | { |
| 944 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 1036 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
| 945 | 1037 | ||
| 946 | usb_kill_urb(usbtouch->irq); | 1038 | if (!usbtouch->type->irq_always) |
| 1039 | usb_kill_urb(usbtouch->irq); | ||
| 947 | } | 1040 | } |
| 948 | 1041 | ||
| 949 | 1042 | ||
| @@ -1066,6 +1159,9 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1066 | 1159 | ||
| 1067 | usb_set_intfdata(intf, usbtouch); | 1160 | usb_set_intfdata(intf, usbtouch); |
| 1068 | 1161 | ||
| 1162 | if (usbtouch->type->irq_always) | ||
| 1163 | usb_submit_urb(usbtouch->irq, GFP_KERNEL); | ||
| 1164 | |||
| 1069 | return 0; | 1165 | return 0; |
| 1070 | 1166 | ||
| 1071 | out_free_buffers: | 1167 | out_free_buffers: |
| @@ -1087,7 +1183,7 @@ static void usbtouch_disconnect(struct usb_interface *intf) | |||
| 1087 | 1183 | ||
| 1088 | dbg("%s - usbtouch is initialized, cleaning up", __func__); | 1184 | dbg("%s - usbtouch is initialized, cleaning up", __func__); |
| 1089 | usb_set_intfdata(intf, NULL); | 1185 | usb_set_intfdata(intf, NULL); |
| 1090 | usb_kill_urb(usbtouch->irq); | 1186 | /* this will stop IO via close */ |
| 1091 | input_unregister_device(usbtouch->input); | 1187 | input_unregister_device(usbtouch->input); |
| 1092 | usb_free_urb(usbtouch->irq); | 1188 | usb_free_urb(usbtouch->irq); |
| 1093 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); | 1189 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); |
