diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 12:12:19 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 12:12:19 -0400 |
| commit | d4e65476bc68dbc9231b3c772b71f1576579b6fb (patch) | |
| tree | 3408d0e17d8ea6bdfaa9c5cd5745298d5b7e67a3 /drivers/input/touchscreen | |
| parent | d042380886fb2fc6c4b0fcfe1214ba473769a8e9 (diff) | |
| parent | c758f96a8c346ac5a6822b521ec92308c5774381 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov:
"You will get
- a new driver for Elan eKTF2127 touchscreen controllers
- a new "gpio-decoder" driver to read and report state of several
GPIO lines
- an ADC resistor ladder driver
- the ft6326 driver is removed because edt-ft5x06 handles the same
devices just fine.
.. plus the regular slew of driver fixes/enhancements"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (26 commits)
Input: elan_i2c - fix return tests of i2c_smbus_read_block_data()
Input: ektf2127 - mark PM functions as __maybe_unused
Input: snvs_pwrkey - drop input_free_device call if input_register_device fails
Input: add support for Elan eKTF2127 touchscreen controller
Input: serio - add hangup support
Input: tps65218-pwrbutton - add support for tps65217 variant
Input: jornada720_ts - get rid of mach/irqs.h and mach/hardware.h includes
Input: jornada720_kbd - remove unneeded mach/hardware.h include
Input: focaltech - mark focaltech_set_resolution() static
Input: wdt87xx_i2c - fix the flash erase issue
Input: gpio-keys-polled - don't use unit-address with button nodes
Input: add generic input driver to read encoded GPIO lines
Input: add ADC resistor ladder driver
Input: pegasus_notetaker - directly include workqueue header
Input: elants_i2c - get product id on recovery mode for FW update
Input: wm97xx - remove deprecated create_singletheread_workqueue
Input: mc13783_ts - remove deprecated create_singletheread_workqueue
Input: psmouse - remove deprecated create_singletheread_workqueue
Input: jornada720_kbd - switch to using dev_dbg
Input: jornada720_kbd - get rid of mach/irqs.h include
...
Diffstat (limited to 'drivers/input/touchscreen')
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 25 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 2 | ||||
| -rw-r--r-- | drivers/input/touchscreen/edt-ft5x06.c | 8 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ektf2127.c | 336 | ||||
| -rw-r--r-- | drivers/input/touchscreen/elants_i2c.c | 31 | ||||
| -rw-r--r-- | drivers/input/touchscreen/ft6236.c | 326 | ||||
| -rw-r--r-- | drivers/input/touchscreen/jornada720_ts.c | 21 | ||||
| -rw-r--r-- | drivers/input/touchscreen/mc13783_ts.c | 24 | ||||
| -rw-r--r-- | drivers/input/touchscreen/pixcir_i2c_ts.c | 13 | ||||
| -rw-r--r-- | drivers/input/touchscreen/wdt87xx_i2c.c | 5 | ||||
| -rw-r--r-- | drivers/input/touchscreen/wm97xx-core.c | 2 |
11 files changed, 403 insertions, 390 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 2fb1f430a431..507981356921 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -305,19 +305,6 @@ config TOUCHSCREEN_EGALAX_SERIAL | |||
| 305 | To compile this driver as a module, choose M here: the | 305 | To compile this driver as a module, choose M here: the |
| 306 | module will be called egalax_ts_serial. | 306 | module will be called egalax_ts_serial. |
| 307 | 307 | ||
| 308 | config TOUCHSCREEN_FT6236 | ||
| 309 | tristate "FT6236 I2C touchscreen" | ||
| 310 | depends on I2C | ||
| 311 | depends on GPIOLIB || COMPILE_TEST | ||
| 312 | help | ||
| 313 | Say Y here to enable support for the I2C connected FT6x06 and | ||
| 314 | FT6x36 family of capacitive touchscreen drivers. | ||
| 315 | |||
| 316 | If unsure, say N. | ||
| 317 | |||
| 318 | To compile this driver as a module, choose M here: the | ||
| 319 | module will be called ft6236. | ||
| 320 | |||
| 321 | config TOUCHSCREEN_FUJITSU | 308 | config TOUCHSCREEN_FUJITSU |
| 322 | tristate "Fujitsu serial touchscreen" | 309 | tristate "Fujitsu serial touchscreen" |
| 323 | select SERIO | 310 | select SERIO |
| @@ -397,6 +384,18 @@ config TOUCHSCREEN_GUNZE | |||
| 397 | To compile this driver as a module, choose M here: the | 384 | To compile this driver as a module, choose M here: the |
| 398 | module will be called gunze. | 385 | module will be called gunze. |
| 399 | 386 | ||
| 387 | config TOUCHSCREEN_EKTF2127 | ||
| 388 | tristate "Elan eKTF2127 I2C touchscreen" | ||
| 389 | depends on I2C | ||
| 390 | help | ||
| 391 | Say Y here if you have an Elan eKTF2127 touchscreen | ||
| 392 | connected to your system. | ||
| 393 | |||
| 394 | If unsure, say N. | ||
| 395 | |||
| 396 | To compile this driver as a module, choose M here: the | ||
| 397 | module will be called ektf2127. | ||
| 398 | |||
| 400 | config TOUCHSCREEN_ELAN | 399 | config TOUCHSCREEN_ELAN |
| 401 | tristate "Elan eKTH I2C touchscreen" | 400 | tristate "Elan eKTH I2C touchscreen" |
| 402 | depends on I2C | 401 | depends on I2C |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index b4373d6be402..81b86451782d 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -32,11 +32,11 @@ obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o | |||
| 32 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | 32 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o |
| 33 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 33 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 34 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 34 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
| 35 | obj-$(CONFIG_TOUCHSCREEN_EKTF2127) += ektf2127.o | ||
| 35 | obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o | 36 | obj-$(CONFIG_TOUCHSCREEN_ELAN) += elants_i2c.o |
| 36 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 37 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
| 37 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o | 38 | obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o |
| 38 | obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o | 39 | obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o |
| 39 | obj-$(CONFIG_TOUCHSCREEN_FT6236) += ft6236.o | ||
| 40 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 40 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
| 41 | obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o | 41 | obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o |
| 42 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | 42 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o |
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 703e295a37ed..28466e358fee 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
| @@ -1063,9 +1063,15 @@ static const struct edt_i2c_chip_data edt_ft5506_data = { | |||
| 1063 | .max_support_points = 10, | 1063 | .max_support_points = 10, |
| 1064 | }; | 1064 | }; |
| 1065 | 1065 | ||
| 1066 | static const struct edt_i2c_chip_data edt_ft6236_data = { | ||
| 1067 | .max_support_points = 2, | ||
| 1068 | }; | ||
| 1069 | |||
| 1066 | static const struct i2c_device_id edt_ft5x06_ts_id[] = { | 1070 | static const struct i2c_device_id edt_ft5x06_ts_id[] = { |
| 1067 | { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data }, | 1071 | { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data }, |
| 1068 | { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data }, | 1072 | { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data }, |
| 1073 | /* Note no edt- prefix for compatibility with the ft6236.c driver */ | ||
| 1074 | { .name = "ft6236", .driver_data = (long)&edt_ft6236_data }, | ||
| 1069 | { /* sentinel */ } | 1075 | { /* sentinel */ } |
| 1070 | }; | 1076 | }; |
| 1071 | MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); | 1077 | MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); |
| @@ -1076,6 +1082,8 @@ static const struct of_device_id edt_ft5x06_of_match[] = { | |||
| 1076 | { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data }, | 1082 | { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data }, |
| 1077 | { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, | 1083 | { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, |
| 1078 | { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data }, | 1084 | { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data }, |
| 1085 | /* Note focaltech vendor prefix for compatibility with ft6236.c */ | ||
| 1086 | { .compatible = "focaltech,ft6236", .data = &edt_ft6236_data }, | ||
| 1079 | { /* sentinel */ } | 1087 | { /* sentinel */ } |
| 1080 | }; | 1088 | }; |
| 1081 | MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); | 1089 | MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); |
diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c new file mode 100644 index 000000000000..0ed34ff787ce --- /dev/null +++ b/drivers/input/touchscreen/ektf2127.c | |||
| @@ -0,0 +1,336 @@ | |||
| 1 | /* | ||
| 2 | * Driver for ELAN eKTF2127 i2c touchscreen controller | ||
| 3 | * | ||
| 4 | * For this driver the layout of the Chipone icn8318 i2c | ||
| 5 | * touchscreencontroller is used. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * Author: | ||
| 13 | * Michel Verlaan <michel.verl@gmail.com> | ||
| 14 | * Siebren Vroegindeweij <siebren.vroegindeweij@hotmail.com> | ||
| 15 | * | ||
| 16 | * Original chipone_icn8318 driver: | ||
| 17 | * Hans de Goede <hdegoede@redhat.com> | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/gpio/consumer.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/i2c.h> | ||
| 23 | #include <linux/input.h> | ||
| 24 | #include <linux/input/mt.h> | ||
| 25 | #include <linux/input/touchscreen.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/of.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | |||
| 30 | /* Packet header defines (first byte of data send / received) */ | ||
| 31 | #define EKTF2127_NOISE 0x40 | ||
| 32 | #define EKTF2127_RESPONSE 0x52 | ||
| 33 | #define EKTF2127_REQUEST 0x53 | ||
| 34 | #define EKTF2127_HELLO 0x55 | ||
| 35 | #define EKTF2127_REPORT 0x5d | ||
| 36 | #define EKTF2127_CALIB_DONE 0x66 | ||
| 37 | |||
| 38 | /* Register defines (second byte of data send / received) */ | ||
| 39 | #define EKTF2127_ENV_NOISY 0x41 | ||
| 40 | #define EKTF2127_HEIGHT 0x60 | ||
| 41 | #define EKTF2127_WIDTH 0x63 | ||
| 42 | |||
| 43 | /* 2 bytes header + 5 * 3 bytes coordinates + 3 bytes pressure info + footer */ | ||
| 44 | #define EKTF2127_TOUCH_REPORT_SIZE 21 | ||
| 45 | #define EKTF2127_MAX_TOUCHES 5 | ||
| 46 | |||
| 47 | struct ektf2127_ts { | ||
| 48 | struct i2c_client *client; | ||
| 49 | struct input_dev *input; | ||
| 50 | struct gpio_desc *power_gpios; | ||
| 51 | struct touchscreen_properties prop; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static void ektf2127_parse_coordinates(const u8* buf, unsigned int touch_count, | ||
| 55 | struct input_mt_pos *touches) | ||
| 56 | { | ||
| 57 | int index = 0; | ||
| 58 | int i; | ||
| 59 | |||
| 60 | for (i = 0; i < touch_count; i++) { | ||
| 61 | index = 2 + i * 3; | ||
| 62 | |||
| 63 | touches[i].x = (buf[index] & 0x0f); | ||
| 64 | touches[i].x <<= 8; | ||
| 65 | touches[i].x |= buf[index + 2]; | ||
| 66 | |||
| 67 | touches[i].y = (buf[index] & 0xf0); | ||
| 68 | touches[i].y <<= 4; | ||
| 69 | touches[i].y |= buf[index + 1]; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | static void ektf2127_report_event(struct ektf2127_ts *ts, const u8 *buf) | ||
| 74 | { | ||
| 75 | struct input_mt_pos touches[EKTF2127_MAX_TOUCHES]; | ||
| 76 | int slots[EKTF2127_MAX_TOUCHES]; | ||
| 77 | unsigned int touch_count, i; | ||
| 78 | |||
| 79 | touch_count = buf[1] & 0x07; | ||
| 80 | if (touch_count > EKTF2127_MAX_TOUCHES) { | ||
| 81 | dev_err(&ts->client->dev, | ||
| 82 | "Too many touches %d > %d\n", | ||
| 83 | touch_count, EKTF2127_MAX_TOUCHES); | ||
| 84 | touch_count = EKTF2127_MAX_TOUCHES; | ||
| 85 | } | ||
| 86 | |||
| 87 | ektf2127_parse_coordinates(buf, touch_count, touches); | ||
| 88 | input_mt_assign_slots(ts->input, slots, touches, | ||
| 89 | touch_count, 0); | ||
| 90 | |||
| 91 | for (i = 0; i < touch_count; i++) { | ||
| 92 | input_mt_slot(ts->input, slots[i]); | ||
| 93 | input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); | ||
| 94 | touchscreen_report_pos(ts->input, &ts->prop, | ||
| 95 | touches[i].x, touches[i].y, true); | ||
| 96 | } | ||
| 97 | |||
| 98 | input_mt_sync_frame(ts->input); | ||
| 99 | input_sync(ts->input); | ||
| 100 | } | ||
| 101 | |||
| 102 | static irqreturn_t ektf2127_irq(int irq, void *dev_id) | ||
| 103 | { | ||
| 104 | struct ektf2127_ts *ts = dev_id; | ||
| 105 | struct device *dev = &ts->client->dev; | ||
| 106 | char buf[EKTF2127_TOUCH_REPORT_SIZE]; | ||
| 107 | int ret; | ||
| 108 | |||
| 109 | ret = i2c_master_recv(ts->client, buf, EKTF2127_TOUCH_REPORT_SIZE); | ||
| 110 | if (ret != EKTF2127_TOUCH_REPORT_SIZE) { | ||
| 111 | dev_err(dev, "Error reading touch data: %d\n", ret); | ||
| 112 | goto out; | ||
| 113 | } | ||
| 114 | |||
| 115 | switch (buf[0]) { | ||
| 116 | case EKTF2127_REPORT: | ||
| 117 | ektf2127_report_event(ts, buf); | ||
| 118 | break; | ||
| 119 | |||
| 120 | case EKTF2127_NOISE: | ||
| 121 | if (buf[1] == EKTF2127_ENV_NOISY) | ||
| 122 | dev_dbg(dev, "Environment is electrically noisy\n"); | ||
| 123 | break; | ||
| 124 | |||
| 125 | case EKTF2127_HELLO: | ||
| 126 | case EKTF2127_CALIB_DONE: | ||
| 127 | break; | ||
| 128 | |||
| 129 | default: | ||
| 130 | dev_err(dev, "Unexpected packet header byte %#02x\n", buf[0]); | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | |||
| 134 | out: | ||
| 135 | return IRQ_HANDLED; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int ektf2127_start(struct input_dev *dev) | ||
| 139 | { | ||
| 140 | struct ektf2127_ts *ts = input_get_drvdata(dev); | ||
| 141 | |||
| 142 | enable_irq(ts->client->irq); | ||
| 143 | gpiod_set_value_cansleep(ts->power_gpios, 1); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static void ektf2127_stop(struct input_dev *dev) | ||
| 149 | { | ||
| 150 | struct ektf2127_ts *ts = input_get_drvdata(dev); | ||
| 151 | |||
| 152 | disable_irq(ts->client->irq); | ||
| 153 | gpiod_set_value_cansleep(ts->power_gpios, 0); | ||
| 154 | } | ||
| 155 | |||
| 156 | static int __maybe_unused ektf2127_suspend(struct device *dev) | ||
| 157 | { | ||
| 158 | struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 159 | |||
| 160 | mutex_lock(&ts->input->mutex); | ||
| 161 | if (ts->input->users) | ||
| 162 | ektf2127_stop(ts->input); | ||
| 163 | mutex_unlock(&ts->input->mutex); | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int __maybe_unused ektf2127_resume(struct device *dev) | ||
| 169 | { | ||
| 170 | struct ektf2127_ts *ts = i2c_get_clientdata(to_i2c_client(dev)); | ||
| 171 | |||
| 172 | mutex_lock(&ts->input->mutex); | ||
| 173 | if (ts->input->users) | ||
| 174 | ektf2127_start(ts->input); | ||
| 175 | mutex_unlock(&ts->input->mutex); | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static SIMPLE_DEV_PM_OPS(ektf2127_pm_ops, ektf2127_suspend, | ||
| 181 | ektf2127_resume); | ||
| 182 | |||
| 183 | static int ektf2127_query_dimension(struct i2c_client *client, bool width) | ||
| 184 | { | ||
| 185 | struct device *dev = &client->dev; | ||
| 186 | const char *what = width ? "width" : "height"; | ||
| 187 | u8 what_code = width ? EKTF2127_WIDTH : EKTF2127_HEIGHT; | ||
| 188 | u8 buf[4]; | ||
| 189 | int ret; | ||
| 190 | int error; | ||
| 191 | |||
| 192 | /* Request dimension */ | ||
| 193 | buf[0] = EKTF2127_REQUEST; | ||
| 194 | buf[1] = width ? EKTF2127_WIDTH : EKTF2127_HEIGHT; | ||
| 195 | buf[2] = 0x00; | ||
| 196 | buf[3] = 0x00; | ||
| 197 | ret = i2c_master_send(client, buf, sizeof(buf)); | ||
| 198 | if (ret != sizeof(buf)) { | ||
| 199 | error = ret < 0 ? ret : -EIO; | ||
| 200 | dev_err(dev, "Failed to request %s: %d\n", what, error); | ||
| 201 | return error; | ||
| 202 | } | ||
| 203 | |||
| 204 | msleep(20); | ||
| 205 | |||
| 206 | /* Read response */ | ||
| 207 | ret = i2c_master_recv(client, buf, sizeof(buf)); | ||
| 208 | if (ret != sizeof(buf)) { | ||
| 209 | error = ret < 0 ? ret : -EIO; | ||
| 210 | dev_err(dev, "Failed to receive %s data: %d\n", what, error); | ||
| 211 | return error; | ||
| 212 | } | ||
| 213 | |||
| 214 | if (buf[0] != EKTF2127_RESPONSE || buf[1] != what_code) { | ||
| 215 | dev_err(dev, "Unexpected %s data: %#02x %#02x\n", | ||
| 216 | what, buf[0], buf[1]); | ||
| 217 | return -EIO; | ||
| 218 | } | ||
| 219 | |||
| 220 | return (((buf[3] & 0xf0) << 4) | buf[2]) - 1; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int ektf2127_probe(struct i2c_client *client, | ||
| 224 | const struct i2c_device_id *id) | ||
| 225 | { | ||
| 226 | struct device *dev = &client->dev; | ||
| 227 | struct ektf2127_ts *ts; | ||
| 228 | struct input_dev *input; | ||
| 229 | u8 buf[4]; | ||
| 230 | int max_x, max_y; | ||
| 231 | int error; | ||
| 232 | |||
| 233 | if (!client->irq) { | ||
| 234 | dev_err(dev, "Error no irq specified\n"); | ||
| 235 | return -EINVAL; | ||
| 236 | } | ||
| 237 | |||
| 238 | ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); | ||
| 239 | if (!ts) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | /* This requests the gpio *and* turns on the touchscreen controller */ | ||
| 243 | ts->power_gpios = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH); | ||
| 244 | if (IS_ERR(ts->power_gpios)) { | ||
| 245 | error = PTR_ERR(ts->power_gpios); | ||
| 246 | if (error != -EPROBE_DEFER) | ||
| 247 | dev_err(dev, "Error getting power gpio: %d\n", error); | ||
| 248 | return error; | ||
| 249 | } | ||
| 250 | |||
| 251 | input = devm_input_allocate_device(dev); | ||
| 252 | if (!input) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | input->name = client->name; | ||
| 256 | input->id.bustype = BUS_I2C; | ||
| 257 | input->open = ektf2127_start; | ||
| 258 | input->close = ektf2127_stop; | ||
| 259 | |||
| 260 | ts->client = client; | ||
| 261 | |||
| 262 | /* Read hello (ignore result, depends on initial power state) */ | ||
| 263 | msleep(20); | ||
| 264 | i2c_master_recv(ts->client, buf, sizeof(buf)); | ||
| 265 | |||
| 266 | /* Read resolution from chip */ | ||
| 267 | max_x = ektf2127_query_dimension(client, true); | ||
| 268 | if (max_x < 0) | ||
| 269 | return max_x; | ||
| 270 | |||
| 271 | max_y = ektf2127_query_dimension(client, false); | ||
| 272 | if (max_y < 0) | ||
| 273 | return max_y; | ||
| 274 | |||
| 275 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_x, 0, 0); | ||
| 276 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); | ||
| 277 | touchscreen_parse_properties(input, true, &ts->prop); | ||
| 278 | |||
| 279 | error = input_mt_init_slots(input, EKTF2127_MAX_TOUCHES, | ||
| 280 | INPUT_MT_DIRECT | | ||
| 281 | INPUT_MT_DROP_UNUSED | | ||
| 282 | INPUT_MT_TRACK); | ||
| 283 | if (error) | ||
| 284 | return error; | ||
| 285 | |||
| 286 | ts->input = input; | ||
| 287 | input_set_drvdata(input, ts); | ||
| 288 | |||
| 289 | error = devm_request_threaded_irq(dev, client->irq, | ||
| 290 | NULL, ektf2127_irq, | ||
| 291 | IRQF_ONESHOT, client->name, ts); | ||
| 292 | if (error) { | ||
| 293 | dev_err(dev, "Error requesting irq: %d\n", error); | ||
| 294 | return error; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* Stop device till opened */ | ||
| 298 | ektf2127_stop(ts->input); | ||
| 299 | |||
| 300 | error = input_register_device(input); | ||
| 301 | if (error) | ||
| 302 | return error; | ||
| 303 | |||
| 304 | i2c_set_clientdata(client, ts); | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | #ifdef CONFIG_OF | ||
| 310 | static const struct of_device_id ektf2127_of_match[] = { | ||
| 311 | { .compatible = "elan,ektf2127" }, | ||
| 312 | {} | ||
| 313 | }; | ||
| 314 | MODULE_DEVICE_TABLE(of, ektf2127_of_match); | ||
| 315 | #endif | ||
| 316 | |||
| 317 | static const struct i2c_device_id ektf2127_i2c_id[] = { | ||
| 318 | { "ektf2127", 0 }, | ||
| 319 | {} | ||
| 320 | }; | ||
| 321 | MODULE_DEVICE_TABLE(i2c, ektf2127_i2c_id); | ||
| 322 | |||
| 323 | static struct i2c_driver ektf2127_driver = { | ||
| 324 | .driver = { | ||
| 325 | .name = "elan_ektf2127", | ||
| 326 | .pm = &ektf2127_pm_ops, | ||
| 327 | .of_match_table = of_match_ptr(ektf2127_of_match), | ||
| 328 | }, | ||
| 329 | .probe = ektf2127_probe, | ||
| 330 | .id_table = ektf2127_i2c_id, | ||
| 331 | }; | ||
| 332 | module_i2c_driver(ektf2127_driver); | ||
| 333 | |||
| 334 | MODULE_DESCRIPTION("ELAN eKTF2127 I2C Touchscreen Driver"); | ||
| 335 | MODULE_AUTHOR("Michel Verlaan, Siebren Vroegindeweij"); | ||
| 336 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index ac09855fa435..02aec284deca 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c | |||
| @@ -298,7 +298,7 @@ static u16 elants_i2c_parse_version(u8 *buf) | |||
| 298 | return get_unaligned_be32(buf) >> 4; | 298 | return get_unaligned_be32(buf) >> 4; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | static int elants_i2c_query_fw_id(struct elants_data *ts) | 301 | static int elants_i2c_query_hw_version(struct elants_data *ts) |
| 302 | { | 302 | { |
| 303 | struct i2c_client *client = ts->client; | 303 | struct i2c_client *client = ts->client; |
| 304 | int error, retry_cnt; | 304 | int error, retry_cnt; |
| @@ -318,8 +318,13 @@ static int elants_i2c_query_fw_id(struct elants_data *ts) | |||
| 318 | error, (int)sizeof(resp), resp); | 318 | error, (int)sizeof(resp), resp); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | dev_err(&client->dev, | 321 | if (error) { |
| 322 | "Failed to read fw id or fw id is invalid\n"); | 322 | dev_err(&client->dev, |
| 323 | "Failed to read fw id: %d\n", error); | ||
| 324 | return error; | ||
| 325 | } | ||
| 326 | |||
| 327 | dev_err(&client->dev, "Invalid fw id: %#04x\n", ts->hw_version); | ||
| 323 | 328 | ||
| 324 | return -EINVAL; | 329 | return -EINVAL; |
| 325 | } | 330 | } |
| @@ -508,7 +513,7 @@ static int elants_i2c_fastboot(struct i2c_client *client) | |||
| 508 | static int elants_i2c_initialize(struct elants_data *ts) | 513 | static int elants_i2c_initialize(struct elants_data *ts) |
| 509 | { | 514 | { |
| 510 | struct i2c_client *client = ts->client; | 515 | struct i2c_client *client = ts->client; |
| 511 | int error, retry_cnt; | 516 | int error, error2, retry_cnt; |
| 512 | const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 }; | 517 | const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 }; |
| 513 | const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 }; | 518 | const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 }; |
| 514 | u8 buf[HEADER_SIZE]; | 519 | u8 buf[HEADER_SIZE]; |
| @@ -553,18 +558,22 @@ static int elants_i2c_initialize(struct elants_data *ts) | |||
| 553 | } | 558 | } |
| 554 | } | 559 | } |
| 555 | 560 | ||
| 561 | /* hw version is available even if device in recovery state */ | ||
| 562 | error2 = elants_i2c_query_hw_version(ts); | ||
| 556 | if (!error) | 563 | if (!error) |
| 557 | error = elants_i2c_query_fw_id(ts); | 564 | error = error2; |
| 565 | |||
| 558 | if (!error) | 566 | if (!error) |
| 559 | error = elants_i2c_query_fw_version(ts); | 567 | error = elants_i2c_query_fw_version(ts); |
| 568 | if (!error) | ||
| 569 | error = elants_i2c_query_test_version(ts); | ||
| 570 | if (!error) | ||
| 571 | error = elants_i2c_query_bc_version(ts); | ||
| 572 | if (!error) | ||
| 573 | error = elants_i2c_query_ts_info(ts); | ||
| 560 | 574 | ||
| 561 | if (error) { | 575 | if (error) |
| 562 | ts->iap_mode = ELAN_IAP_RECOVERY; | 576 | ts->iap_mode = ELAN_IAP_RECOVERY; |
| 563 | } else { | ||
| 564 | elants_i2c_query_test_version(ts); | ||
| 565 | elants_i2c_query_bc_version(ts); | ||
| 566 | elants_i2c_query_ts_info(ts); | ||
| 567 | } | ||
| 568 | 577 | ||
| 569 | return 0; | 578 | return 0; |
| 570 | } | 579 | } |
diff --git a/drivers/input/touchscreen/ft6236.c b/drivers/input/touchscreen/ft6236.c deleted file mode 100644 index d240d2e212bd..000000000000 --- a/drivers/input/touchscreen/ft6236.c +++ /dev/null | |||
| @@ -1,326 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * FocalTech FT6236 TouchScreen driver. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Focal tech Ltd. | ||
| 5 | * | ||
| 6 | * This software is licensed under the terms of the GNU General Public | ||
| 7 | * License version 2, as published by the Free Software Foundation, and | ||
| 8 | * may be copied, distributed, and modified under those terms. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/gpio/consumer.h> | ||
| 18 | #include <linux/i2c.h> | ||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/input/mt.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/property.h> | ||
| 24 | |||
| 25 | #define FT6236_MAX_TOUCH_POINTS 2 | ||
| 26 | |||
| 27 | #define FT6236_REG_TH_GROUP 0x80 | ||
| 28 | #define FT6236_REG_PERIODACTIVE 0x88 | ||
| 29 | #define FT6236_REG_LIB_VER_H 0xa1 | ||
| 30 | #define FT6236_REG_LIB_VER_L 0xa2 | ||
| 31 | #define FT6236_REG_CIPHER 0xa3 | ||
| 32 | #define FT6236_REG_FIRMID 0xa6 | ||
| 33 | #define FT6236_REG_FOCALTECH_ID 0xa8 | ||
| 34 | #define FT6236_REG_RELEASE_CODE_ID 0xaf | ||
| 35 | |||
| 36 | #define FT6236_EVENT_PRESS_DOWN 0 | ||
| 37 | #define FT6236_EVENT_LIFT_UP 1 | ||
| 38 | #define FT6236_EVENT_CONTACT 2 | ||
| 39 | #define FT6236_EVENT_NO_EVENT 3 | ||
| 40 | |||
| 41 | struct ft6236_data { | ||
| 42 | struct i2c_client *client; | ||
| 43 | struct input_dev *input; | ||
| 44 | struct gpio_desc *reset_gpio; | ||
| 45 | u32 max_x; | ||
| 46 | u32 max_y; | ||
| 47 | bool invert_x; | ||
| 48 | bool invert_y; | ||
| 49 | bool swap_xy; | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* | ||
| 53 | * This struct is a touchpoint as stored in hardware. Note that the id, | ||
| 54 | * as well as the event, are stored in the upper nybble of the hi byte. | ||
| 55 | */ | ||
| 56 | struct ft6236_touchpoint { | ||
| 57 | union { | ||
| 58 | u8 xhi; | ||
| 59 | u8 event; | ||
| 60 | }; | ||
| 61 | u8 xlo; | ||
| 62 | union { | ||
| 63 | u8 yhi; | ||
| 64 | u8 id; | ||
| 65 | }; | ||
| 66 | u8 ylo; | ||
| 67 | u8 weight; | ||
| 68 | u8 misc; | ||
| 69 | } __packed; | ||
| 70 | |||
| 71 | /* This packet represents the register map as read from offset 0 */ | ||
| 72 | struct ft6236_packet { | ||
| 73 | u8 dev_mode; | ||
| 74 | u8 gest_id; | ||
| 75 | u8 touches; | ||
| 76 | struct ft6236_touchpoint points[FT6236_MAX_TOUCH_POINTS]; | ||
| 77 | } __packed; | ||
| 78 | |||
| 79 | static int ft6236_read(struct i2c_client *client, u8 reg, u8 len, void *data) | ||
| 80 | { | ||
| 81 | int error; | ||
| 82 | |||
| 83 | error = i2c_smbus_read_i2c_block_data(client, reg, len, data); | ||
| 84 | if (error < 0) | ||
| 85 | return error; | ||
| 86 | |||
| 87 | if (error != len) | ||
| 88 | return -EIO; | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static irqreturn_t ft6236_interrupt(int irq, void *dev_id) | ||
| 94 | { | ||
| 95 | struct ft6236_data *ft6236 = dev_id; | ||
| 96 | struct device *dev = &ft6236->client->dev; | ||
| 97 | struct input_dev *input = ft6236->input; | ||
| 98 | struct ft6236_packet buf; | ||
| 99 | u8 touches; | ||
| 100 | int i, error; | ||
| 101 | |||
| 102 | error = ft6236_read(ft6236->client, 0, sizeof(buf), &buf); | ||
| 103 | if (error) { | ||
| 104 | dev_err(dev, "read touchdata failed %d\n", error); | ||
| 105 | return IRQ_HANDLED; | ||
| 106 | } | ||
| 107 | |||
| 108 | touches = buf.touches & 0xf; | ||
| 109 | if (touches > FT6236_MAX_TOUCH_POINTS) { | ||
| 110 | dev_dbg(dev, | ||
| 111 | "%d touch points reported, only %d are supported\n", | ||
| 112 | touches, FT6236_MAX_TOUCH_POINTS); | ||
| 113 | touches = FT6236_MAX_TOUCH_POINTS; | ||
| 114 | } | ||
| 115 | |||
| 116 | for (i = 0; i < touches; i++) { | ||
| 117 | struct ft6236_touchpoint *point = &buf.points[i]; | ||
| 118 | u16 x = ((point->xhi & 0xf) << 8) | buf.points[i].xlo; | ||
| 119 | u16 y = ((point->yhi & 0xf) << 8) | buf.points[i].ylo; | ||
| 120 | u8 event = point->event >> 6; | ||
| 121 | u8 id = point->id >> 4; | ||
| 122 | bool act = (event == FT6236_EVENT_PRESS_DOWN || | ||
| 123 | event == FT6236_EVENT_CONTACT); | ||
| 124 | |||
| 125 | input_mt_slot(input, id); | ||
| 126 | input_mt_report_slot_state(input, MT_TOOL_FINGER, act); | ||
| 127 | if (!act) | ||
| 128 | continue; | ||
| 129 | |||
| 130 | if (ft6236->invert_x) | ||
| 131 | x = ft6236->max_x - x; | ||
| 132 | |||
| 133 | if (ft6236->invert_y) | ||
| 134 | y = ft6236->max_y - y; | ||
| 135 | |||
| 136 | if (ft6236->swap_xy) { | ||
| 137 | input_report_abs(input, ABS_MT_POSITION_X, y); | ||
| 138 | input_report_abs(input, ABS_MT_POSITION_Y, x); | ||
| 139 | } else { | ||
| 140 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
| 141 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | input_mt_sync_frame(input); | ||
| 146 | input_sync(input); | ||
| 147 | |||
| 148 | return IRQ_HANDLED; | ||
| 149 | } | ||
| 150 | |||
| 151 | static u8 ft6236_debug_read_byte(struct ft6236_data *ft6236, u8 reg) | ||
| 152 | { | ||
| 153 | struct i2c_client *client = ft6236->client; | ||
| 154 | u8 val = 0; | ||
| 155 | int error; | ||
| 156 | |||
| 157 | error = ft6236_read(client, reg, 1, &val); | ||
| 158 | if (error) | ||
| 159 | dev_dbg(&client->dev, | ||
| 160 | "error reading register 0x%02x: %d\n", reg, error); | ||
| 161 | |||
| 162 | return val; | ||
| 163 | } | ||
| 164 | |||
| 165 | static void ft6236_debug_info(struct ft6236_data *ft6236) | ||
| 166 | { | ||
| 167 | struct device *dev = &ft6236->client->dev; | ||
| 168 | |||
| 169 | dev_dbg(dev, "Touch threshold is %d\n", | ||
| 170 | ft6236_debug_read_byte(ft6236, FT6236_REG_TH_GROUP) * 4); | ||
| 171 | dev_dbg(dev, "Report rate is %dHz\n", | ||
| 172 | ft6236_debug_read_byte(ft6236, FT6236_REG_PERIODACTIVE) * 10); | ||
| 173 | dev_dbg(dev, "Firmware library version 0x%02x%02x\n", | ||
| 174 | ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_H), | ||
| 175 | ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_L)); | ||
| 176 | dev_dbg(dev, "Firmware version 0x%02x\n", | ||
| 177 | ft6236_debug_read_byte(ft6236, FT6236_REG_FIRMID)); | ||
| 178 | dev_dbg(dev, "Chip vendor ID 0x%02x\n", | ||
| 179 | ft6236_debug_read_byte(ft6236, FT6236_REG_CIPHER)); | ||
| 180 | dev_dbg(dev, "CTPM vendor ID 0x%02x\n", | ||
| 181 | ft6236_debug_read_byte(ft6236, FT6236_REG_FOCALTECH_ID)); | ||
| 182 | dev_dbg(dev, "Release code version 0x%02x\n", | ||
| 183 | ft6236_debug_read_byte(ft6236, FT6236_REG_RELEASE_CODE_ID)); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void ft6236_reset(struct ft6236_data *ft6236) | ||
| 187 | { | ||
| 188 | if (!ft6236->reset_gpio) | ||
| 189 | return; | ||
| 190 | |||
| 191 | gpiod_set_value_cansleep(ft6236->reset_gpio, 1); | ||
| 192 | usleep_range(5000, 20000); | ||
| 193 | gpiod_set_value_cansleep(ft6236->reset_gpio, 0); | ||
| 194 | msleep(300); | ||
| 195 | } | ||
| 196 | |||
| 197 | static int ft6236_probe(struct i2c_client *client, | ||
| 198 | const struct i2c_device_id *id) | ||
| 199 | { | ||
| 200 | struct device *dev = &client->dev; | ||
| 201 | struct ft6236_data *ft6236; | ||
| 202 | struct input_dev *input; | ||
| 203 | u32 fuzz_x = 0, fuzz_y = 0; | ||
| 204 | u8 val; | ||
| 205 | int error; | ||
| 206 | |||
| 207 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
| 208 | return -ENXIO; | ||
| 209 | |||
| 210 | if (!client->irq) { | ||
| 211 | dev_err(dev, "irq is missing\n"); | ||
| 212 | return -EINVAL; | ||
| 213 | } | ||
| 214 | |||
| 215 | ft6236 = devm_kzalloc(dev, sizeof(*ft6236), GFP_KERNEL); | ||
| 216 | if (!ft6236) | ||
| 217 | return -ENOMEM; | ||
| 218 | |||
| 219 | ft6236->client = client; | ||
| 220 | ft6236->reset_gpio = devm_gpiod_get_optional(dev, "reset", | ||
| 221 | GPIOD_OUT_LOW); | ||
| 222 | if (IS_ERR(ft6236->reset_gpio)) { | ||
| 223 | error = PTR_ERR(ft6236->reset_gpio); | ||
| 224 | if (error != -EPROBE_DEFER) | ||
| 225 | dev_err(dev, "error getting reset gpio: %d\n", error); | ||
| 226 | return error; | ||
| 227 | } | ||
| 228 | |||
| 229 | ft6236_reset(ft6236); | ||
| 230 | |||
| 231 | /* verify that the controller is present */ | ||
| 232 | error = ft6236_read(client, 0x00, 1, &val); | ||
| 233 | if (error) { | ||
| 234 | dev_err(dev, "failed to read from controller: %d\n", error); | ||
| 235 | return error; | ||
| 236 | } | ||
| 237 | |||
| 238 | ft6236_debug_info(ft6236); | ||
| 239 | |||
| 240 | input = devm_input_allocate_device(dev); | ||
| 241 | if (!input) | ||
| 242 | return -ENOMEM; | ||
| 243 | |||
| 244 | ft6236->input = input; | ||
| 245 | input->name = client->name; | ||
| 246 | input->id.bustype = BUS_I2C; | ||
| 247 | |||
| 248 | if (device_property_read_u32(dev, "touchscreen-size-x", | ||
| 249 | &ft6236->max_x) || | ||
| 250 | device_property_read_u32(dev, "touchscreen-size-y", | ||
| 251 | &ft6236->max_y)) { | ||
| 252 | dev_err(dev, "touchscreen-size-x and/or -y missing\n"); | ||
| 253 | return -EINVAL; | ||
| 254 | } | ||
| 255 | |||
| 256 | device_property_read_u32(dev, "touchscreen-fuzz-x", &fuzz_x); | ||
| 257 | device_property_read_u32(dev, "touchscreen-fuzz-y", &fuzz_y); | ||
| 258 | ft6236->invert_x = device_property_read_bool(dev, | ||
| 259 | "touchscreen-inverted-x"); | ||
| 260 | ft6236->invert_y = device_property_read_bool(dev, | ||
| 261 | "touchscreen-inverted-y"); | ||
| 262 | ft6236->swap_xy = device_property_read_bool(dev, | ||
| 263 | "touchscreen-swapped-x-y"); | ||
| 264 | |||
| 265 | if (ft6236->swap_xy) { | ||
| 266 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
| 267 | ft6236->max_y, fuzz_y, 0); | ||
| 268 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
| 269 | ft6236->max_x, fuzz_x, 0); | ||
| 270 | } else { | ||
| 271 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
| 272 | ft6236->max_x, fuzz_x, 0); | ||
| 273 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
| 274 | ft6236->max_y, fuzz_y, 0); | ||
| 275 | } | ||
| 276 | |||
| 277 | error = input_mt_init_slots(input, FT6236_MAX_TOUCH_POINTS, | ||
| 278 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
| 279 | if (error) | ||
| 280 | return error; | ||
| 281 | |||
| 282 | error = devm_request_threaded_irq(dev, client->irq, NULL, | ||
| 283 | ft6236_interrupt, IRQF_ONESHOT, | ||
| 284 | client->name, ft6236); | ||
| 285 | if (error) { | ||
| 286 | dev_err(dev, "request irq %d failed: %d\n", client->irq, error); | ||
| 287 | return error; | ||
| 288 | } | ||
| 289 | |||
| 290 | error = input_register_device(input); | ||
| 291 | if (error) { | ||
| 292 | dev_err(dev, "failed to register input device: %d\n", error); | ||
| 293 | return error; | ||
| 294 | } | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | #ifdef CONFIG_OF | ||
| 300 | static const struct of_device_id ft6236_of_match[] = { | ||
| 301 | { .compatible = "focaltech,ft6236", }, | ||
| 302 | { } | ||
| 303 | }; | ||
| 304 | MODULE_DEVICE_TABLE(of, ft6236_of_match); | ||
| 305 | #endif | ||
| 306 | |||
| 307 | static const struct i2c_device_id ft6236_id[] = { | ||
| 308 | { "ft6236", }, | ||
| 309 | { } | ||
| 310 | }; | ||
| 311 | MODULE_DEVICE_TABLE(i2c, ft6236_id); | ||
| 312 | |||
| 313 | static struct i2c_driver ft6236_driver = { | ||
| 314 | .driver = { | ||
| 315 | .name = "ft6236", | ||
| 316 | .of_match_table = of_match_ptr(ft6236_of_match), | ||
| 317 | }, | ||
| 318 | .probe = ft6236_probe, | ||
| 319 | .id_table = ft6236_id, | ||
| 320 | }; | ||
| 321 | module_i2c_driver(ft6236_driver); | ||
| 322 | |||
| 323 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
| 324 | MODULE_AUTHOR("Noralf Trønnes <noralf@tronnes.org>"); | ||
| 325 | MODULE_DESCRIPTION("FocalTech FT6236 TouchScreen driver"); | ||
| 326 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index ea3b6a5b83e6..729b3c89324c 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | * HP Jornada 710/720/729 Touchscreen Driver | 13 | * HP Jornada 710/720/729 Touchscreen Driver |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/gpio/consumer.h> | ||
| 16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 17 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| @@ -20,9 +21,7 @@ | |||
| 20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 22 | 23 | ||
| 23 | #include <mach/hardware.h> | ||
| 24 | #include <mach/jornada720.h> | 24 | #include <mach/jornada720.h> |
| 25 | #include <mach/irqs.h> | ||
| 26 | 25 | ||
| 27 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | 26 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); |
| 28 | MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); | 27 | MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver"); |
| @@ -30,6 +29,7 @@ MODULE_LICENSE("GPL v2"); | |||
| 30 | 29 | ||
| 31 | struct jornada_ts { | 30 | struct jornada_ts { |
| 32 | struct input_dev *dev; | 31 | struct input_dev *dev; |
| 32 | struct gpio_desc *gpio; | ||
| 33 | int x_data[4]; /* X sample values */ | 33 | int x_data[4]; /* X sample values */ |
| 34 | int y_data[4]; /* Y sample values */ | 34 | int y_data[4]; /* Y sample values */ |
| 35 | }; | 35 | }; |
| @@ -71,8 +71,8 @@ static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) | |||
| 71 | struct input_dev *input = jornada_ts->dev; | 71 | struct input_dev *input = jornada_ts->dev; |
| 72 | int x, y; | 72 | int x, y; |
| 73 | 73 | ||
| 74 | /* If GPIO_GPIO9 is set to high then report pen up */ | 74 | /* If gpio is high then report pen up */ |
| 75 | if (GPLR & GPIO_GPIO(9)) { | 75 | if (gpiod_get_value(jornada_ts->gpio)) { |
| 76 | input_report_key(input, BTN_TOUCH, 0); | 76 | input_report_key(input, BTN_TOUCH, 0); |
| 77 | input_sync(input); | 77 | input_sync(input); |
| 78 | } else { | 78 | } else { |
| @@ -101,7 +101,7 @@ static int jornada720_ts_probe(struct platform_device *pdev) | |||
| 101 | { | 101 | { |
| 102 | struct jornada_ts *jornada_ts; | 102 | struct jornada_ts *jornada_ts; |
| 103 | struct input_dev *input_dev; | 103 | struct input_dev *input_dev; |
| 104 | int error; | 104 | int error, irq; |
| 105 | 105 | ||
| 106 | jornada_ts = devm_kzalloc(&pdev->dev, sizeof(*jornada_ts), GFP_KERNEL); | 106 | jornada_ts = devm_kzalloc(&pdev->dev, sizeof(*jornada_ts), GFP_KERNEL); |
| 107 | if (!jornada_ts) | 107 | if (!jornada_ts) |
| @@ -113,6 +113,14 @@ static int jornada720_ts_probe(struct platform_device *pdev) | |||
| 113 | 113 | ||
| 114 | platform_set_drvdata(pdev, jornada_ts); | 114 | platform_set_drvdata(pdev, jornada_ts); |
| 115 | 115 | ||
| 116 | jornada_ts->gpio = devm_gpiod_get(&pdev->dev, "penup", GPIOD_IN); | ||
| 117 | if (IS_ERR(jornada_ts->gpio)) | ||
| 118 | return PTR_ERR(jornada_ts->gpio); | ||
| 119 | |||
| 120 | irq = gpiod_to_irq(jornada_ts->gpio); | ||
| 121 | if (irq <= 0) | ||
| 122 | return irq < 0 ? irq : -EINVAL; | ||
| 123 | |||
| 116 | jornada_ts->dev = input_dev; | 124 | jornada_ts->dev = input_dev; |
| 117 | 125 | ||
| 118 | input_dev->name = "HP Jornada 7xx Touchscreen"; | 126 | input_dev->name = "HP Jornada 7xx Touchscreen"; |
| @@ -125,8 +133,7 @@ static int jornada720_ts_probe(struct platform_device *pdev) | |||
| 125 | input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); | 133 | input_set_abs_params(input_dev, ABS_X, 270, 3900, 0, 0); |
| 126 | input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); | 134 | input_set_abs_params(input_dev, ABS_Y, 180, 3700, 0, 0); |
| 127 | 135 | ||
| 128 | error = devm_request_irq(&pdev->dev, IRQ_GPIO9, | 136 | error = devm_request_irq(&pdev->dev, irq, jornada720_ts_interrupt, |
| 129 | jornada720_ts_interrupt, | ||
| 130 | IRQF_TRIGGER_RISING, | 137 | IRQF_TRIGGER_RISING, |
| 131 | "HP7XX Touchscreen driver", pdev); | 138 | "HP7XX Touchscreen driver", pdev); |
| 132 | if (error) { | 139 | if (error) { |
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index 913e25a994b4..ef64f36c5ffc 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
| @@ -37,7 +37,6 @@ struct mc13783_ts_priv { | |||
| 37 | struct input_dev *idev; | 37 | struct input_dev *idev; |
| 38 | struct mc13xxx *mc13xxx; | 38 | struct mc13xxx *mc13xxx; |
| 39 | struct delayed_work work; | 39 | struct delayed_work work; |
| 40 | struct workqueue_struct *workq; | ||
| 41 | unsigned int sample[4]; | 40 | unsigned int sample[4]; |
| 42 | struct mc13xxx_ts_platform_data *touch; | 41 | struct mc13xxx_ts_platform_data *touch; |
| 43 | }; | 42 | }; |
| @@ -54,7 +53,7 @@ static irqreturn_t mc13783_ts_handler(int irq, void *data) | |||
| 54 | * be rescheduled for immediate execution here. However the rearm | 53 | * be rescheduled for immediate execution here. However the rearm |
| 55 | * delay is HZ / 50 which is acceptable. | 54 | * delay is HZ / 50 which is acceptable. |
| 56 | */ | 55 | */ |
| 57 | queue_delayed_work(priv->workq, &priv->work, 0); | 56 | schedule_delayed_work(&priv->work, 0); |
| 58 | 57 | ||
| 59 | return IRQ_HANDLED; | 58 | return IRQ_HANDLED; |
| 60 | } | 59 | } |
| @@ -106,16 +105,18 @@ static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv) | |||
| 106 | 105 | ||
| 107 | dev_dbg(&idev->dev, "report (%d, %d, %d)\n", | 106 | dev_dbg(&idev->dev, "report (%d, %d, %d)\n", |
| 108 | x1, y1, 0x1000 - cr0); | 107 | x1, y1, 0x1000 - cr0); |
| 109 | queue_delayed_work(priv->workq, &priv->work, HZ / 50); | 108 | schedule_delayed_work(&priv->work, HZ / 50); |
| 110 | } else | 109 | } else { |
| 111 | dev_dbg(&idev->dev, "report release\n"); | 110 | dev_dbg(&idev->dev, "report release\n"); |
| 111 | } | ||
| 112 | 112 | ||
| 113 | input_report_abs(idev, ABS_PRESSURE, | 113 | input_report_abs(idev, ABS_PRESSURE, |
| 114 | cr0 ? 0x1000 - cr0 : cr0); | 114 | cr0 ? 0x1000 - cr0 : cr0); |
| 115 | input_report_key(idev, BTN_TOUCH, cr0); | 115 | input_report_key(idev, BTN_TOUCH, cr0); |
| 116 | input_sync(idev); | 116 | input_sync(idev); |
| 117 | } else | 117 | } else { |
| 118 | dev_dbg(&idev->dev, "discard event\n"); | 118 | dev_dbg(&idev->dev, "discard event\n"); |
| 119 | } | ||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | static void mc13783_ts_work(struct work_struct *work) | 122 | static void mc13783_ts_work(struct work_struct *work) |
| @@ -189,14 +190,6 @@ static int __init mc13783_ts_probe(struct platform_device *pdev) | |||
| 189 | goto err_free_mem; | 190 | goto err_free_mem; |
| 190 | } | 191 | } |
| 191 | 192 | ||
| 192 | /* | ||
| 193 | * We need separate workqueue because mc13783_adc_do_conversion | ||
| 194 | * uses keventd and thus would deadlock. | ||
| 195 | */ | ||
| 196 | priv->workq = create_singlethread_workqueue("mc13783_ts"); | ||
| 197 | if (!priv->workq) | ||
| 198 | goto err_free_mem; | ||
| 199 | |||
| 200 | idev->name = MC13783_TS_NAME; | 193 | idev->name = MC13783_TS_NAME; |
| 201 | idev->dev.parent = &pdev->dev; | 194 | idev->dev.parent = &pdev->dev; |
| 202 | 195 | ||
| @@ -215,14 +208,12 @@ static int __init mc13783_ts_probe(struct platform_device *pdev) | |||
| 215 | if (ret) { | 208 | if (ret) { |
| 216 | dev_err(&pdev->dev, | 209 | dev_err(&pdev->dev, |
| 217 | "register input device failed with %d\n", ret); | 210 | "register input device failed with %d\n", ret); |
| 218 | goto err_destroy_wq; | 211 | goto err_free_mem; |
| 219 | } | 212 | } |
| 220 | 213 | ||
| 221 | platform_set_drvdata(pdev, priv); | 214 | platform_set_drvdata(pdev, priv); |
| 222 | return 0; | 215 | return 0; |
| 223 | 216 | ||
| 224 | err_destroy_wq: | ||
| 225 | destroy_workqueue(priv->workq); | ||
| 226 | err_free_mem: | 217 | err_free_mem: |
| 227 | input_free_device(idev); | 218 | input_free_device(idev); |
| 228 | kfree(priv); | 219 | kfree(priv); |
| @@ -233,7 +224,6 @@ static int mc13783_ts_remove(struct platform_device *pdev) | |||
| 233 | { | 224 | { |
| 234 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); | 225 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); |
| 235 | 226 | ||
| 236 | destroy_workqueue(priv->workq); | ||
| 237 | input_unregister_device(priv->idev); | 227 | input_unregister_device(priv->idev); |
| 238 | kfree(priv); | 228 | kfree(priv); |
| 239 | 229 | ||
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index d159e14f4d20..3bb0637d832e 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
| @@ -11,10 +11,6 @@ | |||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public | ||
| 16 | * License along with this library; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | 14 | */ |
| 19 | 15 | ||
| 20 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| @@ -404,7 +400,6 @@ static int __maybe_unused pixcir_i2c_ts_resume(struct device *dev) | |||
| 404 | mutex_lock(&input->mutex); | 400 | mutex_lock(&input->mutex); |
| 405 | 401 | ||
| 406 | if (device_may_wakeup(&client->dev)) { | 402 | if (device_may_wakeup(&client->dev)) { |
| 407 | |||
| 408 | if (!input->users) { | 403 | if (!input->users) { |
| 409 | ret = pixcir_stop(ts); | 404 | ret = pixcir_stop(ts); |
| 410 | if (ret) { | 405 | if (ret) { |
| @@ -431,13 +426,7 @@ static const struct of_device_id pixcir_of_match[]; | |||
| 431 | static int pixcir_parse_dt(struct device *dev, | 426 | static int pixcir_parse_dt(struct device *dev, |
| 432 | struct pixcir_i2c_ts_data *tsdata) | 427 | struct pixcir_i2c_ts_data *tsdata) |
| 433 | { | 428 | { |
| 434 | const struct of_device_id *match; | 429 | tsdata->chip = of_device_get_match_data(dev); |
| 435 | |||
| 436 | match = of_match_device(of_match_ptr(pixcir_of_match), dev); | ||
| 437 | if (!match) | ||
| 438 | return -EINVAL; | ||
| 439 | |||
| 440 | tsdata->chip = (const struct pixcir_i2c_chip_data *)match->data; | ||
| 441 | if (!tsdata->chip) | 430 | if (!tsdata->chip) |
| 442 | return -EINVAL; | 431 | return -EINVAL; |
| 443 | 432 | ||
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index 73861ad22df4..a9132603ab34 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <asm/unaligned.h> | 23 | #include <asm/unaligned.h> |
| 24 | 24 | ||
| 25 | #define WDT87XX_NAME "wdt87xx_i2c" | 25 | #define WDT87XX_NAME "wdt87xx_i2c" |
| 26 | #define WDT87XX_DRV_VER "0.9.7" | 26 | #define WDT87XX_DRV_VER "0.9.8" |
| 27 | #define WDT87XX_FW_NAME "wdt87xx_fw.bin" | 27 | #define WDT87XX_FW_NAME "wdt87xx_fw.bin" |
| 28 | #define WDT87XX_CFG_NAME "wdt87xx_cfg.bin" | 28 | #define WDT87XX_CFG_NAME "wdt87xx_cfg.bin" |
| 29 | 29 | ||
| @@ -157,6 +157,7 @@ | |||
| 157 | /* Controller requires minimum 300us between commands */ | 157 | /* Controller requires minimum 300us between commands */ |
| 158 | #define WDT_COMMAND_DELAY_MS 2 | 158 | #define WDT_COMMAND_DELAY_MS 2 |
| 159 | #define WDT_FLASH_WRITE_DELAY_MS 4 | 159 | #define WDT_FLASH_WRITE_DELAY_MS 4 |
| 160 | #define WDT_FLASH_ERASE_DELAY_MS 200 | ||
| 160 | #define WDT_FW_RESET_TIME 2500 | 161 | #define WDT_FW_RESET_TIME 2500 |
| 161 | 162 | ||
| 162 | struct wdt87xx_sys_param { | 163 | struct wdt87xx_sys_param { |
| @@ -726,7 +727,7 @@ static int wdt87xx_write_firmware(struct i2c_client *client, const void *chunk) | |||
| 726 | break; | 727 | break; |
| 727 | } | 728 | } |
| 728 | 729 | ||
| 729 | msleep(50); | 730 | msleep(WDT_FLASH_ERASE_DELAY_MS); |
| 730 | 731 | ||
| 731 | error = wdt87xx_write_data(client, data, start_addr, | 732 | error = wdt87xx_write_data(client, data, start_addr, |
| 732 | page_size); | 733 | page_size); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 1534e9b0788c..90d6be3c26cc 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
| @@ -500,7 +500,7 @@ static int wm97xx_ts_input_open(struct input_dev *idev) | |||
| 500 | { | 500 | { |
| 501 | struct wm97xx *wm = input_get_drvdata(idev); | 501 | struct wm97xx *wm = input_get_drvdata(idev); |
| 502 | 502 | ||
| 503 | wm->ts_workq = create_singlethread_workqueue("kwm97xx"); | 503 | wm->ts_workq = alloc_ordered_workqueue("kwm97xx", 0); |
| 504 | if (wm->ts_workq == NULL) { | 504 | if (wm->ts_workq == NULL) { |
| 505 | dev_err(wm->dev, | 505 | dev_err(wm->dev, |
| 506 | "Failed to create workqueue\n"); | 506 | "Failed to create workqueue\n"); |
