diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-03-27 03:27:10 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-03-27 03:27:10 -0400 |
| commit | 993808253ca256b8ca7f8ff90d9935d7c99cd32d (patch) | |
| tree | ff51c2b3f7625ae8d89b45962cc3dbc59a5152f8 /drivers/input/mouse | |
| parent | 10ce3cc919f50c2043b41ca968b43c26a3672600 (diff) | |
| parent | 131c713fd96e251fcb18f4d2d05f263aa41bb11f (diff) | |
Merge branch 'next' into for-linus
Conflicts:
drivers/input/tablet/wacom_sys.c
Diffstat (limited to 'drivers/input/mouse')
| -rw-r--r-- | drivers/input/mouse/sentelic.c | 294 | ||||
| -rw-r--r-- | drivers/input/mouse/sentelic.h | 35 |
2 files changed, 257 insertions, 72 deletions
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 2a77a52d2e6..a977bfaa682 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Finger Sensing Pad PS/2 mouse driver. | 2 | * Finger Sensing Pad PS/2 mouse driver. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | 4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. |
| 5 | * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation. | 5 | * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
| 24 | #include <linux/input/mt.h> | ||
| 24 | #include <linux/ctype.h> | 25 | #include <linux/ctype.h> |
| 25 | #include <linux/libps2.h> | 26 | #include <linux/libps2.h> |
| 26 | #include <linux/serio.h> | 27 | #include <linux/serio.h> |
| @@ -36,6 +37,9 @@ | |||
| 36 | #define FSP_CMD_TIMEOUT 200 | 37 | #define FSP_CMD_TIMEOUT 200 |
| 37 | #define FSP_CMD_TIMEOUT2 30 | 38 | #define FSP_CMD_TIMEOUT2 30 |
| 38 | 39 | ||
| 40 | #define GET_ABS_X(packet) ((packet[1] << 2) | ((packet[3] >> 2) & 0x03)) | ||
| 41 | #define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03)) | ||
| 42 | |||
| 39 | /** Driver version. */ | 43 | /** Driver version. */ |
| 40 | static const char fsp_drv_ver[] = "1.0.0-K"; | 44 | static const char fsp_drv_ver[] = "1.0.0-K"; |
| 41 | 45 | ||
| @@ -128,8 +132,9 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
| 128 | out: | 132 | out: |
| 129 | ps2_end_command(ps2dev); | 133 | ps2_end_command(ps2dev); |
| 130 | psmouse_activate(psmouse); | 134 | psmouse_activate(psmouse); |
| 131 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | 135 | psmouse_dbg(psmouse, |
| 132 | reg_addr, *reg_val, rc); | 136 | "READ REG: 0x%02x is 0x%02x (rc = %d)\n", |
| 137 | reg_addr, *reg_val, rc); | ||
| 133 | return rc; | 138 | return rc; |
| 134 | } | 139 | } |
| 135 | 140 | ||
| @@ -179,8 +184,9 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
| 179 | 184 | ||
| 180 | out: | 185 | out: |
| 181 | ps2_end_command(ps2dev); | 186 | ps2_end_command(ps2dev); |
| 182 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | 187 | psmouse_dbg(psmouse, |
| 183 | reg_addr, reg_val, rc); | 188 | "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", |
| 189 | reg_addr, reg_val, rc); | ||
| 184 | return rc; | 190 | return rc; |
| 185 | } | 191 | } |
| 186 | 192 | ||
| @@ -237,8 +243,9 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
| 237 | out: | 243 | out: |
| 238 | ps2_end_command(ps2dev); | 244 | ps2_end_command(ps2dev); |
| 239 | psmouse_activate(psmouse); | 245 | psmouse_activate(psmouse); |
| 240 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | 246 | psmouse_dbg(psmouse, |
| 241 | *reg_val, rc); | 247 | "READ PAGE REG: 0x%02x (rc = %d)\n", |
| 248 | *reg_val, rc); | ||
| 242 | return rc; | 249 | return rc; |
| 243 | } | 250 | } |
| 244 | 251 | ||
| @@ -274,8 +281,9 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
| 274 | 281 | ||
| 275 | out: | 282 | out: |
| 276 | ps2_end_command(ps2dev); | 283 | ps2_end_command(ps2dev); |
| 277 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | 284 | psmouse_dbg(psmouse, |
| 278 | reg_val, rc); | 285 | "WRITE PAGE REG: to 0x%02x (rc = %d)\n", |
| 286 | reg_val, rc); | ||
| 279 | return rc; | 287 | return rc; |
| 280 | } | 288 | } |
| 281 | 289 | ||
| @@ -319,7 +327,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) | |||
| 319 | int res = 0; | 327 | int res = 0; |
| 320 | 328 | ||
| 321 | if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { | 329 | if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { |
| 322 | dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); | 330 | psmouse_err(psmouse, "Unable get OPC state.\n"); |
| 323 | return -EIO; | 331 | return -EIO; |
| 324 | } | 332 | } |
| 325 | 333 | ||
| @@ -336,8 +344,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) | |||
| 336 | } | 344 | } |
| 337 | 345 | ||
| 338 | if (res != 0) { | 346 | if (res != 0) { |
| 339 | dev_err(&psmouse->ps2dev.serio->dev, | 347 | psmouse_err(psmouse, "Unable to enable OPC tag.\n"); |
| 340 | "Unable to enable OPC tag.\n"); | ||
| 341 | res = -EIO; | 348 | res = -EIO; |
| 342 | } | 349 | } |
| 343 | 350 | ||
| @@ -615,18 +622,40 @@ static struct attribute_group fsp_attribute_group = { | |||
| 615 | .attrs = fsp_attributes, | 622 | .attrs = fsp_attributes, |
| 616 | }; | 623 | }; |
| 617 | 624 | ||
| 618 | #ifdef FSP_DEBUG | 625 | #ifdef FSP_DEBUG |
| 619 | static void fsp_packet_debug(unsigned char packet[]) | 626 | static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) |
| 620 | { | 627 | { |
| 621 | static unsigned int ps2_packet_cnt; | 628 | static unsigned int ps2_packet_cnt; |
| 622 | static unsigned int ps2_last_second; | 629 | static unsigned int ps2_last_second; |
| 623 | unsigned int jiffies_msec; | 630 | unsigned int jiffies_msec; |
| 631 | const char *packet_type = "UNKNOWN"; | ||
| 632 | unsigned short abs_x = 0, abs_y = 0; | ||
| 633 | |||
| 634 | /* Interpret & dump the packet data. */ | ||
| 635 | switch (packet[0] >> FSP_PKT_TYPE_SHIFT) { | ||
| 636 | case FSP_PKT_TYPE_ABS: | ||
| 637 | packet_type = "Absolute"; | ||
| 638 | abs_x = GET_ABS_X(packet); | ||
| 639 | abs_y = GET_ABS_Y(packet); | ||
| 640 | break; | ||
| 641 | case FSP_PKT_TYPE_NORMAL: | ||
| 642 | packet_type = "Normal"; | ||
| 643 | break; | ||
| 644 | case FSP_PKT_TYPE_NOTIFY: | ||
| 645 | packet_type = "Notify"; | ||
| 646 | break; | ||
| 647 | case FSP_PKT_TYPE_NORMAL_OPC: | ||
| 648 | packet_type = "Normal-OPC"; | ||
| 649 | break; | ||
| 650 | } | ||
| 624 | 651 | ||
| 625 | ps2_packet_cnt++; | 652 | ps2_packet_cnt++; |
| 626 | jiffies_msec = jiffies_to_msecs(jiffies); | 653 | jiffies_msec = jiffies_to_msecs(jiffies); |
| 627 | psmouse_dbg(psmouse, | 654 | psmouse_dbg(psmouse, |
| 628 | "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", | 655 | "%08dms %s packets: %02x, %02x, %02x, %02x; " |
| 629 | jiffies_msec, packet[0], packet[1], packet[2], packet[3]); | 656 | "abs_x: %d, abs_y: %d\n", |
| 657 | jiffies_msec, packet_type, | ||
| 658 | packet[0], packet[1], packet[2], packet[3], abs_x, abs_y); | ||
| 630 | 659 | ||
| 631 | if (jiffies_msec - ps2_last_second > 1000) { | 660 | if (jiffies_msec - ps2_last_second > 1000) { |
| 632 | psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt); | 661 | psmouse_dbg(psmouse, "PS/2 packets/sec = %d\n", ps2_packet_cnt); |
| @@ -635,17 +664,29 @@ static void fsp_packet_debug(unsigned char packet[]) | |||
| 635 | } | 664 | } |
| 636 | } | 665 | } |
| 637 | #else | 666 | #else |
| 638 | static void fsp_packet_debug(unsigned char packet[]) | 667 | static void fsp_packet_debug(struct psmouse *psmouse, unsigned char packet[]) |
| 639 | { | 668 | { |
| 640 | } | 669 | } |
| 641 | #endif | 670 | #endif |
| 642 | 671 | ||
| 672 | static void fsp_set_slot(struct input_dev *dev, int slot, bool active, | ||
| 673 | unsigned int x, unsigned int y) | ||
| 674 | { | ||
| 675 | input_mt_slot(dev, slot); | ||
| 676 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | ||
| 677 | if (active) { | ||
| 678 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
| 679 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | ||
| 680 | } | ||
| 681 | } | ||
| 682 | |||
| 643 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | 683 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) |
| 644 | { | 684 | { |
| 645 | struct input_dev *dev = psmouse->dev; | 685 | struct input_dev *dev = psmouse->dev; |
| 646 | struct fsp_data *ad = psmouse->private; | 686 | struct fsp_data *ad = psmouse->private; |
| 647 | unsigned char *packet = psmouse->packet; | 687 | unsigned char *packet = psmouse->packet; |
| 648 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; | 688 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; |
| 689 | unsigned short abs_x, abs_y, fgrs = 0; | ||
| 649 | int rel_x, rel_y; | 690 | int rel_x, rel_y; |
| 650 | 691 | ||
| 651 | if (psmouse->pktcnt < 4) | 692 | if (psmouse->pktcnt < 4) |
| @@ -655,16 +696,76 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | |||
| 655 | * Full packet accumulated, process it | 696 | * Full packet accumulated, process it |
| 656 | */ | 697 | */ |
| 657 | 698 | ||
| 699 | fsp_packet_debug(psmouse, packet); | ||
| 700 | |||
| 658 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { | 701 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { |
| 659 | case FSP_PKT_TYPE_ABS: | 702 | case FSP_PKT_TYPE_ABS: |
| 660 | dev_warn(&psmouse->ps2dev.serio->dev, | 703 | abs_x = GET_ABS_X(packet); |
| 661 | "Unexpected absolute mode packet, ignored.\n"); | 704 | abs_y = GET_ABS_Y(packet); |
| 705 | |||
| 706 | if (packet[0] & FSP_PB0_MFMC) { | ||
| 707 | /* | ||
| 708 | * MFMC packet: assume that there are two fingers on | ||
| 709 | * pad | ||
| 710 | */ | ||
| 711 | fgrs = 2; | ||
| 712 | |||
| 713 | /* MFMC packet */ | ||
| 714 | if (packet[0] & FSP_PB0_MFMC_FGR2) { | ||
| 715 | /* 2nd finger */ | ||
| 716 | if (ad->last_mt_fgr == 2) { | ||
| 717 | /* | ||
| 718 | * workaround for buggy firmware | ||
| 719 | * which doesn't clear MFMC bit if | ||
| 720 | * the 1st finger is up | ||
| 721 | */ | ||
| 722 | fgrs = 1; | ||
| 723 | fsp_set_slot(dev, 0, false, 0, 0); | ||
| 724 | } | ||
| 725 | ad->last_mt_fgr = 2; | ||
| 726 | |||
| 727 | fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y); | ||
| 728 | } else { | ||
| 729 | /* 1st finger */ | ||
| 730 | if (ad->last_mt_fgr == 1) { | ||
| 731 | /* | ||
| 732 | * workaround for buggy firmware | ||
| 733 | * which doesn't clear MFMC bit if | ||
| 734 | * the 2nd finger is up | ||
| 735 | */ | ||
| 736 | fgrs = 1; | ||
| 737 | fsp_set_slot(dev, 1, false, 0, 0); | ||
| 738 | } | ||
| 739 | ad->last_mt_fgr = 1; | ||
| 740 | fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y); | ||
| 741 | } | ||
| 742 | } else { | ||
| 743 | /* SFAC packet */ | ||
| 744 | |||
| 745 | /* no multi-finger information */ | ||
| 746 | ad->last_mt_fgr = 0; | ||
| 747 | |||
| 748 | if (abs_x != 0 && abs_y != 0) | ||
| 749 | fgrs = 1; | ||
| 750 | |||
| 751 | fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); | ||
| 752 | fsp_set_slot(dev, 1, false, 0, 0); | ||
| 753 | } | ||
| 754 | if (fgrs > 0) { | ||
| 755 | input_report_abs(dev, ABS_X, abs_x); | ||
| 756 | input_report_abs(dev, ABS_Y, abs_y); | ||
| 757 | } | ||
| 758 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
| 759 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
| 760 | input_report_key(dev, BTN_TOUCH, fgrs); | ||
| 761 | input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1); | ||
| 762 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2); | ||
| 662 | break; | 763 | break; |
| 663 | 764 | ||
| 664 | case FSP_PKT_TYPE_NORMAL_OPC: | 765 | case FSP_PKT_TYPE_NORMAL_OPC: |
| 665 | /* on-pad click, filter it if necessary */ | 766 | /* on-pad click, filter it if necessary */ |
| 666 | if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) | 767 | if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) |
| 667 | packet[0] &= ~BIT(0); | 768 | packet[0] &= ~FSP_PB0_LBTN; |
| 668 | /* fall through */ | 769 | /* fall through */ |
| 669 | 770 | ||
| 670 | case FSP_PKT_TYPE_NORMAL: | 771 | case FSP_PKT_TYPE_NORMAL: |
| @@ -711,8 +812,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | |||
| 711 | 812 | ||
| 712 | input_sync(dev); | 813 | input_sync(dev); |
| 713 | 814 | ||
| 714 | fsp_packet_debug(packet); | ||
| 715 | |||
| 716 | return PSMOUSE_FULL_PACKET; | 815 | return PSMOUSE_FULL_PACKET; |
| 717 | } | 816 | } |
| 718 | 817 | ||
| @@ -736,42 +835,106 @@ static int fsp_activate_protocol(struct psmouse *psmouse) | |||
| 736 | 835 | ||
| 737 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); | 836 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); |
| 738 | if (param[0] != 0x04) { | 837 | if (param[0] != 0x04) { |
| 739 | dev_err(&psmouse->ps2dev.serio->dev, | 838 | psmouse_err(psmouse, |
| 740 | "Unable to enable 4 bytes packet format.\n"); | 839 | "Unable to enable 4 bytes packet format.\n"); |
| 741 | return -EIO; | 840 | return -EIO; |
| 742 | } | 841 | } |
| 743 | 842 | ||
| 744 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { | 843 | if (pad->ver < FSP_VER_STL3888_C0) { |
| 745 | dev_err(&psmouse->ps2dev.serio->dev, | 844 | /* Preparing relative coordinates output for older hardware */ |
| 746 | "Unable to read SYSCTL5 register.\n"); | 845 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { |
| 747 | return -EIO; | 846 | psmouse_err(psmouse, |
| 748 | } | 847 | "Unable to read SYSCTL5 register.\n"); |
| 848 | return -EIO; | ||
| 849 | } | ||
| 749 | 850 | ||
| 750 | val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); | 851 | if (fsp_get_buttons(psmouse, &pad->buttons)) { |
| 751 | /* Ensure we are not in absolute mode */ | 852 | psmouse_err(psmouse, |
| 752 | val &= ~FSP_BIT_EN_PKT_G0; | 853 | "Unable to retrieve number of buttons.\n"); |
| 753 | if (pad->buttons == 0x06) { | 854 | return -EIO; |
| 754 | /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | 855 | } |
| 755 | val |= FSP_BIT_EN_MSID6; | ||
| 756 | } | ||
| 757 | 856 | ||
| 758 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { | 857 | val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); |
| 759 | dev_err(&psmouse->ps2dev.serio->dev, | 858 | /* Ensure we are not in absolute mode */ |
| 760 | "Unable to set up required mode bits.\n"); | 859 | val &= ~FSP_BIT_EN_PKT_G0; |
| 761 | return -EIO; | 860 | if (pad->buttons == 0x06) { |
| 861 | /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
| 862 | val |= FSP_BIT_EN_MSID6; | ||
| 863 | } | ||
| 864 | |||
| 865 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { | ||
| 866 | psmouse_err(psmouse, | ||
| 867 | "Unable to set up required mode bits.\n"); | ||
| 868 | return -EIO; | ||
| 869 | } | ||
| 870 | |||
| 871 | /* | ||
| 872 | * Enable OPC tags such that driver can tell the difference | ||
| 873 | * between on-pad and real button click | ||
| 874 | */ | ||
| 875 | if (fsp_opc_tag_enable(psmouse, true)) | ||
| 876 | psmouse_warn(psmouse, | ||
| 877 | "Failed to enable OPC tag mode.\n"); | ||
| 878 | /* enable on-pad click by default */ | ||
| 879 | pad->flags |= FSPDRV_FLAG_EN_OPC; | ||
| 880 | |||
| 881 | /* Enable on-pad vertical and horizontal scrolling */ | ||
| 882 | fsp_onpad_vscr(psmouse, true); | ||
| 883 | fsp_onpad_hscr(psmouse, true); | ||
| 884 | } else { | ||
| 885 | /* Enable absolute coordinates output for Cx/Dx hardware */ | ||
| 886 | if (fsp_reg_write(psmouse, FSP_REG_SWC1, | ||
| 887 | FSP_BIT_SWC1_EN_ABS_1F | | ||
| 888 | FSP_BIT_SWC1_EN_ABS_2F | | ||
| 889 | FSP_BIT_SWC1_EN_FUP_OUT | | ||
| 890 | FSP_BIT_SWC1_EN_ABS_CON)) { | ||
| 891 | psmouse_err(psmouse, | ||
| 892 | "Unable to enable absolute coordinates output.\n"); | ||
| 893 | return -EIO; | ||
| 894 | } | ||
| 762 | } | 895 | } |
| 763 | 896 | ||
| 764 | /* | 897 | return 0; |
| 765 | * Enable OPC tags such that driver can tell the difference between | 898 | } |
| 766 | * on-pad and real button click | ||
| 767 | */ | ||
| 768 | if (fsp_opc_tag_enable(psmouse, true)) | ||
| 769 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
| 770 | "Failed to enable OPC tag mode.\n"); | ||
| 771 | 899 | ||
| 772 | /* Enable on-pad vertical and horizontal scrolling */ | 900 | static int fsp_set_input_params(struct psmouse *psmouse) |
| 773 | fsp_onpad_vscr(psmouse, true); | 901 | { |
| 774 | fsp_onpad_hscr(psmouse, true); | 902 | struct input_dev *dev = psmouse->dev; |
| 903 | struct fsp_data *pad = psmouse->private; | ||
| 904 | |||
| 905 | if (pad->ver < FSP_VER_STL3888_C0) { | ||
| 906 | __set_bit(BTN_MIDDLE, dev->keybit); | ||
| 907 | __set_bit(BTN_BACK, dev->keybit); | ||
| 908 | __set_bit(BTN_FORWARD, dev->keybit); | ||
| 909 | __set_bit(REL_WHEEL, dev->relbit); | ||
| 910 | __set_bit(REL_HWHEEL, dev->relbit); | ||
| 911 | } else { | ||
| 912 | /* | ||
| 913 | * Hardware prior to Cx performs much better in relative mode; | ||
| 914 | * hence, only enable absolute coordinates output as well as | ||
| 915 | * multi-touch output for the newer hardware. | ||
| 916 | * | ||
| 917 | * Maximum coordinates can be computed as: | ||
| 918 | * | ||
| 919 | * number of scanlines * 64 - 57 | ||
| 920 | * | ||
| 921 | * where number of X/Y scanline lines are 16/12. | ||
| 922 | */ | ||
| 923 | int abs_x = 967, abs_y = 711; | ||
| 924 | |||
| 925 | __set_bit(EV_ABS, dev->evbit); | ||
| 926 | __clear_bit(EV_REL, dev->evbit); | ||
| 927 | __set_bit(BTN_TOUCH, dev->keybit); | ||
| 928 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | ||
| 929 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | ||
| 930 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
| 931 | |||
| 932 | input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0); | ||
| 933 | input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0); | ||
| 934 | input_mt_init_slots(dev, 2); | ||
| 935 | input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0); | ||
| 936 | input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0); | ||
| 937 | } | ||
| 775 | 938 | ||
| 776 | return 0; | 939 | return 0; |
| 777 | } | 940 | } |
| @@ -829,18 +992,16 @@ static int fsp_reconnect(struct psmouse *psmouse) | |||
| 829 | int fsp_init(struct psmouse *psmouse) | 992 | int fsp_init(struct psmouse *psmouse) |
| 830 | { | 993 | { |
| 831 | struct fsp_data *priv; | 994 | struct fsp_data *priv; |
| 832 | int ver, rev, buttons; | 995 | int ver, rev; |
| 833 | int error; | 996 | int error; |
| 834 | 997 | ||
| 835 | if (fsp_get_version(psmouse, &ver) || | 998 | if (fsp_get_version(psmouse, &ver) || |
| 836 | fsp_get_revision(psmouse, &rev) || | 999 | fsp_get_revision(psmouse, &rev)) { |
| 837 | fsp_get_buttons(psmouse, &buttons)) { | ||
| 838 | return -ENODEV; | 1000 | return -ENODEV; |
| 839 | } | 1001 | } |
| 840 | 1002 | ||
| 841 | psmouse_info(psmouse, | 1003 | psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s\n", |
| 842 | "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", | 1004 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver); |
| 843 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); | ||
| 844 | 1005 | ||
| 845 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); | 1006 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); |
| 846 | if (!priv) | 1007 | if (!priv) |
| @@ -848,17 +1009,6 @@ int fsp_init(struct psmouse *psmouse) | |||
| 848 | 1009 | ||
| 849 | priv->ver = ver; | 1010 | priv->ver = ver; |
| 850 | priv->rev = rev; | 1011 | priv->rev = rev; |
| 851 | priv->buttons = buttons; | ||
| 852 | |||
| 853 | /* enable on-pad click by default */ | ||
| 854 | priv->flags |= FSPDRV_FLAG_EN_OPC; | ||
| 855 | |||
| 856 | /* Set up various supported input event bits */ | ||
| 857 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 858 | __set_bit(BTN_BACK, psmouse->dev->keybit); | ||
| 859 | __set_bit(BTN_FORWARD, psmouse->dev->keybit); | ||
| 860 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | ||
| 861 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); | ||
| 862 | 1012 | ||
| 863 | psmouse->protocol_handler = fsp_process_byte; | 1013 | psmouse->protocol_handler = fsp_process_byte; |
| 864 | psmouse->disconnect = fsp_disconnect; | 1014 | psmouse->disconnect = fsp_disconnect; |
| @@ -866,16 +1016,20 @@ int fsp_init(struct psmouse *psmouse) | |||
| 866 | psmouse->cleanup = fsp_reset; | 1016 | psmouse->cleanup = fsp_reset; |
| 867 | psmouse->pktsize = 4; | 1017 | psmouse->pktsize = 4; |
| 868 | 1018 | ||
| 869 | /* set default packet output based on number of buttons we found */ | ||
| 870 | error = fsp_activate_protocol(psmouse); | 1019 | error = fsp_activate_protocol(psmouse); |
| 871 | if (error) | 1020 | if (error) |
| 872 | goto err_out; | 1021 | goto err_out; |
| 873 | 1022 | ||
| 1023 | /* Set up various supported input event bits */ | ||
| 1024 | error = fsp_set_input_params(psmouse); | ||
| 1025 | if (error) | ||
| 1026 | goto err_out; | ||
| 1027 | |||
| 874 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | 1028 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, |
| 875 | &fsp_attribute_group); | 1029 | &fsp_attribute_group); |
| 876 | if (error) { | 1030 | if (error) { |
| 877 | dev_err(&psmouse->ps2dev.serio->dev, | 1031 | psmouse_err(psmouse, |
| 878 | "Failed to create sysfs attributes (%d)", error); | 1032 | "Failed to create sysfs attributes (%d)", error); |
| 879 | goto err_out; | 1033 | goto err_out; |
| 880 | } | 1034 | } |
| 881 | 1035 | ||
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h index 2e4af24f8c1..334de19e5dd 100644 --- a/drivers/input/mouse/sentelic.h +++ b/drivers/input/mouse/sentelic.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Finger Sensing Pad PS/2 mouse driver. | 2 | * Finger Sensing Pad PS/2 mouse driver. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | 4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. |
| 5 | * Copyright (C) 2005-2011 Tai-hwa Liang, Sentelic Corporation. | 5 | * Copyright (C) 2005-2012 Tai-hwa Liang, Sentelic Corporation. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
| @@ -55,6 +55,16 @@ | |||
| 55 | #define FSP_BIT_FIX_HSCR BIT(5) | 55 | #define FSP_BIT_FIX_HSCR BIT(5) |
| 56 | #define FSP_BIT_DRAG_LOCK BIT(6) | 56 | #define FSP_BIT_DRAG_LOCK BIT(6) |
| 57 | 57 | ||
| 58 | #define FSP_REG_SWC1 (0x90) | ||
| 59 | #define FSP_BIT_SWC1_EN_ABS_1F BIT(0) | ||
| 60 | #define FSP_BIT_SWC1_EN_GID BIT(1) | ||
| 61 | #define FSP_BIT_SWC1_EN_ABS_2F BIT(2) | ||
| 62 | #define FSP_BIT_SWC1_EN_FUP_OUT BIT(3) | ||
| 63 | #define FSP_BIT_SWC1_EN_ABS_CON BIT(4) | ||
| 64 | #define FSP_BIT_SWC1_GST_GRP0 BIT(5) | ||
| 65 | #define FSP_BIT_SWC1_GST_GRP1 BIT(6) | ||
| 66 | #define FSP_BIT_SWC1_BX_COMPAT BIT(7) | ||
| 67 | |||
| 58 | /* Finger-sensing Pad packet formating related definitions */ | 68 | /* Finger-sensing Pad packet formating related definitions */ |
| 59 | 69 | ||
| 60 | /* absolute packet type */ | 70 | /* absolute packet type */ |
| @@ -64,12 +74,32 @@ | |||
| 64 | #define FSP_PKT_TYPE_NORMAL_OPC (0x03) | 74 | #define FSP_PKT_TYPE_NORMAL_OPC (0x03) |
| 65 | #define FSP_PKT_TYPE_SHIFT (6) | 75 | #define FSP_PKT_TYPE_SHIFT (6) |
| 66 | 76 | ||
| 77 | /* bit definitions for the first byte of report packet */ | ||
| 78 | #define FSP_PB0_LBTN BIT(0) | ||
| 79 | #define FSP_PB0_RBTN BIT(1) | ||
| 80 | #define FSP_PB0_MBTN BIT(2) | ||
| 81 | #define FSP_PB0_MFMC_FGR2 FSP_PB0_MBTN | ||
| 82 | #define FSP_PB0_MUST_SET BIT(3) | ||
| 83 | #define FSP_PB0_PHY_BTN BIT(4) | ||
| 84 | #define FSP_PB0_MFMC BIT(5) | ||
| 85 | |||
| 86 | /* hardware revisions */ | ||
| 87 | #define FSP_VER_STL3888_A4 (0xC1) | ||
| 88 | #define FSP_VER_STL3888_B0 (0xD0) | ||
| 89 | #define FSP_VER_STL3888_B1 (0xD1) | ||
| 90 | #define FSP_VER_STL3888_B2 (0xD2) | ||
| 91 | #define FSP_VER_STL3888_C0 (0xE0) | ||
| 92 | #define FSP_VER_STL3888_C1 (0xE1) | ||
| 93 | #define FSP_VER_STL3888_D0 (0xE2) | ||
| 94 | #define FSP_VER_STL3888_D1 (0xE3) | ||
| 95 | #define FSP_VER_STL3888_E0 (0xE4) | ||
| 96 | |||
| 67 | #ifdef __KERNEL__ | 97 | #ifdef __KERNEL__ |
| 68 | 98 | ||
| 69 | struct fsp_data { | 99 | struct fsp_data { |
| 70 | unsigned char ver; /* hardware version */ | 100 | unsigned char ver; /* hardware version */ |
| 71 | unsigned char rev; /* hardware revison */ | 101 | unsigned char rev; /* hardware revison */ |
| 72 | unsigned char buttons; /* Number of buttons */ | 102 | unsigned int buttons; /* Number of buttons */ |
| 73 | unsigned int flags; | 103 | unsigned int flags; |
| 74 | #define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */ | 104 | #define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */ |
| 75 | 105 | ||
| @@ -78,6 +108,7 @@ struct fsp_data { | |||
| 78 | 108 | ||
| 79 | unsigned char last_reg; /* Last register we requested read from */ | 109 | unsigned char last_reg; /* Last register we requested read from */ |
| 80 | unsigned char last_val; | 110 | unsigned char last_val; |
| 111 | unsigned int last_mt_fgr; /* Last seen finger(multitouch) */ | ||
| 81 | }; | 112 | }; |
| 82 | 113 | ||
| 83 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | 114 | #ifdef CONFIG_MOUSE_PS2_SENTELIC |
