diff options
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/alps.c | 368 | ||||
-rw-r--r-- | drivers/input/mouse/alps.h | 78 | ||||
-rw-r--r-- | drivers/input/mouse/elan_i2c.h | 2 | ||||
-rw-r--r-- | drivers/input/mouse/elan_i2c_core.c | 15 | ||||
-rw-r--r-- | drivers/input/mouse/elan_i2c_i2c.c | 10 | ||||
-rw-r--r-- | drivers/input/mouse/lifebook.c | 6 | ||||
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 40 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.c | 42 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 1 |
9 files changed, 505 insertions, 57 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index da3af8db697c..e6708f6efb4d 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -153,10 +153,18 @@ static const struct alps_protocol_info alps_v7_protocol_data = { | |||
153 | ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT | 153 | ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT |
154 | }; | 154 | }; |
155 | 155 | ||
156 | static const struct alps_protocol_info alps_v8_protocol_data = { | ||
157 | ALPS_PROTO_V8, 0x18, 0x18, 0 | ||
158 | }; | ||
159 | |||
156 | static void alps_set_abs_params_st(struct alps_data *priv, | 160 | static void alps_set_abs_params_st(struct alps_data *priv, |
157 | struct input_dev *dev1); | 161 | struct input_dev *dev1); |
158 | static void alps_set_abs_params_mt(struct alps_data *priv, | 162 | static void alps_set_abs_params_mt(struct alps_data *priv, |
159 | struct input_dev *dev1); | 163 | struct input_dev *dev1); |
164 | static void alps_set_abs_params_v7(struct alps_data *priv, | ||
165 | struct input_dev *dev1); | ||
166 | static void alps_set_abs_params_ss4_v2(struct alps_data *priv, | ||
167 | struct input_dev *dev1); | ||
160 | 168 | ||
161 | /* Packet formats are described in Documentation/input/alps.txt */ | 169 | /* Packet formats are described in Documentation/input/alps.txt */ |
162 | 170 | ||
@@ -1093,6 +1101,176 @@ static void alps_process_packet_v7(struct psmouse *psmouse) | |||
1093 | alps_process_touchpad_packet_v7(psmouse); | 1101 | alps_process_touchpad_packet_v7(psmouse); |
1094 | } | 1102 | } |
1095 | 1103 | ||
1104 | static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte) | ||
1105 | { | ||
1106 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; | ||
1107 | |||
1108 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && | ||
1109 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { | ||
1110 | pkt_id = SS4_PACKET_ID_IDLE; | ||
1111 | } else if (!(byte[3] & 0x10)) { | ||
1112 | pkt_id = SS4_PACKET_ID_ONE; | ||
1113 | } else if (!(byte[3] & 0x20)) { | ||
1114 | pkt_id = SS4_PACKET_ID_TWO; | ||
1115 | } else { | ||
1116 | pkt_id = SS4_PACKET_ID_MULTI; | ||
1117 | } | ||
1118 | |||
1119 | return pkt_id; | ||
1120 | } | ||
1121 | |||
1122 | static int alps_decode_ss4_v2(struct alps_fields *f, | ||
1123 | unsigned char *p, struct psmouse *psmouse) | ||
1124 | { | ||
1125 | struct alps_data *priv = psmouse->private; | ||
1126 | unsigned char pkt_id; | ||
1127 | unsigned int no_data_x, no_data_y; | ||
1128 | |||
1129 | pkt_id = alps_get_pkt_id_ss4_v2(p); | ||
1130 | |||
1131 | /* Current packet is 1Finger coordinate packet */ | ||
1132 | switch (pkt_id) { | ||
1133 | case SS4_PACKET_ID_ONE: | ||
1134 | f->mt[0].x = SS4_1F_X_V2(p); | ||
1135 | f->mt[0].y = SS4_1F_Y_V2(p); | ||
1136 | f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f; | ||
1137 | f->fingers = 1; | ||
1138 | f->first_mp = 0; | ||
1139 | f->is_mp = 0; | ||
1140 | break; | ||
1141 | |||
1142 | case SS4_PACKET_ID_TWO: | ||
1143 | if (priv->flags & ALPS_BUTTONPAD) { | ||
1144 | f->mt[0].x = SS4_BTL_MF_X_V2(p, 0); | ||
1145 | f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0); | ||
1146 | f->mt[1].x = SS4_BTL_MF_X_V2(p, 1); | ||
1147 | f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1); | ||
1148 | } else { | ||
1149 | f->mt[0].x = SS4_STD_MF_X_V2(p, 0); | ||
1150 | f->mt[0].y = SS4_STD_MF_Y_V2(p, 0); | ||
1151 | f->mt[1].x = SS4_STD_MF_X_V2(p, 1); | ||
1152 | f->mt[1].y = SS4_STD_MF_Y_V2(p, 1); | ||
1153 | } | ||
1154 | f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0; | ||
1155 | |||
1156 | if (SS4_IS_MF_CONTINUE(p)) { | ||
1157 | f->first_mp = 1; | ||
1158 | } else { | ||
1159 | f->fingers = 2; | ||
1160 | f->first_mp = 0; | ||
1161 | } | ||
1162 | f->is_mp = 0; | ||
1163 | |||
1164 | break; | ||
1165 | |||
1166 | case SS4_PACKET_ID_MULTI: | ||
1167 | if (priv->flags & ALPS_BUTTONPAD) { | ||
1168 | f->mt[2].x = SS4_BTL_MF_X_V2(p, 0); | ||
1169 | f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0); | ||
1170 | f->mt[3].x = SS4_BTL_MF_X_V2(p, 1); | ||
1171 | f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1); | ||
1172 | no_data_x = SS4_MFPACKET_NO_AX_BL; | ||
1173 | no_data_y = SS4_MFPACKET_NO_AY_BL; | ||
1174 | } else { | ||
1175 | f->mt[2].x = SS4_STD_MF_X_V2(p, 0); | ||
1176 | f->mt[2].y = SS4_STD_MF_Y_V2(p, 0); | ||
1177 | f->mt[3].x = SS4_STD_MF_X_V2(p, 1); | ||
1178 | f->mt[3].y = SS4_STD_MF_Y_V2(p, 1); | ||
1179 | no_data_x = SS4_MFPACKET_NO_AX; | ||
1180 | no_data_y = SS4_MFPACKET_NO_AY; | ||
1181 | } | ||
1182 | |||
1183 | f->first_mp = 0; | ||
1184 | f->is_mp = 1; | ||
1185 | |||
1186 | if (SS4_IS_5F_DETECTED(p)) { | ||
1187 | f->fingers = 5; | ||
1188 | } else if (f->mt[3].x == no_data_x && | ||
1189 | f->mt[3].y == no_data_y) { | ||
1190 | f->mt[3].x = 0; | ||
1191 | f->mt[3].y = 0; | ||
1192 | f->fingers = 3; | ||
1193 | } else { | ||
1194 | f->fingers = 4; | ||
1195 | } | ||
1196 | break; | ||
1197 | |||
1198 | case SS4_PACKET_ID_IDLE: | ||
1199 | default: | ||
1200 | memset(f, 0, sizeof(struct alps_fields)); | ||
1201 | break; | ||
1202 | } | ||
1203 | |||
1204 | f->left = !!(SS4_BTN_V2(p) & 0x01); | ||
1205 | if (!(priv->flags & ALPS_BUTTONPAD)) { | ||
1206 | f->right = !!(SS4_BTN_V2(p) & 0x02); | ||
1207 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | ||
1208 | } | ||
1209 | |||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | ||
1214 | { | ||
1215 | struct alps_data *priv = psmouse->private; | ||
1216 | unsigned char *packet = psmouse->packet; | ||
1217 | struct input_dev *dev = psmouse->dev; | ||
1218 | struct alps_fields *f = &priv->f; | ||
1219 | |||
1220 | memset(f, 0, sizeof(struct alps_fields)); | ||
1221 | priv->decode_fields(f, packet, psmouse); | ||
1222 | if (priv->multi_packet) { | ||
1223 | /* | ||
1224 | * Sometimes the first packet will indicate a multi-packet | ||
1225 | * sequence, but sometimes the next multi-packet would not | ||
1226 | * come. Check for this, and when it happens process the | ||
1227 | * position packet as usual. | ||
1228 | */ | ||
1229 | if (f->is_mp) { | ||
1230 | /* Now process the 1st packet */ | ||
1231 | priv->decode_fields(f, priv->multi_data, psmouse); | ||
1232 | } else { | ||
1233 | priv->multi_packet = 0; | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | /* | ||
1238 | * "f.is_mp" would always be '0' after merging the 1st and 2nd packet. | ||
1239 | * When it is set, it means 2nd packet comes without 1st packet come. | ||
1240 | */ | ||
1241 | if (f->is_mp) | ||
1242 | return; | ||
1243 | |||
1244 | /* Save the first packet */ | ||
1245 | if (!priv->multi_packet && f->first_mp) { | ||
1246 | priv->multi_packet = 1; | ||
1247 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); | ||
1248 | return; | ||
1249 | } | ||
1250 | |||
1251 | priv->multi_packet = 0; | ||
1252 | |||
1253 | alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4); | ||
1254 | |||
1255 | input_mt_report_finger_count(dev, f->fingers); | ||
1256 | |||
1257 | input_report_key(dev, BTN_LEFT, f->left); | ||
1258 | input_report_key(dev, BTN_RIGHT, f->right); | ||
1259 | input_report_key(dev, BTN_MIDDLE, f->middle); | ||
1260 | |||
1261 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | ||
1262 | input_sync(dev); | ||
1263 | } | ||
1264 | |||
1265 | static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) | ||
1266 | { | ||
1267 | if (psmouse->pktcnt == 4 && ((psmouse->packet[3] & 0x08) != 0x08)) | ||
1268 | return false; | ||
1269 | if (psmouse->pktcnt == 6 && ((psmouse->packet[5] & 0x10) != 0x0)) | ||
1270 | return false; | ||
1271 | return true; | ||
1272 | } | ||
1273 | |||
1096 | static DEFINE_MUTEX(alps_mutex); | 1274 | static DEFINE_MUTEX(alps_mutex); |
1097 | 1275 | ||
1098 | static void alps_register_bare_ps2_mouse(struct work_struct *work) | 1276 | static void alps_register_bare_ps2_mouse(struct work_struct *work) |
@@ -1314,8 +1492,12 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1314 | * a device connected to the external PS/2 port. Because bare PS/2 | 1492 | * a device connected to the external PS/2 port. Because bare PS/2 |
1315 | * protocol does not have enough constant bits to self-synchronize | 1493 | * protocol does not have enough constant bits to self-synchronize |
1316 | * properly we only do this if the device is fully synchronized. | 1494 | * properly we only do this if the device is fully synchronized. |
1495 | * Can not distinguish V8's first byte from PS/2 packet's | ||
1317 | */ | 1496 | */ |
1318 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { | 1497 | if (priv->proto_version != ALPS_PROTO_V8 && |
1498 | !psmouse->out_of_sync_cnt && | ||
1499 | (psmouse->packet[0] & 0xc8) == 0x08) { | ||
1500 | |||
1319 | if (psmouse->pktcnt == 3) { | 1501 | if (psmouse->pktcnt == 3) { |
1320 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, | 1502 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
1321 | true); | 1503 | true); |
@@ -1363,8 +1545,10 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1363 | return PSMOUSE_BAD_DATA; | 1545 | return PSMOUSE_BAD_DATA; |
1364 | } | 1546 | } |
1365 | 1547 | ||
1366 | if (priv->proto_version == ALPS_PROTO_V7 && | 1548 | if ((priv->proto_version == ALPS_PROTO_V7 && |
1367 | !alps_is_valid_package_v7(psmouse)) { | 1549 | !alps_is_valid_package_v7(psmouse)) || |
1550 | (priv->proto_version == ALPS_PROTO_V8 && | ||
1551 | !alps_is_valid_package_ss4_v2(psmouse))) { | ||
1368 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 1552 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
1369 | psmouse->pktcnt - 1, | 1553 | psmouse->pktcnt - 1, |
1370 | psmouse->packet[psmouse->pktcnt - 1]); | 1554 | psmouse->packet[psmouse->pktcnt - 1]); |
@@ -2139,6 +2323,88 @@ error: | |||
2139 | return -1; | 2323 | return -1; |
2140 | } | 2324 | } |
2141 | 2325 | ||
2326 | static int alps_get_otp_values_ss4_v2(struct psmouse *psmouse, | ||
2327 | unsigned char index, unsigned char otp[]) | ||
2328 | { | ||
2329 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
2330 | |||
2331 | switch (index) { | ||
2332 | case 0: | ||
2333 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2334 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2335 | ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO)) | ||
2336 | return -1; | ||
2337 | |||
2338 | break; | ||
2339 | |||
2340 | case 1: | ||
2341 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | ||
2342 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | ||
2343 | ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO)) | ||
2344 | return -1; | ||
2345 | |||
2346 | break; | ||
2347 | } | ||
2348 | |||
2349 | return 0; | ||
2350 | } | ||
2351 | |||
2352 | static int alps_update_device_area_ss4_v2(unsigned char otp[][4], | ||
2353 | struct alps_data *priv) | ||
2354 | { | ||
2355 | int num_x_electrode; | ||
2356 | int num_y_electrode; | ||
2357 | int x_pitch, y_pitch, x_phys, y_phys; | ||
2358 | |||
2359 | num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); | ||
2360 | num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); | ||
2361 | |||
2362 | priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE; | ||
2363 | priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; | ||
2364 | |||
2365 | x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM; | ||
2366 | y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM; | ||
2367 | |||
2368 | x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */ | ||
2369 | y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */ | ||
2370 | |||
2371 | priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */ | ||
2372 | priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */ | ||
2373 | |||
2374 | return 0; | ||
2375 | } | ||
2376 | |||
2377 | static int alps_update_btn_info_ss4_v2(unsigned char otp[][4], | ||
2378 | struct alps_data *priv) | ||
2379 | { | ||
2380 | unsigned char is_btnless; | ||
2381 | |||
2382 | is_btnless = (otp[1][1] >> 3) & 0x01; | ||
2383 | |||
2384 | if (is_btnless) | ||
2385 | priv->flags |= ALPS_BUTTONPAD; | ||
2386 | |||
2387 | return 0; | ||
2388 | } | ||
2389 | |||
2390 | static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, | ||
2391 | struct alps_data *priv) | ||
2392 | { | ||
2393 | unsigned char otp[2][4]; | ||
2394 | |||
2395 | memset(otp, 0, sizeof(otp)); | ||
2396 | |||
2397 | if (alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]) || | ||
2398 | alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0])) | ||
2399 | return -1; | ||
2400 | |||
2401 | alps_update_device_area_ss4_v2(otp, priv); | ||
2402 | |||
2403 | alps_update_btn_info_ss4_v2(otp, priv); | ||
2404 | |||
2405 | return 0; | ||
2406 | } | ||
2407 | |||
2142 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, | 2408 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, |
2143 | struct alps_data *priv) | 2409 | struct alps_data *priv) |
2144 | { | 2410 | { |
@@ -2231,6 +2497,35 @@ error: | |||
2231 | return ret; | 2497 | return ret; |
2232 | } | 2498 | } |
2233 | 2499 | ||
2500 | static int alps_hw_init_ss4_v2(struct psmouse *psmouse) | ||
2501 | { | ||
2502 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
2503 | char param[2] = {0x64, 0x28}; | ||
2504 | int ret = -1; | ||
2505 | |||
2506 | /* enter absolute mode */ | ||
2507 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2508 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2509 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | ||
2510 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) { | ||
2511 | goto error; | ||
2512 | } | ||
2513 | |||
2514 | /* T.B.D. Decread noise packet number, delete in the future */ | ||
2515 | if (alps_exit_command_mode(psmouse) || | ||
2516 | alps_enter_command_mode(psmouse) || | ||
2517 | alps_command_mode_write_reg(psmouse, 0x001D, 0x20)) { | ||
2518 | goto error; | ||
2519 | } | ||
2520 | alps_exit_command_mode(psmouse); | ||
2521 | |||
2522 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
2523 | |||
2524 | error: | ||
2525 | alps_exit_command_mode(psmouse); | ||
2526 | return ret; | ||
2527 | } | ||
2528 | |||
2234 | static int alps_set_protocol(struct psmouse *psmouse, | 2529 | static int alps_set_protocol(struct psmouse *psmouse, |
2235 | struct alps_data *priv, | 2530 | struct alps_data *priv, |
2236 | const struct alps_protocol_info *protocol) | 2531 | const struct alps_protocol_info *protocol) |
@@ -2320,7 +2615,7 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2320 | priv->hw_init = alps_hw_init_v7; | 2615 | priv->hw_init = alps_hw_init_v7; |
2321 | priv->process_packet = alps_process_packet_v7; | 2616 | priv->process_packet = alps_process_packet_v7; |
2322 | priv->decode_fields = alps_decode_packet_v7; | 2617 | priv->decode_fields = alps_decode_packet_v7; |
2323 | priv->set_abs_params = alps_set_abs_params_mt; | 2618 | priv->set_abs_params = alps_set_abs_params_v7; |
2324 | priv->nibble_commands = alps_v3_nibble_commands; | 2619 | priv->nibble_commands = alps_v3_nibble_commands; |
2325 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2620 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2326 | priv->x_max = 0xfff; | 2621 | priv->x_max = 0xfff; |
@@ -2330,6 +2625,19 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2330 | priv->flags |= ALPS_BUTTONPAD; | 2625 | priv->flags |= ALPS_BUTTONPAD; |
2331 | 2626 | ||
2332 | break; | 2627 | break; |
2628 | |||
2629 | case ALPS_PROTO_V8: | ||
2630 | priv->hw_init = alps_hw_init_ss4_v2; | ||
2631 | priv->process_packet = alps_process_packet_ss4_v2; | ||
2632 | priv->decode_fields = alps_decode_ss4_v2; | ||
2633 | priv->set_abs_params = alps_set_abs_params_ss4_v2; | ||
2634 | priv->nibble_commands = alps_v3_nibble_commands; | ||
2635 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
2636 | |||
2637 | if (alps_set_defaults_ss4_v2(psmouse, priv)) | ||
2638 | return -EIO; | ||
2639 | |||
2640 | break; | ||
2333 | } | 2641 | } |
2334 | 2642 | ||
2335 | return 0; | 2643 | return 0; |
@@ -2398,6 +2706,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2398 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && | 2706 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && |
2399 | ec[2] >= 0x90 && ec[2] <= 0x9d) { | 2707 | ec[2] >= 0x90 && ec[2] <= 0x9d) { |
2400 | protocol = &alps_v3_protocol_data; | 2708 | protocol = &alps_v3_protocol_data; |
2709 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && | ||
2710 | e7[2] == 0x14 && ec[1] == 0x02) { | ||
2711 | protocol = &alps_v8_protocol_data; | ||
2401 | } else { | 2712 | } else { |
2402 | psmouse_dbg(psmouse, | 2713 | psmouse_dbg(psmouse, |
2403 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2714 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
@@ -2446,10 +2757,11 @@ static void alps_set_abs_params_st(struct alps_data *priv, | |||
2446 | { | 2757 | { |
2447 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); | 2758 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); |
2448 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); | 2759 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); |
2760 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2449 | } | 2761 | } |
2450 | 2762 | ||
2451 | static void alps_set_abs_params_mt(struct alps_data *priv, | 2763 | static void alps_set_abs_params_mt_common(struct alps_data *priv, |
2452 | struct input_dev *dev1) | 2764 | struct input_dev *dev1) |
2453 | { | 2765 | { |
2454 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); | 2766 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); |
2455 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); | 2767 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); |
@@ -2457,15 +2769,44 @@ static void alps_set_abs_params_mt(struct alps_data *priv, | |||
2457 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); | 2769 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); |
2458 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); | 2770 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); |
2459 | 2771 | ||
2460 | input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | | ||
2461 | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | ||
2462 | |||
2463 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); | 2772 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); |
2464 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); | 2773 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); |
2774 | } | ||
2775 | |||
2776 | static void alps_set_abs_params_mt(struct alps_data *priv, | ||
2777 | struct input_dev *dev1) | ||
2778 | { | ||
2779 | alps_set_abs_params_mt_common(priv, dev1); | ||
2780 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2781 | |||
2782 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
2783 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
2784 | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | ||
2785 | } | ||
2786 | |||
2787 | static void alps_set_abs_params_v7(struct alps_data *priv, | ||
2788 | struct input_dev *dev1) | ||
2789 | { | ||
2790 | alps_set_abs_params_mt_common(priv, dev1); | ||
2791 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
2792 | |||
2793 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
2794 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
2795 | INPUT_MT_TRACK); | ||
2796 | |||
2797 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
2798 | } | ||
2799 | |||
2800 | static void alps_set_abs_params_ss4_v2(struct alps_data *priv, | ||
2801 | struct input_dev *dev1) | ||
2802 | { | ||
2803 | alps_set_abs_params_mt_common(priv, dev1); | ||
2804 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2805 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
2465 | 2806 | ||
2466 | /* V7 is real multi-touch */ | 2807 | input_mt_init_slots(dev1, MAX_TOUCHES, |
2467 | if (priv->proto_version == ALPS_PROTO_V7) | 2808 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | |
2468 | clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | 2809 | INPUT_MT_TRACK); |
2469 | } | 2810 | } |
2470 | 2811 | ||
2471 | int alps_init(struct psmouse *psmouse) | 2812 | int alps_init(struct psmouse *psmouse) |
@@ -2498,9 +2839,6 @@ int alps_init(struct psmouse *psmouse) | |||
2498 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 2839 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
2499 | 2840 | ||
2500 | priv->set_abs_params(priv, dev1); | 2841 | priv->set_abs_params(priv, dev1); |
2501 | /* No pressure on V7 */ | ||
2502 | if (priv->proto_version != ALPS_PROTO_V7) | ||
2503 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2504 | 2842 | ||
2505 | if (priv->flags & ALPS_WHEEL) { | 2843 | if (priv->flags & ALPS_WHEEL) { |
2506 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 2844 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 02513c0502fc..6dfdccc3a7c6 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -22,14 +22,90 @@ | |||
22 | #define ALPS_PROTO_V5 0x500 | 22 | #define ALPS_PROTO_V5 0x500 |
23 | #define ALPS_PROTO_V6 0x600 | 23 | #define ALPS_PROTO_V6 0x600 |
24 | #define ALPS_PROTO_V7 0x700 /* t3btl t4s */ | 24 | #define ALPS_PROTO_V7 0x700 /* t3btl t4s */ |
25 | #define ALPS_PROTO_V8 0x800 /* SS4btl SS4s */ | ||
25 | 26 | ||
26 | #define MAX_TOUCHES 2 | 27 | #define MAX_TOUCHES 4 |
27 | 28 | ||
28 | #define DOLPHIN_COUNT_PER_ELECTRODE 64 | 29 | #define DOLPHIN_COUNT_PER_ELECTRODE 64 |
29 | #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ | 30 | #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ |
30 | #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ | 31 | #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ |
31 | 32 | ||
32 | /* | 33 | /* |
34 | * enum SS4_PACKET_ID - defines the packet type for V8 | ||
35 | * SS4_PACKET_ID_IDLE: There's no finger and no button activity. | ||
36 | * SS4_PACKET_ID_ONE: There's one finger on touchpad | ||
37 | * or there's button activities. | ||
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 | ||
40 | */ | ||
41 | enum SS4_PACKET_ID { | ||
42 | SS4_PACKET_ID_IDLE = 0, | ||
43 | SS4_PACKET_ID_ONE, | ||
44 | SS4_PACKET_ID_TWO, | ||
45 | SS4_PACKET_ID_MULTI, | ||
46 | }; | ||
47 | |||
48 | #define SS4_COUNT_PER_ELECTRODE 256 | ||
49 | #define SS4_NUMSENSOR_XOFFSET 7 | ||
50 | #define SS4_NUMSENSOR_YOFFSET 7 | ||
51 | #define SS4_MIN_PITCH_MM 50 | ||
52 | |||
53 | #define SS4_MASK_NORMAL_BUTTONS 0x07 | ||
54 | |||
55 | #define SS4_1F_X_V2(_b) ((_b[0] & 0x0007) | \ | ||
56 | ((_b[1] << 3) & 0x0078) | \ | ||
57 | ((_b[1] << 2) & 0x0380) | \ | ||
58 | ((_b[2] << 5) & 0x1C00) \ | ||
59 | ) | ||
60 | |||
61 | #define SS4_1F_Y_V2(_b) (((_b[2]) & 0x000F) | \ | ||
62 | ((_b[3] >> 2) & 0x0030) | \ | ||
63 | ((_b[4] << 6) & 0x03C0) | \ | ||
64 | ((_b[4] << 5) & 0x0C00) \ | ||
65 | ) | ||
66 | |||
67 | #define SS4_1F_Z_V2(_b) (((_b[5]) & 0x0F) | \ | ||
68 | ((_b[5] >> 1) & 0x70) | \ | ||
69 | ((_b[4]) & 0x80) \ | ||
70 | ) | ||
71 | |||
72 | #define SS4_1F_LFB_V2(_b) (((_b[2] >> 4) & 0x01) == 0x01) | ||
73 | |||
74 | #define SS4_MF_LF_V2(_b, _i) ((_b[1 + (_i) * 3] & 0x0004) == 0x0004) | ||
75 | |||
76 | #define SS4_BTN_V2(_b) ((_b[0] >> 5) & SS4_MASK_NORMAL_BUTTONS) | ||
77 | |||
78 | #define SS4_STD_MF_X_V2(_b, _i) (((_b[0 + (_i) * 3] << 5) & 0x00E0) | \ | ||
79 | ((_b[1 + _i * 3] << 5) & 0x1F00) \ | ||
80 | ) | ||
81 | |||
82 | #define SS4_STD_MF_Y_V2(_b, _i) (((_b[1 + (_i) * 3] << 3) & 0x0010) | \ | ||
83 | ((_b[2 + (_i) * 3] << 5) & 0x01E0) | \ | ||
84 | ((_b[2 + (_i) * 3] << 4) & 0x0E00) \ | ||
85 | ) | ||
86 | |||
87 | #define SS4_BTL_MF_X_V2(_b, _i) (SS4_STD_MF_X_V2(_b, _i) | \ | ||
88 | ((_b[0 + (_i) * 3] >> 3) & 0x0010) \ | ||
89 | ) | ||
90 | |||
91 | #define SS4_BTL_MF_Y_V2(_b, _i) (SS4_STD_MF_Y_V2(_b, _i) | \ | ||
92 | ((_b[0 + (_i) * 3] >> 3) & 0x0008) \ | ||
93 | ) | ||
94 | |||
95 | #define SS4_MF_Z_V2(_b, _i) (((_b[1 + (_i) * 3]) & 0x0001) | \ | ||
96 | ((_b[1 + (_i) * 3] >> 1) & 0x0002) \ | ||
97 | ) | ||
98 | |||
99 | #define SS4_IS_MF_CONTINUE(_b) ((_b[2] & 0x10) == 0x10) | ||
100 | #define SS4_IS_5F_DETECTED(_b) ((_b[2] & 0x10) == 0x10) | ||
101 | |||
102 | |||
103 | #define SS4_MFPACKET_NO_AX 8160 /* X-Coordinate value */ | ||
104 | #define SS4_MFPACKET_NO_AY 4080 /* Y-Coordinate value */ | ||
105 | #define SS4_MFPACKET_NO_AX_BL 8176 /* Buttonless X-Coordinate value */ | ||
106 | #define SS4_MFPACKET_NO_AY_BL 4088 /* Buttonless Y-Coordinate value */ | ||
107 | |||
108 | /* | ||
33 | * enum V7_PACKET_ID - defines the packet type for V7 | 109 | * enum V7_PACKET_ID - defines the packet type for V7 |
34 | * V7_PACKET_ID_IDLE: There's no finger and no button activity. | 110 | * V7_PACKET_ID_IDLE: There's no finger and no button activity. |
35 | * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad | 111 | * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad |
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index e100c1b31597..9b2dc015f20c 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h | |||
@@ -17,7 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifndef _ELAN_I2C_H | 19 | #ifndef _ELAN_I2C_H |
20 | #define _ELAN_i2C_H | 20 | #define _ELAN_I2C_H |
21 | 21 | ||
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | 23 | ||
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 7ce8bfe22d7e..375d98f47483 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c | |||
@@ -99,7 +99,7 @@ static int elan_enable_power(struct elan_tp_data *data) | |||
99 | error = regulator_enable(data->vcc); | 99 | error = regulator_enable(data->vcc); |
100 | if (error) { | 100 | if (error) { |
101 | dev_err(&data->client->dev, | 101 | dev_err(&data->client->dev, |
102 | "Failed to enable regulator: %d\n", error); | 102 | "failed to enable regulator: %d\n", error); |
103 | return error; | 103 | return error; |
104 | } | 104 | } |
105 | 105 | ||
@@ -111,6 +111,7 @@ static int elan_enable_power(struct elan_tp_data *data) | |||
111 | msleep(30); | 111 | msleep(30); |
112 | } while (--repeat > 0); | 112 | } while (--repeat > 0); |
113 | 113 | ||
114 | dev_err(&data->client->dev, "failed to enable power: %d\n", error); | ||
114 | return error; | 115 | return error; |
115 | } | 116 | } |
116 | 117 | ||
@@ -125,7 +126,7 @@ static int elan_disable_power(struct elan_tp_data *data) | |||
125 | error = regulator_disable(data->vcc); | 126 | error = regulator_disable(data->vcc); |
126 | if (error) { | 127 | if (error) { |
127 | dev_err(&data->client->dev, | 128 | dev_err(&data->client->dev, |
128 | "Failed to disable regulator: %d\n", | 129 | "failed to disable regulator: %d\n", |
129 | error); | 130 | error); |
130 | /* Attempt to power the chip back up */ | 131 | /* Attempt to power the chip back up */ |
131 | data->ops->power_control(data->client, true); | 132 | data->ops->power_control(data->client, true); |
@@ -138,6 +139,7 @@ static int elan_disable_power(struct elan_tp_data *data) | |||
138 | msleep(30); | 139 | msleep(30); |
139 | } while (--repeat > 0); | 140 | } while (--repeat > 0); |
140 | 141 | ||
142 | dev_err(&data->client->dev, "failed to disable power: %d\n", error); | ||
141 | return error; | 143 | return error; |
142 | } | 144 | } |
143 | 145 | ||
@@ -196,7 +198,6 @@ static int elan_initialize(struct elan_tp_data *data) | |||
196 | if (!error) | 198 | if (!error) |
197 | return 0; | 199 | return 0; |
198 | 200 | ||
199 | repeat--; | ||
200 | msleep(30); | 201 | msleep(30); |
201 | } while (--repeat > 0); | 202 | } while (--repeat > 0); |
202 | 203 | ||
@@ -1084,16 +1085,18 @@ static int __maybe_unused elan_resume(struct device *dev) | |||
1084 | } | 1085 | } |
1085 | 1086 | ||
1086 | error = elan_enable_power(data); | 1087 | error = elan_enable_power(data); |
1087 | if (error) | 1088 | if (error) { |
1088 | dev_err(dev, "power up when resuming failed: %d\n", error); | 1089 | dev_err(dev, "power up when resuming failed: %d\n", error); |
1090 | goto err; | ||
1091 | } | ||
1089 | 1092 | ||
1090 | error = elan_initialize(data); | 1093 | error = elan_initialize(data); |
1091 | if (error) | 1094 | if (error) |
1092 | dev_err(dev, "initialize when resuming failed: %d\n", error); | 1095 | dev_err(dev, "initialize when resuming failed: %d\n", error); |
1093 | 1096 | ||
1097 | err: | ||
1094 | enable_irq(data->client->irq); | 1098 | enable_irq(data->client->irq); |
1095 | 1099 | return error; | |
1096 | return 0; | ||
1097 | } | 1100 | } |
1098 | 1101 | ||
1099 | static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume); | 1102 | static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume); |
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 029941f861af..6cf0def6d35e 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c | |||
@@ -117,7 +117,15 @@ static int elan_i2c_write_cmd(struct i2c_client *client, u16 reg, u16 cmd) | |||
117 | int ret; | 117 | int ret; |
118 | 118 | ||
119 | ret = i2c_transfer(client->adapter, &msg, 1); | 119 | ret = i2c_transfer(client->adapter, &msg, 1); |
120 | return ret == 1 ? 0 : (ret < 0 ? ret : -EIO); | 120 | if (ret != 1) { |
121 | if (ret >= 0) | ||
122 | ret = -EIO; | ||
123 | dev_err(&client->dev, "writing cmd (0x%04x) failed: %d\n", | ||
124 | reg, ret); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
121 | } | 129 | } |
122 | 130 | ||
123 | static int elan_i2c_initialize(struct i2c_client *client) | 131 | static int elan_i2c_initialize(struct i2c_client *client) |
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 23222dd5a66f..e5ed216824e9 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -256,8 +256,8 @@ static void lifebook_disconnect(struct psmouse *psmouse) | |||
256 | 256 | ||
257 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) | 257 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
258 | { | 258 | { |
259 | if (!lifebook_present) | 259 | if (!lifebook_present) |
260 | return -1; | 260 | return -1; |
261 | 261 | ||
262 | if (desired_serio_phys && | 262 | if (desired_serio_phys && |
263 | strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) | 263 | strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) |
@@ -268,7 +268,7 @@ int lifebook_detect(struct psmouse *psmouse, bool set_properties) | |||
268 | psmouse->name = "Lifebook TouchScreen"; | 268 | psmouse->name = "Lifebook TouchScreen"; |
269 | } | 269 | } |
270 | 270 | ||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | 273 | ||
274 | static int lifebook_create_relative_device(struct psmouse *psmouse) | 274 | static int lifebook_create_relative_device(struct psmouse *psmouse) |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 8bc61237bc1b..27057df7ba74 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -474,19 +474,45 @@ static int psmouse_poll(struct psmouse *psmouse) | |||
474 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); | 474 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); |
475 | } | 475 | } |
476 | 476 | ||
477 | static bool psmouse_check_pnp_id(const char *id, const char * const ids[]) | ||
478 | { | ||
479 | int i; | ||
480 | |||
481 | for (i = 0; ids[i]; i++) | ||
482 | if (!strcasecmp(id, ids[i])) | ||
483 | return true; | ||
484 | |||
485 | return false; | ||
486 | } | ||
487 | |||
477 | /* | 488 | /* |
478 | * psmouse_matches_pnp_id - check if psmouse matches one of the passed in ids. | 489 | * psmouse_matches_pnp_id - check if psmouse matches one of the passed in ids. |
479 | */ | 490 | */ |
480 | bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) | 491 | bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) |
481 | { | 492 | { |
482 | int i; | 493 | struct serio *serio = psmouse->ps2dev.serio; |
483 | 494 | char *p, *fw_id_copy, *save_ptr; | |
484 | if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) | 495 | bool found = false; |
485 | for (i = 0; ids[i]; i++) | 496 | |
486 | if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i])) | 497 | if (strncmp(serio->firmware_id, "PNP: ", 5)) |
487 | return true; | 498 | return false; |
499 | |||
500 | fw_id_copy = kstrndup(&serio->firmware_id[5], | ||
501 | sizeof(serio->firmware_id) - 5, | ||
502 | GFP_KERNEL); | ||
503 | if (!fw_id_copy) | ||
504 | return false; | ||
505 | |||
506 | save_ptr = fw_id_copy; | ||
507 | while ((p = strsep(&fw_id_copy, " ")) != NULL) { | ||
508 | if (psmouse_check_pnp_id(p, ids)) { | ||
509 | found = true; | ||
510 | break; | ||
511 | } | ||
512 | } | ||
488 | 513 | ||
489 | return false; | 514 | kfree(save_ptr); |
515 | return found; | ||
490 | } | 516 | } |
491 | 517 | ||
492 | /* | 518 | /* |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 3b06c8a360b6..630af73e98c4 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -67,6 +67,9 @@ | |||
67 | #define X_MAX_POSITIVE 8176 | 67 | #define X_MAX_POSITIVE 8176 |
68 | #define Y_MAX_POSITIVE 8176 | 68 | #define Y_MAX_POSITIVE 8176 |
69 | 69 | ||
70 | /* maximum ABS_MT_POSITION displacement (in mm) */ | ||
71 | #define DMAX 10 | ||
72 | |||
70 | /***************************************************************************** | 73 | /***************************************************************************** |
71 | * Stuff we need even when we do not want native Synaptics support | 74 | * Stuff we need even when we do not want native Synaptics support |
72 | ****************************************************************************/ | 75 | ****************************************************************************/ |
@@ -203,6 +206,13 @@ static const char * const topbuttonpad_pnp_ids[] = { | |||
203 | NULL | 206 | NULL |
204 | }; | 207 | }; |
205 | 208 | ||
209 | /* This list has been kindly provided by Synaptics. */ | ||
210 | static const char * const forcepad_pnp_ids[] = { | ||
211 | "SYN300D", | ||
212 | "SYN3014", | ||
213 | NULL | ||
214 | }; | ||
215 | |||
206 | /***************************************************************************** | 216 | /***************************************************************************** |
207 | * Synaptics communications functions | 217 | * Synaptics communications functions |
208 | ****************************************************************************/ | 218 | ****************************************************************************/ |
@@ -687,8 +697,6 @@ static void synaptics_parse_ext_buttons(const unsigned char buf[], | |||
687 | hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits; | 697 | hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits; |
688 | } | 698 | } |
689 | 699 | ||
690 | static bool is_forcepad; | ||
691 | |||
692 | static int synaptics_parse_hw_state(const unsigned char buf[], | 700 | static int synaptics_parse_hw_state(const unsigned char buf[], |
693 | struct synaptics_data *priv, | 701 | struct synaptics_data *priv, |
694 | struct synaptics_hw_state *hw) | 702 | struct synaptics_hw_state *hw) |
@@ -718,7 +726,7 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
718 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 726 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
719 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 727 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
720 | 728 | ||
721 | if (is_forcepad) { | 729 | if (priv->is_forcepad) { |
722 | /* | 730 | /* |
723 | * ForcePads, like Clickpads, use middle button | 731 | * ForcePads, like Clickpads, use middle button |
724 | * bits to report primary button clicks. | 732 | * bits to report primary button clicks. |
@@ -917,7 +925,7 @@ static void synaptics_report_mt_data(struct psmouse *psmouse, | |||
917 | pos[i].y = synaptics_invert_y(hw[i]->y); | 925 | pos[i].y = synaptics_invert_y(hw[i]->y); |
918 | } | 926 | } |
919 | 927 | ||
920 | input_mt_assign_slots(dev, slot, pos, nsemi, 0); | 928 | input_mt_assign_slots(dev, slot, pos, nsemi, DMAX * priv->x_res); |
921 | 929 | ||
922 | for (i = 0; i < nsemi; i++) { | 930 | for (i = 0; i < nsemi; i++) { |
923 | input_mt_slot(dev, slot[i]); | 931 | input_mt_slot(dev, slot[i]); |
@@ -1186,7 +1194,7 @@ static void set_input_params(struct psmouse *psmouse, | |||
1186 | ABS_MT_POSITION_Y); | 1194 | ABS_MT_POSITION_Y); |
1187 | /* Image sensors can report per-contact pressure */ | 1195 | /* Image sensors can report per-contact pressure */ |
1188 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | 1196 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); |
1189 | input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK); | 1197 | input_mt_init_slots(dev, 3, INPUT_MT_POINTER | INPUT_MT_TRACK); |
1190 | 1198 | ||
1191 | /* Image sensors can signal 4 and 5 finger clicks */ | 1199 | /* Image sensors can signal 4 and 5 finger clicks */ |
1192 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1200 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
@@ -1418,29 +1426,11 @@ static const struct dmi_system_id __initconst cr48_dmi_table[] = { | |||
1418 | { } | 1426 | { } |
1419 | }; | 1427 | }; |
1420 | 1428 | ||
1421 | static const struct dmi_system_id forcepad_dmi_table[] __initconst = { | ||
1422 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
1423 | { | ||
1424 | .matches = { | ||
1425 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1426 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Folio 1040 G1"), | ||
1427 | }, | ||
1428 | }, | ||
1429 | #endif | ||
1430 | { } | ||
1431 | }; | ||
1432 | |||
1433 | void __init synaptics_module_init(void) | 1429 | void __init synaptics_module_init(void) |
1434 | { | 1430 | { |
1435 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 1431 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
1436 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | 1432 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
1437 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); | 1433 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); |
1438 | |||
1439 | /* | ||
1440 | * Unfortunately ForcePad capability is not exported over PS/2, | ||
1441 | * so we have to resort to checking DMI. | ||
1442 | */ | ||
1443 | is_forcepad = dmi_check_system(forcepad_dmi_table); | ||
1444 | } | 1434 | } |
1445 | 1435 | ||
1446 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | 1436 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
@@ -1475,6 +1465,12 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | |||
1475 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) | 1465 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) |
1476 | priv->disable_gesture = true; | 1466 | priv->disable_gesture = true; |
1477 | 1467 | ||
1468 | /* | ||
1469 | * Unfortunately ForcePad capability is not exported over PS/2, | ||
1470 | * so we have to resort to checking PNP IDs. | ||
1471 | */ | ||
1472 | priv->is_forcepad = psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids); | ||
1473 | |||
1478 | if (synaptics_set_mode(psmouse)) { | 1474 | if (synaptics_set_mode(psmouse)) { |
1479 | psmouse_err(psmouse, "Unable to initialize device.\n"); | 1475 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
1480 | goto init_fail; | 1476 | goto init_fail; |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index ee4bd0d12b26..56faa7ec4434 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -196,6 +196,7 @@ struct synaptics_data { | |||
196 | unsigned long press_start; | 196 | unsigned long press_start; |
197 | bool press; | 197 | bool press; |
198 | bool report_press; | 198 | bool report_press; |
199 | bool is_forcepad; | ||
199 | }; | 200 | }; |
200 | 201 | ||
201 | void synaptics_module_init(void); | 202 | void synaptics_module_init(void); |