diff options
Diffstat (limited to 'drivers/input/mouse/cyapa.c')
-rw-r--r-- | drivers/input/mouse/cyapa.c | 289 |
1 files changed, 156 insertions, 133 deletions
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index b409c3d7d4fb..1bece8cad46f 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Daniel Kurtz <djkurtz@chromium.org> | 6 | * Daniel Kurtz <djkurtz@chromium.org> |
7 | * Benson Leung <bleung@chromium.org> | 7 | * Benson Leung <bleung@chromium.org> |
8 | * | 8 | * |
9 | * Copyright (C) 2011-2012 Cypress Semiconductor, Inc. | 9 | * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. |
10 | * Copyright (C) 2011-2012 Google, Inc. | 10 | * Copyright (C) 2011-2012 Google, Inc. |
11 | * | 11 | * |
12 | * This file is subject to the terms and conditions of the GNU General Public | 12 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -206,7 +206,6 @@ struct cyapa { | |||
206 | struct i2c_client *client; | 206 | struct i2c_client *client; |
207 | struct input_dev *input; | 207 | struct input_dev *input; |
208 | char phys[32]; /* device physical location */ | 208 | char phys[32]; /* device physical location */ |
209 | int irq; | ||
210 | bool irq_wake; /* irq wake is enabled */ | 209 | bool irq_wake; /* irq wake is enabled */ |
211 | bool smbus; | 210 | bool smbus; |
212 | 211 | ||
@@ -422,8 +421,8 @@ static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) | |||
422 | */ | 421 | */ |
423 | static int cyapa_get_state(struct cyapa *cyapa) | 422 | static int cyapa_get_state(struct cyapa *cyapa) |
424 | { | 423 | { |
425 | int ret; | ||
426 | u8 status[BL_STATUS_SIZE]; | 424 | u8 status[BL_STATUS_SIZE]; |
425 | int error; | ||
427 | 426 | ||
428 | cyapa->state = CYAPA_STATE_NO_DEVICE; | 427 | cyapa->state = CYAPA_STATE_NO_DEVICE; |
429 | 428 | ||
@@ -433,18 +432,18 @@ static int cyapa_get_state(struct cyapa *cyapa) | |||
433 | * If the device is in operation mode, this will be the DATA regs. | 432 | * If the device is in operation mode, this will be the DATA regs. |
434 | * | 433 | * |
435 | */ | 434 | */ |
436 | ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, | 435 | error = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, |
437 | status); | 436 | status); |
438 | 437 | ||
439 | /* | 438 | /* |
440 | * On smbus systems in OP mode, the i2c_reg_read will fail with | 439 | * On smbus systems in OP mode, the i2c_reg_read will fail with |
441 | * -ETIMEDOUT. In this case, try again using the smbus equivalent | 440 | * -ETIMEDOUT. In this case, try again using the smbus equivalent |
442 | * command. This should return a BL_HEAD indicating CYAPA_STATE_OP. | 441 | * command. This should return a BL_HEAD indicating CYAPA_STATE_OP. |
443 | */ | 442 | */ |
444 | if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO)) | 443 | if (cyapa->smbus && (error == -ETIMEDOUT || error == -ENXIO)) |
445 | ret = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status); | 444 | error = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status); |
446 | 445 | ||
447 | if (ret != BL_STATUS_SIZE) | 446 | if (error != BL_STATUS_SIZE) |
448 | goto error; | 447 | goto error; |
449 | 448 | ||
450 | if ((status[REG_OP_STATUS] & OP_STATUS_SRC) == OP_STATUS_SRC) { | 449 | if ((status[REG_OP_STATUS] & OP_STATUS_SRC) == OP_STATUS_SRC) { |
@@ -454,7 +453,7 @@ static int cyapa_get_state(struct cyapa *cyapa) | |||
454 | cyapa->state = CYAPA_STATE_OP; | 453 | cyapa->state = CYAPA_STATE_OP; |
455 | break; | 454 | break; |
456 | default: | 455 | default: |
457 | ret = -EAGAIN; | 456 | error = -EAGAIN; |
458 | goto error; | 457 | goto error; |
459 | } | 458 | } |
460 | } else { | 459 | } else { |
@@ -468,7 +467,7 @@ static int cyapa_get_state(struct cyapa *cyapa) | |||
468 | 467 | ||
469 | return 0; | 468 | return 0; |
470 | error: | 469 | error: |
471 | return (ret < 0) ? ret : -EAGAIN; | 470 | return (error < 0) ? error : -EAGAIN; |
472 | } | 471 | } |
473 | 472 | ||
474 | /* | 473 | /* |
@@ -487,31 +486,31 @@ error: | |||
487 | */ | 486 | */ |
488 | static int cyapa_poll_state(struct cyapa *cyapa, unsigned int timeout) | 487 | static int cyapa_poll_state(struct cyapa *cyapa, unsigned int timeout) |
489 | { | 488 | { |
490 | int ret; | 489 | int error; |
491 | int tries = timeout / 100; | 490 | int tries = timeout / 100; |
492 | 491 | ||
493 | ret = cyapa_get_state(cyapa); | 492 | error = cyapa_get_state(cyapa); |
494 | while ((ret || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) { | 493 | while ((error || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) { |
495 | msleep(100); | 494 | msleep(100); |
496 | ret = cyapa_get_state(cyapa); | 495 | error = cyapa_get_state(cyapa); |
497 | } | 496 | } |
498 | return (ret == -EAGAIN || ret == -ETIMEDOUT) ? -ETIMEDOUT : ret; | 497 | return (error == -EAGAIN || error == -ETIMEDOUT) ? -ETIMEDOUT : error; |
499 | } | 498 | } |
500 | 499 | ||
501 | static int cyapa_bl_deactivate(struct cyapa *cyapa) | 500 | static int cyapa_bl_deactivate(struct cyapa *cyapa) |
502 | { | 501 | { |
503 | int ret; | 502 | int error; |
504 | 503 | ||
505 | ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate), | 504 | error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate), |
506 | bl_deactivate); | 505 | bl_deactivate); |
507 | if (ret < 0) | 506 | if (error) |
508 | return ret; | 507 | return error; |
509 | 508 | ||
510 | /* wait for bootloader to switch to idle state; should take < 100ms */ | 509 | /* wait for bootloader to switch to idle state; should take < 100ms */ |
511 | msleep(100); | 510 | msleep(100); |
512 | ret = cyapa_poll_state(cyapa, 500); | 511 | error = cyapa_poll_state(cyapa, 500); |
513 | if (ret < 0) | 512 | if (error) |
514 | return ret; | 513 | return error; |
515 | if (cyapa->state != CYAPA_STATE_BL_IDLE) | 514 | if (cyapa->state != CYAPA_STATE_BL_IDLE) |
516 | return -EAGAIN; | 515 | return -EAGAIN; |
517 | return 0; | 516 | return 0; |
@@ -532,11 +531,11 @@ static int cyapa_bl_deactivate(struct cyapa *cyapa) | |||
532 | */ | 531 | */ |
533 | static int cyapa_bl_exit(struct cyapa *cyapa) | 532 | static int cyapa_bl_exit(struct cyapa *cyapa) |
534 | { | 533 | { |
535 | int ret; | 534 | int error; |
536 | 535 | ||
537 | ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit); | 536 | error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit); |
538 | if (ret < 0) | 537 | if (error) |
539 | return ret; | 538 | return error; |
540 | 539 | ||
541 | /* | 540 | /* |
542 | * Wait for bootloader to exit, and operation mode to start. | 541 | * Wait for bootloader to exit, and operation mode to start. |
@@ -548,9 +547,9 @@ static int cyapa_bl_exit(struct cyapa *cyapa) | |||
548 | * updated to new firmware, it must first calibrate its sensors, which | 547 | * updated to new firmware, it must first calibrate its sensors, which |
549 | * can take up to an additional 2 seconds. | 548 | * can take up to an additional 2 seconds. |
550 | */ | 549 | */ |
551 | ret = cyapa_poll_state(cyapa, 2000); | 550 | error = cyapa_poll_state(cyapa, 2000); |
552 | if (ret < 0) | 551 | if (error < 0) |
553 | return ret; | 552 | return error; |
554 | if (cyapa->state != CYAPA_STATE_OP) | 553 | if (cyapa->state != CYAPA_STATE_OP) |
555 | return -EAGAIN; | 554 | return -EAGAIN; |
556 | 555 | ||
@@ -577,10 +576,13 @@ static int cyapa_set_power_mode(struct cyapa *cyapa, u8 power_mode) | |||
577 | power = ret & ~PWR_MODE_MASK; | 576 | power = ret & ~PWR_MODE_MASK; |
578 | power |= power_mode & PWR_MODE_MASK; | 577 | power |= power_mode & PWR_MODE_MASK; |
579 | ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power); | 578 | ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power); |
580 | if (ret < 0) | 579 | if (ret < 0) { |
581 | dev_err(dev, "failed to set power_mode 0x%02x err = %d\n", | 580 | dev_err(dev, "failed to set power_mode 0x%02x err = %d\n", |
582 | power_mode, ret); | 581 | power_mode, ret); |
583 | return ret; | 582 | return ret; |
583 | } | ||
584 | |||
585 | return 0; | ||
584 | } | 586 | } |
585 | 587 | ||
586 | static int cyapa_get_query_data(struct cyapa *cyapa) | 588 | static int cyapa_get_query_data(struct cyapa *cyapa) |
@@ -637,28 +639,28 @@ static int cyapa_check_is_operational(struct cyapa *cyapa) | |||
637 | { | 639 | { |
638 | struct device *dev = &cyapa->client->dev; | 640 | struct device *dev = &cyapa->client->dev; |
639 | static const char unique_str[] = "CYTRA"; | 641 | static const char unique_str[] = "CYTRA"; |
640 | int ret; | 642 | int error; |
641 | 643 | ||
642 | ret = cyapa_poll_state(cyapa, 2000); | 644 | error = cyapa_poll_state(cyapa, 2000); |
643 | if (ret < 0) | 645 | if (error) |
644 | return ret; | 646 | return error; |
645 | switch (cyapa->state) { | 647 | switch (cyapa->state) { |
646 | case CYAPA_STATE_BL_ACTIVE: | 648 | case CYAPA_STATE_BL_ACTIVE: |
647 | ret = cyapa_bl_deactivate(cyapa); | 649 | error = cyapa_bl_deactivate(cyapa); |
648 | if (ret) | 650 | if (error) |
649 | return ret; | 651 | return error; |
650 | 652 | ||
651 | /* Fallthrough state */ | 653 | /* Fallthrough state */ |
652 | case CYAPA_STATE_BL_IDLE: | 654 | case CYAPA_STATE_BL_IDLE: |
653 | ret = cyapa_bl_exit(cyapa); | 655 | error = cyapa_bl_exit(cyapa); |
654 | if (ret) | 656 | if (error) |
655 | return ret; | 657 | return error; |
656 | 658 | ||
657 | /* Fallthrough state */ | 659 | /* Fallthrough state */ |
658 | case CYAPA_STATE_OP: | 660 | case CYAPA_STATE_OP: |
659 | ret = cyapa_get_query_data(cyapa); | 661 | error = cyapa_get_query_data(cyapa); |
660 | if (ret < 0) | 662 | if (error) |
661 | return ret; | 663 | return error; |
662 | 664 | ||
663 | /* only support firmware protocol gen3 */ | 665 | /* only support firmware protocol gen3 */ |
664 | if (cyapa->gen != CYAPA_GEN3) { | 666 | if (cyapa->gen != CYAPA_GEN3) { |
@@ -753,18 +755,42 @@ static u8 cyapa_check_adapter_functionality(struct i2c_client *client) | |||
753 | return ret; | 755 | return ret; |
754 | } | 756 | } |
755 | 757 | ||
758 | static int cyapa_open(struct input_dev *input) | ||
759 | { | ||
760 | struct cyapa *cyapa = input_get_drvdata(input); | ||
761 | struct i2c_client *client = cyapa->client; | ||
762 | int error; | ||
763 | |||
764 | error = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); | ||
765 | if (error) { | ||
766 | dev_err(&client->dev, "set active power failed: %d\n", error); | ||
767 | return error; | ||
768 | } | ||
769 | |||
770 | enable_irq(client->irq); | ||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static void cyapa_close(struct input_dev *input) | ||
775 | { | ||
776 | struct cyapa *cyapa = input_get_drvdata(input); | ||
777 | |||
778 | disable_irq(cyapa->client->irq); | ||
779 | cyapa_set_power_mode(cyapa, PWR_MODE_OFF); | ||
780 | } | ||
781 | |||
756 | static int cyapa_create_input_dev(struct cyapa *cyapa) | 782 | static int cyapa_create_input_dev(struct cyapa *cyapa) |
757 | { | 783 | { |
758 | struct device *dev = &cyapa->client->dev; | 784 | struct device *dev = &cyapa->client->dev; |
759 | int ret; | ||
760 | struct input_dev *input; | 785 | struct input_dev *input; |
786 | int error; | ||
761 | 787 | ||
762 | if (!cyapa->physical_size_x || !cyapa->physical_size_y) | 788 | if (!cyapa->physical_size_x || !cyapa->physical_size_y) |
763 | return -EINVAL; | 789 | return -EINVAL; |
764 | 790 | ||
765 | input = cyapa->input = input_allocate_device(); | 791 | input = devm_input_allocate_device(dev); |
766 | if (!input) { | 792 | if (!input) { |
767 | dev_err(dev, "allocate memory for input device failed\n"); | 793 | dev_err(dev, "failed to allocate memory for input device.\n"); |
768 | return -ENOMEM; | 794 | return -ENOMEM; |
769 | } | 795 | } |
770 | 796 | ||
@@ -772,14 +798,17 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) | |||
772 | input->phys = cyapa->phys; | 798 | input->phys = cyapa->phys; |
773 | input->id.bustype = BUS_I2C; | 799 | input->id.bustype = BUS_I2C; |
774 | input->id.version = 1; | 800 | input->id.version = 1; |
775 | input->id.product = 0; /* means any product in eventcomm. */ | 801 | input->id.product = 0; /* Means any product in eventcomm. */ |
776 | input->dev.parent = &cyapa->client->dev; | 802 | input->dev.parent = &cyapa->client->dev; |
777 | 803 | ||
804 | input->open = cyapa_open; | ||
805 | input->close = cyapa_close; | ||
806 | |||
778 | input_set_drvdata(input, cyapa); | 807 | input_set_drvdata(input, cyapa); |
779 | 808 | ||
780 | __set_bit(EV_ABS, input->evbit); | 809 | __set_bit(EV_ABS, input->evbit); |
781 | 810 | ||
782 | /* finger position */ | 811 | /* Finger position */ |
783 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, cyapa->max_abs_x, 0, | 812 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, cyapa->max_abs_x, 0, |
784 | 0); | 813 | 0); |
785 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cyapa->max_abs_y, 0, | 814 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cyapa->max_abs_y, 0, |
@@ -801,35 +830,25 @@ static int cyapa_create_input_dev(struct cyapa *cyapa) | |||
801 | if (cyapa->btn_capability == CAPABILITY_LEFT_BTN_MASK) | 830 | if (cyapa->btn_capability == CAPABILITY_LEFT_BTN_MASK) |
802 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | 831 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
803 | 832 | ||
804 | /* handle pointer emulation and unused slots in core */ | 833 | /* Handle pointer emulation and unused slots in core */ |
805 | ret = input_mt_init_slots(input, CYAPA_MAX_MT_SLOTS, | 834 | error = input_mt_init_slots(input, CYAPA_MAX_MT_SLOTS, |
806 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED); | 835 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED); |
807 | if (ret) { | 836 | if (error) { |
808 | dev_err(dev, "allocate memory for MT slots failed, %d\n", ret); | 837 | dev_err(dev, "failed to initialize MT slots: %d\n", error); |
809 | goto err_free_device; | 838 | return error; |
810 | } | 839 | } |
811 | 840 | ||
812 | /* Register the device in input subsystem */ | 841 | cyapa->input = input; |
813 | ret = input_register_device(input); | ||
814 | if (ret) { | ||
815 | dev_err(dev, "input device register failed, %d\n", ret); | ||
816 | goto err_free_device; | ||
817 | } | ||
818 | return 0; | 842 | return 0; |
819 | |||
820 | err_free_device: | ||
821 | input_free_device(input); | ||
822 | cyapa->input = NULL; | ||
823 | return ret; | ||
824 | } | 843 | } |
825 | 844 | ||
826 | static int cyapa_probe(struct i2c_client *client, | 845 | static int cyapa_probe(struct i2c_client *client, |
827 | const struct i2c_device_id *dev_id) | 846 | const struct i2c_device_id *dev_id) |
828 | { | 847 | { |
829 | int ret; | ||
830 | u8 adapter_func; | ||
831 | struct cyapa *cyapa; | ||
832 | struct device *dev = &client->dev; | 848 | struct device *dev = &client->dev; |
849 | struct cyapa *cyapa; | ||
850 | u8 adapter_func; | ||
851 | int error; | ||
833 | 852 | ||
834 | adapter_func = cyapa_check_adapter_functionality(client); | 853 | adapter_func = cyapa_check_adapter_functionality(client); |
835 | if (adapter_func == CYAPA_ADAPTER_FUNC_NONE) { | 854 | if (adapter_func == CYAPA_ADAPTER_FUNC_NONE) { |
@@ -837,11 +856,9 @@ static int cyapa_probe(struct i2c_client *client, | |||
837 | return -EIO; | 856 | return -EIO; |
838 | } | 857 | } |
839 | 858 | ||
840 | cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL); | 859 | cyapa = devm_kzalloc(dev, sizeof(struct cyapa), GFP_KERNEL); |
841 | if (!cyapa) { | 860 | if (!cyapa) |
842 | dev_err(dev, "allocate memory for cyapa failed\n"); | ||
843 | return -ENOMEM; | 861 | return -ENOMEM; |
844 | } | ||
845 | 862 | ||
846 | cyapa->gen = CYAPA_GEN3; | 863 | cyapa->gen = CYAPA_GEN3; |
847 | cyapa->client = client; | 864 | cyapa->client = client; |
@@ -852,67 +869,61 @@ static int cyapa_probe(struct i2c_client *client, | |||
852 | /* i2c isn't supported, use smbus */ | 869 | /* i2c isn't supported, use smbus */ |
853 | if (adapter_func == CYAPA_ADAPTER_FUNC_SMBUS) | 870 | if (adapter_func == CYAPA_ADAPTER_FUNC_SMBUS) |
854 | cyapa->smbus = true; | 871 | cyapa->smbus = true; |
872 | |||
855 | cyapa->state = CYAPA_STATE_NO_DEVICE; | 873 | cyapa->state = CYAPA_STATE_NO_DEVICE; |
856 | ret = cyapa_check_is_operational(cyapa); | ||
857 | if (ret) { | ||
858 | dev_err(dev, "device not operational, %d\n", ret); | ||
859 | goto err_mem_free; | ||
860 | } | ||
861 | 874 | ||
862 | ret = cyapa_create_input_dev(cyapa); | 875 | error = cyapa_check_is_operational(cyapa); |
863 | if (ret) { | 876 | if (error) { |
864 | dev_err(dev, "create input_dev instance failed, %d\n", ret); | 877 | dev_err(dev, "device not operational, %d\n", error); |
865 | goto err_mem_free; | 878 | return error; |
866 | } | 879 | } |
867 | 880 | ||
868 | ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); | 881 | /* Power down the device until we need it */ |
869 | if (ret) { | 882 | error = cyapa_set_power_mode(cyapa, PWR_MODE_OFF); |
870 | dev_err(dev, "set active power failed, %d\n", ret); | 883 | if (error) { |
871 | goto err_unregister_device; | 884 | dev_err(dev, "failed to quiesce the device: %d\n", error); |
885 | return error; | ||
872 | } | 886 | } |
873 | 887 | ||
874 | cyapa->irq = client->irq; | 888 | error = cyapa_create_input_dev(cyapa); |
875 | ret = request_threaded_irq(cyapa->irq, | 889 | if (error) |
876 | NULL, | 890 | return error; |
877 | cyapa_irq, | 891 | |
878 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 892 | error = devm_request_threaded_irq(dev, client->irq, |
879 | "cyapa", | 893 | NULL, cyapa_irq, |
880 | cyapa); | 894 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
881 | if (ret) { | 895 | "cyapa", cyapa); |
882 | dev_err(dev, "IRQ request failed: %d\n, ", ret); | 896 | if (error) { |
883 | goto err_unregister_device; | 897 | dev_err(dev, "failed to request threaded irq: %d\n", error); |
898 | return error; | ||
884 | } | 899 | } |
885 | 900 | ||
886 | return 0; | 901 | /* Disable IRQ until the device is opened */ |
902 | disable_irq(client->irq); | ||
887 | 903 | ||
888 | err_unregister_device: | 904 | /* Register the device in input subsystem */ |
889 | input_unregister_device(cyapa->input); | 905 | error = input_register_device(cyapa->input); |
890 | err_mem_free: | 906 | if (error) { |
891 | kfree(cyapa); | 907 | dev_err(dev, "failed to register input device: %d\n", error); |
892 | 908 | return error; | |
893 | return ret; | 909 | } |
894 | } | ||
895 | |||
896 | static int cyapa_remove(struct i2c_client *client) | ||
897 | { | ||
898 | struct cyapa *cyapa = i2c_get_clientdata(client); | ||
899 | |||
900 | free_irq(cyapa->irq, cyapa); | ||
901 | input_unregister_device(cyapa->input); | ||
902 | cyapa_set_power_mode(cyapa, PWR_MODE_OFF); | ||
903 | kfree(cyapa); | ||
904 | 910 | ||
905 | return 0; | 911 | return 0; |
906 | } | 912 | } |
907 | 913 | ||
908 | #ifdef CONFIG_PM_SLEEP | 914 | static int __maybe_unused cyapa_suspend(struct device *dev) |
909 | static int cyapa_suspend(struct device *dev) | ||
910 | { | 915 | { |
911 | int ret; | 916 | struct i2c_client *client = to_i2c_client(dev); |
917 | struct cyapa *cyapa = i2c_get_clientdata(client); | ||
918 | struct input_dev *input = cyapa->input; | ||
912 | u8 power_mode; | 919 | u8 power_mode; |
913 | struct cyapa *cyapa = dev_get_drvdata(dev); | 920 | int error; |
914 | 921 | ||
915 | disable_irq(cyapa->irq); | 922 | error = mutex_lock_interruptible(&input->mutex); |
923 | if (error) | ||
924 | return error; | ||
925 | |||
926 | disable_irq(client->irq); | ||
916 | 927 | ||
917 | /* | 928 | /* |
918 | * Set trackpad device to idle mode if wakeup is allowed, | 929 | * Set trackpad device to idle mode if wakeup is allowed, |
@@ -920,31 +931,44 @@ static int cyapa_suspend(struct device *dev) | |||
920 | */ | 931 | */ |
921 | power_mode = device_may_wakeup(dev) ? PWR_MODE_IDLE | 932 | power_mode = device_may_wakeup(dev) ? PWR_MODE_IDLE |
922 | : PWR_MODE_OFF; | 933 | : PWR_MODE_OFF; |
923 | ret = cyapa_set_power_mode(cyapa, power_mode); | 934 | error = cyapa_set_power_mode(cyapa, power_mode); |
924 | if (ret < 0) | 935 | if (error) |
925 | dev_err(dev, "set power mode failed, %d\n", ret); | 936 | dev_err(dev, "resume: set power mode to %d failed: %d\n", |
937 | power_mode, error); | ||
926 | 938 | ||
927 | if (device_may_wakeup(dev)) | 939 | if (device_may_wakeup(dev)) |
928 | cyapa->irq_wake = (enable_irq_wake(cyapa->irq) == 0); | 940 | cyapa->irq_wake = (enable_irq_wake(client->irq) == 0); |
941 | |||
942 | mutex_unlock(&input->mutex); | ||
943 | |||
929 | return 0; | 944 | return 0; |
930 | } | 945 | } |
931 | 946 | ||
932 | static int cyapa_resume(struct device *dev) | 947 | static int __maybe_unused cyapa_resume(struct device *dev) |
933 | { | 948 | { |
934 | int ret; | 949 | struct i2c_client *client = to_i2c_client(dev); |
935 | struct cyapa *cyapa = dev_get_drvdata(dev); | 950 | struct cyapa *cyapa = i2c_get_clientdata(client); |
951 | struct input_dev *input = cyapa->input; | ||
952 | u8 power_mode; | ||
953 | int error; | ||
954 | |||
955 | mutex_lock(&input->mutex); | ||
936 | 956 | ||
937 | if (device_may_wakeup(dev) && cyapa->irq_wake) | 957 | if (device_may_wakeup(dev) && cyapa->irq_wake) |
938 | disable_irq_wake(cyapa->irq); | 958 | disable_irq_wake(client->irq); |
959 | |||
960 | power_mode = input->users ? PWR_MODE_FULL_ACTIVE : PWR_MODE_OFF; | ||
961 | error = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); | ||
962 | if (error) | ||
963 | dev_warn(dev, "resume: set power mode to %d failed: %d\n", | ||
964 | power_mode, error); | ||
965 | |||
966 | enable_irq(client->irq); | ||
939 | 967 | ||
940 | ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); | 968 | mutex_unlock(&input->mutex); |
941 | if (ret) | ||
942 | dev_warn(dev, "resume active power failed, %d\n", ret); | ||
943 | 969 | ||
944 | enable_irq(cyapa->irq); | ||
945 | return 0; | 970 | return 0; |
946 | } | 971 | } |
947 | #endif /* CONFIG_PM_SLEEP */ | ||
948 | 972 | ||
949 | static SIMPLE_DEV_PM_OPS(cyapa_pm_ops, cyapa_suspend, cyapa_resume); | 973 | static SIMPLE_DEV_PM_OPS(cyapa_pm_ops, cyapa_suspend, cyapa_resume); |
950 | 974 | ||
@@ -962,7 +986,6 @@ static struct i2c_driver cyapa_driver = { | |||
962 | }, | 986 | }, |
963 | 987 | ||
964 | .probe = cyapa_probe, | 988 | .probe = cyapa_probe, |
965 | .remove = cyapa_remove, | ||
966 | .id_table = cyapa_id_table, | 989 | .id_table = cyapa_id_table, |
967 | }; | 990 | }; |
968 | 991 | ||