[WIP 3/3] Input: ALPS - Add "Dolphin V2" touchpad support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Another ALPS variant; seen on the Fujitsu A512.

Signed-off-by: Kevin Cernekee <cernekee@xxxxxxxxx>
Signed-off-by: Vincent Vanackere <vincent.vanackere@xxxxxxxxx>
---
 drivers/input/mouse/alps.c |   79 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)


This is a work-in-progress and not ready to be merged yet.  See:

https://bugs.launchpad.net/ubuntu/+source/linux/+bug/606238
https://bugs.freedesktop.org/show_bug.cgi?id=59478

The init sequence is probably "mostly OK" but the pressure values read
near the edges are not accurate, so edge scrolling does not work well.
Maybe this is fixable by changing some of the register settings, maybe
the report decoder is slightly off, or maybe the software will actually
need to scale z based on the x/y values.

One thing that might be worth trying is to select the native V2 report
format (short cmd 0x89) instead of the V1 format (short cmd 0x85).  This
probably affects the bit assignments and may require writing a new
alps_decode_* function.

I don't actually have access to any of the "Dolphin" based systems, so
I'm not able to make much progress on my own here.  Hopefully it's a
useful starting point though.


diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 0238e0e..d288f4c 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1520,6 +1520,17 @@ error:
 	return -1;
 }
 
+static int alps_short_cmd_v5(struct psmouse *psmouse, u8 init_command, u8 cmd)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+	if (ps2_command(ps2dev, NULL, init_command) ||
+	    ps2_command(ps2dev, NULL, init_command) ||
+	    __alps_command_mode_write_reg(psmouse, cmd))
+		return -EIO;
+	return 0;
+}
+
 static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -1537,6 +1548,69 @@ static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
 	return 0;
 }
 
+static int alps_hw_init_dolphin_v2(struct psmouse *psmouse)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+	/* sample rate */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x55))
+		goto error;
+
+	/* idle count */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x64))
+		goto error;
+
+	/* button swap */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x47))
+		goto error;
+
+	/* data priority */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x43))
+		goto error;
+
+	/* power mode */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETPOLL, 0x57))
+		goto error;
+
+	/*
+	 * TODO: For Dolphin V2 touchpads, the threshold should be calculated
+	 * from the OTP settings instead.
+	 */
+	if (alps_enter_command_mode(psmouse) ||
+	    alps_command_mode_write_reg(psmouse, 0x001f, 0x09) ||
+	    alps_command_mode_write_reg(psmouse, 0x0020, 0x09) ||
+	    alps_command_mode_write_reg(psmouse, 0x0022, 0x80) ||
+	    alps_exit_command_mode(psmouse))
+		goto error;
+
+	/* select V1 packet format */
+	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+	    alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x85))
+		goto error;
+
+	/* XY and gesture */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x73))
+		goto error;
+
+	/* profile sequence */
+	if (alps_short_cmd_v5(psmouse, PSMOUSE_CMD_SETSTREAM, 0x94))
+		goto error;
+
+	/* final init */
+	if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+	    alps_command_mode_send_nibble(psmouse, 0x7) ||
+	    alps_command_mode_send_nibble(psmouse, 0xf) ||
+	    alps_command_mode_send_nibble(psmouse, 0xe) ||
+	    ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
+		goto error;
+
+	return 0;
+
+error:
+	alps_exit_command_mode(psmouse);
+	return -1;
+}
+
 static void alps_set_defaults(struct alps_data *priv)
 {
 	priv->byte0 = 0x8f;
@@ -1646,10 +1720,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);
 
+		if (ec[1] == 0x02)
+			priv->hw_init = alps_hw_init_dolphin_v2;
+
 		return 0;
 	} else if (ec[0] == 0x88 && ec[1] == 0x08) {
 		priv->proto_version = ALPS_PROTO_V3;
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux