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 | |
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
...
34 files changed, 1033 insertions, 519 deletions
diff --git a/Documentation/devicetree/bindings/input/adc-keys.txt b/Documentation/devicetree/bindings/input/adc-keys.txt new file mode 100644 index 000000000000..e551814629b4 --- /dev/null +++ b/Documentation/devicetree/bindings/input/adc-keys.txt | |||
@@ -0,0 +1,49 @@ | |||
1 | ADC attached resistor ladder buttons | ||
2 | ------------------------------------ | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: "adc-keys" | ||
6 | - io-channels: Phandle to an ADC channel | ||
7 | - io-channel-names = "buttons"; | ||
8 | - keyup-threshold-microvolt: Voltage at which all the keys are considered up. | ||
9 | |||
10 | Optional properties: | ||
11 | - poll-interval: Poll interval time in milliseconds | ||
12 | - autorepeat: Boolean, Enable auto repeat feature of Linux input | ||
13 | subsystem. | ||
14 | |||
15 | Each button (key) is represented as a sub-node of "adc-keys": | ||
16 | |||
17 | Required subnode-properties: | ||
18 | - label: Descriptive name of the key. | ||
19 | - linux,code: Keycode to emit. | ||
20 | - press-threshold-microvolt: Voltage ADC input when this key is pressed. | ||
21 | |||
22 | Example: | ||
23 | |||
24 | #include <dt-bindings/input/input.h> | ||
25 | |||
26 | adc-keys { | ||
27 | compatible = "adc-keys"; | ||
28 | io-channels = <&lradc 0>; | ||
29 | io-channel-names = "buttons"; | ||
30 | keyup-threshold-microvolt = <2000000>; | ||
31 | |||
32 | button-up { | ||
33 | label = "Volume Up"; | ||
34 | linux,code = <KEY_VOLUMEUP>; | ||
35 | press-threshold-microvolt = <1500000>; | ||
36 | }; | ||
37 | |||
38 | button-down { | ||
39 | label = "Volume Down"; | ||
40 | linux,code = <KEY_VOLUMEDOWN>; | ||
41 | press-threshold-microvolt = <1000000>; | ||
42 | }; | ||
43 | |||
44 | button-enter { | ||
45 | label = "Enter"; | ||
46 | linux,code = <KEY_ENTER>; | ||
47 | press-threshold-microvolt = <500000>; | ||
48 | }; | ||
49 | }; | ||
diff --git a/Documentation/devicetree/bindings/input/gpio-decoder.txt b/Documentation/devicetree/bindings/input/gpio-decoder.txt new file mode 100644 index 000000000000..14a77fb96cf0 --- /dev/null +++ b/Documentation/devicetree/bindings/input/gpio-decoder.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | * GPIO Decoder DT bindings | ||
2 | |||
3 | Required Properties: | ||
4 | - compatible: should be "gpio-decoder" | ||
5 | - gpios: a spec of gpios (at least two) to be decoded to a number with | ||
6 | first entry representing the MSB. | ||
7 | |||
8 | Optional Properties: | ||
9 | - decoder-max-value: Maximum possible value that can be reported by | ||
10 | the gpios. | ||
11 | - linux,axis: the input subsystem axis to map to (ABS_X/ABS_Y). | ||
12 | Defaults to 0 (ABS_X). | ||
13 | |||
14 | Example: | ||
15 | gpio-decoder0 { | ||
16 | compatible = "gpio-decoder"; | ||
17 | gpios = <&pca9536 3 GPIO_ACTIVE_HIGH>, | ||
18 | <&pca9536 2 GPIO_ACTIVE_HIGH>, | ||
19 | <&pca9536 1 GPIO_ACTIVE_HIGH>, | ||
20 | <&pca9536 0 GPIO_ACTIVE_HIGH>; | ||
21 | linux,axis = <0>; /* ABS_X */ | ||
22 | decoder-max-value = <9>; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/input/gpio-keys-polled.txt b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt index 95d0fb11a787..4d9a3717eaaf 100644 --- a/Documentation/devicetree/bindings/input/gpio-keys-polled.txt +++ b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt | |||
@@ -34,11 +34,10 @@ Example nodes: | |||
34 | 34 | ||
35 | gpio_keys_polled { | 35 | gpio_keys_polled { |
36 | compatible = "gpio-keys-polled"; | 36 | compatible = "gpio-keys-polled"; |
37 | #address-cells = <1>; | ||
38 | #size-cells = <0>; | ||
39 | poll-interval = <100>; | 37 | poll-interval = <100>; |
40 | autorepeat; | 38 | autorepeat; |
41 | button@21 { | 39 | |
40 | button21 { | ||
42 | label = "GPIO Key UP"; | 41 | label = "GPIO Key UP"; |
43 | linux,code = <103>; | 42 | linux,code = <103>; |
44 | gpios = <&gpio1 0 1>; | 43 | gpios = <&gpio1 0 1>; |
diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt index f99528da1b1d..6db22103e2dd 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt | |||
@@ -19,6 +19,7 @@ Required properties: | |||
19 | or: "edt,edt-ft5306" | 19 | or: "edt,edt-ft5306" |
20 | or: "edt,edt-ft5406" | 20 | or: "edt,edt-ft5406" |
21 | or: "edt,edt-ft5506" | 21 | or: "edt,edt-ft5506" |
22 | or: "focaltech,ft6236" | ||
22 | 23 | ||
23 | - reg: I2C slave address of the chip (0x38) | 24 | - reg: I2C slave address of the chip (0x38) |
24 | - interrupt-parent: a phandle pointing to the interrupt controller | 25 | - interrupt-parent: a phandle pointing to the interrupt controller |
@@ -43,6 +44,13 @@ Optional properties: | |||
43 | 44 | ||
44 | - offset: allows setting the edge compensation in the range from | 45 | - offset: allows setting the edge compensation in the range from |
45 | 0 to 31. | 46 | 0 to 31. |
47 | - touchscreen-size-x : See touchscreen.txt | ||
48 | - touchscreen-size-y : See touchscreen.txt | ||
49 | - touchscreen-fuzz-x : See touchscreen.txt | ||
50 | - touchscreen-fuzz-y : See touchscreen.txt | ||
51 | - touchscreen-inverted-x : See touchscreen.txt | ||
52 | - touchscreen-inverted-y : See touchscreen.txt | ||
53 | - touchscreen-swapped-x-y : See touchscreen.txt | ||
46 | 54 | ||
47 | Example: | 55 | Example: |
48 | polytouch: edt-ft5x06@38 { | 56 | polytouch: edt-ft5x06@38 { |
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ektf2127.txt b/Documentation/devicetree/bindings/input/touchscreen/ektf2127.txt new file mode 100644 index 000000000000..5a19f4c3e9d7 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/ektf2127.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | * Elan eKTF2127 I2C touchscreen controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "elan,ektf2127" | ||
5 | - reg : I2C slave address of the chip (0x40) | ||
6 | - interrupt-parent : a phandle pointing to the interrupt controller | ||
7 | serving the interrupt for this chip | ||
8 | - interrupts : interrupt specification for the ektf2127 interrupt | ||
9 | - power-gpios : GPIO specification for the pin connected to the | ||
10 | ektf2127's wake input. This needs to be driven high | ||
11 | to take ektf2127 out of it's low power state | ||
12 | |||
13 | For additional optional properties see: touchscreen.txt | ||
14 | |||
15 | Example: | ||
16 | |||
17 | i2c@00000000 { | ||
18 | ektf2127: touchscreen@15 { | ||
19 | compatible = "elan,ektf2127"; | ||
20 | reg = <0x15>; | ||
21 | interrupt-parent = <&pio>; | ||
22 | interrupts = <6 11 IRQ_TYPE_EDGE_FALLING> | ||
23 | power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; | ||
24 | touchscreen-inverted-x; | ||
25 | touchscreen-swapped-x-y; | ||
26 | }; | ||
27 | }; | ||
diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt b/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt deleted file mode 100644 index 777521da3da5..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | * FocalTech FT6236 I2C touchscreen controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "focaltech,ft6236" | ||
5 | - reg : I2C slave address of the chip (0x38) | ||
6 | - interrupt-parent : a phandle pointing to the interrupt controller | ||
7 | serving the interrupt for this chip | ||
8 | - interrupts : interrupt specification for the touch controller | ||
9 | interrupt | ||
10 | - reset-gpios : GPIO specification for the RSTN input | ||
11 | - touchscreen-size-x : horizontal resolution of touchscreen (in pixels) | ||
12 | - touchscreen-size-y : vertical resolution of touchscreen (in pixels) | ||
13 | |||
14 | Optional properties: | ||
15 | - touchscreen-fuzz-x : horizontal noise value of the absolute input | ||
16 | device (in pixels) | ||
17 | - touchscreen-fuzz-y : vertical noise value of the absolute input | ||
18 | device (in pixels) | ||
19 | - touchscreen-inverted-x : X axis is inverted (boolean) | ||
20 | - touchscreen-inverted-y : Y axis is inverted (boolean) | ||
21 | - touchscreen-swapped-x-y: X and Y axis are swapped (boolean) | ||
22 | Swapping is done after inverting the axis | ||
23 | |||
24 | Example: | ||
25 | |||
26 | ft6x06@38 { | ||
27 | compatible = "focaltech,ft6236"; | ||
28 | reg = <0x38>; | ||
29 | interrupt-parent = <&gpio>; | ||
30 | interrupts = <23 2>; | ||
31 | touchscreen-size-x = <320>; | ||
32 | touchscreen-size-y = <480>; | ||
33 | touchscreen-inverted-x; | ||
34 | touchscreen-swapped-x-y; | ||
35 | }; | ||
diff --git a/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt b/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt index e30e0b93f2b3..3e5b9793341f 100644 --- a/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt +++ b/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt | |||
@@ -1,13 +1,24 @@ | |||
1 | Texas Instruments TPS65218 power button | 1 | Texas Instruments TPS65217 and TPS65218 power button |
2 | |||
3 | This module is part of the TPS65217/TPS65218. For more details about the whole | ||
4 | TPS65217 chip see Documentation/devicetree/bindings/regulator/tps65217.txt. | ||
2 | 5 | ||
3 | This driver provides a simple power button event via an Interrupt. | 6 | This driver provides a simple power button event via an Interrupt. |
4 | 7 | ||
5 | Required properties: | 8 | Required properties: |
6 | - compatible: should be "ti,tps65218-pwrbutton" | 9 | - compatible: should be "ti,tps65217-pwrbutton" or "ti,tps65218-pwrbutton" |
10 | |||
11 | Required properties for TPS65218: | ||
7 | - interrupts: should be one of the following | 12 | - interrupts: should be one of the following |
8 | - <3 IRQ_TYPE_EDGE_BOTH>: For controllers compatible with tps65218 | 13 | - <3 IRQ_TYPE_EDGE_BOTH>: For controllers compatible with tps65218 |
9 | 14 | ||
10 | Example: | 15 | Examples: |
16 | |||
17 | &tps { | ||
18 | tps65217-pwrbutton { | ||
19 | compatible = "ti,tps65217-pwrbutton"; | ||
20 | }; | ||
21 | }; | ||
11 | 22 | ||
12 | &tps { | 23 | &tps { |
13 | power-button { | 24 | power-button { |
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index c0b1f5bafae4..0a2ca9be00e6 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/gpio/machine.h> | ||
20 | #include <linux/platform_data/sa11x0-serial.h> | 21 | #include <linux/platform_data/sa11x0-serial.h> |
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/ioport.h> | 23 | #include <linux/ioport.h> |
@@ -217,9 +218,22 @@ static struct platform_device jornada_ssp_device = { | |||
217 | .id = -1, | 218 | .id = -1, |
218 | }; | 219 | }; |
219 | 220 | ||
221 | static struct resource jornada_kbd_resources[] = { | ||
222 | DEFINE_RES_IRQ(IRQ_GPIO0), | ||
223 | }; | ||
224 | |||
220 | static struct platform_device jornada_kbd_device = { | 225 | static struct platform_device jornada_kbd_device = { |
221 | .name = "jornada720_kbd", | 226 | .name = "jornada720_kbd", |
222 | .id = -1, | 227 | .id = -1, |
228 | .num_resources = ARRAY_SIZE(jornada_kbd_resources), | ||
229 | .resource = jornada_kbd_resources, | ||
230 | }; | ||
231 | |||
232 | static struct gpiod_lookup_table jornada_ts_gpiod_table = { | ||
233 | .dev_id = "jornada_ts", | ||
234 | .table = { | ||
235 | GPIO_LOOKUP("gpio", 9, "penup", GPIO_ACTIVE_HIGH), | ||
236 | }, | ||
223 | }; | 237 | }; |
224 | 238 | ||
225 | static struct platform_device jornada_ts_device = { | 239 | static struct platform_device jornada_ts_device = { |
@@ -250,6 +264,8 @@ static int __init jornada720_init(void) | |||
250 | GPSR = GPIO_GPIO20; /* restart gpio20 */ | 264 | GPSR = GPIO_GPIO20; /* restart gpio20 */ |
251 | udelay(20); /* give it some time to restart */ | 265 | udelay(20); /* give it some time to restart */ |
252 | 266 | ||
267 | gpiod_add_lookup_table(&jornada_ts_gpiod_table); | ||
268 | |||
253 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); | 269 | ret = platform_add_devices(devices, ARRAY_SIZE(devices)); |
254 | } | 270 | } |
255 | 271 | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 509608c95994..cbd75cf44739 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -12,6 +12,21 @@ menuconfig INPUT_KEYBOARD | |||
12 | 12 | ||
13 | if INPUT_KEYBOARD | 13 | if INPUT_KEYBOARD |
14 | 14 | ||
15 | config KEYBOARD_ADC | ||
16 | tristate "ADC Ladder Buttons" | ||
17 | depends on IIO | ||
18 | select INPUT_POLLDEV | ||
19 | help | ||
20 | This driver implements support for buttons connected | ||
21 | to an ADC using a resistor ladder. | ||
22 | |||
23 | Say Y here if your device has such buttons connected to an ADC. Your | ||
24 | board-specific setup logic must also provide a configuration data | ||
25 | for mapping voltages to buttons. | ||
26 | |||
27 | To compile this driver as a module, choose M here: the | ||
28 | module will be called adc_keys. | ||
29 | |||
15 | config KEYBOARD_ADP5520 | 30 | config KEYBOARD_ADP5520 |
16 | tristate "Keypad Support for ADP5520 PMIC" | 31 | tristate "Keypad Support for ADP5520 PMIC" |
17 | depends on PMIC_ADP5520 | 32 | depends on PMIC_ADP5520 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 1d416ddf84e4..d9f4cfcf3410 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_ADC) += adc-keys.o | ||
7 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o | 8 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o |
8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | 9 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o |
9 | obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o | 10 | obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o |
diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c new file mode 100644 index 000000000000..f8cf2ccacefd --- /dev/null +++ b/drivers/input/keyboard/adc-keys.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * Input driver for resistor ladder connected on ADC | ||
3 | * | ||
4 | * Copyright (c) 2016 Alexandre Belloni | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/err.h> | ||
12 | #include <linux/iio/consumer.h> | ||
13 | #include <linux/iio/types.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/input-polldev.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/property.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | struct adc_keys_button { | ||
24 | u32 voltage; | ||
25 | u32 keycode; | ||
26 | }; | ||
27 | |||
28 | struct adc_keys_state { | ||
29 | struct iio_channel *channel; | ||
30 | u32 num_keys; | ||
31 | u32 last_key; | ||
32 | u32 keyup_voltage; | ||
33 | const struct adc_keys_button *map; | ||
34 | }; | ||
35 | |||
36 | static void adc_keys_poll(struct input_polled_dev *dev) | ||
37 | { | ||
38 | struct adc_keys_state *st = dev->private; | ||
39 | int i, value, ret; | ||
40 | u32 diff, closest = 0xffffffff; | ||
41 | int keycode = 0; | ||
42 | |||
43 | ret = iio_read_channel_processed(st->channel, &value); | ||
44 | if (unlikely(ret < 0)) { | ||
45 | /* Forcibly release key if any was pressed */ | ||
46 | value = st->keyup_voltage; | ||
47 | } else { | ||
48 | for (i = 0; i < st->num_keys; i++) { | ||
49 | diff = abs(st->map[i].voltage - value); | ||
50 | if (diff < closest) { | ||
51 | closest = diff; | ||
52 | keycode = st->map[i].keycode; | ||
53 | } | ||
54 | } | ||
55 | } | ||
56 | |||
57 | if (abs(st->keyup_voltage - value) < closest) | ||
58 | keycode = 0; | ||
59 | |||
60 | if (st->last_key && st->last_key != keycode) | ||
61 | input_report_key(dev->input, st->last_key, 0); | ||
62 | |||
63 | if (keycode) | ||
64 | input_report_key(dev->input, keycode, 1); | ||
65 | |||
66 | input_sync(dev->input); | ||
67 | st->last_key = keycode; | ||
68 | } | ||
69 | |||
70 | static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st) | ||
71 | { | ||
72 | struct adc_keys_button *map; | ||
73 | struct fwnode_handle *child; | ||
74 | int i; | ||
75 | |||
76 | st->num_keys = device_get_child_node_count(dev); | ||
77 | if (st->num_keys == 0) { | ||
78 | dev_err(dev, "keymap is missing\n"); | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | |||
82 | map = devm_kmalloc_array(dev, st->num_keys, sizeof(*map), GFP_KERNEL); | ||
83 | if (!map) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | i = 0; | ||
87 | device_for_each_child_node(dev, child) { | ||
88 | if (fwnode_property_read_u32(child, "press-threshold-microvolt", | ||
89 | &map[i].voltage)) { | ||
90 | dev_err(dev, "Key with invalid or missing voltage\n"); | ||
91 | fwnode_handle_put(child); | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | map[i].voltage /= 1000; | ||
95 | |||
96 | if (fwnode_property_read_u32(child, "linux,code", | ||
97 | &map[i].keycode)) { | ||
98 | dev_err(dev, "Key with invalid or missing linux,code\n"); | ||
99 | fwnode_handle_put(child); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | i++; | ||
104 | } | ||
105 | |||
106 | st->map = map; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int adc_keys_probe(struct platform_device *pdev) | ||
111 | { | ||
112 | struct device *dev = &pdev->dev; | ||
113 | struct adc_keys_state *st; | ||
114 | struct input_polled_dev *poll_dev; | ||
115 | struct input_dev *input; | ||
116 | enum iio_chan_type type; | ||
117 | int i, value; | ||
118 | int error; | ||
119 | |||
120 | st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); | ||
121 | if (!st) | ||
122 | return -ENOMEM; | ||
123 | |||
124 | st->channel = devm_iio_channel_get(dev, "buttons"); | ||
125 | if (IS_ERR(st->channel)) | ||
126 | return PTR_ERR(st->channel); | ||
127 | |||
128 | if (!st->channel->indio_dev) | ||
129 | return -ENXIO; | ||
130 | |||
131 | error = iio_get_channel_type(st->channel, &type); | ||
132 | if (error < 0) | ||
133 | return error; | ||
134 | |||
135 | if (type != IIO_VOLTAGE) { | ||
136 | dev_err(dev, "Incompatible channel type %d\n", type); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | if (device_property_read_u32(dev, "keyup-threshold-microvolt", | ||
141 | &st->keyup_voltage)) { | ||
142 | dev_err(dev, "Invalid or missing keyup voltage\n"); | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | st->keyup_voltage /= 1000; | ||
146 | |||
147 | error = adc_keys_load_keymap(dev, st); | ||
148 | if (error) | ||
149 | return error; | ||
150 | |||
151 | platform_set_drvdata(pdev, st); | ||
152 | |||
153 | poll_dev = devm_input_allocate_polled_device(dev); | ||
154 | if (!poll_dev) { | ||
155 | dev_err(dev, "failed to allocate input device\n"); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | if (!device_property_read_u32(dev, "poll-interval", &value)) | ||
160 | poll_dev->poll_interval = value; | ||
161 | |||
162 | poll_dev->poll = adc_keys_poll; | ||
163 | poll_dev->private = st; | ||
164 | |||
165 | input = poll_dev->input; | ||
166 | |||
167 | input->name = pdev->name; | ||
168 | input->phys = "adc-keys/input0"; | ||
169 | |||
170 | input->id.bustype = BUS_HOST; | ||
171 | input->id.vendor = 0x0001; | ||
172 | input->id.product = 0x0001; | ||
173 | input->id.version = 0x0100; | ||
174 | |||
175 | __set_bit(EV_KEY, input->evbit); | ||
176 | for (i = 0; i < st->num_keys; i++) | ||
177 | __set_bit(st->map[i].keycode, input->keybit); | ||
178 | |||
179 | if (device_property_read_bool(dev, "autorepeat")) | ||
180 | __set_bit(EV_REP, input->evbit); | ||
181 | |||
182 | error = input_register_polled_device(poll_dev); | ||
183 | if (error) { | ||
184 | dev_err(dev, "Unable to register input device: %d\n", error); | ||
185 | return error; | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | #ifdef CONFIG_OF | ||
192 | static const struct of_device_id adc_keys_of_match[] = { | ||
193 | { .compatible = "adc-keys", }, | ||
194 | { } | ||
195 | }; | ||
196 | MODULE_DEVICE_TABLE(of, adc_keys_of_match); | ||
197 | #endif | ||
198 | |||
199 | static struct platform_driver __refdata adc_keys_driver = { | ||
200 | .driver = { | ||
201 | .name = "adc_keys", | ||
202 | .of_match_table = of_match_ptr(adc_keys_of_match), | ||
203 | }, | ||
204 | .probe = adc_keys_probe, | ||
205 | }; | ||
206 | module_platform_driver(adc_keys_driver); | ||
207 | |||
208 | MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>"); | ||
209 | MODULE_DESCRIPTION("Input driver for resistor ladder connected on ADC"); | ||
210 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 421d9c55b0e8..1277c39f9482 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | 26 | ||
27 | #include <mach/jornada720.h> | 27 | #include <mach/jornada720.h> |
28 | #include <mach/hardware.h> | ||
29 | #include <mach/irqs.h> | ||
30 | 28 | ||
31 | MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); | 29 | MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>"); |
32 | MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); | 30 | MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver"); |
@@ -66,10 +64,8 @@ static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) | |||
66 | jornada_ssp_start(); | 64 | jornada_ssp_start(); |
67 | 65 | ||
68 | if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { | 66 | if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) { |
69 | printk(KERN_DEBUG | 67 | dev_dbg(&pdev->dev, |
70 | "jornada720_kbd: " | 68 | "GetKeycode command failed with ETIMEDOUT, flushed bus\n"); |
71 | "GetKeycode command failed with ETIMEDOUT, " | ||
72 | "flushed bus\n"); | ||
73 | } else { | 69 | } else { |
74 | /* How many keycodes are waiting for us? */ | 70 | /* How many keycodes are waiting for us? */ |
75 | count = jornada_ssp_byte(TXDUMMY); | 71 | count = jornada_ssp_byte(TXDUMMY); |
@@ -97,14 +93,16 @@ static int jornada720_kbd_probe(struct platform_device *pdev) | |||
97 | { | 93 | { |
98 | struct jornadakbd *jornadakbd; | 94 | struct jornadakbd *jornadakbd; |
99 | struct input_dev *input_dev; | 95 | struct input_dev *input_dev; |
100 | int i, err; | 96 | int i, err, irq; |
101 | 97 | ||
102 | jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); | 98 | irq = platform_get_irq(pdev, 0); |
103 | input_dev = input_allocate_device(); | 99 | if (irq <= 0) |
104 | if (!jornadakbd || !input_dev) { | 100 | return irq < 0 ? irq : -EINVAL; |
105 | err = -ENOMEM; | 101 | |
106 | goto fail1; | 102 | jornadakbd = devm_kzalloc(&pdev->dev, sizeof(*jornadakbd), GFP_KERNEL); |
107 | } | 103 | input_dev = devm_input_allocate_device(&pdev->dev); |
104 | if (!jornadakbd || !input_dev) | ||
105 | return -ENOMEM; | ||
108 | 106 | ||
109 | platform_set_drvdata(pdev, jornadakbd); | 107 | platform_set_drvdata(pdev, jornadakbd); |
110 | 108 | ||
@@ -127,40 +125,16 @@ static int jornada720_kbd_probe(struct platform_device *pdev) | |||
127 | 125 | ||
128 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 126 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
129 | 127 | ||
130 | err = request_irq(IRQ_GPIO0, | 128 | err = devm_request_irq(&pdev->dev, irq, jornada720_kbd_interrupt, |
131 | jornada720_kbd_interrupt, | 129 | IRQF_TRIGGER_FALLING, "jornadakbd", pdev); |
132 | IRQF_TRIGGER_FALLING, | ||
133 | "jornadakbd", pdev); | ||
134 | if (err) { | 130 | if (err) { |
135 | printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n"); | 131 | dev_err(&pdev->dev, "unable to grab IRQ%d: %d\n", irq, err); |
136 | goto fail1; | 132 | return err; |
137 | } | 133 | } |
138 | 134 | ||
139 | err = input_register_device(jornadakbd->input); | 135 | return input_register_device(jornadakbd->input); |
140 | if (err) | ||
141 | goto fail2; | ||
142 | |||
143 | return 0; | ||
144 | |||
145 | fail2: /* IRQ, DEVICE, MEMORY */ | ||
146 | free_irq(IRQ_GPIO0, pdev); | ||
147 | fail1: /* DEVICE, MEMORY */ | ||
148 | input_free_device(input_dev); | ||
149 | kfree(jornadakbd); | ||
150 | return err; | ||
151 | }; | 136 | }; |
152 | 137 | ||
153 | static int jornada720_kbd_remove(struct platform_device *pdev) | ||
154 | { | ||
155 | struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); | ||
156 | |||
157 | free_irq(IRQ_GPIO0, pdev); | ||
158 | input_unregister_device(jornadakbd->input); | ||
159 | kfree(jornadakbd); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /* work with hotplug and coldplug */ | 138 | /* work with hotplug and coldplug */ |
165 | MODULE_ALIAS("platform:jornada720_kbd"); | 139 | MODULE_ALIAS("platform:jornada720_kbd"); |
166 | 140 | ||
@@ -169,6 +143,5 @@ static struct platform_driver jornada720_kbd_driver = { | |||
169 | .name = "jornada720_kbd", | 143 | .name = "jornada720_kbd", |
170 | }, | 144 | }, |
171 | .probe = jornada720_kbd_probe, | 145 | .probe = jornada720_kbd_probe, |
172 | .remove = jornada720_kbd_remove, | ||
173 | }; | 146 | }; |
174 | module_platform_driver(jornada720_kbd_driver); | 147 | module_platform_driver(jornada720_kbd_driver); |
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index 24a9f599082f..7544888c4749 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c | |||
@@ -168,7 +168,6 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) | |||
168 | error = input_register_device(input); | 168 | error = input_register_device(input); |
169 | if (error < 0) { | 169 | if (error < 0) { |
170 | dev_err(&pdev->dev, "failed to register input device\n"); | 170 | dev_err(&pdev->dev, "failed to register input device\n"); |
171 | input_free_device(input); | ||
172 | return error; | 171 | return error; |
173 | } | 172 | } |
174 | 173 | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index efb0ca871327..7ffb614ce566 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -292,6 +292,18 @@ config INPUT_GPIO_TILT_POLLED | |||
292 | To compile this driver as a module, choose M here: the | 292 | To compile this driver as a module, choose M here: the |
293 | module will be called gpio_tilt_polled. | 293 | module will be called gpio_tilt_polled. |
294 | 294 | ||
295 | config INPUT_GPIO_DECODER | ||
296 | tristate "Polled GPIO Decoder Input driver" | ||
297 | depends on GPIOLIB || COMPILE_TEST | ||
298 | select INPUT_POLLDEV | ||
299 | help | ||
300 | Say Y here if you want driver to read status of multiple GPIO | ||
301 | lines and report the encoded value as an absolute integer to | ||
302 | input subsystem. | ||
303 | |||
304 | To compile this driver as a module, choose M here: the module | ||
305 | will be called gpio_decoder. | ||
306 | |||
295 | config INPUT_IXP4XX_BEEPER | 307 | config INPUT_IXP4XX_BEEPER |
296 | tristate "IXP4XX Beeper support" | 308 | tristate "IXP4XX Beeper support" |
297 | depends on ARCH_IXP4XX | 309 | depends on ARCH_IXP4XX |
@@ -454,10 +466,10 @@ config INPUT_RETU_PWRBUTTON | |||
454 | 466 | ||
455 | config INPUT_TPS65218_PWRBUTTON | 467 | config INPUT_TPS65218_PWRBUTTON |
456 | tristate "TPS65218 Power button driver" | 468 | tristate "TPS65218 Power button driver" |
457 | depends on MFD_TPS65218 | 469 | depends on (MFD_TPS65217 || MFD_TPS65218) |
458 | help | 470 | help |
459 | Say Y here if you want to enable power buttong reporting for | 471 | Say Y here if you want to enable power buttong reporting for |
460 | the TPS65218 Power Management IC device. | 472 | TPS65217 and TPS65218 Power Management IC devices. |
461 | 473 | ||
462 | To compile this driver as a module, choose M here. The module will | 474 | To compile this driver as a module, choose M here. The module will |
463 | be called tps65218-pwrbutton. | 475 | be called tps65218-pwrbutton. |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 6a1e5e20fc1c..0b6d025f0487 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o | |||
35 | obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o | 35 | obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o |
36 | obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o | 36 | obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o |
37 | obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o | 37 | obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o |
38 | obj-$(CONFIG_INPUT_GPIO_DECODER) += gpio_decoder.o | ||
38 | obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o | 39 | obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o |
39 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | 40 | obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o |
40 | obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o | 41 | obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o |
diff --git a/drivers/input/misc/gpio_decoder.c b/drivers/input/misc/gpio_decoder.c new file mode 100644 index 000000000000..ca7e0bacb2d8 --- /dev/null +++ b/drivers/input/misc/gpio_decoder.c | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * A generic driver to read multiple gpio lines and translate the | ||
14 | * encoded numeric value into an input event. | ||
15 | */ | ||
16 | |||
17 | #include <linux/device.h> | ||
18 | #include <linux/gpio/consumer.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/input-polldev.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | |||
26 | struct gpio_decoder { | ||
27 | struct input_polled_dev *poll_dev; | ||
28 | struct gpio_descs *input_gpios; | ||
29 | struct device *dev; | ||
30 | u32 axis; | ||
31 | u32 last_stable; | ||
32 | }; | ||
33 | |||
34 | static int gpio_decoder_get_gpios_state(struct gpio_decoder *decoder) | ||
35 | { | ||
36 | struct gpio_descs *gpios = decoder->input_gpios; | ||
37 | unsigned int ret = 0; | ||
38 | int i, val; | ||
39 | |||
40 | for (i = 0; i < gpios->ndescs; i++) { | ||
41 | val = gpiod_get_value_cansleep(gpios->desc[i]); | ||
42 | if (val < 0) { | ||
43 | dev_err(decoder->dev, | ||
44 | "Error reading gpio %d: %d\n", | ||
45 | desc_to_gpio(gpios->desc[i]), val); | ||
46 | return val; | ||
47 | } | ||
48 | |||
49 | val = !!val; | ||
50 | ret = (ret << 1) | val; | ||
51 | } | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | static void gpio_decoder_poll_gpios(struct input_polled_dev *poll_dev) | ||
57 | { | ||
58 | struct gpio_decoder *decoder = poll_dev->private; | ||
59 | int state; | ||
60 | |||
61 | state = gpio_decoder_get_gpios_state(decoder); | ||
62 | if (state >= 0 && state != decoder->last_stable) { | ||
63 | input_report_abs(poll_dev->input, decoder->axis, state); | ||
64 | input_sync(poll_dev->input); | ||
65 | decoder->last_stable = state; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static int gpio_decoder_probe(struct platform_device *pdev) | ||
70 | { | ||
71 | struct device *dev = &pdev->dev; | ||
72 | struct gpio_decoder *decoder; | ||
73 | struct input_polled_dev *poll_dev; | ||
74 | u32 max; | ||
75 | int err; | ||
76 | |||
77 | decoder = devm_kzalloc(dev, sizeof(struct gpio_decoder), GFP_KERNEL); | ||
78 | if (!decoder) | ||
79 | return -ENOMEM; | ||
80 | |||
81 | device_property_read_u32(dev, "linux,axis", &decoder->axis); | ||
82 | decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); | ||
83 | if (IS_ERR(decoder->input_gpios)) { | ||
84 | dev_err(dev, "unable to acquire input gpios\n"); | ||
85 | return PTR_ERR(decoder->input_gpios); | ||
86 | } | ||
87 | if (decoder->input_gpios->ndescs < 2) { | ||
88 | dev_err(dev, "not enough gpios found\n"); | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | |||
92 | if (device_property_read_u32(dev, "decoder-max-value", &max)) | ||
93 | max = (1U << decoder->input_gpios->ndescs) - 1; | ||
94 | |||
95 | decoder->dev = dev; | ||
96 | poll_dev = devm_input_allocate_polled_device(decoder->dev); | ||
97 | if (!poll_dev) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | poll_dev->private = decoder; | ||
101 | poll_dev->poll = gpio_decoder_poll_gpios; | ||
102 | decoder->poll_dev = poll_dev; | ||
103 | |||
104 | poll_dev->input->name = pdev->name; | ||
105 | poll_dev->input->id.bustype = BUS_HOST; | ||
106 | input_set_abs_params(poll_dev->input, decoder->axis, 0, max, 0, 0); | ||
107 | |||
108 | err = input_register_polled_device(poll_dev); | ||
109 | if (err) { | ||
110 | dev_err(dev, "failed to register polled device\n"); | ||
111 | return err; | ||
112 | } | ||
113 | platform_set_drvdata(pdev, decoder); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | #ifdef CONFIG_OF | ||
119 | static const struct of_device_id gpio_decoder_of_match[] = { | ||
120 | { .compatible = "gpio-decoder", }, | ||
121 | { }, | ||
122 | }; | ||
123 | MODULE_DEVICE_TABLE(of, gpio_decoder_of_match); | ||
124 | #endif | ||
125 | |||
126 | static struct platform_driver gpio_decoder_driver = { | ||
127 | .probe = gpio_decoder_probe, | ||
128 | .driver = { | ||
129 | .name = "gpio-decoder", | ||
130 | .of_match_table = of_match_ptr(gpio_decoder_of_match), | ||
131 | } | ||
132 | }; | ||
133 | module_platform_driver(gpio_decoder_driver); | ||
134 | |||
135 | MODULE_DESCRIPTION("GPIO decoder input driver"); | ||
136 | MODULE_AUTHOR("Vignesh R <vigneshr@ti.com>"); | ||
137 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 29ddeb7be84b..46b0f48fbf49 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2014,2015 Samsung Electronics | 4 | * Copyright (C) 2014,2015 Samsung Electronics |
5 | * Jaewon Kim <jaewon02.kim@samsung.com> | 5 | * Jaewon Kim <jaewon02.kim@samsung.com> |
6 | * Krzysztof Kozlowski <k.kozlowski@samsung.com> | 6 | * Krzysztof Kozlowski <krzk@kernel.org> |
7 | * | 7 | * |
8 | * This program is not provided / owned by Maxim Integrated Products. | 8 | * This program is not provided / owned by Maxim Integrated Products. |
9 | * | 9 | * |
@@ -426,7 +426,7 @@ static struct platform_driver max77693_haptic_driver = { | |||
426 | module_platform_driver(max77693_haptic_driver); | 426 | module_platform_driver(max77693_haptic_driver); |
427 | 427 | ||
428 | MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); | 428 | MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); |
429 | MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>"); | 429 | MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); |
430 | MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver"); | 430 | MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver"); |
431 | MODULE_ALIAS("platform:max77693-haptic"); | 431 | MODULE_ALIAS("platform:max77693-haptic"); |
432 | MODULE_LICENSE("GPL"); | 432 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/input/misc/tps65218-pwrbutton.c b/drivers/input/misc/tps65218-pwrbutton.c index a39b62651a4b..3273217ce80c 100644 --- a/drivers/input/misc/tps65218-pwrbutton.c +++ b/drivers/input/misc/tps65218-pwrbutton.c | |||
@@ -1,8 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Texas Instruments' TPS65218 Power Button Input Driver | 2 | * Texas Instruments' TPS65217 and TPS65218 Power Button Input Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ | 4 | * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ |
5 | * Author: Felipe Balbi <balbi@ti.com> | 5 | * Author: Felipe Balbi <balbi@ti.com> |
6 | * Author: Marcin Niestroj <m.niestroj@grinn-global.com> | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -18,31 +19,61 @@ | |||
18 | #include <linux/input.h> | 19 | #include <linux/input.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/mfd/tps65217.h> | ||
21 | #include <linux/mfd/tps65218.h> | 23 | #include <linux/mfd/tps65218.h> |
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
23 | #include <linux/of.h> | 25 | #include <linux/of.h> |
24 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regmap.h> | ||
25 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
26 | 29 | ||
27 | struct tps65218_pwrbutton { | 30 | struct tps6521x_data { |
31 | unsigned int reg_status; | ||
32 | unsigned int pb_mask; | ||
33 | const char *name; | ||
34 | }; | ||
35 | |||
36 | static const struct tps6521x_data tps65217_data = { | ||
37 | .reg_status = TPS65217_REG_STATUS, | ||
38 | .pb_mask = TPS65217_STATUS_PB, | ||
39 | .name = "tps65217_pwrbutton", | ||
40 | }; | ||
41 | |||
42 | static const struct tps6521x_data tps65218_data = { | ||
43 | .reg_status = TPS65218_REG_STATUS, | ||
44 | .pb_mask = TPS65218_STATUS_PB_STATE, | ||
45 | .name = "tps65218_pwrbutton", | ||
46 | }; | ||
47 | |||
48 | struct tps6521x_pwrbutton { | ||
28 | struct device *dev; | 49 | struct device *dev; |
29 | struct tps65218 *tps; | 50 | struct regmap *regmap; |
30 | struct input_dev *idev; | 51 | struct input_dev *idev; |
52 | const struct tps6521x_data *data; | ||
53 | char phys[32]; | ||
54 | }; | ||
55 | |||
56 | static const struct of_device_id of_tps6521x_pb_match[] = { | ||
57 | { .compatible = "ti,tps65217-pwrbutton", .data = &tps65217_data }, | ||
58 | { .compatible = "ti,tps65218-pwrbutton", .data = &tps65218_data }, | ||
59 | { }, | ||
31 | }; | 60 | }; |
61 | MODULE_DEVICE_TABLE(of, of_tps6521x_pb_match); | ||
32 | 62 | ||
33 | static irqreturn_t tps65218_pwr_irq(int irq, void *_pwr) | 63 | static irqreturn_t tps6521x_pb_irq(int irq, void *_pwr) |
34 | { | 64 | { |
35 | struct tps65218_pwrbutton *pwr = _pwr; | 65 | struct tps6521x_pwrbutton *pwr = _pwr; |
66 | const struct tps6521x_data *tps_data = pwr->data; | ||
36 | unsigned int reg; | 67 | unsigned int reg; |
37 | int error; | 68 | int error; |
38 | 69 | ||
39 | error = tps65218_reg_read(pwr->tps, TPS65218_REG_STATUS, ®); | 70 | error = regmap_read(pwr->regmap, tps_data->reg_status, ®); |
40 | if (error) { | 71 | if (error) { |
41 | dev_err(pwr->dev, "can't read register: %d\n", error); | 72 | dev_err(pwr->dev, "can't read register: %d\n", error); |
42 | goto out; | 73 | goto out; |
43 | } | 74 | } |
44 | 75 | ||
45 | if (reg & TPS65218_STATUS_PB_STATE) { | 76 | if (reg & tps_data->pb_mask) { |
46 | input_report_key(pwr->idev, KEY_POWER, 1); | 77 | input_report_key(pwr->idev, KEY_POWER, 1); |
47 | pm_wakeup_event(pwr->dev, 0); | 78 | pm_wakeup_event(pwr->dev, 0); |
48 | } else { | 79 | } else { |
@@ -55,42 +86,55 @@ out: | |||
55 | return IRQ_HANDLED; | 86 | return IRQ_HANDLED; |
56 | } | 87 | } |
57 | 88 | ||
58 | static int tps65218_pwron_probe(struct platform_device *pdev) | 89 | static int tps6521x_pb_probe(struct platform_device *pdev) |
59 | { | 90 | { |
60 | struct tps65218 *tps = dev_get_drvdata(pdev->dev.parent); | ||
61 | struct device *dev = &pdev->dev; | 91 | struct device *dev = &pdev->dev; |
62 | struct tps65218_pwrbutton *pwr; | 92 | struct tps6521x_pwrbutton *pwr; |
63 | struct input_dev *idev; | 93 | struct input_dev *idev; |
94 | const struct of_device_id *match; | ||
64 | int error; | 95 | int error; |
65 | int irq; | 96 | int irq; |
66 | 97 | ||
98 | match = of_match_node(of_tps6521x_pb_match, pdev->dev.of_node); | ||
99 | if (!match) | ||
100 | return -ENXIO; | ||
101 | |||
67 | pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL); | 102 | pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL); |
68 | if (!pwr) | 103 | if (!pwr) |
69 | return -ENOMEM; | 104 | return -ENOMEM; |
70 | 105 | ||
106 | pwr->data = match->data; | ||
107 | |||
71 | idev = devm_input_allocate_device(dev); | 108 | idev = devm_input_allocate_device(dev); |
72 | if (!idev) | 109 | if (!idev) |
73 | return -ENOMEM; | 110 | return -ENOMEM; |
74 | 111 | ||
75 | idev->name = "tps65218_pwrbutton"; | 112 | idev->name = pwr->data->name; |
76 | idev->phys = "tps65218_pwrbutton/input0"; | 113 | snprintf(pwr->phys, sizeof(pwr->phys), "%s/input0", |
114 | pwr->data->name); | ||
115 | idev->phys = pwr->phys; | ||
77 | idev->dev.parent = dev; | 116 | idev->dev.parent = dev; |
78 | idev->id.bustype = BUS_I2C; | 117 | idev->id.bustype = BUS_I2C; |
79 | 118 | ||
80 | input_set_capability(idev, EV_KEY, KEY_POWER); | 119 | input_set_capability(idev, EV_KEY, KEY_POWER); |
81 | 120 | ||
82 | pwr->tps = tps; | 121 | pwr->regmap = dev_get_regmap(pdev->dev.parent, NULL); |
83 | pwr->dev = dev; | 122 | pwr->dev = dev; |
84 | pwr->idev = idev; | 123 | pwr->idev = idev; |
85 | platform_set_drvdata(pdev, pwr); | 124 | platform_set_drvdata(pdev, pwr); |
86 | device_init_wakeup(dev, true); | 125 | device_init_wakeup(dev, true); |
87 | 126 | ||
88 | irq = platform_get_irq(pdev, 0); | 127 | irq = platform_get_irq(pdev, 0); |
89 | error = devm_request_threaded_irq(dev, irq, NULL, tps65218_pwr_irq, | 128 | if (irq < 0) { |
129 | dev_err(dev, "No IRQ resource!\n"); | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | |||
133 | error = devm_request_threaded_irq(dev, irq, NULL, tps6521x_pb_irq, | ||
90 | IRQF_TRIGGER_RISING | | 134 | IRQF_TRIGGER_RISING | |
91 | IRQF_TRIGGER_FALLING | | 135 | IRQF_TRIGGER_FALLING | |
92 | IRQF_ONESHOT, | 136 | IRQF_ONESHOT, |
93 | "tps65218-pwrbutton", pwr); | 137 | pwr->data->name, pwr); |
94 | if (error) { | 138 | if (error) { |
95 | dev_err(dev, "failed to request IRQ #%d: %d\n", | 139 | dev_err(dev, "failed to request IRQ #%d: %d\n", |
96 | irq, error); | 140 | irq, error); |
@@ -106,21 +150,15 @@ static int tps65218_pwron_probe(struct platform_device *pdev) | |||
106 | return 0; | 150 | return 0; |
107 | } | 151 | } |
108 | 152 | ||
109 | static const struct of_device_id of_tps65218_pwr_match[] = { | 153 | static struct platform_driver tps6521x_pb_driver = { |
110 | { .compatible = "ti,tps65218-pwrbutton" }, | 154 | .probe = tps6521x_pb_probe, |
111 | { }, | ||
112 | }; | ||
113 | MODULE_DEVICE_TABLE(of, of_tps65218_pwr_match); | ||
114 | |||
115 | static struct platform_driver tps65218_pwron_driver = { | ||
116 | .probe = tps65218_pwron_probe, | ||
117 | .driver = { | 155 | .driver = { |
118 | .name = "tps65218_pwrbutton", | 156 | .name = "tps6521x_pwrbutton", |
119 | .of_match_table = of_tps65218_pwr_match, | 157 | .of_match_table = of_tps6521x_pb_match, |
120 | }, | 158 | }, |
121 | }; | 159 | }; |
122 | module_platform_driver(tps65218_pwron_driver); | 160 | module_platform_driver(tps6521x_pb_driver); |
123 | 161 | ||
124 | MODULE_DESCRIPTION("TPS65218 Power Button"); | 162 | MODULE_DESCRIPTION("TPS6521X Power Button"); |
125 | MODULE_LICENSE("GPL v2"); | 163 | MODULE_LICENSE("GPL v2"); |
126 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | 164 | MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); |
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index cb6aecbc1dc2..e23b2495d52e 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c | |||
@@ -222,11 +222,13 @@ static int elan_smbus_get_checksum(struct i2c_client *client, | |||
222 | static int elan_smbus_get_max(struct i2c_client *client, | 222 | static int elan_smbus_get_max(struct i2c_client *client, |
223 | unsigned int *max_x, unsigned int *max_y) | 223 | unsigned int *max_x, unsigned int *max_y) |
224 | { | 224 | { |
225 | int ret; | ||
225 | int error; | 226 | int error; |
226 | u8 val[3]; | 227 | u8 val[3]; |
227 | 228 | ||
228 | error = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val); | 229 | ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val); |
229 | if (error) { | 230 | if (ret != 3) { |
231 | error = ret < 0 ? ret : -EIO; | ||
230 | dev_err(&client->dev, "failed to get dimensions: %d\n", error); | 232 | dev_err(&client->dev, "failed to get dimensions: %d\n", error); |
231 | return error; | 233 | return error; |
232 | } | 234 | } |
@@ -240,12 +242,13 @@ static int elan_smbus_get_max(struct i2c_client *client, | |||
240 | static int elan_smbus_get_resolution(struct i2c_client *client, | 242 | static int elan_smbus_get_resolution(struct i2c_client *client, |
241 | u8 *hw_res_x, u8 *hw_res_y) | 243 | u8 *hw_res_x, u8 *hw_res_y) |
242 | { | 244 | { |
245 | int ret; | ||
243 | int error; | 246 | int error; |
244 | u8 val[3]; | 247 | u8 val[3]; |
245 | 248 | ||
246 | error = i2c_smbus_read_block_data(client, | 249 | ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val); |
247 | ETP_SMBUS_RESOLUTION_CMD, val); | 250 | if (ret != 3) { |
248 | if (error) { | 251 | error = ret < 0 ? ret : -EIO; |
249 | dev_err(&client->dev, "failed to get resolution: %d\n", error); | 252 | dev_err(&client->dev, "failed to get resolution: %d\n", error); |
250 | return error; | 253 | return error; |
251 | } | 254 | } |
@@ -260,12 +263,13 @@ static int elan_smbus_get_num_traces(struct i2c_client *client, | |||
260 | unsigned int *x_traces, | 263 | unsigned int *x_traces, |
261 | unsigned int *y_traces) | 264 | unsigned int *y_traces) |
262 | { | 265 | { |
266 | int ret; | ||
263 | int error; | 267 | int error; |
264 | u8 val[3]; | 268 | u8 val[3]; |
265 | 269 | ||
266 | error = i2c_smbus_read_block_data(client, | 270 | ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val); |
267 | ETP_SMBUS_XY_TRACENUM_CMD, val); | 271 | if (ret != 3) { |
268 | if (error) { | 272 | error = ret < 0 ? ret : -EIO; |
269 | dev_err(&client->dev, "failed to get trace info: %d\n", error); | 273 | dev_err(&client->dev, "failed to get trace info: %d\n", error); |
270 | return error; | 274 | return error; |
271 | } | 275 | } |
diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c index c8c6a8cc329d..54eceb30ede5 100644 --- a/drivers/input/mouse/focaltech.c +++ b/drivers/input/mouse/focaltech.c | |||
@@ -390,7 +390,8 @@ static int focaltech_read_size(struct psmouse *psmouse) | |||
390 | return 0; | 390 | return 0; |
391 | } | 391 | } |
392 | 392 | ||
393 | void focaltech_set_resolution(struct psmouse *psmouse, unsigned int resolution) | 393 | static void focaltech_set_resolution(struct psmouse *psmouse, |
394 | unsigned int resolution) | ||
394 | { | 395 | { |
395 | /* not supported yet */ | 396 | /* not supported yet */ |
396 | } | 397 | } |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 5784e20542a4..fb4b185dea96 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -1916,7 +1916,7 @@ static int __init psmouse_init(void) | |||
1916 | synaptics_module_init(); | 1916 | synaptics_module_init(); |
1917 | hgpk_module_init(); | 1917 | hgpk_module_init(); |
1918 | 1918 | ||
1919 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | 1919 | kpsmoused_wq = alloc_ordered_workqueue("kpsmoused", 0); |
1920 | if (!kpsmoused_wq) { | 1920 | if (!kpsmoused_wq) { |
1921 | pr_err("failed to create kpsmoused workqueue\n"); | 1921 | pr_err("failed to create kpsmoused workqueue\n"); |
1922 | return -ENOMEM; | 1922 | return -ENOMEM; |
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 9c927d35c1f5..d189843f3727 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -71,10 +71,7 @@ static void serport_serio_close(struct serio *serio) | |||
71 | 71 | ||
72 | spin_lock_irqsave(&serport->lock, flags); | 72 | spin_lock_irqsave(&serport->lock, flags); |
73 | clear_bit(SERPORT_ACTIVE, &serport->flags); | 73 | clear_bit(SERPORT_ACTIVE, &serport->flags); |
74 | set_bit(SERPORT_DEAD, &serport->flags); | ||
75 | spin_unlock_irqrestore(&serport->lock, flags); | 74 | spin_unlock_irqrestore(&serport->lock, flags); |
76 | |||
77 | wake_up_interruptible(&serport->wait); | ||
78 | } | 75 | } |
79 | 76 | ||
80 | /* | 77 | /* |
@@ -248,6 +245,19 @@ static long serport_ldisc_compat_ioctl(struct tty_struct *tty, | |||
248 | } | 245 | } |
249 | #endif | 246 | #endif |
250 | 247 | ||
248 | static int serport_ldisc_hangup(struct tty_struct *tty) | ||
249 | { | ||
250 | struct serport *serport = (struct serport *) tty->disc_data; | ||
251 | unsigned long flags; | ||
252 | |||
253 | spin_lock_irqsave(&serport->lock, flags); | ||
254 | set_bit(SERPORT_DEAD, &serport->flags); | ||
255 | spin_unlock_irqrestore(&serport->lock, flags); | ||
256 | |||
257 | wake_up_interruptible(&serport->wait); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
251 | static void serport_ldisc_write_wakeup(struct tty_struct * tty) | 261 | static void serport_ldisc_write_wakeup(struct tty_struct * tty) |
252 | { | 262 | { |
253 | struct serport *serport = (struct serport *) tty->disc_data; | 263 | struct serport *serport = (struct serport *) tty->disc_data; |
@@ -274,6 +284,7 @@ static struct tty_ldisc_ops serport_ldisc = { | |||
274 | .compat_ioctl = serport_ldisc_compat_ioctl, | 284 | .compat_ioctl = serport_ldisc_compat_ioctl, |
275 | #endif | 285 | #endif |
276 | .receive_buf = serport_ldisc_receive, | 286 | .receive_buf = serport_ldisc_receive, |
287 | .hangup = serport_ldisc_hangup, | ||
277 | .write_wakeup = serport_ldisc_write_wakeup | 288 | .write_wakeup = serport_ldisc_write_wakeup |
278 | }; | 289 | }; |
279 | 290 | ||
diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c index 949dacc78664..47de5a81172f 100644 --- a/drivers/input/tablet/pegasus_notetaker.c +++ b/drivers/input/tablet/pegasus_notetaker.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/input.h> | 40 | #include <linux/input.h> |
41 | #include <linux/usb/input.h> | 41 | #include <linux/usb/input.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/workqueue.h> | ||
43 | 44 | ||
44 | /* USB HID defines */ | 45 | /* USB HID defines */ |
45 | #define USB_REQ_GET_REPORT 0x01 | 46 | #define USB_REQ_GET_REPORT 0x01 |
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"); |