diff options
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r-- | drivers/input/mouse/alps.c | 429 |
1 files changed, 394 insertions, 35 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index d28726a0ef85..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 | ||
@@ -243,6 +251,14 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) | |||
243 | return; | 251 | return; |
244 | } | 252 | } |
245 | 253 | ||
254 | /* Non interleaved V2 dualpoint has separate stick button bits */ | ||
255 | if (priv->proto_version == ALPS_PROTO_V2 && | ||
256 | priv->flags == (ALPS_PASS | ALPS_DUALPOINT)) { | ||
257 | left |= packet[0] & 1; | ||
258 | right |= packet[0] & 2; | ||
259 | middle |= packet[0] & 4; | ||
260 | } | ||
261 | |||
246 | alps_report_buttons(dev, dev2, left, right, middle); | 262 | alps_report_buttons(dev, dev2, left, right, middle); |
247 | 263 | ||
248 | /* Convert hardware tap to a reasonable Z value */ | 264 | /* Convert hardware tap to a reasonable Z value */ |
@@ -1085,6 +1101,176 @@ static void alps_process_packet_v7(struct psmouse *psmouse) | |||
1085 | alps_process_touchpad_packet_v7(psmouse); | 1101 | alps_process_touchpad_packet_v7(psmouse); |
1086 | } | 1102 | } |
1087 | 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 | |||
1088 | static DEFINE_MUTEX(alps_mutex); | 1274 | static DEFINE_MUTEX(alps_mutex); |
1089 | 1275 | ||
1090 | static void alps_register_bare_ps2_mouse(struct work_struct *work) | 1276 | static void alps_register_bare_ps2_mouse(struct work_struct *work) |
@@ -1154,12 +1340,31 @@ out: | |||
1154 | mutex_unlock(&alps_mutex); | 1340 | mutex_unlock(&alps_mutex); |
1155 | } | 1341 | } |
1156 | 1342 | ||
1157 | static void alps_report_bare_ps2_packet(struct input_dev *dev, | 1343 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, |
1158 | unsigned char packet[], | 1344 | unsigned char packet[], |
1159 | bool report_buttons) | 1345 | bool report_buttons) |
1160 | { | 1346 | { |
1347 | struct alps_data *priv = psmouse->private; | ||
1348 | struct input_dev *dev, *dev2 = NULL; | ||
1349 | |||
1350 | /* Figure out which device to use to report the bare packet */ | ||
1351 | if (priv->proto_version == ALPS_PROTO_V2 && | ||
1352 | (priv->flags & ALPS_DUALPOINT)) { | ||
1353 | /* On V2 devices the DualPoint Stick reports bare packets */ | ||
1354 | dev = priv->dev2; | ||
1355 | dev2 = psmouse->dev; | ||
1356 | } else if (unlikely(IS_ERR_OR_NULL(priv->dev3))) { | ||
1357 | /* Register dev3 mouse if we received PS/2 packet first time */ | ||
1358 | if (!IS_ERR(priv->dev3)) | ||
1359 | psmouse_queue_work(psmouse, &priv->dev3_register_work, | ||
1360 | 0); | ||
1361 | return; | ||
1362 | } else { | ||
1363 | dev = priv->dev3; | ||
1364 | } | ||
1365 | |||
1161 | if (report_buttons) | 1366 | if (report_buttons) |
1162 | alps_report_buttons(dev, NULL, | 1367 | alps_report_buttons(dev, dev2, |
1163 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | 1368 | packet[0] & 1, packet[0] & 2, packet[0] & 4); |
1164 | 1369 | ||
1165 | input_report_rel(dev, REL_X, | 1370 | input_report_rel(dev, REL_X, |
@@ -1232,8 +1437,8 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | |||
1232 | * de-synchronization. | 1437 | * de-synchronization. |
1233 | */ | 1438 | */ |
1234 | 1439 | ||
1235 | alps_report_bare_ps2_packet(priv->dev2, | 1440 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], |
1236 | &psmouse->packet[3], false); | 1441 | false); |
1237 | 1442 | ||
1238 | /* | 1443 | /* |
1239 | * Continue with the standard ALPS protocol handling, | 1444 | * Continue with the standard ALPS protocol handling, |
@@ -1287,20 +1492,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1287 | * 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 |
1288 | * protocol does not have enough constant bits to self-synchronize | 1493 | * protocol does not have enough constant bits to self-synchronize |
1289 | * 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 | ||
1290 | */ | 1496 | */ |
1291 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { | 1497 | if (priv->proto_version != ALPS_PROTO_V8 && |
1292 | 1498 | !psmouse->out_of_sync_cnt && | |
1293 | /* Register dev3 mouse if we received PS/2 packet first time */ | 1499 | (psmouse->packet[0] & 0xc8) == 0x08) { |
1294 | if (unlikely(!priv->dev3)) | ||
1295 | psmouse_queue_work(psmouse, | ||
1296 | &priv->dev3_register_work, 0); | ||
1297 | 1500 | ||
1298 | if (psmouse->pktcnt == 3) { | 1501 | if (psmouse->pktcnt == 3) { |
1299 | /* Once dev3 mouse device is registered report data */ | 1502 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
1300 | if (likely(!IS_ERR_OR_NULL(priv->dev3))) | 1503 | true); |
1301 | alps_report_bare_ps2_packet(priv->dev3, | ||
1302 | psmouse->packet, | ||
1303 | true); | ||
1304 | return PSMOUSE_FULL_PACKET; | 1504 | return PSMOUSE_FULL_PACKET; |
1305 | } | 1505 | } |
1306 | return PSMOUSE_GOOD_DATA; | 1506 | return PSMOUSE_GOOD_DATA; |
@@ -1345,8 +1545,10 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1345 | return PSMOUSE_BAD_DATA; | 1545 | return PSMOUSE_BAD_DATA; |
1346 | } | 1546 | } |
1347 | 1547 | ||
1348 | if (priv->proto_version == ALPS_PROTO_V7 && | 1548 | if ((priv->proto_version == ALPS_PROTO_V7 && |
1349 | !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))) { | ||
1350 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 1552 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
1351 | psmouse->pktcnt - 1, | 1553 | psmouse->pktcnt - 1, |
1352 | psmouse->packet[psmouse->pktcnt - 1]); | 1554 | psmouse->packet[psmouse->pktcnt - 1]); |
@@ -2121,6 +2323,88 @@ error: | |||
2121 | return -1; | 2323 | return -1; |
2122 | } | 2324 | } |
2123 | 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 | |||
2124 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, | 2408 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, |
2125 | struct alps_data *priv) | 2409 | struct alps_data *priv) |
2126 | { | 2410 | { |
@@ -2213,6 +2497,35 @@ error: | |||
2213 | return ret; | 2497 | return ret; |
2214 | } | 2498 | } |
2215 | 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 | |||
2216 | static int alps_set_protocol(struct psmouse *psmouse, | 2529 | static int alps_set_protocol(struct psmouse *psmouse, |
2217 | struct alps_data *priv, | 2530 | struct alps_data *priv, |
2218 | const struct alps_protocol_info *protocol) | 2531 | const struct alps_protocol_info *protocol) |
@@ -2281,10 +2594,12 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2281 | priv->set_abs_params = alps_set_abs_params_mt; | 2594 | priv->set_abs_params = alps_set_abs_params_mt; |
2282 | priv->nibble_commands = alps_v3_nibble_commands; | 2595 | priv->nibble_commands = alps_v3_nibble_commands; |
2283 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2596 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2284 | priv->x_max = 1360; | ||
2285 | priv->y_max = 660; | ||
2286 | priv->x_bits = 23; | 2597 | priv->x_bits = 23; |
2287 | priv->y_bits = 12; | 2598 | priv->y_bits = 12; |
2599 | |||
2600 | if (alps_dolphin_get_device_area(psmouse, priv)) | ||
2601 | return -EIO; | ||
2602 | |||
2288 | break; | 2603 | break; |
2289 | 2604 | ||
2290 | case ALPS_PROTO_V6: | 2605 | case ALPS_PROTO_V6: |
@@ -2300,17 +2615,29 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2300 | priv->hw_init = alps_hw_init_v7; | 2615 | priv->hw_init = alps_hw_init_v7; |
2301 | priv->process_packet = alps_process_packet_v7; | 2616 | priv->process_packet = alps_process_packet_v7; |
2302 | priv->decode_fields = alps_decode_packet_v7; | 2617 | priv->decode_fields = alps_decode_packet_v7; |
2303 | priv->set_abs_params = alps_set_abs_params_mt; | 2618 | priv->set_abs_params = alps_set_abs_params_v7; |
2304 | priv->nibble_commands = alps_v3_nibble_commands; | 2619 | priv->nibble_commands = alps_v3_nibble_commands; |
2305 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2620 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2306 | 2621 | priv->x_max = 0xfff; | |
2307 | if (alps_dolphin_get_device_area(psmouse, priv)) | 2622 | priv->y_max = 0x7ff; |
2308 | return -EIO; | ||
2309 | 2623 | ||
2310 | if (priv->fw_ver[1] != 0xba) | 2624 | if (priv->fw_ver[1] != 0xba) |
2311 | priv->flags |= ALPS_BUTTONPAD; | 2625 | priv->flags |= ALPS_BUTTONPAD; |
2312 | 2626 | ||
2313 | 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; | ||
2314 | } | 2641 | } |
2315 | 2642 | ||
2316 | return 0; | 2643 | return 0; |
@@ -2379,6 +2706,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2379 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && | 2706 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && |
2380 | ec[2] >= 0x90 && ec[2] <= 0x9d) { | 2707 | ec[2] >= 0x90 && ec[2] <= 0x9d) { |
2381 | 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; | ||
2382 | } else { | 2712 | } else { |
2383 | psmouse_dbg(psmouse, | 2713 | psmouse_dbg(psmouse, |
2384 | "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); |
@@ -2427,10 +2757,11 @@ static void alps_set_abs_params_st(struct alps_data *priv, | |||
2427 | { | 2757 | { |
2428 | 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); |
2429 | 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); | ||
2430 | } | 2761 | } |
2431 | 2762 | ||
2432 | static void alps_set_abs_params_mt(struct alps_data *priv, | 2763 | static void alps_set_abs_params_mt_common(struct alps_data *priv, |
2433 | struct input_dev *dev1) | 2764 | struct input_dev *dev1) |
2434 | { | 2765 | { |
2435 | 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); |
2436 | 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); |
@@ -2438,15 +2769,44 @@ static void alps_set_abs_params_mt(struct alps_data *priv, | |||
2438 | 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); |
2439 | 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); |
2440 | 2771 | ||
2441 | input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | | ||
2442 | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | ||
2443 | |||
2444 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); | 2772 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); |
2445 | 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 | } | ||
2446 | 2786 | ||
2447 | /* V7 is real multi-touch */ | 2787 | static void alps_set_abs_params_v7(struct alps_data *priv, |
2448 | if (priv->proto_version == ALPS_PROTO_V7) | 2788 | struct input_dev *dev1) |
2449 | clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | 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); | ||
2806 | |||
2807 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
2808 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
2809 | INPUT_MT_TRACK); | ||
2450 | } | 2810 | } |
2451 | 2811 | ||
2452 | int alps_init(struct psmouse *psmouse) | 2812 | int alps_init(struct psmouse *psmouse) |
@@ -2479,9 +2839,6 @@ int alps_init(struct psmouse *psmouse) | |||
2479 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 2839 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
2480 | 2840 | ||
2481 | priv->set_abs_params(priv, dev1); | 2841 | priv->set_abs_params(priv, dev1); |
2482 | /* No pressure on V7 */ | ||
2483 | if (priv->proto_version != ALPS_PROTO_V7) | ||
2484 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2485 | 2842 | ||
2486 | if (priv->flags & ALPS_WHEEL) { | 2843 | if (priv->flags & ALPS_WHEEL) { |
2487 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 2844 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
@@ -2605,8 +2962,10 @@ int alps_detect(struct psmouse *psmouse, bool set_properties) | |||
2605 | return -ENOMEM; | 2962 | return -ENOMEM; |
2606 | 2963 | ||
2607 | error = alps_identify(psmouse, priv); | 2964 | error = alps_identify(psmouse, priv); |
2608 | if (error) | 2965 | if (error) { |
2966 | kfree(priv); | ||
2609 | return error; | 2967 | return error; |
2968 | } | ||
2610 | 2969 | ||
2611 | if (set_properties) { | 2970 | if (set_properties) { |
2612 | psmouse->vendor = "ALPS"; | 2971 | psmouse->vendor = "ALPS"; |