aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/synaptics.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r--drivers/input/mouse/synaptics.c145
1 files changed, 90 insertions, 55 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index d8d49d10f9bb..c5ec703c727e 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -117,6 +117,81 @@ void synaptics_reset(struct psmouse *psmouse)
117} 117}
118 118
119#ifdef CONFIG_MOUSE_PS2_SYNAPTICS 119#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
120struct min_max_quirk {
121 const char * const *pnp_ids;
122 int x_min, x_max, y_min, y_max;
123};
124
125static const struct min_max_quirk min_max_pnpid_table[] = {
126 {
127 (const char * const []){"LEN0033", NULL},
128 1024, 5052, 2258, 4832
129 },
130 {
131 (const char * const []){"LEN0035", "LEN0042", NULL},
132 1232, 5710, 1156, 4696
133 },
134 {
135 (const char * const []){"LEN0034", "LEN0036", "LEN2004", NULL},
136 1024, 5112, 2024, 4832
137 },
138 {
139 (const char * const []){"LEN2001", NULL},
140 1024, 5022, 2508, 4832
141 },
142 { }
143};
144
145/* This list has been kindly provided by Synaptics. */
146static const char * const topbuttonpad_pnp_ids[] = {
147 "LEN0017",
148 "LEN0018",
149 "LEN0019",
150 "LEN0023",
151 "LEN002A",
152 "LEN002B",
153 "LEN002C",
154 "LEN002D",
155 "LEN002E",
156 "LEN0033", /* Helix */
157 "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */
158 "LEN0035", /* X240 */
159 "LEN0036", /* T440 */
160 "LEN0037",
161 "LEN0038",
162 "LEN0041",
163 "LEN0042", /* Yoga */
164 "LEN0045",
165 "LEN0046",
166 "LEN0047",
167 "LEN0048",
168 "LEN0049",
169 "LEN2000",
170 "LEN2001", /* Edge E431 */
171 "LEN2002",
172 "LEN2003",
173 "LEN2004", /* L440 */
174 "LEN2005",
175 "LEN2006",
176 "LEN2007",
177 "LEN2008",
178 "LEN2009",
179 "LEN200A",
180 "LEN200B",
181 NULL
182};
183
184static bool matches_pnp_id(struct psmouse *psmouse, const char * const ids[])
185{
186 int i;
187
188 if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4))
189 for (i = 0; ids[i]; i++)
190 if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i]))
191 return true;
192
193 return false;
194}
120 195
121/***************************************************************************** 196/*****************************************************************************
122 * Synaptics communications functions 197 * Synaptics communications functions
@@ -266,20 +341,20 @@ static int synaptics_identify(struct psmouse *psmouse)
266 * Resolution is left zero if touchpad does not support the query 341 * Resolution is left zero if touchpad does not support the query
267 */ 342 */
268 343
269static const int *quirk_min_max;
270
271static int synaptics_resolution(struct psmouse *psmouse) 344static int synaptics_resolution(struct psmouse *psmouse)
272{ 345{
273 struct synaptics_data *priv = psmouse->private; 346 struct synaptics_data *priv = psmouse->private;
274 unsigned char resp[3]; 347 unsigned char resp[3];
348 int i;
275 349
276 if (quirk_min_max) { 350 for (i = 0; min_max_pnpid_table[i].pnp_ids; i++)
277 priv->x_min = quirk_min_max[0]; 351 if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) {
278 priv->x_max = quirk_min_max[1]; 352 priv->x_min = min_max_pnpid_table[i].x_min;
279 priv->y_min = quirk_min_max[2]; 353 priv->x_max = min_max_pnpid_table[i].x_max;
280 priv->y_max = quirk_min_max[3]; 354 priv->y_min = min_max_pnpid_table[i].y_min;
281 return 0; 355 priv->y_max = min_max_pnpid_table[i].y_max;
282 } 356 return 0;
357 }
283 358
284 if (SYN_ID_MAJOR(priv->identity) < 4) 359 if (SYN_ID_MAJOR(priv->identity) < 4)
285 return 0; 360 return 0;
@@ -1255,8 +1330,10 @@ static void set_abs_position_params(struct input_dev *dev,
1255 input_abs_set_res(dev, y_code, priv->y_res); 1330 input_abs_set_res(dev, y_code, priv->y_res);
1256} 1331}
1257 1332
1258static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) 1333static void set_input_params(struct psmouse *psmouse,
1334 struct synaptics_data *priv)
1259{ 1335{
1336 struct input_dev *dev = psmouse->dev;
1260 int i; 1337 int i;
1261 1338
1262 /* Things that apply to both modes */ 1339 /* Things that apply to both modes */
@@ -1325,6 +1402,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
1325 1402
1326 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { 1403 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
1327 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); 1404 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
1405 if (matches_pnp_id(psmouse, topbuttonpad_pnp_ids))
1406 __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit);
1328 /* Clickpads report only left button */ 1407 /* Clickpads report only left button */
1329 __clear_bit(BTN_RIGHT, dev->keybit); 1408 __clear_bit(BTN_RIGHT, dev->keybit);
1330 __clear_bit(BTN_MIDDLE, dev->keybit); 1409 __clear_bit(BTN_MIDDLE, dev->keybit);
@@ -1496,54 +1575,10 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
1496 { } 1575 { }
1497}; 1576};
1498 1577
1499static const struct dmi_system_id min_max_dmi_table[] __initconst = {
1500#if defined(CONFIG_DMI)
1501 {
1502 /* Lenovo ThinkPad Helix */
1503 .matches = {
1504 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1505 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
1506 },
1507 .driver_data = (int []){1024, 5052, 2258, 4832},
1508 },
1509 {
1510 /* Lenovo ThinkPad X240 */
1511 .matches = {
1512 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1513 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"),
1514 },
1515 .driver_data = (int []){1232, 5710, 1156, 4696},
1516 },
1517 {
1518 /* Lenovo ThinkPad T440s */
1519 .matches = {
1520 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1521 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
1522 },
1523 .driver_data = (int []){1024, 5112, 2024, 4832},
1524 },
1525 {
1526 /* Lenovo ThinkPad T540p */
1527 .matches = {
1528 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1529 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
1530 },
1531 .driver_data = (int []){1024, 5056, 2058, 4832},
1532 },
1533#endif
1534 { }
1535};
1536
1537void __init synaptics_module_init(void) 1578void __init synaptics_module_init(void)
1538{ 1579{
1539 const struct dmi_system_id *min_max_dmi;
1540
1541 impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); 1580 impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
1542 broken_olpc_ec = dmi_check_system(olpc_dmi_table); 1581 broken_olpc_ec = dmi_check_system(olpc_dmi_table);
1543
1544 min_max_dmi = dmi_first_match(min_max_dmi_table);
1545 if (min_max_dmi)
1546 quirk_min_max = min_max_dmi->driver_data;
1547} 1582}
1548 1583
1549static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) 1584static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
@@ -1593,7 +1628,7 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
1593 priv->capabilities, priv->ext_cap, priv->ext_cap_0c, 1628 priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
1594 priv->board_id, priv->firmware_id); 1629 priv->board_id, priv->firmware_id);
1595 1630
1596 set_input_params(psmouse->dev, priv); 1631 set_input_params(psmouse, priv);
1597 1632
1598 /* 1633 /*
1599 * Encode touchpad model so that it can be used to set 1634 * Encode touchpad model so that it can be used to set