diff options
| -rw-r--r-- | drivers/input/mouse/alps.c | 329 | ||||
| -rw-r--r-- | drivers/input/mouse/alps.h | 78 |
2 files changed, 403 insertions, 4 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index c7924b6f7d4b..ad741c04936d 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -153,12 +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); |
| 160 | static void alps_set_abs_params_v7(struct alps_data *priv, | 164 | static void alps_set_abs_params_v7(struct alps_data *priv, |
| 161 | struct input_dev *dev1); | 165 | struct input_dev *dev1); |
| 166 | static void alps_set_abs_params_ss4_v2(struct alps_data *priv, | ||
| 167 | struct input_dev *dev1); | ||
| 162 | 168 | ||
| 163 | /* Packet formats are described in Documentation/input/alps.txt */ | 169 | /* Packet formats are described in Documentation/input/alps.txt */ |
| 164 | 170 | ||
| @@ -1087,6 +1093,176 @@ static void alps_process_packet_v7(struct psmouse *psmouse) | |||
| 1087 | alps_process_touchpad_packet_v7(psmouse); | 1093 | alps_process_touchpad_packet_v7(psmouse); |
| 1088 | } | 1094 | } |
| 1089 | 1095 | ||
| 1096 | unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte) | ||
| 1097 | { | ||
| 1098 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; | ||
| 1099 | |||
| 1100 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && | ||
| 1101 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { | ||
| 1102 | pkt_id = SS4_PACKET_ID_IDLE; | ||
| 1103 | } else if (!(byte[3] & 0x10)) { | ||
| 1104 | pkt_id = SS4_PACKET_ID_ONE; | ||
| 1105 | } else if (!(byte[3] & 0x20)) { | ||
| 1106 | pkt_id = SS4_PACKET_ID_TWO; | ||
| 1107 | } else { | ||
| 1108 | pkt_id = SS4_PACKET_ID_MULTI; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | return pkt_id; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static int alps_decode_ss4_v2(struct alps_fields *f, | ||
| 1115 | unsigned char *p, struct psmouse *psmouse) | ||
| 1116 | { | ||
| 1117 | struct alps_data *priv = psmouse->private; | ||
| 1118 | unsigned char pkt_id; | ||
| 1119 | unsigned int no_data_x, no_data_y; | ||
| 1120 | |||
| 1121 | pkt_id = alps_get_pkt_id_ss4_v2(p); | ||
| 1122 | |||
| 1123 | /* Current packet is 1Finger coordinate packet */ | ||
| 1124 | switch (pkt_id) { | ||
| 1125 | case SS4_PACKET_ID_ONE: | ||
| 1126 | f->mt[0].x = SS4_1F_X_V2(p); | ||
| 1127 | f->mt[0].y = SS4_1F_Y_V2(p); | ||
| 1128 | f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f; | ||
| 1129 | f->fingers = 1; | ||
| 1130 | f->first_mp = 0; | ||
| 1131 | f->is_mp = 0; | ||
| 1132 | break; | ||
| 1133 | |||
| 1134 | case SS4_PACKET_ID_TWO: | ||
| 1135 | if (priv->flags & ALPS_BUTTONPAD) { | ||
| 1136 | f->mt[0].x = SS4_BTL_MF_X_V2(p, 0); | ||
| 1137 | f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0); | ||
| 1138 | f->mt[1].x = SS4_BTL_MF_X_V2(p, 1); | ||
| 1139 | f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1); | ||
| 1140 | } else { | ||
| 1141 | f->mt[0].x = SS4_STD_MF_X_V2(p, 0); | ||
| 1142 | f->mt[0].y = SS4_STD_MF_Y_V2(p, 0); | ||
| 1143 | f->mt[1].x = SS4_STD_MF_X_V2(p, 1); | ||
| 1144 | f->mt[1].y = SS4_STD_MF_Y_V2(p, 1); | ||
| 1145 | } | ||
| 1146 | f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0; | ||
| 1147 | |||
| 1148 | if (SS4_IS_MF_CONTINUE(p)) { | ||
| 1149 | f->first_mp = 1; | ||
| 1150 | } else { | ||
| 1151 | f->fingers = 2; | ||
| 1152 | f->first_mp = 0; | ||
| 1153 | } | ||
| 1154 | f->is_mp = 0; | ||
| 1155 | |||
| 1156 | break; | ||
| 1157 | |||
| 1158 | case SS4_PACKET_ID_MULTI: | ||
| 1159 | if (priv->flags & ALPS_BUTTONPAD) { | ||
| 1160 | f->mt[2].x = SS4_BTL_MF_X_V2(p, 0); | ||
| 1161 | f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0); | ||
| 1162 | f->mt[3].x = SS4_BTL_MF_X_V2(p, 1); | ||
| 1163 | f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1); | ||
| 1164 | no_data_x = SS4_MFPACKET_NO_AX_BL; | ||
| 1165 | no_data_y = SS4_MFPACKET_NO_AY_BL; | ||
| 1166 | } else { | ||
| 1167 | f->mt[2].x = SS4_STD_MF_X_V2(p, 0); | ||
| 1168 | f->mt[2].y = SS4_STD_MF_Y_V2(p, 0); | ||
| 1169 | f->mt[3].x = SS4_STD_MF_X_V2(p, 1); | ||
| 1170 | f->mt[3].y = SS4_STD_MF_Y_V2(p, 1); | ||
| 1171 | no_data_x = SS4_MFPACKET_NO_AX; | ||
| 1172 | no_data_y = SS4_MFPACKET_NO_AY; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | f->first_mp = 0; | ||
| 1176 | f->is_mp = 1; | ||
| 1177 | |||
| 1178 | if (SS4_IS_5F_DETECTED(p)) { | ||
| 1179 | f->fingers = 5; | ||
| 1180 | } else if (f->mt[3].x == no_data_x && | ||
| 1181 | f->mt[3].y == no_data_y) { | ||
| 1182 | f->mt[3].x = 0; | ||
| 1183 | f->mt[3].y = 0; | ||
| 1184 | f->fingers = 3; | ||
| 1185 | } else { | ||
| 1186 | f->fingers = 4; | ||
| 1187 | } | ||
| 1188 | break; | ||
| 1189 | |||
| 1190 | case SS4_PACKET_ID_IDLE: | ||
| 1191 | default: | ||
| 1192 | memset(f, 0, sizeof(struct alps_fields)); | ||
| 1193 | break; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | f->left = !!(SS4_BTN_V2(p) & 0x01); | ||
| 1197 | if (!(priv->flags & ALPS_BUTTONPAD)) { | ||
| 1198 | f->right = !!(SS4_BTN_V2(p) & 0x02); | ||
| 1199 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | return 0; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | ||
| 1206 | { | ||
| 1207 | struct alps_data *priv = psmouse->private; | ||
| 1208 | unsigned char *packet = psmouse->packet; | ||
| 1209 | struct input_dev *dev = psmouse->dev; | ||
| 1210 | struct alps_fields *f = &priv->f; | ||
| 1211 | |||
| 1212 | memset(f, 0, sizeof(struct alps_fields)); | ||
| 1213 | priv->decode_fields(f, packet, psmouse); | ||
| 1214 | if (priv->multi_packet) { | ||
| 1215 | /* | ||
| 1216 | * Sometimes the first packet will indicate a multi-packet | ||
| 1217 | * sequence, but sometimes the next multi-packet would not | ||
| 1218 | * come. Check for this, and when it happens process the | ||
| 1219 | * position packet as usual. | ||
| 1220 | */ | ||
| 1221 | if (f->is_mp) { | ||
| 1222 | /* Now process the 1st packet */ | ||
| 1223 | priv->decode_fields(f, priv->multi_data, psmouse); | ||
| 1224 | } else { | ||
| 1225 | priv->multi_packet = 0; | ||
| 1226 | } | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | /* | ||
| 1230 | * "f.is_mp" would always be '0' after merging the 1st and 2nd packet. | ||
| 1231 | * When it is set, it means 2nd packet comes without 1st packet come. | ||
| 1232 | */ | ||
| 1233 | if (f->is_mp) | ||
| 1234 | return; | ||
| 1235 | |||
| 1236 | /* Save the first packet */ | ||
| 1237 | if (!priv->multi_packet && f->first_mp) { | ||
| 1238 | priv->multi_packet = 1; | ||
| 1239 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); | ||
| 1240 | return; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | priv->multi_packet = 0; | ||
| 1244 | |||
| 1245 | alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4); | ||
| 1246 | |||
| 1247 | input_mt_report_finger_count(dev, f->fingers); | ||
| 1248 | |||
| 1249 | input_report_key(dev, BTN_LEFT, f->left); | ||
| 1250 | input_report_key(dev, BTN_RIGHT, f->right); | ||
| 1251 | input_report_key(dev, BTN_MIDDLE, f->middle); | ||
| 1252 | |||
| 1253 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | ||
| 1254 | input_sync(dev); | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) | ||
| 1258 | { | ||
| 1259 | if (psmouse->pktcnt == 4 && ((psmouse->packet[3] & 0x08) != 0x08)) | ||
| 1260 | return false; | ||
| 1261 | if (psmouse->pktcnt == 6 && ((psmouse->packet[5] & 0x10) != 0x0)) | ||
| 1262 | return false; | ||
| 1263 | return true; | ||
| 1264 | } | ||
| 1265 | |||
| 1090 | static DEFINE_MUTEX(alps_mutex); | 1266 | static DEFINE_MUTEX(alps_mutex); |
| 1091 | 1267 | ||
| 1092 | static void alps_register_bare_ps2_mouse(struct work_struct *work) | 1268 | static void alps_register_bare_ps2_mouse(struct work_struct *work) |
| @@ -1307,8 +1483,12 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
| 1307 | * a device connected to the external PS/2 port. Because bare PS/2 | 1483 | * a device connected to the external PS/2 port. Because bare PS/2 |
| 1308 | * protocol does not have enough constant bits to self-synchronize | 1484 | * protocol does not have enough constant bits to self-synchronize |
| 1309 | * properly we only do this if the device is fully synchronized. | 1485 | * properly we only do this if the device is fully synchronized. |
| 1486 | * Can not distinguish V8's first byte from PS/2 packet's | ||
| 1310 | */ | 1487 | */ |
| 1311 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { | 1488 | if (priv->proto_version != ALPS_PROTO_V8 && |
| 1489 | !psmouse->out_of_sync_cnt && | ||
| 1490 | (psmouse->packet[0] & 0xc8) == 0x08) { | ||
| 1491 | |||
| 1312 | if (psmouse->pktcnt == 3) { | 1492 | if (psmouse->pktcnt == 3) { |
| 1313 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, | 1493 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
| 1314 | true); | 1494 | true); |
| @@ -1356,8 +1536,10 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
| 1356 | return PSMOUSE_BAD_DATA; | 1536 | return PSMOUSE_BAD_DATA; |
| 1357 | } | 1537 | } |
| 1358 | 1538 | ||
| 1359 | if (priv->proto_version == ALPS_PROTO_V7 && | 1539 | if ((priv->proto_version == ALPS_PROTO_V7 && |
| 1360 | !alps_is_valid_package_v7(psmouse)) { | 1540 | !alps_is_valid_package_v7(psmouse)) || |
| 1541 | (priv->proto_version == ALPS_PROTO_V8 && | ||
| 1542 | !alps_is_valid_package_ss4_v2(psmouse))) { | ||
| 1361 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 1543 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
| 1362 | psmouse->pktcnt - 1, | 1544 | psmouse->pktcnt - 1, |
| 1363 | psmouse->packet[psmouse->pktcnt - 1]); | 1545 | psmouse->packet[psmouse->pktcnt - 1]); |
| @@ -2132,6 +2314,88 @@ error: | |||
| 2132 | return -1; | 2314 | return -1; |
| 2133 | } | 2315 | } |
| 2134 | 2316 | ||
| 2317 | static int alps_get_otp_values_ss4_v2(struct psmouse *psmouse, | ||
| 2318 | unsigned char index, unsigned char otp[]) | ||
| 2319 | { | ||
| 2320 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
| 2321 | |||
| 2322 | switch (index) { | ||
| 2323 | case 0: | ||
| 2324 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
| 2325 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
| 2326 | ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO)) | ||
| 2327 | return -1; | ||
| 2328 | |||
| 2329 | break; | ||
| 2330 | |||
| 2331 | case 1: | ||
| 2332 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | ||
| 2333 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | ||
| 2334 | ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO)) | ||
| 2335 | return -1; | ||
| 2336 | |||
| 2337 | break; | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | return 0; | ||
| 2341 | } | ||
| 2342 | |||
| 2343 | int alps_update_device_area_ss4_v2(unsigned char otp[][4], | ||
| 2344 | struct alps_data *priv) | ||
| 2345 | { | ||
| 2346 | int num_x_electrode; | ||
| 2347 | int num_y_electrode; | ||
| 2348 | int x_pitch, y_pitch, x_phys, y_phys; | ||
| 2349 | |||
| 2350 | num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); | ||
| 2351 | num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); | ||
| 2352 | |||
| 2353 | priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE; | ||
| 2354 | priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; | ||
| 2355 | |||
| 2356 | x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM; | ||
| 2357 | y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM; | ||
| 2358 | |||
| 2359 | x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */ | ||
| 2360 | y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */ | ||
| 2361 | |||
| 2362 | priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */ | ||
| 2363 | priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */ | ||
| 2364 | |||
| 2365 | return 0; | ||
| 2366 | } | ||
| 2367 | |||
| 2368 | int alps_update_btn_info_ss4_v2(unsigned char otp[][4], struct alps_data *priv) | ||
| 2369 | { | ||
| 2370 | |||
| 2371 | unsigned char is_btnless; | ||
| 2372 | |||
| 2373 | is_btnless = (otp[1][1] >> 3) & 0x01; | ||
| 2374 | |||
| 2375 | if (is_btnless) | ||
| 2376 | priv->flags |= ALPS_BUTTONPAD; | ||
| 2377 | |||
| 2378 | return 0; | ||
| 2379 | } | ||
| 2380 | |||
| 2381 | static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, | ||
| 2382 | struct alps_data *priv) | ||
| 2383 | { | ||
| 2384 | unsigned char otp[2][4]; | ||
| 2385 | |||
| 2386 | memset(otp, 0, sizeof(otp)); | ||
| 2387 | |||
| 2388 | if (alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]) || | ||
| 2389 | alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0])) | ||
| 2390 | return -1; | ||
| 2391 | |||
| 2392 | alps_update_device_area_ss4_v2(otp, priv); | ||
| 2393 | |||
| 2394 | alps_update_btn_info_ss4_v2(otp, priv); | ||
| 2395 | |||
| 2396 | return 0; | ||
| 2397 | } | ||
| 2398 | |||
| 2135 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, | 2399 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, |
| 2136 | struct alps_data *priv) | 2400 | struct alps_data *priv) |
| 2137 | { | 2401 | { |
| @@ -2224,6 +2488,35 @@ error: | |||
| 2224 | return ret; | 2488 | return ret; |
| 2225 | } | 2489 | } |
| 2226 | 2490 | ||
| 2491 | static int alps_hw_init_ss4_v2(struct psmouse *psmouse) | ||
| 2492 | { | ||
| 2493 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
| 2494 | char param[2] = {0x64, 0x28}; | ||
| 2495 | int ret = -1; | ||
| 2496 | |||
| 2497 | /* enter absolute mode */ | ||
| 2498 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
| 2499 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
| 2500 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | ||
| 2501 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) { | ||
| 2502 | goto error; | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | /* T.B.D. Decread noise packet number, delete in the future */ | ||
| 2506 | if (alps_exit_command_mode(psmouse) || | ||
| 2507 | alps_enter_command_mode(psmouse) || | ||
| 2508 | alps_command_mode_write_reg(psmouse, 0x001D, 0x20)) { | ||
| 2509 | goto error; | ||
| 2510 | } | ||
| 2511 | alps_exit_command_mode(psmouse); | ||
| 2512 | |||
| 2513 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
| 2514 | |||
| 2515 | error: | ||
| 2516 | alps_exit_command_mode(psmouse); | ||
| 2517 | return ret; | ||
| 2518 | } | ||
| 2519 | |||
| 2227 | static int alps_set_protocol(struct psmouse *psmouse, | 2520 | static int alps_set_protocol(struct psmouse *psmouse, |
| 2228 | struct alps_data *priv, | 2521 | struct alps_data *priv, |
| 2229 | const struct alps_protocol_info *protocol) | 2522 | const struct alps_protocol_info *protocol) |
| @@ -2323,6 +2616,19 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
| 2323 | priv->flags |= ALPS_BUTTONPAD; | 2616 | priv->flags |= ALPS_BUTTONPAD; |
| 2324 | 2617 | ||
| 2325 | break; | 2618 | break; |
| 2619 | |||
| 2620 | case ALPS_PROTO_V8: | ||
| 2621 | priv->hw_init = alps_hw_init_ss4_v2; | ||
| 2622 | priv->process_packet = alps_process_packet_ss4_v2; | ||
| 2623 | priv->decode_fields = alps_decode_ss4_v2; | ||
| 2624 | priv->set_abs_params = alps_set_abs_params_ss4_v2; | ||
| 2625 | priv->nibble_commands = alps_v3_nibble_commands; | ||
| 2626 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
| 2627 | |||
| 2628 | if (alps_set_defaults_ss4_v2(psmouse, priv)) | ||
| 2629 | return -EIO; | ||
| 2630 | |||
| 2631 | break; | ||
| 2326 | } | 2632 | } |
| 2327 | 2633 | ||
| 2328 | return 0; | 2634 | return 0; |
| @@ -2391,6 +2697,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
| 2391 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && | 2697 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && |
| 2392 | ec[2] >= 0x90 && ec[2] <= 0x9d) { | 2698 | ec[2] >= 0x90 && ec[2] <= 0x9d) { |
| 2393 | protocol = &alps_v3_protocol_data; | 2699 | protocol = &alps_v3_protocol_data; |
| 2700 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && | ||
| 2701 | e7[2] == 0x14 && ec[1] == 0x02) { | ||
| 2702 | protocol = &alps_v8_protocol_data; | ||
| 2394 | } else { | 2703 | } else { |
| 2395 | psmouse_dbg(psmouse, | 2704 | psmouse_dbg(psmouse, |
| 2396 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2705 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
| @@ -2474,6 +2783,20 @@ static void alps_set_abs_params_v7(struct alps_data *priv, | |||
| 2474 | input_mt_init_slots(dev1, MAX_TOUCHES, | 2783 | input_mt_init_slots(dev1, MAX_TOUCHES, |
| 2475 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | 2784 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | |
| 2476 | INPUT_MT_TRACK); | 2785 | INPUT_MT_TRACK); |
| 2786 | |||
| 2787 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
| 2788 | } | ||
| 2789 | |||
| 2790 | static void alps_set_abs_params_ss4_v2(struct alps_data *priv, | ||
| 2791 | struct input_dev *dev1) | ||
| 2792 | { | ||
| 2793 | alps_set_abs_params_mt_common(priv, dev1); | ||
| 2794 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
| 2795 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
| 2796 | |||
| 2797 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
| 2798 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
| 2799 | INPUT_MT_TRACK); | ||
| 2477 | } | 2800 | } |
| 2478 | 2801 | ||
| 2479 | int alps_init(struct psmouse *psmouse) | 2802 | int alps_init(struct psmouse *psmouse) |
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 |
