Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: "Except for the largish change to the ALPS driver adding "Dolphin V1" support and Wacom getting a new signature of yet another device, the rest are straightforward driver fixes." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: mms114 - Fix regulator enable and disable paths Input: ads7864 - check return value of regulator enable Input: tc3589x-keypad - fix keymap size Input: wacom - add support for 0x10d Input: ALPS - update documentation for recent touchpad driver mods Input: ALPS - add "Dolphin V1" touchpad support Input: ALPS - remove unused argument to alps_enter_command_mode() Input: cypress_ps2 - fix trackpadi found in Dell XPS12
This commit is contained in:
commit
152fcb2784
|
@ -3,10 +3,26 @@ ALPS Touchpad Protocol
|
|||
|
||||
Introduction
|
||||
------------
|
||||
Currently the ALPS touchpad driver supports five protocol versions in use by
|
||||
ALPS touchpads, called versions 1, 2, 3, 4 and 5.
|
||||
|
||||
Currently the ALPS touchpad driver supports four protocol versions in use by
|
||||
ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various
|
||||
protocol versions is contained in the following sections.
|
||||
Since roughly mid-2010 several new ALPS touchpads have been released and
|
||||
integrated into a variety of laptops and netbooks. These new touchpads
|
||||
have enough behavior differences that the alps_model_data definition
|
||||
table, describing the properties of the different versions, is no longer
|
||||
adequate. The design choices were to re-define the alps_model_data
|
||||
table, with the risk of regression testing existing devices, or isolate
|
||||
the new devices outside of the alps_model_data table. The latter design
|
||||
choice was made. The new touchpad signatures are named: "Rushmore",
|
||||
"Pinnacle", and "Dolphin", which you will see in the alps.c code.
|
||||
For the purposes of this document, this group of ALPS touchpads will
|
||||
generically be called "new ALPS touchpads".
|
||||
|
||||
We experimented with probing the ACPI interface _HID (Hardware ID)/_CID
|
||||
(Compatibility ID) definition as a way to uniquely identify the
|
||||
different ALPS variants but there did not appear to be a 1:1 mapping.
|
||||
In fact, it appeared to be an m:n mapping between the _HID and actual
|
||||
hardware type.
|
||||
|
||||
Detection
|
||||
---------
|
||||
|
@ -20,9 +36,13 @@ If the E6 report is successful, the touchpad model is identified using the "E7
|
|||
report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is
|
||||
matched against known models in the alps_model_data_array.
|
||||
|
||||
With protocol versions 3 and 4, the E7 report model signature is always
|
||||
73-02-64. To differentiate between these versions, the response from the
|
||||
"Enter Command Mode" sequence must be inspected as described below.
|
||||
For older touchpads supporting protocol versions 3 and 4, the E7 report
|
||||
model signature is always 73-02-64. To differentiate between these
|
||||
versions, the response from the "Enter Command Mode" sequence must be
|
||||
inspected as described below.
|
||||
|
||||
The new ALPS touchpads have an E7 signature of 73-03-50 or 73-03-0A but
|
||||
seem to be better differentiated by the EC Command Mode response.
|
||||
|
||||
Command Mode
|
||||
------------
|
||||
|
@ -47,6 +67,14 @@ address of the register being read, and the third contains the value of the
|
|||
register. Registers are written by writing the value one nibble at a time
|
||||
using the same encoding used for addresses.
|
||||
|
||||
For the new ALPS touchpads, the EC command is used to enter command
|
||||
mode. The response in the new ALPS touchpads is significantly different,
|
||||
and more important in determining the behavior. This code has been
|
||||
separated from the original alps_model_data table and put in the
|
||||
alps_identify function. For example, there seem to be two hardware init
|
||||
sequences for the "Dolphin" touchpads as determined by the second byte
|
||||
of the EC response.
|
||||
|
||||
Packet Format
|
||||
-------------
|
||||
|
||||
|
@ -187,3 +215,28 @@ There are several things worth noting here.
|
|||
well.
|
||||
|
||||
So far no v4 devices with tracksticks have been encountered.
|
||||
|
||||
ALPS Absolute Mode - Protocol Version 5
|
||||
---------------------------------------
|
||||
This is basically Protocol Version 3 but with different logic for packet
|
||||
decode. It uses the same alps_process_touchpad_packet_v3 call with a
|
||||
specialized decode_fields function pointer to correctly interpret the
|
||||
packets. This appears to only be used by the Dolphin devices.
|
||||
|
||||
For single-touch, the 6-byte packet format is:
|
||||
|
||||
byte 0: 1 1 0 0 1 0 0 0
|
||||
byte 1: 0 x6 x5 x4 x3 x2 x1 x0
|
||||
byte 2: 0 y6 y5 y4 y3 y2 y1 y0
|
||||
byte 3: 0 M R L 1 m r l
|
||||
byte 4: y10 y9 y8 y7 x10 x9 x8 x7
|
||||
byte 5: 0 z6 z5 z4 z3 z2 z1 z0
|
||||
|
||||
For mt, the format is:
|
||||
|
||||
byte 0: 1 1 1 n3 1 n2 n1 x24
|
||||
byte 1: 1 y7 y6 y5 y4 y3 y2 y1
|
||||
byte 2: ? x2 x1 y12 y11 y10 y9 y8
|
||||
byte 3: 0 x23 x22 x21 x20 x19 x18 x17
|
||||
byte 4: 0 x9 x8 x7 x6 x5 x4 x3
|
||||
byte 5: 0 x16 x15 x14 x13 x12 x11 x10
|
||||
|
|
|
@ -70,8 +70,6 @@
|
|||
#define TC3589x_EVT_INT_CLR 0x2
|
||||
#define TC3589x_KBD_INT_CLR 0x1
|
||||
|
||||
#define TC3589x_KBD_KEYMAP_SIZE 64
|
||||
|
||||
/**
|
||||
* struct tc_keypad - data structure used by keypad driver
|
||||
* @tc3589x: pointer to tc35893
|
||||
|
@ -88,7 +86,7 @@ struct tc_keypad {
|
|||
const struct tc3589x_keypad_platform_data *board;
|
||||
unsigned int krow;
|
||||
unsigned int kcol;
|
||||
unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE];
|
||||
unsigned short *keymap;
|
||||
bool keypad_stopped;
|
||||
};
|
||||
|
||||
|
@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
|
|||
|
||||
error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
|
||||
TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
|
||||
keypad->keymap, input);
|
||||
NULL, input);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Failed to build keymap\n");
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
keypad->keymap = input->keycode;
|
||||
|
||||
input_set_capability(input, EV_MSC, MSC_SCAN);
|
||||
if (!plat->no_autorepeat)
|
||||
__set_bit(EV_REP, input->evbit);
|
||||
|
|
|
@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p)
|
|||
f->y_map |= (p[5] & 0x20) << 6;
|
||||
}
|
||||
|
||||
static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p)
|
||||
{
|
||||
f->first_mp = !!(p[0] & 0x02);
|
||||
f->is_mp = !!(p[0] & 0x20);
|
||||
|
||||
f->fingers = ((p[0] & 0x6) >> 1 |
|
||||
(p[0] & 0x10) >> 2);
|
||||
f->x_map = ((p[2] & 0x60) >> 5) |
|
||||
((p[4] & 0x7f) << 2) |
|
||||
((p[5] & 0x7f) << 9) |
|
||||
((p[3] & 0x07) << 16) |
|
||||
((p[3] & 0x70) << 15) |
|
||||
((p[0] & 0x01) << 22);
|
||||
f->y_map = (p[1] & 0x7f) |
|
||||
((p[2] & 0x1f) << 7);
|
||||
|
||||
f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
|
||||
f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
|
||||
f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
|
||||
|
||||
alps_decode_buttons_v3(f, p);
|
||||
}
|
||||
|
||||
static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
|
||||
{
|
||||
struct alps_data *priv = psmouse->private;
|
||||
|
@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
|
|||
}
|
||||
|
||||
/* Bytes 2 - pktsize should have 0 in the highest bit */
|
||||
if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
|
||||
if (priv->proto_version != ALPS_PROTO_V5 &&
|
||||
psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
|
||||
(psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
|
||||
psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
|
||||
psmouse->pktcnt - 1,
|
||||
|
@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int alps_enter_command_mode(struct psmouse *psmouse,
|
||||
unsigned char *resp)
|
||||
static int alps_enter_command_mode(struct psmouse *psmouse)
|
||||
{
|
||||
unsigned char param[4];
|
||||
|
||||
|
@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) {
|
||||
if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
|
||||
param[0] != 0x73) {
|
||||
psmouse_dbg(psmouse,
|
||||
"unknown response while entering command mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (resp)
|
||||
*resp = param[2];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse,
|
|||
{
|
||||
int reg_val, ret = -1;
|
||||
|
||||
if (alps_enter_command_mode(psmouse, NULL))
|
||||
if (alps_enter_command_mode(psmouse))
|
||||
return -1;
|
||||
|
||||
reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
|
||||
|
@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
|
|||
{
|
||||
int ret = -EIO, reg_val;
|
||||
|
||||
if (alps_enter_command_mode(psmouse, NULL))
|
||||
if (alps_enter_command_mode(psmouse))
|
||||
goto error;
|
||||
|
||||
reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
|
||||
|
@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
|
|||
* supported by this driver. If bit 1 isn't set the packet
|
||||
* format is different.
|
||||
*/
|
||||
if (alps_enter_command_mode(psmouse, NULL) ||
|
||||
if (alps_enter_command_mode(psmouse) ||
|
||||
alps_command_mode_write_reg(psmouse,
|
||||
reg_base + 0x08, 0x82) ||
|
||||
alps_exit_command_mode(psmouse))
|
||||
|
@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
|
|||
alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
|
||||
goto error;
|
||||
|
||||
if (alps_enter_command_mode(psmouse, NULL) ||
|
||||
if (alps_enter_command_mode(psmouse) ||
|
||||
alps_absolute_mode_v3(psmouse)) {
|
||||
psmouse_err(psmouse, "Failed to enter absolute mode\n");
|
||||
goto error;
|
||||
|
@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
|
|||
priv->flags &= ~ALPS_DUALPOINT;
|
||||
}
|
||||
|
||||
if (alps_enter_command_mode(psmouse, NULL) ||
|
||||
if (alps_enter_command_mode(psmouse) ||
|
||||
alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
|
||||
alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
|
||||
goto error;
|
||||
|
@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
|
|||
struct ps2dev *ps2dev = &psmouse->ps2dev;
|
||||
unsigned char param[4];
|
||||
|
||||
if (alps_enter_command_mode(psmouse, NULL))
|
||||
if (alps_enter_command_mode(psmouse))
|
||||
goto error;
|
||||
|
||||
if (alps_absolute_mode_v4(psmouse)) {
|
||||
|
@ -1499,6 +1520,23 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
|
||||
{
|
||||
struct ps2dev *ps2dev = &psmouse->ps2dev;
|
||||
unsigned char param[2];
|
||||
|
||||
/* This is dolphin "v1" as empirically defined by florin9doi */
|
||||
param[0] = 0x64;
|
||||
param[1] = 0x28;
|
||||
|
||||
if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
|
||||
ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
|
||||
ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void alps_set_defaults(struct alps_data *priv)
|
||||
{
|
||||
priv->byte0 = 0x8f;
|
||||
|
@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv)
|
|||
priv->nibble_commands = alps_v4_nibble_commands;
|
||||
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;
|
||||
priv->nibble_commands = alps_v3_nibble_commands;
|
||||
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
|
||||
priv->byte0 = 0xc8;
|
||||
priv->mask0 = 0xc8;
|
||||
priv->flags = 0;
|
||||
priv->x_max = 1360;
|
||||
priv->y_max = 660;
|
||||
priv->x_bits = 23;
|
||||
priv->y_bits = 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1591,6 +1644,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
|
|||
return -EIO;
|
||||
|
||||
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) {
|
||||
priv->proto_version = ALPS_PROTO_V5;
|
||||
alps_set_defaults(priv);
|
||||
|
||||
return 0;
|
||||
} else if (ec[0] == 0x88 && ec[1] == 0x08) {
|
||||
priv->proto_version = ALPS_PROTO_V3;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define ALPS_PROTO_V2 2
|
||||
#define ALPS_PROTO_V3 3
|
||||
#define ALPS_PROTO_V4 4
|
||||
#define ALPS_PROTO_V5 5
|
||||
|
||||
/**
|
||||
* struct alps_model_info - touchpad ID table
|
||||
|
|
|
@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse)
|
|||
cytp->fw_version = param[2] & FW_VERSION_MASX;
|
||||
cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to
|
||||
* CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594.
|
||||
*/
|
||||
if (cytp->fw_version >= 11)
|
||||
cytp->tp_metrics_supported = 0;
|
||||
|
||||
psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version);
|
||||
psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n",
|
||||
cytp->tp_metrics_supported);
|
||||
|
@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
|
|||
cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width;
|
||||
cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high;
|
||||
|
||||
if (!cytp->tp_metrics_supported)
|
||||
return 0;
|
||||
|
||||
memset(param, 0, sizeof(param));
|
||||
if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) {
|
||||
/* Update trackpad parameters. */
|
||||
|
@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
|
|||
|
||||
static int cypress_query_hardware(struct psmouse *psmouse)
|
||||
{
|
||||
struct cytp_data *cytp = psmouse->private;
|
||||
int ret;
|
||||
|
||||
ret = cypress_read_fw_version(psmouse);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cytp->tp_metrics_supported) {
|
||||
ret = cypress_read_tp_metrics(psmouse);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = cypress_read_tp_metrics(psmouse);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 =
|
|||
static const struct wacom_features wacom_features_0x101 =
|
||||
{ "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
|
||||
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0x10D =
|
||||
{ "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
|
||||
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
static const struct wacom_features wacom_features_0x4001 =
|
||||
{ "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255,
|
||||
0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
|
||||
|
@ -2201,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = {
|
|||
{ USB_DEVICE_WACOM(0xEF) },
|
||||
{ USB_DEVICE_WACOM(0x100) },
|
||||
{ USB_DEVICE_WACOM(0x101) },
|
||||
{ USB_DEVICE_WACOM(0x10D) },
|
||||
{ USB_DEVICE_WACOM(0x4001) },
|
||||
{ USB_DEVICE_WACOM(0x47) },
|
||||
{ USB_DEVICE_WACOM(0xF4) },
|
||||
|
|
|
@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts)
|
|||
/* Must be called with ts->lock held */
|
||||
static void __ads7846_enable(struct ads7846 *ts)
|
||||
{
|
||||
regulator_enable(ts->reg);
|
||||
int error;
|
||||
|
||||
error = regulator_enable(ts->reg);
|
||||
if (error != 0)
|
||||
dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error);
|
||||
|
||||
ads7846_restart(ts);
|
||||
}
|
||||
|
||||
|
|
|
@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data)
|
|||
struct i2c_client *client = data->client;
|
||||
int error;
|
||||
|
||||
if (data->core_reg)
|
||||
regulator_enable(data->core_reg);
|
||||
if (data->io_reg)
|
||||
regulator_enable(data->io_reg);
|
||||
error = regulator_enable(data->core_reg);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to enable avdd: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = regulator_enable(data->io_reg);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to enable vdd: %d\n", error);
|
||||
regulator_disable(data->core_reg);
|
||||
return error;
|
||||
}
|
||||
|
||||
mdelay(MMS114_POWERON_DELAY);
|
||||
|
||||
error = mms114_setup_regs(data);
|
||||
if (error < 0)
|
||||
if (error < 0) {
|
||||
regulator_disable(data->io_reg);
|
||||
regulator_disable(data->core_reg);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (data->pdata->cfg_pin)
|
||||
data->pdata->cfg_pin(true);
|
||||
|
@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data)
|
|||
static void mms114_stop(struct mms114_data *data)
|
||||
{
|
||||
struct i2c_client *client = data->client;
|
||||
int error;
|
||||
|
||||
disable_irq(client->irq);
|
||||
|
||||
if (data->pdata->cfg_pin)
|
||||
data->pdata->cfg_pin(false);
|
||||
|
||||
if (data->io_reg)
|
||||
regulator_disable(data->io_reg);
|
||||
if (data->core_reg)
|
||||
regulator_disable(data->core_reg);
|
||||
error = regulator_disable(data->io_reg);
|
||||
if (error)
|
||||
dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
|
||||
|
||||
error = regulator_disable(data->core_reg);
|
||||
if (error)
|
||||
dev_warn(&client->dev, "Failed to disable avdd: %d\n", error);
|
||||
}
|
||||
|
||||
static int mms114_input_open(struct input_dev *dev)
|
||||
|
|
Loading…
Reference in New Issue
Block a user