hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/input/touchscreen/edt-ft5x06.c
....@@ -1,20 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
34 * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support)
45 * Lothar Waßmann <LW@KARO-electronics.de> (DT support)
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
- * 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
186 */
197
208 /*
....@@ -25,20 +13,23 @@
2513 * http://www.glyn.com/Products/Displays
2614 */
2715
28
-#include <linux/module.h>
29
-#include <linux/ratelimit.h>
30
-#include <linux/irq.h>
16
+#include <linux/debugfs.h>
17
+#include <linux/delay.h>
18
+#include <linux/gpio/consumer.h>
19
+#include <linux/i2c.h>
3120 #include <linux/interrupt.h>
3221 #include <linux/input.h>
33
-#include <linux/i2c.h>
34
-#include <linux/uaccess.h>
35
-#include <linux/delay.h>
36
-#include <linux/debugfs.h>
37
-#include <linux/slab.h>
38
-#include <linux/gpio/consumer.h>
3922 #include <linux/input/mt.h>
4023 #include <linux/input/touchscreen.h>
41
-#include <linux/of_device.h>
24
+#include <linux/irq.h>
25
+#include <linux/kernel.h>
26
+#include <linux/module.h>
27
+#include <linux/ratelimit.h>
28
+#include <linux/regulator/consumer.h>
29
+#include <linux/slab.h>
30
+#include <linux/uaccess.h>
31
+
32
+#include <asm/unaligned.h>
4233
4334 #define WORK_REGISTER_THRESHOLD 0x00
4435 #define WORK_REGISTER_REPORT_RATE 0x08
....@@ -47,16 +38,25 @@
4738 #define WORK_REGISTER_NUM_X 0x33
4839 #define WORK_REGISTER_NUM_Y 0x34
4940
41
+#define PMOD_REGISTER_ACTIVE 0x00
42
+#define PMOD_REGISTER_HIBERNATE 0x03
43
+
5044 #define M09_REGISTER_THRESHOLD 0x80
5145 #define M09_REGISTER_GAIN 0x92
5246 #define M09_REGISTER_OFFSET 0x93
5347 #define M09_REGISTER_NUM_X 0x94
5448 #define M09_REGISTER_NUM_Y 0x95
5549
50
+#define EV_REGISTER_THRESHOLD 0x40
51
+#define EV_REGISTER_GAIN 0x41
52
+#define EV_REGISTER_OFFSET_Y 0x45
53
+#define EV_REGISTER_OFFSET_X 0x46
54
+
5655 #define NO_REGISTER 0xff
5756
5857 #define WORK_REGISTER_OPMODE 0x3c
5958 #define FACTORY_REGISTER_OPMODE 0x01
59
+#define PMOD_REGISTER_OPMODE 0xa5
6060
6161 #define TOUCH_EVENT_DOWN 0x00
6262 #define TOUCH_EVENT_UP 0x01
....@@ -69,10 +69,17 @@
6969 #define EDT_RAW_DATA_RETRIES 100
7070 #define EDT_RAW_DATA_DELAY 1000 /* usec */
7171
72
+enum edt_pmode {
73
+ EDT_PMODE_NOT_SUPPORTED,
74
+ EDT_PMODE_HIBERNATE,
75
+ EDT_PMODE_POWEROFF,
76
+};
77
+
7278 enum edt_ver {
7379 EDT_M06,
7480 EDT_M09,
7581 EDT_M12,
82
+ EV_FT,
7683 GENERIC_FT,
7784 };
7885
....@@ -81,6 +88,8 @@
8188 int reg_report_rate;
8289 int reg_gain;
8390 int reg_offset;
91
+ int reg_offset_x;
92
+ int reg_offset_y;
8493 int reg_num_x;
8594 int reg_num_y;
8695 };
....@@ -91,6 +100,7 @@
91100 struct touchscreen_properties prop;
92101 u16 num_x;
93102 u16 num_y;
103
+ struct regulator *vcc;
94104
95105 struct gpio_desc *reset_gpio;
96106 struct gpio_desc *wake_gpio;
....@@ -103,9 +113,12 @@
103113
104114 struct mutex mutex;
105115 bool factory_mode;
116
+ enum edt_pmode suspend_mode;
106117 int threshold;
107118 int gain;
108119 int offset;
120
+ int offset_x;
121
+ int offset_y;
109122 int report_rate;
110123 int max_support_points;
111124
....@@ -190,6 +203,7 @@
190203
191204 case EDT_M09:
192205 case EDT_M12:
206
+ case EV_FT:
193207 case GENERIC_FT:
194208 cmd = 0x0;
195209 offset = 3;
....@@ -229,7 +243,6 @@
229243
230244 for (i = 0; i < tsdata->max_support_points; i++) {
231245 u8 *buf = &rdbuf[i * tplen + offset];
232
- bool down;
233246
234247 type = buf[0] >> 6;
235248 /* ignore Reserved events */
....@@ -240,19 +253,19 @@
240253 if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN)
241254 continue;
242255
243
- x = ((buf[0] << 8) | buf[1]) & 0x0fff;
244
- y = ((buf[2] << 8) | buf[3]) & 0x0fff;
256
+ x = get_unaligned_be16(buf) & 0x0fff;
257
+ y = get_unaligned_be16(buf + 2) & 0x0fff;
258
+ /* The FT5x26 send the y coordinate first */
259
+ if (tsdata->version == EV_FT)
260
+ swap(x, y);
261
+
245262 id = (buf[2] >> 4) & 0x0f;
246
- down = type != TOUCH_EVENT_UP;
247263
248264 input_mt_slot(tsdata->input, id);
249
- input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down);
250
-
251
- if (!down)
252
- continue;
253
-
254
- touchscreen_report_pos(tsdata->input, &tsdata->prop, x, y,
255
- true);
265
+ if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER,
266
+ type != TOUCH_EVENT_UP))
267
+ touchscreen_report_pos(tsdata->input, &tsdata->prop,
268
+ x, y, true);
256269 }
257270
258271 input_mt_report_pointer_emulation(tsdata->input, true);
....@@ -275,8 +288,10 @@
275288 wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
276289 return edt_ft5x06_ts_readwrite(tsdata->client, 4,
277290 wrbuf, 0, NULL);
291
+
278292 case EDT_M09:
279293 case EDT_M12:
294
+ case EV_FT:
280295 case GENERIC_FT:
281296 wrbuf[0] = addr;
282297 wrbuf[1] = value;
....@@ -317,6 +332,7 @@
317332
318333 case EDT_M09:
319334 case EDT_M12:
335
+ case EV_FT:
320336 case GENERIC_FT:
321337 wrbuf[0] = addr;
322338 error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
....@@ -339,9 +355,10 @@
339355 u8 limit_high;
340356 u8 addr_m06;
341357 u8 addr_m09;
358
+ u8 addr_ev;
342359 };
343360
344
-#define EDT_ATTR(_field, _mode, _addr_m06, _addr_m09, \
361
+#define EDT_ATTR(_field, _mode, _addr_m06, _addr_m09, _addr_ev, \
345362 _limit_low, _limit_high) \
346363 struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \
347364 .dattr = __ATTR(_field, _mode, \
....@@ -350,6 +367,7 @@
350367 .field_offset = offsetof(struct edt_ft5x06_ts_data, _field), \
351368 .addr_m06 = _addr_m06, \
352369 .addr_m09 = _addr_m09, \
370
+ .addr_ev = _addr_ev, \
353371 .limit_low = _limit_low, \
354372 .limit_high = _limit_high, \
355373 }
....@@ -384,6 +402,10 @@
384402 case EDT_M12:
385403 case GENERIC_FT:
386404 addr = attr->addr_m09;
405
+ break;
406
+
407
+ case EV_FT:
408
+ addr = attr->addr_ev;
387409 break;
388410
389411 default:
....@@ -457,6 +479,10 @@
457479 addr = attr->addr_m09;
458480 break;
459481
482
+ case EV_FT:
483
+ addr = attr->addr_ev;
484
+ break;
485
+
460486 default:
461487 error = -ENODEV;
462488 goto out;
....@@ -480,20 +506,28 @@
480506
481507 /* m06, m09: range 0-31, m12: range 0-5 */
482508 static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
483
- M09_REGISTER_GAIN, 0, 31);
509
+ M09_REGISTER_GAIN, EV_REGISTER_GAIN, 0, 31);
484510 /* m06, m09: range 0-31, m12: range 0-16 */
485511 static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
486
- M09_REGISTER_OFFSET, 0, 31);
512
+ M09_REGISTER_OFFSET, NO_REGISTER, 0, 31);
513
+/* m06, m09, m12: no supported, ev_ft: range 0-80 */
514
+static EDT_ATTR(offset_x, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
515
+ EV_REGISTER_OFFSET_X, 0, 80);
516
+/* m06, m09, m12: no supported, ev_ft: range 0-80 */
517
+static EDT_ATTR(offset_y, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
518
+ EV_REGISTER_OFFSET_Y, 0, 80);
487519 /* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */
488520 static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
489
- M09_REGISTER_THRESHOLD, 0, 255);
521
+ M09_REGISTER_THRESHOLD, EV_REGISTER_THRESHOLD, 0, 255);
490522 /* m06: range 3 to 14, m12: (0x64: 100Hz) */
491523 static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
492
- NO_REGISTER, 0, 255);
524
+ NO_REGISTER, NO_REGISTER, 0, 255);
493525
494526 static struct attribute *edt_ft5x06_attrs[] = {
495527 &edt_ft5x06_attr_gain.dattr.attr,
496528 &edt_ft5x06_attr_offset.dattr.attr,
529
+ &edt_ft5x06_attr_offset_x.dattr.attr,
530
+ &edt_ft5x06_attr_offset_y.dattr.attr,
497531 &edt_ft5x06_attr_threshold.dattr.attr,
498532 &edt_ft5x06_attr_report_rate.dattr.attr,
499533 NULL
....@@ -502,6 +536,29 @@
502536 static const struct attribute_group edt_ft5x06_attr_group = {
503537 .attrs = edt_ft5x06_attrs,
504538 };
539
+
540
+static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
541
+{
542
+ struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
543
+
544
+ edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold,
545
+ tsdata->threshold);
546
+ edt_ft5x06_register_write(tsdata, reg_addr->reg_gain,
547
+ tsdata->gain);
548
+ if (reg_addr->reg_offset != NO_REGISTER)
549
+ edt_ft5x06_register_write(tsdata, reg_addr->reg_offset,
550
+ tsdata->offset);
551
+ if (reg_addr->reg_offset_x != NO_REGISTER)
552
+ edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x,
553
+ tsdata->offset_x);
554
+ if (reg_addr->reg_offset_y != NO_REGISTER)
555
+ edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y,
556
+ tsdata->offset_y);
557
+ if (reg_addr->reg_report_rate != NO_REGISTER)
558
+ edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
559
+ tsdata->report_rate);
560
+
561
+}
505562
506563 #ifdef CONFIG_DEBUG_FS
507564 static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
....@@ -568,7 +625,6 @@
568625 {
569626 struct i2c_client *client = tsdata->client;
570627 int retries = EDT_SWITCH_MODE_RETRIES;
571
- struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
572628 int ret;
573629 int error;
574630
....@@ -600,17 +656,7 @@
600656 kfree(tsdata->raw_buffer);
601657 tsdata->raw_buffer = NULL;
602658
603
- /* restore parameters */
604
- edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold,
605
- tsdata->threshold);
606
- edt_ft5x06_register_write(tsdata, reg_addr->reg_gain,
607
- tsdata->gain);
608
- edt_ft5x06_register_write(tsdata, reg_addr->reg_offset,
609
- tsdata->offset);
610
- if (reg_addr->reg_report_rate != NO_REGISTER)
611
- edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
612
- tsdata->report_rate);
613
-
659
+ edt_ft5x06_restore_reg_parameters(tsdata);
614660 enable_irq(client->irq);
615661
616662 return 0;
....@@ -731,13 +777,10 @@
731777 .read = edt_ft5x06_debugfs_raw_data_read,
732778 };
733779
734
-static void
735
-edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
736
- const char *debugfs_name)
780
+static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
781
+ const char *debugfs_name)
737782 {
738783 tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL);
739
- if (!tsdata->debug_dir)
740
- return;
741784
742785 debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x);
743786 debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y);
....@@ -748,8 +791,7 @@
748791 tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
749792 }
750793
751
-static void
752
-edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
794
+static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
753795 {
754796 debugfs_remove_recursive(tsdata->debug_dir);
755797 kfree(tsdata->raw_buffer);
....@@ -757,14 +799,17 @@
757799
758800 #else
759801
760
-static inline void
761
-edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
762
- const char *debugfs_name)
802
+static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
803
+{
804
+ return -ENOSYS;
805
+}
806
+
807
+static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
808
+ const char *debugfs_name)
763809 {
764810 }
765811
766
-static inline void
767
-edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
812
+static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
768813 {
769814 }
770815
....@@ -867,6 +912,16 @@
867912 case 0x5a: /* Solomon Goldentek Display */
868913 snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
869914 break;
915
+ case 0x59: /* Evervision Display with FT5xx6 TS */
916
+ tsdata->version = EV_FT;
917
+ error = edt_ft5x06_ts_readwrite(client, 1, "\x53",
918
+ 1, rdbuf);
919
+ if (error)
920
+ return error;
921
+ strlcpy(fw_version, rdbuf, 1);
922
+ snprintf(model_name, EDT_NAME_LEN,
923
+ "EVERVISION-FT5726NEi");
924
+ break;
870925 default:
871926 snprintf(model_name, EDT_NAME_LEN,
872927 "generic ft5x06 (%02x)",
....@@ -899,8 +954,26 @@
899954
900955 error = device_property_read_u32(dev, "offset", &val);
901956 if (!error) {
902
- edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, val);
957
+ if (reg_addr->reg_offset != NO_REGISTER)
958
+ edt_ft5x06_register_write(tsdata,
959
+ reg_addr->reg_offset, val);
903960 tsdata->offset = val;
961
+ }
962
+
963
+ error = device_property_read_u32(dev, "offset-x", &val);
964
+ if (!error) {
965
+ if (reg_addr->reg_offset_x != NO_REGISTER)
966
+ edt_ft5x06_register_write(tsdata,
967
+ reg_addr->reg_offset_x, val);
968
+ tsdata->offset_x = val;
969
+ }
970
+
971
+ error = device_property_read_u32(dev, "offset-y", &val);
972
+ if (!error) {
973
+ if (reg_addr->reg_offset_y != NO_REGISTER)
974
+ edt_ft5x06_register_write(tsdata,
975
+ reg_addr->reg_offset_y, val);
976
+ tsdata->offset_y = val;
904977 }
905978 }
906979
....@@ -912,7 +985,15 @@
912985 tsdata->threshold = edt_ft5x06_register_read(tsdata,
913986 reg_addr->reg_threshold);
914987 tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain);
915
- tsdata->offset = edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
988
+ if (reg_addr->reg_offset != NO_REGISTER)
989
+ tsdata->offset =
990
+ edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
991
+ if (reg_addr->reg_offset_x != NO_REGISTER)
992
+ tsdata->offset_x = edt_ft5x06_register_read(tsdata,
993
+ reg_addr->reg_offset_x);
994
+ if (reg_addr->reg_offset_y != NO_REGISTER)
995
+ tsdata->offset_y = edt_ft5x06_register_read(tsdata,
996
+ reg_addr->reg_offset_y);
916997 if (reg_addr->reg_report_rate != NO_REGISTER)
917998 tsdata->report_rate = edt_ft5x06_register_read(tsdata,
918999 reg_addr->reg_report_rate);
....@@ -940,6 +1021,8 @@
9401021 reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE;
9411022 reg_addr->reg_gain = WORK_REGISTER_GAIN;
9421023 reg_addr->reg_offset = WORK_REGISTER_OFFSET;
1024
+ reg_addr->reg_offset_x = NO_REGISTER;
1025
+ reg_addr->reg_offset_y = NO_REGISTER;
9431026 reg_addr->reg_num_x = WORK_REGISTER_NUM_X;
9441027 reg_addr->reg_num_y = WORK_REGISTER_NUM_Y;
9451028 break;
....@@ -950,8 +1033,21 @@
9501033 reg_addr->reg_report_rate = NO_REGISTER;
9511034 reg_addr->reg_gain = M09_REGISTER_GAIN;
9521035 reg_addr->reg_offset = M09_REGISTER_OFFSET;
1036
+ reg_addr->reg_offset_x = NO_REGISTER;
1037
+ reg_addr->reg_offset_y = NO_REGISTER;
9531038 reg_addr->reg_num_x = M09_REGISTER_NUM_X;
9541039 reg_addr->reg_num_y = M09_REGISTER_NUM_Y;
1040
+ break;
1041
+
1042
+ case EV_FT:
1043
+ reg_addr->reg_threshold = EV_REGISTER_THRESHOLD;
1044
+ reg_addr->reg_gain = EV_REGISTER_GAIN;
1045
+ reg_addr->reg_offset = NO_REGISTER;
1046
+ reg_addr->reg_offset_x = EV_REGISTER_OFFSET_X;
1047
+ reg_addr->reg_offset_y = EV_REGISTER_OFFSET_Y;
1048
+ reg_addr->reg_num_x = NO_REGISTER;
1049
+ reg_addr->reg_num_y = NO_REGISTER;
1050
+ reg_addr->reg_report_rate = NO_REGISTER;
9551051 break;
9561052
9571053 case GENERIC_FT:
....@@ -959,8 +1055,17 @@
9591055 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
9601056 reg_addr->reg_gain = M09_REGISTER_GAIN;
9611057 reg_addr->reg_offset = M09_REGISTER_OFFSET;
1058
+ reg_addr->reg_offset_x = NO_REGISTER;
1059
+ reg_addr->reg_offset_y = NO_REGISTER;
9621060 break;
9631061 }
1062
+}
1063
+
1064
+static void edt_ft5x06_disable_regulator(void *arg)
1065
+{
1066
+ struct edt_ft5x06_ts_data *data = arg;
1067
+
1068
+ regulator_disable(data->vcc);
9641069 }
9651070
9661071 static int edt_ft5x06_ts_probe(struct i2c_client *client,
....@@ -982,7 +1087,7 @@
9821087 return -ENOMEM;
9831088 }
9841089
985
- chip_data = of_device_get_match_data(&client->dev);
1090
+ chip_data = device_get_match_data(&client->dev);
9861091 if (!chip_data)
9871092 chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
9881093 if (!chip_data || !chip_data->max_support_points) {
....@@ -991,6 +1096,27 @@
9911096 }
9921097
9931098 tsdata->max_support_points = chip_data->max_support_points;
1099
+
1100
+ tsdata->vcc = devm_regulator_get(&client->dev, "vcc");
1101
+ if (IS_ERR(tsdata->vcc)) {
1102
+ error = PTR_ERR(tsdata->vcc);
1103
+ if (error != -EPROBE_DEFER)
1104
+ dev_err(&client->dev,
1105
+ "failed to request regulator: %d\n", error);
1106
+ return error;
1107
+ }
1108
+
1109
+ error = regulator_enable(tsdata->vcc);
1110
+ if (error < 0) {
1111
+ dev_err(&client->dev, "failed to enable vcc: %d\n", error);
1112
+ return error;
1113
+ }
1114
+
1115
+ error = devm_add_action_or_reset(&client->dev,
1116
+ edt_ft5x06_disable_regulator,
1117
+ tsdata);
1118
+ if (error)
1119
+ return error;
9941120
9951121 tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
9961122 "reset", GPIOD_OUT_HIGH);
....@@ -1009,6 +1135,19 @@
10091135 "Failed to request GPIO wake pin, error %d\n", error);
10101136 return error;
10111137 }
1138
+
1139
+ /*
1140
+ * Check which sleep modes we can support. Power-off requieres the
1141
+ * reset-pin to ensure correct power-down/power-up behaviour. Start with
1142
+ * the EDT_PMODE_POWEROFF test since this is the deepest possible sleep
1143
+ * mode.
1144
+ */
1145
+ if (tsdata->reset_gpio)
1146
+ tsdata->suspend_mode = EDT_PMODE_POWEROFF;
1147
+ else if (tsdata->wake_gpio)
1148
+ tsdata->suspend_mode = EDT_PMODE_HIBERNATE;
1149
+ else
1150
+ tsdata->suspend_mode = EDT_PMODE_NOT_SUPPORTED;
10121151
10131152 if (tsdata->wake_gpio) {
10141153 usleep_range(5000, 6000);
....@@ -1104,7 +1243,6 @@
11041243 return error;
11051244
11061245 edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
1107
- device_init_wakeup(&client->dev, 1);
11081246
11091247 dev_dbg(&client->dev,
11101248 "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n",
....@@ -1127,9 +1265,39 @@
11271265 static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
11281266 {
11291267 struct i2c_client *client = to_i2c_client(dev);
1268
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
1269
+ struct gpio_desc *reset_gpio = tsdata->reset_gpio;
1270
+ int ret;
11301271
11311272 if (device_may_wakeup(dev))
1132
- enable_irq_wake(client->irq);
1273
+ return 0;
1274
+
1275
+ if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED)
1276
+ return 0;
1277
+
1278
+ /* Enter hibernate mode. */
1279
+ ret = edt_ft5x06_register_write(tsdata, PMOD_REGISTER_OPMODE,
1280
+ PMOD_REGISTER_HIBERNATE);
1281
+ if (ret)
1282
+ dev_warn(dev, "Failed to set hibernate mode\n");
1283
+
1284
+ if (tsdata->suspend_mode == EDT_PMODE_HIBERNATE)
1285
+ return 0;
1286
+
1287
+ /*
1288
+ * Power-off according the datasheet. Cut the power may leaf the irq
1289
+ * line in an undefined state depending on the host pull resistor
1290
+ * settings. Disable the irq to avoid adjusting each host till the
1291
+ * device is back in a full functional state.
1292
+ */
1293
+ disable_irq(tsdata->client->irq);
1294
+
1295
+ gpiod_set_value_cansleep(reset_gpio, 1);
1296
+ usleep_range(1000, 2000);
1297
+
1298
+ ret = regulator_disable(tsdata->vcc);
1299
+ if (ret)
1300
+ dev_warn(dev, "Failed to disable vcc\n");
11331301
11341302 return 0;
11351303 }
....@@ -1137,11 +1305,54 @@
11371305 static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
11381306 {
11391307 struct i2c_client *client = to_i2c_client(dev);
1308
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
1309
+ int ret = 0;
11401310
11411311 if (device_may_wakeup(dev))
1142
- disable_irq_wake(client->irq);
1312
+ return 0;
11431313
1144
- return 0;
1314
+ if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED)
1315
+ return 0;
1316
+
1317
+ if (tsdata->suspend_mode == EDT_PMODE_POWEROFF) {
1318
+ struct gpio_desc *reset_gpio = tsdata->reset_gpio;
1319
+
1320
+ /*
1321
+ * We can't check if the regulator is a dummy or a real
1322
+ * regulator. So we need to specify the 5ms reset time (T_rst)
1323
+ * here instead of the 100us T_rtp time. We also need to wait
1324
+ * 300ms in case it was a real supply and the power was cutted
1325
+ * of. Toggle the reset pin is also a way to exit the hibernate
1326
+ * mode.
1327
+ */
1328
+ gpiod_set_value_cansleep(reset_gpio, 1);
1329
+ usleep_range(5000, 6000);
1330
+
1331
+ ret = regulator_enable(tsdata->vcc);
1332
+ if (ret) {
1333
+ dev_err(dev, "Failed to enable vcc\n");
1334
+ return ret;
1335
+ }
1336
+
1337
+ usleep_range(1000, 2000);
1338
+ gpiod_set_value_cansleep(reset_gpio, 0);
1339
+ msleep(300);
1340
+
1341
+ edt_ft5x06_restore_reg_parameters(tsdata);
1342
+ enable_irq(tsdata->client->irq);
1343
+
1344
+ if (tsdata->factory_mode)
1345
+ ret = edt_ft5x06_factory_mode(tsdata);
1346
+ } else {
1347
+ struct gpio_desc *wake_gpio = tsdata->wake_gpio;
1348
+
1349
+ gpiod_set_value_cansleep(wake_gpio, 0);
1350
+ usleep_range(5000, 6000);
1351
+ gpiod_set_value_cansleep(wake_gpio, 1);
1352
+ }
1353
+
1354
+
1355
+ return ret;
11451356 }
11461357
11471358 static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
....@@ -1162,30 +1373,31 @@
11621373 static const struct i2c_device_id edt_ft5x06_ts_id[] = {
11631374 { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
11641375 { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
1376
+ { .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data },
11651377 /* Note no edt- prefix for compatibility with the ft6236.c driver */
11661378 { .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
11671379 { /* sentinel */ }
11681380 };
11691381 MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
11701382
1171
-#ifdef CONFIG_OF
11721383 static const struct of_device_id edt_ft5x06_of_match[] = {
11731384 { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data },
11741385 { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
11751386 { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
11761387 { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
1388
+ { .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data },
11771389 /* Note focaltech vendor prefix for compatibility with ft6236.c */
11781390 { .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
11791391 { /* sentinel */ }
11801392 };
11811393 MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
1182
-#endif
11831394
11841395 static struct i2c_driver edt_ft5x06_ts_driver = {
11851396 .driver = {
11861397 .name = "edt_ft5x06",
1187
- .of_match_table = of_match_ptr(edt_ft5x06_of_match),
1398
+ .of_match_table = edt_ft5x06_of_match,
11881399 .pm = &edt_ft5x06_ts_pm_ops,
1400
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
11891401 },
11901402 .id_table = edt_ft5x06_ts_id,
11911403 .probe = edt_ft5x06_ts_probe,
....@@ -1196,4 +1408,4 @@
11961408
11971409 MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>");
11981410 MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver");
1199
-MODULE_LICENSE("GPL");
1411
+MODULE_LICENSE("GPL v2");