From 2218adb440f7dce4a3d92788d209918677c9e92e Mon Sep 17 00:00:00 2001 From: Chris Diamand Date: Sun, 12 May 2013 00:57:55 +0100 Subject: [PATCH] Enable 'Dolphin V2' touchpad support. Copied from alps.c in psmouse-alps-1.3-alt.tbz here: http://dahetral.com/public-download/alps-psmouse-dlkm-for-3-2-and-3-5/view --- drivers/input/mouse/alps.c | 114 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 19 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7c5d72a..5fbb686 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -1321,7 +1321,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE); if (reg_val == -EIO) goto error; - if (reg_val == 0 && alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) goto error; @@ -1519,6 +1518,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; @@ -1536,6 +1546,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; + + /* set 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; @@ -1570,7 +1643,6 @@ static void alps_set_defaults(struct alps_data *priv) 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; @@ -1590,28 +1662,29 @@ static void alps_set_defaults(struct alps_data *priv) static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, unsigned char *e7, unsigned char *ec) { - const struct alps_model_info *model; + const struct alps_model_info *model = NULL; int i; - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - model = &alps_model_data[i]; - - if (!memcmp(e7, model->signature, sizeof(model->signature)) && - (!model->command_mode_resp || - model->command_mode_resp == ec[2])) { - - priv->proto_version = model->proto_version; - alps_set_defaults(priv); + for (i = 0; true; i++) { + if (i == ARRAY_SIZE(alps_model_data)) + return -EINVAL; - priv->flags = model->flags; - priv->byte0 = model->byte0; - priv->mask0 = model->mask0; - - return 0; + model = &alps_model_data[i]; + if (!memcmp(e7, model->signature, sizeof(model->signature))) { + if (!model->command_mode_resp || + model->command_mode_resp == ec[2]) + break; } } - return -EINVAL; + priv->proto_version = model->proto_version; + alps_set_defaults(priv); + + priv->flags = model->flags; + priv->byte0 = model->byte0; + priv->mask0 = model->mask0; + + return 0; } static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) @@ -1645,10 +1718,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); + priv->hw_init = ec[1] == 0x01 ? + alps_hw_init_dolphin_v1 : + alps_hw_init_dolphin_v2; return 0; } else if (ec[0] == 0x88 && ec[1] == 0x08) { priv->proto_version = ALPS_PROTO_V3; -- 1.8.1.2