Backport support for ALPS Dolphin devices (rhbz 953211)
This commit is contained in:
parent
d35c5d0f43
commit
216f1aa541
348
Input-ALPS-add-support-for-Dolphin-devices.patch
Normal file
348
Input-ALPS-add-support-for-Dolphin-devices.patch
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
Bugzilla: 953211
|
||||||
|
Upstream-status: Queued for 3.14
|
||||||
|
|
||||||
|
From 4081924b7b6ce876fdb8e8049f1a5ba9c1496483 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yunkang Tang <tommywill2011@gmail.com>
|
||||||
|
Date: Thu, 26 Dec 2013 14:54:19 -0800
|
||||||
|
Subject: [PATCH] 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>
|
||||||
|
---
|
||||||
|
drivers/input/mouse/alps.c | 214 ++++++++++++++++++++++++++++++++++++---------
|
||||||
|
drivers/input/mouse/alps.h | 7 +-
|
||||||
|
2 files changed, 179 insertions(+), 42 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
|
||||||
|
index 5cf62e3..fb15c64 100644
|
||||||
|
--- a/drivers/input/mouse/alps.c
|
||||||
|
+++ b/drivers/input/mouse/alps.c
|
||||||
|
@@ -277,6 +277,57 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Process bitmap data for V5 protocols. Return value is null.
|
||||||
|
+ *
|
||||||
|
+ * The bitmaps don't have enough data to track fingers, so this function
|
||||||
|
+ * only generates points representing a bounding box of at most two contacts.
|
||||||
|
+ * These two points are returned in x1, y1, x2, and y2.
|
||||||
|
+ */
|
||||||
|
+static void alps_process_bitmap_dolphin(struct alps_data *priv,
|
||||||
|
+ struct alps_fields *fields,
|
||||||
|
+ int *x1, int *y1, int *x2, int *y2)
|
||||||
|
+{
|
||||||
|
+ int box_middle_x, box_middle_y;
|
||||||
|
+ unsigned int x_map, y_map;
|
||||||
|
+ unsigned char start_bit, end_bit;
|
||||||
|
+ unsigned char x_msb, x_lsb, y_msb, y_lsb;
|
||||||
|
+
|
||||||
|
+ x_map = fields->x_map;
|
||||||
|
+ y_map = fields->y_map;
|
||||||
|
+
|
||||||
|
+ if (!x_map || !y_map)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ /* Get Most-significant and Least-significant bit */
|
||||||
|
+ x_msb = fls(x_map);
|
||||||
|
+ x_lsb = ffs(x_map);
|
||||||
|
+ y_msb = fls(y_map);
|
||||||
|
+ y_lsb = ffs(y_map);
|
||||||
|
+
|
||||||
|
+ /* Most-significant bit should never exceed max sensor line number */
|
||||||
|
+ if (x_msb > priv->x_bits || y_msb > priv->y_bits)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ *x1 = *y1 = *x2 = *y2 = 0;
|
||||||
|
+
|
||||||
|
+ if (fields->fingers > 1) {
|
||||||
|
+ start_bit = priv->x_bits - x_msb;
|
||||||
|
+ end_bit = priv->x_bits - x_lsb;
|
||||||
|
+ box_middle_x = (priv->x_max * (start_bit + end_bit)) /
|
||||||
|
+ (2 * (priv->x_bits - 1));
|
||||||
|
+
|
||||||
|
+ start_bit = y_lsb - 1;
|
||||||
|
+ end_bit = y_msb - 1;
|
||||||
|
+ box_middle_y = (priv->y_max * (start_bit + end_bit)) /
|
||||||
|
+ (2 * (priv->y_bits - 1));
|
||||||
|
+ *x1 = fields->x;
|
||||||
|
+ *y1 = fields->y;
|
||||||
|
+ *x2 = 2 * box_middle_x - *x1;
|
||||||
|
+ *y2 = 2 * box_middle_y - *y1;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* Process bitmap data from v3 and v4 protocols. Returns the number of
|
||||||
|
* fingers detected. A return value of 0 means at least one of the
|
||||||
|
* bitmaps was empty.
|
||||||
|
@@ -481,7 +532,8 @@ static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
|
||||||
|
f->ts_middle = !!(p[3] & 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p)
|
||||||
|
+static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
|
||||||
|
+ struct psmouse *psmouse)
|
||||||
|
{
|
||||||
|
f->first_mp = !!(p[4] & 0x40);
|
||||||
|
f->is_mp = !!(p[0] & 0x40);
|
||||||
|
@@ -502,48 +554,61 @@ static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p)
|
||||||
|
alps_decode_buttons_v3(f, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p)
|
||||||
|
+static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
|
||||||
|
+ struct psmouse *psmouse)
|
||||||
|
{
|
||||||
|
- alps_decode_pinnacle(f, p);
|
||||||
|
+ alps_decode_pinnacle(f, p, psmouse);
|
||||||
|
|
||||||
|
f->x_map |= (p[5] & 0x10) << 11;
|
||||||
|
f->y_map |= (p[5] & 0x20) << 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p)
|
||||||
|
+static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
|
||||||
|
+ struct psmouse *psmouse)
|
||||||
|
{
|
||||||
|
+ u64 palm_data = 0;
|
||||||
|
+ struct alps_data *priv = psmouse->private;
|
||||||
|
+
|
||||||
|
f->first_mp = !!(p[0] & 0x02);
|
||||||
|
f->is_mp = !!(p[0] & 0x20);
|
||||||
|
|
||||||
|
- f->fingers = ((p[0] & 0x6) >> 1 |
|
||||||
|
+ if (!f->is_mp) {
|
||||||
|
+ f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
|
||||||
|
+ f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
|
||||||
|
+ f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
|
||||||
|
+ alps_decode_buttons_v3(f, p);
|
||||||
|
+ } else {
|
||||||
|
+ f->fingers = ((p[0] & 0x6) >> 1 |
|
||||||
|
(p[0] & 0x10) >> 2);
|
||||||
|
- f->x_map = ((p[2] & 0x60) >> 5) |
|
||||||
|
- ((p[4] & 0x7f) << 2) |
|
||||||
|
- ((p[5] & 0x7f) << 9) |
|
||||||
|
- ((p[3] & 0x07) << 16) |
|
||||||
|
- ((p[3] & 0x70) << 15) |
|
||||||
|
- ((p[0] & 0x01) << 22);
|
||||||
|
- f->y_map = (p[1] & 0x7f) |
|
||||||
|
- ((p[2] & 0x1f) << 7);
|
||||||
|
-
|
||||||
|
- f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
|
||||||
|
- f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
|
||||||
|
- f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
|
||||||
|
|
||||||
|
- alps_decode_buttons_v3(f, p);
|
||||||
|
+ palm_data = (p[1] & 0x7f) |
|
||||||
|
+ ((p[2] & 0x7f) << 7) |
|
||||||
|
+ ((p[4] & 0x7f) << 14) |
|
||||||
|
+ ((p[5] & 0x7f) << 21) |
|
||||||
|
+ ((p[3] & 0x07) << 28) |
|
||||||
|
+ (((u64)p[3] & 0x70) << 27) |
|
||||||
|
+ (((u64)p[0] & 0x01) << 34);
|
||||||
|
+
|
||||||
|
+ /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */
|
||||||
|
+ f->y_map = palm_data & (BIT(priv->y_bits) - 1);
|
||||||
|
+
|
||||||
|
+ /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */
|
||||||
|
+ f->x_map = (palm_data >> priv->y_bits) &
|
||||||
|
+ (BIT(priv->x_bits) - 1);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
|
||||||
|
+static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
|
||||||
|
{
|
||||||
|
struct alps_data *priv = psmouse->private;
|
||||||
|
unsigned char *packet = psmouse->packet;
|
||||||
|
struct input_dev *dev = psmouse->dev;
|
||||||
|
struct input_dev *dev2 = priv->dev2;
|
||||||
|
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
|
||||||
|
- int fingers = 0, bmap_fingers;
|
||||||
|
- struct alps_fields f;
|
||||||
|
+ int fingers = 0, bmap_fn;
|
||||||
|
+ struct alps_fields f = {0};
|
||||||
|
|
||||||
|
- priv->decode_fields(&f, packet);
|
||||||
|
+ priv->decode_fields(&f, packet, psmouse);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There's no single feature of touchpad position and bitmap packets
|
||||||
|
@@ -560,19 +625,38 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
|
||||||
|
*/
|
||||||
|
if (f.is_mp) {
|
||||||
|
fingers = f.fingers;
|
||||||
|
- bmap_fingers = alps_process_bitmap(priv,
|
||||||
|
- f.x_map, f.y_map,
|
||||||
|
- &x1, &y1, &x2, &y2);
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * We shouldn't report more than one finger if
|
||||||
|
- * we don't have two coordinates.
|
||||||
|
- */
|
||||||
|
- if (fingers > 1 && bmap_fingers < 2)
|
||||||
|
- fingers = bmap_fingers;
|
||||||
|
-
|
||||||
|
- /* Now process position packet */
|
||||||
|
- priv->decode_fields(&f, priv->multi_data);
|
||||||
|
+ if (priv->proto_version == ALPS_PROTO_V3) {
|
||||||
|
+ bmap_fn = alps_process_bitmap(priv, f.x_map,
|
||||||
|
+ f.y_map, &x1, &y1,
|
||||||
|
+ &x2, &y2);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * We shouldn't report more than one finger if
|
||||||
|
+ * we don't have two coordinates.
|
||||||
|
+ */
|
||||||
|
+ if (fingers > 1 && bmap_fn < 2)
|
||||||
|
+ fingers = bmap_fn;
|
||||||
|
+
|
||||||
|
+ /* Now process position packet */
|
||||||
|
+ priv->decode_fields(&f, priv->multi_data,
|
||||||
|
+ psmouse);
|
||||||
|
+ } else {
|
||||||
|
+ /*
|
||||||
|
+ * Because Dolphin uses position packet's
|
||||||
|
+ * coordinate data as Pt1 and uses it to
|
||||||
|
+ * calculate Pt2, so we need to do position
|
||||||
|
+ * packet decode first.
|
||||||
|
+ */
|
||||||
|
+ priv->decode_fields(&f, priv->multi_data,
|
||||||
|
+ psmouse);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Since Dolphin's finger number is reliable,
|
||||||
|
+ * there is no need to compare with bmap_fn.
|
||||||
|
+ */
|
||||||
|
+ alps_process_bitmap_dolphin(priv, &f, &x1, &y1,
|
||||||
|
+ &x2, &y2);
|
||||||
|
+ }
|
||||||
|
} else {
|
||||||
|
priv->multi_packet = 0;
|
||||||
|
}
|
||||||
|
@@ -662,7 +746,7 @@ static void alps_process_packet_v3(struct psmouse *psmouse)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- alps_process_touchpad_packet_v3(psmouse);
|
||||||
|
+ alps_process_touchpad_packet_v3_v5(psmouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alps_process_packet_v6(struct psmouse *psmouse)
|
||||||
|
@@ -1709,6 +1793,52 @@ error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int alps_dolphin_get_device_area(struct psmouse *psmouse,
|
||||||
|
+ struct alps_data *priv)
|
||||||
|
+{
|
||||||
|
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
|
||||||
|
+ unsigned char param[4] = {0};
|
||||||
|
+ int num_x_electrode, num_y_electrode;
|
||||||
|
+
|
||||||
|
+ if (alps_enter_command_mode(psmouse))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ param[0] = 0x0a;
|
||||||
|
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
|
||||||
|
+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
|
||||||
|
+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
|
||||||
|
+ ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
|
||||||
|
+ ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Dolphin's sensor line number is not fixed. It can be calculated
|
||||||
|
+ * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET.
|
||||||
|
+ * Further more, we can get device's x_max and y_max by multiplying
|
||||||
|
+ * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE.
|
||||||
|
+ *
|
||||||
|
+ * e.g. When we get register's sensor_x = 11 & sensor_y = 8,
|
||||||
|
+ * real sensor line number X = 11 + 8 = 19, and
|
||||||
|
+ * real sensor line number Y = 8 + 1 = 9.
|
||||||
|
+ * So, x_max = (19 - 1) * 64 = 1152, and
|
||||||
|
+ * y_max = (9 - 1) * 64 = 512.
|
||||||
|
+ */
|
||||||
|
+ num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F);
|
||||||
|
+ num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F);
|
||||||
|
+ priv->x_bits = num_x_electrode;
|
||||||
|
+ priv->y_bits = num_y_electrode;
|
||||||
|
+ priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
|
||||||
|
+ priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
|
||||||
|
+
|
||||||
|
+ if (alps_exit_command_mode(psmouse))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
|
||||||
|
{
|
||||||
|
struct ps2dev *ps2dev = &psmouse->ps2dev;
|
||||||
|
@@ -1763,13 +1893,13 @@ static void alps_set_defaults(struct alps_data *priv)
|
||||||
|
break;
|
||||||
|
case ALPS_PROTO_V5:
|
||||||
|
priv->hw_init = alps_hw_init_dolphin_v1;
|
||||||
|
- priv->process_packet = alps_process_packet_v3;
|
||||||
|
+ priv->process_packet = alps_process_touchpad_packet_v3_v5;
|
||||||
|
priv->decode_fields = alps_decode_dolphin;
|
||||||
|
priv->set_abs_params = alps_set_abs_params_mt;
|
||||||
|
priv->nibble_commands = alps_v3_nibble_commands;
|
||||||
|
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
|
||||||
|
priv->byte0 = 0xc8;
|
||||||
|
- priv->mask0 = 0xc8;
|
||||||
|
+ priv->mask0 = 0xd8;
|
||||||
|
priv->flags = 0;
|
||||||
|
priv->x_max = 1360;
|
||||||
|
priv->y_max = 660;
|
||||||
|
@@ -1845,11 +1975,13 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
|
||||||
|
if (alps_match_table(psmouse, priv, e7, ec) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
|
||||||
|
- ec[0] == 0x73 && ec[1] == 0x01) {
|
||||||
|
+ ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
|
||||||
|
priv->proto_version = ALPS_PROTO_V5;
|
||||||
|
alps_set_defaults(priv);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ if (alps_dolphin_get_device_area(psmouse, priv))
|
||||||
|
+ return -EIO;
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
} else if (ec[0] == 0x88 && ec[1] == 0x08) {
|
||||||
|
priv->proto_version = ALPS_PROTO_V3;
|
||||||
|
alps_set_defaults(priv);
|
||||||
|
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
|
||||||
|
index 704f0f9..03f88b6 100644
|
||||||
|
--- a/drivers/input/mouse/alps.h
|
||||||
|
+++ b/drivers/input/mouse/alps.h
|
||||||
|
@@ -19,6 +19,10 @@
|
||||||
|
#define ALPS_PROTO_V5 5
|
||||||
|
#define ALPS_PROTO_V6 6
|
||||||
|
|
||||||
|
+#define DOLPHIN_COUNT_PER_ELECTRODE 64
|
||||||
|
+#define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */
|
||||||
|
+#define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* struct alps_model_info - touchpad ID table
|
||||||
|
* @signature: E7 response string to match.
|
||||||
|
@@ -146,7 +150,8 @@ struct alps_data {
|
||||||
|
|
||||||
|
int (*hw_init)(struct psmouse *psmouse);
|
||||||
|
void (*process_packet)(struct psmouse *psmouse);
|
||||||
|
- void (*decode_fields)(struct alps_fields *f, unsigned char *p);
|
||||||
|
+ void (*decode_fields)(struct alps_fields *f, unsigned char *p,
|
||||||
|
+ struct psmouse *psmouse);
|
||||||
|
void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1);
|
||||||
|
|
||||||
|
int prev_fin;
|
||||||
|
--
|
||||||
|
1.8.4.2
|
||||||
|
|
@ -700,6 +700,9 @@ Patch25181: 0001-Input-wacom-make-sure-touch_max-is-set-for-touch-dev.patch
|
|||||||
Patch25182: 0002-Input-wacom-add-support-for-three-new-Intuos-devices.patch
|
Patch25182: 0002-Input-wacom-add-support-for-three-new-Intuos-devices.patch
|
||||||
Patch25183: 0003-Input-wacom-add-reporting-of-SW_MUTE_DEVICE-events.patch
|
Patch25183: 0003-Input-wacom-add-reporting-of-SW_MUTE_DEVICE-events.patch
|
||||||
|
|
||||||
|
#rhbz 953211
|
||||||
|
Patch25184: Input-ALPS-add-support-for-Dolphin-devices.patch
|
||||||
|
|
||||||
# END OF PATCH DEFINITIONS
|
# END OF PATCH DEFINITIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
@ -1374,6 +1377,9 @@ ApplyPatch 0001-Input-wacom-make-sure-touch_max-is-set-for-touch-dev.patch
|
|||||||
ApplyPatch 0002-Input-wacom-add-support-for-three-new-Intuos-devices.patch
|
ApplyPatch 0002-Input-wacom-add-support-for-three-new-Intuos-devices.patch
|
||||||
ApplyPatch 0003-Input-wacom-add-reporting-of-SW_MUTE_DEVICE-events.patch
|
ApplyPatch 0003-Input-wacom-add-reporting-of-SW_MUTE_DEVICE-events.patch
|
||||||
|
|
||||||
|
#rhbz 953211
|
||||||
|
ApplyPatch Input-ALPS-add-support-for-Dolphin-devices.patch
|
||||||
|
|
||||||
# END OF PATCH APPLICATIONS
|
# END OF PATCH APPLICATIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
@ -2161,6 +2167,9 @@ fi
|
|||||||
# ||----w |
|
# ||----w |
|
||||||
# || ||
|
# || ||
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Jan 08 2014 Josh Boyer <jwboyer@fedoraproject.org>
|
||||||
|
- Backport support for ALPS Dolphin devices (rhbz 953211)
|
||||||
|
|
||||||
* Wed Jan 08 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.13.0-0.rc7.git2.1
|
* Wed Jan 08 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.13.0-0.rc7.git2.1
|
||||||
- Linux v3.13-rc7-67-gceb3b02
|
- Linux v3.13-rc7-67-gceb3b02
|
||||||
- Enable BCMA_DRIVER_GPIO by turning on GPIOLIB everywhere (rhbz 1021098)
|
- Enable BCMA_DRIVER_GPIO by turning on GPIOLIB everywhere (rhbz 1021098)
|
||||||
|
Loading…
Reference in New Issue
Block a user