diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-15 19:43:53 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-15 19:43:53 -0500 |
| commit | 4937e2a6f939a41bf811378e80d71f68aa0950c6 (patch) | |
| tree | ed8ac843c96f01cd054542169afc968ec5d96189 /drivers/input/touchscreen | |
| parent | db0b2d01163cc3050eb52a979541e0d16553be48 (diff) | |
| parent | 42249094f79422fbf5ed4b54eeb48ff096809b8f (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"Updates for the input subsystem. You will get an new drivers for
Hyper-V synthetic keyboard and for Neonode zForce touchscreens, plus a
bunch of driver fixes and cleanups"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (49 commits)
Revert "Input: ALPS - add support for model found on Dell XT2"
arm: dts: am335x sk: add touchscreen support
Input: ti_am335x_tsc - fix spelling mistake in TSC/ADC DT binding
Input: cyttsp4 - replace IS_ERR and PTR_ERR with PTR_ERR_OR_ZERO
Input: mma8450 - add missing i2c_set_clientdata() in mma8450_probe()
Input: mpu3050 - add missing i2c_set_clientdata() in mpu3050_probe()
Input: tnetv107x-keypad - make irqs signed for error handling
Input: add driver for Neonode zForce based touchscreens
Input: sh_keysc - enable the driver on all ARM platforms
Input: remove a redundant max() call
Input: mousedev - allow disabling even without CONFIG_EXPERT
Input: allow deselecting serio drivers even without CONFIG_EXPERT
Input: i8042 - add PNP modaliases
Input: evdev - fall back to vmalloc for client event buffer
Input: cypress_ps2 - do not consider data bad if palm is detected
Input: cypress_ps2 - remove useless cast
Input: fix PWM-related undefined reference errors
Input: ALPS - change secondary device's name
Input: wacom - not all multi-interface devices support touch
Input: nspire-keypad - add missing clk_disable_unprepare() on error path
...
Diffstat (limited to 'drivers/input/touchscreen')
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ad7877.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ad7879-spi.c | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/cyttsp4_core.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/cyttsp4_spi.c | 5 | ||||
| -rw-r--r-- | drivers/input/touchscreen/egalax_ts.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/htcpen.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/st1232.c | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ti_am335x_tsc.c | 11 | ||||
| -rw-r--r-- | drivers/input/touchscreen/tsc2005.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/zforce_ts.c | 836 |
12 files changed, 862 insertions, 16 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index e09ec67957a3..00d1e547b211 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -919,4 +919,17 @@ config TOUCHSCREEN_TPS6507X | |||
| 919 | To compile this driver as a module, choose M here: the | 919 | To compile this driver as a module, choose M here: the |
| 920 | module will be called tps6507x_ts. | 920 | module will be called tps6507x_ts. |
| 921 | 921 | ||
| 922 | config TOUCHSCREEN_ZFORCE | ||
| 923 | tristate "Neonode zForce infrared touchscreens" | ||
| 924 | depends on I2C | ||
| 925 | depends on GPIOLIB | ||
| 926 | help | ||
| 927 | Say Y here if you have a touchscreen using the zforce | ||
| 928 | infraread technology from Neonode. | ||
| 929 | |||
| 930 | If unsure, say N. | ||
| 931 | |||
| 932 | To compile this driver as a module, choose M here: the | ||
| 933 | module will be called zforce_ts. | ||
| 934 | |||
| 922 | endif | 935 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index f5216c1bf53e..7587883b8d38 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -75,3 +75,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | |||
| 75 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 75 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
| 76 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 76 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
| 77 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o | 77 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o |
| 78 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o | ||
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index f3a174a83c82..69834dd3c313 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
| @@ -806,7 +806,6 @@ err_free_irq: | |||
| 806 | err_free_mem: | 806 | err_free_mem: |
| 807 | input_free_device(input_dev); | 807 | input_free_device(input_dev); |
| 808 | kfree(ts); | 808 | kfree(ts); |
| 809 | spi_set_drvdata(spi, NULL); | ||
| 810 | return err; | 809 | return err; |
| 811 | } | 810 | } |
| 812 | 811 | ||
| @@ -823,7 +822,6 @@ static int ad7877_remove(struct spi_device *spi) | |||
| 823 | kfree(ts); | 822 | kfree(ts); |
| 824 | 823 | ||
| 825 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | 824 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); |
| 826 | spi_set_drvdata(spi, NULL); | ||
| 827 | 825 | ||
| 828 | return 0; | 826 | return 0; |
| 829 | } | 827 | } |
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index 606da5bd6115..1a7b1143536e 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c | |||
| @@ -142,7 +142,6 @@ static int ad7879_spi_remove(struct spi_device *spi) | |||
| 142 | struct ad7879 *ts = spi_get_drvdata(spi); | 142 | struct ad7879 *ts = spi_get_drvdata(spi); |
| 143 | 143 | ||
| 144 | ad7879_remove(ts); | 144 | ad7879_remove(ts); |
| 145 | spi_set_drvdata(spi, NULL); | ||
| 146 | 145 | ||
| 147 | return 0; | 146 | return 0; |
| 148 | } | 147 | } |
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index d038575f49db..42d830efa316 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c | |||
| @@ -2113,7 +2113,6 @@ error_startup: | |||
| 2113 | error_request_irq: | 2113 | error_request_irq: |
| 2114 | if (cd->cpdata->init) | 2114 | if (cd->cpdata->init) |
| 2115 | cd->cpdata->init(cd->cpdata, 0, dev); | 2115 | cd->cpdata->init(cd->cpdata, 0, dev); |
| 2116 | dev_set_drvdata(dev, NULL); | ||
| 2117 | error_free_xfer: | 2116 | error_free_xfer: |
| 2118 | kfree(cd->xfer_buf); | 2117 | kfree(cd->xfer_buf); |
| 2119 | error_free_cd: | 2118 | error_free_cd: |
| @@ -2151,7 +2150,6 @@ int cyttsp4_remove(struct cyttsp4 *cd) | |||
| 2151 | free_irq(cd->irq, cd); | 2150 | free_irq(cd->irq, cd); |
| 2152 | if (cd->cpdata->init) | 2151 | if (cd->cpdata->init) |
| 2153 | cd->cpdata->init(cd->cpdata, 0, dev); | 2152 | cd->cpdata->init(cd->cpdata, 0, dev); |
| 2154 | dev_set_drvdata(dev, NULL); | ||
| 2155 | cyttsp4_free_si_ptrs(cd); | 2153 | cyttsp4_free_si_ptrs(cd); |
| 2156 | kfree(cd); | 2154 | kfree(cd); |
| 2157 | return 0; | 2155 | return 0; |
diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c index a71e1141d638..b19434cebbf6 100644 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ b/drivers/input/touchscreen/cyttsp4_spi.c | |||
| @@ -171,10 +171,7 @@ static int cyttsp4_spi_probe(struct spi_device *spi) | |||
| 171 | ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, | 171 | ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, |
| 172 | CY_SPI_DATA_BUF_SIZE); | 172 | CY_SPI_DATA_BUF_SIZE); |
| 173 | 173 | ||
| 174 | if (IS_ERR(ts)) | 174 | return PTR_ERR_OR_ZERO(ts); |
| 175 | return PTR_ERR(ts); | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | 175 | } |
| 179 | 176 | ||
| 180 | static int cyttsp4_spi_remove(struct spi_device *spi) | 177 | static int cyttsp4_spi_remove(struct spi_device *spi) |
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index ef5fcb0945e9..054d22583248 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c | |||
| @@ -273,7 +273,7 @@ static struct i2c_driver egalax_ts_driver = { | |||
| 273 | .name = "egalax_ts", | 273 | .name = "egalax_ts", |
| 274 | .owner = THIS_MODULE, | 274 | .owner = THIS_MODULE, |
| 275 | .pm = &egalax_ts_pm_ops, | 275 | .pm = &egalax_ts_pm_ops, |
| 276 | .of_match_table = of_match_ptr(egalax_ts_dt_ids), | 276 | .of_match_table = egalax_ts_dt_ids, |
| 277 | }, | 277 | }, |
| 278 | .id_table = egalax_ts_id, | 278 | .id_table = egalax_ts_id, |
| 279 | .probe = egalax_ts_probe, | 279 | .probe = egalax_ts_probe, |
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index 66500852341b..92e2243fb77d 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c | |||
| @@ -186,8 +186,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id) | |||
| 186 | release_region(HTCPEN_PORT_INIT, 1); | 186 | release_region(HTCPEN_PORT_INIT, 1); |
| 187 | release_region(HTCPEN_PORT_IRQ_CLEAR, 1); | 187 | release_region(HTCPEN_PORT_IRQ_CLEAR, 1); |
| 188 | 188 | ||
| 189 | dev_set_drvdata(dev, NULL); | ||
| 190 | |||
| 191 | return 0; | 189 | return 0; |
| 192 | } | 190 | } |
| 193 | 191 | ||
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 1740a2496371..2f03b2f289dd 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/of.h> | ||
| 27 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
| 28 | #include <linux/pm_qos.h> | 29 | #include <linux/pm_qos.h> |
| 29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 24e625c0b531..68beadaabceb 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
| @@ -354,9 +354,16 @@ static int titsc_parse_dt(struct platform_device *pdev, | |||
| 354 | if (err < 0) | 354 | if (err < 0) |
| 355 | return err; | 355 | return err; |
| 356 | 356 | ||
| 357 | err = of_property_read_u32(node, "ti,coordiante-readouts", | 357 | /* |
| 358 | * Try with the new binding first. If it fails, try again with | ||
| 359 | * bogus, miss-spelled version. | ||
| 360 | */ | ||
| 361 | err = of_property_read_u32(node, "ti,coordinate-readouts", | ||
| 358 | &ts_dev->coordinate_readouts); | 362 | &ts_dev->coordinate_readouts); |
| 359 | if (err < 0) | 363 | if (err < 0) |
| 364 | err = of_property_read_u32(node, "ti,coordiante-readouts", | ||
| 365 | &ts_dev->coordinate_readouts); | ||
| 366 | if (err < 0) | ||
| 360 | return err; | 367 | return err; |
| 361 | 368 | ||
| 362 | return of_property_read_u32_array(node, "ti,wire-config", | 369 | return of_property_read_u32_array(node, "ti,wire-config", |
| @@ -511,7 +518,7 @@ static struct platform_driver ti_tsc_driver = { | |||
| 511 | .name = "TI-am335x-tsc", | 518 | .name = "TI-am335x-tsc", |
| 512 | .owner = THIS_MODULE, | 519 | .owner = THIS_MODULE, |
| 513 | .pm = TITSC_PM_OPS, | 520 | .pm = TITSC_PM_OPS, |
| 514 | .of_match_table = of_match_ptr(ti_tsc_dt_ids), | 521 | .of_match_table = ti_tsc_dt_ids, |
| 515 | }, | 522 | }, |
| 516 | }; | 523 | }; |
| 517 | module_platform_driver(ti_tsc_driver); | 524 | module_platform_driver(ti_tsc_driver); |
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 7213e8b07e79..811353353917 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c | |||
| @@ -678,7 +678,6 @@ static int tsc2005_probe(struct spi_device *spi) | |||
| 678 | err_remove_sysfs: | 678 | err_remove_sysfs: |
| 679 | sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); | 679 | sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); |
| 680 | err_clear_drvdata: | 680 | err_clear_drvdata: |
| 681 | spi_set_drvdata(spi, NULL); | ||
| 682 | free_irq(spi->irq, ts); | 681 | free_irq(spi->irq, ts); |
| 683 | err_free_mem: | 682 | err_free_mem: |
| 684 | input_free_device(input_dev); | 683 | input_free_device(input_dev); |
| @@ -696,7 +695,6 @@ static int tsc2005_remove(struct spi_device *spi) | |||
| 696 | input_unregister_device(ts->idev); | 695 | input_unregister_device(ts->idev); |
| 697 | kfree(ts); | 696 | kfree(ts); |
| 698 | 697 | ||
| 699 | spi_set_drvdata(spi, NULL); | ||
| 700 | return 0; | 698 | return 0; |
| 701 | } | 699 | } |
| 702 | 700 | ||
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c new file mode 100644 index 000000000000..75762d6ff3ba --- /dev/null +++ b/drivers/input/touchscreen/zforce_ts.c | |||
| @@ -0,0 +1,836 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012-2013 MundoReader S.L. | ||
| 3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
| 4 | * | ||
| 5 | * based in parts on Nook zforce driver | ||
| 6 | * | ||
| 7 | * Copyright (C) 2010 Barnes & Noble, Inc. | ||
| 8 | * Author: Pieter Truter<ptruter@intrinsyc.com> | ||
| 9 | * | ||
| 10 | * This software is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2, as published by the Free Software Foundation, and | ||
| 12 | * may be copied, distributed, and modified under those terms. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/hrtimer.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/input.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/i2c.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/gpio.h> | ||
| 28 | #include <linux/device.h> | ||
| 29 | #include <linux/sysfs.h> | ||
| 30 | #include <linux/input/mt.h> | ||
| 31 | #include <linux/platform_data/zforce_ts.h> | ||
| 32 | |||
| 33 | #define WAIT_TIMEOUT msecs_to_jiffies(1000) | ||
| 34 | |||
| 35 | #define FRAME_START 0xee | ||
| 36 | |||
| 37 | /* Offsets of the different parts of the payload the controller sends */ | ||
| 38 | #define PAYLOAD_HEADER 0 | ||
| 39 | #define PAYLOAD_LENGTH 1 | ||
| 40 | #define PAYLOAD_BODY 2 | ||
| 41 | |||
| 42 | /* Response offsets */ | ||
| 43 | #define RESPONSE_ID 0 | ||
| 44 | #define RESPONSE_DATA 1 | ||
| 45 | |||
| 46 | /* Commands */ | ||
| 47 | #define COMMAND_DEACTIVATE 0x00 | ||
| 48 | #define COMMAND_INITIALIZE 0x01 | ||
| 49 | #define COMMAND_RESOLUTION 0x02 | ||
| 50 | #define COMMAND_SETCONFIG 0x03 | ||
| 51 | #define COMMAND_DATAREQUEST 0x04 | ||
| 52 | #define COMMAND_SCANFREQ 0x08 | ||
| 53 | #define COMMAND_STATUS 0X1e | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Responses the controller sends as a result of | ||
| 57 | * command requests | ||
| 58 | */ | ||
| 59 | #define RESPONSE_DEACTIVATE 0x00 | ||
| 60 | #define RESPONSE_INITIALIZE 0x01 | ||
| 61 | #define RESPONSE_RESOLUTION 0x02 | ||
| 62 | #define RESPONSE_SETCONFIG 0x03 | ||
| 63 | #define RESPONSE_SCANFREQ 0x08 | ||
| 64 | #define RESPONSE_STATUS 0X1e | ||
| 65 | |||
| 66 | /* | ||
| 67 | * Notifications are send by the touch controller without | ||
| 68 | * being requested by the driver and include for example | ||
| 69 | * touch indications | ||
| 70 | */ | ||
| 71 | #define NOTIFICATION_TOUCH 0x04 | ||
| 72 | #define NOTIFICATION_BOOTCOMPLETE 0x07 | ||
| 73 | #define NOTIFICATION_OVERRUN 0x25 | ||
| 74 | #define NOTIFICATION_PROXIMITY 0x26 | ||
| 75 | #define NOTIFICATION_INVALID_COMMAND 0xfe | ||
| 76 | |||
| 77 | #define ZFORCE_REPORT_POINTS 2 | ||
| 78 | #define ZFORCE_MAX_AREA 0xff | ||
| 79 | |||
| 80 | #define STATE_DOWN 0 | ||
| 81 | #define STATE_MOVE 1 | ||
| 82 | #define STATE_UP 2 | ||
| 83 | |||
| 84 | #define SETCONFIG_DUALTOUCH (1 << 0) | ||
| 85 | |||
| 86 | struct zforce_point { | ||
| 87 | int coord_x; | ||
| 88 | int coord_y; | ||
| 89 | int state; | ||
| 90 | int id; | ||
| 91 | int area_major; | ||
| 92 | int area_minor; | ||
| 93 | int orientation; | ||
| 94 | int pressure; | ||
| 95 | int prblty; | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* | ||
| 99 | * @client the i2c_client | ||
| 100 | * @input the input device | ||
| 101 | * @suspending in the process of going to suspend (don't emit wakeup | ||
| 102 | * events for commands executed to suspend the device) | ||
| 103 | * @suspended device suspended | ||
| 104 | * @access_mutex serialize i2c-access, to keep multipart reads together | ||
| 105 | * @command_done completion to wait for the command result | ||
| 106 | * @command_mutex serialize commands send to the ic | ||
| 107 | * @command_waiting the id of the command that that is currently waiting | ||
| 108 | * for a result | ||
| 109 | * @command_result returned result of the command | ||
| 110 | */ | ||
| 111 | struct zforce_ts { | ||
| 112 | struct i2c_client *client; | ||
| 113 | struct input_dev *input; | ||
| 114 | const struct zforce_ts_platdata *pdata; | ||
| 115 | char phys[32]; | ||
| 116 | |||
| 117 | bool suspending; | ||
| 118 | bool suspended; | ||
| 119 | bool boot_complete; | ||
| 120 | |||
| 121 | /* Firmware version information */ | ||
| 122 | u16 version_major; | ||
| 123 | u16 version_minor; | ||
| 124 | u16 version_build; | ||
| 125 | u16 version_rev; | ||
| 126 | |||
| 127 | struct mutex access_mutex; | ||
| 128 | |||
| 129 | struct completion command_done; | ||
| 130 | struct mutex command_mutex; | ||
| 131 | int command_waiting; | ||
| 132 | int command_result; | ||
| 133 | }; | ||
| 134 | |||
| 135 | static int zforce_command(struct zforce_ts *ts, u8 cmd) | ||
| 136 | { | ||
| 137 | struct i2c_client *client = ts->client; | ||
| 138 | char buf[3]; | ||
| 139 | int ret; | ||
| 140 | |||
| 141 | dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd); | ||
| 142 | |||
| 143 | buf[0] = FRAME_START; | ||
| 144 | buf[1] = 1; /* data size, command only */ | ||
| 145 | buf[2] = cmd; | ||
| 146 | |||
| 147 | mutex_lock(&ts->access_mutex); | ||
| 148 | ret = i2c_master_send(client, &buf[0], ARRAY_SIZE(buf)); | ||
| 149 | mutex_unlock(&ts->access_mutex); | ||
| 150 | if (ret < 0) { | ||
| 151 | dev_err(&client->dev, "i2c send data request error: %d\n", ret); | ||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int zforce_send_wait(struct zforce_ts *ts, const char *buf, int len) | ||
| 159 | { | ||
| 160 | struct i2c_client *client = ts->client; | ||
| 161 | int ret; | ||
| 162 | |||
| 163 | ret = mutex_trylock(&ts->command_mutex); | ||
| 164 | if (!ret) { | ||
| 165 | dev_err(&client->dev, "already waiting for a command\n"); | ||
| 166 | return -EBUSY; | ||
| 167 | } | ||
| 168 | |||
| 169 | dev_dbg(&client->dev, "sending %d bytes for command 0x%x\n", | ||
| 170 | buf[1], buf[2]); | ||
| 171 | |||
| 172 | ts->command_waiting = buf[2]; | ||
| 173 | |||
| 174 | mutex_lock(&ts->access_mutex); | ||
| 175 | ret = i2c_master_send(client, buf, len); | ||
| 176 | mutex_unlock(&ts->access_mutex); | ||
| 177 | if (ret < 0) { | ||
| 178 | dev_err(&client->dev, "i2c send data request error: %d\n", ret); | ||
| 179 | goto unlock; | ||
| 180 | } | ||
| 181 | |||
| 182 | dev_dbg(&client->dev, "waiting for result for command 0x%x\n", buf[2]); | ||
| 183 | |||
| 184 | if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) { | ||
| 185 | ret = -ETIME; | ||
| 186 | goto unlock; | ||
| 187 | } | ||
| 188 | |||
| 189 | ret = ts->command_result; | ||
| 190 | |||
| 191 | unlock: | ||
| 192 | mutex_unlock(&ts->command_mutex); | ||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | static int zforce_command_wait(struct zforce_ts *ts, u8 cmd) | ||
| 197 | { | ||
| 198 | struct i2c_client *client = ts->client; | ||
| 199 | char buf[3]; | ||
| 200 | int ret; | ||
| 201 | |||
| 202 | dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd); | ||
| 203 | |||
| 204 | buf[0] = FRAME_START; | ||
| 205 | buf[1] = 1; /* data size, command only */ | ||
| 206 | buf[2] = cmd; | ||
| 207 | |||
| 208 | ret = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); | ||
| 209 | if (ret < 0) { | ||
| 210 | dev_err(&client->dev, "i2c send data request error: %d\n", ret); | ||
| 211 | return ret; | ||
| 212 | } | ||
| 213 | |||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int zforce_resolution(struct zforce_ts *ts, u16 x, u16 y) | ||
| 218 | { | ||
| 219 | struct i2c_client *client = ts->client; | ||
| 220 | char buf[7] = { FRAME_START, 5, COMMAND_RESOLUTION, | ||
| 221 | (x & 0xff), ((x >> 8) & 0xff), | ||
| 222 | (y & 0xff), ((y >> 8) & 0xff) }; | ||
| 223 | |||
| 224 | dev_dbg(&client->dev, "set resolution to (%d,%d)\n", x, y); | ||
| 225 | |||
| 226 | return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); | ||
| 227 | } | ||
| 228 | |||
| 229 | static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger, | ||
| 230 | u16 stylus) | ||
| 231 | { | ||
| 232 | struct i2c_client *client = ts->client; | ||
| 233 | char buf[9] = { FRAME_START, 7, COMMAND_SCANFREQ, | ||
| 234 | (idle & 0xff), ((idle >> 8) & 0xff), | ||
| 235 | (finger & 0xff), ((finger >> 8) & 0xff), | ||
| 236 | (stylus & 0xff), ((stylus >> 8) & 0xff) }; | ||
| 237 | |||
| 238 | dev_dbg(&client->dev, "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n", | ||
| 239 | idle, finger, stylus); | ||
| 240 | |||
| 241 | return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); | ||
| 242 | } | ||
| 243 | |||
| 244 | static int zforce_setconfig(struct zforce_ts *ts, char b1) | ||
| 245 | { | ||
| 246 | struct i2c_client *client = ts->client; | ||
| 247 | char buf[7] = { FRAME_START, 5, COMMAND_SETCONFIG, | ||
| 248 | b1, 0, 0, 0 }; | ||
| 249 | |||
| 250 | dev_dbg(&client->dev, "set config to (%d)\n", b1); | ||
| 251 | |||
| 252 | return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); | ||
| 253 | } | ||
| 254 | |||
| 255 | static int zforce_start(struct zforce_ts *ts) | ||
| 256 | { | ||
| 257 | struct i2c_client *client = ts->client; | ||
| 258 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | ||
| 259 | int ret; | ||
| 260 | |||
| 261 | dev_dbg(&client->dev, "starting device\n"); | ||
| 262 | |||
| 263 | ret = zforce_command_wait(ts, COMMAND_INITIALIZE); | ||
| 264 | if (ret) { | ||
| 265 | dev_err(&client->dev, "Unable to initialize, %d\n", ret); | ||
| 266 | return ret; | ||
| 267 | } | ||
| 268 | |||
| 269 | ret = zforce_resolution(ts, pdata->x_max, pdata->y_max); | ||
| 270 | if (ret) { | ||
| 271 | dev_err(&client->dev, "Unable to set resolution, %d\n", ret); | ||
| 272 | goto error; | ||
| 273 | } | ||
| 274 | |||
| 275 | ret = zforce_scan_frequency(ts, 10, 50, 50); | ||
| 276 | if (ret) { | ||
| 277 | dev_err(&client->dev, "Unable to set scan frequency, %d\n", | ||
| 278 | ret); | ||
| 279 | goto error; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (zforce_setconfig(ts, SETCONFIG_DUALTOUCH)) { | ||
| 283 | dev_err(&client->dev, "Unable to set config\n"); | ||
| 284 | goto error; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* start sending touch events */ | ||
| 288 | ret = zforce_command(ts, COMMAND_DATAREQUEST); | ||
| 289 | if (ret) { | ||
| 290 | dev_err(&client->dev, "Unable to request data\n"); | ||
| 291 | goto error; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * Per NN, initial cal. take max. of 200msec. | ||
| 296 | * Allow time to complete this calibration | ||
| 297 | */ | ||
| 298 | msleep(200); | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | |||
| 302 | error: | ||
| 303 | zforce_command_wait(ts, COMMAND_DEACTIVATE); | ||
| 304 | return ret; | ||
| 305 | } | ||
| 306 | |||
| 307 | static int zforce_stop(struct zforce_ts *ts) | ||
| 308 | { | ||
| 309 | struct i2c_client *client = ts->client; | ||
| 310 | int ret; | ||
| 311 | |||
| 312 | dev_dbg(&client->dev, "stopping device\n"); | ||
| 313 | |||
| 314 | /* Deactivates touch sensing and puts the device into sleep. */ | ||
| 315 | ret = zforce_command_wait(ts, COMMAND_DEACTIVATE); | ||
| 316 | if (ret != 0) { | ||
| 317 | dev_err(&client->dev, "could not deactivate device, %d\n", | ||
| 318 | ret); | ||
| 319 | return ret; | ||
| 320 | } | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) | ||
| 326 | { | ||
| 327 | struct i2c_client *client = ts->client; | ||
| 328 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | ||
| 329 | struct zforce_point point; | ||
| 330 | int count, i, num = 0; | ||
| 331 | |||
| 332 | count = payload[0]; | ||
| 333 | if (count > ZFORCE_REPORT_POINTS) { | ||
| 334 | dev_warn(&client->dev, "to many coordinates %d, expected max %d\n", | ||
| 335 | count, ZFORCE_REPORT_POINTS); | ||
| 336 | count = ZFORCE_REPORT_POINTS; | ||
| 337 | } | ||
| 338 | |||
| 339 | for (i = 0; i < count; i++) { | ||
| 340 | point.coord_x = | ||
| 341 | payload[9 * i + 2] << 8 | payload[9 * i + 1]; | ||
| 342 | point.coord_y = | ||
| 343 | payload[9 * i + 4] << 8 | payload[9 * i + 3]; | ||
| 344 | |||
| 345 | if (point.coord_x > pdata->x_max || | ||
| 346 | point.coord_y > pdata->y_max) { | ||
| 347 | dev_warn(&client->dev, "coordinates (%d,%d) invalid\n", | ||
| 348 | point.coord_x, point.coord_y); | ||
| 349 | point.coord_x = point.coord_y = 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | point.state = payload[9 * i + 5] & 0x03; | ||
| 353 | point.id = (payload[9 * i + 5] & 0xfc) >> 2; | ||
| 354 | |||
| 355 | /* determine touch major, minor and orientation */ | ||
| 356 | point.area_major = max(payload[9 * i + 6], | ||
| 357 | payload[9 * i + 7]); | ||
| 358 | point.area_minor = min(payload[9 * i + 6], | ||
| 359 | payload[9 * i + 7]); | ||
| 360 | point.orientation = payload[9 * i + 6] > payload[9 * i + 7]; | ||
| 361 | |||
| 362 | point.pressure = payload[9 * i + 8]; | ||
| 363 | point.prblty = payload[9 * i + 9]; | ||
| 364 | |||
| 365 | dev_dbg(&client->dev, | ||
| 366 | "point %d/%d: state %d, id %d, pressure %d, prblty %d, x %d, y %d, amajor %d, aminor %d, ori %d\n", | ||
| 367 | i, count, point.state, point.id, | ||
| 368 | point.pressure, point.prblty, | ||
| 369 | point.coord_x, point.coord_y, | ||
| 370 | point.area_major, point.area_minor, | ||
| 371 | point.orientation); | ||
| 372 | |||
| 373 | /* the zforce id starts with "1", so needs to be decreased */ | ||
| 374 | input_mt_slot(ts->input, point.id - 1); | ||
| 375 | |||
| 376 | input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, | ||
| 377 | point.state != STATE_UP); | ||
| 378 | |||
| 379 | if (point.state != STATE_UP) { | ||
| 380 | input_report_abs(ts->input, ABS_MT_POSITION_X, | ||
| 381 | point.coord_x); | ||
| 382 | input_report_abs(ts->input, ABS_MT_POSITION_Y, | ||
| 383 | point.coord_y); | ||
| 384 | input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, | ||
| 385 | point.area_major); | ||
| 386 | input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, | ||
| 387 | point.area_minor); | ||
| 388 | input_report_abs(ts->input, ABS_MT_ORIENTATION, | ||
| 389 | point.orientation); | ||
| 390 | num++; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | input_mt_sync_frame(ts->input); | ||
| 395 | |||
| 396 | input_mt_report_finger_count(ts->input, num); | ||
| 397 | |||
| 398 | input_sync(ts->input); | ||
| 399 | |||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int zforce_read_packet(struct zforce_ts *ts, u8 *buf) | ||
| 404 | { | ||
| 405 | struct i2c_client *client = ts->client; | ||
| 406 | int ret; | ||
| 407 | |||
| 408 | mutex_lock(&ts->access_mutex); | ||
| 409 | |||
| 410 | /* read 2 byte message header */ | ||
| 411 | ret = i2c_master_recv(client, buf, 2); | ||
| 412 | if (ret < 0) { | ||
| 413 | dev_err(&client->dev, "error reading header: %d\n", ret); | ||
| 414 | goto unlock; | ||
| 415 | } | ||
| 416 | |||
| 417 | if (buf[PAYLOAD_HEADER] != FRAME_START) { | ||
| 418 | dev_err(&client->dev, "invalid frame start: %d\n", buf[0]); | ||
| 419 | ret = -EIO; | ||
| 420 | goto unlock; | ||
| 421 | } | ||
| 422 | |||
| 423 | if (buf[PAYLOAD_LENGTH] <= 0 || buf[PAYLOAD_LENGTH] > 255) { | ||
| 424 | dev_err(&client->dev, "invalid payload length: %d\n", | ||
| 425 | buf[PAYLOAD_LENGTH]); | ||
| 426 | ret = -EIO; | ||
| 427 | goto unlock; | ||
| 428 | } | ||
| 429 | |||
| 430 | /* read the message */ | ||
| 431 | ret = i2c_master_recv(client, &buf[PAYLOAD_BODY], buf[PAYLOAD_LENGTH]); | ||
| 432 | if (ret < 0) { | ||
| 433 | dev_err(&client->dev, "error reading payload: %d\n", ret); | ||
| 434 | goto unlock; | ||
| 435 | } | ||
| 436 | |||
| 437 | dev_dbg(&client->dev, "read %d bytes for response command 0x%x\n", | ||
| 438 | buf[PAYLOAD_LENGTH], buf[PAYLOAD_BODY]); | ||
| 439 | |||
| 440 | unlock: | ||
| 441 | mutex_unlock(&ts->access_mutex); | ||
| 442 | return ret; | ||
| 443 | } | ||
| 444 | |||
| 445 | static void zforce_complete(struct zforce_ts *ts, int cmd, int result) | ||
| 446 | { | ||
| 447 | struct i2c_client *client = ts->client; | ||
| 448 | |||
| 449 | if (ts->command_waiting == cmd) { | ||
| 450 | dev_dbg(&client->dev, "completing command 0x%x\n", cmd); | ||
| 451 | ts->command_result = result; | ||
| 452 | complete(&ts->command_done); | ||
| 453 | } else { | ||
| 454 | dev_dbg(&client->dev, "command %d not for us\n", cmd); | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 458 | static irqreturn_t zforce_interrupt(int irq, void *dev_id) | ||
| 459 | { | ||
| 460 | struct zforce_ts *ts = dev_id; | ||
| 461 | struct i2c_client *client = ts->client; | ||
| 462 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | ||
| 463 | int ret; | ||
| 464 | u8 payload_buffer[512]; | ||
| 465 | u8 *payload; | ||
| 466 | |||
| 467 | /* | ||
| 468 | * When suspended, emit a wakeup signal if necessary and return. | ||
| 469 | * Due to the level-interrupt we will get re-triggered later. | ||
| 470 | */ | ||
| 471 | if (ts->suspended) { | ||
| 472 | if (device_may_wakeup(&client->dev)) | ||
| 473 | pm_wakeup_event(&client->dev, 500); | ||
| 474 | msleep(20); | ||
| 475 | return IRQ_HANDLED; | ||
| 476 | } | ||
| 477 | |||
| 478 | dev_dbg(&client->dev, "handling interrupt\n"); | ||
| 479 | |||
| 480 | /* Don't emit wakeup events from commands run by zforce_suspend */ | ||
| 481 | if (!ts->suspending && device_may_wakeup(&client->dev)) | ||
| 482 | pm_stay_awake(&client->dev); | ||
| 483 | |||
| 484 | while (!gpio_get_value(pdata->gpio_int)) { | ||
| 485 | ret = zforce_read_packet(ts, payload_buffer); | ||
| 486 | if (ret < 0) { | ||
| 487 | dev_err(&client->dev, "could not read packet, ret: %d\n", | ||
| 488 | ret); | ||
| 489 | break; | ||
| 490 | } | ||
| 491 | |||
| 492 | payload = &payload_buffer[PAYLOAD_BODY]; | ||
| 493 | |||
| 494 | switch (payload[RESPONSE_ID]) { | ||
| 495 | case NOTIFICATION_TOUCH: | ||
| 496 | /* | ||
| 497 | * Always report touch-events received while | ||
| 498 | * suspending, when being a wakeup source | ||
| 499 | */ | ||
| 500 | if (ts->suspending && device_may_wakeup(&client->dev)) | ||
| 501 | pm_wakeup_event(&client->dev, 500); | ||
| 502 | zforce_touch_event(ts, &payload[RESPONSE_DATA]); | ||
| 503 | break; | ||
| 504 | |||
| 505 | case NOTIFICATION_BOOTCOMPLETE: | ||
| 506 | ts->boot_complete = payload[RESPONSE_DATA]; | ||
| 507 | zforce_complete(ts, payload[RESPONSE_ID], 0); | ||
| 508 | break; | ||
| 509 | |||
| 510 | case RESPONSE_INITIALIZE: | ||
| 511 | case RESPONSE_DEACTIVATE: | ||
| 512 | case RESPONSE_SETCONFIG: | ||
| 513 | case RESPONSE_RESOLUTION: | ||
| 514 | case RESPONSE_SCANFREQ: | ||
| 515 | zforce_complete(ts, payload[RESPONSE_ID], | ||
| 516 | payload[RESPONSE_DATA]); | ||
| 517 | break; | ||
| 518 | |||
| 519 | case RESPONSE_STATUS: | ||
| 520 | /* | ||
| 521 | * Version Payload Results | ||
| 522 | * [2:major] [2:minor] [2:build] [2:rev] | ||
| 523 | */ | ||
| 524 | ts->version_major = (payload[RESPONSE_DATA + 1] << 8) | | ||
| 525 | payload[RESPONSE_DATA]; | ||
| 526 | ts->version_minor = (payload[RESPONSE_DATA + 3] << 8) | | ||
| 527 | payload[RESPONSE_DATA + 2]; | ||
| 528 | ts->version_build = (payload[RESPONSE_DATA + 5] << 8) | | ||
| 529 | payload[RESPONSE_DATA + 4]; | ||
| 530 | ts->version_rev = (payload[RESPONSE_DATA + 7] << 8) | | ||
| 531 | payload[RESPONSE_DATA + 6]; | ||
| 532 | dev_dbg(&ts->client->dev, "Firmware Version %04x:%04x %04x:%04x\n", | ||
| 533 | ts->version_major, ts->version_minor, | ||
| 534 | ts->version_build, ts->version_rev); | ||
| 535 | |||
| 536 | zforce_complete(ts, payload[RESPONSE_ID], 0); | ||
| 537 | break; | ||
| 538 | |||
| 539 | case NOTIFICATION_INVALID_COMMAND: | ||
| 540 | dev_err(&ts->client->dev, "invalid command: 0x%x\n", | ||
| 541 | payload[RESPONSE_DATA]); | ||
| 542 | break; | ||
| 543 | |||
| 544 | default: | ||
| 545 | dev_err(&ts->client->dev, "unrecognized response id: 0x%x\n", | ||
| 546 | payload[RESPONSE_ID]); | ||
| 547 | break; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | |||
| 551 | if (!ts->suspending && device_may_wakeup(&client->dev)) | ||
| 552 | pm_relax(&client->dev); | ||
| 553 | |||
| 554 | dev_dbg(&client->dev, "finished interrupt\n"); | ||
| 555 | |||
| 556 | return IRQ_HANDLED; | ||
| 557 | } | ||
| 558 | |||
| 559 | static int zforce_input_open(struct input_dev *dev) | ||
| 560 | { | ||
| 561 | struct zforce_ts *ts = input_get_drvdata(dev); | ||
| 562 | int ret; | ||
| 563 | |||
| 564 | ret = zforce_start(ts); | ||
| 565 | if (ret) | ||
| 566 | return ret; | ||
| 567 | |||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | static void zforce_input_close(struct input_dev *dev) | ||
| 572 | { | ||
| 573 | struct zforce_ts *ts = input_get_drvdata(dev); | ||
| 574 | struct i2c_client *client = ts->client; | ||
| 575 | int ret; | ||
| 576 | |||
| 577 | ret = zforce_stop(ts); | ||
| 578 | if (ret) | ||
| 579 | dev_warn(&client->dev, "stopping zforce failed\n"); | ||
| 580 | |||
| 581 | return; | ||
| 582 | } | ||
| 583 | |||
| 584 | #ifdef CONFIG_PM_SLEEP | ||
| 585 | static int zforce_suspend(struct device *dev) | ||
| 586 | { | ||
| 587 | struct i2c_client *client = to_i2c_client(dev); | ||
| 588 | struct zforce_ts *ts = i2c_get_clientdata(client); | ||
| 589 | struct input_dev *input = ts->input; | ||
| 590 | int ret = 0; | ||
| 591 | |||
| 592 | mutex_lock(&input->mutex); | ||
| 593 | ts->suspending = true; | ||
| 594 | |||
| 595 | /* | ||
| 596 | * When configured as a wakeup source device should always wake | ||
| 597 | * the system, therefore start device if necessary. | ||
| 598 | */ | ||
| 599 | if (device_may_wakeup(&client->dev)) { | ||
| 600 | dev_dbg(&client->dev, "suspend while being a wakeup source\n"); | ||
| 601 | |||
| 602 | /* Need to start device, if not open, to be a wakeup source. */ | ||
| 603 | if (!input->users) { | ||
| 604 | ret = zforce_start(ts); | ||
| 605 | if (ret) | ||
| 606 | goto unlock; | ||
| 607 | } | ||
| 608 | |||
| 609 | enable_irq_wake(client->irq); | ||
| 610 | } else if (input->users) { | ||
| 611 | dev_dbg(&client->dev, "suspend without being a wakeup source\n"); | ||
| 612 | |||
| 613 | ret = zforce_stop(ts); | ||
| 614 | if (ret) | ||
| 615 | goto unlock; | ||
| 616 | |||
| 617 | disable_irq(client->irq); | ||
| 618 | } | ||
| 619 | |||
| 620 | ts->suspended = true; | ||
| 621 | |||
| 622 | unlock: | ||
| 623 | ts->suspending = false; | ||
| 624 | mutex_unlock(&input->mutex); | ||
| 625 | |||
| 626 | return ret; | ||
| 627 | } | ||
| 628 | |||
| 629 | static int zforce_resume(struct device *dev) | ||
| 630 | { | ||
| 631 | struct i2c_client *client = to_i2c_client(dev); | ||
| 632 | struct zforce_ts *ts = i2c_get_clientdata(client); | ||
| 633 | struct input_dev *input = ts->input; | ||
| 634 | int ret = 0; | ||
| 635 | |||
| 636 | mutex_lock(&input->mutex); | ||
| 637 | |||
| 638 | ts->suspended = false; | ||
| 639 | |||
| 640 | if (device_may_wakeup(&client->dev)) { | ||
| 641 | dev_dbg(&client->dev, "resume from being a wakeup source\n"); | ||
| 642 | |||
| 643 | disable_irq_wake(client->irq); | ||
| 644 | |||
| 645 | /* need to stop device if it was not open on suspend */ | ||
| 646 | if (!input->users) { | ||
| 647 | ret = zforce_stop(ts); | ||
| 648 | if (ret) | ||
| 649 | goto unlock; | ||
| 650 | } | ||
| 651 | } else if (input->users) { | ||
| 652 | dev_dbg(&client->dev, "resume without being a wakeup source\n"); | ||
| 653 | |||
| 654 | enable_irq(client->irq); | ||
| 655 | |||
| 656 | ret = zforce_start(ts); | ||
| 657 | if (ret < 0) | ||
| 658 | goto unlock; | ||
| 659 | } | ||
| 660 | |||
| 661 | unlock: | ||
| 662 | mutex_unlock(&input->mutex); | ||
| 663 | |||
| 664 | return ret; | ||
| 665 | } | ||
| 666 | #endif | ||
| 667 | |||
| 668 | static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume); | ||
| 669 | |||
| 670 | static void zforce_reset(void *data) | ||
| 671 | { | ||
| 672 | struct zforce_ts *ts = data; | ||
| 673 | |||
| 674 | gpio_set_value(ts->pdata->gpio_rst, 0); | ||
| 675 | } | ||
| 676 | |||
| 677 | static int zforce_probe(struct i2c_client *client, | ||
| 678 | const struct i2c_device_id *id) | ||
| 679 | { | ||
| 680 | const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); | ||
| 681 | struct zforce_ts *ts; | ||
| 682 | struct input_dev *input_dev; | ||
| 683 | int ret; | ||
| 684 | |||
| 685 | if (!pdata) | ||
| 686 | return -EINVAL; | ||
| 687 | |||
| 688 | ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); | ||
| 689 | if (!ts) | ||
| 690 | return -ENOMEM; | ||
| 691 | |||
| 692 | ret = devm_gpio_request_one(&client->dev, pdata->gpio_int, GPIOF_IN, | ||
| 693 | "zforce_ts_int"); | ||
| 694 | if (ret) { | ||
| 695 | dev_err(&client->dev, "request of gpio %d failed, %d\n", | ||
| 696 | pdata->gpio_int, ret); | ||
| 697 | return ret; | ||
| 698 | } | ||
| 699 | |||
| 700 | ret = devm_gpio_request_one(&client->dev, pdata->gpio_rst, | ||
| 701 | GPIOF_OUT_INIT_LOW, "zforce_ts_rst"); | ||
| 702 | if (ret) { | ||
| 703 | dev_err(&client->dev, "request of gpio %d failed, %d\n", | ||
| 704 | pdata->gpio_rst, ret); | ||
| 705 | return ret; | ||
| 706 | } | ||
| 707 | |||
| 708 | ret = devm_add_action(&client->dev, zforce_reset, ts); | ||
| 709 | if (ret) { | ||
| 710 | dev_err(&client->dev, "failed to register reset action, %d\n", | ||
| 711 | ret); | ||
| 712 | return ret; | ||
| 713 | } | ||
| 714 | |||
| 715 | snprintf(ts->phys, sizeof(ts->phys), | ||
| 716 | "%s/input0", dev_name(&client->dev)); | ||
| 717 | |||
| 718 | input_dev = devm_input_allocate_device(&client->dev); | ||
| 719 | if (!input_dev) { | ||
| 720 | dev_err(&client->dev, "could not allocate input device\n"); | ||
| 721 | return -ENOMEM; | ||
| 722 | } | ||
| 723 | |||
| 724 | mutex_init(&ts->access_mutex); | ||
| 725 | mutex_init(&ts->command_mutex); | ||
| 726 | |||
| 727 | ts->pdata = pdata; | ||
| 728 | ts->client = client; | ||
| 729 | ts->input = input_dev; | ||
| 730 | |||
| 731 | input_dev->name = "Neonode zForce touchscreen"; | ||
| 732 | input_dev->phys = ts->phys; | ||
| 733 | input_dev->id.bustype = BUS_I2C; | ||
| 734 | |||
| 735 | input_dev->open = zforce_input_open; | ||
| 736 | input_dev->close = zforce_input_close; | ||
| 737 | |||
| 738 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 739 | __set_bit(EV_SYN, input_dev->evbit); | ||
| 740 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 741 | |||
| 742 | /* For multi touch */ | ||
| 743 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, | ||
| 744 | pdata->x_max, 0, 0); | ||
| 745 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, | ||
| 746 | pdata->y_max, 0, 0); | ||
| 747 | |||
| 748 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, | ||
| 749 | ZFORCE_MAX_AREA, 0, 0); | ||
| 750 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, | ||
| 751 | ZFORCE_MAX_AREA, 0, 0); | ||
| 752 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); | ||
| 753 | input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, INPUT_MT_DIRECT); | ||
| 754 | |||
| 755 | input_set_drvdata(ts->input, ts); | ||
| 756 | |||
| 757 | init_completion(&ts->command_done); | ||
| 758 | |||
| 759 | /* | ||
| 760 | * The zforce pulls the interrupt low when it has data ready. | ||
| 761 | * After it is triggered the isr thread runs until all the available | ||
| 762 | * packets have been read and the interrupt is high again. | ||
| 763 | * Therefore we can trigger the interrupt anytime it is low and do | ||
| 764 | * not need to limit it to the interrupt edge. | ||
| 765 | */ | ||
| 766 | ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, | ||
| 767 | zforce_interrupt, | ||
| 768 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 769 | input_dev->name, ts); | ||
| 770 | if (ret) { | ||
| 771 | dev_err(&client->dev, "irq %d request failed\n", client->irq); | ||
| 772 | return ret; | ||
| 773 | } | ||
| 774 | |||
| 775 | i2c_set_clientdata(client, ts); | ||
| 776 | |||
| 777 | /* let the controller boot */ | ||
| 778 | gpio_set_value(pdata->gpio_rst, 1); | ||
| 779 | |||
| 780 | ts->command_waiting = NOTIFICATION_BOOTCOMPLETE; | ||
| 781 | if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) | ||
| 782 | dev_warn(&client->dev, "bootcomplete timed out\n"); | ||
| 783 | |||
| 784 | /* need to start device to get version information */ | ||
| 785 | ret = zforce_command_wait(ts, COMMAND_INITIALIZE); | ||
| 786 | if (ret) { | ||
| 787 | dev_err(&client->dev, "unable to initialize, %d\n", ret); | ||
| 788 | return ret; | ||
| 789 | } | ||
| 790 | |||
| 791 | /* this gets the firmware version among other informations */ | ||
| 792 | ret = zforce_command_wait(ts, COMMAND_STATUS); | ||
| 793 | if (ret < 0) { | ||
| 794 | dev_err(&client->dev, "couldn't get status, %d\n", ret); | ||
| 795 | zforce_stop(ts); | ||
| 796 | return ret; | ||
| 797 | } | ||
| 798 | |||
| 799 | /* stop device and put it into sleep until it is opened */ | ||
| 800 | ret = zforce_stop(ts); | ||
| 801 | if (ret < 0) | ||
| 802 | return ret; | ||
| 803 | |||
| 804 | device_set_wakeup_capable(&client->dev, true); | ||
| 805 | |||
| 806 | ret = input_register_device(input_dev); | ||
| 807 | if (ret) { | ||
| 808 | dev_err(&client->dev, "could not register input device, %d\n", | ||
| 809 | ret); | ||
| 810 | return ret; | ||
| 811 | } | ||
| 812 | |||
| 813 | return 0; | ||
| 814 | } | ||
| 815 | |||
| 816 | static struct i2c_device_id zforce_idtable[] = { | ||
| 817 | { "zforce-ts", 0 }, | ||
| 818 | { } | ||
| 819 | }; | ||
| 820 | MODULE_DEVICE_TABLE(i2c, zforce_idtable); | ||
| 821 | |||
| 822 | static struct i2c_driver zforce_driver = { | ||
| 823 | .driver = { | ||
| 824 | .owner = THIS_MODULE, | ||
| 825 | .name = "zforce-ts", | ||
| 826 | .pm = &zforce_pm_ops, | ||
| 827 | }, | ||
| 828 | .probe = zforce_probe, | ||
| 829 | .id_table = zforce_idtable, | ||
| 830 | }; | ||
| 831 | |||
| 832 | module_i2c_driver(zforce_driver); | ||
| 833 | |||
| 834 | MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); | ||
| 835 | MODULE_DESCRIPTION("zForce TouchScreen Driver"); | ||
| 836 | MODULE_LICENSE("GPL"); | ||
