diff options
Diffstat (limited to 'usr/src/dkms_source_tree/synaptics.c')
| -rw-r--r-- | usr/src/dkms_source_tree/synaptics.c | 247 |
1 files changed, 161 insertions, 86 deletions
diff --git a/usr/src/dkms_source_tree/synaptics.c b/usr/src/dkms_source_tree/synaptics.c index ae9891c..c19d39f 100644 --- a/usr/src/dkms_source_tree/synaptics.c +++ b/usr/src/dkms_source_tree/synaptics.c | |||
| @@ -279,6 +279,24 @@ 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_multitouch_mode(struct psmouse *psmouse) | ||
| 283 | { | ||
| 284 | static unsigned char param = 0xc8; | ||
| 285 | struct synaptics_data *priv = psmouse->private; | ||
| 286 | |||
| 287 | if (!SYN_CAP_MULTITOUCH(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 | priv->multitouch = 1; | ||
| 296 | printk(KERN_INFO "Synaptics: Multitouch mode enabled\n"); | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 282 | /***************************************************************************** | 300 | /***************************************************************************** |
| 283 | * Synaptics pass-through PS/2 port support | 301 | * Synaptics pass-through PS/2 port support |
| 284 | ****************************************************************************/ | 302 | ****************************************************************************/ |
| @@ -294,7 +312,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c) | |||
| 294 | return 0; | 312 | return 0; |
| 295 | } | 313 | } |
| 296 | 314 | ||
| 297 | static inline int synaptics_is_pt_packet(unsigned char *buf) | 315 | static int synaptics_pt_start(struct serio *serio) |
| 316 | { | ||
| 317 | struct psmouse *parent = serio_get_drvdata(serio->parent); | ||
| 318 | struct synaptics_data *priv = parent->private; | ||
| 319 | |||
| 320 | serio_pause_rx(parent->ps2dev.serio); | ||
| 321 | priv->pt_port = serio; | ||
| 322 | serio_continue_rx(parent->ps2dev.serio); | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | static void synaptics_pt_stop(struct serio *serio) | ||
| 328 | { | ||
| 329 | struct psmouse *parent = serio_get_drvdata(serio->parent); | ||
| 330 | struct synaptics_data *priv = parent->private; | ||
| 331 | |||
| 332 | serio_pause_rx(parent->ps2dev.serio); | ||
| 333 | priv->pt_port = NULL; | ||
| 334 | serio_continue_rx(parent->ps2dev.serio); | ||
| 335 | } | ||
| 336 | |||
| 337 | static int synaptics_is_pt_packet(unsigned char *buf) | ||
| 298 | { | 338 | { |
| 299 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; | 339 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; |
| 300 | } | 340 | } |
| @@ -315,9 +355,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet | |||
| 315 | 355 | ||
| 316 | static void synaptics_pt_activate(struct psmouse *psmouse) | 356 | static void synaptics_pt_activate(struct psmouse *psmouse) |
| 317 | { | 357 | { |
| 318 | struct serio *ptport = psmouse->ps2dev.serio->child; | ||
| 319 | struct psmouse *child = serio_get_drvdata(ptport); | ||
| 320 | struct synaptics_data *priv = psmouse->private; | 358 | struct synaptics_data *priv = psmouse->private; |
| 359 | struct psmouse *child = serio_get_drvdata(priv->pt_port); | ||
| 321 | 360 | ||
| 322 | /* adjust the touchpad to child's choice of protocol */ | 361 | /* adjust the touchpad to child's choice of protocol */ |
| 323 | if (child) { | 362 | if (child) { |
| @@ -345,6 +384,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
| 345 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); | 384 | strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); |
| 346 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); | 385 | strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); |
| 347 | serio->write = synaptics_pt_write; | 386 | serio->write = synaptics_pt_write; |
| 387 | serio->start = synaptics_pt_start; | ||
| 388 | serio->stop = synaptics_pt_stop; | ||
| 348 | serio->parent = psmouse->ps2dev.serio; | 389 | serio->parent = psmouse->ps2dev.serio; |
| 349 | 390 | ||
| 350 | psmouse->pt_activate = synaptics_pt_activate; | 391 | psmouse->pt_activate = synaptics_pt_activate; |
| @@ -357,62 +398,38 @@ static void synaptics_pt_create(struct psmouse *psmouse) | |||
| 357 | * Functions to interpret the absolute mode packets | 398 | * Functions to interpret the absolute mode packets |
| 358 | ****************************************************************************/ | 399 | ****************************************************************************/ |
| 359 | 400 | ||
| 360 | /* left and right clickpad button ranges; | 401 | static int synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) |
| 361 | * the gap between them is interpreted as a middle-button click | ||
| 362 | */ | ||
| 363 | #define CLICKPAD_LEFT_BTN_X \ | ||
| 364 | ((XMAX_NOMINAL - XMIN_NOMINAL) * 2 / 5 + XMIN_NOMINAL) | ||
| 365 | #define CLICKPAD_RIGHT_BTN_X \ | ||
| 366 | ((XMAX_NOMINAL - XMIN_NOMINAL) * 3 / 5 + XMIN_NOMINAL) | ||
| 367 | |||
| 368 | /* handle clickpad events */ | ||
| 369 | static void clickpad_process_packet(struct synaptics_data *priv, | ||
| 370 | struct synaptics_hw_state *hw) | ||
| 371 | { | ||
| 372 | /* clickpad mode reports Y range from 0 to YMAX_NOMINAL, | ||
| 373 | * where the area Y < YMIN_NOMINAL is used as click buttons | ||
| 374 | */ | ||
| 375 | if (hw->y < YMIN_NOMINAL) { | ||
| 376 | /* button area */ | ||
| 377 | hw->z = 0; /* don't move pointer */ | ||
| 378 | /* clickpad reports only the middle button, and we need | ||
| 379 | * to fake left/right buttons depending on the touch position | ||
| 380 | */ | ||
| 381 | if (hw->middle) { /* clicked? */ | ||
| 382 | hw->middle = 0; | ||
| 383 | if (hw->x < CLICKPAD_LEFT_BTN_X) | ||
| 384 | hw->left = 1; | ||
| 385 | else if (hw->x > CLICKPAD_RIGHT_BTN_X) | ||
| 386 | hw->right = 1; | ||
| 387 | else | ||
| 388 | hw->middle = 1; | ||
| 389 | } | ||
| 390 | } else if (hw->middle) { | ||
| 391 | /* dragging */ | ||
| 392 | hw->left = priv->prev_hw.left; | ||
| 393 | hw->right = priv->prev_hw.right; | ||
| 394 | hw->middle = priv->prev_hw.middle; | ||
| 395 | } | ||
| 396 | priv->prev_hw = *hw; | ||
| 397 | } | ||
| 398 | |||
| 399 | static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw) | ||
| 400 | { | 402 | { |
| 401 | memset(hw, 0, sizeof(struct synaptics_hw_state)); | 403 | memset(hw, 0, sizeof(struct synaptics_hw_state)); |
| 402 | 404 | ||
| 403 | if (SYN_MODEL_NEWABS(priv->model_id)) { | 405 | if (SYN_MODEL_NEWABS(priv->model_id)) { |
| 404 | hw->x = (((buf[3] & 0x10) << 8) | | ||
| 405 | ((buf[1] & 0x0f) << 8) | | ||
| 406 | buf[4]); | ||
| 407 | hw->y = (((buf[3] & 0x20) << 7) | | ||
| 408 | ((buf[1] & 0xf0) << 4) | | ||
| 409 | buf[5]); | ||
| 410 | |||
| 411 | hw->z = buf[2]; | ||
| 412 | hw->w = (((buf[0] & 0x30) >> 2) | | 406 | hw->w = (((buf[0] & 0x30) >> 2) | |
| 413 | ((buf[0] & 0x04) >> 1) | | 407 | ((buf[0] & 0x04) >> 1) | |
| 414 | ((buf[3] & 0x04) >> 2)); | 408 | ((buf[3] & 0x04) >> 2)); |
| 415 | 409 | ||
| 410 | if (priv->multitouch && hw->w == 2) { | ||
| 411 | /* Multitouch data is half normal resolution */ | ||
| 412 | hw->x = (((buf[4] & 0x0f) << 8) | | ||
| 413 | buf[1]) << 1; | ||
| 414 | hw->y = (((buf[4] & 0xf0) << 4) | | ||
| 415 | buf[2]) << 1; | ||
| 416 | |||
| 417 | hw->z = ((buf[3] & 0x30) | | ||
| 418 | (buf[5] & 0x0f)) << 1; | ||
| 419 | |||
| 420 | /* Only look at x, y, and z for MT */ | ||
| 421 | return 1; | ||
| 422 | } else { | ||
| 423 | hw->x = (((buf[3] & 0x10) << 8) | | ||
| 424 | ((buf[1] & 0x0f) << 8) | | ||
| 425 | buf[4]); | ||
| 426 | hw->y = (((buf[3] & 0x20) << 7) | | ||
| 427 | ((buf[1] & 0xf0) << 4) | | ||
| 428 | buf[5]); | ||
| 429 | |||
| 430 | hw->z = buf[2]; | ||
| 431 | } | ||
| 432 | |||
| 416 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 433 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
| 417 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 434 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
| 418 | 435 | ||
| @@ -468,6 +485,8 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
| 468 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 485 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
| 469 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 486 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
| 470 | } | 487 | } |
| 488 | |||
| 489 | return 0; | ||
| 471 | } | 490 | } |
| 472 | 491 | ||
| 473 | /* | 492 | /* |
| @@ -482,10 +501,11 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
| 482 | int finger_width; | 501 | int finger_width; |
| 483 | int i; | 502 | int i; |
| 484 | 503 | ||
| 485 | synaptics_parse_hw_state(psmouse->packet, priv, &hw); | 504 | if (synaptics_parse_hw_state(psmouse->packet, priv, &hw)) { |
| 486 | 505 | priv->mt_pkt = 1; | |
| 487 | if (SYN_CAP_CLICKPAD(priv->ext_cap)) | 506 | priv->mt = hw; |
| 488 | clickpad_process_packet(priv, &hw); | 507 | return; |
| 508 | } | ||
| 489 | 509 | ||
| 490 | if (hw.scroll) { | 510 | if (hw.scroll) { |
| 491 | priv->scroll += hw.scroll; | 511 | priv->scroll += hw.scroll; |
| @@ -513,7 +533,8 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
| 513 | if (SYN_CAP_EXTENDED(priv->capabilities)) { | 533 | if (SYN_CAP_EXTENDED(priv->capabilities)) { |
| 514 | switch (hw.w) { | 534 | switch (hw.w) { |
| 515 | case 0 ... 1: | 535 | case 0 ... 1: |
| 516 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) | 536 | if (SYN_CAP_MULTIFINGER(priv->capabilities) || |
| 537 | priv->multitouch) | ||
| 517 | num_fingers = hw.w + 2; | 538 | num_fingers = hw.w + 2; |
| 518 | break; | 539 | break; |
| 519 | case 2: | 540 | case 2: |
| @@ -531,28 +552,64 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
| 531 | finger_width = 0; | 552 | finger_width = 0; |
| 532 | } | 553 | } |
| 533 | 554 | ||
| 534 | /* Post events | 555 | if (priv->multitouch) { |
| 535 | * BTN_TOUCH has to be first as mousedev relies on it when doing | 556 | struct trk_coord pos[2]; |
| 536 | * absolute -> relative conversion | 557 | int slots[2]; |
| 537 | */ | 558 | int npos; |
| 538 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); | 559 | |
| 539 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); | 560 | pos[0].x = hw.x; |
| 561 | pos[0].y = YMAX_NOMINAL + YMIN_NOMINAL - hw.y; | ||
| 562 | pos[1].x = priv->mt.x; | ||
| 563 | pos[1].y = YMAX_NOMINAL + YMIN_NOMINAL - priv->mt.y; | ||
| 564 | npos = priv->mt_pkt ? 2 : 1; | ||
| 565 | input_mt_assign_slots_by_coord(dev, slots, pos, npos); | ||
| 566 | |||
| 567 | for (i = 0; i < npos; i++) { | ||
| 568 | int x = pos[i].x; | ||
| 569 | int y = pos[i].y; | ||
| 570 | int z = i == 0 ? hw.z : priv->mt.z; | ||
| 571 | int s = z > 0 && x > 1; | ||
| 572 | |||
| 573 | input_mt_slot(dev, slots[i]); | ||
| 574 | input_mt_report_state(dev, s); | ||
| 575 | |||
| 576 | if (s) { | ||
| 577 | input_report_abs(dev, ABS_MT_POSITION_X, x); | ||
| 578 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | ||
| 579 | input_report_abs(dev, ABS_MT_PRESSURE, z); | ||
| 580 | } | ||
| 581 | } | ||
| 540 | 582 | ||
| 541 | if (hw.z > 0) { | 583 | input_mt_sync_slot_complement(dev, slots, npos); |
| 542 | input_report_abs(dev, ABS_X, hw.x); | 584 | input_mt_report_emulation(dev); |
| 543 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); | 585 | } else { |
| 586 | |||
| 587 | /* Post events | ||
| 588 | * BTN_TOUCH has to be first as mousedev relies on it when doing | ||
| 589 | * absolute -> relative conversion | ||
| 590 | */ | ||
| 591 | if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); | ||
| 592 | if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); | ||
| 593 | |||
| 594 | if (hw.z > 0) { | ||
| 595 | input_report_abs(dev, ABS_X, hw.x); | ||
| 596 | input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); | ||
| 597 | } | ||
| 598 | input_report_abs(dev, ABS_PRESSURE, hw.z); | ||
| 599 | |||
| 600 | input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); | ||
| 601 | |||
| 602 | if (SYN_CAP_MULTIFINGER(priv->capabilities) || priv->multitouch) { | ||
| 603 | input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); | ||
| 604 | input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); | ||
| 605 | } | ||
| 544 | } | 606 | } |
| 545 | input_report_abs(dev, ABS_PRESSURE, hw.z); | ||
| 546 | 607 | ||
| 547 | input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); | ||
| 548 | input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); | ||
| 549 | input_report_key(dev, BTN_LEFT, hw.left); | 608 | input_report_key(dev, BTN_LEFT, hw.left); |
| 550 | input_report_key(dev, BTN_RIGHT, hw.right); | 609 | input_report_key(dev, BTN_RIGHT, hw.right); |
| 551 | 610 | ||
| 552 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 611 | if (SYN_CAP_PALMDETECT(priv->capabilities)) |
| 553 | input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); | 612 | input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); |
| 554 | input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); | ||
| 555 | } | ||
| 556 | 613 | ||
| 557 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 614 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) |
| 558 | input_report_key(dev, BTN_MIDDLE, hw.middle); | 615 | input_report_key(dev, BTN_MIDDLE, hw.middle); |
| @@ -566,6 +623,8 @@ static void synaptics_process_packet(struct psmouse *psmouse) | |||
| 566 | input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i)); | 623 | input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i)); |
| 567 | 624 | ||
| 568 | input_sync(dev); | 625 | input_sync(dev); |
| 626 | |||
| 627 | priv->mt_pkt = 0; | ||
| 569 | } | 628 | } |
| 570 | 629 | ||
| 571 | static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type) | 630 | static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type) |
| @@ -618,9 +677,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | |||
| 618 | if (unlikely(priv->pkt_type == SYN_NEWABS)) | 677 | if (unlikely(priv->pkt_type == SYN_NEWABS)) |
| 619 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); | 678 | priv->pkt_type = synaptics_detect_pkt_type(psmouse); |
| 620 | 679 | ||
| 621 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) { | 680 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && |
| 622 | if (psmouse->ps2dev.serio->child) | 681 | synaptics_is_pt_packet(psmouse->packet)) { |
| 623 | synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet); | 682 | if (priv->pt_port) |
| 683 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); | ||
| 624 | } else | 684 | } else |
| 625 | synaptics_process_packet(psmouse); | 685 | synaptics_process_packet(psmouse); |
| 626 | 686 | ||
| @@ -644,7 +704,18 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
| 644 | input_set_abs_params(dev, ABS_Y, | 704 | input_set_abs_params(dev, ABS_Y, |
| 645 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); | 705 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); |
| 646 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 706 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
| 647 | __set_bit(ABS_TOOL_WIDTH, dev->absbit); | 707 | |
| 708 | if (priv->multitouch) { | ||
| 709 | input_mt_create_slots_new(dev, 2); | ||
| 710 | input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, | ||
| 711 | priv->x_max ?: XMAX_NOMINAL, 0, 0); | ||
| 712 | input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, | ||
| 713 | priv->y_max ?: YMAX_NOMINAL, 0, 0); | ||
| 714 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | ||
| 715 | } | ||
| 716 | |||
| 717 | if (SYN_CAP_PALMDETECT(priv->capabilities)) | ||
| 718 | input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); | ||
| 648 | 719 | ||
| 649 | __set_bit(EV_KEY, dev->evbit); | 720 | __set_bit(EV_KEY, dev->evbit); |
| 650 | __set_bit(BTN_TOUCH, dev->keybit); | 721 | __set_bit(BTN_TOUCH, dev->keybit); |
| @@ -652,7 +723,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
| 652 | __set_bit(BTN_LEFT, dev->keybit); | 723 | __set_bit(BTN_LEFT, dev->keybit); |
| 653 | __set_bit(BTN_RIGHT, dev->keybit); | 724 | __set_bit(BTN_RIGHT, dev->keybit); |
| 654 | 725 | ||
| 655 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 726 | if (SYN_CAP_MULTIFINGER(priv->capabilities) | priv->multitouch) { |
| 656 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 727 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
| 657 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 728 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
| 658 | } | 729 | } |
| @@ -673,8 +744,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
| 673 | __clear_bit(REL_X, dev->relbit); | 744 | __clear_bit(REL_X, dev->relbit); |
| 674 | __clear_bit(REL_Y, dev->relbit); | 745 | __clear_bit(REL_Y, dev->relbit); |
| 675 | 746 | ||
| 676 | dev->absres[ABS_X] = priv->x_res; | 747 | input_abs_set_res(dev, ABS_X, priv->x_res); |
| 677 | dev->absres[ABS_Y] = priv->y_res; | 748 | input_abs_set_res(dev, ABS_Y, priv->y_res); |
| 678 | 749 | ||
| 679 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 750 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
| 680 | /* Clickpads report only left button */ | 751 | /* Clickpads report only left button */ |
| @@ -716,6 +787,11 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
| 716 | return -1; | 787 | return -1; |
| 717 | } | 788 | } |
| 718 | 789 | ||
| 790 | if (synaptics_set_multitouch_mode(psmouse)) { | ||
| 791 | printk(KERN_ERR "Unable to initialize Synaptics Multitouch.\n"); | ||
| 792 | return -1; | ||
| 793 | } | ||
| 794 | |||
| 719 | return 0; | 795 | return 0; |
| 720 | } | 796 | } |
| 721 | 797 | ||
| @@ -769,7 +845,7 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 769 | 845 | ||
| 770 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); | 846 | psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); |
| 771 | if (!priv) | 847 | if (!priv) |
| 772 | return -1; | 848 | return -ENOMEM; |
| 773 | 849 | ||
| 774 | psmouse_reset(psmouse); | 850 | psmouse_reset(psmouse); |
| 775 | 851 | ||
| @@ -783,6 +859,11 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 783 | goto init_fail; | 859 | goto init_fail; |
| 784 | } | 860 | } |
| 785 | 861 | ||
| 862 | if (synaptics_set_multitouch_mode(psmouse)) { | ||
| 863 | printk(KERN_ERR "Unable to initialize Synaptics Multitouch.\n"); | ||
| 864 | goto init_fail; | ||
| 865 | } | ||
| 866 | |||
| 786 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 867 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
| 787 | 868 | ||
| 788 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", | 869 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
| @@ -790,12 +871,6 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 790 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), | 871 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), |
| 791 | priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c); | 872 | priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c); |
| 792 | 873 | ||
| 793 | if (SYN_CAP_CLICKPAD(priv->ext_cap)) { | ||
| 794 | printk(KERN_INFO "Synaptics: Clickpad mode enabled\n"); | ||
| 795 | /* force to enable the middle button */ | ||
| 796 | priv->capabilities |= (1 << 18); | ||
| 797 | } | ||
| 798 | |||
| 799 | set_input_params(psmouse->dev, priv); | 874 | set_input_params(psmouse->dev, priv); |
| 800 | 875 | ||
| 801 | /* | 876 | /* |
