diff options
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r-- | drivers/input/mouse/alps.c | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7b99fc7c9438..0238e0e14335 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) | |||
490 | f->y_map |= (p[5] & 0x20) << 6; | 490 | f->y_map |= (p[5] & 0x20) << 6; |
491 | } | 491 | } |
492 | 492 | ||
493 | static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) | ||
494 | { | ||
495 | f->first_mp = !!(p[0] & 0x02); | ||
496 | f->is_mp = !!(p[0] & 0x20); | ||
497 | |||
498 | f->fingers = ((p[0] & 0x6) >> 1 | | ||
499 | (p[0] & 0x10) >> 2); | ||
500 | f->x_map = ((p[2] & 0x60) >> 5) | | ||
501 | ((p[4] & 0x7f) << 2) | | ||
502 | ((p[5] & 0x7f) << 9) | | ||
503 | ((p[3] & 0x07) << 16) | | ||
504 | ((p[3] & 0x70) << 15) | | ||
505 | ((p[0] & 0x01) << 22); | ||
506 | f->y_map = (p[1] & 0x7f) | | ||
507 | ((p[2] & 0x1f) << 7); | ||
508 | |||
509 | f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); | ||
510 | f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); | ||
511 | f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; | ||
512 | |||
513 | alps_decode_buttons_v3(f, p); | ||
514 | } | ||
515 | |||
493 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) | 516 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) |
494 | { | 517 | { |
495 | struct alps_data *priv = psmouse->private; | 518 | struct alps_data *priv = psmouse->private; |
@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
874 | } | 897 | } |
875 | 898 | ||
876 | /* Bytes 2 - pktsize should have 0 in the highest bit */ | 899 | /* Bytes 2 - pktsize should have 0 in the highest bit */ |
877 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | 900 | if (priv->proto_version != ALPS_PROTO_V5 && |
901 | psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | ||
878 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { | 902 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
879 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 903 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
880 | psmouse->pktcnt - 1, | 904 | psmouse->pktcnt - 1, |
@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, | |||
994 | return 0; | 1018 | return 0; |
995 | } | 1019 | } |
996 | 1020 | ||
997 | static int alps_enter_command_mode(struct psmouse *psmouse, | 1021 | static int alps_enter_command_mode(struct psmouse *psmouse) |
998 | unsigned char *resp) | ||
999 | { | 1022 | { |
1000 | unsigned char param[4]; | 1023 | unsigned char param[4]; |
1001 | 1024 | ||
@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, | |||
1004 | return -1; | 1027 | return -1; |
1005 | } | 1028 | } |
1006 | 1029 | ||
1007 | if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { | 1030 | if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && |
1031 | param[0] != 0x73) { | ||
1008 | psmouse_dbg(psmouse, | 1032 | psmouse_dbg(psmouse, |
1009 | "unknown response while entering command mode\n"); | 1033 | "unknown response while entering command mode\n"); |
1010 | return -1; | 1034 | return -1; |
1011 | } | 1035 | } |
1012 | |||
1013 | if (resp) | ||
1014 | *resp = param[2]; | ||
1015 | return 0; | 1036 | return 0; |
1016 | } | 1037 | } |
1017 | 1038 | ||
@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, | |||
1176 | { | 1197 | { |
1177 | int reg_val, ret = -1; | 1198 | int reg_val, ret = -1; |
1178 | 1199 | ||
1179 | if (alps_enter_command_mode(psmouse, NULL)) | 1200 | if (alps_enter_command_mode(psmouse)) |
1180 | return -1; | 1201 | return -1; |
1181 | 1202 | ||
1182 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); | 1203 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); |
@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) | |||
1216 | { | 1237 | { |
1217 | int ret = -EIO, reg_val; | 1238 | int ret = -EIO, reg_val; |
1218 | 1239 | ||
1219 | if (alps_enter_command_mode(psmouse, NULL)) | 1240 | if (alps_enter_command_mode(psmouse)) |
1220 | goto error; | 1241 | goto error; |
1221 | 1242 | ||
1222 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); | 1243 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); |
@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) | |||
1279 | * supported by this driver. If bit 1 isn't set the packet | 1300 | * supported by this driver. If bit 1 isn't set the packet |
1280 | * format is different. | 1301 | * format is different. |
1281 | */ | 1302 | */ |
1282 | if (alps_enter_command_mode(psmouse, NULL) || | 1303 | if (alps_enter_command_mode(psmouse) || |
1283 | alps_command_mode_write_reg(psmouse, | 1304 | alps_command_mode_write_reg(psmouse, |
1284 | reg_base + 0x08, 0x82) || | 1305 | reg_base + 0x08, 0x82) || |
1285 | alps_exit_command_mode(psmouse)) | 1306 | alps_exit_command_mode(psmouse)) |
@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) | |||
1306 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) | 1327 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) |
1307 | goto error; | 1328 | goto error; |
1308 | 1329 | ||
1309 | if (alps_enter_command_mode(psmouse, NULL) || | 1330 | if (alps_enter_command_mode(psmouse) || |
1310 | alps_absolute_mode_v3(psmouse)) { | 1331 | alps_absolute_mode_v3(psmouse)) { |
1311 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); | 1332 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); |
1312 | goto error; | 1333 | goto error; |
@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | |||
1381 | priv->flags &= ~ALPS_DUALPOINT; | 1402 | priv->flags &= ~ALPS_DUALPOINT; |
1382 | } | 1403 | } |
1383 | 1404 | ||
1384 | if (alps_enter_command_mode(psmouse, NULL) || | 1405 | if (alps_enter_command_mode(psmouse) || |
1385 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || | 1406 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || |
1386 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) | 1407 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) |
1387 | goto error; | 1408 | goto error; |
@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) | |||
1431 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1452 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1432 | unsigned char param[4]; | 1453 | unsigned char param[4]; |
1433 | 1454 | ||
1434 | if (alps_enter_command_mode(psmouse, NULL)) | 1455 | if (alps_enter_command_mode(psmouse)) |
1435 | goto error; | 1456 | goto error; |
1436 | 1457 | ||
1437 | if (alps_absolute_mode_v4(psmouse)) { | 1458 | if (alps_absolute_mode_v4(psmouse)) { |
@@ -1499,6 +1520,23 @@ error: | |||
1499 | return -1; | 1520 | return -1; |
1500 | } | 1521 | } |
1501 | 1522 | ||
1523 | static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) | ||
1524 | { | ||
1525 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
1526 | unsigned char param[2]; | ||
1527 | |||
1528 | /* This is dolphin "v1" as empirically defined by florin9doi */ | ||
1529 | param[0] = 0x64; | ||
1530 | param[1] = 0x28; | ||
1531 | |||
1532 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
1533 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | ||
1534 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) | ||
1535 | return -1; | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1502 | static void alps_set_defaults(struct alps_data *priv) | 1540 | static void alps_set_defaults(struct alps_data *priv) |
1503 | { | 1541 | { |
1504 | priv->byte0 = 0x8f; | 1542 | priv->byte0 = 0x8f; |
@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv) | |||
1532 | priv->nibble_commands = alps_v4_nibble_commands; | 1570 | priv->nibble_commands = alps_v4_nibble_commands; |
1533 | priv->addr_command = PSMOUSE_CMD_DISABLE; | 1571 | priv->addr_command = PSMOUSE_CMD_DISABLE; |
1534 | break; | 1572 | break; |
1573 | case ALPS_PROTO_V5: | ||
1574 | priv->hw_init = alps_hw_init_dolphin_v1; | ||
1575 | priv->process_packet = alps_process_packet_v3; | ||
1576 | priv->decode_fields = alps_decode_dolphin; | ||
1577 | priv->set_abs_params = alps_set_abs_params_mt; | ||
1578 | priv->nibble_commands = alps_v3_nibble_commands; | ||
1579 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
1580 | priv->byte0 = 0xc8; | ||
1581 | priv->mask0 = 0xc8; | ||
1582 | priv->flags = 0; | ||
1583 | priv->x_max = 1360; | ||
1584 | priv->y_max = 660; | ||
1585 | priv->x_bits = 23; | ||
1586 | priv->y_bits = 12; | ||
1587 | break; | ||
1535 | } | 1588 | } |
1536 | } | 1589 | } |
1537 | 1590 | ||
@@ -1592,6 +1645,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
1592 | 1645 | ||
1593 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { | 1646 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { |
1594 | return 0; | 1647 | return 0; |
1648 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && | ||
1649 | ec[0] == 0x73 && ec[1] == 0x01) { | ||
1650 | priv->proto_version = ALPS_PROTO_V5; | ||
1651 | alps_set_defaults(priv); | ||
1652 | |||
1653 | return 0; | ||
1595 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { | 1654 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { |
1596 | priv->proto_version = ALPS_PROTO_V3; | 1655 | priv->proto_version = ALPS_PROTO_V3; |
1597 | alps_set_defaults(priv); | 1656 | alps_set_defaults(priv); |