forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/drivers/input/mouse/elantech.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Elantech Touchpad driver (v6)
34 *
45 * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms of the GNU General Public License version 2 as published
8
- * by the Free Software Foundation.
96 *
107 * Trademarks are the property of their respective owners.
118 */
....@@ -90,6 +87,47 @@
9087 psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command);
9188
9289 return rc;
90
+}
91
+
92
+/*
93
+ * Send an Elantech style special command to read 3 bytes from a register
94
+ */
95
+static int elantech_read_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
96
+{
97
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
98
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
99
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
100
+ elantech_ps2_command(psmouse, NULL, reg) ||
101
+ elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
102
+ psmouse_err(psmouse,
103
+ "failed to read register %#02x\n", reg);
104
+ return -EIO;
105
+ }
106
+
107
+ return 0;
108
+}
109
+
110
+/*
111
+ * Send an Elantech style special command to write a register with a parameter
112
+ */
113
+static int elantech_write_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
114
+{
115
+ if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
116
+ elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
117
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
118
+ elantech_ps2_command(psmouse, NULL, reg) ||
119
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
120
+ elantech_ps2_command(psmouse, NULL, param[0]) ||
121
+ elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
122
+ elantech_ps2_command(psmouse, NULL, param[1]) ||
123
+ elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
124
+ psmouse_err(psmouse,
125
+ "failed to write register %#02x with value %#02x%#02x\n",
126
+ reg, param[0], param[1]);
127
+ return -EIO;
128
+ }
129
+
130
+ return 0;
93131 }
94132
95133 /*
....@@ -230,6 +268,52 @@
230268 }
231269
232270 /*
271
+ * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in
272
+ * fw_version for this is based on the following fw_version & caps table:
273
+ *
274
+ * Laptop-model: fw_version: caps: buttons:
275
+ * Acer S3 0x461f00 10, 13, 0e clickpad
276
+ * Acer S7-392 0x581f01 50, 17, 0d clickpad
277
+ * Acer V5-131 0x461f02 01, 16, 0c clickpad
278
+ * Acer V5-551 0x461f00 ? clickpad
279
+ * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
280
+ * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
281
+ * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
282
+ * Asus TP500LN 0x381f17 10, 14, 0e clickpad
283
+ * Asus X750JN 0x381f17 10, 14, 0e clickpad
284
+ * Asus UX31 0x361f00 20, 15, 0e clickpad
285
+ * Asus UX32VD 0x361f02 00, 15, 0e clickpad
286
+ * Avatar AVIU-145A2 0x361f00 ? clickpad
287
+ * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**)
288
+ * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**)
289
+ * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
290
+ * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
291
+ * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
292
+ * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
293
+ * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons
294
+ * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
295
+ * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
296
+ * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
297
+ * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
298
+ * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*)
299
+ * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
300
+ * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
301
+ * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
302
+ * Samsung NP900X3E-A02 0x575f03 ? clickpad
303
+ * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad
304
+ * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons
305
+ * Samsung RF710 0x450f00 ? 2 hw buttons
306
+ * System76 Pangolin 0x250f01 ? 2 hw buttons
307
+ * (*) + 3 trackpoint buttons
308
+ * (**) + 0 trackpoint buttons
309
+ * Note: Lenovo L430 and Lenovo L530 have the same fw_version/caps
310
+ */
311
+static inline int elantech_is_buttonpad(struct elantech_device_info *info)
312
+{
313
+ return info->fw_version & 0x001000;
314
+}
315
+
316
+/*
233317 * Interpret complete data packets and report absolute mode input events for
234318 * hardware version 1. (4 byte packets)
235319 */
....@@ -340,7 +424,7 @@
340424 */
341425 if (packet[3] & 0x80)
342426 fingers = 4;
343
- /* fall through */
427
+ fallthrough;
344428 case 1:
345429 /*
346430 * byte 1: . . . . x11 x10 x9 x8
....@@ -539,7 +623,7 @@
539623 input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
540624
541625 /* For clickpads map both buttons to BTN_LEFT */
542
- if (etd->info.fw_version & 0x001000)
626
+ if (elantech_is_buttonpad(&etd->info))
543627 input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
544628 else
545629 psmouse_report_standard_buttons(dev, packet[0]);
....@@ -557,7 +641,7 @@
557641 unsigned char *packet = psmouse->packet;
558642
559643 /* For clickpads map both buttons to BTN_LEFT */
560
- if (etd->info.fw_version & 0x001000)
644
+ if (elantech_is_buttonpad(&etd->info))
561645 input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
562646 else
563647 psmouse_report_standard_buttons(dev, packet[0]);
....@@ -1007,88 +1091,6 @@
10071091 return rc;
10081092 }
10091093
1010
-static int elantech_set_range(struct psmouse *psmouse,
1011
- unsigned int *x_min, unsigned int *y_min,
1012
- unsigned int *x_max, unsigned int *y_max,
1013
- unsigned int *width)
1014
-{
1015
- struct elantech_data *etd = psmouse->private;
1016
- struct elantech_device_info *info = &etd->info;
1017
- unsigned char param[3];
1018
- unsigned char traces;
1019
-
1020
- switch (info->hw_version) {
1021
- case 1:
1022
- *x_min = ETP_XMIN_V1;
1023
- *y_min = ETP_YMIN_V1;
1024
- *x_max = ETP_XMAX_V1;
1025
- *y_max = ETP_YMAX_V1;
1026
- break;
1027
-
1028
- case 2:
1029
- if (info->fw_version == 0x020800 ||
1030
- info->fw_version == 0x020b00 ||
1031
- info->fw_version == 0x020030) {
1032
- *x_min = ETP_XMIN_V2;
1033
- *y_min = ETP_YMIN_V2;
1034
- *x_max = ETP_XMAX_V2;
1035
- *y_max = ETP_YMAX_V2;
1036
- } else {
1037
- int i;
1038
- int fixed_dpi;
1039
-
1040
- i = (info->fw_version > 0x020800 &&
1041
- info->fw_version < 0x020900) ? 1 : 2;
1042
-
1043
- if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1044
- return -1;
1045
-
1046
- fixed_dpi = param[1] & 0x10;
1047
-
1048
- if (((info->fw_version >> 16) == 0x14) && fixed_dpi) {
1049
- if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
1050
- return -1;
1051
-
1052
- *x_max = (info->capabilities[1] - i) * param[1] / 2;
1053
- *y_max = (info->capabilities[2] - i) * param[2] / 2;
1054
- } else if (info->fw_version == 0x040216) {
1055
- *x_max = 819;
1056
- *y_max = 405;
1057
- } else if (info->fw_version == 0x040219 || info->fw_version == 0x040215) {
1058
- *x_max = 900;
1059
- *y_max = 500;
1060
- } else {
1061
- *x_max = (info->capabilities[1] - i) * 64;
1062
- *y_max = (info->capabilities[2] - i) * 64;
1063
- }
1064
- }
1065
- break;
1066
-
1067
- case 3:
1068
- if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1069
- return -1;
1070
-
1071
- *x_max = (0x0f & param[0]) << 8 | param[1];
1072
- *y_max = (0xf0 & param[0]) << 4 | param[2];
1073
- break;
1074
-
1075
- case 4:
1076
- if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1077
- return -1;
1078
-
1079
- *x_max = (0x0f & param[0]) << 8 | param[1];
1080
- *y_max = (0xf0 & param[0]) << 4 | param[2];
1081
- traces = info->capabilities[1];
1082
- if ((traces < 2) || (traces > *x_max))
1083
- return -1;
1084
-
1085
- *width = *x_max / (traces - 1);
1086
- break;
1087
- }
1088
-
1089
- return 0;
1090
-}
1091
-
10921094 /*
10931095 * (value from firmware) * 10 + 790 = dpi
10941096 * we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
....@@ -1115,53 +1117,12 @@
11151117 return 0;
11161118 }
11171119
1118
-/*
1119
- * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in
1120
- * fw_version for this is based on the following fw_version & caps table:
1121
- *
1122
- * Laptop-model: fw_version: caps: buttons:
1123
- * Acer S3 0x461f00 10, 13, 0e clickpad
1124
- * Acer S7-392 0x581f01 50, 17, 0d clickpad
1125
- * Acer V5-131 0x461f02 01, 16, 0c clickpad
1126
- * Acer V5-551 0x461f00 ? clickpad
1127
- * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
1128
- * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
1129
- * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
1130
- * Asus TP500LN 0x381f17 10, 14, 0e clickpad
1131
- * Asus X750JN 0x381f17 10, 14, 0e clickpad
1132
- * Asus UX31 0x361f00 20, 15, 0e clickpad
1133
- * Asus UX32VD 0x361f02 00, 15, 0e clickpad
1134
- * Avatar AVIU-145A2 0x361f00 ? clickpad
1135
- * Fujitsu CELSIUS H760 0x570f02 40, 14, 0c 3 hw buttons (**)
1136
- * Fujitsu CELSIUS H780 0x5d0f02 41, 16, 0d 3 hw buttons (**)
1137
- * Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
1138
- * Fujitsu LIFEBOOK E546 0x470f00 50, 12, 09 2 hw buttons
1139
- * Fujitsu LIFEBOOK E547 0x470f00 50, 12, 09 2 hw buttons
1140
- * Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
1141
- * Fujitsu LIFEBOOK E557 0x570f01 40, 14, 0c 2 hw buttons
1142
- * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
1143
- * Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
1144
- * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
1145
- * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
1146
- * Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*)
1147
- * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
1148
- * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
1149
- * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
1150
- * Samsung NP900X3E-A02 0x575f03 ? clickpad
1151
- * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad
1152
- * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons
1153
- * Samsung RF710 0x450f00 ? 2 hw buttons
1154
- * System76 Pangolin 0x250f01 ? 2 hw buttons
1155
- * (*) + 3 trackpoint buttons
1156
- * (**) + 0 trackpoint buttons
1157
- * Note: Lenovo L430 and Lenovo L530 have the same fw_version/caps
1158
- */
11591120 static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
11601121 {
11611122 struct input_dev *dev = psmouse->dev;
11621123 struct elantech_data *etd = psmouse->private;
11631124
1164
- if (etd->info.fw_version & 0x001000) {
1125
+ if (elantech_is_buttonpad(&etd->info)) {
11651126 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
11661127 __clear_bit(BTN_RIGHT, dev->keybit);
11671128 }
....@@ -1197,16 +1158,6 @@
11971158 { }
11981159 };
11991160
1200
-static const char * const middle_button_pnp_ids[] = {
1201
- "LEN2131", /* ThinkPad P52 w/ NFC */
1202
- "LEN2132", /* ThinkPad P52 */
1203
- "LEN2133", /* ThinkPad P72 w/ NFC */
1204
- "LEN2134", /* ThinkPad P72 */
1205
- "LEN0407",
1206
- "LEN0408",
1207
- NULL
1208
-};
1209
-
12101161 /*
12111162 * Set the appropriate event bits for the input subsystem
12121163 */
....@@ -1215,10 +1166,9 @@
12151166 struct input_dev *dev = psmouse->dev;
12161167 struct elantech_data *etd = psmouse->private;
12171168 struct elantech_device_info *info = &etd->info;
1218
- unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
1219
-
1220
- if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
1221
- return -1;
1169
+ unsigned int x_min = info->x_min, y_min = info->y_min,
1170
+ x_max = info->x_max, y_max = info->y_max,
1171
+ width = info->width;
12221172
12231173 __set_bit(INPUT_PROP_POINTER, dev->propbit);
12241174 __set_bit(EV_KEY, dev->evbit);
....@@ -1226,8 +1176,7 @@
12261176 __clear_bit(EV_REL, dev->evbit);
12271177
12281178 __set_bit(BTN_LEFT, dev->keybit);
1229
- if (dmi_check_system(elantech_dmi_has_middle_button) ||
1230
- psmouse_matches_pnp_id(psmouse, middle_button_pnp_ids))
1179
+ if (info->has_middle_button)
12311180 __set_bit(BTN_MIDDLE, dev->keybit);
12321181 __set_bit(BTN_RIGHT, dev->keybit);
12331182
....@@ -1251,7 +1200,7 @@
12511200 case 2:
12521201 __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
12531202 __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
1254
- /* fall through */
1203
+ fallthrough;
12551204 case 3:
12561205 if (info->hw_version == 3)
12571206 elantech_set_buttonpad_prop(psmouse);
....@@ -1635,18 +1584,40 @@
16351584 };
16361585
16371586 /*
1587
+ * Change Report id 0x5E to 0x5F.
1588
+ */
1589
+static int elantech_change_report_id(struct psmouse *psmouse)
1590
+{
1591
+ /*
1592
+ * NOTE: the code is expecting to receive param[] as an array of 3
1593
+ * items (see __ps2_command()), even if in this case only 2 are
1594
+ * actually needed. Make sure the array size is 3 to avoid potential
1595
+ * stack out-of-bound accesses.
1596
+ */
1597
+ unsigned char param[3] = { 0x10, 0x03 };
1598
+
1599
+ if (elantech_write_reg_params(psmouse, 0x7, param) ||
1600
+ elantech_read_reg_params(psmouse, 0x7, param) ||
1601
+ param[0] != 0x10 || param[1] != 0x03) {
1602
+ psmouse_err(psmouse, "Unable to change report ID to 0x5f.\n");
1603
+ return -EIO;
1604
+ }
1605
+
1606
+ return 0;
1607
+}
1608
+/*
16381609 * determine hardware version and set some properties according to it.
16391610 */
16401611 static int elantech_set_properties(struct elantech_device_info *info)
16411612 {
16421613 /* This represents the version of IC body. */
1643
- int ver = (info->fw_version & 0x0f0000) >> 16;
1614
+ info->ic_version = (info->fw_version & 0x0f0000) >> 16;
16441615
16451616 /* Early version of Elan touchpads doesn't obey the rule. */
16461617 if (info->fw_version < 0x020030 || info->fw_version == 0x020600)
16471618 info->hw_version = 1;
16481619 else {
1649
- switch (ver) {
1620
+ switch (info->ic_version) {
16501621 case 2:
16511622 case 4:
16521623 info->hw_version = 2;
....@@ -1661,6 +1632,11 @@
16611632 return -1;
16621633 }
16631634 }
1635
+
1636
+ /* Get information pattern for hw_version 4 */
1637
+ info->pattern = 0x00;
1638
+ if (info->ic_version == 0x0f && (info->fw_version & 0xff) <= 0x02)
1639
+ info->pattern = info->fw_version & 0xff;
16641640
16651641 /* decide which send_cmd we're gonna use early */
16661642 info->send_cmd = info->hw_version >= 3 ? elantech_send_cmd :
....@@ -1702,6 +1678,8 @@
17021678 struct elantech_device_info *info)
17031679 {
17041680 unsigned char param[3];
1681
+ unsigned char traces;
1682
+ unsigned char ic_body[3];
17051683
17061684 memset(info, 0, sizeof(*info));
17071685
....@@ -1744,6 +1722,21 @@
17441722 info->samples[2]);
17451723 }
17461724
1725
+ if (info->pattern > 0x00 && info->ic_version == 0xf) {
1726
+ if (info->send_cmd(psmouse, ETP_ICBODY_QUERY, ic_body)) {
1727
+ psmouse_err(psmouse, "failed to query ic body\n");
1728
+ return -EINVAL;
1729
+ }
1730
+ info->ic_version = be16_to_cpup((__be16 *)ic_body);
1731
+ psmouse_info(psmouse,
1732
+ "Elan ic body: %#04x, current fw version: %#02x\n",
1733
+ info->ic_version, ic_body[2]);
1734
+ }
1735
+
1736
+ info->product_id = be16_to_cpup((__be16 *)info->samples);
1737
+ if (info->pattern == 0x00)
1738
+ info->product_id &= 0xff;
1739
+
17471740 if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
17481741 /*
17491742 * This module has a bug which makes absolute mode
....@@ -1758,6 +1751,23 @@
17581751 /* The MSB indicates the presence of the trackpoint */
17591752 info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
17601753
1754
+ if (info->has_trackpoint && info->ic_version == 0x0011 &&
1755
+ (info->product_id == 0x08 || info->product_id == 0x09 ||
1756
+ info->product_id == 0x0d || info->product_id == 0x0e)) {
1757
+ /*
1758
+ * This module has a bug which makes trackpoint in SMBus
1759
+ * mode return invalid data unless trackpoint is switched
1760
+ * from using 0x5e reports to 0x5f. If we are not able to
1761
+ * make the switch, let's abort initialization so we'll be
1762
+ * using standard PS/2 protocol.
1763
+ */
1764
+ if (elantech_change_report_id(psmouse)) {
1765
+ psmouse_info(psmouse,
1766
+ "Trackpoint report is broken, forcing standard PS/2 protocol\n");
1767
+ return -ENODEV;
1768
+ }
1769
+ }
1770
+
17611771 info->x_res = 31;
17621772 info->y_res = 31;
17631773 if (info->hw_version == 4) {
....@@ -1769,6 +1779,90 @@
17691779 "failed to query resolution data.\n");
17701780 }
17711781 }
1782
+
1783
+ /* query range information */
1784
+ switch (info->hw_version) {
1785
+ case 1:
1786
+ info->x_min = ETP_XMIN_V1;
1787
+ info->y_min = ETP_YMIN_V1;
1788
+ info->x_max = ETP_XMAX_V1;
1789
+ info->y_max = ETP_YMAX_V1;
1790
+ break;
1791
+
1792
+ case 2:
1793
+ if (info->fw_version == 0x020800 ||
1794
+ info->fw_version == 0x020b00 ||
1795
+ info->fw_version == 0x020030) {
1796
+ info->x_min = ETP_XMIN_V2;
1797
+ info->y_min = ETP_YMIN_V2;
1798
+ info->x_max = ETP_XMAX_V2;
1799
+ info->y_max = ETP_YMAX_V2;
1800
+ } else {
1801
+ int i;
1802
+ int fixed_dpi;
1803
+
1804
+ i = (info->fw_version > 0x020800 &&
1805
+ info->fw_version < 0x020900) ? 1 : 2;
1806
+
1807
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1808
+ return -EINVAL;
1809
+
1810
+ fixed_dpi = param[1] & 0x10;
1811
+
1812
+ if (((info->fw_version >> 16) == 0x14) && fixed_dpi) {
1813
+ if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
1814
+ return -EINVAL;
1815
+
1816
+ info->x_max = (info->capabilities[1] - i) * param[1] / 2;
1817
+ info->y_max = (info->capabilities[2] - i) * param[2] / 2;
1818
+ } else if (info->fw_version == 0x040216) {
1819
+ info->x_max = 819;
1820
+ info->y_max = 405;
1821
+ } else if (info->fw_version == 0x040219 || info->fw_version == 0x040215) {
1822
+ info->x_max = 900;
1823
+ info->y_max = 500;
1824
+ } else {
1825
+ info->x_max = (info->capabilities[1] - i) * 64;
1826
+ info->y_max = (info->capabilities[2] - i) * 64;
1827
+ }
1828
+ }
1829
+ break;
1830
+
1831
+ case 3:
1832
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1833
+ return -EINVAL;
1834
+
1835
+ info->x_max = (0x0f & param[0]) << 8 | param[1];
1836
+ info->y_max = (0xf0 & param[0]) << 4 | param[2];
1837
+ break;
1838
+
1839
+ case 4:
1840
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1841
+ return -EINVAL;
1842
+
1843
+ info->x_max = (0x0f & param[0]) << 8 | param[1];
1844
+ info->y_max = (0xf0 & param[0]) << 4 | param[2];
1845
+ traces = info->capabilities[1];
1846
+ if ((traces < 2) || (traces > info->x_max))
1847
+ return -EINVAL;
1848
+
1849
+ info->width = info->x_max / (traces - 1);
1850
+
1851
+ /* column number of traces */
1852
+ info->x_traces = traces;
1853
+
1854
+ /* row number of traces */
1855
+ traces = info->capabilities[2];
1856
+ if ((traces >= 2) && (traces <= info->y_max))
1857
+ info->y_traces = traces;
1858
+
1859
+ break;
1860
+ }
1861
+
1862
+ /* check for the middle button: DMI matching or new v4 firmwares */
1863
+ info->has_middle_button = dmi_check_system(elantech_dmi_has_middle_button) ||
1864
+ (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) &&
1865
+ !elantech_is_buttonpad(info));
17721866
17731867 return 0;
17741868 }
....@@ -1796,10 +1890,6 @@
17961890 * These are known to not be working properly as bits are missing
17971891 * in elan_i2c.
17981892 */
1799
- "LEN2131", /* ThinkPad P52 w/ NFC */
1800
- "LEN2132", /* ThinkPad P52 */
1801
- "LEN2133", /* ThinkPad P72 w/ NFC */
1802
- "LEN2134", /* ThinkPad P72 */
18031893 NULL
18041894 };
18051895
....@@ -1807,17 +1897,45 @@
18071897 struct elantech_device_info *info,
18081898 bool leave_breadcrumbs)
18091899 {
1810
- const struct property_entry i2c_properties[] = {
1811
- PROPERTY_ENTRY_BOOL("elan,trackpoint"),
1812
- { },
1813
- };
1900
+ struct property_entry i2c_props[11] = {};
18141901 struct i2c_board_info smbus_board = {
18151902 I2C_BOARD_INFO("elan_i2c", 0x15),
18161903 .flags = I2C_CLIENT_HOST_NOTIFY,
18171904 };
1905
+ unsigned int idx = 0;
1906
+
1907
+ smbus_board.properties = i2c_props;
1908
+
1909
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-size-x",
1910
+ info->x_max + 1);
1911
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-size-y",
1912
+ info->y_max + 1);
1913
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-min-x",
1914
+ info->x_min);
1915
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-min-y",
1916
+ info->y_min);
1917
+ if (info->x_res)
1918
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-x-mm",
1919
+ (info->x_max + 1) / info->x_res);
1920
+ if (info->y_res)
1921
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-y-mm",
1922
+ (info->y_max + 1) / info->y_res);
18181923
18191924 if (info->has_trackpoint)
1820
- smbus_board.properties = i2c_properties;
1925
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,trackpoint");
1926
+
1927
+ if (info->has_middle_button)
1928
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,middle-button");
1929
+
1930
+ if (info->x_traces)
1931
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("elan,x_traces",
1932
+ info->x_traces);
1933
+ if (info->y_traces)
1934
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("elan,y_traces",
1935
+ info->y_traces);
1936
+
1937
+ if (elantech_is_buttonpad(info))
1938
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,clickpad");
18211939
18221940 return psmouse_smbus_init(psmouse, &smbus_board, NULL, 0, false,
18231941 leave_breadcrumbs);
....@@ -1873,12 +1991,10 @@
18731991 /* expected case */
18741992 break;
18751993 case ETP_BUS_SMB_ALERT_ONLY:
1876
- /* fall-through */
18771994 case ETP_BUS_PS2_SMB_ALERT:
18781995 psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n");
18791996 break;
18801997 case ETP_BUS_SMB_HST_NTFY_ONLY:
1881
- /* fall-through */
18821998 case ETP_BUS_PS2_SMB_HST_NTFY:
18831999 return true;
18842000 default:
....@@ -1893,7 +2009,7 @@
18932009 int elantech_init_smbus(struct psmouse *psmouse)
18942010 {
18952011 struct elantech_device_info info;
1896
- int error = -EINVAL;
2012
+ int error;
18972013
18982014 psmouse_reset(psmouse);
18992015
....@@ -2011,7 +2127,7 @@
20112127 int elantech_init_ps2(struct psmouse *psmouse)
20122128 {
20132129 struct elantech_device_info info;
2014
- int error = -EINVAL;
2130
+ int error;
20152131
20162132 psmouse_reset(psmouse);
20172133
....@@ -2032,7 +2148,7 @@
20322148 int elantech_init(struct psmouse *psmouse)
20332149 {
20342150 struct elantech_device_info info;
2035
- int error = -EINVAL;
2151
+ int error;
20362152
20372153 psmouse_reset(psmouse);
20382154