hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
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]);
....@@ -590,10 +674,11 @@
590674 struct input_dev *dev = psmouse->dev;
591675 struct elantech_data *etd = psmouse->private;
592676 unsigned char *packet = psmouse->packet;
593
- int id = ((packet[3] & 0xe0) >> 5) - 1;
677
+ int id;
594678 int pres, traces;
595679
596
- if (id < 0)
680
+ id = ((packet[3] & 0xe0) >> 5) - 1;
681
+ if (id < 0 || id >= ETP_MAX_FINGERS)
597682 return;
598683
599684 etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
....@@ -623,7 +708,7 @@
623708 int id, sid;
624709
625710 id = ((packet[0] & 0xe0) >> 5) - 1;
626
- if (id < 0)
711
+ if (id < 0 || id >= ETP_MAX_FINGERS)
627712 return;
628713
629714 sid = ((packet[3] & 0xe0) >> 5) - 1;
....@@ -644,7 +729,7 @@
644729 input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
645730 input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
646731
647
- if (sid >= 0) {
732
+ if (sid >= 0 && sid < ETP_MAX_FINGERS) {
648733 etd->mt[sid].x += delta_x2 * weight;
649734 etd->mt[sid].y -= delta_y2 * weight;
650735 input_mt_slot(dev, sid);
....@@ -1007,88 +1092,6 @@
10071092 return rc;
10081093 }
10091094
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
-
10921095 /*
10931096 * (value from firmware) * 10 + 790 = dpi
10941097 * we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
....@@ -1115,53 +1118,12 @@
11151118 return 0;
11161119 }
11171120
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
- */
11591121 static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
11601122 {
11611123 struct input_dev *dev = psmouse->dev;
11621124 struct elantech_data *etd = psmouse->private;
11631125
1164
- if (etd->info.fw_version & 0x001000) {
1126
+ if (elantech_is_buttonpad(&etd->info)) {
11651127 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
11661128 __clear_bit(BTN_RIGHT, dev->keybit);
11671129 }
....@@ -1197,16 +1159,6 @@
11971159 { }
11981160 };
11991161
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
-
12101162 /*
12111163 * Set the appropriate event bits for the input subsystem
12121164 */
....@@ -1215,10 +1167,9 @@
12151167 struct input_dev *dev = psmouse->dev;
12161168 struct elantech_data *etd = psmouse->private;
12171169 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;
1170
+ unsigned int x_min = info->x_min, y_min = info->y_min,
1171
+ x_max = info->x_max, y_max = info->y_max,
1172
+ width = info->width;
12221173
12231174 __set_bit(INPUT_PROP_POINTER, dev->propbit);
12241175 __set_bit(EV_KEY, dev->evbit);
....@@ -1226,8 +1177,7 @@
12261177 __clear_bit(EV_REL, dev->evbit);
12271178
12281179 __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))
1180
+ if (info->has_middle_button)
12311181 __set_bit(BTN_MIDDLE, dev->keybit);
12321182 __set_bit(BTN_RIGHT, dev->keybit);
12331183
....@@ -1251,7 +1201,7 @@
12511201 case 2:
12521202 __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
12531203 __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
1254
- /* fall through */
1204
+ fallthrough;
12551205 case 3:
12561206 if (info->hw_version == 3)
12571207 elantech_set_buttonpad_prop(psmouse);
....@@ -1635,18 +1585,40 @@
16351585 };
16361586
16371587 /*
1588
+ * Change Report id 0x5E to 0x5F.
1589
+ */
1590
+static int elantech_change_report_id(struct psmouse *psmouse)
1591
+{
1592
+ /*
1593
+ * NOTE: the code is expecting to receive param[] as an array of 3
1594
+ * items (see __ps2_command()), even if in this case only 2 are
1595
+ * actually needed. Make sure the array size is 3 to avoid potential
1596
+ * stack out-of-bound accesses.
1597
+ */
1598
+ unsigned char param[3] = { 0x10, 0x03 };
1599
+
1600
+ if (elantech_write_reg_params(psmouse, 0x7, param) ||
1601
+ elantech_read_reg_params(psmouse, 0x7, param) ||
1602
+ param[0] != 0x10 || param[1] != 0x03) {
1603
+ psmouse_err(psmouse, "Unable to change report ID to 0x5f.\n");
1604
+ return -EIO;
1605
+ }
1606
+
1607
+ return 0;
1608
+}
1609
+/*
16381610 * determine hardware version and set some properties according to it.
16391611 */
16401612 static int elantech_set_properties(struct elantech_device_info *info)
16411613 {
16421614 /* This represents the version of IC body. */
1643
- int ver = (info->fw_version & 0x0f0000) >> 16;
1615
+ info->ic_version = (info->fw_version & 0x0f0000) >> 16;
16441616
16451617 /* Early version of Elan touchpads doesn't obey the rule. */
16461618 if (info->fw_version < 0x020030 || info->fw_version == 0x020600)
16471619 info->hw_version = 1;
16481620 else {
1649
- switch (ver) {
1621
+ switch (info->ic_version) {
16501622 case 2:
16511623 case 4:
16521624 info->hw_version = 2;
....@@ -1661,6 +1633,11 @@
16611633 return -1;
16621634 }
16631635 }
1636
+
1637
+ /* Get information pattern for hw_version 4 */
1638
+ info->pattern = 0x00;
1639
+ if (info->ic_version == 0x0f && (info->fw_version & 0xff) <= 0x02)
1640
+ info->pattern = info->fw_version & 0xff;
16641641
16651642 /* decide which send_cmd we're gonna use early */
16661643 info->send_cmd = info->hw_version >= 3 ? elantech_send_cmd :
....@@ -1702,6 +1679,8 @@
17021679 struct elantech_device_info *info)
17031680 {
17041681 unsigned char param[3];
1682
+ unsigned char traces;
1683
+ unsigned char ic_body[3];
17051684
17061685 memset(info, 0, sizeof(*info));
17071686
....@@ -1744,6 +1723,21 @@
17441723 info->samples[2]);
17451724 }
17461725
1726
+ if (info->pattern > 0x00 && info->ic_version == 0xf) {
1727
+ if (info->send_cmd(psmouse, ETP_ICBODY_QUERY, ic_body)) {
1728
+ psmouse_err(psmouse, "failed to query ic body\n");
1729
+ return -EINVAL;
1730
+ }
1731
+ info->ic_version = be16_to_cpup((__be16 *)ic_body);
1732
+ psmouse_info(psmouse,
1733
+ "Elan ic body: %#04x, current fw version: %#02x\n",
1734
+ info->ic_version, ic_body[2]);
1735
+ }
1736
+
1737
+ info->product_id = be16_to_cpup((__be16 *)info->samples);
1738
+ if (info->pattern == 0x00)
1739
+ info->product_id &= 0xff;
1740
+
17471741 if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
17481742 /*
17491743 * This module has a bug which makes absolute mode
....@@ -1758,6 +1752,23 @@
17581752 /* The MSB indicates the presence of the trackpoint */
17591753 info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
17601754
1755
+ if (info->has_trackpoint && info->ic_version == 0x0011 &&
1756
+ (info->product_id == 0x08 || info->product_id == 0x09 ||
1757
+ info->product_id == 0x0d || info->product_id == 0x0e)) {
1758
+ /*
1759
+ * This module has a bug which makes trackpoint in SMBus
1760
+ * mode return invalid data unless trackpoint is switched
1761
+ * from using 0x5e reports to 0x5f. If we are not able to
1762
+ * make the switch, let's abort initialization so we'll be
1763
+ * using standard PS/2 protocol.
1764
+ */
1765
+ if (elantech_change_report_id(psmouse)) {
1766
+ psmouse_info(psmouse,
1767
+ "Trackpoint report is broken, forcing standard PS/2 protocol\n");
1768
+ return -ENODEV;
1769
+ }
1770
+ }
1771
+
17611772 info->x_res = 31;
17621773 info->y_res = 31;
17631774 if (info->hw_version == 4) {
....@@ -1769,6 +1780,90 @@
17691780 "failed to query resolution data.\n");
17701781 }
17711782 }
1783
+
1784
+ /* query range information */
1785
+ switch (info->hw_version) {
1786
+ case 1:
1787
+ info->x_min = ETP_XMIN_V1;
1788
+ info->y_min = ETP_YMIN_V1;
1789
+ info->x_max = ETP_XMAX_V1;
1790
+ info->y_max = ETP_YMAX_V1;
1791
+ break;
1792
+
1793
+ case 2:
1794
+ if (info->fw_version == 0x020800 ||
1795
+ info->fw_version == 0x020b00 ||
1796
+ info->fw_version == 0x020030) {
1797
+ info->x_min = ETP_XMIN_V2;
1798
+ info->y_min = ETP_YMIN_V2;
1799
+ info->x_max = ETP_XMAX_V2;
1800
+ info->y_max = ETP_YMAX_V2;
1801
+ } else {
1802
+ int i;
1803
+ int fixed_dpi;
1804
+
1805
+ i = (info->fw_version > 0x020800 &&
1806
+ info->fw_version < 0x020900) ? 1 : 2;
1807
+
1808
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1809
+ return -EINVAL;
1810
+
1811
+ fixed_dpi = param[1] & 0x10;
1812
+
1813
+ if (((info->fw_version >> 16) == 0x14) && fixed_dpi) {
1814
+ if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
1815
+ return -EINVAL;
1816
+
1817
+ info->x_max = (info->capabilities[1] - i) * param[1] / 2;
1818
+ info->y_max = (info->capabilities[2] - i) * param[2] / 2;
1819
+ } else if (info->fw_version == 0x040216) {
1820
+ info->x_max = 819;
1821
+ info->y_max = 405;
1822
+ } else if (info->fw_version == 0x040219 || info->fw_version == 0x040215) {
1823
+ info->x_max = 900;
1824
+ info->y_max = 500;
1825
+ } else {
1826
+ info->x_max = (info->capabilities[1] - i) * 64;
1827
+ info->y_max = (info->capabilities[2] - i) * 64;
1828
+ }
1829
+ }
1830
+ break;
1831
+
1832
+ case 3:
1833
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1834
+ return -EINVAL;
1835
+
1836
+ info->x_max = (0x0f & param[0]) << 8 | param[1];
1837
+ info->y_max = (0xf0 & param[0]) << 4 | param[2];
1838
+ break;
1839
+
1840
+ case 4:
1841
+ if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
1842
+ return -EINVAL;
1843
+
1844
+ info->x_max = (0x0f & param[0]) << 8 | param[1];
1845
+ info->y_max = (0xf0 & param[0]) << 4 | param[2];
1846
+ traces = info->capabilities[1];
1847
+ if ((traces < 2) || (traces > info->x_max))
1848
+ return -EINVAL;
1849
+
1850
+ info->width = info->x_max / (traces - 1);
1851
+
1852
+ /* column number of traces */
1853
+ info->x_traces = traces;
1854
+
1855
+ /* row number of traces */
1856
+ traces = info->capabilities[2];
1857
+ if ((traces >= 2) && (traces <= info->y_max))
1858
+ info->y_traces = traces;
1859
+
1860
+ break;
1861
+ }
1862
+
1863
+ /* check for the middle button: DMI matching or new v4 firmwares */
1864
+ info->has_middle_button = dmi_check_system(elantech_dmi_has_middle_button) ||
1865
+ (ETP_NEW_IC_SMBUS_HOST_NOTIFY(info->fw_version) &&
1866
+ !elantech_is_buttonpad(info));
17721867
17731868 return 0;
17741869 }
....@@ -1796,10 +1891,6 @@
17961891 * These are known to not be working properly as bits are missing
17971892 * in elan_i2c.
17981893 */
1799
- "LEN2131", /* ThinkPad P52 w/ NFC */
1800
- "LEN2132", /* ThinkPad P52 */
1801
- "LEN2133", /* ThinkPad P72 w/ NFC */
1802
- "LEN2134", /* ThinkPad P72 */
18031894 NULL
18041895 };
18051896
....@@ -1807,17 +1898,45 @@
18071898 struct elantech_device_info *info,
18081899 bool leave_breadcrumbs)
18091900 {
1810
- const struct property_entry i2c_properties[] = {
1811
- PROPERTY_ENTRY_BOOL("elan,trackpoint"),
1812
- { },
1813
- };
1901
+ struct property_entry i2c_props[11] = {};
18141902 struct i2c_board_info smbus_board = {
18151903 I2C_BOARD_INFO("elan_i2c", 0x15),
18161904 .flags = I2C_CLIENT_HOST_NOTIFY,
18171905 };
1906
+ unsigned int idx = 0;
1907
+
1908
+ smbus_board.properties = i2c_props;
1909
+
1910
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-size-x",
1911
+ info->x_max + 1);
1912
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-size-y",
1913
+ info->y_max + 1);
1914
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-min-x",
1915
+ info->x_min);
1916
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-min-y",
1917
+ info->y_min);
1918
+ if (info->x_res)
1919
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-x-mm",
1920
+ (info->x_max + 1) / info->x_res);
1921
+ if (info->y_res)
1922
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("touchscreen-y-mm",
1923
+ (info->y_max + 1) / info->y_res);
18181924
18191925 if (info->has_trackpoint)
1820
- smbus_board.properties = i2c_properties;
1926
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,trackpoint");
1927
+
1928
+ if (info->has_middle_button)
1929
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,middle-button");
1930
+
1931
+ if (info->x_traces)
1932
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("elan,x_traces",
1933
+ info->x_traces);
1934
+ if (info->y_traces)
1935
+ i2c_props[idx++] = PROPERTY_ENTRY_U32("elan,y_traces",
1936
+ info->y_traces);
1937
+
1938
+ if (elantech_is_buttonpad(info))
1939
+ i2c_props[idx++] = PROPERTY_ENTRY_BOOL("elan,clickpad");
18211940
18221941 return psmouse_smbus_init(psmouse, &smbus_board, NULL, 0, false,
18231942 leave_breadcrumbs);
....@@ -1873,12 +1992,10 @@
18731992 /* expected case */
18741993 break;
18751994 case ETP_BUS_SMB_ALERT_ONLY:
1876
- /* fall-through */
18771995 case ETP_BUS_PS2_SMB_ALERT:
18781996 psmouse_dbg(psmouse, "Ignoring SMBus provider through alert protocol.\n");
18791997 break;
18801998 case ETP_BUS_SMB_HST_NTFY_ONLY:
1881
- /* fall-through */
18821999 case ETP_BUS_PS2_SMB_HST_NTFY:
18832000 return true;
18842001 default:
....@@ -1893,7 +2010,7 @@
18932010 int elantech_init_smbus(struct psmouse *psmouse)
18942011 {
18952012 struct elantech_device_info info;
1896
- int error = -EINVAL;
2013
+ int error;
18972014
18982015 psmouse_reset(psmouse);
18992016
....@@ -2011,7 +2128,7 @@
20112128 int elantech_init_ps2(struct psmouse *psmouse)
20122129 {
20132130 struct elantech_device_info info;
2014
- int error = -EINVAL;
2131
+ int error;
20152132
20162133 psmouse_reset(psmouse);
20172134
....@@ -2032,7 +2149,7 @@
20322149 int elantech_init(struct psmouse *psmouse)
20332150 {
20342151 struct elantech_device_info info;
2035
- int error = -EINVAL;
2152
+ int error;
20362153
20372154 psmouse_reset(psmouse);
20382155