diff options
Diffstat (limited to 'drivers/input/mouse/synaptics.c')
-rw-r--r-- | drivers/input/mouse/synaptics.c | 197 |
1 files changed, 176 insertions, 21 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 96b70a43515f..e06e045bf907 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/dmi.h> | 27 | #include <linux/dmi.h> |
28 | #include <linux/input.h> | 28 | #include <linux/input/mt.h> |
29 | #include <linux/serio.h> | 29 | #include <linux/serio.h> |
30 | #include <linux/libps2.h> | 30 | #include <linux/libps2.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -279,6 +279,25 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate) | |||
279 | synaptics_mode_cmd(psmouse, priv->mode); | 279 | synaptics_mode_cmd(psmouse, priv->mode); |
280 | } | 280 | } |
281 | 281 | ||
282 | static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) | ||
283 | { | ||
284 | static unsigned char param = 0xc8; | ||
285 | struct synaptics_data *priv = psmouse->private; | ||
286 | |||
287 | if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
288 | return 0; | ||
289 | |||
290 | if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL)) | ||
291 | return -1; | ||
292 | if (ps2_command(&psmouse->ps2dev, ¶m, PSMOUSE_CMD_SETRATE)) | ||
293 | return -1; | ||
294 | |||
295 | /* Advanced gesture mode also sends multi finger data */ | ||
296 | priv->capabilities |= BIT(1); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
282 | /***************************************************************************** | 301 | /***************************************************************************** |
283 | * Synaptics pass-through PS/2 port support | 302 | * Synaptics pass-through PS/2 port support |
284 | ****************************************************************************/ | 303 | ****************************************************************************/ |
@@ -294,7 +313,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c) | |||
294 | return 0; | 313 | return 0; |
295 | } | 314 | } |
296 | 315 | ||
297 | static inline int synaptics_is_pt_packet(unsigned char *buf) | 316 | static int synaptics_pt_start(struct serio *serio) |
317 | { | ||
318 | struct psmouse *parent = serio_get_drvdata(serio->parent); | ||
319 | struct synaptics_data *priv = parent->private; | ||
320 | |||
321 | serio_pause_rx(parent->ps2dev.serio); | ||
322 | priv->pt_port = serio; | ||
323 | serio_continue_rx(parent->ps2dev.serio); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static void synaptics_pt_stop(struct serio *serio) | ||
329 | { | ||
330 | struct psmouse *parent = serio_get_drvdata(serio->parent); | ||
331 | struct synaptics_data *priv = parent->private; | ||
332 | |||
333 | serio_pause_rx(parent->ps2dev.serio); | ||
334 | priv->pt_port = NULL; | ||
335 | serio_continue_rx(parent->ps2dev.serio); | ||
336 | } | ||
337 | |||
338 | static int synaptics_is_pt_packet(unsigned char *buf) | ||
298 | { | 339 | { |
299 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; | 340 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; |
300 | } | 341 | } |
@@ -315,9 +356,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet | |||
315 | 356 | ||
316 | static void synaptics_pt_activate(struct psmouse *psmouse) | 357 | static void synaptics_pt_activate(struct psmouse *psmouse) |
317 | { | 358 | { |
318 | struct serio *ptport = psmouse->ps2dev.serio->child; | ||
319 | struct psmouse *child = serio_get_drvdata(ptport); | ||
320 | struct synaptics_data *priv = psmouse->private; | 359 | struct synaptics_data *priv = psmouse->private; |
360 | struct psmouse *child = serio_get_drvdata(priv->pt_port); | ||
321 | 361 | ||
322 | /* adjust the touchpad to child's choice of protocol */ | 362 | /* adjust the touchpad to child's choice of protocol */ |
323 | if (child) { | 363 | if (child) { |
@@ -345,6 +385,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
345 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); | 385 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); |
346 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); | 386 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); |
347 | serio->write = synaptics_pt_write; | 387 | serio->write = synaptics_pt_write; |
388 | serio->start = synaptics_pt_start; | ||
389 | serio->stop = synaptics_pt_stop; | ||
348 | serio->parent = psmouse->ps2dev.serio; | 390 | serio->parent = psmouse->ps2dev.serio; |
349 | 391 | ||
350 | psmouse->pt_activate = synaptics_pt_activate; | 392 | psmouse->pt_activate = synaptics_pt_activate; |
@@ -357,7 +399,9 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
357 | * Functions to interpret the absolute mode packets | 399 | * Functions to interpret the absolute mode packets |
358 | ****************************************************************************/ | 400 | ****************************************************************************/ |
359 | 401 | ||
360 | static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) | 402 | static int synaptics_parse_hw_state(const unsigned char buf[], |
403 | struct synaptics_data *priv, | ||
404 | struct synaptics_hw_state *hw) | ||
361 | { | 405 | { |
362 | memset(hw, 0, sizeof(struct synaptics_hw_state)); | 406 | memset(hw, 0, sizeof(struct synaptics_hw_state)); |
363 | 407 | ||
@@ -374,6 +418,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
374 | ((buf[0] & 0x04) >> 1) | | 418 | ((buf[0] & 0x04) >> 1) | |
375 | ((buf[3] & 0x04) >> 2)); | 419 | ((buf[3] & 0x04) >> 2)); |
376 | 420 | ||
421 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) { | ||
422 | /* Gesture packet: (x, y, z) at half resolution */ | ||
423 | priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; | ||
424 | priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; | ||
425 | priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; | ||
426 | return 1; | ||
427 | } | ||
428 | |||
377 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 429 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
378 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 430 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
379 | 431 | ||
@@ -429,6 +481,36 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
429 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 481 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
430 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 482 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
431 | } | 483 | } |
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y) | ||
489 | { | ||
490 | input_mt_slot(dev, slot); | ||
491 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | ||
492 | if (active) { | ||
493 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
494 | input_report_abs(dev, ABS_MT_POSITION_Y, | ||
495 | YMAX_NOMINAL + YMIN_NOMINAL - y); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | static void synaptics_report_semi_mt_data(struct input_dev *dev, | ||
500 | const struct synaptics_hw_state *a, | ||
501 | const struct synaptics_hw_state *b, | ||
502 | int num_fingers) | ||
503 | { | ||
504 | if (num_fingers >= 2) { | ||
505 | set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y)); | ||
506 | set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y)); | ||
507 | } else if (num_fingers == 1) { | ||
508 | set_slot(dev, 0, true, a->x, a->y); | ||
509 | set_slot(dev, 1, false, 0, 0); | ||
510 | } else { | ||
511 | set_slot(dev, 0, false, 0, 0); | ||
512 | set_slot(dev, 1, false, 0, 0); | ||
513 | } | ||
432 | } | 514 | } |
433 | 515 | ||
434 | /* | 516 | /* |
@@ -443,7 +525,8 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
443 | int finger_width; | 525 | int finger_width; |
444 | int i; | 526 | int i; |
445 | 527 | ||
446 | synaptics_parse_hw_state(psmouse->packet, priv, &hw); | 528 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) |
529 | return; | ||
447 | 530 | ||
448 | if (hw.scroll) { | 531 | if (hw.scroll) { |
449 | priv->scroll += hw.scroll; | 532 | priv->scroll += hw.scroll; |
@@ -465,7 +548,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
465 | return; | 548 | return; |
466 | } | 549 | } |
467 | 550 | ||
468 | if (hw.z > 0) { | 551 | if (hw.z > 0 && hw.x > 1) { |
469 | num_fingers = 1; | 552 | num_fingers = 1; |
470 | finger_width = 5; | 553 | finger_width = 5; |
471 | if (SYN_CAP_EXTENDED(priv->capabilities)) { | 554 | if (SYN_CAP_EXTENDED(priv->capabilities)) { |
@@ -489,6 +572,9 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
489 | finger_width = 0; | 572 | finger_width = 0; |
490 | } | 573 | } |
491 | 574 | ||
575 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) | ||
576 | synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers); | ||
577 | |||
492 | /* Post events | 578 | /* Post events |
493 | * BTN_TOUCH has to be first as mousedev relies on it when doing | 579 | * BTN_TOUCH has to be first as mousedev relies on it when doing |
494 | * absolute -> relative conversion | 580 | * absolute -> relative conversion |
@@ -496,7 +582,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
496 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); | 582 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); |
497 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); | 583 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); |
498 | 584 | ||
499 | if (hw.z > 0) { | 585 | if (num_fingers > 0) { |
500 | input_report_abs(dev, ABS_X, hw.x); | 586 | input_report_abs(dev, ABS_X, hw.x); |
501 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); | 587 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); |
502 | } | 588 | } |
@@ -578,9 +664,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | |||
578 | if (unlikely(priv->pkt_type == SYN_NEWABS)) | 664 | if (unlikely(priv->pkt_type == SYN_NEWABS)) |
579 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); | 665 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); |
580 | 666 | ||
581 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) { | 667 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && |
582 | if (psmouse->ps2dev.serio->child) | 668 | synaptics_is_pt_packet(psmouse->packet)) { |
583 | synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet); | 669 | if (priv->pt_port) |
670 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); | ||
584 | } else | 671 | } else |
585 | synaptics_process_packet(psmouse); | 672 | synaptics_process_packet(psmouse); |
586 | 673 | ||
@@ -598,6 +685,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
598 | { | 685 | { |
599 | int i; | 686 | int i; |
600 | 687 | ||
688 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | ||
689 | |||
601 | __set_bit(EV_ABS, dev->evbit); | 690 | __set_bit(EV_ABS, dev->evbit); |
602 | input_set_abs_params(dev, ABS_X, | 691 | input_set_abs_params(dev, ABS_X, |
603 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); | 692 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); |
@@ -605,6 +694,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
605 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); | 694 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); |
606 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 695 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
607 | 696 | ||
697 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | ||
698 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
699 | input_mt_init_slots(dev, 2); | ||
700 | input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, | ||
701 | priv->x_max ?: XMAX_NOMINAL, 0, 0); | ||
702 | input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, | ||
703 | priv->y_max ?: YMAX_NOMINAL, 0, 0); | ||
704 | } | ||
705 | |||
608 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | 706 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
609 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | 707 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); |
610 | 708 | ||
@@ -639,6 +737,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
639 | input_abs_set_res(dev, ABS_Y, priv->y_res); | 737 | input_abs_set_res(dev, ABS_Y, priv->y_res); |
640 | 738 | ||
641 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 739 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
740 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | ||
642 | /* Clickpads report only left button */ | 741 | /* Clickpads report only left button */ |
643 | __clear_bit(BTN_RIGHT, dev->keybit); | 742 | __clear_bit(BTN_RIGHT, dev->keybit); |
644 | __clear_bit(BTN_MIDDLE, dev->keybit); | 743 | __clear_bit(BTN_MIDDLE, dev->keybit); |
@@ -656,25 +755,46 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
656 | { | 755 | { |
657 | struct synaptics_data *priv = psmouse->private; | 756 | struct synaptics_data *priv = psmouse->private; |
658 | struct synaptics_data old_priv = *priv; | 757 | struct synaptics_data old_priv = *priv; |
758 | int retry = 0; | ||
759 | int error; | ||
659 | 760 | ||
660 | psmouse_reset(psmouse); | 761 | do { |
762 | psmouse_reset(psmouse); | ||
763 | error = synaptics_detect(psmouse, 0); | ||
764 | } while (error && ++retry < 3); | ||
661 | 765 | ||
662 | if (synaptics_detect(psmouse, 0)) | 766 | if (error) |
663 | return -1; | 767 | return -1; |
664 | 768 | ||
769 | if (retry > 1) | ||
770 | printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", | ||
771 | retry); | ||
772 | |||
665 | if (synaptics_query_hardware(psmouse)) { | 773 | if (synaptics_query_hardware(psmouse)) { |
666 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); | 774 | printk(KERN_ERR "Unable to query Synaptics hardware.\n"); |
667 | return -1; | 775 | return -1; |
668 | } | 776 | } |
669 | 777 | ||
778 | if (synaptics_set_absolute_mode(psmouse)) { | ||
779 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | ||
780 | return -1; | ||
781 | } | ||
782 | |||
783 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
784 | printk(KERN_ERR "Advanced gesture mode reconnect failed.\n"); | ||
785 | return -1; | ||
786 | } | ||
787 | |||
670 | if (old_priv.identity != priv->identity || | 788 | if (old_priv.identity != priv->identity || |
671 | old_priv.model_id != priv->model_id || | 789 | old_priv.model_id != priv->model_id || |
672 | old_priv.capabilities != priv->capabilities || | 790 | old_priv.capabilities != priv->capabilities || |
673 | old_priv.ext_cap != priv->ext_cap) | 791 | old_priv.ext_cap != priv->ext_cap) { |
674 | return -1; | 792 | printk(KERN_ERR "Synaptics hardware appears to be different: " |
675 | 793 | "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", | |
676 | if (synaptics_set_absolute_mode(psmouse)) { | 794 | old_priv.identity, priv->identity, |
677 | printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); | 795 | old_priv.model_id, priv->model_id, |
796 | old_priv.capabilities, priv->capabilities, | ||
797 | old_priv.ext_cap, priv->ext_cap); | ||
678 | return -1; | 798 | return -1; |
679 | } | 799 | } |
680 | 800 | ||
@@ -716,22 +836,52 @@ static const struct dmi_system_id __initconst toshiba_dmi_table[] = { | |||
716 | }, | 836 | }, |
717 | 837 | ||
718 | }, | 838 | }, |
839 | #endif | ||
719 | { } | 840 | { } |
841 | }; | ||
842 | |||
843 | static bool broken_olpc_ec; | ||
844 | |||
845 | static const struct dmi_system_id __initconst olpc_dmi_table[] = { | ||
846 | #if defined(CONFIG_DMI) && defined(CONFIG_OLPC) | ||
847 | { | ||
848 | /* OLPC XO-1 or XO-1.5 */ | ||
849 | .matches = { | ||
850 | DMI_MATCH(DMI_SYS_VENDOR, "OLPC"), | ||
851 | DMI_MATCH(DMI_PRODUCT_NAME, "XO"), | ||
852 | }, | ||
853 | }, | ||
720 | #endif | 854 | #endif |
855 | { } | ||
721 | }; | 856 | }; |
722 | 857 | ||
723 | void __init synaptics_module_init(void) | 858 | void __init synaptics_module_init(void) |
724 | { | 859 | { |
725 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 860 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
861 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | ||
726 | } | 862 | } |
727 | 863 | ||
728 | int synaptics_init(struct psmouse *psmouse) | 864 | int synaptics_init(struct psmouse *psmouse) |
729 | { | 865 | { |
730 | struct synaptics_data *priv; | 866 | struct synaptics_data *priv; |
731 | 867 | ||
868 | /* | ||
869 | * The OLPC XO has issues with Synaptics' absolute mode; similarly to | ||
870 | * the HGPK, it quickly degrades and the hardware becomes jumpy and | ||
871 | * overly sensitive. Not only that, but the constant packet spew | ||
872 | * (even at a lowered 40pps rate) overloads the EC such that key | ||
873 | * presses on the keyboard are missed. Given all of that, don't | ||
874 | * even attempt to use Synaptics mode. Relative mode seems to work | ||
875 | * just fine. | ||
876 | */ | ||
877 | if (broken_olpc_ec) { | ||
878 | printk(KERN_INFO "synaptics: OLPC XO detected, not enabling Synaptics protocol.\n"); | ||
879 | return -ENODEV; | ||
880 | } | ||
881 | |||
732 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); | 882 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); |
733 | if (!priv) | 883 | if (!priv) |
734 | return -1; | 884 | return -ENOMEM; |
735 | 885 | ||
736 | psmouse_reset(psmouse); | 886 | psmouse_reset(psmouse); |
737 | 887 | ||
@@ -745,6 +895,11 @@ int synaptics_init(struct psmouse *psmouse) | |||
745 | goto init_fail; | 895 | goto init_fail; |
746 | } | 896 | } |
747 | 897 | ||
898 | if (synaptics_set_advanced_gesture_mode(psmouse)) { | ||
899 | printk(KERN_ERR "Advanced gesture mode init failed.\n"); | ||
900 | goto init_fail; | ||
901 | } | ||
902 | |||
748 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 903 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
749 | 904 | ||
750 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", | 905 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
@@ -778,8 +933,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
778 | 933 | ||
779 | /* | 934 | /* |
780 | * Toshiba's KBC seems to have trouble handling data from | 935 | * Toshiba's KBC seems to have trouble handling data from |
781 | * Synaptics as full rate, switch to lower rate which is roughly | 936 | * Synaptics at full rate. Switch to a lower rate (roughly |
782 | * thye same as rate of standard PS/2 mouse. | 937 | * the same rate as a standard PS/2 mouse). |
783 | */ | 938 | */ |
784 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { | 939 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { |
785 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", | 940 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", |