diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 13:06:02 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 13:06:02 -0500 |
| commit | d797da41b2aceed5daa8cd2eee92cd74b2a0c652 (patch) | |
| tree | f4de7daf5a81f425c057dd5a65a0e1b8056de5a9 /drivers/input/touchscreen | |
| parent | d6666be6f0c43efb9475d1d35fbef9f8be61b7b1 (diff) | |
| parent | f20c86cd75f1c8c728dafd0218645ff3c5e8545d (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov:
"Two new drivers for Elan hardware (for I2C touchpad and touchscreen
found in several Chromebooks and other devices), a driver for Goodix
touch panel, and small fixes to Cypress I2C trackpad and other input
drivers.
Also we switched to use __maybe_unused instead of gating suspend/
resume code with #ifdef guards to get better compile coverage"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (27 commits)
Input: gpio_keys - fix warning regarding uninitialized 'button' variable
Input: add support for Elan eKTH I2C touchscreens
Input: gpio_keys - fix warning regarding uninitialized 'irq' variable
Input: cyapa - use 'error' for error codes
Input: cyapa - fix resuming the device
Input: gpio_keys - add device tree support for interrupt only keys
Input: amikbd - allocate temporary keymap buffer on the stack
Input: amikbd - fix build if !CONFIG_HW_CONSOLE
Input: lm8323 - missing error check in lm8323_set_disable()
Input: initialize device counter variables with -1
Input: initialize input_no to -1 to avoid subtraction
Input: i8042 - do not try to load on Intel NUC D54250WYK
Input: atkbd - correct MSC_SCAN events for force_release keys
Input: cyapa - switch to using managed resources
Input: lifebook - use "static inline" instead of "inline" in lifebook.h
Input: touchscreen - use __maybe_unused instead of ifdef around suspend/resume
Input: mouse - use __maybe_unused instead of ifdef around suspend/resume
Input: misc - use __maybe_unused instead of ifdef around suspend/resume
Input: cap11xx - support for irq-active-high option
Input: cap11xx - add support for various cap11xx devices
...
Diffstat (limited to 'drivers/input/touchscreen')
23 files changed, 1731 insertions, 78 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index e1d8003d01f8..58917525126e 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -295,6 +295,19 @@ config TOUCHSCREEN_FUJITSU | |||
| 295 | To compile this driver as a module, choose M here: the | 295 | To compile this driver as a module, choose M here: the |
| 296 | module will be called fujitsu-ts. | 296 | module will be called fujitsu-ts. |
| 297 | 297 | ||
| 298 | config TOUCHSCREEN_GOODIX | ||
| 299 | tristate "Goodix I2C touchscreen" | ||
| 300 | depends on I2C && ACPI | ||
| 301 | help | ||
| 302 | Say Y here if you have the Goodix touchscreen (such as one | ||
| 303 | installed in Onda v975w tablets) connected to your | ||
| 304 | system. | ||
| 305 | |||
| 306 | If unsure, say N. | ||
| 307 | |||
| 308 | To compile this driver as a module, choose M here: the | ||
| 309 | module will be called goodix. | ||
| 310 | |||
| 298 | config TOUCHSCREEN_ILI210X | 311 | config TOUCHSCREEN_ILI210X |
| 299 | tristate "Ilitek ILI210X based touchscreen" | 312 | tristate "Ilitek ILI210X based touchscreen" |
| 300 | depends on I2C | 313 | depends on I2C |
| @@ -334,6 +347,18 @@ config TOUCHSCREEN_GUNZE | |||
| 334 | To compile this driver as a module, choose M here: the | 347 | To compile this driver as a module, choose M here: the |
| 335 | module will be called gunze. | 348 | module will be called gunze. |
| 336 | 349 | ||
| 350 | config TOUCHSCREEN_ELAN | ||
| 351 | tristate "Elan eKTH I2C touchscreen" | ||
| 352 | depends on I2C | ||
| 353 | help | ||
| 354 | Say Y here if you have an Elan eKTH I2C touchscreen | ||
| 355 | connected to your system. | ||
| 356 | |||
| 357 | If unsure, say N. | ||
| 358 | |||
| 359 | To compile this driver as a module, choose M here: the | ||
| 360 | module will be called elants_i2c. | ||
| 361 | |||
| 337 | config TOUCHSCREEN_ELO | 362 | config TOUCHSCREEN_ELO |
| 338 | tristate "Elo serial touchscreens" | 363 | tristate "Elo serial touchscreens" |
| 339 | select SERIO | 364 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 090e61cc9171..0242fea2102a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -31,9 +31,11 @@ obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o | |||
| 31 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | 31 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o |
| 32 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 32 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 33 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 33 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
| 34 | obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o | ||
| 34 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 35 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
| 35 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o | 36 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o |
| 36 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 37 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
| 38 | obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o | ||
| 37 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | 39 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o |
| 38 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 40 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
| 39 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o | 41 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 523865daa1d3..da4e5bb5e045 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
| @@ -820,8 +820,7 @@ static int ad7877_remove(struct spi_device *spi) | |||
| 820 | return 0; | 820 | return 0; |
| 821 | } | 821 | } |
| 822 | 822 | ||
| 823 | #ifdef CONFIG_PM_SLEEP | 823 | static int __maybe_unused ad7877_suspend(struct device *dev) |
| 824 | static int ad7877_suspend(struct device *dev) | ||
| 825 | { | 824 | { |
| 826 | struct ad7877 *ts = dev_get_drvdata(dev); | 825 | struct ad7877 *ts = dev_get_drvdata(dev); |
| 827 | 826 | ||
| @@ -830,7 +829,7 @@ static int ad7877_suspend(struct device *dev) | |||
| 830 | return 0; | 829 | return 0; |
| 831 | } | 830 | } |
| 832 | 831 | ||
| 833 | static int ad7877_resume(struct device *dev) | 832 | static int __maybe_unused ad7877_resume(struct device *dev) |
| 834 | { | 833 | { |
| 835 | struct ad7877 *ts = dev_get_drvdata(dev); | 834 | struct ad7877 *ts = dev_get_drvdata(dev); |
| 836 | 835 | ||
| @@ -838,7 +837,6 @@ static int ad7877_resume(struct device *dev) | |||
| 838 | 837 | ||
| 839 | return 0; | 838 | return 0; |
| 840 | } | 839 | } |
| 841 | #endif | ||
| 842 | 840 | ||
| 843 | static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume); | 841 | static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume); |
| 844 | 842 | ||
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 1eb9d3c20886..fec66ad80513 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
| @@ -284,8 +284,7 @@ static void ad7879_close(struct input_dev* input) | |||
| 284 | __ad7879_disable(ts); | 284 | __ad7879_disable(ts); |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | #ifdef CONFIG_PM_SLEEP | 287 | static int __maybe_unused ad7879_suspend(struct device *dev) |
| 288 | static int ad7879_suspend(struct device *dev) | ||
| 289 | { | 288 | { |
| 290 | struct ad7879 *ts = dev_get_drvdata(dev); | 289 | struct ad7879 *ts = dev_get_drvdata(dev); |
| 291 | 290 | ||
| @@ -301,7 +300,7 @@ static int ad7879_suspend(struct device *dev) | |||
| 301 | return 0; | 300 | return 0; |
| 302 | } | 301 | } |
| 303 | 302 | ||
| 304 | static int ad7879_resume(struct device *dev) | 303 | static int __maybe_unused ad7879_resume(struct device *dev) |
| 305 | { | 304 | { |
| 306 | struct ad7879 *ts = dev_get_drvdata(dev); | 305 | struct ad7879 *ts = dev_get_drvdata(dev); |
| 307 | 306 | ||
| @@ -316,7 +315,6 @@ static int ad7879_resume(struct device *dev) | |||
| 316 | 315 | ||
| 317 | return 0; | 316 | return 0; |
| 318 | } | 317 | } |
| 319 | #endif | ||
| 320 | 318 | ||
| 321 | SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume); | 319 | SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume); |
| 322 | EXPORT_SYMBOL(ad7879_pm_ops); | 320 | EXPORT_SYMBOL(ad7879_pm_ops); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index e57ba52bf484..e4eb8a6c658f 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -883,8 +883,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle) | |||
| 883 | return IRQ_HANDLED; | 883 | return IRQ_HANDLED; |
| 884 | } | 884 | } |
| 885 | 885 | ||
| 886 | #ifdef CONFIG_PM_SLEEP | 886 | static int __maybe_unused ads7846_suspend(struct device *dev) |
| 887 | static int ads7846_suspend(struct device *dev) | ||
| 888 | { | 887 | { |
| 889 | struct ads7846 *ts = dev_get_drvdata(dev); | 888 | struct ads7846 *ts = dev_get_drvdata(dev); |
| 890 | 889 | ||
| @@ -906,7 +905,7 @@ static int ads7846_suspend(struct device *dev) | |||
| 906 | return 0; | 905 | return 0; |
| 907 | } | 906 | } |
| 908 | 907 | ||
| 909 | static int ads7846_resume(struct device *dev) | 908 | static int __maybe_unused ads7846_resume(struct device *dev) |
| 910 | { | 909 | { |
| 911 | struct ads7846 *ts = dev_get_drvdata(dev); | 910 | struct ads7846 *ts = dev_get_drvdata(dev); |
| 912 | 911 | ||
| @@ -927,7 +926,6 @@ static int ads7846_resume(struct device *dev) | |||
| 927 | 926 | ||
| 928 | return 0; | 927 | return 0; |
| 929 | } | 928 | } |
| 930 | #endif | ||
| 931 | 929 | ||
| 932 | static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); | 930 | static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); |
| 933 | 931 | ||
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index aaacf8bfa61f..bb070206223c 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -2244,8 +2244,7 @@ static int mxt_remove(struct i2c_client *client) | |||
| 2244 | return 0; | 2244 | return 0; |
| 2245 | } | 2245 | } |
| 2246 | 2246 | ||
| 2247 | #ifdef CONFIG_PM_SLEEP | 2247 | static int __maybe_unused mxt_suspend(struct device *dev) |
| 2248 | static int mxt_suspend(struct device *dev) | ||
| 2249 | { | 2248 | { |
| 2250 | struct i2c_client *client = to_i2c_client(dev); | 2249 | struct i2c_client *client = to_i2c_client(dev); |
| 2251 | struct mxt_data *data = i2c_get_clientdata(client); | 2250 | struct mxt_data *data = i2c_get_clientdata(client); |
| @@ -2261,7 +2260,7 @@ static int mxt_suspend(struct device *dev) | |||
| 2261 | return 0; | 2260 | return 0; |
| 2262 | } | 2261 | } |
| 2263 | 2262 | ||
| 2264 | static int mxt_resume(struct device *dev) | 2263 | static int __maybe_unused mxt_resume(struct device *dev) |
| 2265 | { | 2264 | { |
| 2266 | struct i2c_client *client = to_i2c_client(dev); | 2265 | struct i2c_client *client = to_i2c_client(dev); |
| 2267 | struct mxt_data *data = i2c_get_clientdata(client); | 2266 | struct mxt_data *data = i2c_get_clientdata(client); |
| @@ -2276,7 +2275,6 @@ static int mxt_resume(struct device *dev) | |||
| 2276 | 2275 | ||
| 2277 | return 0; | 2276 | return 0; |
| 2278 | } | 2277 | } |
| 2279 | #endif | ||
| 2280 | 2278 | ||
| 2281 | static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | 2279 | static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); |
| 2282 | 2280 | ||
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 7f3c94787787..40e02dd5b2f9 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c | |||
| @@ -417,8 +417,7 @@ static void auo_pixcir_input_close(struct input_dev *dev) | |||
| 417 | return; | 417 | return; |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | #ifdef CONFIG_PM_SLEEP | 420 | static int __maybe_unused auo_pixcir_suspend(struct device *dev) |
| 421 | static int auo_pixcir_suspend(struct device *dev) | ||
| 422 | { | 421 | { |
| 423 | struct i2c_client *client = to_i2c_client(dev); | 422 | struct i2c_client *client = to_i2c_client(dev); |
| 424 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); | 423 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); |
| @@ -450,7 +449,7 @@ unlock: | |||
| 450 | return ret; | 449 | return ret; |
| 451 | } | 450 | } |
| 452 | 451 | ||
| 453 | static int auo_pixcir_resume(struct device *dev) | 452 | static int __maybe_unused auo_pixcir_resume(struct device *dev) |
| 454 | { | 453 | { |
| 455 | struct i2c_client *client = to_i2c_client(dev); | 454 | struct i2c_client *client = to_i2c_client(dev); |
| 456 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); | 455 | struct auo_pixcir_ts *ts = i2c_get_clientdata(client); |
| @@ -479,7 +478,6 @@ unlock: | |||
| 479 | 478 | ||
| 480 | return ret; | 479 | return ret; |
| 481 | } | 480 | } |
| 482 | #endif | ||
| 483 | 481 | ||
| 484 | static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, | 482 | static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, |
| 485 | auo_pixcir_suspend, auo_pixcir_resume); | 483 | auo_pixcir_suspend, auo_pixcir_resume); |
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 5bf1aeeea825..f2119ee0e21b 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
| @@ -291,8 +291,7 @@ err_free_mem: | |||
| 291 | return err; | 291 | return err; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | #ifdef CONFIG_PM_SLEEP | 294 | static int __maybe_unused cy8ctmg110_suspend(struct device *dev) |
| 295 | static int cy8ctmg110_suspend(struct device *dev) | ||
| 296 | { | 295 | { |
| 297 | struct i2c_client *client = to_i2c_client(dev); | 296 | struct i2c_client *client = to_i2c_client(dev); |
| 298 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 297 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
| @@ -306,7 +305,7 @@ static int cy8ctmg110_suspend(struct device *dev) | |||
| 306 | return 0; | 305 | return 0; |
| 307 | } | 306 | } |
| 308 | 307 | ||
| 309 | static int cy8ctmg110_resume(struct device *dev) | 308 | static int __maybe_unused cy8ctmg110_resume(struct device *dev) |
| 310 | { | 309 | { |
| 311 | struct i2c_client *client = to_i2c_client(dev); | 310 | struct i2c_client *client = to_i2c_client(dev); |
| 312 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 311 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
| @@ -319,7 +318,6 @@ static int cy8ctmg110_resume(struct device *dev) | |||
| 319 | } | 318 | } |
| 320 | return 0; | 319 | return 0; |
| 321 | } | 320 | } |
| 322 | #endif | ||
| 323 | 321 | ||
| 324 | static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); | 322 | static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); |
| 325 | 323 | ||
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index eee656f77a2e..5b74e8b84e79 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c | |||
| @@ -472,8 +472,7 @@ static int cyttsp_disable(struct cyttsp *ts) | |||
| 472 | return 0; | 472 | return 0; |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | #ifdef CONFIG_PM_SLEEP | 475 | static int __maybe_unused cyttsp_suspend(struct device *dev) |
| 476 | static int cyttsp_suspend(struct device *dev) | ||
| 477 | { | 476 | { |
| 478 | struct cyttsp *ts = dev_get_drvdata(dev); | 477 | struct cyttsp *ts = dev_get_drvdata(dev); |
| 479 | int retval = 0; | 478 | int retval = 0; |
| @@ -491,7 +490,7 @@ static int cyttsp_suspend(struct device *dev) | |||
| 491 | return retval; | 490 | return retval; |
| 492 | } | 491 | } |
| 493 | 492 | ||
| 494 | static int cyttsp_resume(struct device *dev) | 493 | static int __maybe_unused cyttsp_resume(struct device *dev) |
| 495 | { | 494 | { |
| 496 | struct cyttsp *ts = dev_get_drvdata(dev); | 495 | struct cyttsp *ts = dev_get_drvdata(dev); |
| 497 | 496 | ||
| @@ -507,8 +506,6 @@ static int cyttsp_resume(struct device *dev) | |||
| 507 | return 0; | 506 | return 0; |
| 508 | } | 507 | } |
| 509 | 508 | ||
| 510 | #endif | ||
| 511 | |||
| 512 | SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume); | 509 | SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume); |
| 513 | EXPORT_SYMBOL_GPL(cyttsp_pm_ops); | 510 | EXPORT_SYMBOL_GPL(cyttsp_pm_ops); |
| 514 | 511 | ||
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index ee3434f1e949..3793fcc7e5db 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
| @@ -1092,8 +1092,7 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client) | |||
| 1092 | return 0; | 1092 | return 0; |
| 1093 | } | 1093 | } |
| 1094 | 1094 | ||
| 1095 | #ifdef CONFIG_PM_SLEEP | 1095 | static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev) |
| 1096 | static int edt_ft5x06_ts_suspend(struct device *dev) | ||
| 1097 | { | 1096 | { |
| 1098 | struct i2c_client *client = to_i2c_client(dev); | 1097 | struct i2c_client *client = to_i2c_client(dev); |
| 1099 | 1098 | ||
| @@ -1103,7 +1102,7 @@ static int edt_ft5x06_ts_suspend(struct device *dev) | |||
| 1103 | return 0; | 1102 | return 0; |
| 1104 | } | 1103 | } |
| 1105 | 1104 | ||
| 1106 | static int edt_ft5x06_ts_resume(struct device *dev) | 1105 | static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev) |
| 1107 | { | 1106 | { |
| 1108 | struct i2c_client *client = to_i2c_client(dev); | 1107 | struct i2c_client *client = to_i2c_client(dev); |
| 1109 | 1108 | ||
| @@ -1112,7 +1111,6 @@ static int edt_ft5x06_ts_resume(struct device *dev) | |||
| 1112 | 1111 | ||
| 1113 | return 0; | 1112 | return 0; |
| 1114 | } | 1113 | } |
| 1115 | #endif | ||
| 1116 | 1114 | ||
| 1117 | static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, | 1115 | static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, |
| 1118 | edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); | 1116 | edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index b1884ddd7a84..09be6ced7151 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
| @@ -264,8 +264,7 @@ static int eeti_ts_remove(struct i2c_client *client) | |||
| 264 | return 0; | 264 | return 0; |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | #ifdef CONFIG_PM_SLEEP | 267 | static int __maybe_unused eeti_ts_suspend(struct device *dev) |
| 268 | static int eeti_ts_suspend(struct device *dev) | ||
| 269 | { | 268 | { |
| 270 | struct i2c_client *client = to_i2c_client(dev); | 269 | struct i2c_client *client = to_i2c_client(dev); |
| 271 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 270 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
| @@ -284,7 +283,7 @@ static int eeti_ts_suspend(struct device *dev) | |||
| 284 | return 0; | 283 | return 0; |
| 285 | } | 284 | } |
| 286 | 285 | ||
| 287 | static int eeti_ts_resume(struct device *dev) | 286 | static int __maybe_unused eeti_ts_resume(struct device *dev) |
| 288 | { | 287 | { |
| 289 | struct i2c_client *client = to_i2c_client(dev); | 288 | struct i2c_client *client = to_i2c_client(dev); |
| 290 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 289 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
| @@ -302,7 +301,6 @@ static int eeti_ts_resume(struct device *dev) | |||
| 302 | 301 | ||
| 303 | return 0; | 302 | return 0; |
| 304 | } | 303 | } |
| 305 | #endif | ||
| 306 | 304 | ||
| 307 | static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume); | 305 | static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume); |
| 308 | 306 | ||
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index c8057847d71d..4c56299284ef 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c | |||
| @@ -239,8 +239,7 @@ static const struct i2c_device_id egalax_ts_id[] = { | |||
| 239 | }; | 239 | }; |
| 240 | MODULE_DEVICE_TABLE(i2c, egalax_ts_id); | 240 | MODULE_DEVICE_TABLE(i2c, egalax_ts_id); |
| 241 | 241 | ||
| 242 | #ifdef CONFIG_PM_SLEEP | 242 | static int __maybe_unused egalax_ts_suspend(struct device *dev) |
| 243 | static int egalax_ts_suspend(struct device *dev) | ||
| 244 | { | 243 | { |
| 245 | static const u8 suspend_cmd[MAX_I2C_DATA_LEN] = { | 244 | static const u8 suspend_cmd[MAX_I2C_DATA_LEN] = { |
| 246 | 0x3, 0x6, 0xa, 0x3, 0x36, 0x3f, 0x2, 0, 0, 0 | 245 | 0x3, 0x6, 0xa, 0x3, 0x36, 0x3f, 0x2, 0, 0, 0 |
| @@ -252,13 +251,12 @@ static int egalax_ts_suspend(struct device *dev) | |||
| 252 | return ret > 0 ? 0 : ret; | 251 | return ret > 0 ? 0 : ret; |
| 253 | } | 252 | } |
| 254 | 253 | ||
| 255 | static int egalax_ts_resume(struct device *dev) | 254 | static int __maybe_unused egalax_ts_resume(struct device *dev) |
| 256 | { | 255 | { |
| 257 | struct i2c_client *client = to_i2c_client(dev); | 256 | struct i2c_client *client = to_i2c_client(dev); |
| 258 | 257 | ||
| 259 | return egalax_wake_up_device(client); | 258 | return egalax_wake_up_device(client); |
| 260 | } | 259 | } |
| 261 | #endif | ||
| 262 | 260 | ||
| 263 | static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); | 261 | static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); |
| 264 | 262 | ||
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c new file mode 100644 index 000000000000..a510f7ef9b66 --- /dev/null +++ b/drivers/input/touchscreen/elants_i2c.c | |||
| @@ -0,0 +1,1271 @@ | |||
| 1 | /* | ||
| 2 | * Elan Microelectronics touch panels with I2C interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Elan Microelectronics Corporation. | ||
| 5 | * Scott Liu <scott.liu@emc.com.tw> | ||
| 6 | * | ||
| 7 | * This code is partly based on hid-multitouch.c: | ||
| 8 | * | ||
| 9 | * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr> | ||
| 10 | * Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com> | ||
| 11 | * Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France | ||
| 12 | * | ||
| 13 | * | ||
| 14 | * This code is partly based on i2c-hid.c: | ||
| 15 | * | ||
| 16 | * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com> | ||
| 17 | * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France | ||
| 18 | * Copyright (c) 2012 Red Hat, Inc | ||
| 19 | */ | ||
| 20 | |||
| 21 | /* | ||
| 22 | * This software is licensed under the terms of the GNU General Public | ||
| 23 | * License version 2, as published by the Free Software Foundation, and | ||
| 24 | * may be copied, distributed, and modified under those terms. | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <linux/module.h> | ||
| 28 | #include <linux/input.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | #include <linux/platform_device.h> | ||
| 31 | #include <linux/async.h> | ||
| 32 | #include <linux/i2c.h> | ||
| 33 | #include <linux/delay.h> | ||
| 34 | #include <linux/uaccess.h> | ||
| 35 | #include <linux/buffer_head.h> | ||
| 36 | #include <linux/version.h> | ||
| 37 | #include <linux/slab.h> | ||
| 38 | #include <linux/firmware.h> | ||
| 39 | #include <linux/version.h> | ||
| 40 | #include <linux/input/mt.h> | ||
| 41 | #include <linux/acpi.h> | ||
| 42 | #include <linux/of.h> | ||
| 43 | #include <asm/unaligned.h> | ||
| 44 | |||
| 45 | /* Device, Driver information */ | ||
| 46 | #define DEVICE_NAME "elants_i2c" | ||
| 47 | #define DRV_VERSION "1.0.9" | ||
| 48 | |||
| 49 | /* Convert from rows or columns into resolution */ | ||
| 50 | #define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m)) | ||
| 51 | |||
| 52 | /* FW header data */ | ||
| 53 | #define HEADER_SIZE 4 | ||
| 54 | #define FW_HDR_TYPE 0 | ||
| 55 | #define FW_HDR_COUNT 1 | ||
| 56 | #define FW_HDR_LENGTH 2 | ||
| 57 | |||
| 58 | /* Buffer mode Queue Header information */ | ||
| 59 | #define QUEUE_HEADER_SINGLE 0x62 | ||
| 60 | #define QUEUE_HEADER_NORMAL 0X63 | ||
| 61 | #define QUEUE_HEADER_WAIT 0x64 | ||
| 62 | |||
| 63 | /* Command header definition */ | ||
| 64 | #define CMD_HEADER_WRITE 0x54 | ||
| 65 | #define CMD_HEADER_READ 0x53 | ||
| 66 | #define CMD_HEADER_6B_READ 0x5B | ||
| 67 | #define CMD_HEADER_RESP 0x52 | ||
| 68 | #define CMD_HEADER_6B_RESP 0x9B | ||
| 69 | #define CMD_HEADER_HELLO 0x55 | ||
| 70 | #define CMD_HEADER_REK 0x66 | ||
| 71 | |||
| 72 | /* FW position data */ | ||
| 73 | #define PACKET_SIZE 55 | ||
| 74 | #define MAX_CONTACT_NUM 10 | ||
| 75 | #define FW_POS_HEADER 0 | ||
| 76 | #define FW_POS_STATE 1 | ||
| 77 | #define FW_POS_TOTAL 2 | ||
| 78 | #define FW_POS_XY 3 | ||
| 79 | #define FW_POS_CHECKSUM 34 | ||
| 80 | #define FW_POS_WIDTH 35 | ||
| 81 | #define FW_POS_PRESSURE 45 | ||
| 82 | |||
| 83 | #define HEADER_REPORT_10_FINGER 0x62 | ||
| 84 | |||
| 85 | /* Header (4 bytes) plus 3 fill 10-finger packets */ | ||
| 86 | #define MAX_PACKET_SIZE 169 | ||
| 87 | |||
| 88 | #define BOOT_TIME_DELAY_MS 50 | ||
| 89 | |||
| 90 | /* FW read command, 0x53 0x?? 0x0, 0x01 */ | ||
| 91 | #define E_ELAN_INFO_FW_VER 0x00 | ||
| 92 | #define E_ELAN_INFO_BC_VER 0x10 | ||
| 93 | #define E_ELAN_INFO_TEST_VER 0xE0 | ||
| 94 | #define E_ELAN_INFO_FW_ID 0xF0 | ||
| 95 | #define E_INFO_OSR 0xD6 | ||
| 96 | #define E_INFO_PHY_SCAN 0xD7 | ||
| 97 | #define E_INFO_PHY_DRIVER 0xD8 | ||
| 98 | |||
| 99 | #define MAX_RETRIES 3 | ||
| 100 | #define MAX_FW_UPDATE_RETRIES 30 | ||
| 101 | |||
| 102 | #define ELAN_FW_PAGESIZE 132 | ||
| 103 | #define ELAN_FW_FILENAME "elants_i2c.bin" | ||
| 104 | |||
| 105 | /* calibration timeout definition */ | ||
| 106 | #define ELAN_CALI_TIMEOUT_MSEC 10000 | ||
| 107 | |||
| 108 | enum elants_state { | ||
| 109 | ELAN_STATE_NORMAL, | ||
| 110 | ELAN_WAIT_QUEUE_HEADER, | ||
| 111 | ELAN_WAIT_RECALIBRATION, | ||
| 112 | }; | ||
| 113 | |||
| 114 | enum elants_iap_mode { | ||
| 115 | ELAN_IAP_OPERATIONAL, | ||
| 116 | ELAN_IAP_RECOVERY, | ||
| 117 | }; | ||
| 118 | |||
| 119 | /* struct elants_data - represents state of Elan touchscreen device */ | ||
| 120 | struct elants_data { | ||
| 121 | struct i2c_client *client; | ||
| 122 | struct input_dev *input; | ||
| 123 | |||
| 124 | u16 fw_version; | ||
| 125 | u8 test_version; | ||
| 126 | u8 solution_version; | ||
| 127 | u8 bc_version; | ||
| 128 | u8 iap_version; | ||
| 129 | u16 hw_version; | ||
| 130 | unsigned int x_res; /* resolution in units/mm */ | ||
| 131 | unsigned int y_res; | ||
| 132 | unsigned int x_max; | ||
| 133 | unsigned int y_max; | ||
| 134 | |||
| 135 | enum elants_state state; | ||
| 136 | enum elants_iap_mode iap_mode; | ||
| 137 | |||
| 138 | /* Guards against concurrent access to the device via sysfs */ | ||
| 139 | struct mutex sysfs_mutex; | ||
| 140 | |||
| 141 | u8 cmd_resp[HEADER_SIZE]; | ||
| 142 | struct completion cmd_done; | ||
| 143 | |||
| 144 | u8 buf[MAX_PACKET_SIZE]; | ||
| 145 | |||
| 146 | bool wake_irq_enabled; | ||
| 147 | }; | ||
| 148 | |||
| 149 | static int elants_i2c_send(struct i2c_client *client, | ||
| 150 | const void *data, size_t size) | ||
| 151 | { | ||
| 152 | int ret; | ||
| 153 | |||
| 154 | ret = i2c_master_send(client, data, size); | ||
| 155 | if (ret == size) | ||
| 156 | return 0; | ||
| 157 | |||
| 158 | if (ret >= 0) | ||
| 159 | ret = -EIO; | ||
| 160 | |||
| 161 | dev_err(&client->dev, "%s failed (%*ph): %d\n", | ||
| 162 | __func__, (int)size, data, ret); | ||
| 163 | |||
| 164 | return ret; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int elants_i2c_read(struct i2c_client *client, void *data, size_t size) | ||
| 168 | { | ||
| 169 | int ret; | ||
| 170 | |||
| 171 | ret = i2c_master_recv(client, data, size); | ||
| 172 | if (ret == size) | ||
| 173 | return 0; | ||
| 174 | |||
| 175 | if (ret >= 0) | ||
| 176 | ret = -EIO; | ||
| 177 | |||
| 178 | dev_err(&client->dev, "%s failed: %d\n", __func__, ret); | ||
| 179 | |||
| 180 | return ret; | ||
| 181 | } | ||
| 182 | |||
| 183 | static int elants_i2c_execute_command(struct i2c_client *client, | ||
| 184 | const u8 *cmd, size_t cmd_size, | ||
| 185 | u8 *resp, size_t resp_size) | ||
| 186 | { | ||
| 187 | struct i2c_msg msgs[2]; | ||
| 188 | int ret; | ||
| 189 | u8 expected_response; | ||
| 190 | |||
| 191 | switch (cmd[0]) { | ||
| 192 | case CMD_HEADER_READ: | ||
| 193 | expected_response = CMD_HEADER_RESP; | ||
| 194 | break; | ||
| 195 | |||
| 196 | case CMD_HEADER_6B_READ: | ||
| 197 | expected_response = CMD_HEADER_6B_RESP; | ||
| 198 | break; | ||
| 199 | |||
| 200 | default: | ||
| 201 | dev_err(&client->dev, "%s: invalid command %*ph\n", | ||
| 202 | __func__, (int)cmd_size, cmd); | ||
| 203 | return -EINVAL; | ||
| 204 | } | ||
| 205 | |||
| 206 | msgs[0].addr = client->addr; | ||
| 207 | msgs[0].flags = client->flags & I2C_M_TEN; | ||
| 208 | msgs[0].len = cmd_size; | ||
| 209 | msgs[0].buf = (u8 *)cmd; | ||
| 210 | |||
| 211 | msgs[1].addr = client->addr; | ||
| 212 | msgs[1].flags = client->flags & I2C_M_TEN; | ||
| 213 | msgs[1].flags |= I2C_M_RD; | ||
| 214 | msgs[1].len = resp_size; | ||
| 215 | msgs[1].buf = resp; | ||
| 216 | |||
| 217 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 218 | if (ret < 0) | ||
| 219 | return ret; | ||
| 220 | |||
| 221 | if (ret != ARRAY_SIZE(msgs) || resp[FW_HDR_TYPE] != expected_response) | ||
| 222 | return -EIO; | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int elants_i2c_calibrate(struct elants_data *ts) | ||
| 228 | { | ||
| 229 | struct i2c_client *client = ts->client; | ||
| 230 | int ret, error; | ||
| 231 | static const u8 w_flashkey[] = { 0x54, 0xC0, 0xE1, 0x5A }; | ||
| 232 | static const u8 rek[] = { 0x54, 0x29, 0x00, 0x01 }; | ||
| 233 | static const u8 rek_resp[] = { CMD_HEADER_REK, 0x66, 0x66, 0x66 }; | ||
| 234 | |||
| 235 | disable_irq(client->irq); | ||
| 236 | |||
| 237 | ts->state = ELAN_WAIT_RECALIBRATION; | ||
| 238 | reinit_completion(&ts->cmd_done); | ||
| 239 | |||
| 240 | elants_i2c_send(client, w_flashkey, sizeof(w_flashkey)); | ||
| 241 | elants_i2c_send(client, rek, sizeof(rek)); | ||
| 242 | |||
| 243 | enable_irq(client->irq); | ||
| 244 | |||
| 245 | ret = wait_for_completion_interruptible_timeout(&ts->cmd_done, | ||
| 246 | msecs_to_jiffies(ELAN_CALI_TIMEOUT_MSEC)); | ||
| 247 | |||
| 248 | ts->state = ELAN_STATE_NORMAL; | ||
| 249 | |||
| 250 | if (ret <= 0) { | ||
| 251 | error = ret < 0 ? ret : -ETIMEDOUT; | ||
| 252 | dev_err(&client->dev, | ||
| 253 | "error while waiting for calibration to complete: %d\n", | ||
| 254 | error); | ||
| 255 | return error; | ||
| 256 | } | ||
| 257 | |||
| 258 | if (memcmp(rek_resp, ts->cmd_resp, sizeof(rek_resp))) { | ||
| 259 | dev_err(&client->dev, | ||
| 260 | "unexpected calibration response: %*ph\n", | ||
| 261 | (int)sizeof(ts->cmd_resp), ts->cmd_resp); | ||
| 262 | return -EINVAL; | ||
| 263 | } | ||
| 264 | |||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | static int elants_i2c_sw_reset(struct i2c_client *client) | ||
| 269 | { | ||
| 270 | const u8 soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 }; | ||
| 271 | int error; | ||
| 272 | |||
| 273 | error = elants_i2c_send(client, soft_rst_cmd, | ||
| 274 | sizeof(soft_rst_cmd)); | ||
| 275 | if (error) { | ||
| 276 | dev_err(&client->dev, "software reset failed: %d\n", error); | ||
| 277 | return error; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* | ||
| 281 | * We should wait at least 10 msec (but no more than 40) before | ||
| 282 | * sending fastboot or IAP command to the device. | ||
| 283 | */ | ||
| 284 | msleep(30); | ||
| 285 | |||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static u16 elants_i2c_parse_version(u8 *buf) | ||
| 290 | { | ||
| 291 | return get_unaligned_be32(buf) >> 4; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int elants_i2c_query_fw_id(struct elants_data *ts) | ||
| 295 | { | ||
| 296 | struct i2c_client *client = ts->client; | ||
| 297 | int error, retry_cnt; | ||
| 298 | const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_ID, 0x00, 0x01 }; | ||
| 299 | u8 resp[HEADER_SIZE]; | ||
| 300 | |||
| 301 | for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { | ||
| 302 | error = elants_i2c_execute_command(client, cmd, sizeof(cmd), | ||
| 303 | resp, sizeof(resp)); | ||
| 304 | if (!error) { | ||
| 305 | ts->hw_version = elants_i2c_parse_version(resp); | ||
| 306 | if (ts->hw_version != 0xffff) | ||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | dev_dbg(&client->dev, "read fw id error=%d, buf=%*phC\n", | ||
| 311 | error, (int)sizeof(resp), resp); | ||
| 312 | } | ||
| 313 | |||
| 314 | dev_err(&client->dev, | ||
| 315 | "Failed to read fw id or fw id is invalid\n"); | ||
| 316 | |||
| 317 | return -EINVAL; | ||
| 318 | } | ||
| 319 | |||
| 320 | static int elants_i2c_query_fw_version(struct elants_data *ts) | ||
| 321 | { | ||
| 322 | struct i2c_client *client = ts->client; | ||
| 323 | int error, retry_cnt; | ||
| 324 | const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_VER, 0x00, 0x01 }; | ||
| 325 | u8 resp[HEADER_SIZE]; | ||
| 326 | |||
| 327 | for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { | ||
| 328 | error = elants_i2c_execute_command(client, cmd, sizeof(cmd), | ||
| 329 | resp, sizeof(resp)); | ||
| 330 | if (!error) { | ||
| 331 | ts->fw_version = elants_i2c_parse_version(resp); | ||
| 332 | if (ts->fw_version != 0x0000 && | ||
| 333 | ts->fw_version != 0xffff) | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | dev_dbg(&client->dev, "read fw version error=%d, buf=%*phC\n", | ||
| 338 | error, (int)sizeof(resp), resp); | ||
| 339 | } | ||
| 340 | |||
| 341 | dev_err(&client->dev, | ||
| 342 | "Failed to read fw version or fw version is invalid\n"); | ||
| 343 | |||
| 344 | return -EINVAL; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int elants_i2c_query_test_version(struct elants_data *ts) | ||
| 348 | { | ||
| 349 | struct i2c_client *client = ts->client; | ||
| 350 | int error, retry_cnt; | ||
| 351 | u16 version; | ||
| 352 | const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_TEST_VER, 0x00, 0x01 }; | ||
| 353 | u8 resp[HEADER_SIZE]; | ||
| 354 | |||
| 355 | for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { | ||
| 356 | error = elants_i2c_execute_command(client, cmd, sizeof(cmd), | ||
| 357 | resp, sizeof(resp)); | ||
| 358 | if (!error) { | ||
| 359 | version = elants_i2c_parse_version(resp); | ||
| 360 | ts->test_version = version >> 8; | ||
| 361 | ts->solution_version = version & 0xff; | ||
| 362 | |||
| 363 | return 0; | ||
| 364 | } | ||
| 365 | |||
| 366 | dev_dbg(&client->dev, | ||
| 367 | "read test version error rc=%d, buf=%*phC\n", | ||
| 368 | error, (int)sizeof(resp), resp); | ||
| 369 | } | ||
| 370 | |||
| 371 | dev_err(&client->dev, "Failed to read test version\n"); | ||
| 372 | |||
| 373 | return -EINVAL; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int elants_i2c_query_bc_version(struct elants_data *ts) | ||
| 377 | { | ||
| 378 | struct i2c_client *client = ts->client; | ||
| 379 | const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_BC_VER, 0x00, 0x01 }; | ||
| 380 | u8 resp[HEADER_SIZE]; | ||
| 381 | u16 version; | ||
| 382 | int error; | ||
| 383 | |||
| 384 | error = elants_i2c_execute_command(client, cmd, sizeof(cmd), | ||
| 385 | resp, sizeof(resp)); | ||
| 386 | if (error) { | ||
| 387 | dev_err(&client->dev, | ||
| 388 | "read BC version error=%d, buf=%*phC\n", | ||
| 389 | error, (int)sizeof(resp), resp); | ||
| 390 | return error; | ||
| 391 | } | ||
| 392 | |||
| 393 | version = elants_i2c_parse_version(resp); | ||
| 394 | ts->bc_version = version >> 8; | ||
| 395 | ts->iap_version = version & 0xff; | ||
| 396 | |||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | static int elants_i2c_query_ts_info(struct elants_data *ts) | ||
| 401 | { | ||
| 402 | struct i2c_client *client = ts->client; | ||
| 403 | int error; | ||
| 404 | u8 resp[17]; | ||
| 405 | u16 phy_x, phy_y, rows, cols, osr; | ||
| 406 | const u8 get_resolution_cmd[] = { | ||
| 407 | CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 408 | }; | ||
| 409 | const u8 get_osr_cmd[] = { | ||
| 410 | CMD_HEADER_READ, E_INFO_OSR, 0x00, 0x01 | ||
| 411 | }; | ||
| 412 | const u8 get_physical_scan_cmd[] = { | ||
| 413 | CMD_HEADER_READ, E_INFO_PHY_SCAN, 0x00, 0x01 | ||
| 414 | }; | ||
| 415 | const u8 get_physical_drive_cmd[] = { | ||
| 416 | CMD_HEADER_READ, E_INFO_PHY_DRIVER, 0x00, 0x01 | ||
| 417 | }; | ||
| 418 | |||
| 419 | /* Get trace number */ | ||
| 420 | error = elants_i2c_execute_command(client, | ||
| 421 | get_resolution_cmd, | ||
| 422 | sizeof(get_resolution_cmd), | ||
| 423 | resp, sizeof(resp)); | ||
| 424 | if (error) { | ||
| 425 | dev_err(&client->dev, "get resolution command failed: %d\n", | ||
| 426 | error); | ||
| 427 | return error; | ||
| 428 | } | ||
| 429 | |||
| 430 | rows = resp[2] + resp[6] + resp[10]; | ||
| 431 | cols = resp[3] + resp[7] + resp[11]; | ||
| 432 | |||
| 433 | /* Process mm_to_pixel information */ | ||
| 434 | error = elants_i2c_execute_command(client, | ||
| 435 | get_osr_cmd, sizeof(get_osr_cmd), | ||
| 436 | resp, sizeof(resp)); | ||
| 437 | if (error) { | ||
| 438 | dev_err(&client->dev, "get osr command failed: %d\n", | ||
| 439 | error); | ||
| 440 | return error; | ||
| 441 | } | ||
| 442 | |||
| 443 | osr = resp[3]; | ||
| 444 | |||
| 445 | error = elants_i2c_execute_command(client, | ||
| 446 | get_physical_scan_cmd, | ||
| 447 | sizeof(get_physical_scan_cmd), | ||
| 448 | resp, sizeof(resp)); | ||
| 449 | if (error) { | ||
| 450 | dev_err(&client->dev, "get physical scan command failed: %d\n", | ||
| 451 | error); | ||
| 452 | return error; | ||
| 453 | } | ||
| 454 | |||
| 455 | phy_x = get_unaligned_be16(&resp[2]); | ||
| 456 | |||
| 457 | error = elants_i2c_execute_command(client, | ||
| 458 | get_physical_drive_cmd, | ||
| 459 | sizeof(get_physical_drive_cmd), | ||
| 460 | resp, sizeof(resp)); | ||
| 461 | if (error) { | ||
| 462 | dev_err(&client->dev, "get physical drive command failed: %d\n", | ||
| 463 | error); | ||
| 464 | return error; | ||
| 465 | } | ||
| 466 | |||
| 467 | phy_y = get_unaligned_be16(&resp[2]); | ||
| 468 | |||
| 469 | dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y); | ||
| 470 | |||
| 471 | if (rows == 0 || cols == 0 || osr == 0) { | ||
| 472 | dev_warn(&client->dev, | ||
| 473 | "invalid trace number data: %d, %d, %d\n", | ||
| 474 | rows, cols, osr); | ||
| 475 | } else { | ||
| 476 | /* translate trace number to TS resolution */ | ||
| 477 | ts->x_max = ELAN_TS_RESOLUTION(rows, osr); | ||
| 478 | ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x); | ||
| 479 | ts->y_max = ELAN_TS_RESOLUTION(cols, osr); | ||
| 480 | ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y); | ||
| 481 | } | ||
| 482 | |||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | static int elants_i2c_fastboot(struct i2c_client *client) | ||
| 487 | { | ||
| 488 | const u8 boot_cmd[] = { 0x4D, 0x61, 0x69, 0x6E }; | ||
| 489 | int error; | ||
| 490 | |||
| 491 | error = elants_i2c_send(client, boot_cmd, sizeof(boot_cmd)); | ||
| 492 | if (error) { | ||
| 493 | dev_err(&client->dev, "boot failed: %d\n", error); | ||
| 494 | return error; | ||
| 495 | } | ||
| 496 | |||
| 497 | dev_dbg(&client->dev, "boot success -- 0x%x\n", client->addr); | ||
| 498 | return 0; | ||
| 499 | } | ||
| 500 | |||
| 501 | static int elants_i2c_initialize(struct elants_data *ts) | ||
| 502 | { | ||
| 503 | struct i2c_client *client = ts->client; | ||
| 504 | int error, retry_cnt; | ||
| 505 | const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 }; | ||
| 506 | const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 }; | ||
| 507 | u8 buf[HEADER_SIZE]; | ||
| 508 | |||
| 509 | for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { | ||
| 510 | error = elants_i2c_sw_reset(client); | ||
| 511 | if (error) { | ||
| 512 | /* Continue initializing if it's the last try */ | ||
| 513 | if (retry_cnt < MAX_RETRIES - 1) | ||
| 514 | continue; | ||
| 515 | } | ||
| 516 | |||
| 517 | error = elants_i2c_fastboot(client); | ||
| 518 | if (error) { | ||
| 519 | /* Continue initializing if it's the last try */ | ||
| 520 | if (retry_cnt < MAX_RETRIES - 1) | ||
| 521 | continue; | ||
| 522 | } | ||
| 523 | |||
| 524 | /* Wait for Hello packet */ | ||
| 525 | msleep(BOOT_TIME_DELAY_MS); | ||
| 526 | |||
| 527 | error = elants_i2c_read(client, buf, sizeof(buf)); | ||
| 528 | if (error) { | ||
| 529 | dev_err(&client->dev, | ||
| 530 | "failed to read 'hello' packet: %d\n", error); | ||
| 531 | } else if (!memcmp(buf, hello_packet, sizeof(hello_packet))) { | ||
| 532 | ts->iap_mode = ELAN_IAP_OPERATIONAL; | ||
| 533 | break; | ||
| 534 | } else if (!memcmp(buf, recov_packet, sizeof(recov_packet))) { | ||
| 535 | /* | ||
| 536 | * Setting error code will mark device | ||
| 537 | * in recovery mode below. | ||
| 538 | */ | ||
| 539 | error = -EIO; | ||
| 540 | break; | ||
| 541 | } else { | ||
| 542 | error = -EINVAL; | ||
| 543 | dev_err(&client->dev, | ||
| 544 | "invalid 'hello' packet: %*ph\n", | ||
| 545 | (int)sizeof(buf), buf); | ||
| 546 | } | ||
| 547 | } | ||
| 548 | |||
| 549 | if (!error) | ||
| 550 | error = elants_i2c_query_fw_id(ts); | ||
| 551 | if (!error) | ||
| 552 | error = elants_i2c_query_fw_version(ts); | ||
| 553 | |||
| 554 | if (error) { | ||
| 555 | ts->iap_mode = ELAN_IAP_RECOVERY; | ||
| 556 | } else { | ||
| 557 | elants_i2c_query_test_version(ts); | ||
| 558 | elants_i2c_query_bc_version(ts); | ||
| 559 | elants_i2c_query_ts_info(ts); | ||
| 560 | } | ||
| 561 | |||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | /* | ||
| 566 | * Firmware update interface. | ||
| 567 | */ | ||
| 568 | |||
| 569 | static int elants_i2c_fw_write_page(struct i2c_client *client, | ||
| 570 | const void *page) | ||
| 571 | { | ||
| 572 | const u8 ack_ok[] = { 0xaa, 0xaa }; | ||
| 573 | u8 buf[2]; | ||
| 574 | int retry; | ||
| 575 | int error; | ||
| 576 | |||
| 577 | for (retry = 0; retry < MAX_FW_UPDATE_RETRIES; retry++) { | ||
| 578 | error = elants_i2c_send(client, page, ELAN_FW_PAGESIZE); | ||
| 579 | if (error) { | ||
| 580 | dev_err(&client->dev, | ||
| 581 | "IAP Write Page failed: %d\n", error); | ||
| 582 | continue; | ||
| 583 | } | ||
| 584 | |||
| 585 | error = elants_i2c_read(client, buf, 2); | ||
| 586 | if (error) { | ||
| 587 | dev_err(&client->dev, | ||
| 588 | "IAP Ack read failed: %d\n", error); | ||
| 589 | return error; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (!memcmp(buf, ack_ok, sizeof(ack_ok))) | ||
| 593 | return 0; | ||
| 594 | |||
| 595 | error = -EIO; | ||
| 596 | dev_err(&client->dev, | ||
| 597 | "IAP Get Ack Error [%02x:%02x]\n", | ||
| 598 | buf[0], buf[1]); | ||
| 599 | } | ||
| 600 | |||
| 601 | return error; | ||
| 602 | } | ||
| 603 | |||
| 604 | static int elants_i2c_do_update_firmware(struct i2c_client *client, | ||
| 605 | const struct firmware *fw, | ||
| 606 | bool force) | ||
| 607 | { | ||
| 608 | const u8 enter_iap[] = { 0x45, 0x49, 0x41, 0x50 }; | ||
| 609 | const u8 enter_iap2[] = { 0x54, 0x00, 0x12, 0x34 }; | ||
| 610 | const u8 iap_ack[] = { 0x55, 0xaa, 0x33, 0xcc }; | ||
| 611 | u8 buf[HEADER_SIZE]; | ||
| 612 | u16 send_id; | ||
| 613 | int page, n_fw_pages; | ||
| 614 | int error; | ||
| 615 | |||
| 616 | /* Recovery mode detection! */ | ||
| 617 | if (force) { | ||
| 618 | dev_dbg(&client->dev, "Recovery mode procedure\n"); | ||
| 619 | error = elants_i2c_send(client, enter_iap2, sizeof(enter_iap2)); | ||
| 620 | } else { | ||
| 621 | /* Start IAP Procedure */ | ||
| 622 | dev_dbg(&client->dev, "Normal IAP procedure\n"); | ||
| 623 | elants_i2c_sw_reset(client); | ||
| 624 | |||
| 625 | error = elants_i2c_send(client, enter_iap, sizeof(enter_iap)); | ||
| 626 | } | ||
| 627 | |||
| 628 | if (error) { | ||
| 629 | dev_err(&client->dev, "failed to enter IAP mode: %d\n", error); | ||
| 630 | return error; | ||
| 631 | } | ||
| 632 | |||
| 633 | msleep(20); | ||
| 634 | |||
| 635 | /* check IAP state */ | ||
| 636 | error = elants_i2c_read(client, buf, 4); | ||
| 637 | if (error) { | ||
| 638 | dev_err(&client->dev, | ||
| 639 | "failed to read IAP acknowledgement: %d\n", | ||
| 640 | error); | ||
| 641 | return error; | ||
| 642 | } | ||
| 643 | |||
| 644 | if (memcmp(buf, iap_ack, sizeof(iap_ack))) { | ||
| 645 | dev_err(&client->dev, | ||
| 646 | "failed to enter IAP: %*ph (expected %*ph)\n", | ||
| 647 | (int)sizeof(buf), buf, (int)sizeof(iap_ack), iap_ack); | ||
| 648 | return -EIO; | ||
| 649 | } | ||
| 650 | |||
| 651 | dev_info(&client->dev, "successfully entered IAP mode"); | ||
| 652 | |||
| 653 | send_id = client->addr; | ||
| 654 | error = elants_i2c_send(client, &send_id, 1); | ||
| 655 | if (error) { | ||
| 656 | dev_err(&client->dev, "sending dummy byte failed: %d\n", | ||
| 657 | error); | ||
| 658 | return error; | ||
| 659 | } | ||
| 660 | |||
| 661 | /* Clear the last page of Master */ | ||
| 662 | error = elants_i2c_send(client, fw->data, ELAN_FW_PAGESIZE); | ||
| 663 | if (error) { | ||
| 664 | dev_err(&client->dev, "clearing of the last page failed: %d\n", | ||
| 665 | error); | ||
| 666 | return error; | ||
| 667 | } | ||
| 668 | |||
| 669 | error = elants_i2c_read(client, buf, 2); | ||
| 670 | if (error) { | ||
| 671 | dev_err(&client->dev, | ||
| 672 | "failed to read ACK for clearing the last page: %d\n", | ||
| 673 | error); | ||
| 674 | return error; | ||
| 675 | } | ||
| 676 | |||
| 677 | n_fw_pages = fw->size / ELAN_FW_PAGESIZE; | ||
| 678 | dev_dbg(&client->dev, "IAP Pages = %d\n", n_fw_pages); | ||
| 679 | |||
| 680 | for (page = 0; page < n_fw_pages; page++) { | ||
| 681 | error = elants_i2c_fw_write_page(client, | ||
| 682 | fw->data + page * ELAN_FW_PAGESIZE); | ||
| 683 | if (error) { | ||
| 684 | dev_err(&client->dev, | ||
| 685 | "failed to write FW page %d: %d\n", | ||
| 686 | page, error); | ||
| 687 | return error; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | /* Old iap needs to wait 200ms for WDT and rest is for hello packets */ | ||
| 692 | msleep(300); | ||
| 693 | |||
| 694 | dev_info(&client->dev, "firmware update completed\n"); | ||
| 695 | return 0; | ||
| 696 | } | ||
| 697 | |||
| 698 | static int elants_i2c_fw_update(struct elants_data *ts) | ||
| 699 | { | ||
| 700 | struct i2c_client *client = ts->client; | ||
| 701 | const struct firmware *fw; | ||
| 702 | int error; | ||
| 703 | |||
| 704 | error = request_firmware(&fw, ELAN_FW_FILENAME, &client->dev); | ||
| 705 | if (error) { | ||
| 706 | dev_err(&client->dev, "failed to request firmware %s: %d\n", | ||
| 707 | ELAN_FW_FILENAME, error); | ||
| 708 | return error; | ||
| 709 | } | ||
| 710 | |||
| 711 | if (fw->size % ELAN_FW_PAGESIZE) { | ||
| 712 | dev_err(&client->dev, "invalid firmware length: %zu\n", | ||
| 713 | fw->size); | ||
| 714 | error = -EINVAL; | ||
| 715 | goto out; | ||
| 716 | } | ||
| 717 | |||
| 718 | disable_irq(client->irq); | ||
| 719 | |||
| 720 | error = elants_i2c_do_update_firmware(client, fw, | ||
| 721 | ts->iap_mode == ELAN_IAP_RECOVERY); | ||
| 722 | if (error) { | ||
| 723 | dev_err(&client->dev, "firmware update failed: %d\n", error); | ||
| 724 | ts->iap_mode = ELAN_IAP_RECOVERY; | ||
| 725 | goto out_enable_irq; | ||
| 726 | } | ||
| 727 | |||
| 728 | error = elants_i2c_initialize(ts); | ||
| 729 | if (error) { | ||
| 730 | dev_err(&client->dev, | ||
| 731 | "failed to initialize device after firmware update: %d\n", | ||
| 732 | error); | ||
| 733 | ts->iap_mode = ELAN_IAP_RECOVERY; | ||
| 734 | goto out_enable_irq; | ||
| 735 | } | ||
| 736 | |||
| 737 | ts->iap_mode = ELAN_IAP_OPERATIONAL; | ||
| 738 | |||
| 739 | out_enable_irq: | ||
| 740 | ts->state = ELAN_STATE_NORMAL; | ||
| 741 | enable_irq(client->irq); | ||
| 742 | msleep(100); | ||
| 743 | |||
| 744 | if (!error) | ||
| 745 | elants_i2c_calibrate(ts); | ||
| 746 | out: | ||
| 747 | release_firmware(fw); | ||
| 748 | return error; | ||
| 749 | } | ||
| 750 | |||
| 751 | /* | ||
| 752 | * Event reporting. | ||
| 753 | */ | ||
| 754 | |||
| 755 | static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) | ||
| 756 | { | ||
| 757 | struct input_dev *input = ts->input; | ||
| 758 | unsigned int n_fingers; | ||
| 759 | u16 finger_state; | ||
| 760 | int i; | ||
| 761 | |||
| 762 | n_fingers = buf[FW_POS_STATE + 1] & 0x0f; | ||
| 763 | finger_state = ((buf[FW_POS_STATE + 1] & 0x30) << 4) | | ||
| 764 | buf[FW_POS_STATE]; | ||
| 765 | |||
| 766 | dev_dbg(&ts->client->dev, | ||
| 767 | "n_fingers: %u, state: %04x\n", n_fingers, finger_state); | ||
| 768 | |||
| 769 | for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) { | ||
| 770 | if (finger_state & 1) { | ||
| 771 | unsigned int x, y, p, w; | ||
| 772 | u8 *pos; | ||
| 773 | |||
| 774 | pos = &buf[FW_POS_XY + i * 3]; | ||
| 775 | x = (((u16)pos[0] & 0xf0) << 4) | pos[1]; | ||
| 776 | y = (((u16)pos[0] & 0x0f) << 8) | pos[2]; | ||
| 777 | p = buf[FW_POS_PRESSURE + i]; | ||
| 778 | w = buf[FW_POS_WIDTH + i]; | ||
| 779 | |||
| 780 | dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n", | ||
| 781 | i, x, y, p, w); | ||
| 782 | |||
| 783 | input_mt_slot(input, i); | ||
| 784 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | ||
| 785 | input_event(input, EV_ABS, ABS_MT_POSITION_X, x); | ||
| 786 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, y); | ||
| 787 | input_event(input, EV_ABS, ABS_MT_PRESSURE, p); | ||
| 788 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, w); | ||
| 789 | |||
| 790 | n_fingers--; | ||
| 791 | } | ||
| 792 | |||
| 793 | finger_state >>= 1; | ||
| 794 | } | ||
| 795 | |||
| 796 | input_mt_sync_frame(input); | ||
| 797 | input_sync(input); | ||
| 798 | } | ||
| 799 | |||
| 800 | static u8 elants_i2c_calculate_checksum(u8 *buf) | ||
| 801 | { | ||
| 802 | u8 checksum = 0; | ||
| 803 | u8 i; | ||
| 804 | |||
| 805 | for (i = 0; i < FW_POS_CHECKSUM; i++) | ||
| 806 | checksum += buf[i]; | ||
| 807 | |||
| 808 | return checksum; | ||
| 809 | } | ||
| 810 | |||
| 811 | static void elants_i2c_event(struct elants_data *ts, u8 *buf) | ||
| 812 | { | ||
| 813 | u8 checksum = elants_i2c_calculate_checksum(buf); | ||
| 814 | |||
| 815 | if (unlikely(buf[FW_POS_CHECKSUM] != checksum)) | ||
| 816 | dev_warn(&ts->client->dev, | ||
| 817 | "%s: invalid checksum for packet %02x: %02x vs. %02x\n", | ||
| 818 | __func__, buf[FW_POS_HEADER], | ||
| 819 | checksum, buf[FW_POS_CHECKSUM]); | ||
| 820 | else if (unlikely(buf[FW_POS_HEADER] != HEADER_REPORT_10_FINGER)) | ||
| 821 | dev_warn(&ts->client->dev, | ||
| 822 | "%s: unknown packet type: %02x\n", | ||
| 823 | __func__, buf[FW_POS_HEADER]); | ||
| 824 | else | ||
| 825 | elants_i2c_mt_event(ts, buf); | ||
| 826 | } | ||
| 827 | |||
| 828 | static irqreturn_t elants_i2c_irq(int irq, void *_dev) | ||
| 829 | { | ||
| 830 | const u8 wait_packet[] = { 0x64, 0x64, 0x64, 0x64 }; | ||
| 831 | struct elants_data *ts = _dev; | ||
| 832 | struct i2c_client *client = ts->client; | ||
| 833 | int report_count, report_len; | ||
| 834 | int i; | ||
| 835 | int len; | ||
| 836 | |||
| 837 | len = i2c_master_recv(client, ts->buf, sizeof(ts->buf)); | ||
| 838 | if (len < 0) { | ||
| 839 | dev_err(&client->dev, "%s: failed to read data: %d\n", | ||
| 840 | __func__, len); | ||
| 841 | goto out; | ||
| 842 | } | ||
| 843 | |||
| 844 | dev_dbg(&client->dev, "%s: packet %*ph\n", | ||
| 845 | __func__, HEADER_SIZE, ts->buf); | ||
| 846 | |||
| 847 | switch (ts->state) { | ||
| 848 | case ELAN_WAIT_RECALIBRATION: | ||
| 849 | if (ts->buf[FW_HDR_TYPE] == CMD_HEADER_REK) { | ||
| 850 | memcpy(ts->cmd_resp, ts->buf, sizeof(ts->cmd_resp)); | ||
| 851 | complete(&ts->cmd_done); | ||
| 852 | ts->state = ELAN_STATE_NORMAL; | ||
| 853 | } | ||
| 854 | break; | ||
| 855 | |||
| 856 | case ELAN_WAIT_QUEUE_HEADER: | ||
| 857 | if (ts->buf[FW_HDR_TYPE] != QUEUE_HEADER_NORMAL) | ||
| 858 | break; | ||
| 859 | |||
| 860 | ts->state = ELAN_STATE_NORMAL; | ||
| 861 | /* fall through */ | ||
| 862 | |||
| 863 | case ELAN_STATE_NORMAL: | ||
| 864 | |||
| 865 | switch (ts->buf[FW_HDR_TYPE]) { | ||
| 866 | case CMD_HEADER_HELLO: | ||
| 867 | case CMD_HEADER_RESP: | ||
| 868 | case CMD_HEADER_REK: | ||
| 869 | break; | ||
| 870 | |||
| 871 | case QUEUE_HEADER_WAIT: | ||
| 872 | if (memcmp(ts->buf, wait_packet, sizeof(wait_packet))) { | ||
| 873 | dev_err(&client->dev, | ||
| 874 | "invalid wait packet %*ph\n", | ||
| 875 | HEADER_SIZE, ts->buf); | ||
| 876 | } else { | ||
| 877 | ts->state = ELAN_WAIT_QUEUE_HEADER; | ||
| 878 | udelay(30); | ||
| 879 | } | ||
| 880 | break; | ||
| 881 | |||
| 882 | case QUEUE_HEADER_SINGLE: | ||
| 883 | elants_i2c_event(ts, &ts->buf[HEADER_SIZE]); | ||
| 884 | break; | ||
| 885 | |||
| 886 | case QUEUE_HEADER_NORMAL: | ||
| 887 | report_count = ts->buf[FW_HDR_COUNT]; | ||
| 888 | if (report_count > 3) { | ||
| 889 | dev_err(&client->dev, | ||
| 890 | "too large report count: %*ph\n", | ||
| 891 | HEADER_SIZE, ts->buf); | ||
| 892 | break; | ||
| 893 | } | ||
| 894 | |||
| 895 | report_len = ts->buf[FW_HDR_LENGTH] / report_count; | ||
| 896 | if (report_len != PACKET_SIZE) { | ||
| 897 | dev_err(&client->dev, | ||
| 898 | "mismatching report length: %*ph\n", | ||
| 899 | HEADER_SIZE, ts->buf); | ||
| 900 | break; | ||
| 901 | } | ||
| 902 | |||
| 903 | for (i = 0; i < report_count; i++) { | ||
| 904 | u8 *buf = ts->buf + HEADER_SIZE + | ||
| 905 | i * PACKET_SIZE; | ||
| 906 | elants_i2c_event(ts, buf); | ||
| 907 | } | ||
| 908 | break; | ||
| 909 | |||
| 910 | default: | ||
| 911 | dev_err(&client->dev, "unknown packet %*ph\n", | ||
| 912 | HEADER_SIZE, ts->buf); | ||
| 913 | break; | ||
| 914 | } | ||
| 915 | break; | ||
| 916 | } | ||
| 917 | |||
| 918 | out: | ||
| 919 | return IRQ_HANDLED; | ||
| 920 | } | ||
| 921 | |||
| 922 | /* | ||
| 923 | * sysfs interface | ||
| 924 | */ | ||
| 925 | static ssize_t calibrate_store(struct device *dev, | ||
| 926 | struct device_attribute *attr, | ||
| 927 | const char *buf, size_t count) | ||
| 928 | { | ||
| 929 | struct i2c_client *client = to_i2c_client(dev); | ||
| 930 | struct elants_data *ts = i2c_get_clientdata(client); | ||
| 931 | int error; | ||
| 932 | |||
| 933 | error = mutex_lock_interruptible(&ts->sysfs_mutex); | ||
| 934 | if (error) | ||
| 935 | return error; | ||
| 936 | |||
| 937 | error = elants_i2c_calibrate(ts); | ||
| 938 | |||
| 939 | mutex_unlock(&ts->sysfs_mutex); | ||
| 940 | return error ?: count; | ||
| 941 | } | ||
| 942 | |||
| 943 | static ssize_t write_update_fw(struct device *dev, | ||
| 944 | struct device_attribute *attr, | ||
| 945 | const char *buf, size_t count) | ||
| 946 | { | ||
| 947 | struct i2c_client *client = to_i2c_client(dev); | ||
| 948 | struct elants_data *ts = i2c_get_clientdata(client); | ||
| 949 | int error; | ||
| 950 | |||
| 951 | error = mutex_lock_interruptible(&ts->sysfs_mutex); | ||
| 952 | if (error) | ||
| 953 | return error; | ||
| 954 | |||
| 955 | error = elants_i2c_fw_update(ts); | ||
| 956 | dev_dbg(dev, "firmware update result: %d\n", error); | ||
| 957 | |||
| 958 | mutex_unlock(&ts->sysfs_mutex); | ||
| 959 | return error ?: count; | ||
| 960 | } | ||
| 961 | |||
| 962 | static ssize_t show_iap_mode(struct device *dev, | ||
| 963 | struct device_attribute *attr, char *buf) | ||
| 964 | { | ||
| 965 | struct i2c_client *client = to_i2c_client(dev); | ||
| 966 | struct elants_data *ts = i2c_get_clientdata(client); | ||
| 967 | |||
| 968 | return sprintf(buf, "%s\n", | ||
| 969 | ts->iap_mode == ELAN_IAP_OPERATIONAL ? | ||
| 970 | "Normal" : "Recovery"); | ||
| 971 | } | ||
| 972 | |||
| 973 | static DEVICE_ATTR(calibrate, S_IWUSR, NULL, calibrate_store); | ||
| 974 | static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL); | ||
| 975 | static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw); | ||
| 976 | |||
| 977 | struct elants_version_attribute { | ||
| 978 | struct device_attribute dattr; | ||
| 979 | size_t field_offset; | ||
| 980 | size_t field_size; | ||
| 981 | }; | ||
| 982 | |||
| 983 | #define __ELANTS_FIELD_SIZE(_field) \ | ||
| 984 | sizeof(((struct elants_data *)NULL)->_field) | ||
| 985 | #define __ELANTS_VERIFY_SIZE(_field) \ | ||
| 986 | (BUILD_BUG_ON_ZERO(__ELANTS_FIELD_SIZE(_field) > 2) + \ | ||
| 987 | __ELANTS_FIELD_SIZE(_field)) | ||
| 988 | #define ELANTS_VERSION_ATTR(_field) \ | ||
| 989 | struct elants_version_attribute elants_ver_attr_##_field = { \ | ||
| 990 | .dattr = __ATTR(_field, S_IRUGO, \ | ||
| 991 | elants_version_attribute_show, NULL), \ | ||
| 992 | .field_offset = offsetof(struct elants_data, _field), \ | ||
| 993 | .field_size = __ELANTS_VERIFY_SIZE(_field), \ | ||
| 994 | } | ||
| 995 | |||
| 996 | static ssize_t elants_version_attribute_show(struct device *dev, | ||
| 997 | struct device_attribute *dattr, | ||
| 998 | char *buf) | ||
| 999 | { | ||
| 1000 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1001 | struct elants_data *ts = i2c_get_clientdata(client); | ||
| 1002 | struct elants_version_attribute *attr = | ||
| 1003 | container_of(dattr, struct elants_version_attribute, dattr); | ||
| 1004 | u8 *field = (u8 *)((char *)ts + attr->field_offset); | ||
| 1005 | unsigned int fmt_size; | ||
| 1006 | unsigned int val; | ||
| 1007 | |||
| 1008 | if (attr->field_size == 1) { | ||
| 1009 | val = *field; | ||
| 1010 | fmt_size = 2; /* 2 HEX digits */ | ||
| 1011 | } else { | ||
| 1012 | val = *(u16 *)field; | ||
| 1013 | fmt_size = 4; /* 4 HEX digits */ | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | return sprintf(buf, "%0*x\n", fmt_size, val); | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | static ELANTS_VERSION_ATTR(fw_version); | ||
| 1020 | static ELANTS_VERSION_ATTR(hw_version); | ||
| 1021 | static ELANTS_VERSION_ATTR(test_version); | ||
| 1022 | static ELANTS_VERSION_ATTR(solution_version); | ||
| 1023 | static ELANTS_VERSION_ATTR(bc_version); | ||
| 1024 | static ELANTS_VERSION_ATTR(iap_version); | ||
| 1025 | |||
| 1026 | static struct attribute *elants_attributes[] = { | ||
| 1027 | &dev_attr_calibrate.attr, | ||
| 1028 | &dev_attr_update_fw.attr, | ||
| 1029 | &dev_attr_iap_mode.attr, | ||
| 1030 | |||
| 1031 | &elants_ver_attr_fw_version.dattr.attr, | ||
| 1032 | &elants_ver_attr_hw_version.dattr.attr, | ||
| 1033 | &elants_ver_attr_test_version.dattr.attr, | ||
| 1034 | &elants_ver_attr_solution_version.dattr.attr, | ||
| 1035 | &elants_ver_attr_bc_version.dattr.attr, | ||
| 1036 | &elants_ver_attr_iap_version.dattr.attr, | ||
| 1037 | NULL | ||
| 1038 | }; | ||
| 1039 | |||
| 1040 | static struct attribute_group elants_attribute_group = { | ||
| 1041 | .attrs = elants_attributes, | ||
| 1042 | }; | ||
| 1043 | |||
| 1044 | static void elants_i2c_remove_sysfs_group(void *_data) | ||
| 1045 | { | ||
| 1046 | struct elants_data *ts = _data; | ||
| 1047 | |||
| 1048 | sysfs_remove_group(&ts->client->dev.kobj, &elants_attribute_group); | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | static int elants_i2c_probe(struct i2c_client *client, | ||
| 1052 | const struct i2c_device_id *id) | ||
| 1053 | { | ||
| 1054 | union i2c_smbus_data dummy; | ||
| 1055 | struct elants_data *ts; | ||
| 1056 | unsigned long irqflags; | ||
| 1057 | int error; | ||
| 1058 | |||
| 1059 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 1060 | dev_err(&client->dev, | ||
| 1061 | "%s: i2c check functionality error\n", DEVICE_NAME); | ||
| 1062 | return -ENXIO; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | /* Make sure there is something at this address */ | ||
| 1066 | if (i2c_smbus_xfer(client->adapter, client->addr, 0, | ||
| 1067 | I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) { | ||
| 1068 | dev_err(&client->dev, "nothing at this address\n"); | ||
| 1069 | return -ENXIO; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | ts = devm_kzalloc(&client->dev, sizeof(struct elants_data), GFP_KERNEL); | ||
| 1073 | if (!ts) | ||
| 1074 | return -ENOMEM; | ||
| 1075 | |||
| 1076 | mutex_init(&ts->sysfs_mutex); | ||
| 1077 | init_completion(&ts->cmd_done); | ||
| 1078 | |||
| 1079 | ts->client = client; | ||
| 1080 | i2c_set_clientdata(client, ts); | ||
| 1081 | |||
| 1082 | error = elants_i2c_initialize(ts); | ||
| 1083 | if (error) { | ||
| 1084 | dev_err(&client->dev, "failed to initialize: %d\n", error); | ||
| 1085 | return error; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | ts->input = devm_input_allocate_device(&client->dev); | ||
| 1089 | if (!ts->input) { | ||
| 1090 | dev_err(&client->dev, "Failed to allocate input device\n"); | ||
| 1091 | return -ENOMEM; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | ts->input->name = "Elan Touchscreen"; | ||
| 1095 | ts->input->id.bustype = BUS_I2C; | ||
| 1096 | |||
| 1097 | __set_bit(BTN_TOUCH, ts->input->keybit); | ||
| 1098 | __set_bit(EV_ABS, ts->input->evbit); | ||
| 1099 | __set_bit(EV_KEY, ts->input->evbit); | ||
| 1100 | |||
| 1101 | /* Single touch input params setup */ | ||
| 1102 | input_set_abs_params(ts->input, ABS_X, 0, ts->x_max, 0, 0); | ||
| 1103 | input_set_abs_params(ts->input, ABS_Y, 0, ts->y_max, 0, 0); | ||
| 1104 | input_set_abs_params(ts->input, ABS_PRESSURE, 0, 255, 0, 0); | ||
| 1105 | input_abs_set_res(ts->input, ABS_X, ts->x_res); | ||
| 1106 | input_abs_set_res(ts->input, ABS_Y, ts->y_res); | ||
| 1107 | |||
| 1108 | /* Multitouch input params setup */ | ||
| 1109 | error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, | ||
| 1110 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
| 1111 | if (error) { | ||
| 1112 | dev_err(&client->dev, | ||
| 1113 | "failed to initialize MT slots: %d\n", error); | ||
| 1114 | return error; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0); | ||
| 1118 | input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0); | ||
| 1119 | input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | ||
| 1120 | input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
| 1121 | input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res); | ||
| 1122 | input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); | ||
| 1123 | |||
| 1124 | input_set_drvdata(ts->input, ts); | ||
| 1125 | |||
| 1126 | error = input_register_device(ts->input); | ||
| 1127 | if (error) { | ||
| 1128 | dev_err(&client->dev, | ||
| 1129 | "unable to register input device: %d\n", error); | ||
| 1130 | return error; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | /* | ||
| 1134 | * Systems using device tree should set up interrupt via DTS, | ||
| 1135 | * the rest will use the default falling edge interrupts. | ||
| 1136 | */ | ||
| 1137 | irqflags = client->dev.of_node ? 0 : IRQF_TRIGGER_FALLING; | ||
| 1138 | |||
| 1139 | error = devm_request_threaded_irq(&client->dev, client->irq, | ||
| 1140 | NULL, elants_i2c_irq, | ||
| 1141 | irqflags | IRQF_ONESHOT, | ||
| 1142 | client->name, ts); | ||
| 1143 | if (error) { | ||
| 1144 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
| 1145 | return error; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | /* | ||
| 1149 | * Systems using device tree should set up wakeup via DTS, | ||
| 1150 | * the rest will configure device as wakeup source by default. | ||
| 1151 | */ | ||
| 1152 | if (!client->dev.of_node) | ||
| 1153 | device_init_wakeup(&client->dev, true); | ||
| 1154 | |||
| 1155 | error = sysfs_create_group(&client->dev.kobj, &elants_attribute_group); | ||
| 1156 | if (error) { | ||
| 1157 | dev_err(&client->dev, "failed to create sysfs attributes: %d\n", | ||
| 1158 | error); | ||
| 1159 | return error; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | error = devm_add_action(&client->dev, | ||
| 1163 | elants_i2c_remove_sysfs_group, ts); | ||
| 1164 | if (error) { | ||
| 1165 | elants_i2c_remove_sysfs_group(ts); | ||
| 1166 | dev_err(&client->dev, | ||
| 1167 | "Failed to add sysfs cleanup action: %d\n", | ||
| 1168 | error); | ||
| 1169 | return error; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | return 0; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static int __maybe_unused elants_i2c_suspend(struct device *dev) | ||
| 1176 | { | ||
| 1177 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1178 | struct elants_data *ts = i2c_get_clientdata(client); | ||
| 1179 | const u8 set_sleep_cmd[] = { 0x54, 0x50, 0x00, 0x01 }; | ||
| 1180 | int retry_cnt; | ||
| 1181 | int error; | ||
| 1182 | |||
| 1183 | /* Command not support in IAP recovery mode */ | ||
| 1184 | if (ts->iap_mode != ELAN_IAP_OPERATIONAL) | ||
| 1185 | return -EBUSY; | ||
| 1186 | |||
| 1187 | disable_irq(client->irq); | ||
| 1188 | |||
| 1189 | for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { | ||
| 1190 | error = elants_i2c_send(client, set_sleep_cmd, | ||
| 1191 | sizeof(set_sleep_cmd)); | ||
| 1192 | if (!error) | ||
| 1193 | break; | ||
| 1194 | |||
| 1195 | dev_err(&client->dev, "suspend command failed: %d\n", error); | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | if (device_may_wakeup(dev)) | ||
| 1199 | ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0); | ||
| 1200 | |||
| 1201 | return 0; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | static int __maybe_unused elants_i2c_resume(struct device *dev) | ||
| 1205 | { | ||
| 1206 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1207 | struct elants_data *ts = i2c_get_clientdata(client); | ||
| 1208 | const u8 set_active_cmd[] = { 0x54, 0x58, 0x00, 0x01 }; | ||
| 1209 | int retry_cnt; | ||
| 1210 | int error; | ||
| 1211 | |||
| 1212 | if (device_may_wakeup(dev) && ts->wake_irq_enabled) | ||
| 1213 | disable_irq_wake(client->irq); | ||
| 1214 | |||
| 1215 | for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { | ||
| 1216 | error = elants_i2c_send(client, set_active_cmd, | ||
| 1217 | sizeof(set_active_cmd)); | ||
| 1218 | if (!error) | ||
| 1219 | break; | ||
| 1220 | |||
| 1221 | dev_err(&client->dev, "resume command failed: %d\n", error); | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | ts->state = ELAN_STATE_NORMAL; | ||
| 1225 | enable_irq(client->irq); | ||
| 1226 | |||
| 1227 | return 0; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops, | ||
| 1231 | elants_i2c_suspend, elants_i2c_resume); | ||
| 1232 | |||
| 1233 | static const struct i2c_device_id elants_i2c_id[] = { | ||
| 1234 | { DEVICE_NAME, 0 }, | ||
| 1235 | { } | ||
| 1236 | }; | ||
| 1237 | MODULE_DEVICE_TABLE(i2c, elants_i2c_id); | ||
| 1238 | |||
| 1239 | #ifdef CONFIG_ACPI | ||
| 1240 | static const struct acpi_device_id elants_acpi_id[] = { | ||
| 1241 | { "ELAN0001", 0 }, | ||
| 1242 | { } | ||
| 1243 | }; | ||
| 1244 | MODULE_DEVICE_TABLE(acpi, elants_acpi_id); | ||
| 1245 | #endif | ||
| 1246 | |||
| 1247 | #ifdef CONFIG_OF | ||
| 1248 | static const struct of_device_id elants_of_match[] = { | ||
| 1249 | { .compatible = "elan,ekth3500" }, | ||
| 1250 | { /* sentinel */ } | ||
| 1251 | }; | ||
| 1252 | MODULE_DEVICE_TABLE(of, elants_of_match); | ||
| 1253 | #endif | ||
| 1254 | |||
| 1255 | static struct i2c_driver elants_i2c_driver = { | ||
| 1256 | .probe = elants_i2c_probe, | ||
| 1257 | .id_table = elants_i2c_id, | ||
| 1258 | .driver = { | ||
| 1259 | .name = DEVICE_NAME, | ||
| 1260 | .owner = THIS_MODULE, | ||
| 1261 | .pm = &elants_i2c_pm_ops, | ||
| 1262 | .acpi_match_table = ACPI_PTR(elants_acpi_id), | ||
| 1263 | .of_match_table = of_match_ptr(elants_of_match), | ||
| 1264 | }, | ||
| 1265 | }; | ||
| 1266 | module_i2c_driver(elants_i2c_driver); | ||
| 1267 | |||
| 1268 | MODULE_AUTHOR("Scott Liu <scott.liu@emc.com.tw>"); | ||
| 1269 | MODULE_DESCRIPTION("Elan I2c Touchscreen driver"); | ||
| 1270 | MODULE_VERSION(DRV_VERSION); | ||
| 1271 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c new file mode 100644 index 000000000000..ca196689f025 --- /dev/null +++ b/drivers/input/touchscreen/goodix.c | |||
| @@ -0,0 +1,395 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Goodix Touchscreens | ||
| 3 | * | ||
| 4 | * Copyright (c) 2014 Red Hat Inc. | ||
| 5 | * | ||
| 6 | * This code is based on gt9xx.c authored by andrew@goodix.com: | ||
| 7 | * | ||
| 8 | * 2010 - 2012 Goodix Technology. | ||
| 9 | */ | ||
| 10 | |||
| 11 | /* | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the Free | ||
| 14 | * Software Foundation; version 2 of the License. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/i2c.h> | ||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/input/mt.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/irq.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <asm/unaligned.h> | ||
| 27 | |||
| 28 | struct goodix_ts_data { | ||
| 29 | struct i2c_client *client; | ||
| 30 | struct input_dev *input_dev; | ||
| 31 | int abs_x_max; | ||
| 32 | int abs_y_max; | ||
| 33 | unsigned int max_touch_num; | ||
| 34 | unsigned int int_trigger_type; | ||
| 35 | }; | ||
| 36 | |||
| 37 | #define GOODIX_MAX_HEIGHT 4096 | ||
| 38 | #define GOODIX_MAX_WIDTH 4096 | ||
| 39 | #define GOODIX_INT_TRIGGER 1 | ||
| 40 | #define GOODIX_CONTACT_SIZE 8 | ||
| 41 | #define GOODIX_MAX_CONTACTS 10 | ||
| 42 | |||
| 43 | #define GOODIX_CONFIG_MAX_LENGTH 240 | ||
| 44 | |||
| 45 | /* Register defines */ | ||
| 46 | #define GOODIX_READ_COOR_ADDR 0x814E | ||
| 47 | #define GOODIX_REG_CONFIG_DATA 0x8047 | ||
| 48 | #define GOODIX_REG_VERSION 0x8140 | ||
| 49 | |||
| 50 | #define RESOLUTION_LOC 1 | ||
| 51 | #define TRIGGER_LOC 6 | ||
| 52 | |||
| 53 | static const unsigned long goodix_irq_flags[] = { | ||
| 54 | IRQ_TYPE_EDGE_RISING, | ||
| 55 | IRQ_TYPE_EDGE_FALLING, | ||
| 56 | IRQ_TYPE_LEVEL_LOW, | ||
| 57 | IRQ_TYPE_LEVEL_HIGH, | ||
| 58 | }; | ||
| 59 | |||
| 60 | /** | ||
| 61 | * goodix_i2c_read - read data from a register of the i2c slave device. | ||
| 62 | * | ||
| 63 | * @client: i2c device. | ||
| 64 | * @reg: the register to read from. | ||
| 65 | * @buf: raw write data buffer. | ||
| 66 | * @len: length of the buffer to write | ||
| 67 | */ | ||
| 68 | static int goodix_i2c_read(struct i2c_client *client, | ||
| 69 | u16 reg, u8 *buf, int len) | ||
| 70 | { | ||
| 71 | struct i2c_msg msgs[2]; | ||
| 72 | u16 wbuf = cpu_to_be16(reg); | ||
| 73 | int ret; | ||
| 74 | |||
| 75 | msgs[0].flags = 0; | ||
| 76 | msgs[0].addr = client->addr; | ||
| 77 | msgs[0].len = 2; | ||
| 78 | msgs[0].buf = (u8 *) &wbuf; | ||
| 79 | |||
| 80 | msgs[1].flags = I2C_M_RD; | ||
| 81 | msgs[1].addr = client->addr; | ||
| 82 | msgs[1].len = len; | ||
| 83 | msgs[1].buf = buf; | ||
| 84 | |||
| 85 | ret = i2c_transfer(client->adapter, msgs, 2); | ||
| 86 | return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0); | ||
| 87 | } | ||
| 88 | |||
| 89 | static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) | ||
| 90 | { | ||
| 91 | int touch_num; | ||
| 92 | int error; | ||
| 93 | |||
| 94 | error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data, | ||
| 95 | GOODIX_CONTACT_SIZE + 1); | ||
| 96 | if (error) { | ||
| 97 | dev_err(&ts->client->dev, "I2C transfer error: %d\n", error); | ||
| 98 | return error; | ||
| 99 | } | ||
| 100 | |||
| 101 | touch_num = data[0] & 0x0f; | ||
| 102 | if (touch_num > GOODIX_MAX_CONTACTS) | ||
| 103 | return -EPROTO; | ||
| 104 | |||
| 105 | if (touch_num > 1) { | ||
| 106 | data += 1 + GOODIX_CONTACT_SIZE; | ||
| 107 | error = goodix_i2c_read(ts->client, | ||
| 108 | GOODIX_READ_COOR_ADDR + | ||
| 109 | 1 + GOODIX_CONTACT_SIZE, | ||
| 110 | data, | ||
| 111 | GOODIX_CONTACT_SIZE * (touch_num - 1)); | ||
| 112 | if (error) | ||
| 113 | return error; | ||
| 114 | } | ||
| 115 | |||
| 116 | return touch_num; | ||
| 117 | } | ||
| 118 | |||
| 119 | static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) | ||
| 120 | { | ||
| 121 | int id = coor_data[0] & 0x0F; | ||
| 122 | int input_x = get_unaligned_le16(&coor_data[1]); | ||
| 123 | int input_y = get_unaligned_le16(&coor_data[3]); | ||
| 124 | int input_w = get_unaligned_le16(&coor_data[5]); | ||
| 125 | |||
| 126 | input_mt_slot(ts->input_dev, id); | ||
| 127 | input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); | ||
| 128 | input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); | ||
| 129 | input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y); | ||
| 130 | input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); | ||
| 131 | input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w); | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * goodix_process_events - Process incoming events | ||
| 136 | * | ||
| 137 | * @ts: our goodix_ts_data pointer | ||
| 138 | * | ||
| 139 | * Called when the IRQ is triggered. Read the current device state, and push | ||
| 140 | * the input events to the user space. | ||
| 141 | */ | ||
| 142 | static void goodix_process_events(struct goodix_ts_data *ts) | ||
| 143 | { | ||
| 144 | u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; | ||
| 145 | int touch_num; | ||
| 146 | int i; | ||
| 147 | |||
| 148 | touch_num = goodix_ts_read_input_report(ts, point_data); | ||
| 149 | if (touch_num < 0) | ||
| 150 | return; | ||
| 151 | |||
| 152 | for (i = 0; i < touch_num; i++) | ||
| 153 | goodix_ts_report_touch(ts, | ||
| 154 | &point_data[1 + GOODIX_CONTACT_SIZE * i]); | ||
| 155 | |||
| 156 | input_mt_sync_frame(ts->input_dev); | ||
| 157 | input_sync(ts->input_dev); | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * goodix_ts_irq_handler - The IRQ handler | ||
| 162 | * | ||
| 163 | * @irq: interrupt number. | ||
| 164 | * @dev_id: private data pointer. | ||
| 165 | */ | ||
| 166 | static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) | ||
| 167 | { | ||
| 168 | static const u8 end_cmd[] = { | ||
| 169 | GOODIX_READ_COOR_ADDR >> 8, | ||
| 170 | GOODIX_READ_COOR_ADDR & 0xff, | ||
| 171 | 0 | ||
| 172 | }; | ||
| 173 | struct goodix_ts_data *ts = dev_id; | ||
| 174 | |||
| 175 | goodix_process_events(ts); | ||
| 176 | |||
| 177 | if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0) | ||
| 178 | dev_err(&ts->client->dev, "I2C write end_cmd error\n"); | ||
| 179 | |||
| 180 | return IRQ_HANDLED; | ||
| 181 | } | ||
| 182 | |||
| 183 | /** | ||
| 184 | * goodix_read_config - Read the embedded configuration of the panel | ||
| 185 | * | ||
| 186 | * @ts: our goodix_ts_data pointer | ||
| 187 | * | ||
| 188 | * Must be called during probe | ||
| 189 | */ | ||
| 190 | static void goodix_read_config(struct goodix_ts_data *ts) | ||
| 191 | { | ||
| 192 | u8 config[GOODIX_CONFIG_MAX_LENGTH]; | ||
| 193 | int error; | ||
| 194 | |||
| 195 | error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA, | ||
| 196 | config, | ||
| 197 | GOODIX_CONFIG_MAX_LENGTH); | ||
| 198 | if (error) { | ||
| 199 | dev_warn(&ts->client->dev, | ||
| 200 | "Error reading config (%d), using defaults\n", | ||
| 201 | error); | ||
| 202 | ts->abs_x_max = GOODIX_MAX_WIDTH; | ||
| 203 | ts->abs_y_max = GOODIX_MAX_HEIGHT; | ||
| 204 | ts->int_trigger_type = GOODIX_INT_TRIGGER; | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | |||
| 208 | ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); | ||
| 209 | ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); | ||
| 210 | ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03; | ||
| 211 | if (!ts->abs_x_max || !ts->abs_y_max) { | ||
| 212 | dev_err(&ts->client->dev, | ||
| 213 | "Invalid config, using defaults\n"); | ||
| 214 | ts->abs_x_max = GOODIX_MAX_WIDTH; | ||
| 215 | ts->abs_y_max = GOODIX_MAX_HEIGHT; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | |||
| 220 | /** | ||
| 221 | * goodix_read_version - Read goodix touchscreen version | ||
| 222 | * | ||
| 223 | * @client: the i2c client | ||
| 224 | * @version: output buffer containing the version on success | ||
| 225 | */ | ||
| 226 | static int goodix_read_version(struct i2c_client *client, u16 *version) | ||
| 227 | { | ||
| 228 | int error; | ||
| 229 | u8 buf[6]; | ||
| 230 | |||
| 231 | error = goodix_i2c_read(client, GOODIX_REG_VERSION, buf, sizeof(buf)); | ||
| 232 | if (error) { | ||
| 233 | dev_err(&client->dev, "read version failed: %d\n", error); | ||
| 234 | return error; | ||
| 235 | } | ||
| 236 | |||
| 237 | if (version) | ||
| 238 | *version = get_unaligned_le16(&buf[4]); | ||
| 239 | |||
| 240 | dev_info(&client->dev, "IC VERSION: %6ph\n", buf); | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | /** | ||
| 246 | * goodix_i2c_test - I2C test function to check if the device answers. | ||
| 247 | * | ||
| 248 | * @client: the i2c client | ||
| 249 | */ | ||
| 250 | static int goodix_i2c_test(struct i2c_client *client) | ||
| 251 | { | ||
| 252 | int retry = 0; | ||
| 253 | int error; | ||
| 254 | u8 test; | ||
| 255 | |||
| 256 | while (retry++ < 2) { | ||
| 257 | error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA, | ||
| 258 | &test, 1); | ||
| 259 | if (!error) | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | dev_err(&client->dev, "i2c test failed attempt %d: %d\n", | ||
| 263 | retry, error); | ||
| 264 | msleep(20); | ||
| 265 | } | ||
| 266 | |||
| 267 | return error; | ||
| 268 | } | ||
| 269 | |||
| 270 | /** | ||
| 271 | * goodix_request_input_dev - Allocate, populate and register the input device | ||
| 272 | * | ||
| 273 | * @ts: our goodix_ts_data pointer | ||
| 274 | * | ||
| 275 | * Must be called during probe | ||
| 276 | */ | ||
| 277 | static int goodix_request_input_dev(struct goodix_ts_data *ts) | ||
| 278 | { | ||
| 279 | int error; | ||
| 280 | |||
| 281 | ts->input_dev = devm_input_allocate_device(&ts->client->dev); | ||
| 282 | if (!ts->input_dev) { | ||
| 283 | dev_err(&ts->client->dev, "Failed to allocate input device."); | ||
| 284 | return -ENOMEM; | ||
| 285 | } | ||
| 286 | |||
| 287 | ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | | ||
| 288 | BIT_MASK(EV_KEY) | | ||
| 289 | BIT_MASK(EV_ABS); | ||
| 290 | |||
| 291 | input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, | ||
| 292 | ts->abs_x_max, 0, 0); | ||
| 293 | input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, | ||
| 294 | ts->abs_y_max, 0, 0); | ||
| 295 | input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); | ||
| 296 | input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | ||
| 297 | |||
| 298 | input_mt_init_slots(ts->input_dev, GOODIX_MAX_CONTACTS, | ||
| 299 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
| 300 | |||
| 301 | ts->input_dev->name = "Goodix Capacitive TouchScreen"; | ||
| 302 | ts->input_dev->phys = "input/ts"; | ||
| 303 | ts->input_dev->id.bustype = BUS_I2C; | ||
| 304 | ts->input_dev->id.vendor = 0x0416; | ||
| 305 | ts->input_dev->id.product = 0x1001; | ||
| 306 | ts->input_dev->id.version = 10427; | ||
| 307 | |||
| 308 | error = input_register_device(ts->input_dev); | ||
| 309 | if (error) { | ||
| 310 | dev_err(&ts->client->dev, | ||
| 311 | "Failed to register input device: %d", error); | ||
| 312 | return error; | ||
| 313 | } | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int goodix_ts_probe(struct i2c_client *client, | ||
| 319 | const struct i2c_device_id *id) | ||
| 320 | { | ||
| 321 | struct goodix_ts_data *ts; | ||
| 322 | unsigned long irq_flags; | ||
| 323 | int error; | ||
| 324 | u16 version_info; | ||
| 325 | |||
| 326 | dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr); | ||
| 327 | |||
| 328 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 329 | dev_err(&client->dev, "I2C check functionality failed.\n"); | ||
| 330 | return -ENXIO; | ||
| 331 | } | ||
| 332 | |||
| 333 | ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); | ||
| 334 | if (!ts) | ||
| 335 | return -ENOMEM; | ||
| 336 | |||
| 337 | ts->client = client; | ||
| 338 | i2c_set_clientdata(client, ts); | ||
| 339 | |||
| 340 | error = goodix_i2c_test(client); | ||
| 341 | if (error) { | ||
| 342 | dev_err(&client->dev, "I2C communication failure: %d\n", error); | ||
| 343 | return error; | ||
| 344 | } | ||
| 345 | |||
| 346 | error = goodix_read_version(client, &version_info); | ||
| 347 | if (error) { | ||
| 348 | dev_err(&client->dev, "Read version failed.\n"); | ||
| 349 | return error; | ||
| 350 | } | ||
| 351 | |||
| 352 | goodix_read_config(ts); | ||
| 353 | |||
| 354 | error = goodix_request_input_dev(ts); | ||
| 355 | if (error) | ||
| 356 | return error; | ||
| 357 | |||
| 358 | irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT; | ||
| 359 | error = devm_request_threaded_irq(&ts->client->dev, client->irq, | ||
| 360 | NULL, goodix_ts_irq_handler, | ||
| 361 | irq_flags, client->name, ts); | ||
| 362 | if (error) { | ||
| 363 | dev_err(&client->dev, "request IRQ failed: %d\n", error); | ||
| 364 | return error; | ||
| 365 | } | ||
| 366 | |||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | static const struct i2c_device_id goodix_ts_id[] = { | ||
| 371 | { "GDIX1001:00", 0 }, | ||
| 372 | { } | ||
| 373 | }; | ||
| 374 | |||
| 375 | static const struct acpi_device_id goodix_acpi_match[] = { | ||
| 376 | { "GDIX1001", 0 }, | ||
| 377 | { } | ||
| 378 | }; | ||
| 379 | MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); | ||
| 380 | |||
| 381 | static struct i2c_driver goodix_ts_driver = { | ||
| 382 | .probe = goodix_ts_probe, | ||
| 383 | .id_table = goodix_ts_id, | ||
| 384 | .driver = { | ||
| 385 | .name = "Goodix-TS", | ||
| 386 | .owner = THIS_MODULE, | ||
| 387 | .acpi_match_table = goodix_acpi_match, | ||
| 388 | }, | ||
| 389 | }; | ||
| 390 | module_i2c_driver(goodix_ts_driver); | ||
| 391 | |||
| 392 | MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); | ||
| 393 | MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); | ||
| 394 | MODULE_DESCRIPTION("Goodix touchscreen driver"); | ||
| 395 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 2a5089139818..da6dc819c846 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c | |||
| @@ -311,8 +311,7 @@ static int ili210x_i2c_remove(struct i2c_client *client) | |||
| 311 | return 0; | 311 | return 0; |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | #ifdef CONFIG_PM_SLEEP | 314 | static int __maybe_unused ili210x_i2c_suspend(struct device *dev) |
| 315 | static int ili210x_i2c_suspend(struct device *dev) | ||
| 316 | { | 315 | { |
| 317 | struct i2c_client *client = to_i2c_client(dev); | 316 | struct i2c_client *client = to_i2c_client(dev); |
| 318 | 317 | ||
| @@ -322,7 +321,7 @@ static int ili210x_i2c_suspend(struct device *dev) | |||
| 322 | return 0; | 321 | return 0; |
| 323 | } | 322 | } |
| 324 | 323 | ||
| 325 | static int ili210x_i2c_resume(struct device *dev) | 324 | static int __maybe_unused ili210x_i2c_resume(struct device *dev) |
| 326 | { | 325 | { |
| 327 | struct i2c_client *client = to_i2c_client(dev); | 326 | struct i2c_client *client = to_i2c_client(dev); |
| 328 | 327 | ||
| @@ -331,7 +330,6 @@ static int ili210x_i2c_resume(struct device *dev) | |||
| 331 | 330 | ||
| 332 | return 0; | 331 | return 0; |
| 333 | } | 332 | } |
| 334 | #endif | ||
| 335 | 333 | ||
| 336 | static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, | 334 | static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, |
| 337 | ili210x_i2c_suspend, ili210x_i2c_resume); | 335 | ili210x_i2c_suspend, ili210x_i2c_resume); |
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c index 62c8976e616f..33c134820ef9 100644 --- a/drivers/input/touchscreen/ipaq-micro-ts.c +++ b/drivers/input/touchscreen/ipaq-micro-ts.c | |||
| @@ -122,8 +122,7 @@ static int micro_ts_probe(struct platform_device *pdev) | |||
| 122 | return 0; | 122 | return 0; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | #ifdef CONFIG_PM_SLEEP | 125 | static int __maybe_unused micro_ts_suspend(struct device *dev) |
| 126 | static int micro_ts_suspend(struct device *dev) | ||
| 127 | { | 126 | { |
| 128 | struct touchscreen_data *ts = dev_get_drvdata(dev); | 127 | struct touchscreen_data *ts = dev_get_drvdata(dev); |
| 129 | 128 | ||
| @@ -132,7 +131,7 @@ static int micro_ts_suspend(struct device *dev) | |||
| 132 | return 0; | 131 | return 0; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | static int micro_ts_resume(struct device *dev) | 134 | static int __maybe_unused micro_ts_resume(struct device *dev) |
| 136 | { | 135 | { |
| 137 | struct touchscreen_data *ts = dev_get_drvdata(dev); | 136 | struct touchscreen_data *ts = dev_get_drvdata(dev); |
| 138 | struct input_dev *input = ts->input; | 137 | struct input_dev *input = ts->input; |
| @@ -146,7 +145,6 @@ static int micro_ts_resume(struct device *dev) | |||
| 146 | 145 | ||
| 147 | return 0; | 146 | return 0; |
| 148 | } | 147 | } |
| 149 | #endif | ||
| 150 | 148 | ||
| 151 | static const struct dev_pm_ops micro_ts_dev_pm_ops = { | 149 | static const struct dev_pm_ops micro_ts_dev_pm_ops = { |
| 152 | SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume) | 150 | SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume) |
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 372bbf7658fe..67c0d31613d8 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c | |||
| @@ -515,8 +515,7 @@ static int mms114_probe(struct i2c_client *client, | |||
| 515 | return 0; | 515 | return 0; |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | #ifdef CONFIG_PM_SLEEP | 518 | static int __maybe_unused mms114_suspend(struct device *dev) |
| 519 | static int mms114_suspend(struct device *dev) | ||
| 520 | { | 519 | { |
| 521 | struct i2c_client *client = to_i2c_client(dev); | 520 | struct i2c_client *client = to_i2c_client(dev); |
| 522 | struct mms114_data *data = i2c_get_clientdata(client); | 521 | struct mms114_data *data = i2c_get_clientdata(client); |
| @@ -540,7 +539,7 @@ static int mms114_suspend(struct device *dev) | |||
| 540 | return 0; | 539 | return 0; |
| 541 | } | 540 | } |
| 542 | 541 | ||
| 543 | static int mms114_resume(struct device *dev) | 542 | static int __maybe_unused mms114_resume(struct device *dev) |
| 544 | { | 543 | { |
| 545 | struct i2c_client *client = to_i2c_client(dev); | 544 | struct i2c_client *client = to_i2c_client(dev); |
| 546 | struct mms114_data *data = i2c_get_clientdata(client); | 545 | struct mms114_data *data = i2c_get_clientdata(client); |
| @@ -559,7 +558,6 @@ static int mms114_resume(struct device *dev) | |||
| 559 | 558 | ||
| 560 | return 0; | 559 | return 0; |
| 561 | } | 560 | } |
| 562 | #endif | ||
| 563 | 561 | ||
| 564 | static SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume); | 562 | static SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume); |
| 565 | 563 | ||
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index fc49c75317d1..4fb5537fdd42 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
| @@ -347,8 +347,7 @@ static void pixcir_input_close(struct input_dev *dev) | |||
| 347 | pixcir_stop(ts); | 347 | pixcir_stop(ts); |
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | #ifdef CONFIG_PM_SLEEP | 350 | static int __maybe_unused pixcir_i2c_ts_suspend(struct device *dev) |
| 351 | static int pixcir_i2c_ts_suspend(struct device *dev) | ||
| 352 | { | 351 | { |
| 353 | struct i2c_client *client = to_i2c_client(dev); | 352 | struct i2c_client *client = to_i2c_client(dev); |
| 354 | struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); | 353 | struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); |
| @@ -377,7 +376,7 @@ unlock: | |||
| 377 | return ret; | 376 | return ret; |
| 378 | } | 377 | } |
| 379 | 378 | ||
| 380 | static int pixcir_i2c_ts_resume(struct device *dev) | 379 | static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev) |
| 381 | { | 380 | { |
| 382 | struct i2c_client *client = to_i2c_client(dev); | 381 | struct i2c_client *client = to_i2c_client(dev); |
| 383 | struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); | 382 | struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); |
| @@ -405,7 +404,6 @@ unlock: | |||
| 405 | 404 | ||
| 406 | return ret; | 405 | return ret; |
| 407 | } | 406 | } |
| 408 | #endif | ||
| 409 | 407 | ||
| 410 | static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, | 408 | static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, |
| 411 | pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); | 409 | pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); |
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 3c0f57efe7b1..697e26e52d54 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
| @@ -243,8 +243,7 @@ static int st1232_ts_remove(struct i2c_client *client) | |||
| 243 | return 0; | 243 | return 0; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | #ifdef CONFIG_PM_SLEEP | 246 | static int __maybe_unused st1232_ts_suspend(struct device *dev) |
| 247 | static int st1232_ts_suspend(struct device *dev) | ||
| 248 | { | 247 | { |
| 249 | struct i2c_client *client = to_i2c_client(dev); | 248 | struct i2c_client *client = to_i2c_client(dev); |
| 250 | struct st1232_ts_data *ts = i2c_get_clientdata(client); | 249 | struct st1232_ts_data *ts = i2c_get_clientdata(client); |
| @@ -259,7 +258,7 @@ static int st1232_ts_suspend(struct device *dev) | |||
| 259 | return 0; | 258 | return 0; |
| 260 | } | 259 | } |
| 261 | 260 | ||
| 262 | static int st1232_ts_resume(struct device *dev) | 261 | static int __maybe_unused st1232_ts_resume(struct device *dev) |
| 263 | { | 262 | { |
| 264 | struct i2c_client *client = to_i2c_client(dev); | 263 | struct i2c_client *client = to_i2c_client(dev); |
| 265 | struct st1232_ts_data *ts = i2c_get_clientdata(client); | 264 | struct st1232_ts_data *ts = i2c_get_clientdata(client); |
| @@ -274,8 +273,6 @@ static int st1232_ts_resume(struct device *dev) | |||
| 274 | return 0; | 273 | return 0; |
| 275 | } | 274 | } |
| 276 | 275 | ||
| 277 | #endif | ||
| 278 | |||
| 279 | static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, | 276 | static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, |
| 280 | st1232_ts_suspend, st1232_ts_resume); | 277 | st1232_ts_suspend, st1232_ts_resume); |
| 281 | 278 | ||
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 52380b68ebdf..72657c579430 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
| @@ -773,8 +773,7 @@ static int tsc2005_remove(struct spi_device *spi) | |||
| 773 | return 0; | 773 | return 0; |
| 774 | } | 774 | } |
| 775 | 775 | ||
| 776 | #ifdef CONFIG_PM_SLEEP | 776 | static int __maybe_unused tsc2005_suspend(struct device *dev) |
| 777 | static int tsc2005_suspend(struct device *dev) | ||
| 778 | { | 777 | { |
| 779 | struct spi_device *spi = to_spi_device(dev); | 778 | struct spi_device *spi = to_spi_device(dev); |
| 780 | struct tsc2005 *ts = spi_get_drvdata(spi); | 779 | struct tsc2005 *ts = spi_get_drvdata(spi); |
| @@ -791,7 +790,7 @@ static int tsc2005_suspend(struct device *dev) | |||
| 791 | return 0; | 790 | return 0; |
| 792 | } | 791 | } |
| 793 | 792 | ||
| 794 | static int tsc2005_resume(struct device *dev) | 793 | static int __maybe_unused tsc2005_resume(struct device *dev) |
| 795 | { | 794 | { |
| 796 | struct spi_device *spi = to_spi_device(dev); | 795 | struct spi_device *spi = to_spi_device(dev); |
| 797 | struct tsc2005 *ts = spi_get_drvdata(spi); | 796 | struct tsc2005 *ts = spi_get_drvdata(spi); |
| @@ -807,7 +806,6 @@ static int tsc2005_resume(struct device *dev) | |||
| 807 | 806 | ||
| 808 | return 0; | 807 | return 0; |
| 809 | } | 808 | } |
| 810 | #endif | ||
| 811 | 809 | ||
| 812 | static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume); | 810 | static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume); |
| 813 | 811 | ||
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 0eca00da584b..c1e23cfc6155 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -406,8 +406,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev) | |||
| 406 | return 0; | 406 | return 0; |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | #ifdef CONFIG_PM_SLEEP | 409 | static int __maybe_unused ucb1400_ts_suspend(struct device *dev) |
| 410 | static int ucb1400_ts_suspend(struct device *dev) | ||
| 411 | { | 410 | { |
| 412 | struct ucb1400_ts *ucb = dev_get_platdata(dev); | 411 | struct ucb1400_ts *ucb = dev_get_platdata(dev); |
| 413 | struct input_dev *idev = ucb->ts_idev; | 412 | struct input_dev *idev = ucb->ts_idev; |
| @@ -421,7 +420,7 @@ static int ucb1400_ts_suspend(struct device *dev) | |||
| 421 | return 0; | 420 | return 0; |
| 422 | } | 421 | } |
| 423 | 422 | ||
| 424 | static int ucb1400_ts_resume(struct device *dev) | 423 | static int __maybe_unused ucb1400_ts_resume(struct device *dev) |
| 425 | { | 424 | { |
| 426 | struct ucb1400_ts *ucb = dev_get_platdata(dev); | 425 | struct ucb1400_ts *ucb = dev_get_platdata(dev); |
| 427 | struct input_dev *idev = ucb->ts_idev; | 426 | struct input_dev *idev = ucb->ts_idev; |
| @@ -434,7 +433,6 @@ static int ucb1400_ts_resume(struct device *dev) | |||
| 434 | mutex_unlock(&idev->mutex); | 433 | mutex_unlock(&idev->mutex); |
| 435 | return 0; | 434 | return 0; |
| 436 | } | 435 | } |
| 437 | #endif | ||
| 438 | 436 | ||
| 439 | static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops, | 437 | static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops, |
| 440 | ucb1400_ts_suspend, ucb1400_ts_resume); | 438 | ucb1400_ts_suspend, ucb1400_ts_resume); |
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index 7ccaa1b12b05..32f8ac003936 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c | |||
| @@ -242,8 +242,7 @@ static int wacom_i2c_remove(struct i2c_client *client) | |||
| 242 | return 0; | 242 | return 0; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | #ifdef CONFIG_PM_SLEEP | 245 | static int __maybe_unused wacom_i2c_suspend(struct device *dev) |
| 246 | static int wacom_i2c_suspend(struct device *dev) | ||
| 247 | { | 246 | { |
| 248 | struct i2c_client *client = to_i2c_client(dev); | 247 | struct i2c_client *client = to_i2c_client(dev); |
| 249 | 248 | ||
| @@ -252,7 +251,7 @@ static int wacom_i2c_suspend(struct device *dev) | |||
| 252 | return 0; | 251 | return 0; |
| 253 | } | 252 | } |
| 254 | 253 | ||
| 255 | static int wacom_i2c_resume(struct device *dev) | 254 | static int __maybe_unused wacom_i2c_resume(struct device *dev) |
| 256 | { | 255 | { |
| 257 | struct i2c_client *client = to_i2c_client(dev); | 256 | struct i2c_client *client = to_i2c_client(dev); |
| 258 | 257 | ||
| @@ -260,7 +259,6 @@ static int wacom_i2c_resume(struct device *dev) | |||
| 260 | 259 | ||
| 261 | return 0; | 260 | return 0; |
| 262 | } | 261 | } |
| 263 | #endif | ||
| 264 | 262 | ||
| 265 | static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); | 263 | static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); |
| 266 | 264 | ||
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 8ba48f5eff7b..19880c7385e3 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c | |||
| @@ -602,8 +602,7 @@ static void zforce_input_close(struct input_dev *dev) | |||
| 602 | return; | 602 | return; |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | #ifdef CONFIG_PM_SLEEP | 605 | static int __maybe_unused zforce_suspend(struct device *dev) |
| 606 | static int zforce_suspend(struct device *dev) | ||
| 607 | { | 606 | { |
| 608 | struct i2c_client *client = to_i2c_client(dev); | 607 | struct i2c_client *client = to_i2c_client(dev); |
| 609 | struct zforce_ts *ts = i2c_get_clientdata(client); | 608 | struct zforce_ts *ts = i2c_get_clientdata(client); |
| @@ -648,7 +647,7 @@ unlock: | |||
| 648 | return ret; | 647 | return ret; |
| 649 | } | 648 | } |
| 650 | 649 | ||
| 651 | static int zforce_resume(struct device *dev) | 650 | static int __maybe_unused zforce_resume(struct device *dev) |
| 652 | { | 651 | { |
| 653 | struct i2c_client *client = to_i2c_client(dev); | 652 | struct i2c_client *client = to_i2c_client(dev); |
| 654 | struct zforce_ts *ts = i2c_get_clientdata(client); | 653 | struct zforce_ts *ts = i2c_get_clientdata(client); |
| @@ -685,7 +684,6 @@ unlock: | |||
| 685 | 684 | ||
| 686 | return ret; | 685 | return ret; |
| 687 | } | 686 | } |
| 688 | #endif | ||
| 689 | 687 | ||
| 690 | static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume); | 688 | static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume); |
| 691 | 689 | ||
