diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-11-14 20:38:05 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2013-11-14 20:38:05 -0500 |
| commit | 42249094f79422fbf5ed4b54eeb48ff096809b8f (patch) | |
| tree | 91e6850c8c7e8cc284cf8bb6363f8662f84011f4 /drivers/input/touchscreen | |
| parent | 936816161978ca716a56c5e553c68f25972b1e3a (diff) | |
| parent | 2c027b7c48a888ab173ba45babb4525e278375d9 (diff) | |
Merge branch 'next' into for-linus
Merge first round of changes for 3.13 merge window.
Diffstat (limited to 'drivers/input/touchscreen')
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 17 | ||||
| -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 | 295 | ||||
| -rw-r--r-- | drivers/input/touchscreen/tsc2005.c | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/zforce_ts.c | 836 |
12 files changed, 1065 insertions, 101 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 3b9758b5f4d7..00d1e547b211 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -389,7 +389,7 @@ config TOUCHSCREEN_MCS5000 | |||
| 389 | 389 | ||
| 390 | config TOUCHSCREEN_MMS114 | 390 | config TOUCHSCREEN_MMS114 |
| 391 | tristate "MELFAS MMS114 touchscreen" | 391 | tristate "MELFAS MMS114 touchscreen" |
| 392 | depends on I2C && GENERIC_HARDIRQS | 392 | depends on I2C |
| 393 | help | 393 | help |
| 394 | Say Y here if you have the MELFAS MMS114 touchscreen controller | 394 | Say Y here if you have the MELFAS MMS114 touchscreen controller |
| 395 | chip in your system. | 395 | chip in your system. |
| @@ -845,7 +845,7 @@ config TOUCHSCREEN_TSC_SERIO | |||
| 845 | 845 | ||
| 846 | config TOUCHSCREEN_TSC2005 | 846 | config TOUCHSCREEN_TSC2005 |
| 847 | tristate "TSC2005 based touchscreens" | 847 | tristate "TSC2005 based touchscreens" |
| 848 | depends on SPI_MASTER && GENERIC_HARDIRQS | 848 | depends on SPI_MASTER |
| 849 | help | 849 | help |
| 850 | Say Y here if you have a TSC2005 based touchscreen. | 850 | Say Y here if you have a TSC2005 based touchscreen. |
| 851 | 851 | ||
| @@ -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 50fb1293874e..ad7564296ddf 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
| @@ -24,8 +24,9 @@ | |||
| 24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/input/ti_am335x_tsc.h> | ||
| 28 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 28 | #include <linux/of.h> | ||
| 29 | #include <linux/of_device.h> | ||
| 29 | 30 | ||
| 30 | #include <linux/mfd/ti_am335x_tscadc.h> | 31 | #include <linux/mfd/ti_am335x_tscadc.h> |
| 31 | 32 | ||
| @@ -33,6 +34,13 @@ | |||
| 33 | #define SEQ_SETTLE 275 | 34 | #define SEQ_SETTLE 275 |
| 34 | #define MAX_12BIT ((1 << 12) - 1) | 35 | #define MAX_12BIT ((1 << 12) - 1) |
| 35 | 36 | ||
| 37 | static const int config_pins[] = { | ||
| 38 | STEPCONFIG_XPP, | ||
| 39 | STEPCONFIG_XNN, | ||
| 40 | STEPCONFIG_YPP, | ||
| 41 | STEPCONFIG_YNN, | ||
| 42 | }; | ||
| 43 | |||
| 36 | struct titsc { | 44 | struct titsc { |
| 37 | struct input_dev *input; | 45 | struct input_dev *input; |
| 38 | struct ti_tscadc_dev *mfd_tscadc; | 46 | struct ti_tscadc_dev *mfd_tscadc; |
| @@ -40,7 +48,10 @@ struct titsc { | |||
| 40 | unsigned int wires; | 48 | unsigned int wires; |
| 41 | unsigned int x_plate_resistance; | 49 | unsigned int x_plate_resistance; |
| 42 | bool pen_down; | 50 | bool pen_down; |
| 43 | int steps_to_configure; | 51 | int coordinate_readouts; |
| 52 | u32 config_inp[4]; | ||
| 53 | u32 bit_xp, bit_xn, bit_yp, bit_yn; | ||
| 54 | u32 inp_xp, inp_xn, inp_yp, inp_yn; | ||
| 44 | }; | 55 | }; |
| 45 | 56 | ||
| 46 | static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) | 57 | static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) |
| @@ -54,92 +65,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, | |||
| 54 | writel(val, tsc->mfd_tscadc->tscadc_base + reg); | 65 | writel(val, tsc->mfd_tscadc->tscadc_base + reg); |
| 55 | } | 66 | } |
| 56 | 67 | ||
| 68 | static int titsc_config_wires(struct titsc *ts_dev) | ||
| 69 | { | ||
| 70 | u32 analog_line[4]; | ||
| 71 | u32 wire_order[4]; | ||
| 72 | int i, bit_cfg; | ||
| 73 | |||
| 74 | for (i = 0; i < 4; i++) { | ||
| 75 | /* | ||
| 76 | * Get the order in which TSC wires are attached | ||
| 77 | * w.r.t. each of the analog input lines on the EVM. | ||
| 78 | */ | ||
| 79 | analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4; | ||
| 80 | wire_order[i] = ts_dev->config_inp[i] & 0x0F; | ||
| 81 | if (WARN_ON(analog_line[i] > 7)) | ||
| 82 | return -EINVAL; | ||
| 83 | if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins))) | ||
| 84 | return -EINVAL; | ||
| 85 | } | ||
| 86 | |||
| 87 | for (i = 0; i < 4; i++) { | ||
| 88 | int an_line; | ||
| 89 | int wi_order; | ||
| 90 | |||
| 91 | an_line = analog_line[i]; | ||
| 92 | wi_order = wire_order[i]; | ||
| 93 | bit_cfg = config_pins[wi_order]; | ||
| 94 | if (bit_cfg == 0) | ||
| 95 | return -EINVAL; | ||
| 96 | switch (wi_order) { | ||
| 97 | case 0: | ||
| 98 | ts_dev->bit_xp = bit_cfg; | ||
| 99 | ts_dev->inp_xp = an_line; | ||
| 100 | break; | ||
| 101 | |||
| 102 | case 1: | ||
| 103 | ts_dev->bit_xn = bit_cfg; | ||
| 104 | ts_dev->inp_xn = an_line; | ||
| 105 | break; | ||
| 106 | |||
| 107 | case 2: | ||
| 108 | ts_dev->bit_yp = bit_cfg; | ||
| 109 | ts_dev->inp_yp = an_line; | ||
| 110 | break; | ||
| 111 | case 3: | ||
| 112 | ts_dev->bit_yn = bit_cfg; | ||
| 113 | ts_dev->inp_yn = an_line; | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 57 | static void titsc_step_config(struct titsc *ts_dev) | 120 | static void titsc_step_config(struct titsc *ts_dev) |
| 58 | { | 121 | { |
| 59 | unsigned int config; | 122 | unsigned int config; |
| 60 | int i, total_steps; | 123 | int i; |
| 61 | 124 | int end_step; | |
| 62 | /* Configure the Step registers */ | 125 | u32 stepenable; |
| 63 | total_steps = 2 * ts_dev->steps_to_configure; | ||
| 64 | 126 | ||
| 65 | config = STEPCONFIG_MODE_HWSYNC | | 127 | config = STEPCONFIG_MODE_HWSYNC | |
| 66 | STEPCONFIG_AVG_16 | STEPCONFIG_XPP; | 128 | STEPCONFIG_AVG_16 | ts_dev->bit_xp; |
| 67 | switch (ts_dev->wires) { | 129 | switch (ts_dev->wires) { |
| 68 | case 4: | 130 | case 4: |
| 69 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | 131 | config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; |
| 70 | break; | 132 | break; |
| 71 | case 5: | 133 | case 5: |
| 72 | config |= STEPCONFIG_YNN | | 134 | config |= ts_dev->bit_yn | |
| 73 | STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | | 135 | STEPCONFIG_INP_AN4 | ts_dev->bit_xn | |
| 74 | STEPCONFIG_YPP; | 136 | ts_dev->bit_yp; |
| 75 | break; | 137 | break; |
| 76 | case 8: | 138 | case 8: |
| 77 | config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; | 139 | config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; |
| 78 | break; | 140 | break; |
| 79 | } | 141 | } |
| 80 | 142 | ||
| 81 | for (i = 1; i <= ts_dev->steps_to_configure; i++) { | 143 | /* 1 … coordinate_readouts is for X */ |
| 144 | end_step = ts_dev->coordinate_readouts; | ||
| 145 | for (i = 0; i < end_step; i++) { | ||
| 82 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | 146 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); |
| 83 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | 147 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); |
| 84 | } | 148 | } |
| 85 | 149 | ||
| 86 | config = 0; | 150 | config = 0; |
| 87 | config = STEPCONFIG_MODE_HWSYNC | | 151 | config = STEPCONFIG_MODE_HWSYNC | |
| 88 | STEPCONFIG_AVG_16 | STEPCONFIG_YNN | | 152 | STEPCONFIG_AVG_16 | ts_dev->bit_yn | |
| 89 | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; | 153 | STEPCONFIG_INM_ADCREFM; |
| 90 | switch (ts_dev->wires) { | 154 | switch (ts_dev->wires) { |
| 91 | case 4: | 155 | case 4: |
| 92 | config |= STEPCONFIG_YPP; | 156 | config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); |
| 93 | break; | 157 | break; |
| 94 | case 5: | 158 | case 5: |
| 95 | config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | | 159 | config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | |
| 96 | STEPCONFIG_XNP | STEPCONFIG_YPN; | 160 | ts_dev->bit_xn | ts_dev->bit_yp; |
| 97 | break; | 161 | break; |
| 98 | case 8: | 162 | case 8: |
| 99 | config |= STEPCONFIG_YPP; | 163 | config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); |
| 100 | break; | 164 | break; |
| 101 | } | 165 | } |
| 102 | 166 | ||
| 103 | for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { | 167 | /* coordinate_readouts … coordinate_readouts * 2 is for Y */ |
| 168 | end_step = ts_dev->coordinate_readouts * 2; | ||
| 169 | for (i = ts_dev->coordinate_readouts; i < end_step; i++) { | ||
| 104 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); | 170 | titsc_writel(ts_dev, REG_STEPCONFIG(i), config); |
| 105 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); | 171 | titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); |
| 106 | } | 172 | } |
| 107 | 173 | ||
| 108 | config = 0; | ||
| 109 | /* Charge step configuration */ | 174 | /* Charge step configuration */ |
| 110 | config = STEPCONFIG_XPP | STEPCONFIG_YNN | | 175 | config = ts_dev->bit_xp | ts_dev->bit_yn | |
| 111 | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | | 176 | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | |
| 112 | STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; | 177 | STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp); |
| 113 | 178 | ||
| 114 | titsc_writel(ts_dev, REG_CHARGECONFIG, config); | 179 | titsc_writel(ts_dev, REG_CHARGECONFIG, config); |
| 115 | titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); | 180 | titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); |
| 116 | 181 | ||
| 117 | config = 0; | 182 | /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */ |
| 118 | /* Configure to calculate pressure */ | ||
| 119 | config = STEPCONFIG_MODE_HWSYNC | | 183 | config = STEPCONFIG_MODE_HWSYNC | |
| 120 | STEPCONFIG_AVG_16 | STEPCONFIG_YPP | | 184 | STEPCONFIG_AVG_16 | ts_dev->bit_yp | |
| 121 | STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; | 185 | ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | |
| 122 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); | 186 | STEPCONFIG_INP(ts_dev->inp_xp); |
| 123 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), | 187 | titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); |
| 188 | titsc_writel(ts_dev, REG_STEPDELAY(end_step), | ||
| 124 | STEPCONFIG_OPENDLY); | 189 | STEPCONFIG_OPENDLY); |
| 125 | 190 | ||
| 126 | config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; | 191 | end_step++; |
| 127 | titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); | 192 | config |= STEPCONFIG_INP(ts_dev->inp_yn); |
| 128 | titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), | 193 | titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); |
| 194 | titsc_writel(ts_dev, REG_STEPDELAY(end_step), | ||
| 129 | STEPCONFIG_OPENDLY); | 195 | STEPCONFIG_OPENDLY); |
| 130 | 196 | ||
| 131 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | 197 | /* The steps1 … end and bit 0 for TS_Charge */ |
| 198 | stepenable = (1 << (end_step + 2)) - 1; | ||
| 199 | am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); | ||
| 132 | } | 200 | } |
| 133 | 201 | ||
| 134 | static void titsc_read_coordinates(struct titsc *ts_dev, | 202 | static void titsc_read_coordinates(struct titsc *ts_dev, |
| 135 | unsigned int *x, unsigned int *y) | 203 | u32 *x, u32 *y, u32 *z1, u32 *z2) |
| 136 | { | 204 | { |
| 137 | unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); | 205 | unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); |
| 138 | unsigned int prev_val_x = ~0, prev_val_y = ~0; | 206 | unsigned int prev_val_x = ~0, prev_val_y = ~0; |
| 139 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; | 207 | unsigned int prev_diff_x = ~0, prev_diff_y = ~0; |
| 140 | unsigned int read, diff; | 208 | unsigned int read, diff; |
| 141 | unsigned int i, channel; | 209 | unsigned int i, channel; |
| 210 | unsigned int creads = ts_dev->coordinate_readouts; | ||
| 142 | 211 | ||
| 212 | *z1 = *z2 = 0; | ||
| 213 | if (fifocount % (creads * 2 + 2)) | ||
| 214 | fifocount -= fifocount % (creads * 2 + 2); | ||
| 143 | /* | 215 | /* |
| 144 | * Delta filter is used to remove large variations in sampled | 216 | * Delta filter is used to remove large variations in sampled |
| 145 | * values from ADC. The filter tries to predict where the next | 217 | * values from ADC. The filter tries to predict where the next |
| @@ -148,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev, | |||
| 148 | * algorithm compares the difference with that of a present value, | 220 | * algorithm compares the difference with that of a present value, |
| 149 | * if true the value is reported to the sub system. | 221 | * if true the value is reported to the sub system. |
| 150 | */ | 222 | */ |
| 151 | for (i = 0; i < fifocount - 1; i++) { | 223 | for (i = 0; i < fifocount; i++) { |
| 152 | read = titsc_readl(ts_dev, REG_FIFO0); | 224 | read = titsc_readl(ts_dev, REG_FIFO0); |
| 153 | channel = read & 0xf0000; | 225 | |
| 154 | channel = channel >> 0x10; | 226 | channel = (read & 0xf0000) >> 16; |
| 155 | if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { | 227 | read &= 0xfff; |
| 156 | read &= 0xfff; | 228 | if (channel < creads) { |
| 157 | diff = abs(read - prev_val_x); | 229 | diff = abs(read - prev_val_x); |
| 158 | if (diff < prev_diff_x) { | 230 | if (diff < prev_diff_x) { |
| 159 | prev_diff_x = diff; | 231 | prev_diff_x = diff; |
| 160 | *x = read; | 232 | *x = read; |
| 161 | } | 233 | } |
| 162 | prev_val_x = read; | 234 | prev_val_x = read; |
| 163 | } | ||
| 164 | 235 | ||
| 165 | read = titsc_readl(ts_dev, REG_FIFO1); | 236 | } else if (channel < creads * 2) { |
| 166 | channel = read & 0xf0000; | ||
| 167 | channel = channel >> 0x10; | ||
| 168 | if ((channel >= ts_dev->steps_to_configure) && | ||
| 169 | (channel < (2 * ts_dev->steps_to_configure - 1))) { | ||
| 170 | read &= 0xfff; | ||
| 171 | diff = abs(read - prev_val_y); | 237 | diff = abs(read - prev_val_y); |
| 172 | if (diff < prev_diff_y) { | 238 | if (diff < prev_diff_y) { |
| 173 | prev_diff_y = diff; | 239 | prev_diff_y = diff; |
| 174 | *y = read; | 240 | *y = read; |
| 175 | } | 241 | } |
| 176 | prev_val_y = read; | 242 | prev_val_y = read; |
| 243 | |||
| 244 | } else if (channel < creads * 2 + 1) { | ||
| 245 | *z1 = read; | ||
| 246 | |||
| 247 | } else if (channel < creads * 2 + 2) { | ||
| 248 | *z2 = read; | ||
| 177 | } | 249 | } |
| 178 | } | 250 | } |
| 179 | } | 251 | } |
| @@ -186,23 +258,11 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
| 186 | unsigned int x = 0, y = 0; | 258 | unsigned int x = 0, y = 0; |
| 187 | unsigned int z1, z2, z; | 259 | unsigned int z1, z2, z; |
| 188 | unsigned int fsm; | 260 | unsigned int fsm; |
| 189 | unsigned int fifo1count, fifo0count; | ||
| 190 | int i; | ||
| 191 | 261 | ||
| 192 | status = titsc_readl(ts_dev, REG_IRQSTATUS); | 262 | status = titsc_readl(ts_dev, REG_IRQSTATUS); |
| 193 | if (status & IRQENB_FIFO0THRES) { | 263 | if (status & IRQENB_FIFO0THRES) { |
| 194 | titsc_read_coordinates(ts_dev, &x, &y); | ||
| 195 | 264 | ||
| 196 | z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; | 265 | titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2); |
| 197 | z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; | ||
| 198 | |||
| 199 | fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); | ||
| 200 | for (i = 0; i < fifo1count; i++) | ||
| 201 | titsc_readl(ts_dev, REG_FIFO1); | ||
| 202 | |||
| 203 | fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); | ||
| 204 | for (i = 0; i < fifo0count; i++) | ||
| 205 | titsc_readl(ts_dev, REG_FIFO0); | ||
| 206 | 266 | ||
| 207 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { | 267 | if (ts_dev->pen_down && z1 != 0 && z2 != 0) { |
| 208 | /* | 268 | /* |
| @@ -210,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
| 210 | * Resistance(touch) = x plate resistance * | 270 | * Resistance(touch) = x plate resistance * |
| 211 | * x postion/4096 * ((z2 / z1) - 1) | 271 | * x postion/4096 * ((z2 / z1) - 1) |
| 212 | */ | 272 | */ |
| 213 | z = z2 - z1; | 273 | z = z1 - z2; |
| 214 | z *= x; | 274 | z *= x; |
| 215 | z *= ts_dev->x_plate_resistance; | 275 | z *= ts_dev->x_plate_resistance; |
| 216 | z /= z1; | 276 | z /= z2; |
| 217 | z = (z + 2047) >> 12; | 277 | z = (z + 2047) >> 12; |
| 218 | 278 | ||
| 219 | if (z <= MAX_12BIT) { | 279 | if (z <= MAX_12BIT) { |
| @@ -248,10 +308,60 @@ static irqreturn_t titsc_irq(int irq, void *dev) | |||
| 248 | irqclr |= IRQENB_PENUP; | 308 | irqclr |= IRQENB_PENUP; |
| 249 | } | 309 | } |
| 250 | 310 | ||
| 251 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); | 311 | if (status & IRQENB_HW_PEN) { |
| 312 | |||
| 313 | titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); | ||
| 314 | titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); | ||
| 315 | } | ||
| 316 | |||
| 317 | if (irqclr) { | ||
| 318 | titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); | ||
| 319 | am335x_tsc_se_update(ts_dev->mfd_tscadc); | ||
| 320 | return IRQ_HANDLED; | ||
| 321 | } | ||
| 322 | return IRQ_NONE; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int titsc_parse_dt(struct platform_device *pdev, | ||
| 326 | struct titsc *ts_dev) | ||
| 327 | { | ||
| 328 | struct device_node *node = pdev->dev.of_node; | ||
| 329 | int err; | ||
| 330 | |||
| 331 | if (!node) | ||
| 332 | return -EINVAL; | ||
| 333 | |||
| 334 | err = of_property_read_u32(node, "ti,wires", &ts_dev->wires); | ||
| 335 | if (err < 0) | ||
| 336 | return err; | ||
| 337 | switch (ts_dev->wires) { | ||
| 338 | case 4: | ||
| 339 | case 5: | ||
| 340 | case 8: | ||
| 341 | break; | ||
| 342 | default: | ||
| 343 | return -EINVAL; | ||
| 344 | } | ||
| 345 | |||
| 346 | err = of_property_read_u32(node, "ti,x-plate-resistance", | ||
| 347 | &ts_dev->x_plate_resistance); | ||
| 348 | if (err < 0) | ||
| 349 | return err; | ||
| 252 | 350 | ||
| 253 | titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); | 351 | /* |
| 254 | return IRQ_HANDLED; | 352 | * Try with the new binding first. If it fails, try again with |
| 353 | * bogus, miss-spelled version. | ||
| 354 | */ | ||
| 355 | err = of_property_read_u32(node, "ti,coordinate-readouts", | ||
| 356 | &ts_dev->coordinate_readouts); | ||
| 357 | if (err < 0) | ||
| 358 | err = of_property_read_u32(node, "ti,coordiante-readouts", | ||
| 359 | &ts_dev->coordinate_readouts); | ||
| 360 | if (err < 0) | ||
| 361 | return err; | ||
| 362 | |||
| 363 | return of_property_read_u32_array(node, "ti,wire-config", | ||
| 364 | ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp)); | ||
| 255 | } | 365 | } |
| 256 | 366 | ||
| 257 | /* | 367 | /* |
| @@ -262,17 +372,9 @@ static int titsc_probe(struct platform_device *pdev) | |||
| 262 | { | 372 | { |
| 263 | struct titsc *ts_dev; | 373 | struct titsc *ts_dev; |
| 264 | struct input_dev *input_dev; | 374 | struct input_dev *input_dev; |
| 265 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | 375 | struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); |
| 266 | struct mfd_tscadc_board *pdata; | ||
| 267 | int err; | 376 | int err; |
| 268 | 377 | ||
| 269 | pdata = tscadc_dev->dev->platform_data; | ||
| 270 | |||
| 271 | if (!pdata) { | ||
| 272 | dev_err(&pdev->dev, "Could not find platform data\n"); | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* Allocate memory for device */ | 378 | /* Allocate memory for device */ |
| 277 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); | 379 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); |
| 278 | input_dev = input_allocate_device(); | 380 | input_dev = input_allocate_device(); |
| @@ -286,9 +388,12 @@ static int titsc_probe(struct platform_device *pdev) | |||
| 286 | ts_dev->mfd_tscadc = tscadc_dev; | 388 | ts_dev->mfd_tscadc = tscadc_dev; |
| 287 | ts_dev->input = input_dev; | 389 | ts_dev->input = input_dev; |
| 288 | ts_dev->irq = tscadc_dev->irq; | 390 | ts_dev->irq = tscadc_dev->irq; |
| 289 | ts_dev->wires = pdata->tsc_init->wires; | 391 | |
| 290 | ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; | 392 | err = titsc_parse_dt(pdev, ts_dev); |
| 291 | ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; | 393 | if (err) { |
| 394 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); | ||
| 395 | goto err_free_mem; | ||
| 396 | } | ||
| 292 | 397 | ||
| 293 | err = request_irq(ts_dev->irq, titsc_irq, | 398 | err = request_irq(ts_dev->irq, titsc_irq, |
| 294 | 0, pdev->dev.driver->name, ts_dev); | 399 | 0, pdev->dev.driver->name, ts_dev); |
| @@ -298,8 +403,14 @@ static int titsc_probe(struct platform_device *pdev) | |||
| 298 | } | 403 | } |
| 299 | 404 | ||
| 300 | titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); | 405 | titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); |
| 406 | err = titsc_config_wires(ts_dev); | ||
| 407 | if (err) { | ||
| 408 | dev_err(&pdev->dev, "wrong i/p wire configuration\n"); | ||
| 409 | goto err_free_irq; | ||
| 410 | } | ||
| 301 | titsc_step_config(ts_dev); | 411 | titsc_step_config(ts_dev); |
| 302 | titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); | 412 | titsc_writel(ts_dev, REG_FIFO0THR, |
| 413 | ts_dev->coordinate_readouts * 2 + 2 - 1); | ||
| 303 | 414 | ||
| 304 | input_dev->name = "ti-tsc"; | 415 | input_dev->name = "ti-tsc"; |
| 305 | input_dev->dev.parent = &pdev->dev; | 416 | input_dev->dev.parent = &pdev->dev; |
| @@ -329,11 +440,16 @@ err_free_mem: | |||
| 329 | 440 | ||
| 330 | static int titsc_remove(struct platform_device *pdev) | 441 | static int titsc_remove(struct platform_device *pdev) |
| 331 | { | 442 | { |
| 332 | struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; | 443 | struct titsc *ts_dev = platform_get_drvdata(pdev); |
| 333 | struct titsc *ts_dev = tscadc_dev->tsc; | 444 | u32 steps; |
| 334 | 445 | ||
| 335 | free_irq(ts_dev->irq, ts_dev); | 446 | free_irq(ts_dev->irq, ts_dev); |
| 336 | 447 | ||
| 448 | /* total steps followed by the enable mask */ | ||
| 449 | steps = 2 * ts_dev->coordinate_readouts + 2; | ||
| 450 | steps = (1 << steps) - 1; | ||
| 451 | am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); | ||
| 452 | |||
| 337 | input_unregister_device(ts_dev->input); | 453 | input_unregister_device(ts_dev->input); |
| 338 | 454 | ||
| 339 | kfree(ts_dev); | 455 | kfree(ts_dev); |
| @@ -343,10 +459,11 @@ static int titsc_remove(struct platform_device *pdev) | |||
| 343 | #ifdef CONFIG_PM | 459 | #ifdef CONFIG_PM |
| 344 | static int titsc_suspend(struct device *dev) | 460 | static int titsc_suspend(struct device *dev) |
| 345 | { | 461 | { |
| 346 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | 462 | struct titsc *ts_dev = dev_get_drvdata(dev); |
| 347 | struct titsc *ts_dev = tscadc_dev->tsc; | 463 | struct ti_tscadc_dev *tscadc_dev; |
| 348 | unsigned int idle; | 464 | unsigned int idle; |
| 349 | 465 | ||
| 466 | tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); | ||
| 350 | if (device_may_wakeup(tscadc_dev->dev)) { | 467 | if (device_may_wakeup(tscadc_dev->dev)) { |
| 351 | idle = titsc_readl(ts_dev, REG_IRQENABLE); | 468 | idle = titsc_readl(ts_dev, REG_IRQENABLE); |
| 352 | titsc_writel(ts_dev, REG_IRQENABLE, | 469 | titsc_writel(ts_dev, REG_IRQENABLE, |
| @@ -358,9 +475,10 @@ static int titsc_suspend(struct device *dev) | |||
| 358 | 475 | ||
| 359 | static int titsc_resume(struct device *dev) | 476 | static int titsc_resume(struct device *dev) |
| 360 | { | 477 | { |
| 361 | struct ti_tscadc_dev *tscadc_dev = dev->platform_data; | 478 | struct titsc *ts_dev = dev_get_drvdata(dev); |
| 362 | struct titsc *ts_dev = tscadc_dev->tsc; | 479 | struct ti_tscadc_dev *tscadc_dev; |
| 363 | 480 | ||
| 481 | tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); | ||
| 364 | if (device_may_wakeup(tscadc_dev->dev)) { | 482 | if (device_may_wakeup(tscadc_dev->dev)) { |
| 365 | titsc_writel(ts_dev, REG_IRQWAKEUP, | 483 | titsc_writel(ts_dev, REG_IRQWAKEUP, |
| 366 | 0x00); | 484 | 0x00); |
| @@ -368,7 +486,7 @@ static int titsc_resume(struct device *dev) | |||
| 368 | } | 486 | } |
| 369 | titsc_step_config(ts_dev); | 487 | titsc_step_config(ts_dev); |
| 370 | titsc_writel(ts_dev, REG_FIFO0THR, | 488 | titsc_writel(ts_dev, REG_FIFO0THR, |
| 371 | ts_dev->steps_to_configure); | 489 | ts_dev->coordinate_readouts * 2 + 2 - 1); |
| 372 | return 0; | 490 | return 0; |
| 373 | } | 491 | } |
| 374 | 492 | ||
| @@ -381,13 +499,20 @@ static const struct dev_pm_ops titsc_pm_ops = { | |||
| 381 | #define TITSC_PM_OPS NULL | 499 | #define TITSC_PM_OPS NULL |
| 382 | #endif | 500 | #endif |
| 383 | 501 | ||
| 502 | static const struct of_device_id ti_tsc_dt_ids[] = { | ||
| 503 | { .compatible = "ti,am3359-tsc", }, | ||
| 504 | { } | ||
| 505 | }; | ||
| 506 | MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids); | ||
| 507 | |||
| 384 | static struct platform_driver ti_tsc_driver = { | 508 | static struct platform_driver ti_tsc_driver = { |
| 385 | .probe = titsc_probe, | 509 | .probe = titsc_probe, |
| 386 | .remove = titsc_remove, | 510 | .remove = titsc_remove, |
| 387 | .driver = { | 511 | .driver = { |
| 388 | .name = "tsc", | 512 | .name = "TI-am335x-tsc", |
| 389 | .owner = THIS_MODULE, | 513 | .owner = THIS_MODULE, |
| 390 | .pm = TITSC_PM_OPS, | 514 | .pm = TITSC_PM_OPS, |
| 515 | .of_match_table = ti_tsc_dt_ids, | ||
| 391 | }, | 516 | }, |
| 392 | }; | 517 | }; |
| 393 | module_platform_driver(ti_tsc_driver); | 518 | 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"); | ||
