Commit 421e08c4 authored by Benjamin Tissoires's avatar Benjamin Tissoires Committed by Dmitry Torokhov

Input: synaptics - add manual min/max quirk

The new Lenovo Haswell series (-40's) contains a new Synaptics touchpad.
However, these new Synaptics devices report bad axis ranges.
Under Windows, it is not a problem because the Windows driver uses RMI4
over SMBus to talk to the device. Under Linux, we are using the PS/2
fallback interface and it occurs the reported ranges are wrong.

Of course, it would be too easy to have only one range for the whole
series, each touchpad seems to be calibrated in a different way.

We can not use SMBus to get the actual range because I suspect the firmware
will switch into the SMBus mode and stop talking through PS/2 (this is the
case for hybrid HID over I2C / PS/2 Synaptics touchpads).

So as a temporary solution (until RMI4 land into upstream), start a new
list of quirks with the min/max manually set.
Signed-off-by: default avatarBenjamin Tissoires <benjamin.tissoires@redhat.com>
CC: stable@vger.kernel.org
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 6797b39e
...@@ -265,11 +265,22 @@ static int synaptics_identify(struct psmouse *psmouse) ...@@ -265,11 +265,22 @@ static int synaptics_identify(struct psmouse *psmouse)
* Read touchpad resolution and maximum reported coordinates * Read touchpad resolution and maximum reported coordinates
* Resolution is left zero if touchpad does not support the query * Resolution is left zero if touchpad does not support the query
*/ */
static const int *quirk_min_max;
static int synaptics_resolution(struct psmouse *psmouse) static int synaptics_resolution(struct psmouse *psmouse)
{ {
struct synaptics_data *priv = psmouse->private; struct synaptics_data *priv = psmouse->private;
unsigned char resp[3]; unsigned char resp[3];
if (quirk_min_max) {
priv->x_min = quirk_min_max[0];
priv->x_max = quirk_min_max[1];
priv->y_min = quirk_min_max[2];
priv->y_max = quirk_min_max[3];
return 0;
}
if (SYN_ID_MAJOR(priv->identity) < 4) if (SYN_ID_MAJOR(priv->identity) < 4)
return 0; return 0;
...@@ -1485,10 +1496,46 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = { ...@@ -1485,10 +1496,46 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
{ } { }
}; };
static const struct dmi_system_id min_max_dmi_table[] __initconst = {
#if defined(CONFIG_DMI)
{
/* Lenovo ThinkPad Helix */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
},
.driver_data = (int []){1024, 5052, 2258, 4832},
},
{
/* Lenovo ThinkPad T440s */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
},
.driver_data = (int []){1024, 5112, 2024, 4832},
},
{
/* Lenovo ThinkPad T540p */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
},
.driver_data = (int []){1024, 5056, 2058, 4832},
},
#endif
{ }
};
void __init synaptics_module_init(void) void __init synaptics_module_init(void)
{ {
const struct dmi_system_id *min_max_dmi;
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
broken_olpc_ec = dmi_check_system(olpc_dmi_table); broken_olpc_ec = dmi_check_system(olpc_dmi_table);
min_max_dmi = dmi_first_match(min_max_dmi_table);
if (min_max_dmi)
quirk_min_max = min_max_dmi->driver_data;
} }
static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
......
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