diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 23:20:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 23:20:18 -0400 |
commit | 7bfe0e66d5da32961f0060fc5d96b739b1ed64b9 (patch) | |
tree | 6d5dcf77248b574bb0c50930bbf9030aafb99fce /drivers/input/touchscreen | |
parent | 6a76a6992341faab0ef31e7d97000e0cf336d0ba (diff) | |
parent | 10ce3cc919f50c2043b41ca968b43c26a3672600 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov:
"- we finally merged driver for USB version of Synaptics touchpads
(I guess most commonly found in IBM/Lenovo keyboard/touchpad combo);
- a bunch of new drivers for embedded platforms (Cypress
touchscreens, DA9052 OnKey, MAX8997-haptic, Ilitek ILI210x
touchscreens, TI touchscreen);
- input core allows clients to specify desired clock source for
timestamps on input events (EVIOCSCLOCKID ioctl);
- input core allows querying state of all MT slots for given event
code via EVIOCGMTSLOTS ioctl;
- various driver fixes and improvements."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (45 commits)
Input: ili210x - add support for Ilitek ILI210x based touchscreens
Input: altera_ps2 - use of_match_ptr()
Input: synaptics_usb - switch to module_usb_driver()
Input: convert I2C drivers to use module_i2c_driver()
Input: convert SPI drivers to use module_spi_driver()
Input: omap4-keypad - move platform_data to <linux/platform_data>
Input: kxtj9 - who_am_i check value and initial data rate fixes
Input: add driver support for MAX8997-haptic
Input: tegra-kbc - revise device tree support
Input: of_keymap - add device tree bindings for simple key matrices
Input: wacom - fix physical size calculation for 3rd-gen Bamboo
Input: twl4030-vibra - really switch from #if to #ifdef
Input: hp680_ts_input - ensure arguments to request_irq and free_irq are compatible
Input: max8925_onkey - avoid accessing input device too early
Input: max8925_onkey - allow to be used as a wakeup source
Input: atmel-wm97xx - convert to dev_pm_ops
Input: atmel-wm97xx - set driver owner
Input: add cyttsp touchscreen maintainer entry
Input: cyttsp - remove useless checks in cyttsp_probe()
Input: usbtouchscreen - add support for Data Modul EasyTouch TP 72037
...
Diffstat (limited to 'drivers/input/touchscreen')
28 files changed, 2121 insertions, 221 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 4af2a18eb3ba..97b31a0e0525 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -139,7 +139,6 @@ config TOUCHSCREEN_CY8CTMG110 | |||
139 | tristate "cy8ctmg110 touchscreen" | 139 | tristate "cy8ctmg110 touchscreen" |
140 | depends on I2C | 140 | depends on I2C |
141 | depends on GPIOLIB | 141 | depends on GPIOLIB |
142 | |||
143 | help | 142 | help |
144 | Say Y here if you have a cy8ctmg110 capacitive touchscreen on | 143 | Say Y here if you have a cy8ctmg110 capacitive touchscreen on |
145 | an AAVA device. | 144 | an AAVA device. |
@@ -149,6 +148,37 @@ config TOUCHSCREEN_CY8CTMG110 | |||
149 | To compile this driver as a module, choose M here: the | 148 | To compile this driver as a module, choose M here: the |
150 | module will be called cy8ctmg110_ts. | 149 | module will be called cy8ctmg110_ts. |
151 | 150 | ||
151 | config TOUCHSCREEN_CYTTSP_CORE | ||
152 | tristate "Cypress TTSP touchscreen" | ||
153 | help | ||
154 | Say Y here if you have a touchscreen using controller from | ||
155 | the Cypress TrueTouch(tm) Standard Product family connected | ||
156 | to your system. You will also need to select appropriate | ||
157 | bus connection below. | ||
158 | |||
159 | If unsure, say N. | ||
160 | |||
161 | To compile this driver as a module, choose M here: the | ||
162 | module will be called cyttsp_core. | ||
163 | |||
164 | config TOUCHSCREEN_CYTTSP_I2C | ||
165 | tristate "support I2C bus connection" | ||
166 | depends on TOUCHSCREEN_CYTTSP_CORE && I2C | ||
167 | help | ||
168 | Say Y here if the touchscreen is connected via I2C bus. | ||
169 | |||
170 | To compile this driver as a module, choose M here: the | ||
171 | module will be called cyttsp_i2c. | ||
172 | |||
173 | config TOUCHSCREEN_CYTTSP_SPI | ||
174 | tristate "support SPI bus connection" | ||
175 | depends on TOUCHSCREEN_CYTTSP_CORE && SPI_MASTER | ||
176 | help | ||
177 | Say Y here if the touchscreen is connected via SPI bus. | ||
178 | |||
179 | To compile this driver as a module, choose M here: the | ||
180 | module will be called cyttsp_spi. | ||
181 | |||
152 | config TOUCHSCREEN_DA9034 | 182 | config TOUCHSCREEN_DA9034 |
153 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 183 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
154 | depends on PMIC_DA903X | 184 | depends on PMIC_DA903X |
@@ -213,6 +243,21 @@ config TOUCHSCREEN_FUJITSU | |||
213 | To compile this driver as a module, choose M here: the | 243 | To compile this driver as a module, choose M here: the |
214 | module will be called fujitsu-ts. | 244 | module will be called fujitsu-ts. |
215 | 245 | ||
246 | config TOUCHSCREEN_ILI210X | ||
247 | tristate "Ilitek ILI210X based touchscreen" | ||
248 | depends on I2C | ||
249 | help | ||
250 | Say Y here if you have a ILI210X based touchscreen | ||
251 | controller. This driver supports models ILI2102, | ||
252 | ILI2102s, ILI2103, ILI2103s and ILI2105. | ||
253 | Such kind of chipsets can be found in Amazon Kindle Fire | ||
254 | touchscreens. | ||
255 | |||
256 | If unsure, say N. | ||
257 | |||
258 | To compile this driver as a module, choose M here: the | ||
259 | module will be called ili210x. | ||
260 | |||
216 | config TOUCHSCREEN_S3C2410 | 261 | config TOUCHSCREEN_S3C2410 |
217 | tristate "Samsung S3C2410/generic touchscreen input driver" | 262 | tristate "Samsung S3C2410/generic touchscreen input driver" |
218 | depends on ARCH_S3C2410 || SAMSUNG_DEV_TS | 263 | depends on ARCH_S3C2410 || SAMSUNG_DEV_TS |
@@ -430,6 +475,18 @@ config TOUCHSCREEN_TOUCHWIN | |||
430 | To compile this driver as a module, choose M here: the | 475 | To compile this driver as a module, choose M here: the |
431 | module will be called touchwin. | 476 | module will be called touchwin. |
432 | 477 | ||
478 | config TOUCHSCREEN_TI_TSCADC | ||
479 | tristate "TI Touchscreen Interface" | ||
480 | depends on ARCH_OMAP2PLUS | ||
481 | help | ||
482 | Say Y here if you have 4/5/8 wire touchscreen controller | ||
483 | to be connected to the ADC controller on your TI AM335x SoC. | ||
484 | |||
485 | If unsure, say N. | ||
486 | |||
487 | To compile this driver as a module, choose M here: the | ||
488 | module will be called ti_tscadc. | ||
489 | |||
433 | config TOUCHSCREEN_ATMEL_TSADCC | 490 | config TOUCHSCREEN_ATMEL_TSADCC |
434 | tristate "Atmel Touchscreen Interface" | 491 | tristate "Atmel Touchscreen Interface" |
435 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 | 492 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
@@ -577,6 +634,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
577 | - JASTEC USB Touch Controller/DigiTech DTR-02U | 634 | - JASTEC USB Touch Controller/DigiTech DTR-02U |
578 | - Zytronic controllers | 635 | - Zytronic controllers |
579 | - Elo TouchSystems 2700 IntelliTouch | 636 | - Elo TouchSystems 2700 IntelliTouch |
637 | - EasyTouch USB Touch Controller from Data Modul | ||
580 | 638 | ||
581 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 639 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
582 | a usage description and the required user-space stuff. | 640 | a usage description and the required user-space stuff. |
@@ -681,6 +739,14 @@ config TOUCHSCREEN_USB_NEXIO | |||
681 | bool "NEXIO/iNexio device support" if EXPERT | 739 | bool "NEXIO/iNexio device support" if EXPERT |
682 | depends on TOUCHSCREEN_USB_COMPOSITE | 740 | depends on TOUCHSCREEN_USB_COMPOSITE |
683 | 741 | ||
742 | config TOUCHSCREEN_USB_EASYTOUCH | ||
743 | default y | ||
744 | bool "EasyTouch USB Touch controller device support" if EMBEDDED | ||
745 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
746 | help | ||
747 | Say Y here if you have a EasyTouch USB Touch controller device support. | ||
748 | If unsure, say N. | ||
749 | |||
684 | config TOUCHSCREEN_TOUCHIT213 | 750 | config TOUCHSCREEN_TOUCHIT213 |
685 | tristate "Sahara TouchIT-213 touchscreen" | 751 | tristate "Sahara TouchIT-213 touchscreen" |
686 | select SERIO | 752 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 496091e88460..3d5cf8cbf89c 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -16,8 +16,11 @@ obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o | |||
16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 16 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
17 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o |
18 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 18 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
20 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o | 20 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o |
21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | ||
22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o | ||
23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o | ||
21 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o | 24 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o |
22 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 25 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
23 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | 26 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o |
@@ -26,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | |||
26 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 29 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
27 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o | 30 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o |
28 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 31 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
32 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | ||
29 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 33 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
30 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o | 34 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o |
31 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o | 35 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o |
@@ -45,6 +49,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o | |||
45 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 49 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
46 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | 50 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o |
47 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 51 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
52 | obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o | ||
48 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o | 53 | obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o |
49 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 54 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
50 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 55 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 49a36df0b752..2c7692108e6c 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
@@ -860,17 +860,7 @@ static struct spi_driver ad7877_driver = { | |||
860 | .remove = __devexit_p(ad7877_remove), | 860 | .remove = __devexit_p(ad7877_remove), |
861 | }; | 861 | }; |
862 | 862 | ||
863 | static int __init ad7877_init(void) | 863 | module_spi_driver(ad7877_driver); |
864 | { | ||
865 | return spi_register_driver(&ad7877_driver); | ||
866 | } | ||
867 | module_init(ad7877_init); | ||
868 | |||
869 | static void __exit ad7877_exit(void) | ||
870 | { | ||
871 | spi_unregister_driver(&ad7877_driver); | ||
872 | } | ||
873 | module_exit(ad7877_exit); | ||
874 | 864 | ||
875 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 865 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
876 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); | 866 | MODULE_DESCRIPTION("AD7877 touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 0dac6712f42b..3054354d0dd3 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c | |||
@@ -102,17 +102,7 @@ static struct i2c_driver ad7879_i2c_driver = { | |||
102 | .id_table = ad7879_id, | 102 | .id_table = ad7879_id, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static int __init ad7879_i2c_init(void) | 105 | module_i2c_driver(ad7879_i2c_driver); |
106 | { | ||
107 | return i2c_add_driver(&ad7879_i2c_driver); | ||
108 | } | ||
109 | module_init(ad7879_i2c_init); | ||
110 | |||
111 | static void __exit ad7879_i2c_exit(void) | ||
112 | { | ||
113 | i2c_del_driver(&ad7879_i2c_driver); | ||
114 | } | ||
115 | module_exit(ad7879_i2c_exit); | ||
116 | 106 | ||
117 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 107 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
118 | MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); | 108 | MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver"); |
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 9b2e1c2b1971..db49abf056ba 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c | |||
@@ -157,17 +157,7 @@ static struct spi_driver ad7879_spi_driver = { | |||
157 | .remove = __devexit_p(ad7879_spi_remove), | 157 | .remove = __devexit_p(ad7879_spi_remove), |
158 | }; | 158 | }; |
159 | 159 | ||
160 | static int __init ad7879_spi_init(void) | 160 | module_spi_driver(ad7879_spi_driver); |
161 | { | ||
162 | return spi_register_driver(&ad7879_spi_driver); | ||
163 | } | ||
164 | module_init(ad7879_spi_init); | ||
165 | |||
166 | static void __exit ad7879_spi_exit(void) | ||
167 | { | ||
168 | spi_unregister_driver(&ad7879_spi_driver); | ||
169 | } | ||
170 | module_exit(ad7879_spi_exit); | ||
171 | 161 | ||
172 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 162 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
173 | MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); | 163 | MODULE_DESCRIPTION("AD7879(-1) touchscreen SPI bus driver"); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 23fd90185659..f02028ec3db6 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -1433,17 +1433,7 @@ static struct spi_driver ads7846_driver = { | |||
1433 | .remove = __devexit_p(ads7846_remove), | 1433 | .remove = __devexit_p(ads7846_remove), |
1434 | }; | 1434 | }; |
1435 | 1435 | ||
1436 | static int __init ads7846_init(void) | 1436 | module_spi_driver(ads7846_driver); |
1437 | { | ||
1438 | return spi_register_driver(&ads7846_driver); | ||
1439 | } | ||
1440 | module_init(ads7846_init); | ||
1441 | |||
1442 | static void __exit ads7846_exit(void) | ||
1443 | { | ||
1444 | spi_unregister_driver(&ads7846_driver); | ||
1445 | } | ||
1446 | module_exit(ads7846_exit); | ||
1447 | 1437 | ||
1448 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); | 1438 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); |
1449 | MODULE_LICENSE("GPL"); | 1439 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index 8034cbb20f74..c5c2dbb93869 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c | |||
@@ -392,9 +392,10 @@ static int __exit atmel_wm97xx_remove(struct platform_device *pdev) | |||
392 | return 0; | 392 | return 0; |
393 | } | 393 | } |
394 | 394 | ||
395 | #ifdef CONFIG_PM | 395 | #ifdef CONFIG_PM_SLEEP |
396 | static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) | 396 | static int atmel_wm97xx_suspend(struct *dev) |
397 | { | 397 | { |
398 | struct platform_device *pdev = to_platform_device(dev); | ||
398 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | 399 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); |
399 | 400 | ||
400 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); | 401 | ac97c_writel(atmel_wm97xx, IDR, AC97C_INT_CBEVT); |
@@ -404,8 +405,9 @@ static int atmel_wm97xx_suspend(struct platform_device *pdev, pm_message_t msg) | |||
404 | return 0; | 405 | return 0; |
405 | } | 406 | } |
406 | 407 | ||
407 | static int atmel_wm97xx_resume(struct platform_device *pdev) | 408 | static int atmel_wm97xx_resume(struct device *dev) |
408 | { | 409 | { |
410 | struct platform_device *pdev = to_platform_device(dev); | ||
409 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); | 411 | struct atmel_wm97xx *atmel_wm97xx = platform_get_drvdata(pdev); |
410 | struct wm97xx *wm = atmel_wm97xx->wm; | 412 | struct wm97xx *wm = atmel_wm97xx->wm; |
411 | 413 | ||
@@ -416,18 +418,18 @@ static int atmel_wm97xx_resume(struct platform_device *pdev) | |||
416 | 418 | ||
417 | return 0; | 419 | return 0; |
418 | } | 420 | } |
419 | #else | ||
420 | #define atmel_wm97xx_suspend NULL | ||
421 | #define atmel_wm97xx_resume NULL | ||
422 | #endif | 421 | #endif |
423 | 422 | ||
423 | static SIMPLE_DEV_PM_OPS(atmel_wm97xx_pm_ops, | ||
424 | atmel_wm97xx_suspend, atmel_wm97xx_resume); | ||
425 | |||
424 | static struct platform_driver atmel_wm97xx_driver = { | 426 | static struct platform_driver atmel_wm97xx_driver = { |
425 | .remove = __exit_p(atmel_wm97xx_remove), | 427 | .remove = __exit_p(atmel_wm97xx_remove), |
426 | .driver = { | 428 | .driver = { |
427 | .name = "wm97xx-touch", | 429 | .name = "wm97xx-touch", |
430 | .owner = THIS_MODULE, | ||
431 | .pm = &atmel_wm97xx_pm_ops, | ||
428 | }, | 432 | }, |
429 | .suspend = atmel_wm97xx_suspend, | ||
430 | .resume = atmel_wm97xx_resume, | ||
431 | }; | 433 | }; |
432 | 434 | ||
433 | static int __init atmel_wm97xx_init(void) | 435 | static int __init atmel_wm97xx_init(void) |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index a596c2775d1a..19d4ea65ea01 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -1267,18 +1267,7 @@ static struct i2c_driver mxt_driver = { | |||
1267 | .id_table = mxt_id, | 1267 | .id_table = mxt_id, |
1268 | }; | 1268 | }; |
1269 | 1269 | ||
1270 | static int __init mxt_init(void) | 1270 | module_i2c_driver(mxt_driver); |
1271 | { | ||
1272 | return i2c_add_driver(&mxt_driver); | ||
1273 | } | ||
1274 | |||
1275 | static void __exit mxt_exit(void) | ||
1276 | { | ||
1277 | i2c_del_driver(&mxt_driver); | ||
1278 | } | ||
1279 | |||
1280 | module_init(mxt_init); | ||
1281 | module_exit(mxt_exit); | ||
1282 | 1271 | ||
1283 | /* Module information */ | 1272 | /* Module information */ |
1284 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 1273 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 94fb9fbb08a9..c7047b6bb020 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c | |||
@@ -635,17 +635,7 @@ static struct i2c_driver auo_pixcir_driver = { | |||
635 | .id_table = auo_pixcir_idtable, | 635 | .id_table = auo_pixcir_idtable, |
636 | }; | 636 | }; |
637 | 637 | ||
638 | static int __init auo_pixcir_init(void) | 638 | module_i2c_driver(auo_pixcir_driver); |
639 | { | ||
640 | return i2c_add_driver(&auo_pixcir_driver); | ||
641 | } | ||
642 | module_init(auo_pixcir_init); | ||
643 | |||
644 | static void __exit auo_pixcir_exit(void) | ||
645 | { | ||
646 | i2c_del_driver(&auo_pixcir_driver); | ||
647 | } | ||
648 | module_exit(auo_pixcir_exit); | ||
649 | 639 | ||
650 | MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); | 640 | MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver"); |
651 | MODULE_LICENSE("GPL v2"); | 641 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 902c7214e887..f2d03c06c2da 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c | |||
@@ -652,30 +652,7 @@ static struct i2c_driver bu21013_driver = { | |||
652 | .id_table = bu21013_id, | 652 | .id_table = bu21013_id, |
653 | }; | 653 | }; |
654 | 654 | ||
655 | /** | 655 | module_i2c_driver(bu21013_driver); |
656 | * bu21013_init() - initializes the bu21013 touchscreen driver | ||
657 | * | ||
658 | * This function used to initializes the bu21013 | ||
659 | * touchscreen driver and returns integer. | ||
660 | */ | ||
661 | static int __init bu21013_init(void) | ||
662 | { | ||
663 | return i2c_add_driver(&bu21013_driver); | ||
664 | } | ||
665 | |||
666 | /** | ||
667 | * bu21013_exit() - de-initializes the bu21013 touchscreen driver | ||
668 | * | ||
669 | * This function uses to de-initializes the bu21013 | ||
670 | * touchscreen driver and returns none. | ||
671 | */ | ||
672 | static void __exit bu21013_exit(void) | ||
673 | { | ||
674 | i2c_del_driver(&bu21013_driver); | ||
675 | } | ||
676 | |||
677 | module_init(bu21013_init); | ||
678 | module_exit(bu21013_exit); | ||
679 | 656 | ||
680 | MODULE_LICENSE("GPL v2"); | 657 | MODULE_LICENSE("GPL v2"); |
681 | MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); | 658 | MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>"); |
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index d8815c5d54ad..237753ad1031 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
@@ -350,18 +350,7 @@ static struct i2c_driver cy8ctmg110_driver = { | |||
350 | .remove = __devexit_p(cy8ctmg110_remove), | 350 | .remove = __devexit_p(cy8ctmg110_remove), |
351 | }; | 351 | }; |
352 | 352 | ||
353 | static int __init cy8ctmg110_init(void) | 353 | module_i2c_driver(cy8ctmg110_driver); |
354 | { | ||
355 | return i2c_add_driver(&cy8ctmg110_driver); | ||
356 | } | ||
357 | |||
358 | static void __exit cy8ctmg110_exit(void) | ||
359 | { | ||
360 | i2c_del_driver(&cy8ctmg110_driver); | ||
361 | } | ||
362 | |||
363 | module_init(cy8ctmg110_init); | ||
364 | module_exit(cy8ctmg110_exit); | ||
365 | 354 | ||
366 | MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); | 355 | MODULE_AUTHOR("Samuli Konttila <samuli.konttila@aavamobile.com>"); |
367 | MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); | 356 | MODULE_DESCRIPTION("cy8ctmg110 TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c new file mode 100644 index 000000000000..f030d9ec795d --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_core.c | |||
@@ -0,0 +1,625 @@ | |||
1 | /* | ||
2 | * Core Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/delay.h> | ||
31 | #include <linux/input.h> | ||
32 | #include <linux/input/mt.h> | ||
33 | #include <linux/gpio.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/slab.h> | ||
36 | |||
37 | #include "cyttsp_core.h" | ||
38 | |||
39 | /* Bootloader number of command keys */ | ||
40 | #define CY_NUM_BL_KEYS 8 | ||
41 | |||
42 | /* helpers */ | ||
43 | #define GET_NUM_TOUCHES(x) ((x) & 0x0F) | ||
44 | #define IS_LARGE_AREA(x) (((x) & 0x10) >> 4) | ||
45 | #define IS_BAD_PKT(x) ((x) & 0x20) | ||
46 | #define IS_VALID_APP(x) ((x) & 0x01) | ||
47 | #define IS_OPERATIONAL_ERR(x) ((x) & 0x3F) | ||
48 | #define GET_HSTMODE(reg) (((reg) & 0x70) >> 4) | ||
49 | #define GET_BOOTLOADERMODE(reg) (((reg) & 0x10) >> 4) | ||
50 | |||
51 | #define CY_REG_BASE 0x00 | ||
52 | #define CY_REG_ACT_DIST 0x1E | ||
53 | #define CY_REG_ACT_INTRVL 0x1D | ||
54 | #define CY_REG_TCH_TMOUT (CY_REG_ACT_INTRVL + 1) | ||
55 | #define CY_REG_LP_INTRVL (CY_REG_TCH_TMOUT + 1) | ||
56 | #define CY_MAXZ 255 | ||
57 | #define CY_DELAY_DFLT 20 /* ms */ | ||
58 | #define CY_DELAY_MAX 500 | ||
59 | #define CY_ACT_DIST_DFLT 0xF8 | ||
60 | #define CY_HNDSHK_BIT 0x80 | ||
61 | /* device mode bits */ | ||
62 | #define CY_OPERATE_MODE 0x00 | ||
63 | #define CY_SYSINFO_MODE 0x10 | ||
64 | /* power mode select bits */ | ||
65 | #define CY_SOFT_RESET_MODE 0x01 /* return to Bootloader mode */ | ||
66 | #define CY_DEEP_SLEEP_MODE 0x02 | ||
67 | #define CY_LOW_POWER_MODE 0x04 | ||
68 | |||
69 | /* Slots management */ | ||
70 | #define CY_MAX_FINGER 4 | ||
71 | #define CY_MAX_ID 16 | ||
72 | |||
73 | static const u8 bl_command[] = { | ||
74 | 0x00, /* file offset */ | ||
75 | 0xFF, /* command */ | ||
76 | 0xA5, /* exit bootloader command */ | ||
77 | 0, 1, 2, 3, 4, 5, 6, 7 /* default keys */ | ||
78 | }; | ||
79 | |||
80 | static int ttsp_read_block_data(struct cyttsp *ts, u8 command, | ||
81 | u8 length, void *buf) | ||
82 | { | ||
83 | int error; | ||
84 | int tries; | ||
85 | |||
86 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | ||
87 | error = ts->bus_ops->read(ts, command, length, buf); | ||
88 | if (!error) | ||
89 | return 0; | ||
90 | |||
91 | msleep(CY_DELAY_DFLT); | ||
92 | } | ||
93 | |||
94 | return -EIO; | ||
95 | } | ||
96 | |||
97 | static int ttsp_write_block_data(struct cyttsp *ts, u8 command, | ||
98 | u8 length, void *buf) | ||
99 | { | ||
100 | int error; | ||
101 | int tries; | ||
102 | |||
103 | for (tries = 0; tries < CY_NUM_RETRY; tries++) { | ||
104 | error = ts->bus_ops->write(ts, command, length, buf); | ||
105 | if (!error) | ||
106 | return 0; | ||
107 | |||
108 | msleep(CY_DELAY_DFLT); | ||
109 | } | ||
110 | |||
111 | return -EIO; | ||
112 | } | ||
113 | |||
114 | static int ttsp_send_command(struct cyttsp *ts, u8 cmd) | ||
115 | { | ||
116 | return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd); | ||
117 | } | ||
118 | |||
119 | static int cyttsp_load_bl_regs(struct cyttsp *ts) | ||
120 | { | ||
121 | memset(&ts->bl_data, 0, sizeof(ts->bl_data)); | ||
122 | ts->bl_data.bl_status = 0x10; | ||
123 | |||
124 | return ttsp_read_block_data(ts, CY_REG_BASE, | ||
125 | sizeof(ts->bl_data), &ts->bl_data); | ||
126 | } | ||
127 | |||
128 | static int cyttsp_exit_bl_mode(struct cyttsp *ts) | ||
129 | { | ||
130 | int error; | ||
131 | u8 bl_cmd[sizeof(bl_command)]; | ||
132 | |||
133 | memcpy(bl_cmd, bl_command, sizeof(bl_command)); | ||
134 | if (ts->pdata->bl_keys) | ||
135 | memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], | ||
136 | ts->pdata->bl_keys, sizeof(bl_command)); | ||
137 | |||
138 | error = ttsp_write_block_data(ts, CY_REG_BASE, | ||
139 | sizeof(bl_cmd), bl_cmd); | ||
140 | if (error) | ||
141 | return error; | ||
142 | |||
143 | /* wait for TTSP Device to complete the operation */ | ||
144 | msleep(CY_DELAY_DFLT); | ||
145 | |||
146 | error = cyttsp_load_bl_regs(ts); | ||
147 | if (error) | ||
148 | return error; | ||
149 | |||
150 | if (GET_BOOTLOADERMODE(ts->bl_data.bl_status)) | ||
151 | return -EIO; | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int cyttsp_set_operational_mode(struct cyttsp *ts) | ||
157 | { | ||
158 | int error; | ||
159 | |||
160 | error = ttsp_send_command(ts, CY_OPERATE_MODE); | ||
161 | if (error) | ||
162 | return error; | ||
163 | |||
164 | /* wait for TTSP Device to complete switch to Operational mode */ | ||
165 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
166 | sizeof(ts->xy_data), &ts->xy_data); | ||
167 | if (error) | ||
168 | return error; | ||
169 | |||
170 | return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0; | ||
171 | } | ||
172 | |||
173 | static int cyttsp_set_sysinfo_mode(struct cyttsp *ts) | ||
174 | { | ||
175 | int error; | ||
176 | |||
177 | memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data)); | ||
178 | |||
179 | /* switch to sysinfo mode */ | ||
180 | error = ttsp_send_command(ts, CY_SYSINFO_MODE); | ||
181 | if (error) | ||
182 | return error; | ||
183 | |||
184 | /* read sysinfo registers */ | ||
185 | msleep(CY_DELAY_DFLT); | ||
186 | error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data), | ||
187 | &ts->sysinfo_data); | ||
188 | if (error) | ||
189 | return error; | ||
190 | |||
191 | if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl) | ||
192 | return -EIO; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) | ||
198 | { | ||
199 | int retval = 0; | ||
200 | |||
201 | if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT || | ||
202 | ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT || | ||
203 | ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) { | ||
204 | |||
205 | u8 intrvl_ray[] = { | ||
206 | ts->pdata->act_intrvl, | ||
207 | ts->pdata->tch_tmout, | ||
208 | ts->pdata->lp_intrvl | ||
209 | }; | ||
210 | |||
211 | /* set intrvl registers */ | ||
212 | retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL, | ||
213 | sizeof(intrvl_ray), intrvl_ray); | ||
214 | msleep(CY_DELAY_DFLT); | ||
215 | } | ||
216 | |||
217 | return retval; | ||
218 | } | ||
219 | |||
220 | static int cyttsp_soft_reset(struct cyttsp *ts) | ||
221 | { | ||
222 | unsigned long timeout; | ||
223 | int retval; | ||
224 | |||
225 | /* wait for interrupt to set ready completion */ | ||
226 | INIT_COMPLETION(ts->bl_ready); | ||
227 | ts->state = CY_BL_STATE; | ||
228 | |||
229 | enable_irq(ts->irq); | ||
230 | |||
231 | retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE); | ||
232 | if (retval) | ||
233 | goto out; | ||
234 | |||
235 | timeout = wait_for_completion_timeout(&ts->bl_ready, | ||
236 | msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX)); | ||
237 | retval = timeout ? 0 : -EIO; | ||
238 | |||
239 | out: | ||
240 | ts->state = CY_IDLE_STATE; | ||
241 | disable_irq(ts->irq); | ||
242 | return retval; | ||
243 | } | ||
244 | |||
245 | static int cyttsp_act_dist_setup(struct cyttsp *ts) | ||
246 | { | ||
247 | u8 act_dist_setup = ts->pdata->act_dist; | ||
248 | |||
249 | /* Init gesture; active distance setup */ | ||
250 | return ttsp_write_block_data(ts, CY_REG_ACT_DIST, | ||
251 | sizeof(act_dist_setup), &act_dist_setup); | ||
252 | } | ||
253 | |||
254 | static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids) | ||
255 | { | ||
256 | ids[0] = xy_data->touch12_id >> 4; | ||
257 | ids[1] = xy_data->touch12_id & 0xF; | ||
258 | ids[2] = xy_data->touch34_id >> 4; | ||
259 | ids[3] = xy_data->touch34_id & 0xF; | ||
260 | } | ||
261 | |||
262 | static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data, | ||
263 | int idx) | ||
264 | { | ||
265 | switch (idx) { | ||
266 | case 0: | ||
267 | return &xy_data->tch1; | ||
268 | case 1: | ||
269 | return &xy_data->tch2; | ||
270 | case 2: | ||
271 | return &xy_data->tch3; | ||
272 | case 3: | ||
273 | return &xy_data->tch4; | ||
274 | default: | ||
275 | return NULL; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | static void cyttsp_report_tchdata(struct cyttsp *ts) | ||
280 | { | ||
281 | struct cyttsp_xydata *xy_data = &ts->xy_data; | ||
282 | struct input_dev *input = ts->input; | ||
283 | int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat); | ||
284 | const struct cyttsp_tch *tch; | ||
285 | int ids[CY_MAX_ID]; | ||
286 | int i; | ||
287 | DECLARE_BITMAP(used, CY_MAX_ID); | ||
288 | |||
289 | if (IS_LARGE_AREA(xy_data->tt_stat) == 1) { | ||
290 | /* terminate all active tracks */ | ||
291 | num_tch = 0; | ||
292 | dev_dbg(ts->dev, "%s: Large area detected\n", __func__); | ||
293 | } else if (num_tch > CY_MAX_FINGER) { | ||
294 | /* terminate all active tracks */ | ||
295 | num_tch = 0; | ||
296 | dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__); | ||
297 | } else if (IS_BAD_PKT(xy_data->tt_mode)) { | ||
298 | /* terminate all active tracks */ | ||
299 | num_tch = 0; | ||
300 | dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__); | ||
301 | } | ||
302 | |||
303 | cyttsp_extract_track_ids(xy_data, ids); | ||
304 | |||
305 | bitmap_zero(used, CY_MAX_ID); | ||
306 | |||
307 | for (i = 0; i < num_tch; i++) { | ||
308 | tch = cyttsp_get_tch(xy_data, i); | ||
309 | |||
310 | input_mt_slot(input, ids[i]); | ||
311 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | ||
312 | input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x)); | ||
313 | input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y)); | ||
314 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z); | ||
315 | |||
316 | __set_bit(ids[i], used); | ||
317 | } | ||
318 | |||
319 | for (i = 0; i < CY_MAX_ID; i++) { | ||
320 | if (test_bit(i, used)) | ||
321 | continue; | ||
322 | |||
323 | input_mt_slot(input, i); | ||
324 | input_mt_report_slot_state(input, MT_TOOL_FINGER, false); | ||
325 | } | ||
326 | |||
327 | input_sync(input); | ||
328 | } | ||
329 | |||
330 | static irqreturn_t cyttsp_irq(int irq, void *handle) | ||
331 | { | ||
332 | struct cyttsp *ts = handle; | ||
333 | int error; | ||
334 | |||
335 | if (unlikely(ts->state == CY_BL_STATE)) { | ||
336 | complete(&ts->bl_ready); | ||
337 | goto out; | ||
338 | } | ||
339 | |||
340 | /* Get touch data from CYTTSP device */ | ||
341 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
342 | sizeof(struct cyttsp_xydata), &ts->xy_data); | ||
343 | if (error) | ||
344 | goto out; | ||
345 | |||
346 | /* provide flow control handshake */ | ||
347 | if (ts->pdata->use_hndshk) { | ||
348 | error = ttsp_send_command(ts, | ||
349 | ts->xy_data.hst_mode ^ CY_HNDSHK_BIT); | ||
350 | if (error) | ||
351 | goto out; | ||
352 | } | ||
353 | |||
354 | if (unlikely(ts->state == CY_IDLE_STATE)) | ||
355 | goto out; | ||
356 | |||
357 | if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) { | ||
358 | /* | ||
359 | * TTSP device has reset back to bootloader mode. | ||
360 | * Restore to operational mode. | ||
361 | */ | ||
362 | error = cyttsp_exit_bl_mode(ts); | ||
363 | if (error) { | ||
364 | dev_err(ts->dev, | ||
365 | "Could not return to operational mode, err: %d\n", | ||
366 | error); | ||
367 | ts->state = CY_IDLE_STATE; | ||
368 | } | ||
369 | } else { | ||
370 | cyttsp_report_tchdata(ts); | ||
371 | } | ||
372 | |||
373 | out: | ||
374 | return IRQ_HANDLED; | ||
375 | } | ||
376 | |||
377 | static int cyttsp_power_on(struct cyttsp *ts) | ||
378 | { | ||
379 | int error; | ||
380 | |||
381 | error = cyttsp_soft_reset(ts); | ||
382 | if (error) | ||
383 | return error; | ||
384 | |||
385 | error = cyttsp_load_bl_regs(ts); | ||
386 | if (error) | ||
387 | return error; | ||
388 | |||
389 | if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) && | ||
390 | IS_VALID_APP(ts->bl_data.bl_status)) { | ||
391 | error = cyttsp_exit_bl_mode(ts); | ||
392 | if (error) | ||
393 | return error; | ||
394 | } | ||
395 | |||
396 | if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE || | ||
397 | IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) { | ||
398 | return -ENODEV; | ||
399 | } | ||
400 | |||
401 | error = cyttsp_set_sysinfo_mode(ts); | ||
402 | if (error) | ||
403 | return error; | ||
404 | |||
405 | error = cyttsp_set_sysinfo_regs(ts); | ||
406 | if (error) | ||
407 | return error; | ||
408 | |||
409 | error = cyttsp_set_operational_mode(ts); | ||
410 | if (error) | ||
411 | return error; | ||
412 | |||
413 | /* init active distance */ | ||
414 | error = cyttsp_act_dist_setup(ts); | ||
415 | if (error) | ||
416 | return error; | ||
417 | |||
418 | ts->state = CY_ACTIVE_STATE; | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int cyttsp_enable(struct cyttsp *ts) | ||
424 | { | ||
425 | int error; | ||
426 | |||
427 | /* | ||
428 | * The device firmware can wake on an I2C or SPI memory slave | ||
429 | * address match. So just reading a register is sufficient to | ||
430 | * wake up the device. The first read attempt will fail but it | ||
431 | * will wake it up making the second read attempt successful. | ||
432 | */ | ||
433 | error = ttsp_read_block_data(ts, CY_REG_BASE, | ||
434 | sizeof(ts->xy_data), &ts->xy_data); | ||
435 | if (error) | ||
436 | return error; | ||
437 | |||
438 | if (GET_HSTMODE(ts->xy_data.hst_mode)) | ||
439 | return -EIO; | ||
440 | |||
441 | enable_irq(ts->irq); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int cyttsp_disable(struct cyttsp *ts) | ||
447 | { | ||
448 | int error; | ||
449 | |||
450 | error = ttsp_send_command(ts, CY_LOW_POWER_MODE); | ||
451 | if (error) | ||
452 | return error; | ||
453 | |||
454 | disable_irq(ts->irq); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | #ifdef CONFIG_PM_SLEEP | ||
460 | static int cyttsp_suspend(struct device *dev) | ||
461 | { | ||
462 | struct cyttsp *ts = dev_get_drvdata(dev); | ||
463 | int retval = 0; | ||
464 | |||
465 | mutex_lock(&ts->input->mutex); | ||
466 | |||
467 | if (ts->input->users) { | ||
468 | retval = cyttsp_disable(ts); | ||
469 | if (retval == 0) | ||
470 | ts->suspended = true; | ||
471 | } | ||
472 | |||
473 | mutex_unlock(&ts->input->mutex); | ||
474 | |||
475 | return retval; | ||
476 | } | ||
477 | |||
478 | static int cyttsp_resume(struct device *dev) | ||
479 | { | ||
480 | struct cyttsp *ts = dev_get_drvdata(dev); | ||
481 | |||
482 | mutex_lock(&ts->input->mutex); | ||
483 | |||
484 | if (ts->input->users) | ||
485 | cyttsp_enable(ts); | ||
486 | |||
487 | ts->suspended = false; | ||
488 | |||
489 | mutex_unlock(&ts->input->mutex); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | #endif | ||
495 | |||
496 | SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume); | ||
497 | EXPORT_SYMBOL_GPL(cyttsp_pm_ops); | ||
498 | |||
499 | static int cyttsp_open(struct input_dev *dev) | ||
500 | { | ||
501 | struct cyttsp *ts = input_get_drvdata(dev); | ||
502 | int retval = 0; | ||
503 | |||
504 | if (!ts->suspended) | ||
505 | retval = cyttsp_enable(ts); | ||
506 | |||
507 | return retval; | ||
508 | } | ||
509 | |||
510 | static void cyttsp_close(struct input_dev *dev) | ||
511 | { | ||
512 | struct cyttsp *ts = input_get_drvdata(dev); | ||
513 | |||
514 | if (!ts->suspended) | ||
515 | cyttsp_disable(ts); | ||
516 | } | ||
517 | |||
518 | struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | ||
519 | struct device *dev, int irq, size_t xfer_buf_size) | ||
520 | { | ||
521 | const struct cyttsp_platform_data *pdata = dev->platform_data; | ||
522 | struct cyttsp *ts; | ||
523 | struct input_dev *input_dev; | ||
524 | int error; | ||
525 | |||
526 | if (!pdata || !pdata->name || irq <= 0) { | ||
527 | error = -EINVAL; | ||
528 | goto err_out; | ||
529 | } | ||
530 | |||
531 | ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL); | ||
532 | input_dev = input_allocate_device(); | ||
533 | if (!ts || !input_dev) { | ||
534 | error = -ENOMEM; | ||
535 | goto err_free_mem; | ||
536 | } | ||
537 | |||
538 | ts->dev = dev; | ||
539 | ts->input = input_dev; | ||
540 | ts->pdata = dev->platform_data; | ||
541 | ts->bus_ops = bus_ops; | ||
542 | ts->irq = irq; | ||
543 | |||
544 | init_completion(&ts->bl_ready); | ||
545 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); | ||
546 | |||
547 | if (pdata->init) { | ||
548 | error = pdata->init(); | ||
549 | if (error) { | ||
550 | dev_err(ts->dev, "platform init failed, err: %d\n", | ||
551 | error); | ||
552 | goto err_free_mem; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | input_dev->name = pdata->name; | ||
557 | input_dev->phys = ts->phys; | ||
558 | input_dev->id.bustype = bus_ops->bustype; | ||
559 | input_dev->dev.parent = ts->dev; | ||
560 | |||
561 | input_dev->open = cyttsp_open; | ||
562 | input_dev->close = cyttsp_close; | ||
563 | |||
564 | input_set_drvdata(input_dev, ts); | ||
565 | |||
566 | __set_bit(EV_ABS, input_dev->evbit); | ||
567 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
568 | 0, pdata->maxx, 0, 0); | ||
569 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
570 | 0, pdata->maxy, 0, 0); | ||
571 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
572 | 0, CY_MAXZ, 0, 0); | ||
573 | |||
574 | input_mt_init_slots(input_dev, CY_MAX_ID); | ||
575 | |||
576 | error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, | ||
577 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
578 | pdata->name, ts); | ||
579 | if (error) { | ||
580 | dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", | ||
581 | ts->irq, error); | ||
582 | goto err_platform_exit; | ||
583 | } | ||
584 | |||
585 | disable_irq(ts->irq); | ||
586 | |||
587 | error = cyttsp_power_on(ts); | ||
588 | if (error) | ||
589 | goto err_free_irq; | ||
590 | |||
591 | error = input_register_device(input_dev); | ||
592 | if (error) { | ||
593 | dev_err(ts->dev, "failed to register input device: %d\n", | ||
594 | error); | ||
595 | goto err_free_irq; | ||
596 | } | ||
597 | |||
598 | return ts; | ||
599 | |||
600 | err_free_irq: | ||
601 | free_irq(ts->irq, ts); | ||
602 | err_platform_exit: | ||
603 | if (pdata->exit) | ||
604 | pdata->exit(); | ||
605 | err_free_mem: | ||
606 | input_free_device(input_dev); | ||
607 | kfree(ts); | ||
608 | err_out: | ||
609 | return ERR_PTR(error); | ||
610 | } | ||
611 | EXPORT_SYMBOL_GPL(cyttsp_probe); | ||
612 | |||
613 | void cyttsp_remove(struct cyttsp *ts) | ||
614 | { | ||
615 | free_irq(ts->irq, ts); | ||
616 | input_unregister_device(ts->input); | ||
617 | if (ts->pdata->exit) | ||
618 | ts->pdata->exit(); | ||
619 | kfree(ts); | ||
620 | } | ||
621 | EXPORT_SYMBOL_GPL(cyttsp_remove); | ||
622 | |||
623 | MODULE_LICENSE("GPL"); | ||
624 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); | ||
625 | MODULE_AUTHOR("Cypress"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h new file mode 100644 index 000000000000..1aa3c6967e70 --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_core.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * Header file for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | |||
31 | #ifndef __CYTTSP_CORE_H__ | ||
32 | #define __CYTTSP_CORE_H__ | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/module.h> | ||
37 | #include <linux/types.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/input/cyttsp.h> | ||
40 | |||
41 | #define CY_NUM_RETRY 16 /* max number of retries for read ops */ | ||
42 | |||
43 | struct cyttsp_tch { | ||
44 | __be16 x, y; | ||
45 | u8 z; | ||
46 | } __packed; | ||
47 | |||
48 | /* TrueTouch Standard Product Gen3 interface definition */ | ||
49 | struct cyttsp_xydata { | ||
50 | u8 hst_mode; | ||
51 | u8 tt_mode; | ||
52 | u8 tt_stat; | ||
53 | struct cyttsp_tch tch1; | ||
54 | u8 touch12_id; | ||
55 | struct cyttsp_tch tch2; | ||
56 | u8 gest_cnt; | ||
57 | u8 gest_id; | ||
58 | struct cyttsp_tch tch3; | ||
59 | u8 touch34_id; | ||
60 | struct cyttsp_tch tch4; | ||
61 | u8 tt_undef[3]; | ||
62 | u8 act_dist; | ||
63 | u8 tt_reserved; | ||
64 | } __packed; | ||
65 | |||
66 | |||
67 | /* TTSP System Information interface definition */ | ||
68 | struct cyttsp_sysinfo_data { | ||
69 | u8 hst_mode; | ||
70 | u8 mfg_cmd; | ||
71 | u8 mfg_stat; | ||
72 | u8 cid[3]; | ||
73 | u8 tt_undef1; | ||
74 | u8 uid[8]; | ||
75 | u8 bl_verh; | ||
76 | u8 bl_verl; | ||
77 | u8 tts_verh; | ||
78 | u8 tts_verl; | ||
79 | u8 app_idh; | ||
80 | u8 app_idl; | ||
81 | u8 app_verh; | ||
82 | u8 app_verl; | ||
83 | u8 tt_undef[5]; | ||
84 | u8 scn_typ; | ||
85 | u8 act_intrvl; | ||
86 | u8 tch_tmout; | ||
87 | u8 lp_intrvl; | ||
88 | }; | ||
89 | |||
90 | /* TTSP Bootloader Register Map interface definition */ | ||
91 | #define CY_BL_CHKSUM_OK 0x01 | ||
92 | struct cyttsp_bootloader_data { | ||
93 | u8 bl_file; | ||
94 | u8 bl_status; | ||
95 | u8 bl_error; | ||
96 | u8 blver_hi; | ||
97 | u8 blver_lo; | ||
98 | u8 bld_blver_hi; | ||
99 | u8 bld_blver_lo; | ||
100 | u8 ttspver_hi; | ||
101 | u8 ttspver_lo; | ||
102 | u8 appid_hi; | ||
103 | u8 appid_lo; | ||
104 | u8 appver_hi; | ||
105 | u8 appver_lo; | ||
106 | u8 cid_0; | ||
107 | u8 cid_1; | ||
108 | u8 cid_2; | ||
109 | }; | ||
110 | |||
111 | struct cyttsp; | ||
112 | |||
113 | struct cyttsp_bus_ops { | ||
114 | u16 bustype; | ||
115 | int (*write)(struct cyttsp *ts, | ||
116 | u8 addr, u8 length, const void *values); | ||
117 | int (*read)(struct cyttsp *ts, u8 addr, u8 length, void *values); | ||
118 | }; | ||
119 | |||
120 | enum cyttsp_state { | ||
121 | CY_IDLE_STATE, | ||
122 | CY_ACTIVE_STATE, | ||
123 | CY_BL_STATE, | ||
124 | }; | ||
125 | |||
126 | struct cyttsp { | ||
127 | struct device *dev; | ||
128 | int irq; | ||
129 | struct input_dev *input; | ||
130 | char phys[32]; | ||
131 | const struct cyttsp_platform_data *pdata; | ||
132 | const struct cyttsp_bus_ops *bus_ops; | ||
133 | struct cyttsp_bootloader_data bl_data; | ||
134 | struct cyttsp_sysinfo_data sysinfo_data; | ||
135 | struct cyttsp_xydata xy_data; | ||
136 | struct completion bl_ready; | ||
137 | enum cyttsp_state state; | ||
138 | bool suspended; | ||
139 | |||
140 | u8 xfer_buf[] ____cacheline_aligned; | ||
141 | }; | ||
142 | |||
143 | struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | ||
144 | struct device *dev, int irq, size_t xfer_buf_size); | ||
145 | void cyttsp_remove(struct cyttsp *ts); | ||
146 | |||
147 | extern const struct dev_pm_ops cyttsp_pm_ops; | ||
148 | |||
149 | #endif /* __CYTTSP_CORE_H__ */ | ||
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c new file mode 100644 index 000000000000..2af1d0c52bcd --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_i2c.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include "cyttsp_core.h" | ||
31 | |||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/input.h> | ||
34 | |||
35 | #define CY_I2C_DATA_SIZE 128 | ||
36 | |||
37 | static int cyttsp_i2c_read_block_data(struct cyttsp *ts, | ||
38 | u8 addr, u8 length, void *values) | ||
39 | { | ||
40 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
41 | struct i2c_msg msgs[] = { | ||
42 | { | ||
43 | .addr = client->addr, | ||
44 | .flags = 0, | ||
45 | .len = 1, | ||
46 | .buf = &addr, | ||
47 | }, | ||
48 | { | ||
49 | .addr = client->addr, | ||
50 | .flags = I2C_M_RD, | ||
51 | .len = length, | ||
52 | .buf = values, | ||
53 | }, | ||
54 | }; | ||
55 | int retval; | ||
56 | |||
57 | retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
58 | if (retval < 0) | ||
59 | return retval; | ||
60 | |||
61 | return retval != ARRAY_SIZE(msgs) ? -EIO : 0; | ||
62 | } | ||
63 | |||
64 | static int cyttsp_i2c_write_block_data(struct cyttsp *ts, | ||
65 | u8 addr, u8 length, const void *values) | ||
66 | { | ||
67 | struct i2c_client *client = to_i2c_client(ts->dev); | ||
68 | int retval; | ||
69 | |||
70 | ts->xfer_buf[0] = addr; | ||
71 | memcpy(&ts->xfer_buf[1], values, length); | ||
72 | |||
73 | retval = i2c_master_send(client, ts->xfer_buf, length + 1); | ||
74 | |||
75 | return retval < 0 ? retval : 0; | ||
76 | } | ||
77 | |||
78 | static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { | ||
79 | .bustype = BUS_I2C, | ||
80 | .write = cyttsp_i2c_write_block_data, | ||
81 | .read = cyttsp_i2c_read_block_data, | ||
82 | }; | ||
83 | |||
84 | static int __devinit cyttsp_i2c_probe(struct i2c_client *client, | ||
85 | const struct i2c_device_id *id) | ||
86 | { | ||
87 | struct cyttsp *ts; | ||
88 | |||
89 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
90 | dev_err(&client->dev, "I2C functionality not Supported\n"); | ||
91 | return -EIO; | ||
92 | } | ||
93 | |||
94 | ts = cyttsp_probe(&cyttsp_i2c_bus_ops, &client->dev, client->irq, | ||
95 | CY_I2C_DATA_SIZE); | ||
96 | |||
97 | if (IS_ERR(ts)) | ||
98 | return PTR_ERR(ts); | ||
99 | |||
100 | i2c_set_clientdata(client, ts); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int __devexit cyttsp_i2c_remove(struct i2c_client *client) | ||
106 | { | ||
107 | struct cyttsp *ts = i2c_get_clientdata(client); | ||
108 | |||
109 | cyttsp_remove(ts); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static const struct i2c_device_id cyttsp_i2c_id[] = { | ||
115 | { CY_I2C_NAME, 0 }, | ||
116 | { } | ||
117 | }; | ||
118 | MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); | ||
119 | |||
120 | static struct i2c_driver cyttsp_i2c_driver = { | ||
121 | .driver = { | ||
122 | .name = CY_I2C_NAME, | ||
123 | .owner = THIS_MODULE, | ||
124 | .pm = &cyttsp_pm_ops, | ||
125 | }, | ||
126 | .probe = cyttsp_i2c_probe, | ||
127 | .remove = __devexit_p(cyttsp_i2c_remove), | ||
128 | .id_table = cyttsp_i2c_id, | ||
129 | }; | ||
130 | |||
131 | module_i2c_driver(cyttsp_i2c_driver); | ||
132 | |||
133 | MODULE_LICENSE("GPL"); | ||
134 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); | ||
135 | MODULE_AUTHOR("Cypress"); | ||
136 | MODULE_ALIAS("i2c:cyttsp"); | ||
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c new file mode 100644 index 000000000000..9f263410407b --- /dev/null +++ b/drivers/input/touchscreen/cyttsp_spi.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * Source for: | ||
3 | * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. | ||
4 | * For use with Cypress Txx3xx parts. | ||
5 | * Supported parts include: | ||
6 | * CY8CTST341 | ||
7 | * CY8CTMA340 | ||
8 | * | ||
9 | * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2, and only version 2, as published by the | ||
15 | * Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
25 | * | ||
26 | * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com> | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include "cyttsp_core.h" | ||
31 | |||
32 | #include <linux/delay.h> | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/spi/spi.h> | ||
35 | |||
36 | #define CY_SPI_WR_OP 0x00 /* r/~w */ | ||
37 | #define CY_SPI_RD_OP 0x01 | ||
38 | #define CY_SPI_CMD_BYTES 4 | ||
39 | #define CY_SPI_SYNC_BYTE 2 | ||
40 | #define CY_SPI_SYNC_ACK1 0x62 /* from protocol v.2 */ | ||
41 | #define CY_SPI_SYNC_ACK2 0x9D /* from protocol v.2 */ | ||
42 | #define CY_SPI_DATA_SIZE 128 | ||
43 | #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) | ||
44 | #define CY_SPI_BITS_PER_WORD 8 | ||
45 | |||
46 | static int cyttsp_spi_xfer(struct cyttsp *ts, | ||
47 | u8 op, u8 reg, u8 *buf, int length) | ||
48 | { | ||
49 | struct spi_device *spi = to_spi_device(ts->dev); | ||
50 | struct spi_message msg; | ||
51 | struct spi_transfer xfer[2]; | ||
52 | u8 *wr_buf = &ts->xfer_buf[0]; | ||
53 | u8 *rd_buf = &ts->xfer_buf[CY_SPI_DATA_BUF_SIZE]; | ||
54 | int retval; | ||
55 | int i; | ||
56 | |||
57 | if (length > CY_SPI_DATA_SIZE) { | ||
58 | dev_err(ts->dev, "%s: length %d is too big.\n", | ||
59 | __func__, length); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | |||
63 | memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
64 | memset(rd_buf, 0, CY_SPI_DATA_BUF_SIZE); | ||
65 | |||
66 | wr_buf[0] = 0x00; /* header byte 0 */ | ||
67 | wr_buf[1] = 0xFF; /* header byte 1 */ | ||
68 | wr_buf[2] = reg; /* reg index */ | ||
69 | wr_buf[3] = op; /* r/~w */ | ||
70 | if (op == CY_SPI_WR_OP) | ||
71 | memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); | ||
72 | |||
73 | memset(xfer, 0, sizeof(xfer)); | ||
74 | spi_message_init(&msg); | ||
75 | |||
76 | /* | ||
77 | We set both TX and RX buffers because Cypress TTSP | ||
78 | requires full duplex operation. | ||
79 | */ | ||
80 | xfer[0].tx_buf = wr_buf; | ||
81 | xfer[0].rx_buf = rd_buf; | ||
82 | switch (op) { | ||
83 | case CY_SPI_WR_OP: | ||
84 | xfer[0].len = length + CY_SPI_CMD_BYTES; | ||
85 | spi_message_add_tail(&xfer[0], &msg); | ||
86 | break; | ||
87 | |||
88 | case CY_SPI_RD_OP: | ||
89 | xfer[0].len = CY_SPI_CMD_BYTES; | ||
90 | spi_message_add_tail(&xfer[0], &msg); | ||
91 | |||
92 | xfer[1].rx_buf = buf; | ||
93 | xfer[1].len = length; | ||
94 | spi_message_add_tail(&xfer[1], &msg); | ||
95 | break; | ||
96 | |||
97 | default: | ||
98 | dev_err(ts->dev, "%s: bad operation code=%d\n", __func__, op); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | retval = spi_sync(spi, &msg); | ||
103 | if (retval < 0) { | ||
104 | dev_dbg(ts->dev, "%s: spi_sync() error %d, len=%d, op=%d\n", | ||
105 | __func__, retval, xfer[1].len, op); | ||
106 | |||
107 | /* | ||
108 | * do not return here since was a bad ACK sequence | ||
109 | * let the following ACK check handle any errors and | ||
110 | * allow silent retries | ||
111 | */ | ||
112 | } | ||
113 | |||
114 | if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK1 || | ||
115 | rd_buf[CY_SPI_SYNC_BYTE + 1] != CY_SPI_SYNC_ACK2) { | ||
116 | |||
117 | dev_dbg(ts->dev, "%s: operation %d failed\n", __func__, op); | ||
118 | |||
119 | for (i = 0; i < CY_SPI_CMD_BYTES; i++) | ||
120 | dev_dbg(ts->dev, "%s: test rd_buf[%d]:0x%02x\n", | ||
121 | __func__, i, rd_buf[i]); | ||
122 | for (i = 0; i < length; i++) | ||
123 | dev_dbg(ts->dev, "%s: test buf[%d]:0x%02x\n", | ||
124 | __func__, i, buf[i]); | ||
125 | |||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int cyttsp_spi_read_block_data(struct cyttsp *ts, | ||
133 | u8 addr, u8 length, void *data) | ||
134 | { | ||
135 | return cyttsp_spi_xfer(ts, CY_SPI_RD_OP, addr, data, length); | ||
136 | } | ||
137 | |||
138 | static int cyttsp_spi_write_block_data(struct cyttsp *ts, | ||
139 | u8 addr, u8 length, const void *data) | ||
140 | { | ||
141 | return cyttsp_spi_xfer(ts, CY_SPI_WR_OP, addr, (void *)data, length); | ||
142 | } | ||
143 | |||
144 | static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = { | ||
145 | .bustype = BUS_SPI, | ||
146 | .write = cyttsp_spi_write_block_data, | ||
147 | .read = cyttsp_spi_read_block_data, | ||
148 | }; | ||
149 | |||
150 | static int __devinit cyttsp_spi_probe(struct spi_device *spi) | ||
151 | { | ||
152 | struct cyttsp *ts; | ||
153 | int error; | ||
154 | |||
155 | /* Set up SPI*/ | ||
156 | spi->bits_per_word = CY_SPI_BITS_PER_WORD; | ||
157 | spi->mode = SPI_MODE_0; | ||
158 | error = spi_setup(spi); | ||
159 | if (error < 0) { | ||
160 | dev_err(&spi->dev, "%s: SPI setup error %d\n", | ||
161 | __func__, error); | ||
162 | return error; | ||
163 | } | ||
164 | |||
165 | ts = cyttsp_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, | ||
166 | CY_SPI_DATA_BUF_SIZE * 2); | ||
167 | if (IS_ERR(ts)) | ||
168 | return PTR_ERR(ts); | ||
169 | |||
170 | spi_set_drvdata(spi, ts); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int __devexit cyttsp_spi_remove(struct spi_device *spi) | ||
176 | { | ||
177 | struct cyttsp *ts = spi_get_drvdata(spi); | ||
178 | |||
179 | cyttsp_remove(ts); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static struct spi_driver cyttsp_spi_driver = { | ||
185 | .driver = { | ||
186 | .name = CY_SPI_NAME, | ||
187 | .owner = THIS_MODULE, | ||
188 | .pm = &cyttsp_pm_ops, | ||
189 | }, | ||
190 | .probe = cyttsp_spi_probe, | ||
191 | .remove = __devexit_p(cyttsp_spi_remove), | ||
192 | }; | ||
193 | |||
194 | module_spi_driver(cyttsp_spi_driver); | ||
195 | |||
196 | MODULE_ALIAS("spi:cyttsp"); | ||
197 | MODULE_LICENSE("GPL"); | ||
198 | MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); | ||
199 | MODULE_AUTHOR("Cypress"); | ||
200 | MODULE_ALIAS("spi:cyttsp"); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 1df19bb8534a..503c7096ed36 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -320,20 +320,8 @@ static struct i2c_driver eeti_ts_driver = { | |||
320 | .id_table = eeti_ts_id, | 320 | .id_table = eeti_ts_id, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static int __init eeti_ts_init(void) | 323 | module_i2c_driver(eeti_ts_driver); |
324 | { | ||
325 | return i2c_add_driver(&eeti_ts_driver); | ||
326 | } | ||
327 | |||
328 | static void __exit eeti_ts_exit(void) | ||
329 | { | ||
330 | i2c_del_driver(&eeti_ts_driver); | ||
331 | } | ||
332 | 324 | ||
333 | MODULE_DESCRIPTION("EETI Touchscreen driver"); | 325 | MODULE_DESCRIPTION("EETI Touchscreen driver"); |
334 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 326 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
335 | MODULE_LICENSE("GPL"); | 327 | MODULE_LICENSE("GPL"); |
336 | |||
337 | module_init(eeti_ts_init); | ||
338 | module_exit(eeti_ts_exit); | ||
339 | |||
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index eadcc2e83c77..70524dd34f42 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c | |||
@@ -285,18 +285,7 @@ static struct i2c_driver egalax_ts_driver = { | |||
285 | .remove = __devexit_p(egalax_ts_remove), | 285 | .remove = __devexit_p(egalax_ts_remove), |
286 | }; | 286 | }; |
287 | 287 | ||
288 | static int __init egalax_ts_init(void) | 288 | module_i2c_driver(egalax_ts_driver); |
289 | { | ||
290 | return i2c_add_driver(&egalax_ts_driver); | ||
291 | } | ||
292 | |||
293 | static void __exit egalax_ts_exit(void) | ||
294 | { | ||
295 | i2c_del_driver(&egalax_ts_driver); | ||
296 | } | ||
297 | |||
298 | module_init(egalax_ts_init); | ||
299 | module_exit(egalax_ts_exit); | ||
300 | 289 | ||
301 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | 290 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); |
302 | MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller"); | 291 | MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller"); |
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c index 639a6044183d..85cf9bee8018 100644 --- a/drivers/input/touchscreen/hp680_ts_input.c +++ b/drivers/input/touchscreen/hp680_ts_input.c | |||
@@ -93,7 +93,7 @@ static int __init hp680_ts_init(void) | |||
93 | hp680_ts_dev->phys = "hp680_ts/input0"; | 93 | hp680_ts_dev->phys = "hp680_ts/input0"; |
94 | 94 | ||
95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, | 95 | if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, |
96 | 0, MODNAME, 0) < 0) { | 96 | 0, MODNAME, NULL) < 0) { |
97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", | 97 | printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", |
98 | HP680_TS_IRQ); | 98 | HP680_TS_IRQ); |
99 | err = -EBUSY; | 99 | err = -EBUSY; |
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c new file mode 100644 index 000000000000..c0044175a921 --- /dev/null +++ b/drivers/input/touchscreen/ili210x.c | |||
@@ -0,0 +1,360 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/i2c.h> | ||
3 | #include <linux/interrupt.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/input.h> | ||
6 | #include <linux/input/mt.h> | ||
7 | #include <linux/delay.h> | ||
8 | #include <linux/workqueue.h> | ||
9 | #include <linux/input/ili210x.h> | ||
10 | |||
11 | #define MAX_TOUCHES 2 | ||
12 | #define DEFAULT_POLL_PERIOD 20 | ||
13 | |||
14 | /* Touchscreen commands */ | ||
15 | #define REG_TOUCHDATA 0x10 | ||
16 | #define REG_PANEL_INFO 0x20 | ||
17 | #define REG_FIRMWARE_VERSION 0x40 | ||
18 | #define REG_CALIBRATE 0xcc | ||
19 | |||
20 | struct finger { | ||
21 | u8 x_low; | ||
22 | u8 x_high; | ||
23 | u8 y_low; | ||
24 | u8 y_high; | ||
25 | } __packed; | ||
26 | |||
27 | struct touchdata { | ||
28 | u8 status; | ||
29 | struct finger finger[MAX_TOUCHES]; | ||
30 | } __packed; | ||
31 | |||
32 | struct panel_info { | ||
33 | struct finger finger_max; | ||
34 | u8 xchannel_num; | ||
35 | u8 ychannel_num; | ||
36 | } __packed; | ||
37 | |||
38 | struct firmware_version { | ||
39 | u8 id; | ||
40 | u8 major; | ||
41 | u8 minor; | ||
42 | } __packed; | ||
43 | |||
44 | struct ili210x { | ||
45 | struct i2c_client *client; | ||
46 | struct input_dev *input; | ||
47 | bool (*get_pendown_state)(void); | ||
48 | unsigned int poll_period; | ||
49 | struct delayed_work dwork; | ||
50 | }; | ||
51 | |||
52 | static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, | ||
53 | size_t len) | ||
54 | { | ||
55 | struct i2c_msg msg[2] = { | ||
56 | { | ||
57 | .addr = client->addr, | ||
58 | .flags = 0, | ||
59 | .len = 1, | ||
60 | .buf = ®, | ||
61 | }, | ||
62 | { | ||
63 | .addr = client->addr, | ||
64 | .flags = I2C_M_RD, | ||
65 | .len = len, | ||
66 | .buf = buf, | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | if (i2c_transfer(client->adapter, msg, 2) != 2) { | ||
71 | dev_err(&client->dev, "i2c transfer failed\n"); | ||
72 | return -EIO; | ||
73 | } | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static void ili210x_report_events(struct input_dev *input, | ||
79 | const struct touchdata *touchdata) | ||
80 | { | ||
81 | int i; | ||
82 | bool touch; | ||
83 | unsigned int x, y; | ||
84 | const struct finger *finger; | ||
85 | |||
86 | for (i = 0; i < MAX_TOUCHES; i++) { | ||
87 | input_mt_slot(input, i); | ||
88 | |||
89 | finger = &touchdata->finger[i]; | ||
90 | |||
91 | touch = touchdata->status & (1 << i); | ||
92 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
93 | if (touch) { | ||
94 | x = finger->x_low | (finger->x_high << 8); | ||
95 | y = finger->y_low | (finger->y_high << 8); | ||
96 | |||
97 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
98 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | input_mt_report_pointer_emulation(input, false); | ||
103 | input_sync(input); | ||
104 | } | ||
105 | |||
106 | static bool get_pendown_state(const struct ili210x *priv) | ||
107 | { | ||
108 | bool state = false; | ||
109 | |||
110 | if (priv->get_pendown_state) | ||
111 | state = priv->get_pendown_state(); | ||
112 | |||
113 | return state; | ||
114 | } | ||
115 | |||
116 | static void ili210x_work(struct work_struct *work) | ||
117 | { | ||
118 | struct ili210x *priv = container_of(work, struct ili210x, | ||
119 | dwork.work); | ||
120 | struct i2c_client *client = priv->client; | ||
121 | struct touchdata touchdata; | ||
122 | int error; | ||
123 | |||
124 | error = ili210x_read_reg(client, REG_TOUCHDATA, | ||
125 | &touchdata, sizeof(touchdata)); | ||
126 | if (error) { | ||
127 | dev_err(&client->dev, | ||
128 | "Unable to get touchdata, err = %d\n", error); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | ili210x_report_events(priv->input, &touchdata); | ||
133 | |||
134 | if ((touchdata.status & 0xf3) || get_pendown_state(priv)) | ||
135 | schedule_delayed_work(&priv->dwork, | ||
136 | msecs_to_jiffies(priv->poll_period)); | ||
137 | } | ||
138 | |||
139 | static irqreturn_t ili210x_irq(int irq, void *irq_data) | ||
140 | { | ||
141 | struct ili210x *priv = irq_data; | ||
142 | |||
143 | schedule_delayed_work(&priv->dwork, 0); | ||
144 | |||
145 | return IRQ_HANDLED; | ||
146 | } | ||
147 | |||
148 | static ssize_t ili210x_calibrate(struct device *dev, | ||
149 | struct device_attribute *attr, | ||
150 | const char *buf, size_t count) | ||
151 | { | ||
152 | struct i2c_client *client = to_i2c_client(dev); | ||
153 | struct ili210x *priv = i2c_get_clientdata(client); | ||
154 | unsigned long calibrate; | ||
155 | int rc; | ||
156 | u8 cmd = REG_CALIBRATE; | ||
157 | |||
158 | if (kstrtoul(buf, 10, &calibrate)) | ||
159 | return -EINVAL; | ||
160 | |||
161 | if (calibrate > 1) | ||
162 | return -EINVAL; | ||
163 | |||
164 | if (calibrate) { | ||
165 | rc = i2c_master_send(priv->client, &cmd, sizeof(cmd)); | ||
166 | if (rc != sizeof(cmd)) | ||
167 | return -EIO; | ||
168 | } | ||
169 | |||
170 | return count; | ||
171 | } | ||
172 | static DEVICE_ATTR(calibrate, 0644, NULL, ili210x_calibrate); | ||
173 | |||
174 | static struct attribute *ili210x_attributes[] = { | ||
175 | &dev_attr_calibrate.attr, | ||
176 | NULL, | ||
177 | }; | ||
178 | |||
179 | static const struct attribute_group ili210x_attr_group = { | ||
180 | .attrs = ili210x_attributes, | ||
181 | }; | ||
182 | |||
183 | static int __devinit ili210x_i2c_probe(struct i2c_client *client, | ||
184 | const struct i2c_device_id *id) | ||
185 | { | ||
186 | struct device *dev = &client->dev; | ||
187 | const struct ili210x_platform_data *pdata = dev->platform_data; | ||
188 | struct ili210x *priv; | ||
189 | struct input_dev *input; | ||
190 | struct panel_info panel; | ||
191 | struct firmware_version firmware; | ||
192 | int xmax, ymax; | ||
193 | int error; | ||
194 | |||
195 | dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); | ||
196 | |||
197 | if (!pdata) { | ||
198 | dev_err(dev, "No platform data!\n"); | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | |||
202 | if (client->irq <= 0) { | ||
203 | dev_err(dev, "No IRQ!\n"); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | /* Get firmware version */ | ||
208 | error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, | ||
209 | &firmware, sizeof(firmware)); | ||
210 | if (error) { | ||
211 | dev_err(dev, "Failed to get firmware version, err: %d\n", | ||
212 | error); | ||
213 | return error; | ||
214 | } | ||
215 | |||
216 | /* get panel info */ | ||
217 | error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel)); | ||
218 | if (error) { | ||
219 | dev_err(dev, "Failed to get panel informations, err: %d\n", | ||
220 | error); | ||
221 | return error; | ||
222 | } | ||
223 | |||
224 | xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8); | ||
225 | ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8); | ||
226 | |||
227 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
228 | input = input_allocate_device(); | ||
229 | if (!priv || !input) { | ||
230 | error = -ENOMEM; | ||
231 | goto err_free_mem; | ||
232 | } | ||
233 | |||
234 | priv->client = client; | ||
235 | priv->input = input; | ||
236 | priv->get_pendown_state = pdata->get_pendown_state; | ||
237 | priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD; | ||
238 | INIT_DELAYED_WORK(&priv->dwork, ili210x_work); | ||
239 | |||
240 | /* Setup input device */ | ||
241 | input->name = "ILI210x Touchscreen"; | ||
242 | input->id.bustype = BUS_I2C; | ||
243 | input->dev.parent = dev; | ||
244 | |||
245 | __set_bit(EV_SYN, input->evbit); | ||
246 | __set_bit(EV_KEY, input->evbit); | ||
247 | __set_bit(EV_ABS, input->evbit); | ||
248 | __set_bit(BTN_TOUCH, input->keybit); | ||
249 | |||
250 | /* Single touch */ | ||
251 | input_set_abs_params(input, ABS_X, 0, xmax, 0, 0); | ||
252 | input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0); | ||
253 | |||
254 | /* Multi touch */ | ||
255 | input_mt_init_slots(input, MAX_TOUCHES); | ||
256 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0); | ||
257 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0); | ||
258 | |||
259 | input_set_drvdata(input, priv); | ||
260 | i2c_set_clientdata(client, priv); | ||
261 | |||
262 | error = request_irq(client->irq, ili210x_irq, pdata->irq_flags, | ||
263 | client->name, priv); | ||
264 | if (error) { | ||
265 | dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", | ||
266 | error); | ||
267 | goto err_free_mem; | ||
268 | } | ||
269 | |||
270 | error = sysfs_create_group(&dev->kobj, &ili210x_attr_group); | ||
271 | if (error) { | ||
272 | dev_err(dev, "Unable to create sysfs attributes, err: %d\n", | ||
273 | error); | ||
274 | goto err_free_irq; | ||
275 | } | ||
276 | |||
277 | error = input_register_device(priv->input); | ||
278 | if (error) { | ||
279 | dev_err(dev, "Cannot regiser input device, err: %d\n", error); | ||
280 | goto err_remove_sysfs; | ||
281 | } | ||
282 | |||
283 | device_init_wakeup(&client->dev, 1); | ||
284 | |||
285 | dev_dbg(dev, | ||
286 | "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d", | ||
287 | client->irq, firmware.id, firmware.major, firmware.minor); | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | err_remove_sysfs: | ||
292 | sysfs_remove_group(&dev->kobj, &ili210x_attr_group); | ||
293 | err_free_irq: | ||
294 | free_irq(client->irq, priv); | ||
295 | err_free_mem: | ||
296 | input_free_device(input); | ||
297 | kfree(priv); | ||
298 | return error; | ||
299 | } | ||
300 | |||
301 | static int __devexit ili210x_i2c_remove(struct i2c_client *client) | ||
302 | { | ||
303 | struct ili210x *priv = i2c_get_clientdata(client); | ||
304 | |||
305 | sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group); | ||
306 | free_irq(priv->client->irq, priv); | ||
307 | cancel_delayed_work_sync(&priv->dwork); | ||
308 | input_unregister_device(priv->input); | ||
309 | kfree(priv); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | #ifdef CONFIG_PM_SLEEP | ||
315 | static int ili210x_i2c_suspend(struct device *dev) | ||
316 | { | ||
317 | struct i2c_client *client = to_i2c_client(dev); | ||
318 | |||
319 | if (device_may_wakeup(&client->dev)) | ||
320 | enable_irq_wake(client->irq); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int ili210x_i2c_resume(struct device *dev) | ||
326 | { | ||
327 | struct i2c_client *client = to_i2c_client(dev); | ||
328 | |||
329 | if (device_may_wakeup(&client->dev)) | ||
330 | disable_irq_wake(client->irq); | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | #endif | ||
335 | |||
336 | static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, | ||
337 | ili210x_i2c_suspend, ili210x_i2c_resume); | ||
338 | |||
339 | static const struct i2c_device_id ili210x_i2c_id[] = { | ||
340 | { "ili210x", 0 }, | ||
341 | { } | ||
342 | }; | ||
343 | MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); | ||
344 | |||
345 | static struct i2c_driver ili210x_ts_driver = { | ||
346 | .driver = { | ||
347 | .name = "ili210x_i2c", | ||
348 | .owner = THIS_MODULE, | ||
349 | .pm = &ili210x_i2c_pm, | ||
350 | }, | ||
351 | .id_table = ili210x_i2c_id, | ||
352 | .probe = ili210x_i2c_probe, | ||
353 | .remove = __devexit_p(ili210x_i2c_remove), | ||
354 | }; | ||
355 | |||
356 | module_i2c_driver(ili210x_ts_driver); | ||
357 | |||
358 | MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>"); | ||
359 | MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver"); | ||
360 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 4627fe55b401..4eab50b856d7 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c | |||
@@ -255,18 +255,7 @@ static struct i2c_driver max11801_ts_driver = { | |||
255 | .remove = __devexit_p(max11801_ts_remove), | 255 | .remove = __devexit_p(max11801_ts_remove), |
256 | }; | 256 | }; |
257 | 257 | ||
258 | static int __init max11801_ts_init(void) | 258 | module_i2c_driver(max11801_ts_driver); |
259 | { | ||
260 | return i2c_add_driver(&max11801_ts_driver); | ||
261 | } | ||
262 | |||
263 | static void __exit max11801_ts_exit(void) | ||
264 | { | ||
265 | i2c_del_driver(&max11801_ts_driver); | ||
266 | } | ||
267 | |||
268 | module_init(max11801_ts_init); | ||
269 | module_exit(max11801_ts_exit); | ||
270 | 259 | ||
271 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); | 260 | MODULE_AUTHOR("Zhang Jiejing <jiejing.zhang@freescale.com>"); |
272 | MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); | 261 | MODULE_DESCRIPTION("Touchscreen driver for MAXI MAX11801 controller"); |
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 2d84c80ceb66..b528511861ce 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
@@ -302,18 +302,7 @@ static struct i2c_driver mcs5000_ts_driver = { | |||
302 | .id_table = mcs5000_ts_id, | 302 | .id_table = mcs5000_ts_id, |
303 | }; | 303 | }; |
304 | 304 | ||
305 | static int __init mcs5000_ts_init(void) | 305 | module_i2c_driver(mcs5000_ts_driver); |
306 | { | ||
307 | return i2c_add_driver(&mcs5000_ts_driver); | ||
308 | } | ||
309 | |||
310 | static void __exit mcs5000_ts_exit(void) | ||
311 | { | ||
312 | i2c_del_driver(&mcs5000_ts_driver); | ||
313 | } | ||
314 | |||
315 | module_init(mcs5000_ts_init); | ||
316 | module_exit(mcs5000_ts_exit); | ||
317 | 306 | ||
318 | /* Module information */ | 307 | /* Module information */ |
319 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 308 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 5226194aa78e..c038db93e2c3 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
@@ -242,19 +242,8 @@ static struct i2c_driver migor_ts_driver = { | |||
242 | .id_table = migor_ts_id, | 242 | .id_table = migor_ts_id, |
243 | }; | 243 | }; |
244 | 244 | ||
245 | static int __init migor_ts_init(void) | 245 | module_i2c_driver(migor_ts_driver); |
246 | { | ||
247 | return i2c_add_driver(&migor_ts_driver); | ||
248 | } | ||
249 | |||
250 | static void __exit migor_ts_exit(void) | ||
251 | { | ||
252 | i2c_del_driver(&migor_ts_driver); | ||
253 | } | ||
254 | 246 | ||
255 | MODULE_DESCRIPTION("MigoR Touchscreen driver"); | 247 | MODULE_DESCRIPTION("MigoR Touchscreen driver"); |
256 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | 248 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); |
257 | MODULE_LICENSE("GPL"); | 249 | MODULE_LICENSE("GPL"); |
258 | |||
259 | module_init(migor_ts_init); | ||
260 | module_exit(migor_ts_exit); | ||
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index d5ac09a1ee56..72f6ba3a4709 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
@@ -222,17 +222,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = { | |||
222 | .id_table = pixcir_i2c_ts_id, | 222 | .id_table = pixcir_i2c_ts_id, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static int __init pixcir_i2c_ts_init(void) | 225 | module_i2c_driver(pixcir_i2c_ts_driver); |
226 | { | ||
227 | return i2c_add_driver(&pixcir_i2c_ts_driver); | ||
228 | } | ||
229 | module_init(pixcir_i2c_ts_init); | ||
230 | |||
231 | static void __exit pixcir_i2c_ts_exit(void) | ||
232 | { | ||
233 | i2c_del_driver(&pixcir_i2c_ts_driver); | ||
234 | } | ||
235 | module_exit(pixcir_i2c_ts_exit); | ||
236 | 226 | ||
237 | MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>"); | 227 | MODULE_AUTHOR("Jianchun Bian <jcbian@pixcir.com.cn>, Dequan Meng <dqmeng@pixcir.com.cn>"); |
238 | MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); | 228 | MODULE_DESCRIPTION("Pixcir I2C Touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 8825fe37d433..cbbf71b22696 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
@@ -268,17 +268,7 @@ static struct i2c_driver st1232_ts_driver = { | |||
268 | }, | 268 | }, |
269 | }; | 269 | }; |
270 | 270 | ||
271 | static int __init st1232_ts_init(void) | 271 | module_i2c_driver(st1232_ts_driver); |
272 | { | ||
273 | return i2c_add_driver(&st1232_ts_driver); | ||
274 | } | ||
275 | module_init(st1232_ts_init); | ||
276 | |||
277 | static void __exit st1232_ts_exit(void) | ||
278 | { | ||
279 | i2c_del_driver(&st1232_ts_driver); | ||
280 | } | ||
281 | module_exit(st1232_ts_exit); | ||
282 | 272 | ||
283 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); | 273 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); |
284 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); | 274 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); |
diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c new file mode 100644 index 000000000000..d229c741d544 --- /dev/null +++ b/drivers/input/touchscreen/ti_tscadc.c | |||
@@ -0,0 +1,486 @@ | |||
1 | /* | ||
2 | * TI Touch Screen driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/input/ti_tscadc.h> | ||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #define REG_IRQEOI 0x020 | ||
31 | #define REG_RAWIRQSTATUS 0x024 | ||
32 | #define REG_IRQSTATUS 0x028 | ||
33 | #define REG_IRQENABLE 0x02C | ||
34 | #define REG_IRQWAKEUP 0x034 | ||
35 | #define REG_CTRL 0x040 | ||
36 | #define REG_ADCFSM 0x044 | ||
37 | #define REG_CLKDIV 0x04C | ||
38 | #define REG_SE 0x054 | ||
39 | #define REG_IDLECONFIG 0x058 | ||
40 | #define REG_CHARGECONFIG 0x05C | ||
41 | #define REG_CHARGEDELAY 0x060 | ||
42 | #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) | ||
43 | #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) | ||
44 | #define REG_STEPCONFIG13 0x0C4 | ||
45 | #define REG_STEPDELAY13 0x0C8 | ||
46 | #define REG_STEPCONFIG14 0x0CC | ||
47 | #define REG_STEPDELAY14 0x0D0 | ||
48 | #define REG_FIFO0CNT 0xE4 | ||
49 | #define REG_FIFO1THR 0xF4 | ||
50 | #define REG_FIFO0 0x100 | ||
51 | #define REG_FIFO1 0x200 | ||
52 | |||
53 | /* Register Bitfields */ | ||
54 | #define IRQWKUP_ENB BIT(0) | ||
55 | #define STPENB_STEPENB 0x7FFF | ||
56 | #define IRQENB_FIFO1THRES BIT(5) | ||
57 | #define IRQENB_PENUP BIT(9) | ||
58 | #define STEPCONFIG_MODE_HWSYNC 0x2 | ||
59 | #define STEPCONFIG_SAMPLES_AVG (1 << 4) | ||
60 | #define STEPCONFIG_XPP (1 << 5) | ||
61 | #define STEPCONFIG_XNN (1 << 6) | ||
62 | #define STEPCONFIG_YPP (1 << 7) | ||
63 | #define STEPCONFIG_YNN (1 << 8) | ||
64 | #define STEPCONFIG_XNP (1 << 9) | ||
65 | #define STEPCONFIG_YPN (1 << 10) | ||
66 | #define STEPCONFIG_INM (1 << 18) | ||
67 | #define STEPCONFIG_INP (1 << 20) | ||
68 | #define STEPCONFIG_INP_5 (1 << 21) | ||
69 | #define STEPCONFIG_FIFO1 (1 << 26) | ||
70 | #define STEPCONFIG_OPENDLY 0xff | ||
71 | #define STEPCONFIG_Z1 (3 << 19) | ||
72 | #define STEPIDLE_INP (1 << 22) | ||
73 | #define STEPCHARGE_RFP (1 << 12) | ||
74 | #define STEPCHARGE_INM (1 << 15) | ||
75 | #define STEPCHARGE_INP (1 << 19) | ||
76 | #define STEPCHARGE_RFM (1 << 23) | ||
77 | #define STEPCHARGE_DELAY 0x1 | ||
78 | #define CNTRLREG_TSCSSENB (1 << 0) | ||
79 | #define CNTRLREG_STEPID (1 << 1) | ||
80 | #define CNTRLREG_STEPCONFIGWRT (1 << 2) | ||
81 | #define CNTRLREG_4WIRE (1 << 5) | ||
82 | #define CNTRLREG_5WIRE (1 << 6) | ||
83 | #define CNTRLREG_8WIRE (3 << 5) | ||
84 | #define CNTRLREG_TSCENB (1 << 7) | ||
85 | #define ADCFSM_STEPID 0x10 | ||
86 | |||
87 | #define SEQ_SETTLE 275 | ||
88 | #define ADC_CLK 3000000 | ||
89 | #define MAX_12BIT ((1 << 12) - 1) | ||
90 | #define TSCADC_DELTA_X 15 | ||
91 | #define TSCADC_DELTA_Y 15 | ||
92 | |||
93 | struct tscadc { | ||
94 | struct input_dev *input; | ||
95 | struct clk *tsc_ick; | ||
96 | void __iomem *tsc_base; | ||
97 | unsigned int irq; | ||
98 | unsigned int wires; | ||
99 | unsigned int x_plate_resistance; | ||
100 | bool pen_down; | ||
101 | }; | ||
102 | |||
103 | static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg) | ||
104 | { | ||
105 | return readl(ts->tsc_base + reg); | ||
106 | } | ||
107 | |||
108 | static void tscadc_writel(struct tscadc *tsc, unsigned int reg, | ||
109 | unsigned int val) | ||
110 | { | ||
111 | writel(val, tsc->tsc_base + reg); | ||
112 | } | ||
113 | |||
114 | static void tscadc_step_config(struct tscadc *ts_dev) | ||
115 | { | ||
116 | unsigned int config; | ||
117 | int i; | ||
118 | |||
119 | /* Configure the Step registers */ | ||
120 | |||
121 | config = STEPCONFIG_MODE_HWSYNC | | ||
122 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP; | ||
123 | switch (ts_dev->wires) { | ||
124 | case 4: | ||
125 | config |= STEPCONFIG_INP | STEPCONFIG_XNN; | ||
126 | break; | ||
127 | case 5: | ||
128 | config |= STEPCONFIG_YNN | | ||
129 | STEPCONFIG_INP_5 | STEPCONFIG_XNN | | ||
130 | STEPCONFIG_YPP; | ||
131 | break; | ||
132 | case 8: | ||
133 | config |= STEPCONFIG_INP | STEPCONFIG_XNN; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | for (i = 1; i < 7; i++) { | ||
138 | tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
139 | tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
140 | } | ||
141 | |||
142 | config = 0; | ||
143 | config = STEPCONFIG_MODE_HWSYNC | | ||
144 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN | | ||
145 | STEPCONFIG_INM | STEPCONFIG_FIFO1; | ||
146 | switch (ts_dev->wires) { | ||
147 | case 4: | ||
148 | config |= STEPCONFIG_YPP; | ||
149 | break; | ||
150 | case 5: | ||
151 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 | | ||
152 | STEPCONFIG_XNP | STEPCONFIG_YPN; | ||
153 | break; | ||
154 | case 8: | ||
155 | config |= STEPCONFIG_YPP; | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | for (i = 7; i < 13; i++) { | ||
160 | tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); | ||
161 | tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | ||
162 | } | ||
163 | |||
164 | config = 0; | ||
165 | /* Charge step configuration */ | ||
166 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | ||
167 | STEPCHARGE_RFP | STEPCHARGE_RFM | | ||
168 | STEPCHARGE_INM | STEPCHARGE_INP; | ||
169 | |||
170 | tscadc_writel(ts_dev, REG_CHARGECONFIG, config); | ||
171 | tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY); | ||
172 | |||
173 | config = 0; | ||
174 | /* Configure to calculate pressure */ | ||
175 | config = STEPCONFIG_MODE_HWSYNC | | ||
176 | STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP | | ||
177 | STEPCONFIG_XNN | STEPCONFIG_INM; | ||
178 | tscadc_writel(ts_dev, REG_STEPCONFIG13, config); | ||
179 | tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY); | ||
180 | |||
181 | config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1; | ||
182 | tscadc_writel(ts_dev, REG_STEPCONFIG14, config); | ||
183 | tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY); | ||
184 | |||
185 | tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); | ||
186 | } | ||
187 | |||
188 | static void tscadc_idle_config(struct tscadc *ts_config) | ||
189 | { | ||
190 | unsigned int idleconfig; | ||
191 | |||
192 | idleconfig = STEPCONFIG_YNN | | ||
193 | STEPCONFIG_INM | | ||
194 | STEPCONFIG_YPN | STEPIDLE_INP; | ||
195 | tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig); | ||
196 | } | ||
197 | |||
198 | static void tscadc_read_coordinates(struct tscadc *ts_dev, | ||
199 | unsigned int *x, unsigned int *y) | ||
200 | { | ||
201 | unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT); | ||
202 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | ||
203 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | ||
204 | unsigned int read, diff; | ||
205 | unsigned int i; | ||
206 | |||
207 | /* | ||
208 | * Delta filter is used to remove large variations in sampled | ||
209 | * values from ADC. The filter tries to predict where the next | ||
210 | * coordinate could be. This is done by taking a previous | ||
211 | * coordinate and subtracting it form current one. Further the | ||
212 | * algorithm compares the difference with that of a present value, | ||
213 | * if true the value is reported to the sub system. | ||
214 | */ | ||
215 | for (i = 0; i < fifocount - 1; i++) { | ||
216 | read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
217 | diff = abs(read - prev_val_x); | ||
218 | if (diff < prev_diff_x) { | ||
219 | prev_diff_x = diff; | ||
220 | *x = read; | ||
221 | } | ||
222 | prev_val_x = read; | ||
223 | |||
224 | read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
225 | diff = abs(read - prev_val_y); | ||
226 | if (diff < prev_diff_y) { | ||
227 | prev_diff_y = diff; | ||
228 | *y = read; | ||
229 | } | ||
230 | prev_val_y = read; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static irqreturn_t tscadc_irq(int irq, void *dev) | ||
235 | { | ||
236 | struct tscadc *ts_dev = dev; | ||
237 | struct input_dev *input_dev = ts_dev->input; | ||
238 | unsigned int status, irqclr = 0; | ||
239 | unsigned int x = 0, y = 0; | ||
240 | unsigned int z1, z2, z; | ||
241 | unsigned int fsm; | ||
242 | |||
243 | status = tscadc_readl(ts_dev, REG_IRQSTATUS); | ||
244 | if (status & IRQENB_FIFO1THRES) { | ||
245 | tscadc_read_coordinates(ts_dev, &x, &y); | ||
246 | |||
247 | z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; | ||
248 | z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
249 | |||
250 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | ||
251 | /* | ||
252 | * Calculate pressure using formula | ||
253 | * Resistance(touch) = x plate resistance * | ||
254 | * x postion/4096 * ((z2 / z1) - 1) | ||
255 | */ | ||
256 | z = z2 - z1; | ||
257 | z *= x; | ||
258 | z *= ts_dev->x_plate_resistance; | ||
259 | z /= z1; | ||
260 | z = (z + 2047) >> 12; | ||
261 | |||
262 | if (z <= MAX_12BIT) { | ||
263 | input_report_abs(input_dev, ABS_X, x); | ||
264 | input_report_abs(input_dev, ABS_Y, y); | ||
265 | input_report_abs(input_dev, ABS_PRESSURE, z); | ||
266 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
267 | input_sync(input_dev); | ||
268 | } | ||
269 | } | ||
270 | irqclr |= IRQENB_FIFO1THRES; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Time for sequencer to settle, to read | ||
275 | * correct state of the sequencer. | ||
276 | */ | ||
277 | udelay(SEQ_SETTLE); | ||
278 | |||
279 | status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS); | ||
280 | if (status & IRQENB_PENUP) { | ||
281 | /* Pen up event */ | ||
282 | fsm = tscadc_readl(ts_dev, REG_ADCFSM); | ||
283 | if (fsm == ADCFSM_STEPID) { | ||
284 | ts_dev->pen_down = false; | ||
285 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
286 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
287 | input_sync(input_dev); | ||
288 | } else { | ||
289 | ts_dev->pen_down = true; | ||
290 | } | ||
291 | irqclr |= IRQENB_PENUP; | ||
292 | } | ||
293 | |||
294 | tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr); | ||
295 | /* check pending interrupts */ | ||
296 | tscadc_writel(ts_dev, REG_IRQEOI, 0x0); | ||
297 | |||
298 | tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); | ||
299 | return IRQ_HANDLED; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * The functions for inserting/removing driver as a module. | ||
304 | */ | ||
305 | |||
306 | static int __devinit tscadc_probe(struct platform_device *pdev) | ||
307 | { | ||
308 | const struct tsc_data *pdata = pdev->dev.platform_data; | ||
309 | struct resource *res; | ||
310 | struct tscadc *ts_dev; | ||
311 | struct input_dev *input_dev; | ||
312 | struct clk *clk; | ||
313 | int err; | ||
314 | int clk_value, ctrl, irq; | ||
315 | |||
316 | if (!pdata) { | ||
317 | dev_err(&pdev->dev, "missing platform data.\n"); | ||
318 | return -EINVAL; | ||
319 | } | ||
320 | |||
321 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
322 | if (!res) { | ||
323 | dev_err(&pdev->dev, "no memory resource defined.\n"); | ||
324 | return -EINVAL; | ||
325 | } | ||
326 | |||
327 | irq = platform_get_irq(pdev, 0); | ||
328 | if (irq < 0) { | ||
329 | dev_err(&pdev->dev, "no irq ID is specified.\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
333 | /* Allocate memory for device */ | ||
334 | ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL); | ||
335 | input_dev = input_allocate_device(); | ||
336 | if (!ts_dev || !input_dev) { | ||
337 | dev_err(&pdev->dev, "failed to allocate memory.\n"); | ||
338 | err = -ENOMEM; | ||
339 | goto err_free_mem; | ||
340 | } | ||
341 | |||
342 | ts_dev->input = input_dev; | ||
343 | ts_dev->irq = irq; | ||
344 | ts_dev->wires = pdata->wires; | ||
345 | ts_dev->x_plate_resistance = pdata->x_plate_resistance; | ||
346 | |||
347 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
348 | if (!res) { | ||
349 | dev_err(&pdev->dev, "failed to reserve registers.\n"); | ||
350 | err = -EBUSY; | ||
351 | goto err_free_mem; | ||
352 | } | ||
353 | |||
354 | ts_dev->tsc_base = ioremap(res->start, resource_size(res)); | ||
355 | if (!ts_dev->tsc_base) { | ||
356 | dev_err(&pdev->dev, "failed to map registers.\n"); | ||
357 | err = -ENOMEM; | ||
358 | goto err_release_mem_region; | ||
359 | } | ||
360 | |||
361 | err = request_irq(ts_dev->irq, tscadc_irq, | ||
362 | 0, pdev->dev.driver->name, ts_dev); | ||
363 | if (err) { | ||
364 | dev_err(&pdev->dev, "failed to allocate irq.\n"); | ||
365 | goto err_unmap_regs; | ||
366 | } | ||
367 | |||
368 | ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick"); | ||
369 | if (IS_ERR(ts_dev->tsc_ick)) { | ||
370 | dev_err(&pdev->dev, "failed to get TSC ick\n"); | ||
371 | goto err_free_irq; | ||
372 | } | ||
373 | clk_enable(ts_dev->tsc_ick); | ||
374 | |||
375 | clk = clk_get(&pdev->dev, "adc_tsc_fck"); | ||
376 | if (IS_ERR(clk)) { | ||
377 | dev_err(&pdev->dev, "failed to get TSC fck\n"); | ||
378 | err = PTR_ERR(clk); | ||
379 | goto err_disable_clk; | ||
380 | } | ||
381 | |||
382 | clk_value = clk_get_rate(clk) / ADC_CLK; | ||
383 | clk_put(clk); | ||
384 | |||
385 | if (clk_value < 7) { | ||
386 | dev_err(&pdev->dev, "clock input less than min clock requirement\n"); | ||
387 | goto err_disable_clk; | ||
388 | } | ||
389 | /* CLKDIV needs to be configured to the value minus 1 */ | ||
390 | tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1); | ||
391 | |||
392 | /* Enable wake-up of the SoC using touchscreen */ | ||
393 | tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); | ||
394 | |||
395 | ctrl = CNTRLREG_STEPCONFIGWRT | | ||
396 | CNTRLREG_TSCENB | | ||
397 | CNTRLREG_STEPID; | ||
398 | switch (ts_dev->wires) { | ||
399 | case 4: | ||
400 | ctrl |= CNTRLREG_4WIRE; | ||
401 | break; | ||
402 | case 5: | ||
403 | ctrl |= CNTRLREG_5WIRE; | ||
404 | break; | ||
405 | case 8: | ||
406 | ctrl |= CNTRLREG_8WIRE; | ||
407 | break; | ||
408 | } | ||
409 | tscadc_writel(ts_dev, REG_CTRL, ctrl); | ||
410 | |||
411 | tscadc_idle_config(ts_dev); | ||
412 | tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); | ||
413 | tscadc_step_config(ts_dev); | ||
414 | tscadc_writel(ts_dev, REG_FIFO1THR, 6); | ||
415 | |||
416 | ctrl |= CNTRLREG_TSCSSENB; | ||
417 | tscadc_writel(ts_dev, REG_CTRL, ctrl); | ||
418 | |||
419 | input_dev->name = "ti-tsc-adc"; | ||
420 | input_dev->dev.parent = &pdev->dev; | ||
421 | |||
422 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
423 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
424 | |||
425 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | ||
426 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
427 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | ||
428 | |||
429 | /* register to the input system */ | ||
430 | err = input_register_device(input_dev); | ||
431 | if (err) | ||
432 | goto err_disable_clk; | ||
433 | |||
434 | platform_set_drvdata(pdev, ts_dev); | ||
435 | return 0; | ||
436 | |||
437 | err_disable_clk: | ||
438 | clk_disable(ts_dev->tsc_ick); | ||
439 | clk_put(ts_dev->tsc_ick); | ||
440 | err_free_irq: | ||
441 | free_irq(ts_dev->irq, ts_dev); | ||
442 | err_unmap_regs: | ||
443 | iounmap(ts_dev->tsc_base); | ||
444 | err_release_mem_region: | ||
445 | release_mem_region(res->start, resource_size(res)); | ||
446 | err_free_mem: | ||
447 | input_free_device(input_dev); | ||
448 | kfree(ts_dev); | ||
449 | return err; | ||
450 | } | ||
451 | |||
452 | static int __devexit tscadc_remove(struct platform_device *pdev) | ||
453 | { | ||
454 | struct tscadc *ts_dev = platform_get_drvdata(pdev); | ||
455 | struct resource *res; | ||
456 | |||
457 | free_irq(ts_dev->irq, ts_dev); | ||
458 | |||
459 | input_unregister_device(ts_dev->input); | ||
460 | |||
461 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
462 | iounmap(ts_dev->tsc_base); | ||
463 | release_mem_region(res->start, resource_size(res)); | ||
464 | |||
465 | clk_disable(ts_dev->tsc_ick); | ||
466 | clk_put(ts_dev->tsc_ick); | ||
467 | |||
468 | kfree(ts_dev); | ||
469 | |||
470 | platform_set_drvdata(pdev, NULL); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static struct platform_driver ti_tsc_driver = { | ||
475 | .probe = tscadc_probe, | ||
476 | .remove = __devexit_p(tscadc_remove), | ||
477 | .driver = { | ||
478 | .name = "tsc", | ||
479 | .owner = THIS_MODULE, | ||
480 | }, | ||
481 | }; | ||
482 | module_platform_driver(ti_tsc_driver); | ||
483 | |||
484 | MODULE_DESCRIPTION("TI touchscreen controller driver"); | ||
485 | MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); | ||
486 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 067d95662997..b6adeaee9cc5 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
@@ -747,17 +747,7 @@ static struct spi_driver tsc2005_driver = { | |||
747 | .remove = __devexit_p(tsc2005_remove), | 747 | .remove = __devexit_p(tsc2005_remove), |
748 | }; | 748 | }; |
749 | 749 | ||
750 | static int __init tsc2005_init(void) | 750 | module_spi_driver(tsc2005_driver); |
751 | { | ||
752 | return spi_register_driver(&tsc2005_driver); | ||
753 | } | ||
754 | module_init(tsc2005_init); | ||
755 | |||
756 | static void __exit tsc2005_exit(void) | ||
757 | { | ||
758 | spi_unregister_driver(&tsc2005_driver); | ||
759 | } | ||
760 | module_exit(tsc2005_exit); | ||
761 | 751 | ||
762 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); | 752 | MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); |
763 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); | 753 | MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 1f674cb6c55b..1473d2382afd 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -399,18 +399,7 @@ static struct i2c_driver tsc2007_driver = { | |||
399 | .remove = __devexit_p(tsc2007_remove), | 399 | .remove = __devexit_p(tsc2007_remove), |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static int __init tsc2007_init(void) | 402 | module_i2c_driver(tsc2007_driver); |
403 | { | ||
404 | return i2c_add_driver(&tsc2007_driver); | ||
405 | } | ||
406 | |||
407 | static void __exit tsc2007_exit(void) | ||
408 | { | ||
409 | i2c_del_driver(&tsc2007_driver); | ||
410 | } | ||
411 | |||
412 | module_init(tsc2007_init); | ||
413 | module_exit(tsc2007_exit); | ||
414 | 403 | ||
415 | MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>"); | 404 | MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>"); |
416 | MODULE_DESCRIPTION("TSC2007 TouchScreen Driver"); | 405 | MODULE_DESCRIPTION("TSC2007 TouchScreen Driver"); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 3a5ebf452e81..22cd96f58c99 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * - Zytronic capacitive touchscreen | 17 | * - Zytronic capacitive touchscreen |
18 | * - NEXIO/iNexio | 18 | * - NEXIO/iNexio |
19 | * - Elo TouchSystems 2700 IntelliTouch | 19 | * - Elo TouchSystems 2700 IntelliTouch |
20 | * - EasyTouch USB Dual/Multi touch controller from Data Modul | ||
20 | * | 21 | * |
21 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 22 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
22 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 23 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -140,6 +141,7 @@ enum { | |||
140 | DEVTYPE_TC45USB, | 141 | DEVTYPE_TC45USB, |
141 | DEVTYPE_NEXIO, | 142 | DEVTYPE_NEXIO, |
142 | DEVTYPE_ELO, | 143 | DEVTYPE_ELO, |
144 | DEVTYPE_ETOUCH, | ||
143 | }; | 145 | }; |
144 | 146 | ||
145 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 147 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
@@ -245,6 +247,10 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
245 | {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, | 247 | {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, |
246 | #endif | 248 | #endif |
247 | 249 | ||
250 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
251 | {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, | ||
252 | #endif | ||
253 | |||
248 | {} | 254 | {} |
249 | }; | 255 | }; |
250 | 256 | ||
@@ -326,6 +332,51 @@ static int egalax_get_pkt_len(unsigned char *buf, int len) | |||
326 | } | 332 | } |
327 | #endif | 333 | #endif |
328 | 334 | ||
335 | /***************************************************************************** | ||
336 | * EasyTouch part | ||
337 | */ | ||
338 | |||
339 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
340 | |||
341 | #ifndef MULTI_PACKET | ||
342 | #define MULTI_PACKET | ||
343 | #endif | ||
344 | |||
345 | #define ETOUCH_PKT_TYPE_MASK 0xFE | ||
346 | #define ETOUCH_PKT_TYPE_REPT 0x80 | ||
347 | #define ETOUCH_PKT_TYPE_REPT2 0xB0 | ||
348 | #define ETOUCH_PKT_TYPE_DIAG 0x0A | ||
349 | |||
350 | static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
351 | { | ||
352 | if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT && | ||
353 | (pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2) | ||
354 | return 0; | ||
355 | |||
356 | dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F); | ||
357 | dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F); | ||
358 | dev->touch = pkt[0] & 0x01; | ||
359 | |||
360 | return 1; | ||
361 | } | ||
362 | |||
363 | static int etouch_get_pkt_len(unsigned char *buf, int len) | ||
364 | { | ||
365 | switch (buf[0] & ETOUCH_PKT_TYPE_MASK) { | ||
366 | case ETOUCH_PKT_TYPE_REPT: | ||
367 | case ETOUCH_PKT_TYPE_REPT2: | ||
368 | return 5; | ||
369 | |||
370 | case ETOUCH_PKT_TYPE_DIAG: | ||
371 | if (len < 2) | ||
372 | return -1; | ||
373 | |||
374 | return buf[1] + 2; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | #endif | ||
329 | 380 | ||
330 | /***************************************************************************** | 381 | /***************************************************************************** |
331 | * PanJit Part | 382 | * PanJit Part |
@@ -1175,6 +1226,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
1175 | .exit = nexio_exit, | 1226 | .exit = nexio_exit, |
1176 | }, | 1227 | }, |
1177 | #endif | 1228 | #endif |
1229 | #ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH | ||
1230 | [DEVTYPE_ETOUCH] = { | ||
1231 | .min_xc = 0x0, | ||
1232 | .max_xc = 0x07ff, | ||
1233 | .min_yc = 0x0, | ||
1234 | .max_yc = 0x07ff, | ||
1235 | .rept_size = 16, | ||
1236 | .process_pkt = usbtouch_process_multi, | ||
1237 | .get_pkt_len = etouch_get_pkt_len, | ||
1238 | .read_data = etouch_read_data, | ||
1239 | }, | ||
1240 | #endif | ||
1178 | }; | 1241 | }; |
1179 | 1242 | ||
1180 | 1243 | ||