diff options
-rw-r--r-- | Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt | 21 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/vendor-prefixes.txt | 1 | ||||
-rw-r--r-- | Documentation/input/alps.txt | 57 | ||||
-rw-r--r-- | Documentation/kernel-parameters.txt | 9 | ||||
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | drivers/input/mouse/alps.c | 87 | ||||
-rw-r--r-- | drivers/input/mouse/alps.h | 2 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.c | 27 | ||||
-rw-r--r-- | drivers/input/rmi4/rmi_i2c.c | 38 | ||||
-rw-r--r-- | drivers/input/rmi4/rmi_spi.c | 22 | ||||
-rw-r--r-- | drivers/input/serio/i8042-io.h | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-ip22io.h | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-ppcio.h | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-sparcio.h | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-unicore32io.h | 2 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 96 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 55 | ||||
-rw-r--r-- | drivers/input/touchscreen/melfas_mip4.c | 38 |
18 files changed, 411 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt b/Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt new file mode 100644 index 000000000000..7b8944c2cb31 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt | |||
@@ -0,0 +1,21 @@ | |||
1 | * MELFAS MIP4 Touchscreen | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: must be "melfas,mip4_ts" | ||
5 | - reg: I2C slave address of the chip (0x48 or 0x34) | ||
6 | - interrupt-parent: interrupt controller to which the chip is connected | ||
7 | - interrupts: interrupt to which the chip is connected | ||
8 | |||
9 | Optional properties: | ||
10 | - ce-gpios: GPIO connected to the CE (chip enable) pin of the chip | ||
11 | |||
12 | Example: | ||
13 | i2c@00000000 { | ||
14 | touchscreen: melfas_mip4@48 { | ||
15 | compatible = "melfas,mip4_ts"; | ||
16 | reg = <0x48>; | ||
17 | interrupt-parent = <&gpio>; | ||
18 | interrupts = <0 IRQ_TYPE_EDGE_FALLING>; | ||
19 | ce-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; | ||
20 | }; | ||
21 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index caf0798908e2..f0a48ea78659 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -163,6 +163,7 @@ maxim Maxim Integrated Products | |||
163 | meas Measurement Specialties | 163 | meas Measurement Specialties |
164 | mediatek MediaTek Inc. | 164 | mediatek MediaTek Inc. |
165 | melexis Melexis N.V. | 165 | melexis Melexis N.V. |
166 | melfas MELFAS Inc. | ||
166 | merrii Merrii Technology Co., Ltd. | 167 | merrii Merrii Technology Co., Ltd. |
167 | micrel Micrel Inc. | 168 | micrel Micrel Inc. |
168 | microchip Microchip Technology Inc. | 169 | microchip Microchip Technology Inc. |
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt index 1fec1135791d..8d1341ccde64 100644 --- a/Documentation/input/alps.txt +++ b/Documentation/input/alps.txt | |||
@@ -319,3 +319,60 @@ For touchpad packet, the format is: | |||
319 | otherwise byte 0 bit 4 must be set and byte 0/4/5 are | 319 | otherwise byte 0 bit 4 must be set and byte 0/4/5 are |
320 | in NEW fmt | 320 | in NEW fmt |
321 | F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ... | 321 | F: Number of fingers - 3, 0 means 3 fingers, 1 means 4 ... |
322 | |||
323 | |||
324 | ALPS Absolute Mode - Protocol Version 8 | ||
325 | --------------------------------------- | ||
326 | |||
327 | Spoken by SS4 (73 03 14) and SS5 (73 03 28) hardware. | ||
328 | |||
329 | The packet type is given by the APD field, bits 4-5 of byte 3. | ||
330 | |||
331 | Touchpad packet (APD = 0x2): | ||
332 | |||
333 | b7 b6 b5 b4 b3 b2 b1 b0 | ||
334 | byte 0: SWM SWR SWL 1 1 0 0 X7 | ||
335 | byte 1: 0 X6 X5 X4 X3 X2 X1 X0 | ||
336 | byte 2: 0 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
337 | byte 3: 0 T&P 1 0 1 0 0 Y7 | ||
338 | byte 4: 0 Z6 Z5 Z4 Z3 Z2 Z1 Z0 | ||
339 | byte 5: 0 0 0 0 0 0 0 0 | ||
340 | |||
341 | SWM, SWR, SWL: Middle, Right, and Left button states | ||
342 | |||
343 | Touchpad 1 Finger packet (APD = 0x0): | ||
344 | |||
345 | b7 b6 b5 b4 b3 b2 b1 b0 | ||
346 | byte 0: SWM SWR SWL 1 1 X2 X1 X0 | ||
347 | byte 1: X9 X8 X7 1 X6 X5 X4 X3 | ||
348 | byte 2: 0 X11 X10 LFB Y3 Y2 Y1 Y0 | ||
349 | byte 3: Y5 Y4 0 0 1 TAPF2 TAPF1 TAPF0 | ||
350 | byte 4: Zv7 Y11 Y10 1 Y9 Y8 Y7 Y6 | ||
351 | byte 5: Zv6 Zv5 Zv4 0 Zv3 Zv2 Zv1 Zv0 | ||
352 | |||
353 | TAPF: ??? | ||
354 | LFB: ??? | ||
355 | |||
356 | Touchpad 2 Finger packet (APD = 0x1): | ||
357 | |||
358 | b7 b6 b5 b4 b3 b2 b1 b0 | ||
359 | byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4 | ||
360 | byte 1: AX11 AX10 AX9 AX8 AX7 AZ1 AY4 AZ0 | ||
361 | byte 2: AY11 AY10 AY9 CONT AY8 AY7 AY6 AY5 | ||
362 | byte 3: 0 0 0 1 1 BX6 BX5 BX4 | ||
363 | byte 4: BX11 BX10 BX9 BX8 BX7 BZ1 BY4 BZ0 | ||
364 | byte 5: BY11 BY10 BY9 0 BY8 BY7 BY5 BY5 | ||
365 | |||
366 | CONT: A 3-or-4 Finger packet is to follow | ||
367 | |||
368 | Touchpad 3-or-4 Finger packet (APD = 0x3): | ||
369 | |||
370 | b7 b6 b5 b4 b3 b2 b1 b0 | ||
371 | byte 0: SWM SWR SWL 1 1 AX6 AX5 AX4 | ||
372 | byte 1: AX11 AX10 AX9 AX8 AX7 AZ1 AY4 AZ0 | ||
373 | byte 2: AY11 AY10 AY9 OVF AY8 AY7 AY6 AY5 | ||
374 | byte 3: 0 0 1 1 1 BX6 BX5 BX4 | ||
375 | byte 4: BX11 BX10 BX9 BX8 BX7 BZ1 BY4 BZ0 | ||
376 | byte 5: BY11 BY10 BY9 0 BY8 BY7 BY5 BY5 | ||
377 | |||
378 | OVF: 5th finger detected | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 58f3c1041759..37babf91f2cb 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1511,7 +1511,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1511 | i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX | 1511 | i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX |
1512 | controllers | 1512 | controllers |
1513 | i8042.notimeout [HW] Ignore timeout condition signalled by controller | 1513 | i8042.notimeout [HW] Ignore timeout condition signalled by controller |
1514 | i8042.reset [HW] Reset the controller during init and cleanup | 1514 | i8042.reset [HW] Reset the controller during init, cleanup and |
1515 | suspend-to-ram transitions, only during s2r | ||
1516 | transitions, or never reset | ||
1517 | Format: { 1 | Y | y | 0 | N | n } | ||
1518 | 1, Y, y: always reset controller | ||
1519 | 0, N, n: don't ever reset controller | ||
1520 | Default: only on s2r transitions on x86; most other | ||
1521 | architectures force reset to be always executed | ||
1515 | i8042.unlock [HW] Unlock (ignore) the keylock | 1522 | i8042.unlock [HW] Unlock (ignore) the keylock |
1516 | i8042.kbdreset [HW] Reset device connected to KBD port | 1523 | i8042.kbdreset [HW] Reset device connected to KBD port |
1517 | 1524 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 146d1498aa01..a452c404141d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7829,6 +7829,13 @@ F: Documentation/scsi/megaraid.txt | |||
7829 | F: drivers/scsi/megaraid.* | 7829 | F: drivers/scsi/megaraid.* |
7830 | F: drivers/scsi/megaraid/ | 7830 | F: drivers/scsi/megaraid/ |
7831 | 7831 | ||
7832 | MELFAS MIP4 TOUCHSCREEN DRIVER | ||
7833 | M: Sangwon Jee <jeesw@melfas.com> | ||
7834 | W: http://www.melfas.com | ||
7835 | S: Supported | ||
7836 | F: drivers/input/touchscreen/melfas_mip4.c | ||
7837 | F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt | ||
7838 | |||
7832 | MELLANOX ETHERNET DRIVER (mlx4_en) | 7839 | MELLANOX ETHERNET DRIVER (mlx4_en) |
7833 | M: Tariq Toukan <tariqt@mellanox.com> | 7840 | M: Tariq Toukan <tariqt@mellanox.com> |
7834 | L: netdev@vger.kernel.org | 7841 | L: netdev@vger.kernel.org |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 936f07a4e35f..6d7de9bfed9a 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -103,6 +103,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = { | |||
103 | 6-byte ALPS packet */ | 103 | 6-byte ALPS packet */ |
104 | #define ALPS_STICK_BITS 0x100 /* separate stick button bits */ | 104 | #define ALPS_STICK_BITS 0x100 /* separate stick button bits */ |
105 | #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ | 105 | #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */ |
106 | #define ALPS_DUALPOINT_WITH_PRESSURE 0x400 /* device can report trackpoint pressure */ | ||
106 | 107 | ||
107 | static const struct alps_model_info alps_model_data[] = { | 108 | static const struct alps_model_info alps_model_data[] = { |
108 | { { 0x32, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */ | 109 | { { 0x32, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */ |
@@ -1156,15 +1157,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte) | |||
1156 | { | 1157 | { |
1157 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; | 1158 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; |
1158 | 1159 | ||
1159 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && | 1160 | switch (byte[3] & 0x30) { |
1160 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { | 1161 | case 0x00: |
1161 | pkt_id = SS4_PACKET_ID_IDLE; | 1162 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && |
1162 | } else if (!(byte[3] & 0x10)) { | 1163 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && |
1163 | pkt_id = SS4_PACKET_ID_ONE; | 1164 | byte[5] == 0x00) { |
1164 | } else if (!(byte[3] & 0x20)) { | 1165 | pkt_id = SS4_PACKET_ID_IDLE; |
1166 | } else { | ||
1167 | pkt_id = SS4_PACKET_ID_ONE; | ||
1168 | } | ||
1169 | break; | ||
1170 | case 0x10: | ||
1171 | /* two-finger finger positions */ | ||
1165 | pkt_id = SS4_PACKET_ID_TWO; | 1172 | pkt_id = SS4_PACKET_ID_TWO; |
1166 | } else { | 1173 | break; |
1174 | case 0x20: | ||
1175 | /* stick pointer */ | ||
1176 | pkt_id = SS4_PACKET_ID_STICK; | ||
1177 | break; | ||
1178 | case 0x30: | ||
1179 | /* third and fourth finger positions */ | ||
1167 | pkt_id = SS4_PACKET_ID_MULTI; | 1180 | pkt_id = SS4_PACKET_ID_MULTI; |
1181 | break; | ||
1168 | } | 1182 | } |
1169 | 1183 | ||
1170 | return pkt_id; | 1184 | return pkt_id; |
@@ -1185,7 +1199,13 @@ static int alps_decode_ss4_v2(struct alps_fields *f, | |||
1185 | f->mt[0].x = SS4_1F_X_V2(p); | 1199 | f->mt[0].x = SS4_1F_X_V2(p); |
1186 | f->mt[0].y = SS4_1F_Y_V2(p); | 1200 | f->mt[0].y = SS4_1F_Y_V2(p); |
1187 | f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f; | 1201 | f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f; |
1188 | f->fingers = 1; | 1202 | /* |
1203 | * When a button is held the device will give us events | ||
1204 | * with x, y, and pressure of 0. This causes annoying jumps | ||
1205 | * if a touch is released while the button is held. | ||
1206 | * Handle this by claiming zero contacts. | ||
1207 | */ | ||
1208 | f->fingers = f->pressure > 0 ? 1 : 0; | ||
1189 | f->first_mp = 0; | 1209 | f->first_mp = 0; |
1190 | f->is_mp = 0; | 1210 | f->is_mp = 0; |
1191 | break; | 1211 | break; |
@@ -1246,16 +1266,40 @@ static int alps_decode_ss4_v2(struct alps_fields *f, | |||
1246 | } | 1266 | } |
1247 | break; | 1267 | break; |
1248 | 1268 | ||
1269 | case SS4_PACKET_ID_STICK: | ||
1270 | if (!(priv->flags & ALPS_DUALPOINT)) { | ||
1271 | psmouse_warn(psmouse, | ||
1272 | "Rejected trackstick packet from non DualPoint device"); | ||
1273 | } else { | ||
1274 | int x = (s8)(((p[0] & 1) << 7) | (p[1] & 0x7f)); | ||
1275 | int y = (s8)(((p[3] & 1) << 7) | (p[2] & 0x7f)); | ||
1276 | int pressure = (s8)(p[4] & 0x7f); | ||
1277 | |||
1278 | input_report_rel(priv->dev2, REL_X, x); | ||
1279 | input_report_rel(priv->dev2, REL_Y, -y); | ||
1280 | input_report_abs(priv->dev2, ABS_PRESSURE, pressure); | ||
1281 | } | ||
1282 | break; | ||
1283 | |||
1249 | case SS4_PACKET_ID_IDLE: | 1284 | case SS4_PACKET_ID_IDLE: |
1250 | default: | 1285 | default: |
1251 | memset(f, 0, sizeof(struct alps_fields)); | 1286 | memset(f, 0, sizeof(struct alps_fields)); |
1252 | break; | 1287 | break; |
1253 | } | 1288 | } |
1254 | 1289 | ||
1255 | f->left = !!(SS4_BTN_V2(p) & 0x01); | 1290 | /* handle buttons */ |
1256 | if (!(priv->flags & ALPS_BUTTONPAD)) { | 1291 | if (pkt_id == SS4_PACKET_ID_STICK) { |
1257 | f->right = !!(SS4_BTN_V2(p) & 0x02); | 1292 | f->ts_left = !!(SS4_BTN_V2(p) & 0x01); |
1258 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | 1293 | if (!(priv->flags & ALPS_BUTTONPAD)) { |
1294 | f->ts_right = !!(SS4_BTN_V2(p) & 0x02); | ||
1295 | f->ts_middle = !!(SS4_BTN_V2(p) & 0x04); | ||
1296 | } | ||
1297 | } else { | ||
1298 | f->left = !!(SS4_BTN_V2(p) & 0x01); | ||
1299 | if (!(priv->flags & ALPS_BUTTONPAD)) { | ||
1300 | f->right = !!(SS4_BTN_V2(p) & 0x02); | ||
1301 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | ||
1302 | } | ||
1259 | } | 1303 | } |
1260 | 1304 | ||
1261 | return 0; | 1305 | return 0; |
@@ -1266,6 +1310,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | |||
1266 | struct alps_data *priv = psmouse->private; | 1310 | struct alps_data *priv = psmouse->private; |
1267 | unsigned char *packet = psmouse->packet; | 1311 | unsigned char *packet = psmouse->packet; |
1268 | struct input_dev *dev = psmouse->dev; | 1312 | struct input_dev *dev = psmouse->dev; |
1313 | struct input_dev *dev2 = priv->dev2; | ||
1269 | struct alps_fields *f = &priv->f; | 1314 | struct alps_fields *f = &priv->f; |
1270 | 1315 | ||
1271 | memset(f, 0, sizeof(struct alps_fields)); | 1316 | memset(f, 0, sizeof(struct alps_fields)); |
@@ -1311,6 +1356,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | |||
1311 | 1356 | ||
1312 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | 1357 | input_report_abs(dev, ABS_PRESSURE, f->pressure); |
1313 | input_sync(dev); | 1358 | input_sync(dev); |
1359 | |||
1360 | if (priv->flags & ALPS_DUALPOINT) { | ||
1361 | input_report_key(dev2, BTN_LEFT, f->ts_left); | ||
1362 | input_report_key(dev2, BTN_RIGHT, f->ts_right); | ||
1363 | input_report_key(dev2, BTN_MIDDLE, f->ts_middle); | ||
1364 | input_sync(dev2); | ||
1365 | } | ||
1314 | } | 1366 | } |
1315 | 1367 | ||
1316 | static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) | 1368 | static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) |
@@ -2695,6 +2747,10 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2695 | if (alps_set_defaults_ss4_v2(psmouse, priv)) | 2747 | if (alps_set_defaults_ss4_v2(psmouse, priv)) |
2696 | return -EIO; | 2748 | return -EIO; |
2697 | 2749 | ||
2750 | if (priv->fw_ver[1] == 0x1) | ||
2751 | priv->flags |= ALPS_DUALPOINT | | ||
2752 | ALPS_DUALPOINT_WITH_PRESSURE; | ||
2753 | |||
2698 | break; | 2754 | break; |
2699 | } | 2755 | } |
2700 | 2756 | ||
@@ -2767,6 +2823,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2767 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && | 2823 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && |
2768 | e7[2] == 0x14 && ec[1] == 0x02) { | 2824 | e7[2] == 0x14 && ec[1] == 0x02) { |
2769 | protocol = &alps_v8_protocol_data; | 2825 | protocol = &alps_v8_protocol_data; |
2826 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && | ||
2827 | e7[2] == 0x28 && ec[1] == 0x01) { | ||
2828 | protocol = &alps_v8_protocol_data; | ||
2770 | } else { | 2829 | } else { |
2771 | psmouse_dbg(psmouse, | 2830 | psmouse_dbg(psmouse, |
2772 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2831 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
@@ -2949,6 +3008,10 @@ int alps_init(struct psmouse *psmouse) | |||
2949 | 3008 | ||
2950 | input_set_capability(dev2, EV_REL, REL_X); | 3009 | input_set_capability(dev2, EV_REL, REL_X); |
2951 | input_set_capability(dev2, EV_REL, REL_Y); | 3010 | input_set_capability(dev2, EV_REL, REL_Y); |
3011 | if (priv->flags & ALPS_DUALPOINT_WITH_PRESSURE) { | ||
3012 | input_set_capability(dev2, EV_ABS, ABS_PRESSURE); | ||
3013 | input_set_abs_params(dev2, ABS_PRESSURE, 0, 127, 0, 0); | ||
3014 | } | ||
2952 | input_set_capability(dev2, EV_KEY, BTN_LEFT); | 3015 | input_set_capability(dev2, EV_KEY, BTN_LEFT); |
2953 | input_set_capability(dev2, EV_KEY, BTN_RIGHT); | 3016 | input_set_capability(dev2, EV_KEY, BTN_RIGHT); |
2954 | input_set_capability(dev2, EV_KEY, BTN_MIDDLE); | 3017 | input_set_capability(dev2, EV_KEY, BTN_MIDDLE); |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index d37f814dc447..b9417e2d7ad3 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -37,12 +37,14 @@ | |||
37 | * or there's button activities. | 37 | * or there's button activities. |
38 | * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad | 38 | * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad |
39 | * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad | 39 | * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad |
40 | * SS4_PACKET_ID_STICK: A stick pointer packet | ||
40 | */ | 41 | */ |
41 | enum SS4_PACKET_ID { | 42 | enum SS4_PACKET_ID { |
42 | SS4_PACKET_ID_IDLE = 0, | 43 | SS4_PACKET_ID_IDLE = 0, |
43 | SS4_PACKET_ID_ONE, | 44 | SS4_PACKET_ID_ONE, |
44 | SS4_PACKET_ID_TWO, | 45 | SS4_PACKET_ID_TWO, |
45 | SS4_PACKET_ID_MULTI, | 46 | SS4_PACKET_ID_MULTI, |
47 | SS4_PACKET_ID_STICK, | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | #define SS4_COUNT_PER_ELECTRODE 256 | 50 | #define SS4_COUNT_PER_ELECTRODE 256 |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 08e252a42480..db7d1d666ac1 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -1134,7 +1134,7 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
1134 | * System76 Pangolin 0x250f01 ? 2 hw buttons | 1134 | * System76 Pangolin 0x250f01 ? 2 hw buttons |
1135 | * (*) + 3 trackpoint buttons | 1135 | * (*) + 3 trackpoint buttons |
1136 | * (**) + 0 trackpoint buttons | 1136 | * (**) + 0 trackpoint buttons |
1137 | * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps | 1137 | * Note: Lenovo L430 and Lenovo L530 have the same fw_version/caps |
1138 | */ | 1138 | */ |
1139 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) | 1139 | static void elantech_set_buttonpad_prop(struct psmouse *psmouse) |
1140 | { | 1140 | { |
@@ -1159,6 +1159,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = { | |||
1159 | DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"), | 1159 | DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"), |
1160 | }, | 1160 | }, |
1161 | }, | 1161 | }, |
1162 | { | ||
1163 | /* Fujitsu H760 also has a middle button */ | ||
1164 | .matches = { | ||
1165 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
1166 | DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"), | ||
1167 | }, | ||
1168 | }, | ||
1162 | #endif | 1169 | #endif |
1163 | { } | 1170 | { } |
1164 | }; | 1171 | }; |
@@ -1503,10 +1510,10 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { | |||
1503 | }, | 1510 | }, |
1504 | }, | 1511 | }, |
1505 | { | 1512 | { |
1506 | /* Fujitsu LIFEBOOK E554 does not work with crc_enabled == 0 */ | 1513 | /* Fujitsu H760 does not work with crc_enabled == 0 */ |
1507 | .matches = { | 1514 | .matches = { |
1508 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 1515 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
1509 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E554"), | 1516 | DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"), |
1510 | }, | 1517 | }, |
1511 | }, | 1518 | }, |
1512 | { | 1519 | { |
@@ -1517,6 +1524,20 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = { | |||
1517 | }, | 1524 | }, |
1518 | }, | 1525 | }, |
1519 | { | 1526 | { |
1527 | /* Fujitsu LIFEBOOK E554 does not work with crc_enabled == 0 */ | ||
1528 | .matches = { | ||
1529 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
1530 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E554"), | ||
1531 | }, | ||
1532 | }, | ||
1533 | { | ||
1534 | /* Fujitsu LIFEBOOK E556 does not work with crc_enabled == 0 */ | ||
1535 | .matches = { | ||
1536 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | ||
1537 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E556"), | ||
1538 | }, | ||
1539 | }, | ||
1540 | { | ||
1520 | /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */ | 1541 | /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */ |
1521 | .matches = { | 1542 | .matches = { |
1522 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 1543 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c index 6f2e0e4f0296..1ebc2c1debae 100644 --- a/drivers/input/rmi4/rmi_i2c.c +++ b/drivers/input/rmi4/rmi_i2c.c | |||
@@ -221,6 +221,21 @@ static const struct of_device_id rmi_i2c_of_match[] = { | |||
221 | MODULE_DEVICE_TABLE(of, rmi_i2c_of_match); | 221 | MODULE_DEVICE_TABLE(of, rmi_i2c_of_match); |
222 | #endif | 222 | #endif |
223 | 223 | ||
224 | static void rmi_i2c_regulator_bulk_disable(void *data) | ||
225 | { | ||
226 | struct rmi_i2c_xport *rmi_i2c = data; | ||
227 | |||
228 | regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), | ||
229 | rmi_i2c->supplies); | ||
230 | } | ||
231 | |||
232 | static void rmi_i2c_unregister_transport(void *data) | ||
233 | { | ||
234 | struct rmi_i2c_xport *rmi_i2c = data; | ||
235 | |||
236 | rmi_unregister_transport_device(&rmi_i2c->xport); | ||
237 | } | ||
238 | |||
224 | static int rmi_i2c_probe(struct i2c_client *client, | 239 | static int rmi_i2c_probe(struct i2c_client *client, |
225 | const struct i2c_device_id *id) | 240 | const struct i2c_device_id *id) |
226 | { | 241 | { |
@@ -264,6 +279,12 @@ static int rmi_i2c_probe(struct i2c_client *client, | |||
264 | if (retval < 0) | 279 | if (retval < 0) |
265 | return retval; | 280 | return retval; |
266 | 281 | ||
282 | retval = devm_add_action_or_reset(&client->dev, | ||
283 | rmi_i2c_regulator_bulk_disable, | ||
284 | rmi_i2c); | ||
285 | if (retval) | ||
286 | return retval; | ||
287 | |||
267 | of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms", | 288 | of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms", |
268 | &rmi_i2c->startup_delay); | 289 | &rmi_i2c->startup_delay); |
269 | 290 | ||
@@ -294,6 +315,11 @@ static int rmi_i2c_probe(struct i2c_client *client, | |||
294 | client->addr); | 315 | client->addr); |
295 | return retval; | 316 | return retval; |
296 | } | 317 | } |
318 | retval = devm_add_action_or_reset(&client->dev, | ||
319 | rmi_i2c_unregister_transport, | ||
320 | rmi_i2c); | ||
321 | if (retval) | ||
322 | return retval; | ||
297 | 323 | ||
298 | retval = rmi_i2c_init_irq(client); | 324 | retval = rmi_i2c_init_irq(client); |
299 | if (retval < 0) | 325 | if (retval < 0) |
@@ -304,17 +330,6 @@ static int rmi_i2c_probe(struct i2c_client *client, | |||
304 | return 0; | 330 | return 0; |
305 | } | 331 | } |
306 | 332 | ||
307 | static int rmi_i2c_remove(struct i2c_client *client) | ||
308 | { | ||
309 | struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); | ||
310 | |||
311 | rmi_unregister_transport_device(&rmi_i2c->xport); | ||
312 | regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), | ||
313 | rmi_i2c->supplies); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | #ifdef CONFIG_PM_SLEEP | 333 | #ifdef CONFIG_PM_SLEEP |
319 | static int rmi_i2c_suspend(struct device *dev) | 334 | static int rmi_i2c_suspend(struct device *dev) |
320 | { | 335 | { |
@@ -431,7 +446,6 @@ static struct i2c_driver rmi_i2c_driver = { | |||
431 | }, | 446 | }, |
432 | .id_table = rmi_id, | 447 | .id_table = rmi_id, |
433 | .probe = rmi_i2c_probe, | 448 | .probe = rmi_i2c_probe, |
434 | .remove = rmi_i2c_remove, | ||
435 | }; | 449 | }; |
436 | 450 | ||
437 | module_i2c_driver(rmi_i2c_driver); | 451 | module_i2c_driver(rmi_i2c_driver); |
diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c index 55bd1b34970c..4ebef607e214 100644 --- a/drivers/input/rmi4/rmi_spi.c +++ b/drivers/input/rmi4/rmi_spi.c | |||
@@ -396,6 +396,13 @@ static inline int rmi_spi_of_probe(struct spi_device *spi, | |||
396 | } | 396 | } |
397 | #endif | 397 | #endif |
398 | 398 | ||
399 | static void rmi_spi_unregister_transport(void *data) | ||
400 | { | ||
401 | struct rmi_spi_xport *rmi_spi = data; | ||
402 | |||
403 | rmi_unregister_transport_device(&rmi_spi->xport); | ||
404 | } | ||
405 | |||
399 | static int rmi_spi_probe(struct spi_device *spi) | 406 | static int rmi_spi_probe(struct spi_device *spi) |
400 | { | 407 | { |
401 | struct rmi_spi_xport *rmi_spi; | 408 | struct rmi_spi_xport *rmi_spi; |
@@ -464,6 +471,11 @@ static int rmi_spi_probe(struct spi_device *spi) | |||
464 | dev_err(&spi->dev, "failed to register transport.\n"); | 471 | dev_err(&spi->dev, "failed to register transport.\n"); |
465 | return retval; | 472 | return retval; |
466 | } | 473 | } |
474 | retval = devm_add_action_or_reset(&spi->dev, | ||
475 | rmi_spi_unregister_transport, | ||
476 | rmi_spi); | ||
477 | if (retval) | ||
478 | return retval; | ||
467 | 479 | ||
468 | retval = rmi_spi_init_irq(spi); | 480 | retval = rmi_spi_init_irq(spi); |
469 | if (retval < 0) | 481 | if (retval < 0) |
@@ -473,15 +485,6 @@ static int rmi_spi_probe(struct spi_device *spi) | |||
473 | return 0; | 485 | return 0; |
474 | } | 486 | } |
475 | 487 | ||
476 | static int rmi_spi_remove(struct spi_device *spi) | ||
477 | { | ||
478 | struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi); | ||
479 | |||
480 | rmi_unregister_transport_device(&rmi_spi->xport); | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | #ifdef CONFIG_PM_SLEEP | 488 | #ifdef CONFIG_PM_SLEEP |
486 | static int rmi_spi_suspend(struct device *dev) | 489 | static int rmi_spi_suspend(struct device *dev) |
487 | { | 490 | { |
@@ -577,7 +580,6 @@ static struct spi_driver rmi_spi_driver = { | |||
577 | }, | 580 | }, |
578 | .id_table = rmi_id, | 581 | .id_table = rmi_id, |
579 | .probe = rmi_spi_probe, | 582 | .probe = rmi_spi_probe, |
580 | .remove = rmi_spi_remove, | ||
581 | }; | 583 | }; |
582 | 584 | ||
583 | module_spi_driver(rmi_spi_driver); | 585 | module_spi_driver(rmi_spi_driver); |
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index a5eed2ade53d..34da81c006b6 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h | |||
@@ -81,7 +81,7 @@ static inline int i8042_platform_init(void) | |||
81 | return -EBUSY; | 81 | return -EBUSY; |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | i8042_reset = 1; | 84 | i8042_reset = I8042_RESET_ALWAYS; |
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
diff --git a/drivers/input/serio/i8042-ip22io.h b/drivers/input/serio/i8042-ip22io.h index ee1ad27d6ed0..08a1c10a1448 100644 --- a/drivers/input/serio/i8042-ip22io.h +++ b/drivers/input/serio/i8042-ip22io.h | |||
@@ -61,7 +61,7 @@ static inline int i8042_platform_init(void) | |||
61 | return -EBUSY; | 61 | return -EBUSY; |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | i8042_reset = 1; | 64 | i8042_reset = I8042_RESET_ALWAYS; |
65 | 65 | ||
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
diff --git a/drivers/input/serio/i8042-ppcio.h b/drivers/input/serio/i8042-ppcio.h index f708c75d16f1..1aabea43329e 100644 --- a/drivers/input/serio/i8042-ppcio.h +++ b/drivers/input/serio/i8042-ppcio.h | |||
@@ -44,7 +44,7 @@ static inline void i8042_write_command(int val) | |||
44 | 44 | ||
45 | static inline int i8042_platform_init(void) | 45 | static inline int i8042_platform_init(void) |
46 | { | 46 | { |
47 | i8042_reset = 1; | 47 | i8042_reset = I8042_RESET_ALWAYS; |
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index afcd1c1a05b2..6231d63860ee 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -130,7 +130,7 @@ static int __init i8042_platform_init(void) | |||
130 | } | 130 | } |
131 | } | 131 | } |
132 | 132 | ||
133 | i8042_reset = 1; | 133 | i8042_reset = I8042_RESET_ALWAYS; |
134 | 134 | ||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h index 73f5cc124a36..455747552f85 100644 --- a/drivers/input/serio/i8042-unicore32io.h +++ b/drivers/input/serio/i8042-unicore32io.h | |||
@@ -61,7 +61,7 @@ static inline int i8042_platform_init(void) | |||
61 | if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) | 61 | if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042")) |
62 | return -EBUSY; | 62 | return -EBUSY; |
63 | 63 | ||
64 | i8042_reset = 1; | 64 | i8042_reset = I8042_RESET_ALWAYS; |
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 68f5f4a0f1e7..f4bfb4b2d50a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -510,6 +510,90 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { | |||
510 | { } | 510 | { } |
511 | }; | 511 | }; |
512 | 512 | ||
513 | /* | ||
514 | * On some Asus laptops, just running self tests cause problems. | ||
515 | */ | ||
516 | static const struct dmi_system_id i8042_dmi_noselftest_table[] = { | ||
517 | { | ||
518 | .matches = { | ||
519 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
520 | DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"), | ||
521 | }, | ||
522 | }, | ||
523 | { | ||
524 | .matches = { | ||
525 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
526 | DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"), | ||
527 | }, | ||
528 | }, | ||
529 | { | ||
530 | .matches = { | ||
531 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
532 | DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"), | ||
533 | }, | ||
534 | }, | ||
535 | { | ||
536 | .matches = { | ||
537 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
538 | DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"), | ||
539 | }, | ||
540 | }, | ||
541 | { | ||
542 | .matches = { | ||
543 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
544 | DMI_MATCH(DMI_PRODUCT_NAME, "R409L"), | ||
545 | }, | ||
546 | }, | ||
547 | { | ||
548 | .matches = { | ||
549 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
550 | DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"), | ||
551 | }, | ||
552 | }, | ||
553 | { | ||
554 | .matches = { | ||
555 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
556 | DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"), | ||
557 | }, | ||
558 | }, | ||
559 | { | ||
560 | .matches = { | ||
561 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
562 | DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"), | ||
563 | }, | ||
564 | }, | ||
565 | { | ||
566 | .matches = { | ||
567 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
568 | DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"), | ||
569 | }, | ||
570 | }, | ||
571 | { | ||
572 | .matches = { | ||
573 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
574 | DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"), | ||
575 | }, | ||
576 | }, | ||
577 | { | ||
578 | .matches = { | ||
579 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
580 | DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"), | ||
581 | }, | ||
582 | }, | ||
583 | { | ||
584 | .matches = { | ||
585 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
586 | DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"), | ||
587 | }, | ||
588 | }, | ||
589 | { | ||
590 | .matches = { | ||
591 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
592 | DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"), | ||
593 | }, | ||
594 | }, | ||
595 | { } | ||
596 | }; | ||
513 | static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { | 597 | static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { |
514 | { | 598 | { |
515 | /* MSI Wind U-100 */ | 599 | /* MSI Wind U-100 */ |
@@ -1072,12 +1156,18 @@ static int __init i8042_platform_init(void) | |||
1072 | return retval; | 1156 | return retval; |
1073 | 1157 | ||
1074 | #if defined(__ia64__) | 1158 | #if defined(__ia64__) |
1075 | i8042_reset = true; | 1159 | i8042_reset = I8042_RESET_ALWAYS; |
1076 | #endif | 1160 | #endif |
1077 | 1161 | ||
1078 | #ifdef CONFIG_X86 | 1162 | #ifdef CONFIG_X86 |
1079 | if (dmi_check_system(i8042_dmi_reset_table)) | 1163 | /* Honor module parameter when value is not default */ |
1080 | i8042_reset = true; | 1164 | if (i8042_reset == I8042_RESET_DEFAULT) { |
1165 | if (dmi_check_system(i8042_dmi_reset_table)) | ||
1166 | i8042_reset = I8042_RESET_ALWAYS; | ||
1167 | |||
1168 | if (dmi_check_system(i8042_dmi_noselftest_table)) | ||
1169 | i8042_reset = I8042_RESET_NEVER; | ||
1170 | } | ||
1081 | 1171 | ||
1082 | if (dmi_check_system(i8042_dmi_noloop_table)) | 1172 | if (dmi_check_system(i8042_dmi_noloop_table)) |
1083 | i8042_noloop = true; | 1173 | i8042_noloop = true; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 405252a884dd..89abfdb539ac 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -48,9 +48,39 @@ static bool i8042_unlock; | |||
48 | module_param_named(unlock, i8042_unlock, bool, 0); | 48 | module_param_named(unlock, i8042_unlock, bool, 0); |
49 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); | 49 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); |
50 | 50 | ||
51 | static bool i8042_reset; | 51 | enum i8042_controller_reset_mode { |
52 | module_param_named(reset, i8042_reset, bool, 0); | 52 | I8042_RESET_NEVER, |
53 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); | 53 | I8042_RESET_ALWAYS, |
54 | I8042_RESET_ON_S2RAM, | ||
55 | #define I8042_RESET_DEFAULT I8042_RESET_ON_S2RAM | ||
56 | }; | ||
57 | static enum i8042_controller_reset_mode i8042_reset = I8042_RESET_DEFAULT; | ||
58 | static int i8042_set_reset(const char *val, const struct kernel_param *kp) | ||
59 | { | ||
60 | enum i8042_controller_reset_mode *arg = kp->arg; | ||
61 | int error; | ||
62 | bool reset; | ||
63 | |||
64 | if (val) { | ||
65 | error = kstrtobool(val, &reset); | ||
66 | if (error) | ||
67 | return error; | ||
68 | } else { | ||
69 | reset = true; | ||
70 | } | ||
71 | |||
72 | *arg = reset ? I8042_RESET_ALWAYS : I8042_RESET_NEVER; | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static const struct kernel_param_ops param_ops_reset_param = { | ||
77 | .flags = KERNEL_PARAM_OPS_FL_NOARG, | ||
78 | .set = i8042_set_reset, | ||
79 | }; | ||
80 | #define param_check_reset_param(name, p) \ | ||
81 | __param_check(name, p, enum i8042_controller_reset_mode) | ||
82 | module_param_named(reset, i8042_reset, reset_param, 0); | ||
83 | MODULE_PARM_DESC(reset, "Reset controller on resume, cleanup or both"); | ||
54 | 84 | ||
55 | static bool i8042_direct; | 85 | static bool i8042_direct; |
56 | module_param_named(direct, i8042_direct, bool, 0); | 86 | module_param_named(direct, i8042_direct, bool, 0); |
@@ -1019,7 +1049,7 @@ static int i8042_controller_init(void) | |||
1019 | * Reset the controller and reset CRT to the original value set by BIOS. | 1049 | * Reset the controller and reset CRT to the original value set by BIOS. |
1020 | */ | 1050 | */ |
1021 | 1051 | ||
1022 | static void i8042_controller_reset(bool force_reset) | 1052 | static void i8042_controller_reset(bool s2r_wants_reset) |
1023 | { | 1053 | { |
1024 | i8042_flush(); | 1054 | i8042_flush(); |
1025 | 1055 | ||
@@ -1044,8 +1074,10 @@ static void i8042_controller_reset(bool force_reset) | |||
1044 | * Reset the controller if requested. | 1074 | * Reset the controller if requested. |
1045 | */ | 1075 | */ |
1046 | 1076 | ||
1047 | if (i8042_reset || force_reset) | 1077 | if (i8042_reset == I8042_RESET_ALWAYS || |
1078 | (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) { | ||
1048 | i8042_controller_selftest(); | 1079 | i8042_controller_selftest(); |
1080 | } | ||
1049 | 1081 | ||
1050 | /* | 1082 | /* |
1051 | * Restore the original control register setting. | 1083 | * Restore the original control register setting. |
@@ -1110,7 +1142,7 @@ static void i8042_dritek_enable(void) | |||
1110 | * before suspending. | 1142 | * before suspending. |
1111 | */ | 1143 | */ |
1112 | 1144 | ||
1113 | static int i8042_controller_resume(bool force_reset) | 1145 | static int i8042_controller_resume(bool s2r_wants_reset) |
1114 | { | 1146 | { |
1115 | int error; | 1147 | int error; |
1116 | 1148 | ||
@@ -1118,7 +1150,8 @@ static int i8042_controller_resume(bool force_reset) | |||
1118 | if (error) | 1150 | if (error) |
1119 | return error; | 1151 | return error; |
1120 | 1152 | ||
1121 | if (i8042_reset || force_reset) { | 1153 | if (i8042_reset == I8042_RESET_ALWAYS || |
1154 | (i8042_reset == I8042_RESET_ON_S2RAM && s2r_wants_reset)) { | ||
1122 | error = i8042_controller_selftest(); | 1155 | error = i8042_controller_selftest(); |
1123 | if (error) | 1156 | if (error) |
1124 | return error; | 1157 | return error; |
@@ -1195,7 +1228,7 @@ static int i8042_pm_resume_noirq(struct device *dev) | |||
1195 | 1228 | ||
1196 | static int i8042_pm_resume(struct device *dev) | 1229 | static int i8042_pm_resume(struct device *dev) |
1197 | { | 1230 | { |
1198 | bool force_reset; | 1231 | bool want_reset; |
1199 | int i; | 1232 | int i; |
1200 | 1233 | ||
1201 | for (i = 0; i < I8042_NUM_PORTS; i++) { | 1234 | for (i = 0; i < I8042_NUM_PORTS; i++) { |
@@ -1218,9 +1251,9 @@ static int i8042_pm_resume(struct device *dev) | |||
1218 | * off control to the platform firmware, otherwise we can simply restore | 1251 | * off control to the platform firmware, otherwise we can simply restore |
1219 | * the mode. | 1252 | * the mode. |
1220 | */ | 1253 | */ |
1221 | force_reset = pm_resume_via_firmware(); | 1254 | want_reset = pm_resume_via_firmware(); |
1222 | 1255 | ||
1223 | return i8042_controller_resume(force_reset); | 1256 | return i8042_controller_resume(want_reset); |
1224 | } | 1257 | } |
1225 | 1258 | ||
1226 | static int i8042_pm_thaw(struct device *dev) | 1259 | static int i8042_pm_thaw(struct device *dev) |
@@ -1482,7 +1515,7 @@ static int __init i8042_probe(struct platform_device *dev) | |||
1482 | 1515 | ||
1483 | i8042_platform_device = dev; | 1516 | i8042_platform_device = dev; |
1484 | 1517 | ||
1485 | if (i8042_reset) { | 1518 | if (i8042_reset == I8042_RESET_ALWAYS) { |
1486 | error = i8042_controller_selftest(); | 1519 | error = i8042_controller_selftest(); |
1487 | if (error) | 1520 | if (error) |
1488 | return error; | 1521 | return error; |
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index fb5fb9140ca9..552a3773f79d 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c | |||
@@ -157,6 +157,7 @@ struct mip4_ts { | |||
157 | 157 | ||
158 | char phys[32]; | 158 | char phys[32]; |
159 | char product_name[16]; | 159 | char product_name[16]; |
160 | char ic_name[4]; | ||
160 | 161 | ||
161 | unsigned int max_x; | 162 | unsigned int max_x; |
162 | unsigned int max_y; | 163 | unsigned int max_y; |
@@ -263,6 +264,18 @@ static int mip4_query_device(struct mip4_ts *ts) | |||
263 | dev_dbg(&ts->client->dev, "product name: %.*s\n", | 264 | dev_dbg(&ts->client->dev, "product name: %.*s\n", |
264 | (int)sizeof(ts->product_name), ts->product_name); | 265 | (int)sizeof(ts->product_name), ts->product_name); |
265 | 266 | ||
267 | /* IC name */ | ||
268 | cmd[0] = MIP4_R0_INFO; | ||
269 | cmd[1] = MIP4_R1_INFO_IC_NAME; | ||
270 | error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), | ||
271 | ts->ic_name, sizeof(ts->ic_name)); | ||
272 | if (error) | ||
273 | dev_warn(&ts->client->dev, | ||
274 | "Failed to retrieve IC name: %d\n", error); | ||
275 | else | ||
276 | dev_dbg(&ts->client->dev, "IC name: %.*s\n", | ||
277 | (int)sizeof(ts->ic_name), ts->ic_name); | ||
278 | |||
266 | /* Firmware version */ | 279 | /* Firmware version */ |
267 | error = mip4_get_fw_version(ts); | 280 | error = mip4_get_fw_version(ts); |
268 | if (error) | 281 | if (error) |
@@ -1326,7 +1339,7 @@ static ssize_t mip4_sysfs_read_hw_version(struct device *dev, | |||
1326 | * paired with current firmware in the chip. | 1339 | * paired with current firmware in the chip. |
1327 | */ | 1340 | */ |
1328 | count = snprintf(buf, PAGE_SIZE, "%.*s\n", | 1341 | count = snprintf(buf, PAGE_SIZE, "%.*s\n", |
1329 | (int)sizeof(ts->product_name), ts->product_name); | 1342 | (int)sizeof(ts->product_name), ts->product_name); |
1330 | 1343 | ||
1331 | mutex_unlock(&ts->input->mutex); | 1344 | mutex_unlock(&ts->input->mutex); |
1332 | 1345 | ||
@@ -1335,9 +1348,30 @@ static ssize_t mip4_sysfs_read_hw_version(struct device *dev, | |||
1335 | 1348 | ||
1336 | static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL); | 1349 | static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL); |
1337 | 1350 | ||
1351 | static ssize_t mip4_sysfs_read_ic_name(struct device *dev, | ||
1352 | struct device_attribute *attr, | ||
1353 | char *buf) | ||
1354 | { | ||
1355 | struct i2c_client *client = to_i2c_client(dev); | ||
1356 | struct mip4_ts *ts = i2c_get_clientdata(client); | ||
1357 | size_t count; | ||
1358 | |||
1359 | mutex_lock(&ts->input->mutex); | ||
1360 | |||
1361 | count = snprintf(buf, PAGE_SIZE, "%.*s\n", | ||
1362 | (int)sizeof(ts->ic_name), ts->ic_name); | ||
1363 | |||
1364 | mutex_unlock(&ts->input->mutex); | ||
1365 | |||
1366 | return count; | ||
1367 | } | ||
1368 | |||
1369 | static DEVICE_ATTR(ic_name, S_IRUGO, mip4_sysfs_read_ic_name, NULL); | ||
1370 | |||
1338 | static struct attribute *mip4_attrs[] = { | 1371 | static struct attribute *mip4_attrs[] = { |
1339 | &dev_attr_fw_version.attr, | 1372 | &dev_attr_fw_version.attr, |
1340 | &dev_attr_hw_version.attr, | 1373 | &dev_attr_hw_version.attr, |
1374 | &dev_attr_ic_name.attr, | ||
1341 | &dev_attr_update_fw.attr, | 1375 | &dev_attr_update_fw.attr, |
1342 | NULL, | 1376 | NULL, |
1343 | }; | 1377 | }; |
@@ -1538,6 +1572,6 @@ static struct i2c_driver mip4_driver = { | |||
1538 | module_i2c_driver(mip4_driver); | 1572 | module_i2c_driver(mip4_driver); |
1539 | 1573 | ||
1540 | MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen"); | 1574 | MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen"); |
1541 | MODULE_VERSION("2016.03.12"); | 1575 | MODULE_VERSION("2016.09.28"); |
1542 | MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>"); | 1576 | MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>"); |
1543 | MODULE_LICENSE("GPL"); | 1577 | MODULE_LICENSE("GPL"); |