forked from Minki/linux
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov: "Mostly small fixups to PS/2 tochpad drivers (ALPS, Elantech, Synaptics) to better deal with specific hardware" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: elantech - update the documentation Input: elantech - provide a sysfs knob for crc_enabled Input: elantech - report the middle button of the touchpad Input: alps - ignore bad data on Dell Latitudes E6440 and E7440 Input: alps - allow up to 2 invalid packets without resetting device Input: alps - ignore potential bare packets when device is out of sync Input: elantech - fix crc_enabled for Fujitsu H730 Input: elantech - use elantech_report_trackpoint for hardware v4 too Input: twl4030-pwrbutton - ensure a wakeup event is recorded. Input: synaptics - add min/max quirk for Lenovo T440s
This commit is contained in:
commit
56c381f93d
@ -38,22 +38,38 @@ Contents
|
||||
7.2.1 Status packet
|
||||
7.2.2 Head packet
|
||||
7.2.3 Motion packet
|
||||
8. Trackpoint (for Hardware version 3 and 4)
|
||||
8.1 Registers
|
||||
8.2 Native relative mode 6 byte packet format
|
||||
8.2.1 Status Packet
|
||||
|
||||
|
||||
|
||||
1. Introduction
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Currently the Linux Elantech touchpad driver is aware of two different
|
||||
hardware versions unimaginatively called version 1 and version 2. Version 1
|
||||
is found in "older" laptops and uses 4 bytes per packet. Version 2 seems to
|
||||
be introduced with the EeePC and uses 6 bytes per packet, and provides
|
||||
additional features such as position of two fingers, and width of the touch.
|
||||
Currently the Linux Elantech touchpad driver is aware of four different
|
||||
hardware versions unimaginatively called version 1,version 2, version 3
|
||||
and version 4. Version 1 is found in "older" laptops and uses 4 bytes per
|
||||
packet. Version 2 seems to be introduced with the EeePC and uses 6 bytes
|
||||
per packet, and provides additional features such as position of two fingers,
|
||||
and width of the touch. Hardware version 3 uses 6 bytes per packet (and
|
||||
for 2 fingers the concatenation of two 6 bytes packets) and allows tracking
|
||||
of up to 3 fingers. Hardware version 4 uses 6 bytes per packet, and can
|
||||
combine a status packet with multiple head or motion packets. Hardware version
|
||||
4 allows tracking up to 5 fingers.
|
||||
|
||||
Some Hardware version 3 and version 4 also have a trackpoint which uses a
|
||||
separate packet format. It is also 6 bytes per packet.
|
||||
|
||||
The driver tries to support both hardware versions and should be compatible
|
||||
with the Xorg Synaptics touchpad driver and its graphical configuration
|
||||
utilities.
|
||||
|
||||
Note that a mouse button is also associated with either the touchpad or the
|
||||
trackpoint when a trackpoint is available. Disabling the Touchpad in xorg
|
||||
(TouchPadOff=0) will also disable the buttons associated with the touchpad.
|
||||
|
||||
Additionally the operation of the touchpad can be altered by adjusting the
|
||||
contents of some of its internal registers. These registers are represented
|
||||
by the driver as sysfs entries under /sys/bus/serio/drivers/psmouse/serio?
|
||||
@ -78,7 +94,7 @@ completeness sake.
|
||||
2. Extra knobs
|
||||
~~~~~~~~~~~
|
||||
|
||||
Currently the Linux Elantech touchpad driver provides two extra knobs under
|
||||
Currently the Linux Elantech touchpad driver provides three extra knobs under
|
||||
/sys/bus/serio/drivers/psmouse/serio? for the user.
|
||||
|
||||
* debug
|
||||
@ -112,6 +128,20 @@ Currently the Linux Elantech touchpad driver provides two extra knobs under
|
||||
data consistency checking can be done. For now checking is disabled by
|
||||
default. Currently even turning it on will do nothing.
|
||||
|
||||
* crc_enabled
|
||||
|
||||
Sets crc_enabled to 0/1. The name "crc_enabled" is the official name of
|
||||
this integrity check, even though it is not an actual cyclic redundancy
|
||||
check.
|
||||
|
||||
Depending on the state of crc_enabled, certain basic data integrity
|
||||
verification is done by the driver on hardware version 3 and 4. The
|
||||
driver will reject any packet that appears corrupted. Using this knob,
|
||||
The state of crc_enabled can be altered with this knob.
|
||||
|
||||
Reading the crc_enabled value will show the active value. Echoing
|
||||
"0" or "1" to this file will set the state to "0" or "1".
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
3. Differentiating hardware versions
|
||||
@ -746,3 +776,42 @@ byte 5:
|
||||
|
||||
byte 0 ~ 2 for one finger
|
||||
byte 3 ~ 5 for another
|
||||
|
||||
|
||||
8. Trackpoint (for Hardware version 3 and 4)
|
||||
=========================================
|
||||
8.1 Registers
|
||||
~~~~~~~~~
|
||||
No special registers have been identified.
|
||||
|
||||
8.2 Native relative mode 6 byte packet format
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
8.2.1 Status Packet
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
byte 0:
|
||||
bit 7 6 5 4 3 2 1 0
|
||||
0 0 sx sy 0 M R L
|
||||
byte 1:
|
||||
bit 7 6 5 4 3 2 1 0
|
||||
~sx 0 0 0 0 0 0 0
|
||||
byte 2:
|
||||
bit 7 6 5 4 3 2 1 0
|
||||
~sy 0 0 0 0 0 0 0
|
||||
byte 3:
|
||||
bit 7 6 5 4 3 2 1 0
|
||||
0 0 ~sy ~sx 0 1 1 0
|
||||
byte 4:
|
||||
bit 7 6 5 4 3 2 1 0
|
||||
x7 x6 x5 x4 x3 x2 x1 x0
|
||||
byte 5:
|
||||
bit 7 6 5 4 3 2 1 0
|
||||
y7 y6 y5 y4 y3 y2 y1 y0
|
||||
|
||||
|
||||
x and y are written in two's complement spread
|
||||
over 9 bits with sx/sy the relative top bit and
|
||||
x7..x0 and y7..y0 the lower bits.
|
||||
~sx is the inverse of sx, ~sy is the inverse of sy.
|
||||
The sign of y is opposite to what the input driver
|
||||
expects for a relative movement
|
||||
|
@ -85,6 +85,7 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pwr);
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1156,7 +1156,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
|
||||
{
|
||||
struct alps_data *priv = psmouse->private;
|
||||
|
||||
if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
|
||||
/*
|
||||
* Check if we are dealing with a bare PS/2 packet, presumably from
|
||||
* a device connected to the external PS/2 port. Because bare PS/2
|
||||
* protocol does not have enough constant bits to self-synchronize
|
||||
* properly we only do this if the device is fully synchronized.
|
||||
*/
|
||||
if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) {
|
||||
if (psmouse->pktcnt == 3) {
|
||||
alps_report_bare_ps2_packet(psmouse, psmouse->packet,
|
||||
true);
|
||||
@ -1180,12 +1186,27 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
|
||||
}
|
||||
|
||||
/* Bytes 2 - pktsize should have 0 in the highest bit */
|
||||
if ((priv->proto_version < ALPS_PROTO_V5) &&
|
||||
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,
|
||||
psmouse->packet[psmouse->pktcnt - 1]);
|
||||
|
||||
if (priv->proto_version == ALPS_PROTO_V3 &&
|
||||
psmouse->pktcnt == psmouse->pktsize) {
|
||||
/*
|
||||
* Some Dell boxes, such as Latitude E6440 or E7440
|
||||
* with closed lid, quite often smash last byte of
|
||||
* otherwise valid packet with 0xff. Given that the
|
||||
* next packet is very likely to be valid let's
|
||||
* report PSMOUSE_FULL_PACKET but not process data,
|
||||
* rather than reporting PSMOUSE_BAD_DATA and
|
||||
* filling the logs.
|
||||
*/
|
||||
return PSMOUSE_FULL_PACKET;
|
||||
}
|
||||
|
||||
return PSMOUSE_BAD_DATA;
|
||||
}
|
||||
|
||||
@ -2389,6 +2410,9 @@ int alps_init(struct psmouse *psmouse)
|
||||
/* We are having trouble resyncing ALPS touchpads so disable it for now */
|
||||
psmouse->resync_time = 0;
|
||||
|
||||
/* Allow 2 invalid packets without resetting device */
|
||||
psmouse->resetafter = psmouse->pktsize * 2;
|
||||
|
||||
return 0;
|
||||
|
||||
init_fail:
|
||||
|
@ -563,6 +563,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
|
||||
} else {
|
||||
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
|
||||
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
|
||||
input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04);
|
||||
}
|
||||
|
||||
input_mt_report_pointer_emulation(dev, true);
|
||||
@ -792,6 +793,9 @@ static int elantech_packet_check_v4(struct psmouse *psmouse)
|
||||
unsigned char packet_type = packet[3] & 0x03;
|
||||
bool sanity_check;
|
||||
|
||||
if ((packet[3] & 0x0f) == 0x06)
|
||||
return PACKET_TRACKPOINT;
|
||||
|
||||
/*
|
||||
* Sanity check based on the constant bits of a packet.
|
||||
* The constant bits change depending on the value of
|
||||
@ -877,10 +881,19 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
|
||||
|
||||
case 4:
|
||||
packet_type = elantech_packet_check_v4(psmouse);
|
||||
if (packet_type == PACKET_UNKNOWN)
|
||||
switch (packet_type) {
|
||||
case PACKET_UNKNOWN:
|
||||
return PSMOUSE_BAD_DATA;
|
||||
|
||||
elantech_report_absolute_v4(psmouse, packet_type);
|
||||
case PACKET_TRACKPOINT:
|
||||
elantech_report_trackpoint(psmouse, packet_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
elantech_report_absolute_v4(psmouse, packet_type);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1119,6 +1132,22 @@ static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some hw_version 4 models do have a middle button
|
||||
*/
|
||||
static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
|
||||
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
||||
{
|
||||
/* Fujitsu H730 has a middle button */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
|
||||
},
|
||||
},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Set the appropriate event bits for the input subsystem
|
||||
*/
|
||||
@ -1138,6 +1167,8 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
||||
__clear_bit(EV_REL, dev->evbit);
|
||||
|
||||
__set_bit(BTN_LEFT, dev->keybit);
|
||||
if (dmi_check_system(elantech_dmi_has_middle_button))
|
||||
__set_bit(BTN_MIDDLE, dev->keybit);
|
||||
__set_bit(BTN_RIGHT, dev->keybit);
|
||||
|
||||
__set_bit(BTN_TOUCH, dev->keybit);
|
||||
@ -1299,6 +1330,7 @@ ELANTECH_INT_ATTR(reg_25, 0x25);
|
||||
ELANTECH_INT_ATTR(reg_26, 0x26);
|
||||
ELANTECH_INT_ATTR(debug, 0);
|
||||
ELANTECH_INT_ATTR(paritycheck, 0);
|
||||
ELANTECH_INT_ATTR(crc_enabled, 0);
|
||||
|
||||
static struct attribute *elantech_attrs[] = {
|
||||
&psmouse_attr_reg_07.dattr.attr,
|
||||
@ -1313,6 +1345,7 @@ static struct attribute *elantech_attrs[] = {
|
||||
&psmouse_attr_reg_26.dattr.attr,
|
||||
&psmouse_attr_debug.dattr.attr,
|
||||
&psmouse_attr_paritycheck.dattr.attr,
|
||||
&psmouse_attr_crc_enabled.dattr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -1438,6 +1471,22 @@ static int elantech_reconnect(struct psmouse *psmouse)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some hw_version 4 models do not work with crc_disabled
|
||||
*/
|
||||
static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
|
||||
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
||||
{
|
||||
/* Fujitsu H730 does not work with crc_enabled == 0 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
|
||||
},
|
||||
},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Some hw_version 3 models go into error state when we try to set
|
||||
* bit 3 and/or bit 1 of r10.
|
||||
@ -1513,7 +1562,8 @@ static int elantech_set_properties(struct elantech_data *etd)
|
||||
* The signatures of v3 and v4 packets change depending on the
|
||||
* value of this hardware flag.
|
||||
*/
|
||||
etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
|
||||
etd->crc_enabled = (etd->fw_version & 0x4000) == 0x4000 ||
|
||||
dmi_check_system(elantech_dmi_force_crc_enabled);
|
||||
|
||||
/* Enable real hardware resolution on hw_version 3 ? */
|
||||
etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
|
||||
|
@ -135,8 +135,8 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
|
||||
1232, 5710, 1156, 4696
|
||||
},
|
||||
{
|
||||
(const char * const []){"LEN0034", "LEN0036", "LEN2002",
|
||||
"LEN2004", NULL},
|
||||
(const char * const []){"LEN0034", "LEN0036", "LEN0039",
|
||||
"LEN2002", "LEN2004", NULL},
|
||||
1024, 5112, 2024, 4832
|
||||
},
|
||||
{
|
||||
@ -163,6 +163,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
|
||||
"LEN0036", /* T440 */
|
||||
"LEN0037",
|
||||
"LEN0038",
|
||||
"LEN0039", /* T440s */
|
||||
"LEN0041",
|
||||
"LEN0042", /* Yoga */
|
||||
"LEN0045",
|
||||
|
Loading…
Reference in New Issue
Block a user