Input: alps - demystify trackstick initialization for v3 and v6 protocols
authorPali Rohár <pali.rohar@gmail.com>
Mon, 23 Apr 2018 23:30:39 +0000 (16:30 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 23 Apr 2018 23:37:54 +0000 (16:37 -0700)
Remove cite "Not sure what this does, but it is absolutely essential".

Extract initialization of trackstick part when touchpad is in passthrough
mode for v3 and v6 protocols into own function. Initialization for v3 is:
setscale11, setscale11, setscale11, nibble 0x9, nibble 0x4. Initialization
for v6 is: setscale11, setscale11, setscale11, setrate 0xC8, setrate 0x14.
Nibbles 0x9 and 0x4 for v3 protocol correspond to setrate 0xC8 and 0x14,
therefore these sequences are same.

When touchpad is in passthrough mode, then OS communicates with trackstick
and this sequence is some magic vendor PS/2 command to put trackstick into
"extended" mode. After that sequence trackstick starts reporting packets in
some vendor 4 bytes format (first byte is always 0xE8).

Next step after configuring trackstick to be in "extended" mode, is to
configure touchpad for v3 protocol to expect that trackstick reports data
in "extended" mode. For v3 protocol this is done by setting bit 1 in
register 0xC2C8 (offset 0x08 from base address 0xC2C0).

When both touchpad and trackstick are not configured for "extended" mode
then touchpad reports trackstick packets in different format, which is not
supported by psmouse/alps driver (yet).

In Cirque documentation GP-AN- 130823 INTERFACING TO GEN4 OVER I2C (PDF)
available at http://www.cirque.com/gen4-dev-resources is Logical Address
0xC2C8 named as PS2AuxControl and Bit Number 1 as ProcessAuxExtendedData
with description: Auxiliary device data is assumed to be extended data when
set.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/mouse/alps.c

index f0b1060a7feef35f54d72c29566a96f67add9c06..adf7f05c643a70d5a2c7b0818247e70a2e2f21c6 100644 (file)
@@ -2049,14 +2049,11 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse)
        return 0;
 }
 
-static int alps_hw_init_v6(struct psmouse *psmouse)
+/* Must be in passthrough mode when calling this function */
+static int alps_trackstick_enter_extended_mode_v3_v6(struct psmouse *psmouse)
 {
        unsigned char param[2] = {0xC8, 0x14};
 
-       /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
-       if (alps_passthrough_mode_v2(psmouse, true))
-               return -1;
-
        if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
            ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
            ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
@@ -2064,9 +2061,25 @@ static int alps_hw_init_v6(struct psmouse *psmouse)
            ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
                return -1;
 
+       return 0;
+}
+
+static int alps_hw_init_v6(struct psmouse *psmouse)
+{
+       int ret;
+
+       /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
+       if (alps_passthrough_mode_v2(psmouse, true))
+               return -1;
+
+       ret = alps_trackstick_enter_extended_mode_v3_v6(psmouse);
+
        if (alps_passthrough_mode_v2(psmouse, false))
                return -1;
 
+       if (ret)
+               return ret;
+
        if (alps_absolute_mode_v6(psmouse)) {
                psmouse_err(psmouse, "Failed to enable absolute mode\n");
                return -1;
@@ -2140,10 +2153,18 @@ error:
 
 static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
 {
-       struct ps2dev *ps2dev = &psmouse->ps2dev;
        int ret = 0;
+       int reg_val;
        unsigned char param[4];
 
+       /*
+        * We need to configure trackstick to report data for touchpad in
+        * extended format. And also we need to tell touchpad to expect data
+        * from trackstick in extended format. Without this configuration
+        * trackstick packets sent from touchpad are in basic format which is
+        * different from what we expect.
+        */
+
        if (alps_passthrough_mode_v3(psmouse, reg_base, true))
                return -EIO;
 
@@ -2161,39 +2182,36 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
                ret = -ENODEV;
        } else {
                psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
-
-               /*
-                * Not sure what this does, but it is absolutely
-                * essential. Without it, the touchpad does not
-                * work at all and the trackstick just emits normal
-                * PS/2 packets.
-                */
-               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
-                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
-                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
-                   alps_command_mode_send_nibble(psmouse, 0x9) ||
-                   alps_command_mode_send_nibble(psmouse, 0x4)) {
-                       psmouse_err(psmouse,
-                                   "Error sending magic E6 sequence\n");
+               if (alps_trackstick_enter_extended_mode_v3_v6(psmouse)) {
+                       psmouse_err(psmouse, "Failed to enter into trackstick extended mode\n");
                        ret = -EIO;
-                       goto error;
                }
+       }
+
+       if (alps_passthrough_mode_v3(psmouse, reg_base, false))
+               return -EIO;
+
+       if (ret)
+               return ret;
 
+       if (alps_enter_command_mode(psmouse))
+               return -EIO;
+
+       reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
+       if (reg_val == -1) {
+               ret = -EIO;
+       } else {
                /*
-                * This ensures the trackstick packets are in the format
-                * supported by this driver. If bit 1 isn't set the packet
-                * format is different.
+                * Tell touchpad that trackstick is now in extended mode.
+                * If bit 1 isn't set the packet format is different.
                 */
-               if (alps_enter_command_mode(psmouse) ||
-                   alps_command_mode_write_reg(psmouse,
-                                               reg_base + 0x08, 0x82) ||
-                   alps_exit_command_mode(psmouse))
+               reg_val |= BIT(1);
+               if (__alps_command_mode_write_reg(psmouse, reg_val))
                        ret = -EIO;
        }
 
-error:
-       if (alps_passthrough_mode_v3(psmouse, reg_base, false))
-               ret = -EIO;
+       if (alps_exit_command_mode(psmouse))
+               return -EIO;
 
        return ret;
 }