aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2013-02-14 01:28:07 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-02-14 12:18:34 -0500
commitcd401204873101245287afc07271b39c79194d9c (patch)
tree22a7bee493a3c10259e8640fd14da1d952c4310a /drivers/input
parent1302bac33d9e88cd43e482191a806998f3ed43cc (diff)
Input: ALPS - enable trackstick on Rushmore touchpads
Separate out the common trackstick probe/setup sequences, then call them from each of the v3 init functions. Credits: Emmanual Thome furnished the information on the trackstick init and how it affected the report format. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Tested-by: Dave Turvene <dturvene@dahetral.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/mouse/alps.c185
1 files changed, 115 insertions, 70 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index bf2fa51853e3..7b99fc7c9438 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -29,6 +29,9 @@
29 */ 29 */
30#define ALPS_CMD_NIBBLE_10 0x01f2 30#define ALPS_CMD_NIBBLE_10 0x01f2
31 31
32#define ALPS_REG_BASE_RUSHMORE 0xc2c0
33#define ALPS_REG_BASE_PINNACLE 0x0000
34
32static const struct alps_nibble_commands alps_v3_nibble_commands[] = { 35static const struct alps_nibble_commands alps_v3_nibble_commands[] = {
33 { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ 36 { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */
34 { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ 37 { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
@@ -1166,26 +1169,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse)
1166} 1169}
1167 1170
1168/* 1171/*
1169 * Enable or disable passthrough mode to the trackstick. Must be in 1172 * Enable or disable passthrough mode to the trackstick.
1170 * command mode when calling this function.
1171 */ 1173 */
1172static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) 1174static int alps_passthrough_mode_v3(struct psmouse *psmouse,
1175 int reg_base, bool enable)
1173{ 1176{
1174 int reg_val; 1177 int reg_val, ret = -1;
1175 1178
1176 reg_val = alps_command_mode_read_reg(psmouse, 0x0008); 1179 if (alps_enter_command_mode(psmouse, NULL))
1177 if (reg_val == -1)
1178 return -1; 1180 return -1;
1179 1181
1182 reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
1183 if (reg_val == -1)
1184 goto error;
1185
1180 if (enable) 1186 if (enable)
1181 reg_val |= 0x01; 1187 reg_val |= 0x01;
1182 else 1188 else
1183 reg_val &= ~0x01; 1189 reg_val &= ~0x01;
1184 1190
1185 if (__alps_command_mode_write_reg(psmouse, reg_val)) 1191 ret = __alps_command_mode_write_reg(psmouse, reg_val);
1186 return -1;
1187 1192
1188 return 0; 1193error:
1194 if (alps_exit_command_mode(psmouse))
1195 ret = -1;
1196 return ret;
1189} 1197}
1190 1198
1191/* Must be in command mode when calling this function */ 1199/* Must be in command mode when calling this function */
@@ -1204,69 +1212,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse)
1204 return 0; 1212 return 0;
1205} 1213}
1206 1214
1207static int alps_hw_init_v3(struct psmouse *psmouse) 1215static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
1208{ 1216{
1209 struct ps2dev *ps2dev = &psmouse->ps2dev; 1217 int ret = -EIO, reg_val;
1210 int reg_val;
1211 unsigned char param[4];
1212 1218
1213 if (alps_enter_command_mode(psmouse, NULL)) 1219 if (alps_enter_command_mode(psmouse, NULL))
1214 goto error; 1220 goto error;
1215 1221
1216 /* Check for trackstick */ 1222 reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
1217 reg_val = alps_command_mode_read_reg(psmouse, 0x0008);
1218 if (reg_val == -1) 1223 if (reg_val == -1)
1219 goto error; 1224 goto error;
1220 if (reg_val & 0x80) { 1225
1221 if (alps_passthrough_mode_v3(psmouse, true)) 1226 /* bit 7: trackstick is present */
1222 goto error; 1227 ret = reg_val & 0x80 ? 0 : -ENODEV;
1223 if (alps_exit_command_mode(psmouse)) 1228
1224 goto error; 1229error:
1230 alps_exit_command_mode(psmouse);
1231 return ret;
1232}
1233
1234static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
1235{
1236 struct ps2dev *ps2dev = &psmouse->ps2dev;
1237 int ret = 0;
1238 unsigned char param[4];
1239
1240 if (alps_passthrough_mode_v3(psmouse, reg_base, true))
1241 return -EIO;
1242
1243 /*
1244 * E7 report for the trackstick
1245 *
1246 * There have been reports of failures to seem to trace back
1247 * to the above trackstick check failing. When these occur
1248 * this E7 report fails, so when that happens we continue
1249 * with the assumption that there isn't a trackstick after
1250 * all.
1251 */
1252 if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
1253 psmouse_warn(psmouse, "trackstick E7 report failed\n");
1254 ret = -ENODEV;
1255 } else {
1256 psmouse_dbg(psmouse,
1257 "trackstick E7 report: %2.2x %2.2x %2.2x\n",
1258 param[0], param[1], param[2]);
1225 1259
1226 /* 1260 /*
1227 * E7 report for the trackstick 1261 * Not sure what this does, but it is absolutely
1228 * 1262 * essential. Without it, the touchpad does not
1229 * There have been reports of failures to seem to trace back 1263 * work at all and the trackstick just emits normal
1230 * to the above trackstick check failing. When these occur 1264 * PS/2 packets.
1231 * this E7 report fails, so when that happens we continue
1232 * with the assumption that there isn't a trackstick after
1233 * all.
1234 */ 1265 */
1235 param[0] = 0x64; 1266 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1236 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || 1267 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1237 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || 1268 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1238 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || 1269 alps_command_mode_send_nibble(psmouse, 0x9) ||
1239 ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { 1270 alps_command_mode_send_nibble(psmouse, 0x4)) {
1240 psmouse_warn(psmouse, "trackstick E7 report failed\n"); 1271 psmouse_err(psmouse,
1241 } else { 1272 "Error sending magic E6 sequence\n");
1242 psmouse_dbg(psmouse, 1273 ret = -EIO;
1243 "trackstick E7 report: %2.2x %2.2x %2.2x\n", 1274 goto error;
1244 param[0], param[1], param[2]);
1245
1246 /*
1247 * Not sure what this does, but it is absolutely
1248 * essential. Without it, the touchpad does not
1249 * work at all and the trackstick just emits normal
1250 * PS/2 packets.
1251 */
1252 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1253 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1254 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1255 alps_command_mode_send_nibble(psmouse, 0x9) ||
1256 alps_command_mode_send_nibble(psmouse, 0x4)) {
1257 psmouse_err(psmouse,
1258 "Error sending magic E6 sequence\n");
1259 goto error_passthrough;
1260 }
1261 } 1275 }
1262 1276
1263 if (alps_enter_command_mode(psmouse, NULL)) 1277 /*
1264 goto error_passthrough; 1278 * This ensures the trackstick packets are in the format
1265 if (alps_passthrough_mode_v3(psmouse, false)) 1279 * supported by this driver. If bit 1 isn't set the packet
1266 goto error; 1280 * format is different.
1281 */
1282 if (alps_enter_command_mode(psmouse, NULL) ||
1283 alps_command_mode_write_reg(psmouse,
1284 reg_base + 0x08, 0x82) ||
1285 alps_exit_command_mode(psmouse))
1286 ret = -EIO;
1267 } 1287 }
1268 1288
1269 if (alps_absolute_mode_v3(psmouse)) { 1289error:
1290 if (alps_passthrough_mode_v3(psmouse, reg_base, false))
1291 ret = -EIO;
1292
1293 return ret;
1294}
1295
1296static int alps_hw_init_v3(struct psmouse *psmouse)
1297{
1298 struct ps2dev *ps2dev = &psmouse->ps2dev;
1299 int reg_val;
1300 unsigned char param[4];
1301
1302 reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE);
1303 if (reg_val == -EIO)
1304 goto error;
1305 if (reg_val == 0 &&
1306 alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
1307 goto error;
1308
1309 if (alps_enter_command_mode(psmouse, NULL) ||
1310 alps_absolute_mode_v3(psmouse)) {
1270 psmouse_err(psmouse, "Failed to enter absolute mode\n"); 1311 psmouse_err(psmouse, "Failed to enter absolute mode\n");
1271 goto error; 1312 goto error;
1272 } 1313 }
@@ -1303,14 +1344,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
1303 if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) 1344 if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04))
1304 goto error; 1345 goto error;
1305 1346
1306 /*
1307 * This ensures the trackstick packets are in the format
1308 * supported by this driver. If bit 1 isn't set the packet
1309 * format is different.
1310 */
1311 if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82))
1312 goto error;
1313
1314 alps_exit_command_mode(psmouse); 1347 alps_exit_command_mode(psmouse);
1315 1348
1316 /* Set rate and enable data reporting */ 1349 /* Set rate and enable data reporting */
@@ -1323,10 +1356,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
1323 1356
1324 return 0; 1357 return 0;
1325 1358
1326error_passthrough:
1327 /* Something failed while in passthrough mode, so try to get out */
1328 if (!alps_enter_command_mode(psmouse, NULL))
1329 alps_passthrough_mode_v3(psmouse, false);
1330error: 1359error:
1331 /* 1360 /*
1332 * Leaving the touchpad in command mode will essentially render 1361 * Leaving the touchpad in command mode will essentially render
@@ -1339,9 +1368,19 @@ error:
1339 1368
1340static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) 1369static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
1341{ 1370{
1371 struct alps_data *priv = psmouse->private;
1342 struct ps2dev *ps2dev = &psmouse->ps2dev; 1372 struct ps2dev *ps2dev = &psmouse->ps2dev;
1343 int reg_val, ret = -1; 1373 int reg_val, ret = -1;
1344 1374
1375 if (priv->flags & ALPS_DUALPOINT) {
1376 reg_val = alps_setup_trackstick_v3(psmouse,
1377 ALPS_REG_BASE_RUSHMORE);
1378 if (reg_val == -EIO)
1379 goto error;
1380 if (reg_val == -ENODEV)
1381 priv->flags &= ~ALPS_DUALPOINT;
1382 }
1383
1345 if (alps_enter_command_mode(psmouse, NULL) || 1384 if (alps_enter_command_mode(psmouse, NULL) ||
1346 alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || 1385 alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
1347 alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) 1386 alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
@@ -1562,6 +1601,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
1562 priv->x_bits = 16; 1601 priv->x_bits = 16;
1563 priv->y_bits = 12; 1602 priv->y_bits = 12;
1564 1603
1604 /* hack to make addr_command, nibble_command available */
1605 psmouse->private = priv;
1606
1607 if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE))
1608 priv->flags &= ~ALPS_DUALPOINT;
1609
1565 return 0; 1610 return 0;
1566 } else if (ec[0] == 0x88 && ec[1] == 0x07 && 1611 } else if (ec[0] == 0x88 && ec[1] == 0x07 &&
1567 ec[2] >= 0x90 && ec[2] <= 0x9d) { 1612 ec[2] >= 0x90 && ec[2] <= 0x9d) {