diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2016-07-26 15:07:15 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2016-07-26 15:07:15 -0400 |
commit | 0808882863774ab69066d83f49f511606be024e0 (patch) | |
tree | dc5eaab5db6c18e06025356235b0c9ba02bd7a1d /drivers/input/touchscreen | |
parent | e9003c9cfaa17d26991688268b04244adb67ee2b (diff) | |
parent | 0097ff3d5dad1f76c5e1099d849d52509500708c (diff) |
Merge branch 'next' into for-linus
Prepare first round of input updates for 4.8 merge window.
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 28 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/chipone_icn8318.c | 61 | ||||
-rw-r--r-- | drivers/input/touchscreen/cyttsp_core.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/edt-ft5x06.c | 7 | ||||
-rw-r--r-- | drivers/input/touchscreen/migor_ts.c | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/of_touchscreen.c | 81 | ||||
-rw-r--r-- | drivers/input/touchscreen/pixcir_i2c_ts.c | 53 | ||||
-rw-r--r-- | drivers/input/touchscreen/raydium_i2c_ts.c | 1238 | ||||
-rw-r--r-- | drivers/input/touchscreen/surface3_spi.c | 427 | ||||
-rw-r--r-- | drivers/input/touchscreen/ti_am335x_tsc.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/tsc200x-core.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom_w8001.c | 10 |
14 files changed, 1828 insertions, 93 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8ecdc38fd489..ee02dc7422bd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -632,7 +632,7 @@ config TOUCHSCREEN_EDT_FT5X06 | |||
632 | 632 | ||
633 | config TOUCHSCREEN_MIGOR | 633 | config TOUCHSCREEN_MIGOR |
634 | tristate "Renesas MIGO-R touchscreen" | 634 | tristate "Renesas MIGO-R touchscreen" |
635 | depends on SH_MIGOR && I2C | 635 | depends on (SH_MIGOR || COMPILE_TEST) && I2C |
636 | help | 636 | help |
637 | Say Y here to enable MIGO-R touchscreen support. | 637 | Say Y here to enable MIGO-R touchscreen support. |
638 | 638 | ||
@@ -1046,6 +1046,19 @@ config TOUCHSCREEN_PCAP | |||
1046 | To compile this driver as a module, choose M here: the | 1046 | To compile this driver as a module, choose M here: the |
1047 | module will be called pcap_ts. | 1047 | module will be called pcap_ts. |
1048 | 1048 | ||
1049 | config TOUCHSCREEN_RM_TS | ||
1050 | tristate "Raydium I2C Touchscreen" | ||
1051 | depends on I2C | ||
1052 | depends on GPIOLIB || COMPILE_TEST | ||
1053 | help | ||
1054 | Say Y here if you have Raydium series I2C touchscreen, | ||
1055 | such as RM32380, connected to your system. | ||
1056 | |||
1057 | If unsure, say N. | ||
1058 | |||
1059 | To compile this driver as a module, choose M here: the | ||
1060 | module will be called raydium_i2c_ts. | ||
1061 | |||
1049 | config TOUCHSCREEN_ST1232 | 1062 | config TOUCHSCREEN_ST1232 |
1050 | tristate "Sitronix ST1232 touchscreen controllers" | 1063 | tristate "Sitronix ST1232 touchscreen controllers" |
1051 | depends on I2C | 1064 | depends on I2C |
@@ -1094,6 +1107,19 @@ config TOUCHSCREEN_SUR40 | |||
1094 | To compile this driver as a module, choose M here: the | 1107 | To compile this driver as a module, choose M here: the |
1095 | module will be called sur40. | 1108 | module will be called sur40. |
1096 | 1109 | ||
1110 | config TOUCHSCREEN_SURFACE3_SPI | ||
1111 | tristate "Ntrig/Microsoft Surface 3 SPI touchscreen" | ||
1112 | depends on SPI | ||
1113 | depends on GPIOLIB || COMPILE_TEST | ||
1114 | help | ||
1115 | Say Y here if you have the Ntrig/Microsoft SPI touchscreen | ||
1116 | controller chip as found on the Surface 3 in your system. | ||
1117 | |||
1118 | If unsure, say N. | ||
1119 | |||
1120 | To compile this driver as a module, choose M here: the | ||
1121 | module will be called surface3_spi. | ||
1122 | |||
1097 | config TOUCHSCREEN_SX8654 | 1123 | config TOUCHSCREEN_SX8654 |
1098 | tristate "Semtech SX8654 touchscreen" | 1124 | tristate "Semtech SX8654 touchscreen" |
1099 | depends on I2C | 1125 | depends on I2C |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index f42975e719e0..3315882905f7 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -62,11 +62,13 @@ obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | |||
62 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | 62 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o |
63 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 63 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
64 | obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o | 64 | obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o |
65 | obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o | ||
65 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | 66 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o |
66 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o | 67 | obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o |
67 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o | 68 | obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o |
68 | obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o | 69 | obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o |
69 | obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o | 70 | obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o |
71 | obj-$(CONFIG_TOUCHSCREEN_SURFACE3_SPI) += surface3_spi.o | ||
70 | obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o | 72 | obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o |
71 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 73 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
72 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 74 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 69d299d5dd00..8a84fd4d9147 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
@@ -595,7 +595,7 @@ struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq, | |||
595 | } else { | 595 | } else { |
596 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); | 596 | input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); |
597 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | 597 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); |
598 | touchscreen_parse_properties(input_dev, false); | 598 | touchscreen_parse_properties(input_dev, false, NULL); |
599 | if (!input_abs_get_max(input_dev, ABS_PRESSURE)) { | 599 | if (!input_abs_get_max(input_dev, ABS_PRESSURE)) { |
600 | dev_err(dev, "Touchscreen pressure is not specified\n"); | 600 | dev_err(dev, "Touchscreen pressure is not specified\n"); |
601 | return ERR_PTR(-EINVAL); | 601 | return ERR_PTR(-EINVAL); |
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c index 22a6fead8cfb..0bf14067c167 100644 --- a/drivers/input/touchscreen/chipone_icn8318.c +++ b/drivers/input/touchscreen/chipone_icn8318.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/input/mt.h> | 19 | #include <linux/input/mt.h> |
20 | #include <linux/input/touchscreen.h> | ||
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/of.h> | 22 | #include <linux/of.h> |
22 | 23 | ||
@@ -52,11 +53,7 @@ struct icn8318_data { | |||
52 | struct i2c_client *client; | 53 | struct i2c_client *client; |
53 | struct input_dev *input; | 54 | struct input_dev *input; |
54 | struct gpio_desc *wake_gpio; | 55 | struct gpio_desc *wake_gpio; |
55 | u32 max_x; | 56 | struct touchscreen_properties prop; |
56 | u32 max_y; | ||
57 | bool invert_x; | ||
58 | bool invert_y; | ||
59 | bool swap_x_y; | ||
60 | }; | 57 | }; |
61 | 58 | ||
62 | static int icn8318_read_touch_data(struct i2c_client *client, | 59 | static int icn8318_read_touch_data(struct i2c_client *client, |
@@ -91,7 +88,7 @@ static irqreturn_t icn8318_irq(int irq, void *dev_id) | |||
91 | struct icn8318_data *data = dev_id; | 88 | struct icn8318_data *data = dev_id; |
92 | struct device *dev = &data->client->dev; | 89 | struct device *dev = &data->client->dev; |
93 | struct icn8318_touch_data touch_data; | 90 | struct icn8318_touch_data touch_data; |
94 | int i, ret, x, y; | 91 | int i, ret; |
95 | 92 | ||
96 | ret = icn8318_read_touch_data(data->client, &touch_data); | 93 | ret = icn8318_read_touch_data(data->client, &touch_data); |
97 | if (ret < 0) { | 94 | if (ret < 0) { |
@@ -124,22 +121,9 @@ static irqreturn_t icn8318_irq(int irq, void *dev_id) | |||
124 | if (!act) | 121 | if (!act) |
125 | continue; | 122 | continue; |
126 | 123 | ||
127 | x = be16_to_cpu(touch->x); | 124 | touchscreen_report_pos(data->input, &data->prop, |
128 | y = be16_to_cpu(touch->y); | 125 | be16_to_cpu(touch->x), |
129 | 126 | be16_to_cpu(touch->y), true); | |
130 | if (data->invert_x) | ||
131 | x = data->max_x - x; | ||
132 | |||
133 | if (data->invert_y) | ||
134 | y = data->max_y - y; | ||
135 | |||
136 | if (!data->swap_x_y) { | ||
137 | input_event(data->input, EV_ABS, ABS_MT_POSITION_X, x); | ||
138 | input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, y); | ||
139 | } else { | ||
140 | input_event(data->input, EV_ABS, ABS_MT_POSITION_X, y); | ||
141 | input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, x); | ||
142 | } | ||
143 | } | 127 | } |
144 | 128 | ||
145 | input_mt_sync_frame(data->input); | 129 | input_mt_sync_frame(data->input); |
@@ -200,10 +184,8 @@ static int icn8318_probe(struct i2c_client *client, | |||
200 | const struct i2c_device_id *id) | 184 | const struct i2c_device_id *id) |
201 | { | 185 | { |
202 | struct device *dev = &client->dev; | 186 | struct device *dev = &client->dev; |
203 | struct device_node *np = dev->of_node; | ||
204 | struct icn8318_data *data; | 187 | struct icn8318_data *data; |
205 | struct input_dev *input; | 188 | struct input_dev *input; |
206 | u32 fuzz_x = 0, fuzz_y = 0; | ||
207 | int error; | 189 | int error; |
208 | 190 | ||
209 | if (!client->irq) { | 191 | if (!client->irq) { |
@@ -223,19 +205,6 @@ static int icn8318_probe(struct i2c_client *client, | |||
223 | return error; | 205 | return error; |
224 | } | 206 | } |
225 | 207 | ||
226 | if (of_property_read_u32(np, "touchscreen-size-x", &data->max_x) || | ||
227 | of_property_read_u32(np, "touchscreen-size-y", &data->max_y)) { | ||
228 | dev_err(dev, "Error touchscreen-size-x and/or -y missing\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | /* Optional */ | ||
233 | of_property_read_u32(np, "touchscreen-fuzz-x", &fuzz_x); | ||
234 | of_property_read_u32(np, "touchscreen-fuzz-y", &fuzz_y); | ||
235 | data->invert_x = of_property_read_bool(np, "touchscreen-inverted-x"); | ||
236 | data->invert_y = of_property_read_bool(np, "touchscreen-inverted-y"); | ||
237 | data->swap_x_y = of_property_read_bool(np, "touchscreen-swapped-x-y"); | ||
238 | |||
239 | input = devm_input_allocate_device(dev); | 208 | input = devm_input_allocate_device(dev); |
240 | if (!input) | 209 | if (!input) |
241 | return -ENOMEM; | 210 | return -ENOMEM; |
@@ -246,16 +215,14 @@ static int icn8318_probe(struct i2c_client *client, | |||
246 | input->close = icn8318_stop; | 215 | input->close = icn8318_stop; |
247 | input->dev.parent = dev; | 216 | input->dev.parent = dev; |
248 | 217 | ||
249 | if (!data->swap_x_y) { | 218 | input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); |
250 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | 219 | input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); |
251 | data->max_x, fuzz_x, 0); | 220 | |
252 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | 221 | touchscreen_parse_properties(input, true, &data->prop); |
253 | data->max_y, fuzz_y, 0); | 222 | if (!input_abs_get_max(input, ABS_MT_POSITION_X) || |
254 | } else { | 223 | !input_abs_get_max(input, ABS_MT_POSITION_Y)) { |
255 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | 224 | dev_err(dev, "Error touchscreen-size-x and/or -y missing\n"); |
256 | data->max_y, fuzz_y, 0); | 225 | return -EINVAL; |
257 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
258 | data->max_x, fuzz_x, 0); | ||
259 | } | 226 | } |
260 | 227 | ||
261 | error = input_mt_init_slots(input, ICN8318_MAX_TOUCHES, | 228 | error = input_mt_init_slots(input, ICN8318_MAX_TOUCHES, |
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 91cda8f8119d..79381cc1774a 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c | |||
@@ -657,7 +657,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, | |||
657 | 657 | ||
658 | input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); | 658 | input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); |
659 | input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); | 659 | input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); |
660 | touchscreen_parse_properties(input_dev, true); | 660 | touchscreen_parse_properties(input_dev, true, NULL); |
661 | 661 | ||
662 | error = input_mt_init_slots(input_dev, CY_MAX_ID, 0); | 662 | error = input_mt_init_slots(input_dev, CY_MAX_ID, 0); |
663 | if (error) { | 663 | if (error) { |
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 23fbe382da8b..703e295a37ed 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
@@ -86,6 +86,7 @@ struct edt_reg_addr { | |||
86 | struct edt_ft5x06_ts_data { | 86 | struct edt_ft5x06_ts_data { |
87 | struct i2c_client *client; | 87 | struct i2c_client *client; |
88 | struct input_dev *input; | 88 | struct input_dev *input; |
89 | struct touchscreen_properties prop; | ||
89 | u16 num_x; | 90 | u16 num_x; |
90 | u16 num_y; | 91 | u16 num_y; |
91 | 92 | ||
@@ -246,8 +247,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) | |||
246 | if (!down) | 247 | if (!down) |
247 | continue; | 248 | continue; |
248 | 249 | ||
249 | input_report_abs(tsdata->input, ABS_MT_POSITION_X, x); | 250 | touchscreen_report_pos(tsdata->input, &tsdata->prop, x, y, |
250 | input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y); | 251 | true); |
251 | } | 252 | } |
252 | 253 | ||
253 | input_mt_report_pointer_emulation(tsdata->input, true); | 254 | input_mt_report_pointer_emulation(tsdata->input, true); |
@@ -972,7 +973,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
972 | input_set_abs_params(input, ABS_MT_POSITION_Y, | 973 | input_set_abs_params(input, ABS_MT_POSITION_Y, |
973 | 0, tsdata->num_y * 64 - 1, 0, 0); | 974 | 0, tsdata->num_y * 64 - 1, 0, 0); |
974 | 975 | ||
975 | touchscreen_parse_properties(input, true); | 976 | touchscreen_parse_properties(input, true, &tsdata->prop); |
976 | 977 | ||
977 | error = input_mt_init_slots(input, tsdata->max_support_points, | 978 | error = input_mt_init_slots(input, tsdata->max_support_points, |
978 | INPUT_MT_DIRECT); | 979 | INPUT_MT_DIRECT); |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index c038db93e2c3..02fb11985819 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
@@ -202,7 +202,7 @@ static int migor_ts_remove(struct i2c_client *client) | |||
202 | return 0; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | static int migor_ts_suspend(struct device *dev) | 205 | static int __maybe_unused migor_ts_suspend(struct device *dev) |
206 | { | 206 | { |
207 | struct i2c_client *client = to_i2c_client(dev); | 207 | struct i2c_client *client = to_i2c_client(dev); |
208 | struct migor_ts_priv *priv = i2c_get_clientdata(client); | 208 | struct migor_ts_priv *priv = i2c_get_clientdata(client); |
@@ -213,7 +213,7 @@ static int migor_ts_suspend(struct device *dev) | |||
213 | return 0; | 213 | return 0; |
214 | } | 214 | } |
215 | 215 | ||
216 | static int migor_ts_resume(struct device *dev) | 216 | static int __maybe_unused migor_ts_resume(struct device *dev) |
217 | { | 217 | { |
218 | struct i2c_client *client = to_i2c_client(dev); | 218 | struct i2c_client *client = to_i2c_client(dev); |
219 | struct migor_ts_priv *priv = i2c_get_clientdata(client); | 219 | struct migor_ts_priv *priv = i2c_get_clientdata(client); |
@@ -230,7 +230,7 @@ static const struct i2c_device_id migor_ts_id[] = { | |||
230 | { "migor_ts", 0 }, | 230 | { "migor_ts", 0 }, |
231 | { } | 231 | { } |
232 | }; | 232 | }; |
233 | MODULE_DEVICE_TABLE(i2c, migor_ts); | 233 | MODULE_DEVICE_TABLE(i2c, migor_ts_id); |
234 | 234 | ||
235 | static struct i2c_driver migor_ts_driver = { | 235 | static struct i2c_driver migor_ts_driver = { |
236 | .driver = { | 236 | .driver = { |
diff --git a/drivers/input/touchscreen/of_touchscreen.c b/drivers/input/touchscreen/of_touchscreen.c index bb6f2fe14667..8d7f9c8f2771 100644 --- a/drivers/input/touchscreen/of_touchscreen.c +++ b/drivers/input/touchscreen/of_touchscreen.c | |||
@@ -55,12 +55,16 @@ static void touchscreen_set_params(struct input_dev *dev, | |||
55 | * @input: input device that should be parsed | 55 | * @input: input device that should be parsed |
56 | * @multitouch: specifies whether parsed properties should be applied to | 56 | * @multitouch: specifies whether parsed properties should be applied to |
57 | * single-touch or multi-touch axes | 57 | * single-touch or multi-touch axes |
58 | * @prop: pointer to a struct touchscreen_properties into which to store | ||
59 | * axis swap and invert info for use with touchscreen_report_x_y(); | ||
60 | * or %NULL | ||
58 | * | 61 | * |
59 | * This function parses common DT properties for touchscreens and setups the | 62 | * This function parses common DT properties for touchscreens and setups the |
60 | * input device accordingly. The function keeps previously set up default | 63 | * input device accordingly. The function keeps previously set up default |
61 | * values if no value is specified via DT. | 64 | * values if no value is specified via DT. |
62 | */ | 65 | */ |
63 | void touchscreen_parse_properties(struct input_dev *input, bool multitouch) | 66 | void touchscreen_parse_properties(struct input_dev *input, bool multitouch, |
67 | struct touchscreen_properties *prop) | ||
64 | { | 68 | { |
65 | struct device *dev = input->dev.parent; | 69 | struct device *dev = input->dev.parent; |
66 | unsigned int axis; | 70 | unsigned int axis; |
@@ -104,5 +108,80 @@ void touchscreen_parse_properties(struct input_dev *input, bool multitouch) | |||
104 | &fuzz); | 108 | &fuzz); |
105 | if (data_present) | 109 | if (data_present) |
106 | touchscreen_set_params(input, axis, maximum, fuzz); | 110 | touchscreen_set_params(input, axis, maximum, fuzz); |
111 | |||
112 | if (!prop) | ||
113 | return; | ||
114 | |||
115 | axis = multitouch ? ABS_MT_POSITION_X : ABS_X; | ||
116 | |||
117 | prop->max_x = input_abs_get_max(input, axis); | ||
118 | prop->max_y = input_abs_get_max(input, axis + 1); | ||
119 | prop->invert_x = | ||
120 | device_property_read_bool(dev, "touchscreen-inverted-x"); | ||
121 | prop->invert_y = | ||
122 | device_property_read_bool(dev, "touchscreen-inverted-y"); | ||
123 | prop->swap_x_y = | ||
124 | device_property_read_bool(dev, "touchscreen-swapped-x-y"); | ||
125 | |||
126 | if (prop->swap_x_y) | ||
127 | swap(input->absinfo[axis], input->absinfo[axis + 1]); | ||
107 | } | 128 | } |
108 | EXPORT_SYMBOL(touchscreen_parse_properties); | 129 | EXPORT_SYMBOL(touchscreen_parse_properties); |
130 | |||
131 | static void | ||
132 | touchscreen_apply_prop_to_x_y(const struct touchscreen_properties *prop, | ||
133 | unsigned int *x, unsigned int *y) | ||
134 | { | ||
135 | if (prop->invert_x) | ||
136 | *x = prop->max_x - *x; | ||
137 | |||
138 | if (prop->invert_y) | ||
139 | *y = prop->max_y - *y; | ||
140 | |||
141 | if (prop->swap_x_y) | ||
142 | swap(*x, *y); | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * touchscreen_set_mt_pos - Set input_mt_pos coordinates | ||
147 | * @pos: input_mt_pos to set coordinates of | ||
148 | * @prop: pointer to a struct touchscreen_properties | ||
149 | * @x: X coordinate to store in pos | ||
150 | * @y: Y coordinate to store in pos | ||
151 | * | ||
152 | * Adjust the passed in x and y values applying any axis inversion and | ||
153 | * swapping requested in the passed in touchscreen_properties and store | ||
154 | * the result in a struct input_mt_pos. | ||
155 | */ | ||
156 | void touchscreen_set_mt_pos(struct input_mt_pos *pos, | ||
157 | const struct touchscreen_properties *prop, | ||
158 | unsigned int x, unsigned int y) | ||
159 | { | ||
160 | touchscreen_apply_prop_to_x_y(prop, &x, &y); | ||
161 | pos->x = x; | ||
162 | pos->y = y; | ||
163 | } | ||
164 | EXPORT_SYMBOL(touchscreen_set_mt_pos); | ||
165 | |||
166 | /** | ||
167 | * touchscreen_report_pos - Report touchscreen coordinates | ||
168 | * @input: input_device to report coordinates for | ||
169 | * @prop: pointer to a struct touchscreen_properties | ||
170 | * @x: X coordinate to report | ||
171 | * @y: Y coordinate to report | ||
172 | * @multitouch: Report coordinates on single-touch or multi-touch axes | ||
173 | * | ||
174 | * Adjust the passed in x and y values applying any axis inversion and | ||
175 | * swapping requested in the passed in touchscreen_properties and then | ||
176 | * report the resulting coordinates on the input_dev's x and y axis. | ||
177 | */ | ||
178 | void touchscreen_report_pos(struct input_dev *input, | ||
179 | const struct touchscreen_properties *prop, | ||
180 | unsigned int x, unsigned int y, | ||
181 | bool multitouch) | ||
182 | { | ||
183 | touchscreen_apply_prop_to_x_y(prop, &x, &y); | ||
184 | input_report_abs(input, multitouch ? ABS_MT_POSITION_X : ABS_X, x); | ||
185 | input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y); | ||
186 | } | ||
187 | EXPORT_SYMBOL(touchscreen_report_pos); | ||
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 09523a3d3f23..d159e14f4d20 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include <linux/input/touchscreen.h> | 27 | #include <linux/input/touchscreen.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | #include <linux/gpio/consumer.h> | 29 | #include <linux/gpio/consumer.h> |
30 | /*#include <linux/of.h>*/ | ||
31 | #include <linux/of_device.h> | 30 | #include <linux/of_device.h> |
32 | #include <linux/platform_data/pixcir_i2c_ts.h> | 31 | #include <linux/platform_data/pixcir_i2c_ts.h> |
32 | #include <asm/unaligned.h> | ||
33 | 33 | ||
34 | #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ | 34 | #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ |
35 | 35 | ||
@@ -41,19 +41,15 @@ struct pixcir_i2c_ts_data { | |||
41 | struct gpio_desc *gpio_enable; | 41 | struct gpio_desc *gpio_enable; |
42 | struct gpio_desc *gpio_wake; | 42 | struct gpio_desc *gpio_wake; |
43 | const struct pixcir_i2c_chip_data *chip; | 43 | const struct pixcir_i2c_chip_data *chip; |
44 | struct touchscreen_properties prop; | ||
44 | int max_fingers; /* Max fingers supported in this instance */ | 45 | int max_fingers; /* Max fingers supported in this instance */ |
45 | bool running; | 46 | bool running; |
46 | }; | 47 | }; |
47 | 48 | ||
48 | struct pixcir_touch { | ||
49 | int x; | ||
50 | int y; | ||
51 | int id; | ||
52 | }; | ||
53 | |||
54 | struct pixcir_report_data { | 49 | struct pixcir_report_data { |
55 | int num_touches; | 50 | int num_touches; |
56 | struct pixcir_touch touches[PIXCIR_MAX_SLOTS]; | 51 | struct input_mt_pos pos[PIXCIR_MAX_SLOTS]; |
52 | int ids[PIXCIR_MAX_SLOTS]; | ||
57 | }; | 53 | }; |
58 | 54 | ||
59 | static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | 55 | static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, |
@@ -98,11 +94,11 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | |||
98 | bufptr = &rdbuf[2]; | 94 | bufptr = &rdbuf[2]; |
99 | 95 | ||
100 | for (i = 0; i < touch; i++) { | 96 | for (i = 0; i < touch; i++) { |
101 | report->touches[i].x = (bufptr[1] << 8) | bufptr[0]; | 97 | touchscreen_set_mt_pos(&report->pos[i], &tsdata->prop, |
102 | report->touches[i].y = (bufptr[3] << 8) | bufptr[2]; | 98 | get_unaligned_le16(bufptr), |
103 | 99 | get_unaligned_le16(bufptr + 2)); | |
104 | if (chip->has_hw_ids) { | 100 | if (chip->has_hw_ids) { |
105 | report->touches[i].id = bufptr[4]; | 101 | report->ids[i] = bufptr[4]; |
106 | bufptr = bufptr + 5; | 102 | bufptr = bufptr + 5; |
107 | } else { | 103 | } else { |
108 | bufptr = bufptr + 4; | 104 | bufptr = bufptr + 4; |
@@ -113,9 +109,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | |||
113 | static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, | 109 | static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, |
114 | struct pixcir_report_data *report) | 110 | struct pixcir_report_data *report) |
115 | { | 111 | { |
116 | struct input_mt_pos pos[PIXCIR_MAX_SLOTS]; | ||
117 | int slots[PIXCIR_MAX_SLOTS]; | 112 | int slots[PIXCIR_MAX_SLOTS]; |
118 | struct pixcir_touch *touch; | ||
119 | int n, i, slot; | 113 | int n, i, slot; |
120 | struct device *dev = &ts->client->dev; | 114 | struct device *dev = &ts->client->dev; |
121 | const struct pixcir_i2c_chip_data *chip = ts->chip; | 115 | const struct pixcir_i2c_chip_data *chip = ts->chip; |
@@ -124,24 +118,16 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, | |||
124 | if (n > PIXCIR_MAX_SLOTS) | 118 | if (n > PIXCIR_MAX_SLOTS) |
125 | n = PIXCIR_MAX_SLOTS; | 119 | n = PIXCIR_MAX_SLOTS; |
126 | 120 | ||
127 | if (!ts->chip->has_hw_ids) { | 121 | if (!ts->chip->has_hw_ids) |
128 | for (i = 0; i < n; i++) { | 122 | input_mt_assign_slots(ts->input, slots, report->pos, n, 0); |
129 | touch = &report->touches[i]; | ||
130 | pos[i].x = touch->x; | ||
131 | pos[i].y = touch->y; | ||
132 | } | ||
133 | |||
134 | input_mt_assign_slots(ts->input, slots, pos, n, 0); | ||
135 | } | ||
136 | 123 | ||
137 | for (i = 0; i < n; i++) { | 124 | for (i = 0; i < n; i++) { |
138 | touch = &report->touches[i]; | ||
139 | |||
140 | if (chip->has_hw_ids) { | 125 | if (chip->has_hw_ids) { |
141 | slot = input_mt_get_slot_by_key(ts->input, touch->id); | 126 | slot = input_mt_get_slot_by_key(ts->input, |
127 | report->ids[i]); | ||
142 | if (slot < 0) { | 128 | if (slot < 0) { |
143 | dev_dbg(dev, "no free slot for id 0x%x\n", | 129 | dev_dbg(dev, "no free slot for id 0x%x\n", |
144 | touch->id); | 130 | report->ids[i]); |
145 | continue; | 131 | continue; |
146 | } | 132 | } |
147 | } else { | 133 | } else { |
@@ -149,14 +135,15 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, | |||
149 | } | 135 | } |
150 | 136 | ||
151 | input_mt_slot(ts->input, slot); | 137 | input_mt_slot(ts->input, slot); |
152 | input_mt_report_slot_state(ts->input, | 138 | input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); |
153 | MT_TOOL_FINGER, true); | ||
154 | 139 | ||
155 | input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x); | 140 | input_report_abs(ts->input, ABS_MT_POSITION_X, |
156 | input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y); | 141 | report->pos[i].x); |
142 | input_report_abs(ts->input, ABS_MT_POSITION_Y, | ||
143 | report->pos[i].y); | ||
157 | 144 | ||
158 | dev_dbg(dev, "%d: slot %d, x %d, y %d\n", | 145 | dev_dbg(dev, "%d: slot %d, x %d, y %d\n", |
159 | i, slot, touch->x, touch->y); | 146 | i, slot, report->pos[i].x, report->pos[i].y); |
160 | } | 147 | } |
161 | 148 | ||
162 | input_mt_sync_frame(ts->input); | 149 | input_mt_sync_frame(ts->input); |
@@ -515,7 +502,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, | |||
515 | } else { | 502 | } else { |
516 | input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); | 503 | input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); |
517 | input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); | 504 | input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); |
518 | touchscreen_parse_properties(input, true); | 505 | touchscreen_parse_properties(input, true, &tsdata->prop); |
519 | if (!input_abs_get_max(input, ABS_MT_POSITION_X) || | 506 | if (!input_abs_get_max(input, ABS_MT_POSITION_X) || |
520 | !input_abs_get_max(input, ABS_MT_POSITION_Y)) { | 507 | !input_abs_get_max(input, ABS_MT_POSITION_Y)) { |
521 | dev_err(dev, "Touchscreen size is not specified\n"); | 508 | dev_err(dev, "Touchscreen size is not specified\n"); |
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c new file mode 100644 index 000000000000..a99fb5cac5a0 --- /dev/null +++ b/drivers/input/touchscreen/raydium_i2c_ts.c | |||
@@ -0,0 +1,1238 @@ | |||
1 | /* | ||
2 | * Raydium touchscreen I2C driver. | ||
3 | * | ||
4 | * Copyright (C) 2012-2014, Raydium Semiconductor Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2, and only version 2, as published by the | ||
9 | * Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * Raydium reserves the right to make changes without further notice | ||
17 | * to the materials described herein. Raydium does not assume any | ||
18 | * liability arising out of the application described herein. | ||
19 | * | ||
20 | * Contact Raydium Semiconductor Corporation at www.rad-ic.com | ||
21 | */ | ||
22 | |||
23 | #include <linux/acpi.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/firmware.h> | ||
26 | #include <linux/gpio/consumer.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/input.h> | ||
29 | #include <linux/input/mt.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/of.h> | ||
33 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <asm/unaligned.h> | ||
36 | |||
37 | /* Slave I2C mode */ | ||
38 | #define RM_BOOT_BLDR 0x02 | ||
39 | #define RM_BOOT_MAIN 0x03 | ||
40 | |||
41 | /* I2C bootoloader commands */ | ||
42 | #define RM_CMD_BOOT_PAGE_WRT 0x0B /* send bl page write */ | ||
43 | #define RM_CMD_BOOT_WRT 0x11 /* send bl write */ | ||
44 | #define RM_CMD_BOOT_ACK 0x22 /* send ack*/ | ||
45 | #define RM_CMD_BOOT_CHK 0x33 /* send data check */ | ||
46 | #define RM_CMD_BOOT_READ 0x44 /* send wait bl data ready*/ | ||
47 | |||
48 | #define RM_BOOT_RDY 0xFF /* bl data ready */ | ||
49 | |||
50 | /* I2C main commands */ | ||
51 | #define RM_CMD_QUERY_BANK 0x2B | ||
52 | #define RM_CMD_DATA_BANK 0x4D | ||
53 | #define RM_CMD_ENTER_SLEEP 0x4E | ||
54 | #define RM_CMD_BANK_SWITCH 0xAA | ||
55 | |||
56 | #define RM_RESET_MSG_ADDR 0x40000004 | ||
57 | |||
58 | #define RM_MAX_READ_SIZE 56 | ||
59 | #define RM_PACKET_CRC_SIZE 2 | ||
60 | |||
61 | /* Touch relative info */ | ||
62 | #define RM_MAX_RETRIES 3 | ||
63 | #define RM_MAX_TOUCH_NUM 10 | ||
64 | #define RM_BOOT_DELAY_MS 100 | ||
65 | |||
66 | /* Offsets in contact data */ | ||
67 | #define RM_CONTACT_STATE_POS 0 | ||
68 | #define RM_CONTACT_X_POS 1 | ||
69 | #define RM_CONTACT_Y_POS 3 | ||
70 | #define RM_CONTACT_PRESSURE_POS 5 | ||
71 | #define RM_CONTACT_WIDTH_X_POS 6 | ||
72 | #define RM_CONTACT_WIDTH_Y_POS 7 | ||
73 | |||
74 | /* Bootloader relative info */ | ||
75 | #define RM_BL_WRT_CMD_SIZE 3 /* bl flash wrt cmd size */ | ||
76 | #define RM_BL_WRT_PKG_SIZE 32 /* bl wrt pkg size */ | ||
77 | #define RM_BL_WRT_LEN (RM_BL_WRT_PKG_SIZE + RM_BL_WRT_CMD_SIZE) | ||
78 | #define RM_FW_PAGE_SIZE 128 | ||
79 | #define RM_MAX_FW_RETRIES 30 | ||
80 | #define RM_MAX_FW_SIZE 0xD000 | ||
81 | |||
82 | #define RM_POWERON_DELAY_USEC 500 | ||
83 | #define RM_RESET_DELAY_MSEC 50 | ||
84 | |||
85 | enum raydium_bl_cmd { | ||
86 | BL_HEADER = 0, | ||
87 | BL_PAGE_STR, | ||
88 | BL_PKG_IDX, | ||
89 | BL_DATA_STR, | ||
90 | }; | ||
91 | |||
92 | enum raydium_bl_ack { | ||
93 | RAYDIUM_ACK_NULL = 0, | ||
94 | RAYDIUM_WAIT_READY, | ||
95 | RAYDIUM_PATH_READY, | ||
96 | }; | ||
97 | |||
98 | enum raydium_boot_mode { | ||
99 | RAYDIUM_TS_MAIN = 0, | ||
100 | RAYDIUM_TS_BLDR, | ||
101 | }; | ||
102 | |||
103 | /* Response to RM_CMD_DATA_BANK request */ | ||
104 | struct raydium_data_info { | ||
105 | __le32 data_bank_addr; | ||
106 | u8 pkg_size; | ||
107 | u8 tp_info_size; | ||
108 | }; | ||
109 | |||
110 | struct raydium_info { | ||
111 | __le32 hw_ver; /*device version */ | ||
112 | u8 main_ver; | ||
113 | u8 sub_ver; | ||
114 | __le16 ft_ver; /* test version */ | ||
115 | u8 x_num; | ||
116 | u8 y_num; | ||
117 | __le16 x_max; | ||
118 | __le16 y_max; | ||
119 | u8 x_res; /* units/mm */ | ||
120 | u8 y_res; /* units/mm */ | ||
121 | }; | ||
122 | |||
123 | /* struct raydium_data - represents state of Raydium touchscreen device */ | ||
124 | struct raydium_data { | ||
125 | struct i2c_client *client; | ||
126 | struct input_dev *input; | ||
127 | |||
128 | struct regulator *avdd; | ||
129 | struct regulator *vccio; | ||
130 | struct gpio_desc *reset_gpio; | ||
131 | |||
132 | struct raydium_info info; | ||
133 | |||
134 | struct mutex sysfs_mutex; | ||
135 | |||
136 | u8 *report_data; | ||
137 | |||
138 | u32 data_bank_addr; | ||
139 | u8 report_size; | ||
140 | u8 contact_size; | ||
141 | u8 pkg_size; | ||
142 | |||
143 | enum raydium_boot_mode boot_mode; | ||
144 | |||
145 | bool wake_irq_enabled; | ||
146 | }; | ||
147 | |||
148 | static int raydium_i2c_send(struct i2c_client *client, | ||
149 | u8 addr, const void *data, size_t len) | ||
150 | { | ||
151 | u8 *buf; | ||
152 | int tries = 0; | ||
153 | int ret; | ||
154 | |||
155 | buf = kmalloc(len + 1, GFP_KERNEL); | ||
156 | if (!buf) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | buf[0] = addr; | ||
160 | memcpy(buf + 1, data, len); | ||
161 | |||
162 | do { | ||
163 | ret = i2c_master_send(client, buf, len + 1); | ||
164 | if (likely(ret == len + 1)) | ||
165 | break; | ||
166 | |||
167 | msleep(20); | ||
168 | } while (++tries < RM_MAX_RETRIES); | ||
169 | |||
170 | kfree(buf); | ||
171 | |||
172 | if (unlikely(ret != len + 1)) { | ||
173 | if (ret >= 0) | ||
174 | ret = -EIO; | ||
175 | dev_err(&client->dev, "%s failed: %d\n", __func__, ret); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int raydium_i2c_read(struct i2c_client *client, | ||
183 | u8 addr, void *data, size_t len) | ||
184 | { | ||
185 | struct i2c_msg xfer[] = { | ||
186 | { | ||
187 | .addr = client->addr, | ||
188 | .len = 1, | ||
189 | .buf = &addr, | ||
190 | }, | ||
191 | { | ||
192 | .addr = client->addr, | ||
193 | .flags = I2C_M_RD, | ||
194 | .len = len, | ||
195 | .buf = data, | ||
196 | } | ||
197 | }; | ||
198 | int ret; | ||
199 | |||
200 | ret = i2c_transfer(client->adapter, xfer, ARRAY_SIZE(xfer)); | ||
201 | if (unlikely(ret != ARRAY_SIZE(xfer))) | ||
202 | return ret < 0 ? ret : -EIO; | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int raydium_i2c_read_message(struct i2c_client *client, | ||
208 | u32 addr, void *data, size_t len) | ||
209 | { | ||
210 | __be32 be_addr; | ||
211 | size_t xfer_len; | ||
212 | int error; | ||
213 | |||
214 | while (len) { | ||
215 | xfer_len = min_t(size_t, len, RM_MAX_READ_SIZE); | ||
216 | |||
217 | be_addr = cpu_to_be32(addr); | ||
218 | |||
219 | error = raydium_i2c_send(client, RM_CMD_BANK_SWITCH, | ||
220 | &be_addr, sizeof(be_addr)); | ||
221 | if (!error) | ||
222 | error = raydium_i2c_read(client, addr & 0xff, | ||
223 | data, xfer_len); | ||
224 | if (error) | ||
225 | return error; | ||
226 | |||
227 | len -= xfer_len; | ||
228 | data += xfer_len; | ||
229 | addr += xfer_len; | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int raydium_i2c_send_message(struct i2c_client *client, | ||
236 | u32 addr, const void *data, size_t len) | ||
237 | { | ||
238 | __be32 be_addr = cpu_to_be32(addr); | ||
239 | int error; | ||
240 | |||
241 | error = raydium_i2c_send(client, RM_CMD_BANK_SWITCH, | ||
242 | &be_addr, sizeof(be_addr)); | ||
243 | if (!error) | ||
244 | error = raydium_i2c_send(client, addr & 0xff, data, len); | ||
245 | |||
246 | return error; | ||
247 | } | ||
248 | |||
249 | static int raydium_i2c_sw_reset(struct i2c_client *client) | ||
250 | { | ||
251 | const u8 soft_rst_cmd = 0x01; | ||
252 | int error; | ||
253 | |||
254 | error = raydium_i2c_send_message(client, RM_RESET_MSG_ADDR, | ||
255 | &soft_rst_cmd, sizeof(soft_rst_cmd)); | ||
256 | if (error) { | ||
257 | dev_err(&client->dev, "software reset failed: %d\n", error); | ||
258 | return error; | ||
259 | } | ||
260 | |||
261 | msleep(RM_RESET_DELAY_MSEC); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int raydium_i2c_query_ts_info(struct raydium_data *ts) | ||
267 | { | ||
268 | struct i2c_client *client = ts->client; | ||
269 | struct raydium_data_info data_info; | ||
270 | __le32 query_bank_addr; | ||
271 | |||
272 | int error, retry_cnt; | ||
273 | |||
274 | for (retry_cnt = 0; retry_cnt < RM_MAX_RETRIES; retry_cnt++) { | ||
275 | error = raydium_i2c_read(client, RM_CMD_DATA_BANK, | ||
276 | &data_info, sizeof(data_info)); | ||
277 | if (error) | ||
278 | continue; | ||
279 | |||
280 | /* | ||
281 | * Warn user if we already allocated memory for reports and | ||
282 | * then the size changed (due to firmware update?) and keep | ||
283 | * old size instead. | ||
284 | */ | ||
285 | if (ts->report_data && ts->pkg_size != data_info.pkg_size) { | ||
286 | dev_warn(&client->dev, | ||
287 | "report size changes, was: %d, new: %d\n", | ||
288 | ts->pkg_size, data_info.pkg_size); | ||
289 | } else { | ||
290 | ts->pkg_size = data_info.pkg_size; | ||
291 | ts->report_size = ts->pkg_size - RM_PACKET_CRC_SIZE; | ||
292 | } | ||
293 | |||
294 | ts->contact_size = data_info.tp_info_size; | ||
295 | ts->data_bank_addr = le32_to_cpu(data_info.data_bank_addr); | ||
296 | |||
297 | dev_dbg(&client->dev, | ||
298 | "data_bank_addr: %#08x, report_size: %d, contact_size: %d\n", | ||
299 | ts->data_bank_addr, ts->report_size, ts->contact_size); | ||
300 | |||
301 | error = raydium_i2c_read(client, RM_CMD_QUERY_BANK, | ||
302 | &query_bank_addr, | ||
303 | sizeof(query_bank_addr)); | ||
304 | if (error) | ||
305 | continue; | ||
306 | |||
307 | error = raydium_i2c_read_message(client, | ||
308 | le32_to_cpu(query_bank_addr), | ||
309 | &ts->info, sizeof(ts->info)); | ||
310 | if (error) | ||
311 | continue; | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | dev_err(&client->dev, "failed to query device parameters: %d\n", error); | ||
317 | return error; | ||
318 | } | ||
319 | |||
320 | static int raydium_i2c_check_fw_status(struct raydium_data *ts) | ||
321 | { | ||
322 | struct i2c_client *client = ts->client; | ||
323 | static const u8 bl_ack = 0x62; | ||
324 | static const u8 main_ack = 0x66; | ||
325 | u8 buf[4]; | ||
326 | int error; | ||
327 | |||
328 | error = raydium_i2c_read(client, RM_CMD_BOOT_READ, buf, sizeof(buf)); | ||
329 | if (!error) { | ||
330 | if (buf[0] == bl_ack) | ||
331 | ts->boot_mode = RAYDIUM_TS_BLDR; | ||
332 | else if (buf[0] == main_ack) | ||
333 | ts->boot_mode = RAYDIUM_TS_MAIN; | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | return error; | ||
338 | } | ||
339 | |||
340 | static int raydium_i2c_initialize(struct raydium_data *ts) | ||
341 | { | ||
342 | struct i2c_client *client = ts->client; | ||
343 | int error, retry_cnt; | ||
344 | |||
345 | for (retry_cnt = 0; retry_cnt < RM_MAX_RETRIES; retry_cnt++) { | ||
346 | /* Wait for Hello packet */ | ||
347 | msleep(RM_BOOT_DELAY_MS); | ||
348 | |||
349 | error = raydium_i2c_check_fw_status(ts); | ||
350 | if (error) { | ||
351 | dev_err(&client->dev, | ||
352 | "failed to read 'hello' packet: %d\n", error); | ||
353 | continue; | ||
354 | } | ||
355 | |||
356 | if (ts->boot_mode == RAYDIUM_TS_BLDR || | ||
357 | ts->boot_mode == RAYDIUM_TS_MAIN) { | ||
358 | break; | ||
359 | } | ||
360 | } | ||
361 | |||
362 | if (error) | ||
363 | ts->boot_mode = RAYDIUM_TS_BLDR; | ||
364 | |||
365 | if (ts->boot_mode == RAYDIUM_TS_BLDR) { | ||
366 | ts->info.hw_ver = cpu_to_le32(0xffffffffUL); | ||
367 | ts->info.main_ver = 0xff; | ||
368 | ts->info.sub_ver = 0xff; | ||
369 | } else { | ||
370 | raydium_i2c_query_ts_info(ts); | ||
371 | } | ||
372 | |||
373 | return error; | ||
374 | } | ||
375 | |||
376 | static int raydium_i2c_bl_chk_state(struct i2c_client *client, | ||
377 | enum raydium_bl_ack state) | ||
378 | { | ||
379 | static const u8 ack_ok[] = { 0xFF, 0x39, 0x30, 0x30, 0x54 }; | ||
380 | u8 rbuf[sizeof(ack_ok)]; | ||
381 | u8 retry; | ||
382 | int error; | ||
383 | |||
384 | for (retry = 0; retry < RM_MAX_FW_RETRIES; retry++) { | ||
385 | switch (state) { | ||
386 | case RAYDIUM_ACK_NULL: | ||
387 | return 0; | ||
388 | |||
389 | case RAYDIUM_WAIT_READY: | ||
390 | error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, | ||
391 | &rbuf[0], 1); | ||
392 | if (!error && rbuf[0] == RM_BOOT_RDY) | ||
393 | return 0; | ||
394 | |||
395 | break; | ||
396 | |||
397 | case RAYDIUM_PATH_READY: | ||
398 | error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, | ||
399 | rbuf, sizeof(rbuf)); | ||
400 | if (!error && !memcmp(rbuf, ack_ok, sizeof(ack_ok))) | ||
401 | return 0; | ||
402 | |||
403 | break; | ||
404 | |||
405 | default: | ||
406 | dev_err(&client->dev, "%s: invalid target state %d\n", | ||
407 | __func__, state); | ||
408 | return -EINVAL; | ||
409 | } | ||
410 | |||
411 | msleep(20); | ||
412 | } | ||
413 | |||
414 | return -ETIMEDOUT; | ||
415 | } | ||
416 | |||
417 | static int raydium_i2c_write_object(struct i2c_client *client, | ||
418 | const void *data, size_t len, | ||
419 | enum raydium_bl_ack state) | ||
420 | { | ||
421 | int error; | ||
422 | |||
423 | error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len); | ||
424 | if (error) { | ||
425 | dev_err(&client->dev, "WRT obj command failed: %d\n", | ||
426 | error); | ||
427 | return error; | ||
428 | } | ||
429 | |||
430 | error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, NULL, 0); | ||
431 | if (error) { | ||
432 | dev_err(&client->dev, "Ack obj command failed: %d\n", error); | ||
433 | return error; | ||
434 | } | ||
435 | |||
436 | error = raydium_i2c_bl_chk_state(client, state); | ||
437 | if (error) { | ||
438 | dev_err(&client->dev, "BL check state failed: %d\n", error); | ||
439 | return error; | ||
440 | } | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static bool raydium_i2c_boot_trigger(struct i2c_client *client) | ||
445 | { | ||
446 | static const u8 cmd[7][6] = { | ||
447 | { 0x08, 0x0C, 0x09, 0x00, 0x50, 0xD7 }, | ||
448 | { 0x08, 0x04, 0x09, 0x00, 0x50, 0xA5 }, | ||
449 | { 0x08, 0x04, 0x09, 0x00, 0x50, 0x00 }, | ||
450 | { 0x08, 0x04, 0x09, 0x00, 0x50, 0xA5 }, | ||
451 | { 0x08, 0x0C, 0x09, 0x00, 0x50, 0x00 }, | ||
452 | { 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 }, | ||
453 | { 0x02, 0xA2, 0x00, 0x00, 0x00, 0x00 }, | ||
454 | }; | ||
455 | int i; | ||
456 | int error; | ||
457 | |||
458 | for (i = 0; i < 7; i++) { | ||
459 | error = raydium_i2c_write_object(client, cmd[i], sizeof(cmd[i]), | ||
460 | RAYDIUM_WAIT_READY); | ||
461 | if (error) { | ||
462 | dev_err(&client->dev, | ||
463 | "boot trigger failed at step %d: %d\n", | ||
464 | i, error); | ||
465 | return error; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static bool raydium_i2c_fw_trigger(struct i2c_client *client) | ||
473 | { | ||
474 | static const u8 cmd[5][11] = { | ||
475 | { 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0xD7, 0, 0, 0 }, | ||
476 | { 0, 0x09, 0x71, 0x04, 0x09, 0x00, 0x50, 0xA5, 0, 0, 0 }, | ||
477 | { 0, 0x09, 0x71, 0x04, 0x09, 0x00, 0x50, 0x00, 0, 0, 0 }, | ||
478 | { 0, 0x09, 0x71, 0x04, 0x09, 0x00, 0x50, 0xA5, 0, 0, 0 }, | ||
479 | { 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0x00, 0, 0, 0 }, | ||
480 | }; | ||
481 | int i; | ||
482 | int error; | ||
483 | |||
484 | for (i = 0; i < 5; i++) { | ||
485 | error = raydium_i2c_write_object(client, cmd[i], sizeof(cmd[i]), | ||
486 | RAYDIUM_ACK_NULL); | ||
487 | if (error) { | ||
488 | dev_err(&client->dev, | ||
489 | "fw trigger failed at step %d: %d\n", | ||
490 | i, error); | ||
491 | return error; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static int raydium_i2c_check_path(struct i2c_client *client) | ||
499 | { | ||
500 | static const u8 cmd[] = { 0x09, 0x00, 0x09, 0x00, 0x50, 0x10, 0x00 }; | ||
501 | int error; | ||
502 | |||
503 | error = raydium_i2c_write_object(client, cmd, sizeof(cmd), | ||
504 | RAYDIUM_PATH_READY); | ||
505 | if (error) { | ||
506 | dev_err(&client->dev, "check path command failed: %d\n", error); | ||
507 | return error; | ||
508 | } | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static int raydium_i2c_enter_bl(struct i2c_client *client) | ||
514 | { | ||
515 | static const u8 cal_cmd[] = { 0x00, 0x01, 0x52 }; | ||
516 | int error; | ||
517 | |||
518 | error = raydium_i2c_write_object(client, cal_cmd, sizeof(cal_cmd), | ||
519 | RAYDIUM_ACK_NULL); | ||
520 | if (error) { | ||
521 | dev_err(&client->dev, "enter bl command failed: %d\n", error); | ||
522 | return error; | ||
523 | } | ||
524 | |||
525 | msleep(RM_BOOT_DELAY_MS); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static int raydium_i2c_leave_bl(struct i2c_client *client) | ||
530 | { | ||
531 | static const u8 leave_cmd[] = { 0x05, 0x00 }; | ||
532 | int error; | ||
533 | |||
534 | error = raydium_i2c_write_object(client, leave_cmd, sizeof(leave_cmd), | ||
535 | RAYDIUM_ACK_NULL); | ||
536 | if (error) { | ||
537 | dev_err(&client->dev, "leave bl command failed: %d\n", error); | ||
538 | return error; | ||
539 | } | ||
540 | |||
541 | msleep(RM_BOOT_DELAY_MS); | ||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | static int raydium_i2c_write_checksum(struct i2c_client *client, | ||
546 | size_t length, u16 checksum) | ||
547 | { | ||
548 | u8 checksum_cmd[] = { 0x00, 0x05, 0x6D, 0x00, 0x00, 0x00, 0x00 }; | ||
549 | int error; | ||
550 | |||
551 | put_unaligned_le16(length, &checksum_cmd[3]); | ||
552 | put_unaligned_le16(checksum, &checksum_cmd[5]); | ||
553 | |||
554 | error = raydium_i2c_write_object(client, | ||
555 | checksum_cmd, sizeof(checksum_cmd), | ||
556 | RAYDIUM_ACK_NULL); | ||
557 | if (error) { | ||
558 | dev_err(&client->dev, "failed to write checksum: %d\n", | ||
559 | error); | ||
560 | return error; | ||
561 | } | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int raydium_i2c_disable_watch_dog(struct i2c_client *client) | ||
567 | { | ||
568 | static const u8 cmd[] = { 0x0A, 0xAA }; | ||
569 | int error; | ||
570 | |||
571 | error = raydium_i2c_write_object(client, cmd, sizeof(cmd), | ||
572 | RAYDIUM_WAIT_READY); | ||
573 | if (error) { | ||
574 | dev_err(&client->dev, "disable watchdog command failed: %d\n", | ||
575 | error); | ||
576 | return error; | ||
577 | } | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int raydium_i2c_fw_write_page(struct i2c_client *client, | ||
583 | u16 page_idx, const void *data, size_t len) | ||
584 | { | ||
585 | u8 buf[RM_BL_WRT_LEN]; | ||
586 | size_t xfer_len; | ||
587 | int error; | ||
588 | int i; | ||
589 | |||
590 | BUILD_BUG_ON((RM_FW_PAGE_SIZE % RM_BL_WRT_PKG_SIZE) != 0); | ||
591 | |||
592 | for (i = 0; i < RM_FW_PAGE_SIZE / RM_BL_WRT_PKG_SIZE; i++) { | ||
593 | buf[BL_HEADER] = RM_CMD_BOOT_PAGE_WRT; | ||
594 | buf[BL_PAGE_STR] = page_idx ? 0xff : 0; | ||
595 | buf[BL_PKG_IDX] = i + 1; | ||
596 | |||
597 | xfer_len = min_t(size_t, len, RM_BL_WRT_PKG_SIZE); | ||
598 | memcpy(&buf[BL_DATA_STR], data, xfer_len); | ||
599 | if (len < RM_BL_WRT_PKG_SIZE) | ||
600 | memset(&buf[BL_DATA_STR + xfer_len], 0xff, | ||
601 | RM_BL_WRT_PKG_SIZE - xfer_len); | ||
602 | |||
603 | error = raydium_i2c_write_object(client, buf, RM_BL_WRT_LEN, | ||
604 | RAYDIUM_WAIT_READY); | ||
605 | if (error) { | ||
606 | dev_err(&client->dev, | ||
607 | "page write command failed for page %d, chunk %d: %d\n", | ||
608 | page_idx, i, error); | ||
609 | return error; | ||
610 | } | ||
611 | |||
612 | data += xfer_len; | ||
613 | len -= xfer_len; | ||
614 | } | ||
615 | |||
616 | return error; | ||
617 | } | ||
618 | |||
619 | static u16 raydium_calc_chksum(const u8 *buf, u16 len) | ||
620 | { | ||
621 | u16 checksum = 0; | ||
622 | u16 i; | ||
623 | |||
624 | for (i = 0; i < len; i++) | ||
625 | checksum += buf[i]; | ||
626 | |||
627 | return checksum; | ||
628 | } | ||
629 | |||
630 | static int raydium_i2c_do_update_firmware(struct raydium_data *ts, | ||
631 | const struct firmware *fw) | ||
632 | { | ||
633 | struct i2c_client *client = ts->client; | ||
634 | const void *data; | ||
635 | size_t data_len; | ||
636 | size_t len; | ||
637 | int page_nr; | ||
638 | int i; | ||
639 | int error; | ||
640 | u16 fw_checksum; | ||
641 | |||
642 | if (fw->size == 0 || fw->size > RM_MAX_FW_SIZE) { | ||
643 | dev_err(&client->dev, "Invalid firmware length\n"); | ||
644 | return -EINVAL; | ||
645 | } | ||
646 | |||
647 | error = raydium_i2c_check_fw_status(ts); | ||
648 | if (error) { | ||
649 | dev_err(&client->dev, "Unable to access IC %d\n", error); | ||
650 | return error; | ||
651 | } | ||
652 | |||
653 | if (ts->boot_mode == RAYDIUM_TS_MAIN) { | ||
654 | for (i = 0; i < RM_MAX_RETRIES; i++) { | ||
655 | error = raydium_i2c_enter_bl(client); | ||
656 | if (!error) { | ||
657 | error = raydium_i2c_check_fw_status(ts); | ||
658 | if (error) { | ||
659 | dev_err(&client->dev, | ||
660 | "unable to access IC: %d\n", | ||
661 | error); | ||
662 | return error; | ||
663 | } | ||
664 | |||
665 | if (ts->boot_mode == RAYDIUM_TS_BLDR) | ||
666 | break; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | if (ts->boot_mode == RAYDIUM_TS_MAIN) { | ||
671 | dev_err(&client->dev, | ||
672 | "failied to jump to boot loader: %d\n", | ||
673 | error); | ||
674 | return -EIO; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | error = raydium_i2c_disable_watch_dog(client); | ||
679 | if (error) | ||
680 | return error; | ||
681 | |||
682 | error = raydium_i2c_check_path(client); | ||
683 | if (error) | ||
684 | return error; | ||
685 | |||
686 | error = raydium_i2c_boot_trigger(client); | ||
687 | if (error) { | ||
688 | dev_err(&client->dev, "send boot trigger fail: %d\n", error); | ||
689 | return error; | ||
690 | } | ||
691 | |||
692 | msleep(RM_BOOT_DELAY_MS); | ||
693 | |||
694 | data = fw->data; | ||
695 | data_len = fw->size; | ||
696 | page_nr = 0; | ||
697 | |||
698 | while (data_len) { | ||
699 | len = min_t(size_t, data_len, RM_FW_PAGE_SIZE); | ||
700 | |||
701 | error = raydium_i2c_fw_write_page(client, page_nr++, data, len); | ||
702 | if (error) | ||
703 | return error; | ||
704 | |||
705 | msleep(20); | ||
706 | |||
707 | data += len; | ||
708 | data_len -= len; | ||
709 | } | ||
710 | |||
711 | error = raydium_i2c_leave_bl(client); | ||
712 | if (error) { | ||
713 | dev_err(&client->dev, | ||
714 | "failed to leave boot loader: %d\n", error); | ||
715 | return error; | ||
716 | } | ||
717 | |||
718 | dev_dbg(&client->dev, "left boot loader mode\n"); | ||
719 | msleep(RM_BOOT_DELAY_MS); | ||
720 | |||
721 | error = raydium_i2c_check_fw_status(ts); | ||
722 | if (error) { | ||
723 | dev_err(&client->dev, | ||
724 | "failed to check fw status after write: %d\n", | ||
725 | error); | ||
726 | return error; | ||
727 | } | ||
728 | |||
729 | if (ts->boot_mode != RAYDIUM_TS_MAIN) { | ||
730 | dev_err(&client->dev, | ||
731 | "failed to switch to main fw after writing firmware: %d\n", | ||
732 | error); | ||
733 | return -EINVAL; | ||
734 | } | ||
735 | |||
736 | error = raydium_i2c_fw_trigger(client); | ||
737 | if (error) { | ||
738 | dev_err(&client->dev, "failed to trigger fw: %d\n", error); | ||
739 | return error; | ||
740 | } | ||
741 | |||
742 | fw_checksum = raydium_calc_chksum(fw->data, fw->size); | ||
743 | |||
744 | error = raydium_i2c_write_checksum(client, fw->size, fw_checksum); | ||
745 | if (error) | ||
746 | return error; | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static int raydium_i2c_fw_update(struct raydium_data *ts) | ||
752 | { | ||
753 | struct i2c_client *client = ts->client; | ||
754 | const struct firmware *fw = NULL; | ||
755 | const char *fw_file = "raydium.fw"; | ||
756 | int error; | ||
757 | |||
758 | error = request_firmware(&fw, fw_file, &client->dev); | ||
759 | if (error) { | ||
760 | dev_err(&client->dev, "Unable to open firmware %s\n", fw_file); | ||
761 | return error; | ||
762 | } | ||
763 | |||
764 | disable_irq(client->irq); | ||
765 | |||
766 | error = raydium_i2c_do_update_firmware(ts, fw); | ||
767 | if (error) { | ||
768 | dev_err(&client->dev, "firmware update failed: %d\n", error); | ||
769 | ts->boot_mode = RAYDIUM_TS_BLDR; | ||
770 | goto out_enable_irq; | ||
771 | } | ||
772 | |||
773 | error = raydium_i2c_initialize(ts); | ||
774 | if (error) { | ||
775 | dev_err(&client->dev, | ||
776 | "failed to initialize device after firmware update: %d\n", | ||
777 | error); | ||
778 | ts->boot_mode = RAYDIUM_TS_BLDR; | ||
779 | goto out_enable_irq; | ||
780 | } | ||
781 | |||
782 | ts->boot_mode = RAYDIUM_TS_MAIN; | ||
783 | |||
784 | out_enable_irq: | ||
785 | enable_irq(client->irq); | ||
786 | msleep(100); | ||
787 | |||
788 | release_firmware(fw); | ||
789 | |||
790 | return error; | ||
791 | } | ||
792 | |||
793 | static void raydium_mt_event(struct raydium_data *ts) | ||
794 | { | ||
795 | int i; | ||
796 | |||
797 | for (i = 0; i < ts->report_size / ts->contact_size; i++) { | ||
798 | u8 *contact = &ts->report_data[ts->contact_size * i]; | ||
799 | bool state = contact[RM_CONTACT_STATE_POS]; | ||
800 | u8 wx, wy; | ||
801 | |||
802 | input_mt_slot(ts->input, i); | ||
803 | input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, state); | ||
804 | |||
805 | if (!state) | ||
806 | continue; | ||
807 | |||
808 | input_report_abs(ts->input, ABS_MT_POSITION_X, | ||
809 | get_unaligned_le16(&contact[RM_CONTACT_X_POS])); | ||
810 | input_report_abs(ts->input, ABS_MT_POSITION_Y, | ||
811 | get_unaligned_le16(&contact[RM_CONTACT_Y_POS])); | ||
812 | input_report_abs(ts->input, ABS_MT_PRESSURE, | ||
813 | contact[RM_CONTACT_PRESSURE_POS]); | ||
814 | |||
815 | wx = contact[RM_CONTACT_WIDTH_X_POS]; | ||
816 | wy = contact[RM_CONTACT_WIDTH_Y_POS]; | ||
817 | |||
818 | input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, max(wx, wy)); | ||
819 | input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, min(wx, wy)); | ||
820 | } | ||
821 | |||
822 | input_mt_sync_frame(ts->input); | ||
823 | input_sync(ts->input); | ||
824 | } | ||
825 | |||
826 | static irqreturn_t raydium_i2c_irq(int irq, void *_dev) | ||
827 | { | ||
828 | struct raydium_data *ts = _dev; | ||
829 | int error; | ||
830 | u16 fw_crc; | ||
831 | u16 calc_crc; | ||
832 | |||
833 | if (ts->boot_mode != RAYDIUM_TS_MAIN) | ||
834 | goto out; | ||
835 | |||
836 | error = raydium_i2c_read_message(ts->client, ts->data_bank_addr, | ||
837 | ts->report_data, ts->pkg_size); | ||
838 | if (error) | ||
839 | goto out; | ||
840 | |||
841 | fw_crc = get_unaligned_le16(&ts->report_data[ts->report_size]); | ||
842 | calc_crc = raydium_calc_chksum(ts->report_data, ts->report_size); | ||
843 | if (unlikely(fw_crc != calc_crc)) { | ||
844 | dev_warn(&ts->client->dev, | ||
845 | "%s: invalid packet crc %#04x vs %#04x\n", | ||
846 | __func__, calc_crc, fw_crc); | ||
847 | goto out; | ||
848 | } | ||
849 | |||
850 | raydium_mt_event(ts); | ||
851 | |||
852 | out: | ||
853 | return IRQ_HANDLED; | ||
854 | } | ||
855 | |||
856 | static ssize_t raydium_i2c_fw_ver_show(struct device *dev, | ||
857 | struct device_attribute *attr, char *buf) | ||
858 | { | ||
859 | struct i2c_client *client = to_i2c_client(dev); | ||
860 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
861 | |||
862 | return sprintf(buf, "%d.%d\n", ts->info.main_ver, ts->info.sub_ver); | ||
863 | } | ||
864 | |||
865 | static ssize_t raydium_i2c_hw_ver_show(struct device *dev, | ||
866 | struct device_attribute *attr, char *buf) | ||
867 | { | ||
868 | struct i2c_client *client = to_i2c_client(dev); | ||
869 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
870 | |||
871 | return sprintf(buf, "%#04x\n", le32_to_cpu(ts->info.hw_ver)); | ||
872 | } | ||
873 | |||
874 | static ssize_t raydium_i2c_boot_mode_show(struct device *dev, | ||
875 | struct device_attribute *attr, | ||
876 | char *buf) | ||
877 | { | ||
878 | struct i2c_client *client = to_i2c_client(dev); | ||
879 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
880 | |||
881 | return sprintf(buf, "%s\n", | ||
882 | ts->boot_mode == RAYDIUM_TS_MAIN ? | ||
883 | "Normal" : "Recovery"); | ||
884 | } | ||
885 | |||
886 | static ssize_t raydium_i2c_update_fw_store(struct device *dev, | ||
887 | struct device_attribute *attr, | ||
888 | const char *buf, size_t count) | ||
889 | { | ||
890 | struct i2c_client *client = to_i2c_client(dev); | ||
891 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
892 | int error; | ||
893 | |||
894 | error = mutex_lock_interruptible(&ts->sysfs_mutex); | ||
895 | if (error) | ||
896 | return error; | ||
897 | |||
898 | error = raydium_i2c_fw_update(ts); | ||
899 | |||
900 | mutex_unlock(&ts->sysfs_mutex); | ||
901 | |||
902 | return error ?: count; | ||
903 | } | ||
904 | |||
905 | static ssize_t raydium_i2c_calibrate_store(struct device *dev, | ||
906 | struct device_attribute *attr, | ||
907 | const char *buf, size_t count) | ||
908 | { | ||
909 | struct i2c_client *client = to_i2c_client(dev); | ||
910 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
911 | static const u8 cal_cmd[] = { 0x00, 0x01, 0x9E }; | ||
912 | int error; | ||
913 | |||
914 | error = mutex_lock_interruptible(&ts->sysfs_mutex); | ||
915 | if (error) | ||
916 | return error; | ||
917 | |||
918 | error = raydium_i2c_write_object(client, cal_cmd, sizeof(cal_cmd), | ||
919 | RAYDIUM_WAIT_READY); | ||
920 | if (error) | ||
921 | dev_err(&client->dev, "calibrate command failed: %d\n", error); | ||
922 | |||
923 | mutex_unlock(&ts->sysfs_mutex); | ||
924 | return error ?: count; | ||
925 | } | ||
926 | |||
927 | static DEVICE_ATTR(fw_version, S_IRUGO, raydium_i2c_fw_ver_show, NULL); | ||
928 | static DEVICE_ATTR(hw_version, S_IRUGO, raydium_i2c_hw_ver_show, NULL); | ||
929 | static DEVICE_ATTR(boot_mode, S_IRUGO, raydium_i2c_boot_mode_show, NULL); | ||
930 | static DEVICE_ATTR(update_fw, S_IWUSR, NULL, raydium_i2c_update_fw_store); | ||
931 | static DEVICE_ATTR(calibrate, S_IWUSR, NULL, raydium_i2c_calibrate_store); | ||
932 | |||
933 | static struct attribute *raydium_i2c_attributes[] = { | ||
934 | &dev_attr_update_fw.attr, | ||
935 | &dev_attr_boot_mode.attr, | ||
936 | &dev_attr_fw_version.attr, | ||
937 | &dev_attr_hw_version.attr, | ||
938 | &dev_attr_calibrate.attr, | ||
939 | NULL | ||
940 | }; | ||
941 | |||
942 | static struct attribute_group raydium_i2c_attribute_group = { | ||
943 | .attrs = raydium_i2c_attributes, | ||
944 | }; | ||
945 | |||
946 | static void raydium_i2c_remove_sysfs_group(void *_data) | ||
947 | { | ||
948 | struct raydium_data *ts = _data; | ||
949 | |||
950 | sysfs_remove_group(&ts->client->dev.kobj, &raydium_i2c_attribute_group); | ||
951 | } | ||
952 | |||
953 | static int raydium_i2c_power_on(struct raydium_data *ts) | ||
954 | { | ||
955 | int error; | ||
956 | |||
957 | if (!ts->reset_gpio) | ||
958 | return 0; | ||
959 | |||
960 | gpiod_set_value_cansleep(ts->reset_gpio, 1); | ||
961 | |||
962 | error = regulator_enable(ts->avdd); | ||
963 | if (error) { | ||
964 | dev_err(&ts->client->dev, | ||
965 | "failed to enable avdd regulator: %d\n", error); | ||
966 | goto release_reset_gpio; | ||
967 | } | ||
968 | |||
969 | error = regulator_enable(ts->vccio); | ||
970 | if (error) { | ||
971 | regulator_disable(ts->avdd); | ||
972 | dev_err(&ts->client->dev, | ||
973 | "failed to enable vccio regulator: %d\n", error); | ||
974 | goto release_reset_gpio; | ||
975 | } | ||
976 | |||
977 | udelay(RM_POWERON_DELAY_USEC); | ||
978 | |||
979 | release_reset_gpio: | ||
980 | gpiod_set_value_cansleep(ts->reset_gpio, 0); | ||
981 | |||
982 | if (error) | ||
983 | return error; | ||
984 | |||
985 | msleep(RM_RESET_DELAY_MSEC); | ||
986 | |||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | static void raydium_i2c_power_off(void *_data) | ||
991 | { | ||
992 | struct raydium_data *ts = _data; | ||
993 | |||
994 | if (ts->reset_gpio) { | ||
995 | gpiod_set_value_cansleep(ts->reset_gpio, 1); | ||
996 | regulator_disable(ts->vccio); | ||
997 | regulator_disable(ts->avdd); | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | static int raydium_i2c_probe(struct i2c_client *client, | ||
1002 | const struct i2c_device_id *id) | ||
1003 | { | ||
1004 | union i2c_smbus_data dummy; | ||
1005 | struct raydium_data *ts; | ||
1006 | int error; | ||
1007 | |||
1008 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
1009 | dev_err(&client->dev, | ||
1010 | "i2c check functionality error (need I2C_FUNC_I2C)\n"); | ||
1011 | return -ENXIO; | ||
1012 | } | ||
1013 | |||
1014 | ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); | ||
1015 | if (!ts) | ||
1016 | return -ENOMEM; | ||
1017 | |||
1018 | mutex_init(&ts->sysfs_mutex); | ||
1019 | |||
1020 | ts->client = client; | ||
1021 | i2c_set_clientdata(client, ts); | ||
1022 | |||
1023 | ts->avdd = devm_regulator_get(&client->dev, "avdd"); | ||
1024 | if (IS_ERR(ts->avdd)) { | ||
1025 | error = PTR_ERR(ts->avdd); | ||
1026 | if (error != -EPROBE_DEFER) | ||
1027 | dev_err(&client->dev, | ||
1028 | "Failed to get 'avdd' regulator: %d\n", error); | ||
1029 | return error; | ||
1030 | } | ||
1031 | |||
1032 | ts->vccio = devm_regulator_get(&client->dev, "vccio"); | ||
1033 | if (IS_ERR(ts->vccio)) { | ||
1034 | error = PTR_ERR(ts->vccio); | ||
1035 | if (error != -EPROBE_DEFER) | ||
1036 | dev_err(&client->dev, | ||
1037 | "Failed to get 'vccio' regulator: %d\n", error); | ||
1038 | return error; | ||
1039 | } | ||
1040 | |||
1041 | ts->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", | ||
1042 | GPIOD_OUT_LOW); | ||
1043 | if (IS_ERR(ts->reset_gpio)) { | ||
1044 | error = PTR_ERR(ts->reset_gpio); | ||
1045 | if (error != -EPROBE_DEFER) | ||
1046 | dev_err(&client->dev, | ||
1047 | "failed to get reset gpio: %d\n", error); | ||
1048 | return error; | ||
1049 | } | ||
1050 | |||
1051 | error = raydium_i2c_power_on(ts); | ||
1052 | if (error) | ||
1053 | return error; | ||
1054 | |||
1055 | error = devm_add_action(&client->dev, raydium_i2c_power_off, ts); | ||
1056 | if (error) { | ||
1057 | dev_err(&client->dev, | ||
1058 | "failed to install power off action: %d\n", error); | ||
1059 | raydium_i2c_power_off(ts); | ||
1060 | return error; | ||
1061 | } | ||
1062 | |||
1063 | /* Make sure there is something at this address */ | ||
1064 | if (i2c_smbus_xfer(client->adapter, client->addr, 0, | ||
1065 | I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) { | ||
1066 | dev_err(&client->dev, "nothing at this address\n"); | ||
1067 | return -ENXIO; | ||
1068 | } | ||
1069 | |||
1070 | error = raydium_i2c_initialize(ts); | ||
1071 | if (error) { | ||
1072 | dev_err(&client->dev, "failed to initialize: %d\n", error); | ||
1073 | return error; | ||
1074 | } | ||
1075 | |||
1076 | ts->report_data = devm_kmalloc(&client->dev, | ||
1077 | ts->pkg_size, GFP_KERNEL); | ||
1078 | if (!ts->report_data) | ||
1079 | return -ENOMEM; | ||
1080 | |||
1081 | ts->input = devm_input_allocate_device(&client->dev); | ||
1082 | if (!ts->input) { | ||
1083 | dev_err(&client->dev, "Failed to allocate input device\n"); | ||
1084 | return -ENOMEM; | ||
1085 | } | ||
1086 | |||
1087 | ts->input->name = "Raydium Touchscreen"; | ||
1088 | ts->input->id.bustype = BUS_I2C; | ||
1089 | |||
1090 | input_set_drvdata(ts->input, ts); | ||
1091 | |||
1092 | input_set_abs_params(ts->input, ABS_MT_POSITION_X, | ||
1093 | 0, le16_to_cpu(ts->info.x_max), 0, 0); | ||
1094 | input_set_abs_params(ts->input, ABS_MT_POSITION_Y, | ||
1095 | 0, le16_to_cpu(ts->info.y_max), 0, 0); | ||
1096 | input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->info.x_res); | ||
1097 | input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->info.y_res); | ||
1098 | |||
1099 | input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | ||
1100 | input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
1101 | |||
1102 | error = input_mt_init_slots(ts->input, RM_MAX_TOUCH_NUM, | ||
1103 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
1104 | if (error) { | ||
1105 | dev_err(&client->dev, | ||
1106 | "failed to initialize MT slots: %d\n", error); | ||
1107 | return error; | ||
1108 | } | ||
1109 | |||
1110 | error = input_register_device(ts->input); | ||
1111 | if (error) { | ||
1112 | dev_err(&client->dev, | ||
1113 | "unable to register input device: %d\n", error); | ||
1114 | return error; | ||
1115 | } | ||
1116 | |||
1117 | error = devm_request_threaded_irq(&client->dev, client->irq, | ||
1118 | NULL, raydium_i2c_irq, | ||
1119 | IRQF_ONESHOT, client->name, ts); | ||
1120 | if (error) { | ||
1121 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
1122 | return error; | ||
1123 | } | ||
1124 | |||
1125 | error = sysfs_create_group(&client->dev.kobj, | ||
1126 | &raydium_i2c_attribute_group); | ||
1127 | if (error) { | ||
1128 | dev_err(&client->dev, "failed to create sysfs attributes: %d\n", | ||
1129 | error); | ||
1130 | return error; | ||
1131 | } | ||
1132 | |||
1133 | error = devm_add_action(&client->dev, | ||
1134 | raydium_i2c_remove_sysfs_group, ts); | ||
1135 | if (error) { | ||
1136 | raydium_i2c_remove_sysfs_group(ts); | ||
1137 | dev_err(&client->dev, | ||
1138 | "Failed to add sysfs cleanup action: %d\n", error); | ||
1139 | return error; | ||
1140 | } | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | static void __maybe_unused raydium_enter_sleep(struct i2c_client *client) | ||
1146 | { | ||
1147 | static const u8 sleep_cmd[] = { 0x5A, 0xff, 0x00, 0x0f }; | ||
1148 | int error; | ||
1149 | |||
1150 | error = raydium_i2c_send(client, RM_CMD_ENTER_SLEEP, | ||
1151 | sleep_cmd, sizeof(sleep_cmd)); | ||
1152 | if (error) | ||
1153 | dev_err(&client->dev, | ||
1154 | "sleep command failed: %d\n", error); | ||
1155 | } | ||
1156 | |||
1157 | static int __maybe_unused raydium_i2c_suspend(struct device *dev) | ||
1158 | { | ||
1159 | struct i2c_client *client = to_i2c_client(dev); | ||
1160 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
1161 | |||
1162 | /* Sleep is not available in BLDR recovery mode */ | ||
1163 | if (ts->boot_mode != RAYDIUM_TS_MAIN) | ||
1164 | return -EBUSY; | ||
1165 | |||
1166 | disable_irq(client->irq); | ||
1167 | |||
1168 | if (device_may_wakeup(dev)) { | ||
1169 | raydium_enter_sleep(client); | ||
1170 | |||
1171 | ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0); | ||
1172 | } else { | ||
1173 | raydium_i2c_power_off(ts); | ||
1174 | } | ||
1175 | |||
1176 | return 0; | ||
1177 | } | ||
1178 | |||
1179 | static int __maybe_unused raydium_i2c_resume(struct device *dev) | ||
1180 | { | ||
1181 | struct i2c_client *client = to_i2c_client(dev); | ||
1182 | struct raydium_data *ts = i2c_get_clientdata(client); | ||
1183 | |||
1184 | if (device_may_wakeup(dev)) { | ||
1185 | if (ts->wake_irq_enabled) | ||
1186 | disable_irq_wake(client->irq); | ||
1187 | raydium_i2c_sw_reset(client); | ||
1188 | } else { | ||
1189 | raydium_i2c_power_on(ts); | ||
1190 | raydium_i2c_initialize(ts); | ||
1191 | } | ||
1192 | |||
1193 | enable_irq(client->irq); | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
1197 | |||
1198 | static SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops, | ||
1199 | raydium_i2c_suspend, raydium_i2c_resume); | ||
1200 | |||
1201 | static const struct i2c_device_id raydium_i2c_id[] = { | ||
1202 | { "raydium_i2c" , 0 }, | ||
1203 | { "rm32380", 0 }, | ||
1204 | { /* sentinel */ } | ||
1205 | }; | ||
1206 | MODULE_DEVICE_TABLE(i2c, raydium_i2c_id); | ||
1207 | |||
1208 | #ifdef CONFIG_ACPI | ||
1209 | static const struct acpi_device_id raydium_acpi_id[] = { | ||
1210 | { "RAYD0001", 0 }, | ||
1211 | { /* sentinel */ } | ||
1212 | }; | ||
1213 | MODULE_DEVICE_TABLE(acpi, raydium_acpi_id); | ||
1214 | #endif | ||
1215 | |||
1216 | #ifdef CONFIG_OF | ||
1217 | static const struct of_device_id raydium_of_match[] = { | ||
1218 | { .compatible = "raydium,rm32380", }, | ||
1219 | { /* sentinel */ } | ||
1220 | }; | ||
1221 | MODULE_DEVICE_TABLE(of, raydium_of_match); | ||
1222 | #endif | ||
1223 | |||
1224 | static struct i2c_driver raydium_i2c_driver = { | ||
1225 | .probe = raydium_i2c_probe, | ||
1226 | .id_table = raydium_i2c_id, | ||
1227 | .driver = { | ||
1228 | .name = "raydium_ts", | ||
1229 | .pm = &raydium_i2c_pm_ops, | ||
1230 | .acpi_match_table = ACPI_PTR(raydium_acpi_id), | ||
1231 | .of_match_table = of_match_ptr(raydium_of_match), | ||
1232 | }, | ||
1233 | }; | ||
1234 | module_i2c_driver(raydium_i2c_driver); | ||
1235 | |||
1236 | MODULE_AUTHOR("Raydium"); | ||
1237 | MODULE_DESCRIPTION("Raydium I2c Touchscreen driver"); | ||
1238 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/surface3_spi.c b/drivers/input/touchscreen/surface3_spi.c new file mode 100644 index 000000000000..e12fb9b63f31 --- /dev/null +++ b/drivers/input/touchscreen/surface3_spi.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * Driver for Ntrig/Microsoft Touchscreens over SPI | ||
3 | * | ||
4 | * Copyright (c) 2016 Red Hat Inc. | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; version 2 of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/gpio/consumer.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/input/mt.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | #include <linux/acpi.h> | ||
24 | |||
25 | #include <asm/unaligned.h> | ||
26 | |||
27 | #define SURFACE3_PACKET_SIZE 264 | ||
28 | |||
29 | #define SURFACE3_REPORT_TOUCH 0xd2 | ||
30 | #define SURFACE3_REPORT_PEN 0x16 | ||
31 | |||
32 | struct surface3_ts_data { | ||
33 | struct spi_device *spi; | ||
34 | struct gpio_desc *gpiod_rst[2]; | ||
35 | struct input_dev *input_dev; | ||
36 | struct input_dev *pen_input_dev; | ||
37 | int pen_tool; | ||
38 | |||
39 | u8 rd_buf[SURFACE3_PACKET_SIZE] ____cacheline_aligned; | ||
40 | }; | ||
41 | |||
42 | struct surface3_ts_data_finger { | ||
43 | u8 status; | ||
44 | __le16 tracking_id; | ||
45 | __le16 x; | ||
46 | __le16 cx; | ||
47 | __le16 y; | ||
48 | __le16 cy; | ||
49 | __le16 width; | ||
50 | __le16 height; | ||
51 | u32 padding; | ||
52 | } __packed; | ||
53 | |||
54 | struct surface3_ts_data_pen { | ||
55 | u8 status; | ||
56 | __le16 x; | ||
57 | __le16 y; | ||
58 | __le16 pressure; | ||
59 | u8 padding; | ||
60 | } __packed; | ||
61 | |||
62 | static int surface3_spi_read(struct surface3_ts_data *ts_data) | ||
63 | { | ||
64 | struct spi_device *spi = ts_data->spi; | ||
65 | |||
66 | memset(ts_data->rd_buf, 0, sizeof(ts_data->rd_buf)); | ||
67 | return spi_read(spi, ts_data->rd_buf, sizeof(ts_data->rd_buf)); | ||
68 | } | ||
69 | |||
70 | static void surface3_spi_report_touch(struct surface3_ts_data *ts_data, | ||
71 | struct surface3_ts_data_finger *finger) | ||
72 | { | ||
73 | int st = finger->status & 0x01; | ||
74 | int slot; | ||
75 | |||
76 | slot = input_mt_get_slot_by_key(ts_data->input_dev, | ||
77 | get_unaligned_le16(&finger->tracking_id)); | ||
78 | if (slot < 0) | ||
79 | return; | ||
80 | |||
81 | input_mt_slot(ts_data->input_dev, slot); | ||
82 | input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, st); | ||
83 | if (st) { | ||
84 | input_report_abs(ts_data->input_dev, | ||
85 | ABS_MT_POSITION_X, | ||
86 | get_unaligned_le16(&finger->x)); | ||
87 | input_report_abs(ts_data->input_dev, | ||
88 | ABS_MT_POSITION_Y, | ||
89 | get_unaligned_le16(&finger->y)); | ||
90 | input_report_abs(ts_data->input_dev, | ||
91 | ABS_MT_WIDTH_MAJOR, | ||
92 | get_unaligned_le16(&finger->width)); | ||
93 | input_report_abs(ts_data->input_dev, | ||
94 | ABS_MT_WIDTH_MINOR, | ||
95 | get_unaligned_le16(&finger->height)); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data) | ||
100 | { | ||
101 | u16 timestamp; | ||
102 | unsigned int i; | ||
103 | timestamp = get_unaligned_le16(&data[15]); | ||
104 | |||
105 | for (i = 0; i < 13; i++) { | ||
106 | struct surface3_ts_data_finger *finger; | ||
107 | |||
108 | finger = (struct surface3_ts_data_finger *)&data[17 + | ||
109 | i * sizeof(struct surface3_ts_data_finger)]; | ||
110 | |||
111 | /* | ||
112 | * When bit 5 of status is 1, it marks the end of the report: | ||
113 | * - touch present: 0xe7 | ||
114 | * - touch released: 0xe4 | ||
115 | * - nothing valuable: 0xff | ||
116 | */ | ||
117 | if (finger->status & 0x10) | ||
118 | break; | ||
119 | |||
120 | surface3_spi_report_touch(ts_data, finger); | ||
121 | } | ||
122 | |||
123 | input_mt_sync_frame(ts_data->input_dev); | ||
124 | input_sync(ts_data->input_dev); | ||
125 | } | ||
126 | |||
127 | static void surface3_spi_report_pen(struct surface3_ts_data *ts_data, | ||
128 | struct surface3_ts_data_pen *pen) | ||
129 | { | ||
130 | struct input_dev *dev = ts_data->pen_input_dev; | ||
131 | int st = pen->status; | ||
132 | int prox = st & 0x01; | ||
133 | int rubber = st & 0x18; | ||
134 | int tool = (prox && rubber) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
135 | |||
136 | /* fake proximity out to switch tools */ | ||
137 | if (ts_data->pen_tool != tool) { | ||
138 | input_report_key(dev, ts_data->pen_tool, 0); | ||
139 | input_sync(dev); | ||
140 | ts_data->pen_tool = tool; | ||
141 | } | ||
142 | |||
143 | input_report_key(dev, BTN_TOUCH, st & 0x12); | ||
144 | |||
145 | input_report_key(dev, ts_data->pen_tool, prox); | ||
146 | |||
147 | if (st) { | ||
148 | input_report_key(dev, | ||
149 | BTN_STYLUS, | ||
150 | st & 0x04); | ||
151 | |||
152 | input_report_abs(dev, | ||
153 | ABS_X, | ||
154 | get_unaligned_le16(&pen->x)); | ||
155 | input_report_abs(dev, | ||
156 | ABS_Y, | ||
157 | get_unaligned_le16(&pen->y)); | ||
158 | input_report_abs(dev, | ||
159 | ABS_PRESSURE, | ||
160 | get_unaligned_le16(&pen->pressure)); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | static void surface3_spi_process_pen(struct surface3_ts_data *ts_data, u8 *data) | ||
165 | { | ||
166 | struct surface3_ts_data_pen *pen; | ||
167 | |||
168 | pen = (struct surface3_ts_data_pen *)&data[15]; | ||
169 | |||
170 | surface3_spi_report_pen(ts_data, pen); | ||
171 | input_sync(ts_data->pen_input_dev); | ||
172 | } | ||
173 | |||
174 | static void surface3_spi_process(struct surface3_ts_data *ts_data) | ||
175 | { | ||
176 | const char header[] = { | ||
177 | 0xff, 0xff, 0xff, 0xff, 0xa5, 0x5a, 0xe7, 0x7e, 0x01 | ||
178 | }; | ||
179 | u8 *data = ts_data->rd_buf; | ||
180 | |||
181 | if (memcmp(header, data, sizeof(header))) | ||
182 | dev_err(&ts_data->spi->dev, | ||
183 | "%s header error: %*ph, ignoring...\n", | ||
184 | __func__, (int)sizeof(header), data); | ||
185 | |||
186 | switch (data[9]) { | ||
187 | case SURFACE3_REPORT_TOUCH: | ||
188 | surface3_spi_process_touch(ts_data, data); | ||
189 | break; | ||
190 | case SURFACE3_REPORT_PEN: | ||
191 | surface3_spi_process_pen(ts_data, data); | ||
192 | break; | ||
193 | default: | ||
194 | dev_err(&ts_data->spi->dev, | ||
195 | "%s unknown packet type: %x, ignoring...\n", | ||
196 | __func__, data[9]); | ||
197 | break; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static irqreturn_t surface3_spi_irq_handler(int irq, void *dev_id) | ||
202 | { | ||
203 | struct surface3_ts_data *data = dev_id; | ||
204 | |||
205 | if (surface3_spi_read(data)) | ||
206 | return IRQ_HANDLED; | ||
207 | |||
208 | dev_dbg(&data->spi->dev, "%s received -> %*ph\n", | ||
209 | __func__, SURFACE3_PACKET_SIZE, data->rd_buf); | ||
210 | surface3_spi_process(data); | ||
211 | |||
212 | return IRQ_HANDLED; | ||
213 | } | ||
214 | |||
215 | static void surface3_spi_power(struct surface3_ts_data *data, bool on) | ||
216 | { | ||
217 | gpiod_set_value(data->gpiod_rst[0], on); | ||
218 | gpiod_set_value(data->gpiod_rst[1], on); | ||
219 | /* let the device settle a little */ | ||
220 | msleep(20); | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * surface3_spi_get_gpio_config - Get GPIO config from ACPI/DT | ||
225 | * | ||
226 | * @ts: surface3_spi_ts_data pointer | ||
227 | */ | ||
228 | static int surface3_spi_get_gpio_config(struct surface3_ts_data *data) | ||
229 | { | ||
230 | int error; | ||
231 | struct device *dev; | ||
232 | struct gpio_desc *gpiod; | ||
233 | int i; | ||
234 | |||
235 | dev = &data->spi->dev; | ||
236 | |||
237 | /* Get the reset lines GPIO pin number */ | ||
238 | for (i = 0; i < 2; i++) { | ||
239 | gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_OUT_LOW); | ||
240 | if (IS_ERR(gpiod)) { | ||
241 | error = PTR_ERR(gpiod); | ||
242 | if (error != -EPROBE_DEFER) | ||
243 | dev_err(dev, | ||
244 | "Failed to get power GPIO %d: %d\n", | ||
245 | i, | ||
246 | error); | ||
247 | return error; | ||
248 | } | ||
249 | |||
250 | data->gpiod_rst[i] = gpiod; | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static int surface3_spi_create_touch_input(struct surface3_ts_data *data) | ||
257 | { | ||
258 | struct input_dev *input; | ||
259 | int error; | ||
260 | |||
261 | input = devm_input_allocate_device(&data->spi->dev); | ||
262 | if (!input) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | data->input_dev = input; | ||
266 | |||
267 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, 9600, 0, 0); | ||
268 | input_abs_set_res(input, ABS_MT_POSITION_X, 40); | ||
269 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 7200, 0, 0); | ||
270 | input_abs_set_res(input, ABS_MT_POSITION_Y, 48); | ||
271 | input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 1024, 0, 0); | ||
272 | input_set_abs_params(input, ABS_MT_WIDTH_MINOR, 0, 1024, 0, 0); | ||
273 | input_mt_init_slots(input, 10, INPUT_MT_DIRECT); | ||
274 | |||
275 | input->name = "Surface3 SPI Capacitive TouchScreen"; | ||
276 | input->phys = "input/ts"; | ||
277 | input->id.bustype = BUS_SPI; | ||
278 | input->id.vendor = 0x045e; /* Microsoft */ | ||
279 | input->id.product = 0x0001; | ||
280 | input->id.version = 0x0000; | ||
281 | |||
282 | error = input_register_device(input); | ||
283 | if (error) { | ||
284 | dev_err(&data->spi->dev, | ||
285 | "Failed to register input device: %d", error); | ||
286 | return error; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int surface3_spi_create_pen_input(struct surface3_ts_data *data) | ||
293 | { | ||
294 | struct input_dev *input; | ||
295 | int error; | ||
296 | |||
297 | input = devm_input_allocate_device(&data->spi->dev); | ||
298 | if (!input) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | data->pen_input_dev = input; | ||
302 | data->pen_tool = BTN_TOOL_PEN; | ||
303 | |||
304 | __set_bit(INPUT_PROP_DIRECT, input->propbit); | ||
305 | __set_bit(INPUT_PROP_POINTER, input->propbit); | ||
306 | input_set_abs_params(input, ABS_X, 0, 9600, 0, 0); | ||
307 | input_abs_set_res(input, ABS_X, 40); | ||
308 | input_set_abs_params(input, ABS_Y, 0, 7200, 0, 0); | ||
309 | input_abs_set_res(input, ABS_Y, 48); | ||
310 | input_set_abs_params(input, ABS_PRESSURE, 0, 1024, 0, 0); | ||
311 | input_set_capability(input, EV_KEY, BTN_TOUCH); | ||
312 | input_set_capability(input, EV_KEY, BTN_STYLUS); | ||
313 | input_set_capability(input, EV_KEY, BTN_TOOL_PEN); | ||
314 | input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER); | ||
315 | |||
316 | input->name = "Surface3 SPI Pen Input"; | ||
317 | input->phys = "input/ts"; | ||
318 | input->id.bustype = BUS_SPI; | ||
319 | input->id.vendor = 0x045e; /* Microsoft */ | ||
320 | input->id.product = 0x0002; | ||
321 | input->id.version = 0x0000; | ||
322 | |||
323 | error = input_register_device(input); | ||
324 | if (error) { | ||
325 | dev_err(&data->spi->dev, | ||
326 | "Failed to register input device: %d", error); | ||
327 | return error; | ||
328 | } | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int surface3_spi_probe(struct spi_device *spi) | ||
334 | { | ||
335 | struct surface3_ts_data *data; | ||
336 | int error; | ||
337 | |||
338 | /* Set up SPI*/ | ||
339 | spi->bits_per_word = 8; | ||
340 | spi->mode = SPI_MODE_0; | ||
341 | error = spi_setup(spi); | ||
342 | if (error) | ||
343 | return error; | ||
344 | |||
345 | data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL); | ||
346 | if (!data) | ||
347 | return -ENOMEM; | ||
348 | |||
349 | data->spi = spi; | ||
350 | spi_set_drvdata(spi, data); | ||
351 | |||
352 | error = surface3_spi_get_gpio_config(data); | ||
353 | if (error) | ||
354 | return error; | ||
355 | |||
356 | surface3_spi_power(data, true); | ||
357 | surface3_spi_power(data, false); | ||
358 | surface3_spi_power(data, true); | ||
359 | |||
360 | error = surface3_spi_create_touch_input(data); | ||
361 | if (error) | ||
362 | return error; | ||
363 | |||
364 | error = surface3_spi_create_pen_input(data); | ||
365 | if (error) | ||
366 | return error; | ||
367 | |||
368 | error = devm_request_threaded_irq(&spi->dev, spi->irq, | ||
369 | NULL, surface3_spi_irq_handler, | ||
370 | IRQF_ONESHOT, | ||
371 | "Surface3-irq", data); | ||
372 | if (error) | ||
373 | return error; | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int __maybe_unused surface3_spi_suspend(struct device *dev) | ||
379 | { | ||
380 | struct spi_device *spi = to_spi_device(dev); | ||
381 | struct surface3_ts_data *data = spi_get_drvdata(spi); | ||
382 | |||
383 | disable_irq(data->spi->irq); | ||
384 | |||
385 | surface3_spi_power(data, false); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int __maybe_unused surface3_spi_resume(struct device *dev) | ||
391 | { | ||
392 | struct spi_device *spi = to_spi_device(dev); | ||
393 | struct surface3_ts_data *data = spi_get_drvdata(spi); | ||
394 | |||
395 | surface3_spi_power(data, true); | ||
396 | |||
397 | enable_irq(data->spi->irq); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static SIMPLE_DEV_PM_OPS(surface3_spi_pm_ops, | ||
403 | surface3_spi_suspend, | ||
404 | surface3_spi_resume); | ||
405 | |||
406 | #ifdef CONFIG_ACPI | ||
407 | static const struct acpi_device_id surface3_spi_acpi_match[] = { | ||
408 | { "MSHW0037", 0 }, | ||
409 | { } | ||
410 | }; | ||
411 | MODULE_DEVICE_TABLE(acpi, surface3_spi_acpi_match); | ||
412 | #endif | ||
413 | |||
414 | static struct spi_driver surface3_spi_driver = { | ||
415 | .driver = { | ||
416 | .name = "Surface3-spi", | ||
417 | .acpi_match_table = ACPI_PTR(surface3_spi_acpi_match), | ||
418 | .pm = &surface3_spi_pm_ops, | ||
419 | }, | ||
420 | .probe = surface3_spi_probe, | ||
421 | }; | ||
422 | |||
423 | module_spi_driver(surface3_spi_driver); | ||
424 | |||
425 | MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); | ||
426 | MODULE_DESCRIPTION("Surface 3 SPI touchscreen driver"); | ||
427 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 8b3f15ca7725..7953381d939a 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c | |||
@@ -406,7 +406,7 @@ static int titsc_probe(struct platform_device *pdev) | |||
406 | int err; | 406 | int err; |
407 | 407 | ||
408 | /* Allocate memory for device */ | 408 | /* Allocate memory for device */ |
409 | ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); | 409 | ts_dev = kzalloc(sizeof(*ts_dev), GFP_KERNEL); |
410 | input_dev = input_allocate_device(); | 410 | input_dev = input_allocate_device(); |
411 | if (!ts_dev || !input_dev) { | 411 | if (!ts_dev || !input_dev) { |
412 | dev_err(&pdev->dev, "failed to allocate memory.\n"); | 412 | dev_err(&pdev->dev, "failed to allocate memory.\n"); |
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c index dfa7f1c4f545..b7059ed8872e 100644 --- a/drivers/input/touchscreen/tsc200x-core.c +++ b/drivers/input/touchscreen/tsc200x-core.c | |||
@@ -568,7 +568,7 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, | |||
568 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); | 568 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); |
569 | 569 | ||
570 | if (np) | 570 | if (np) |
571 | touchscreen_parse_properties(input_dev, false); | 571 | touchscreen_parse_properties(input_dev, false, NULL); |
572 | 572 | ||
573 | input_dev->open = tsc200x_open; | 573 | input_dev->open = tsc200x_open; |
574 | input_dev->close = tsc200x_close; | 574 | input_dev->close = tsc200x_close; |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index b6fc4bde79de..85e95725d0df 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -518,13 +518,21 @@ static int w8001_setup_touch(struct w8001 *w8001, char *basename, | |||
518 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; | 518 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; |
519 | 519 | ||
520 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 520 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
521 | input_mt_init_slots(dev, 2, 0); | 521 | error = input_mt_init_slots(dev, 2, 0); |
522 | if (error) { | ||
523 | dev_err(&w8001->serio->dev, | ||
524 | "failed to initialize MT slots: %d\n", error); | ||
525 | return error; | ||
526 | } | ||
527 | |||
522 | input_set_abs_params(dev, ABS_MT_POSITION_X, | 528 | input_set_abs_params(dev, ABS_MT_POSITION_X, |
523 | 0, touch.x, 0, 0); | 529 | 0, touch.x, 0, 0); |
524 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | 530 | input_set_abs_params(dev, ABS_MT_POSITION_Y, |
525 | 0, touch.y, 0, 0); | 531 | 0, touch.y, 0, 0); |
526 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, | 532 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, |
527 | 0, MT_TOOL_MAX, 0, 0); | 533 | 0, MT_TOOL_MAX, 0, 0); |
534 | input_abs_set_res(dev, ABS_MT_POSITION_X, touch.panel_res); | ||
535 | input_abs_set_res(dev, ABS_MT_POSITION_Y, touch.panel_res); | ||
528 | 536 | ||
529 | strlcat(basename, " 2FG", basename_sz); | 537 | strlcat(basename, " 2FG", basename_sz); |
530 | if (w8001->max_pen_x && w8001->max_pen_y) | 538 | if (w8001->max_pen_x && w8001->max_pen_y) |