diff options
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 2a77a52d2e62..a977bfaa6821 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 2e4af24f8c15..334de19e5ddb 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 |