diff options
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r-- | drivers/input/mouse/synaptics.c | 145 |
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 |
120 | struct min_max_quirk { | ||
121 | const char * const *pnp_ids; | ||
122 | int x_min, x_max, y_min, y_max; | ||
123 | }; | ||
124 | |||
125 | static 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. */ | ||
146 | static 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 | |||
184 | static 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 | ||
269 | static const int *quirk_min_max; | ||
270 | |||
271 | static int synaptics_resolution(struct psmouse *psmouse) | 344 | static 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 | ||
1258 | static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | 1333 | static 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 | ||
1499 | static 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 | |||
1537 | void __init synaptics_module_init(void) | 1578 | void __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 | ||
1549 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | 1584 | static 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 |