Commit d91abc21 authored by Pali Rohár's avatar Pali Rohár Committed by Dmitry Torokhov

Input: alps - demystify trackstick initialization for v3 and v6 protocols

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: default avatarPali Rohár <pali.rohar@gmail.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 57eb13a9
...@@ -2049,14 +2049,11 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) ...@@ -2049,14 +2049,11 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse)
return 0; 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}; 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) || 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) ||
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) ...@@ -2064,9 +2061,25 @@ static int alps_hw_init_v6(struct psmouse *psmouse)
ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE)) ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
return -1; 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)) if (alps_passthrough_mode_v2(psmouse, false))
return -1; return -1;
if (ret)
return ret;
if (alps_absolute_mode_v6(psmouse)) { if (alps_absolute_mode_v6(psmouse)) {
psmouse_err(psmouse, "Failed to enable absolute mode\n"); psmouse_err(psmouse, "Failed to enable absolute mode\n");
return -1; return -1;
...@@ -2140,10 +2153,18 @@ static int alps_probe_trackstick_v3_v7(struct psmouse *psmouse, int reg_base) ...@@ -2140,10 +2153,18 @@ static int alps_probe_trackstick_v3_v7(struct psmouse *psmouse, int reg_base)
static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
{ {
struct ps2dev *ps2dev = &psmouse->ps2dev;
int ret = 0; int ret = 0;
int reg_val;
unsigned char param[4]; 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)) if (alps_passthrough_mode_v3(psmouse, reg_base, true))
return -EIO; return -EIO;
...@@ -2161,39 +2182,36 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) ...@@ -2161,39 +2182,36 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
ret = -ENODEV; ret = -ENODEV;
} else { } else {
psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
if (alps_trackstick_enter_extended_mode_v3_v6(psmouse)) {
/* psmouse_err(psmouse, "Failed to enter into trackstick extended mode\n");
* 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");
ret = -EIO; 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 * Tell touchpad that trackstick is now in extended mode.
* supported by this driver. If bit 1 isn't set the packet * If bit 1 isn't set the packet format is different.
* format is different.
*/ */
if (alps_enter_command_mode(psmouse) || reg_val |= BIT(1);
alps_command_mode_write_reg(psmouse, if (__alps_command_mode_write_reg(psmouse, reg_val))
reg_base + 0x08, 0x82) ||
alps_exit_command_mode(psmouse))
ret = -EIO; ret = -EIO;
} }
error: if (alps_exit_command_mode(psmouse))
if (alps_passthrough_mode_v3(psmouse, reg_base, false)) return -EIO;
ret = -EIO;
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment