Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: ALPS - add support for "Dolphin" devices

This adds support for another flavor of ALPS protocol used in newer
"Dolphin" devices.

Signed-off-by: Yunkang Tang <yunkang.tang@cn.alps.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Yunkang Tang and committed by
Dmitry Torokhov
ee65d4b3 01d08185

+176 -39
+170 -38
drivers/input/mouse/alps.c
··· 277 277 } 278 278 279 279 /* 280 + * Process bitmap data for V5 protocols. Return value is null. 281 + * 282 + * The bitmaps don't have enough data to track fingers, so this function 283 + * only generates points representing a bounding box of at most two contacts. 284 + * These two points are returned in x1, y1, x2, and y2. 285 + */ 286 + static void alps_process_bitmap_dolphin(struct alps_data *priv, 287 + struct alps_fields *fields, 288 + int *x1, int *y1, int *x2, int *y2) 289 + { 290 + int box_middle_x, box_middle_y; 291 + unsigned int x_map, y_map; 292 + unsigned char start_bit, end_bit; 293 + unsigned char x_msb, x_lsb, y_msb, y_lsb; 294 + 295 + x_map = fields->x_map; 296 + y_map = fields->y_map; 297 + 298 + if (!x_map || !y_map) 299 + return; 300 + 301 + /* Get Most-significant and Least-significant bit */ 302 + x_msb = fls(x_map); 303 + x_lsb = ffs(x_map); 304 + y_msb = fls(y_map); 305 + y_lsb = ffs(y_map); 306 + 307 + /* Most-significant bit should never exceed max sensor line number */ 308 + if (x_msb > priv->x_bits || y_msb > priv->y_bits) 309 + return; 310 + 311 + *x1 = *y1 = *x2 = *y2 = 0; 312 + 313 + if (fields->fingers > 1) { 314 + start_bit = priv->x_bits - x_msb; 315 + end_bit = priv->x_bits - x_lsb; 316 + box_middle_x = (priv->x_max * (start_bit + end_bit)) / 317 + (2 * (priv->x_bits - 1)); 318 + 319 + start_bit = y_lsb - 1; 320 + end_bit = y_msb - 1; 321 + box_middle_y = (priv->y_max * (start_bit + end_bit)) / 322 + (2 * (priv->y_bits - 1)); 323 + *x1 = fields->x; 324 + *y1 = fields->y; 325 + *x2 = 2 * box_middle_x - *x1; 326 + *y2 = 2 * box_middle_y - *y1; 327 + } 328 + } 329 + 330 + /* 280 331 * Process bitmap data from v3 and v4 protocols. Returns the number of 281 332 * fingers detected. A return value of 0 means at least one of the 282 333 * bitmaps was empty. ··· 532 481 f->ts_middle = !!(p[3] & 0x40); 533 482 } 534 483 535 - static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) 484 + static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, 485 + struct psmouse *psmouse) 536 486 { 537 487 f->first_mp = !!(p[4] & 0x40); 538 488 f->is_mp = !!(p[0] & 0x40); ··· 554 502 alps_decode_buttons_v3(f, p); 555 503 } 556 504 557 - static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) 505 + static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p, 506 + struct psmouse *psmouse) 558 507 { 559 - alps_decode_pinnacle(f, p); 508 + alps_decode_pinnacle(f, p, psmouse); 560 509 561 510 f->x_map |= (p[5] & 0x10) << 11; 562 511 f->y_map |= (p[5] & 0x20) << 6; 563 512 } 564 513 565 - static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) 514 + static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p, 515 + struct psmouse *psmouse) 566 516 { 517 + u64 palm_data = 0; 518 + struct alps_data *priv = psmouse->private; 519 + 567 520 f->first_mp = !!(p[0] & 0x02); 568 521 f->is_mp = !!(p[0] & 0x20); 569 522 570 - f->fingers = ((p[0] & 0x6) >> 1 | 523 + if (!f->is_mp) { 524 + f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); 525 + f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); 526 + f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; 527 + alps_decode_buttons_v3(f, p); 528 + } else { 529 + f->fingers = ((p[0] & 0x6) >> 1 | 571 530 (p[0] & 0x10) >> 2); 572 - f->x_map = ((p[2] & 0x60) >> 5) | 573 - ((p[4] & 0x7f) << 2) | 574 - ((p[5] & 0x7f) << 9) | 575 - ((p[3] & 0x07) << 16) | 576 - ((p[3] & 0x70) << 15) | 577 - ((p[0] & 0x01) << 22); 578 - f->y_map = (p[1] & 0x7f) | 579 - ((p[2] & 0x1f) << 7); 580 531 581 - f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); 582 - f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); 583 - f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; 532 + palm_data = (p[1] & 0x7f) | 533 + ((p[2] & 0x7f) << 7) | 534 + ((p[4] & 0x7f) << 14) | 535 + ((p[5] & 0x7f) << 21) | 536 + ((p[3] & 0x07) << 28) | 537 + (((u64)p[3] & 0x70) << 27) | 538 + (((u64)p[0] & 0x01) << 34); 584 539 585 - alps_decode_buttons_v3(f, p); 540 + /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */ 541 + f->y_map = palm_data & (BIT(priv->y_bits) - 1); 542 + 543 + /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */ 544 + f->x_map = (palm_data >> priv->y_bits) & 545 + (BIT(priv->x_bits) - 1); 546 + } 586 547 } 587 548 588 - static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) 549 + static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) 589 550 { 590 551 struct alps_data *priv = psmouse->private; 591 552 unsigned char *packet = psmouse->packet; 592 553 struct input_dev *dev = psmouse->dev; 593 554 struct input_dev *dev2 = priv->dev2; 594 555 int x1 = 0, y1 = 0, x2 = 0, y2 = 0; 595 - int fingers = 0, bmap_fingers; 596 - struct alps_fields f; 556 + int fingers = 0, bmap_fn; 557 + struct alps_fields f = {0}; 597 558 598 - priv->decode_fields(&f, packet); 559 + priv->decode_fields(&f, packet, psmouse); 599 560 600 561 /* 601 562 * There's no single feature of touchpad position and bitmap packets ··· 625 560 */ 626 561 if (f.is_mp) { 627 562 fingers = f.fingers; 628 - bmap_fingers = alps_process_bitmap(priv, 629 - f.x_map, f.y_map, 630 - &x1, &y1, &x2, &y2); 563 + if (priv->proto_version == ALPS_PROTO_V3) { 564 + bmap_fn = alps_process_bitmap(priv, f.x_map, 565 + f.y_map, &x1, &y1, 566 + &x2, &y2); 631 567 632 - /* 633 - * We shouldn't report more than one finger if 634 - * we don't have two coordinates. 635 - */ 636 - if (fingers > 1 && bmap_fingers < 2) 637 - fingers = bmap_fingers; 568 + /* 569 + * We shouldn't report more than one finger if 570 + * we don't have two coordinates. 571 + */ 572 + if (fingers > 1 && bmap_fn < 2) 573 + fingers = bmap_fn; 638 574 639 - /* Now process position packet */ 640 - priv->decode_fields(&f, priv->multi_data); 575 + /* Now process position packet */ 576 + priv->decode_fields(&f, priv->multi_data, 577 + psmouse); 578 + } else { 579 + /* 580 + * Because Dolphin uses position packet's 581 + * coordinate data as Pt1 and uses it to 582 + * calculate Pt2, so we need to do position 583 + * packet decode first. 584 + */ 585 + priv->decode_fields(&f, priv->multi_data, 586 + psmouse); 587 + 588 + /* 589 + * Since Dolphin's finger number is reliable, 590 + * there is no need to compare with bmap_fn. 591 + */ 592 + alps_process_bitmap_dolphin(priv, &f, &x1, &y1, 593 + &x2, &y2); 594 + } 641 595 } else { 642 596 priv->multi_packet = 0; 643 597 } ··· 746 662 return; 747 663 } 748 664 749 - alps_process_touchpad_packet_v3(psmouse); 665 + alps_process_touchpad_packet_v3_v5(psmouse); 750 666 } 751 667 752 668 static void alps_process_packet_v6(struct psmouse *psmouse) ··· 1793 1709 return -1; 1794 1710 } 1795 1711 1712 + static int alps_dolphin_get_device_area(struct psmouse *psmouse, 1713 + struct alps_data *priv) 1714 + { 1715 + struct ps2dev *ps2dev = &psmouse->ps2dev; 1716 + unsigned char param[4] = {0}; 1717 + int num_x_electrode, num_y_electrode; 1718 + 1719 + if (alps_enter_command_mode(psmouse)) 1720 + return -1; 1721 + 1722 + param[0] = 0x0a; 1723 + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || 1724 + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || 1725 + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || 1726 + ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) || 1727 + ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE)) 1728 + return -1; 1729 + 1730 + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) 1731 + return -1; 1732 + 1733 + /* 1734 + * Dolphin's sensor line number is not fixed. It can be calculated 1735 + * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET. 1736 + * Further more, we can get device's x_max and y_max by multiplying 1737 + * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE. 1738 + * 1739 + * e.g. When we get register's sensor_x = 11 & sensor_y = 8, 1740 + * real sensor line number X = 11 + 8 = 19, and 1741 + * real sensor line number Y = 8 + 1 = 9. 1742 + * So, x_max = (19 - 1) * 64 = 1152, and 1743 + * y_max = (9 - 1) * 64 = 512. 1744 + */ 1745 + num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F); 1746 + num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F); 1747 + priv->x_bits = num_x_electrode; 1748 + priv->y_bits = num_y_electrode; 1749 + priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; 1750 + priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE; 1751 + 1752 + if (alps_exit_command_mode(psmouse)) 1753 + return -1; 1754 + 1755 + return 0; 1756 + } 1757 + 1796 1758 static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) 1797 1759 { 1798 1760 struct ps2dev *ps2dev = &psmouse->ps2dev; ··· 1893 1763 break; 1894 1764 case ALPS_PROTO_V5: 1895 1765 priv->hw_init = alps_hw_init_dolphin_v1; 1896 - priv->process_packet = alps_process_packet_v3; 1766 + priv->process_packet = alps_process_touchpad_packet_v3_v5; 1897 1767 priv->decode_fields = alps_decode_dolphin; 1898 1768 priv->set_abs_params = alps_set_abs_params_mt; 1899 1769 priv->nibble_commands = alps_v3_nibble_commands; 1900 1770 priv->addr_command = PSMOUSE_CMD_RESET_WRAP; 1901 1771 priv->byte0 = 0xc8; 1902 - priv->mask0 = 0xc8; 1772 + priv->mask0 = 0xd8; 1903 1773 priv->flags = 0; 1904 1774 priv->x_max = 1360; 1905 1775 priv->y_max = 660; ··· 1975 1845 if (alps_match_table(psmouse, priv, e7, ec) == 0) { 1976 1846 return 0; 1977 1847 } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && 1978 - ec[0] == 0x73 && ec[1] == 0x01) { 1848 + ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) { 1979 1849 priv->proto_version = ALPS_PROTO_V5; 1980 1850 alps_set_defaults(priv); 1981 - 1982 - return 0; 1851 + if (alps_dolphin_get_device_area(psmouse, priv)) 1852 + return -EIO; 1853 + else 1854 + return 0; 1983 1855 } else if (ec[0] == 0x88 && ec[1] == 0x08) { 1984 1856 priv->proto_version = ALPS_PROTO_V3; 1985 1857 alps_set_defaults(priv);
+6 -1
drivers/input/mouse/alps.h
··· 19 19 #define ALPS_PROTO_V5 5 20 20 #define ALPS_PROTO_V6 6 21 21 22 + #define DOLPHIN_COUNT_PER_ELECTRODE 64 23 + #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ 24 + #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ 25 + 22 26 /** 23 27 * struct alps_model_info - touchpad ID table 24 28 * @signature: E7 response string to match. ··· 150 146 151 147 int (*hw_init)(struct psmouse *psmouse); 152 148 void (*process_packet)(struct psmouse *psmouse); 153 - void (*decode_fields)(struct alps_fields *f, unsigned char *p); 149 + void (*decode_fields)(struct alps_fields *f, unsigned char *p, 150 + struct psmouse *psmouse); 154 151 void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); 155 152 156 153 int prev_fin;