diff options
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); |