diff options
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 35 |
2 files changed, 36 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 637074d89790..c86bae828c28 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -289,6 +289,7 @@ config IDEAPAD_LAPTOP | |||
289 | tristate "Lenovo IdeaPad Laptop Extras" | 289 | tristate "Lenovo IdeaPad Laptop Extras" |
290 | depends on ACPI | 290 | depends on ACPI |
291 | depends on RFKILL && INPUT | 291 | depends on RFKILL && INPUT |
292 | depends on SERIO_I8042 | ||
292 | select INPUT_SPARSEKMAP | 293 | select INPUT_SPARSEKMAP |
293 | help | 294 | help |
294 | This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. | 295 | This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. |
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 2396242e8418..7bc1b6c60e56 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/fb.h> | 36 | #include <linux/fb.h> |
37 | #include <linux/debugfs.h> | 37 | #include <linux/debugfs.h> |
38 | #include <linux/seq_file.h> | 38 | #include <linux/seq_file.h> |
39 | #include <linux/i8042.h> | ||
39 | 40 | ||
40 | #define IDEAPAD_RFKILL_DEV_NUM (3) | 41 | #define IDEAPAD_RFKILL_DEV_NUM (3) |
41 | 42 | ||
@@ -526,6 +527,8 @@ static const struct key_entry ideapad_keymap[] = { | |||
526 | { KE_KEY, 17, { KEY_PROG2 } }, | 527 | { KE_KEY, 17, { KEY_PROG2 } }, |
527 | { KE_KEY, 64, { KEY_PROG3 } }, | 528 | { KE_KEY, 64, { KEY_PROG3 } }, |
528 | { KE_KEY, 65, { KEY_PROG4 } }, | 529 | { KE_KEY, 65, { KEY_PROG4 } }, |
530 | { KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, | ||
531 | { KE_KEY, 67, { KEY_TOUCHPAD_ON } }, | ||
529 | { KE_END, 0 }, | 532 | { KE_END, 0 }, |
530 | }; | 533 | }; |
531 | 534 | ||
@@ -718,6 +721,24 @@ static const struct acpi_device_id ideapad_device_ids[] = { | |||
718 | }; | 721 | }; |
719 | MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); | 722 | MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); |
720 | 723 | ||
724 | static void ideapad_sync_touchpad_state(struct acpi_device *adevice) | ||
725 | { | ||
726 | struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); | ||
727 | unsigned long value; | ||
728 | |||
729 | /* Without reading from EC touchpad LED doesn't switch state */ | ||
730 | if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { | ||
731 | /* Some IdeaPads don't really turn off touchpad - they only | ||
732 | * switch the LED state. We (de)activate KBC AUX port to turn | ||
733 | * touchpad off and on. We send KEY_TOUCHPAD_OFF and | ||
734 | * KEY_TOUCHPAD_ON to not to get out of sync with LED */ | ||
735 | unsigned char param; | ||
736 | i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : | ||
737 | I8042_CMD_AUX_DISABLE); | ||
738 | ideapad_input_report(priv, value ? 67 : 66); | ||
739 | } | ||
740 | } | ||
741 | |||
721 | static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | 742 | static int __devinit ideapad_acpi_add(struct acpi_device *adevice) |
722 | { | 743 | { |
723 | int ret, i; | 744 | int ret, i; |
@@ -754,6 +775,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | |||
754 | priv->rfk[i] = NULL; | 775 | priv->rfk[i] = NULL; |
755 | } | 776 | } |
756 | ideapad_sync_rfk_state(priv); | 777 | ideapad_sync_rfk_state(priv); |
778 | ideapad_sync_touchpad_state(adevice); | ||
757 | 779 | ||
758 | if (!acpi_video_backlight_support()) { | 780 | if (!acpi_video_backlight_support()) { |
759 | ret = ideapad_backlight_init(priv); | 781 | ret = ideapad_backlight_init(priv); |
@@ -817,6 +839,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) | |||
817 | case 6: | 839 | case 6: |
818 | ideapad_input_report(priv, vpc_bit); | 840 | ideapad_input_report(priv, vpc_bit); |
819 | break; | 841 | break; |
842 | case 5: | ||
843 | ideapad_sync_touchpad_state(adevice); | ||
844 | break; | ||
820 | case 4: | 845 | case 4: |
821 | ideapad_backlight_notify_brightness(priv); | 846 | ideapad_backlight_notify_brightness(priv); |
822 | break; | 847 | break; |
@@ -836,6 +861,15 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event) | |||
836 | } | 861 | } |
837 | } | 862 | } |
838 | 863 | ||
864 | static int ideapad_acpi_resume(struct device *device) | ||
865 | { | ||
866 | ideapad_sync_rfk_state(ideapad_priv); | ||
867 | ideapad_sync_touchpad_state(to_acpi_device(device)); | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); | ||
872 | |||
839 | static struct acpi_driver ideapad_acpi_driver = { | 873 | static struct acpi_driver ideapad_acpi_driver = { |
840 | .name = "ideapad_acpi", | 874 | .name = "ideapad_acpi", |
841 | .class = "IdeaPad", | 875 | .class = "IdeaPad", |
@@ -843,6 +877,7 @@ static struct acpi_driver ideapad_acpi_driver = { | |||
843 | .ops.add = ideapad_acpi_add, | 877 | .ops.add = ideapad_acpi_add, |
844 | .ops.remove = ideapad_acpi_remove, | 878 | .ops.remove = ideapad_acpi_remove, |
845 | .ops.notify = ideapad_acpi_notify, | 879 | .ops.notify = ideapad_acpi_notify, |
880 | .drv.pm = &ideapad_pm, | ||
846 | .owner = THIS_MODULE, | 881 | .owner = THIS_MODULE, |
847 | }; | 882 | }; |
848 | 883 | ||