aboutsummaryrefslogtreecommitdiff
path: root/drivers/input/mouse/alps.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2013-03-21 11:11:52 -0300
committerMarcelo Tosatti <mtosatti@redhat.com>2013-03-21 11:11:52 -0300
commit2ae33b389601b86a3d0cfe2d09f5e3189d5322fd (patch)
tree53e658f7ef511b5afb7d2e88753e1aaaed3de5ba /drivers/input/mouse/alps.c
parent04b66839d312d3bdaff77f265eb7305347fa1fb7 (diff)
parent2ffdd7e23cde5a8b94d41ec0adfdd58cffe67f3a (diff)
Merge remote-tracking branch 'upstream/master' into queue
Merge reason: From: Alexander Graf <agraf@suse.de> "Just recently this really important patch got pulled into Linus' tree for 3.9: commit 1674400aaee5b466c595a8fc310488263ce888c7 Author: Anton Blanchard <anton <at> samba.org> Date: Tue Mar 12 01:51:51 2013 +0000 Without that commit, I can not boot my G5, thus I can't run automated tests on it against my queue. Could you please merge kvm/next against linus/master, so that I can base my trees against that?" * upstream/master: (653 commits) PCI: Use ROM images from firmware only if no other ROM source available sparc: remove unused "config BITS" sparc: delete "if !ULTRA_HAS_POPULATION_COUNT" KVM: Fix bounds checking in ioapic indirect register reads (CVE-2013-1798) KVM: x86: Convert MSR_KVM_SYSTEM_TIME to use gfn_to_hva_cache functions (CVE-2013-1797) KVM: x86: fix for buffer overflow in handling of MSR_KVM_SYSTEM_TIME (CVE-2013-1796) arm64: Kconfig.debug: Remove unused CONFIG_DEBUG_ERRORS arm64: Do not select GENERIC_HARDIRQS_NO_DEPRECATED inet: limit length of fragment queue hash table bucket lists qeth: Fix scatter-gather regression qeth: Fix invalid router settings handling qeth: delay feature trace sgy-cts1000: Remove __dev* attributes KVM: x86: fix deadlock in clock-in-progress request handling KVM: allow host header to be included even for !CONFIG_KVM hwmon: (lm75) Fix tcn75 prefix hwmon: (lm75.h) Update header inclusion MAINTAINERS: Remove Mark M. Hoffman xfs: ensure we capture IO errors correctly xfs: fix xfs_iomap_eof_prealloc_initial_size type ... Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'drivers/input/mouse/alps.c')
-rw-r--r--drivers/input/mouse/alps.c85
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 7b99fc7c943..0238e0e1433 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p)
f->y_map |= (p[5] & 0x20) << 6;
}
+static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p)
+{
+ f->first_mp = !!(p[0] & 0x02);
+ f->is_mp = !!(p[0] & 0x20);
+
+ 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);
+}
+
static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
}
/* Bytes 2 - pktsize should have 0 in the highest bit */
- if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
+ if (priv->proto_version != ALPS_PROTO_V5 &&
+ psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
(psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
psmouse->pktcnt - 1,
@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
return 0;
}
-static int alps_enter_command_mode(struct psmouse *psmouse,
- unsigned char *resp)
+static int alps_enter_command_mode(struct psmouse *psmouse)
{
unsigned char param[4];
@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse,
return -1;
}
- if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) {
+ if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
+ param[0] != 0x73) {
psmouse_dbg(psmouse,
"unknown response while entering command mode\n");
return -1;
}
-
- if (resp)
- *resp = param[2];
return 0;
}
@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse,
{
int reg_val, ret = -1;
- if (alps_enter_command_mode(psmouse, NULL))
+ if (alps_enter_command_mode(psmouse))
return -1;
reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
{
int ret = -EIO, reg_val;
- if (alps_enter_command_mode(psmouse, NULL))
+ if (alps_enter_command_mode(psmouse))
goto error;
reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
* supported by this driver. If bit 1 isn't set the packet
* format is different.
*/
- if (alps_enter_command_mode(psmouse, NULL) ||
+ if (alps_enter_command_mode(psmouse) ||
alps_command_mode_write_reg(psmouse,
reg_base + 0x08, 0x82) ||
alps_exit_command_mode(psmouse))
@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
goto error;
- if (alps_enter_command_mode(psmouse, NULL) ||
+ if (alps_enter_command_mode(psmouse) ||
alps_absolute_mode_v3(psmouse)) {
psmouse_err(psmouse, "Failed to enter absolute mode\n");
goto error;
@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
priv->flags &= ~ALPS_DUALPOINT;
}
- if (alps_enter_command_mode(psmouse, NULL) ||
+ if (alps_enter_command_mode(psmouse) ||
alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
goto error;
@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char param[4];
- if (alps_enter_command_mode(psmouse, NULL))
+ if (alps_enter_command_mode(psmouse))
goto error;
if (alps_absolute_mode_v4(psmouse)) {
@@ -1499,6 +1520,23 @@ error:
return -1;
}
+static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
+{
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char param[2];
+
+ /* This is dolphin "v1" as empirically defined by florin9doi */
+ param[0] = 0x64;
+ param[1] = 0x28;
+
+ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+ ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+ ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+ return -1;
+
+ return 0;
+}
+
static void alps_set_defaults(struct alps_data *priv)
{
priv->byte0 = 0x8f;
@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv)
priv->nibble_commands = alps_v4_nibble_commands;
priv->addr_command = PSMOUSE_CMD_DISABLE;
break;
+ case ALPS_PROTO_V5:
+ priv->hw_init = alps_hw_init_dolphin_v1;
+ priv->process_packet = alps_process_packet_v3;
+ 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->flags = 0;
+ priv->x_max = 1360;
+ priv->y_max = 660;
+ priv->x_bits = 23;
+ priv->y_bits = 12;
+ break;
}
}
@@ -1592,6 +1645,12 @@ 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) {
+ priv->proto_version = ALPS_PROTO_V5;
+ alps_set_defaults(priv);
+
+ return 0;
} else if (ec[0] == 0x88 && ec[1] == 0x08) {
priv->proto_version = ALPS_PROTO_V3;
alps_set_defaults(priv);