diff options
author | Tai-hwa Liang <avatar@sentelic.com> | 2012-03-25 20:16:36 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-03-25 20:18:10 -0400 |
commit | a4c85075f00d56b38f5c277ab89f9aaad69eb17b (patch) | |
tree | 572cf90d91ec2315d10a5504191b4f8528bef2ce /drivers/input/mouse | |
parent | 3ac1780f9e6ed212e56d4132e997551297a97112 (diff) |
Input: sentelic - enabling absolute coordinates output for newer hardware
- Hooking multi-finger coordinates output with kernel multitouch library;
- Enabling absolute coordinates output for Cx+ hardware. The older hardware
performs much better in relative mode; thus relative mode related code
are preserved.
Part of the code is based on the work done by Oskari Saarenmaa <os@ohmu.fi>,
which was used to support the clickpad found on ASUS UX21/31 Ultrabook.
On the other hand, the FSP found on UX21/31 doesn't have hardware capability
register other than PnP ID, which means that we'll have to figure out an
alternative approach to identify such pad correctly; otherwise, blindly
adding INPUT_PROP_BUTTONPAD property may compatability issues amongst
existing FSPs.
Signed-off-by: Tai-hwa Liang <avatar@sentelic.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/sentelic.c | 114 | ||||
-rw-r--r-- | drivers/input/mouse/sentelic.h | 22 |
2 files changed, 132 insertions, 4 deletions
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 62fa69825671..5ea5c689d262 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> |
@@ -643,12 +644,24 @@ static void fsp_packet_debug(unsigned char packet[]) | |||
643 | } | 644 | } |
644 | #endif | 645 | #endif |
645 | 646 | ||
647 | static void fsp_set_slot(struct input_dev *dev, int slot, bool active, | ||
648 | unsigned int x, unsigned int y) | ||
649 | { | ||
650 | input_mt_slot(dev, slot); | ||
651 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | ||
652 | if (active) { | ||
653 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
654 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | ||
655 | } | ||
656 | } | ||
657 | |||
646 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | 658 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) |
647 | { | 659 | { |
648 | struct input_dev *dev = psmouse->dev; | 660 | struct input_dev *dev = psmouse->dev; |
649 | struct fsp_data *ad = psmouse->private; | 661 | struct fsp_data *ad = psmouse->private; |
650 | unsigned char *packet = psmouse->packet; | 662 | unsigned char *packet = psmouse->packet; |
651 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; | 663 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; |
664 | unsigned short abs_x, abs_y, fgrs = 0; | ||
652 | int rel_x, rel_y; | 665 | int rel_x, rel_y; |
653 | 666 | ||
654 | if (psmouse->pktcnt < 4) | 667 | if (psmouse->pktcnt < 4) |
@@ -660,8 +673,66 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | |||
660 | 673 | ||
661 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { | 674 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { |
662 | case FSP_PKT_TYPE_ABS: | 675 | case FSP_PKT_TYPE_ABS: |
663 | psmouse_warn(psmouse, | 676 | abs_x = (packet[1] << 2) | ((packet[3] >> 2) & 0x03); |
664 | "Unexpected absolute mode packet, ignored.\n"); | 677 | abs_y = (packet[2] << 2) | (packet[3] & 0x03); |
678 | |||
679 | if (packet[0] & FSP_PB0_MFMC) { | ||
680 | /* | ||
681 | * MFMC packet: assume that there are two fingers on | ||
682 | * pad | ||
683 | */ | ||
684 | fgrs = 2; | ||
685 | |||
686 | /* MFMC packet */ | ||
687 | if (packet[0] & FSP_PB0_MFMC_FGR2) { | ||
688 | /* 2nd finger */ | ||
689 | if (ad->last_mt_fgr == 2) { | ||
690 | /* | ||
691 | * workaround for buggy firmware | ||
692 | * which doesn't clear MFMC bit if | ||
693 | * the 1st finger is up | ||
694 | */ | ||
695 | fgrs = 1; | ||
696 | fsp_set_slot(dev, 0, false, 0, 0); | ||
697 | } | ||
698 | ad->last_mt_fgr = 2; | ||
699 | |||
700 | fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y); | ||
701 | } else { | ||
702 | /* 1st finger */ | ||
703 | if (ad->last_mt_fgr == 1) { | ||
704 | /* | ||
705 | * workaround for buggy firmware | ||
706 | * which doesn't clear MFMC bit if | ||
707 | * the 2nd finger is up | ||
708 | */ | ||
709 | fgrs = 1; | ||
710 | fsp_set_slot(dev, 1, false, 0, 0); | ||
711 | } | ||
712 | ad->last_mt_fgr = 1; | ||
713 | fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y); | ||
714 | } | ||
715 | } else { | ||
716 | /* SFAC packet */ | ||
717 | |||
718 | /* no multi-finger information */ | ||
719 | ad->last_mt_fgr = 0; | ||
720 | |||
721 | if (abs_x != 0 && abs_y != 0) | ||
722 | fgrs = 1; | ||
723 | |||
724 | fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); | ||
725 | fsp_set_slot(dev, 1, false, 0, 0); | ||
726 | } | ||
727 | if (fgrs > 0) { | ||
728 | input_report_abs(dev, ABS_X, abs_x); | ||
729 | input_report_abs(dev, ABS_Y, abs_y); | ||
730 | } | ||
731 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
732 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
733 | input_report_key(dev, BTN_TOUCH, fgrs); | ||
734 | input_report_key(dev, BTN_TOOL_FINGER, fgrs == 1); | ||
735 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fgrs == 2); | ||
665 | break; | 736 | break; |
666 | 737 | ||
667 | case FSP_PKT_TYPE_NORMAL_OPC: | 738 | case FSP_PKT_TYPE_NORMAL_OPC: |
@@ -785,6 +856,17 @@ static int fsp_activate_protocol(struct psmouse *psmouse) | |||
785 | /* Enable on-pad vertical and horizontal scrolling */ | 856 | /* Enable on-pad vertical and horizontal scrolling */ |
786 | fsp_onpad_vscr(psmouse, true); | 857 | fsp_onpad_vscr(psmouse, true); |
787 | fsp_onpad_hscr(psmouse, true); | 858 | fsp_onpad_hscr(psmouse, true); |
859 | } else { | ||
860 | /* Enable absolute coordinates output for Cx/Dx hardware */ | ||
861 | if (fsp_reg_write(psmouse, FSP_REG_SWC1, | ||
862 | FSP_BIT_SWC1_EN_ABS_1F | | ||
863 | FSP_BIT_SWC1_EN_ABS_2F | | ||
864 | FSP_BIT_SWC1_EN_FUP_OUT | | ||
865 | FSP_BIT_SWC1_EN_ABS_CON)) { | ||
866 | psmouse_err(psmouse, | ||
867 | "Unable to enable absolute coordinates output.\n"); | ||
868 | return -EIO; | ||
869 | } | ||
788 | } | 870 | } |
789 | 871 | ||
790 | return 0; | 872 | return 0; |
@@ -801,6 +883,32 @@ static int fsp_set_input_params(struct psmouse *psmouse) | |||
801 | __set_bit(BTN_FORWARD, dev->keybit); | 883 | __set_bit(BTN_FORWARD, dev->keybit); |
802 | __set_bit(REL_WHEEL, dev->relbit); | 884 | __set_bit(REL_WHEEL, dev->relbit); |
803 | __set_bit(REL_HWHEEL, dev->relbit); | 885 | __set_bit(REL_HWHEEL, dev->relbit); |
886 | } else { | ||
887 | /* | ||
888 | * Hardware prior to Cx performs much better in relative mode; | ||
889 | * hence, only enable absolute coordinates output as well as | ||
890 | * multi-touch output for the newer hardware. | ||
891 | * | ||
892 | * Maximum coordinates can be computed as: | ||
893 | * | ||
894 | * number of scanlines * 64 - 57 | ||
895 | * | ||
896 | * where number of X/Y scanline lines are 16/12. | ||
897 | */ | ||
898 | int abs_x = 967, abs_y = 711; | ||
899 | |||
900 | __set_bit(EV_ABS, dev->evbit); | ||
901 | __clear_bit(EV_REL, dev->evbit); | ||
902 | __set_bit(BTN_TOUCH, dev->keybit); | ||
903 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | ||
904 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | ||
905 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
906 | |||
907 | input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0); | ||
908 | input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0); | ||
909 | input_mt_init_slots(dev, 2); | ||
910 | input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0); | ||
911 | input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0); | ||
804 | } | 912 | } |
805 | 913 | ||
806 | return 0; | 914 | return 0; |
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h index 23bd25e539ba..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,6 +74,15 @@ | |||
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 | |||
67 | /* hardware revisions */ | 86 | /* hardware revisions */ |
68 | #define FSP_VER_STL3888_A4 (0xC1) | 87 | #define FSP_VER_STL3888_A4 (0xC1) |
69 | #define FSP_VER_STL3888_B0 (0xD0) | 88 | #define FSP_VER_STL3888_B0 (0xD0) |
@@ -89,6 +108,7 @@ struct fsp_data { | |||
89 | 108 | ||
90 | unsigned char last_reg; /* Last register we requested read from */ | 109 | unsigned char last_reg; /* Last register we requested read from */ |
91 | unsigned char last_val; | 110 | unsigned char last_val; |
111 | unsigned int last_mt_fgr; /* Last seen finger(multitouch) */ | ||
92 | }; | 112 | }; |
93 | 113 | ||
94 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | 114 | #ifdef CONFIG_MOUSE_PS2_SENTELIC |