diff options
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 340 |
1 files changed, 205 insertions, 135 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 222ffb892f22..da3c08b3dcc1 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -142,18 +142,28 @@ struct eeepc_hotk { | |||
142 | struct rfkill *wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
143 | struct rfkill *bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
144 | struct rfkill *wwan3g_rfkill; | 144 | struct rfkill *wwan3g_rfkill; |
145 | struct rfkill *wimax_rfkill; | ||
145 | struct hotplug_slot *hotplug_slot; | 146 | struct hotplug_slot *hotplug_slot; |
146 | struct work_struct hotplug_work; | 147 | struct mutex hotplug_lock; |
147 | }; | 148 | }; |
148 | 149 | ||
149 | /* The actual device the driver binds to */ | 150 | /* The actual device the driver binds to */ |
150 | static struct eeepc_hotk *ehotk; | 151 | static struct eeepc_hotk *ehotk; |
151 | 152 | ||
152 | /* Platform device/driver */ | 153 | /* Platform device/driver */ |
154 | static int eeepc_hotk_thaw(struct device *device); | ||
155 | static int eeepc_hotk_restore(struct device *device); | ||
156 | |||
157 | static struct dev_pm_ops eeepc_pm_ops = { | ||
158 | .thaw = eeepc_hotk_thaw, | ||
159 | .restore = eeepc_hotk_restore, | ||
160 | }; | ||
161 | |||
153 | static struct platform_driver platform_driver = { | 162 | static struct platform_driver platform_driver = { |
154 | .driver = { | 163 | .driver = { |
155 | .name = EEEPC_HOTK_FILE, | 164 | .name = EEEPC_HOTK_FILE, |
156 | .owner = THIS_MODULE, | 165 | .owner = THIS_MODULE, |
166 | .pm = &eeepc_pm_ops, | ||
157 | } | 167 | } |
158 | }; | 168 | }; |
159 | 169 | ||
@@ -192,7 +202,6 @@ static struct key_entry eeepc_keymap[] = { | |||
192 | */ | 202 | */ |
193 | static int eeepc_hotk_add(struct acpi_device *device); | 203 | static int eeepc_hotk_add(struct acpi_device *device); |
194 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | 204 | static int eeepc_hotk_remove(struct acpi_device *device, int type); |
195 | static int eeepc_hotk_resume(struct acpi_device *device); | ||
196 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event); | 205 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event); |
197 | 206 | ||
198 | static const struct acpi_device_id eeepc_device_ids[] = { | 207 | static const struct acpi_device_id eeepc_device_ids[] = { |
@@ -209,7 +218,6 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
209 | .ops = { | 218 | .ops = { |
210 | .add = eeepc_hotk_add, | 219 | .add = eeepc_hotk_add, |
211 | .remove = eeepc_hotk_remove, | 220 | .remove = eeepc_hotk_remove, |
212 | .resume = eeepc_hotk_resume, | ||
213 | .notify = eeepc_hotk_notify, | 221 | .notify = eeepc_hotk_notify, |
214 | }, | 222 | }, |
215 | }; | 223 | }; |
@@ -579,7 +587,6 @@ static void cmsg_quirks(void) | |||
579 | 587 | ||
580 | static int eeepc_hotk_check(void) | 588 | static int eeepc_hotk_check(void) |
581 | { | 589 | { |
582 | const struct key_entry *key; | ||
583 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 590 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
584 | int result; | 591 | int result; |
585 | 592 | ||
@@ -604,31 +611,6 @@ static int eeepc_hotk_check(void) | |||
604 | pr_info("Get control methods supported: 0x%x\n", | 611 | pr_info("Get control methods supported: 0x%x\n", |
605 | ehotk->cm_supported); | 612 | ehotk->cm_supported); |
606 | } | 613 | } |
607 | ehotk->inputdev = input_allocate_device(); | ||
608 | if (!ehotk->inputdev) { | ||
609 | pr_info("Unable to allocate input device\n"); | ||
610 | return 0; | ||
611 | } | ||
612 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | ||
613 | ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; | ||
614 | ehotk->inputdev->id.bustype = BUS_HOST; | ||
615 | ehotk->inputdev->getkeycode = eeepc_getkeycode; | ||
616 | ehotk->inputdev->setkeycode = eeepc_setkeycode; | ||
617 | |||
618 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
619 | switch (key->type) { | ||
620 | case KE_KEY: | ||
621 | set_bit(EV_KEY, ehotk->inputdev->evbit); | ||
622 | set_bit(key->keycode, ehotk->inputdev->keybit); | ||
623 | break; | ||
624 | } | ||
625 | } | ||
626 | result = input_register_device(ehotk->inputdev); | ||
627 | if (result) { | ||
628 | pr_info("Unable to register input device\n"); | ||
629 | input_free_device(ehotk->inputdev); | ||
630 | return 0; | ||
631 | } | ||
632 | } else { | 614 | } else { |
633 | pr_err("Hotkey device not present, aborting\n"); | 615 | pr_err("Hotkey device not present, aborting\n"); |
634 | return -EINVAL; | 616 | return -EINVAL; |
@@ -661,40 +643,48 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | |||
661 | return 0; | 643 | return 0; |
662 | } | 644 | } |
663 | 645 | ||
664 | static void eeepc_hotplug_work(struct work_struct *work) | 646 | static void eeepc_rfkill_hotplug(void) |
665 | { | 647 | { |
666 | struct pci_dev *dev; | 648 | struct pci_dev *dev; |
667 | struct pci_bus *bus = pci_find_bus(0, 1); | 649 | struct pci_bus *bus; |
668 | bool blocked; | 650 | bool blocked = eeepc_wlan_rfkill_blocked(); |
669 | 651 | ||
670 | if (!bus) { | 652 | if (ehotk->wlan_rfkill) |
671 | pr_warning("Unable to find PCI bus 1?\n"); | 653 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
672 | return; | ||
673 | } | ||
674 | 654 | ||
675 | blocked = eeepc_wlan_rfkill_blocked(); | 655 | mutex_lock(&ehotk->hotplug_lock); |
676 | if (!blocked) { | 656 | |
677 | dev = pci_get_slot(bus, 0); | 657 | if (ehotk->hotplug_slot) { |
678 | if (dev) { | 658 | bus = pci_find_bus(0, 1); |
679 | /* Device already present */ | 659 | if (!bus) { |
680 | pci_dev_put(dev); | 660 | pr_warning("Unable to find PCI bus 1?\n"); |
681 | return; | 661 | goto out_unlock; |
682 | } | ||
683 | dev = pci_scan_single_device(bus, 0); | ||
684 | if (dev) { | ||
685 | pci_bus_assign_resources(bus); | ||
686 | if (pci_bus_add_device(dev)) | ||
687 | pr_err("Unable to hotplug wifi\n"); | ||
688 | } | 662 | } |
689 | } else { | 663 | |
690 | dev = pci_get_slot(bus, 0); | 664 | if (!blocked) { |
691 | if (dev) { | 665 | dev = pci_get_slot(bus, 0); |
692 | pci_remove_bus_device(dev); | 666 | if (dev) { |
693 | pci_dev_put(dev); | 667 | /* Device already present */ |
668 | pci_dev_put(dev); | ||
669 | goto out_unlock; | ||
670 | } | ||
671 | dev = pci_scan_single_device(bus, 0); | ||
672 | if (dev) { | ||
673 | pci_bus_assign_resources(bus); | ||
674 | if (pci_bus_add_device(dev)) | ||
675 | pr_err("Unable to hotplug wifi\n"); | ||
676 | } | ||
677 | } else { | ||
678 | dev = pci_get_slot(bus, 0); | ||
679 | if (dev) { | ||
680 | pci_remove_bus_device(dev); | ||
681 | pci_dev_put(dev); | ||
682 | } | ||
694 | } | 683 | } |
695 | } | 684 | } |
696 | 685 | ||
697 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); | 686 | out_unlock: |
687 | mutex_unlock(&ehotk->hotplug_lock); | ||
698 | } | 688 | } |
699 | 689 | ||
700 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 690 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
@@ -702,7 +692,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
702 | if (event != ACPI_NOTIFY_BUS_CHECK) | 692 | if (event != ACPI_NOTIFY_BUS_CHECK) |
703 | return; | 693 | return; |
704 | 694 | ||
705 | schedule_work(&ehotk->hotplug_work); | 695 | eeepc_rfkill_hotplug(); |
706 | } | 696 | } |
707 | 697 | ||
708 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) | 698 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) |
@@ -839,66 +829,38 @@ error_slot: | |||
839 | return ret; | 829 | return ret; |
840 | } | 830 | } |
841 | 831 | ||
842 | static int eeepc_hotk_add(struct acpi_device *device) | 832 | static int eeepc_hotk_thaw(struct device *device) |
843 | { | ||
844 | int result; | ||
845 | |||
846 | if (!device) | ||
847 | return -EINVAL; | ||
848 | pr_notice(EEEPC_HOTK_NAME "\n"); | ||
849 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | ||
850 | if (!ehotk) | ||
851 | return -ENOMEM; | ||
852 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; | ||
853 | ehotk->handle = device->handle; | ||
854 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | ||
855 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
856 | device->driver_data = ehotk; | ||
857 | ehotk->device = device; | ||
858 | result = eeepc_hotk_check(); | ||
859 | if (result) | ||
860 | goto ehotk_fail; | ||
861 | |||
862 | return 0; | ||
863 | |||
864 | ehotk_fail: | ||
865 | kfree(ehotk); | ||
866 | ehotk = NULL; | ||
867 | |||
868 | return result; | ||
869 | } | ||
870 | |||
871 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
872 | { | ||
873 | if (!device || !acpi_driver_data(device)) | ||
874 | return -EINVAL; | ||
875 | |||
876 | kfree(ehotk); | ||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | static int eeepc_hotk_resume(struct acpi_device *device) | ||
881 | { | 833 | { |
882 | if (ehotk->wlan_rfkill) { | 834 | if (ehotk->wlan_rfkill) { |
883 | bool wlan; | 835 | bool wlan; |
884 | 836 | ||
885 | /* Workaround - it seems that _PTS disables the wireless | 837 | /* |
886 | without notification or changing the value read by WLAN. | 838 | * Work around bios bug - acpi _PTS turns off the wireless led |
887 | Normally this is fine because the correct value is restored | 839 | * during suspend. Normally it restores it on resume, but |
888 | from the non-volatile storage on resume, but we need to do | 840 | * we should kick it ourselves in case hibernation is aborted. |
889 | it ourself if case suspend is aborted, or we lose wireless. | ||
890 | */ | 841 | */ |
891 | wlan = get_acpi(CM_ASL_WLAN); | 842 | wlan = get_acpi(CM_ASL_WLAN); |
892 | set_acpi(CM_ASL_WLAN, wlan); | 843 | set_acpi(CM_ASL_WLAN, wlan); |
844 | } | ||
893 | 845 | ||
894 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); | 846 | return 0; |
847 | } | ||
895 | 848 | ||
896 | schedule_work(&ehotk->hotplug_work); | 849 | static int eeepc_hotk_restore(struct device *device) |
897 | } | 850 | { |
851 | /* Refresh both wlan rfkill state and pci hotplug */ | ||
852 | if (ehotk->wlan_rfkill) | ||
853 | eeepc_rfkill_hotplug(); | ||
898 | 854 | ||
899 | if (ehotk->bluetooth_rfkill) | 855 | if (ehotk->bluetooth_rfkill) |
900 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, | 856 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
901 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 857 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
858 | if (ehotk->wwan3g_rfkill) | ||
859 | rfkill_set_sw_state(ehotk->wwan3g_rfkill, | ||
860 | get_acpi(CM_ASL_3G) != 1); | ||
861 | if (ehotk->wimax_rfkill) | ||
862 | rfkill_set_sw_state(ehotk->wimax_rfkill, | ||
863 | get_acpi(CM_ASL_WIMAX) != 1); | ||
902 | 864 | ||
903 | return 0; | 865 | return 0; |
904 | } | 866 | } |
@@ -1019,16 +981,37 @@ static void eeepc_backlight_exit(void) | |||
1019 | 981 | ||
1020 | static void eeepc_rfkill_exit(void) | 982 | static void eeepc_rfkill_exit(void) |
1021 | { | 983 | { |
984 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5"); | ||
1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | 985 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
1023 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | 986 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
1024 | if (ehotk->wlan_rfkill) | 987 | if (ehotk->wlan_rfkill) { |
1025 | rfkill_unregister(ehotk->wlan_rfkill); | 988 | rfkill_unregister(ehotk->wlan_rfkill); |
1026 | if (ehotk->bluetooth_rfkill) | 989 | rfkill_destroy(ehotk->wlan_rfkill); |
1027 | rfkill_unregister(ehotk->bluetooth_rfkill); | 990 | ehotk->wlan_rfkill = NULL; |
1028 | if (ehotk->wwan3g_rfkill) | 991 | } |
1029 | rfkill_unregister(ehotk->wwan3g_rfkill); | 992 | /* |
993 | * Refresh pci hotplug in case the rfkill state was changed after | ||
994 | * eeepc_unregister_rfkill_notifier() | ||
995 | */ | ||
996 | eeepc_rfkill_hotplug(); | ||
1030 | if (ehotk->hotplug_slot) | 997 | if (ehotk->hotplug_slot) |
1031 | pci_hp_deregister(ehotk->hotplug_slot); | 998 | pci_hp_deregister(ehotk->hotplug_slot); |
999 | |||
1000 | if (ehotk->bluetooth_rfkill) { | ||
1001 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
1002 | rfkill_destroy(ehotk->bluetooth_rfkill); | ||
1003 | ehotk->bluetooth_rfkill = NULL; | ||
1004 | } | ||
1005 | if (ehotk->wwan3g_rfkill) { | ||
1006 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
1007 | rfkill_destroy(ehotk->wwan3g_rfkill); | ||
1008 | ehotk->wwan3g_rfkill = NULL; | ||
1009 | } | ||
1010 | if (ehotk->wimax_rfkill) { | ||
1011 | rfkill_unregister(ehotk->wimax_rfkill); | ||
1012 | rfkill_destroy(ehotk->wimax_rfkill); | ||
1013 | ehotk->wimax_rfkill = NULL; | ||
1014 | } | ||
1032 | } | 1015 | } |
1033 | 1016 | ||
1034 | static void eeepc_input_exit(void) | 1017 | static void eeepc_input_exit(void) |
@@ -1050,19 +1033,6 @@ static void eeepc_hwmon_exit(void) | |||
1050 | eeepc_hwmon_device = NULL; | 1033 | eeepc_hwmon_device = NULL; |
1051 | } | 1034 | } |
1052 | 1035 | ||
1053 | static void __exit eeepc_laptop_exit(void) | ||
1054 | { | ||
1055 | eeepc_backlight_exit(); | ||
1056 | eeepc_rfkill_exit(); | ||
1057 | eeepc_input_exit(); | ||
1058 | eeepc_hwmon_exit(); | ||
1059 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1060 | sysfs_remove_group(&platform_device->dev.kobj, | ||
1061 | &platform_attribute_group); | ||
1062 | platform_device_unregister(platform_device); | ||
1063 | platform_driver_unregister(&platform_driver); | ||
1064 | } | ||
1065 | |||
1066 | static int eeepc_new_rfkill(struct rfkill **rfkill, | 1036 | static int eeepc_new_rfkill(struct rfkill **rfkill, |
1067 | const char *name, struct device *dev, | 1037 | const char *name, struct device *dev, |
1068 | enum rfkill_type type, int cm) | 1038 | enum rfkill_type type, int cm) |
@@ -1094,10 +1064,7 @@ static int eeepc_rfkill_init(struct device *dev) | |||
1094 | { | 1064 | { |
1095 | int result = 0; | 1065 | int result = 0; |
1096 | 1066 | ||
1097 | INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work); | 1067 | mutex_init(&ehotk->hotplug_lock); |
1098 | |||
1099 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
1100 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
1101 | 1068 | ||
1102 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | 1069 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, |
1103 | "eeepc-wlan", dev, | 1070 | "eeepc-wlan", dev, |
@@ -1120,6 +1087,13 @@ static int eeepc_rfkill_init(struct device *dev) | |||
1120 | if (result && result != -ENODEV) | 1087 | if (result && result != -ENODEV) |
1121 | goto exit; | 1088 | goto exit; |
1122 | 1089 | ||
1090 | result = eeepc_new_rfkill(&ehotk->wimax_rfkill, | ||
1091 | "eeepc-wimax", dev, | ||
1092 | RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); | ||
1093 | |||
1094 | if (result && result != -ENODEV) | ||
1095 | goto exit; | ||
1096 | |||
1123 | result = eeepc_setup_pci_hotplug(); | 1097 | result = eeepc_setup_pci_hotplug(); |
1124 | /* | 1098 | /* |
1125 | * If we get -EBUSY then something else is handling the PCI hotplug - | 1099 | * If we get -EBUSY then something else is handling the PCI hotplug - |
@@ -1128,6 +1102,15 @@ static int eeepc_rfkill_init(struct device *dev) | |||
1128 | if (result == -EBUSY) | 1102 | if (result == -EBUSY) |
1129 | result = 0; | 1103 | result = 0; |
1130 | 1104 | ||
1105 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); | ||
1106 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
1107 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
1108 | /* | ||
1109 | * Refresh pci hotplug in case the rfkill state was changed during | ||
1110 | * setup. | ||
1111 | */ | ||
1112 | eeepc_rfkill_hotplug(); | ||
1113 | |||
1131 | exit: | 1114 | exit: |
1132 | if (result && result != -ENODEV) | 1115 | if (result && result != -ENODEV) |
1133 | eeepc_rfkill_exit(); | 1116 | eeepc_rfkill_exit(); |
@@ -1172,21 +1155,61 @@ static int eeepc_hwmon_init(struct device *dev) | |||
1172 | return result; | 1155 | return result; |
1173 | } | 1156 | } |
1174 | 1157 | ||
1175 | static int __init eeepc_laptop_init(void) | 1158 | static int eeepc_input_init(struct device *dev) |
1176 | { | 1159 | { |
1177 | struct device *dev; | 1160 | const struct key_entry *key; |
1178 | int result; | 1161 | int result; |
1179 | 1162 | ||
1180 | if (acpi_disabled) | 1163 | ehotk->inputdev = input_allocate_device(); |
1181 | return -ENODEV; | 1164 | if (!ehotk->inputdev) { |
1182 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | 1165 | pr_info("Unable to allocate input device\n"); |
1183 | if (result < 0) | 1166 | return -ENOMEM; |
1167 | } | ||
1168 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | ||
1169 | ehotk->inputdev->dev.parent = dev; | ||
1170 | ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; | ||
1171 | ehotk->inputdev->id.bustype = BUS_HOST; | ||
1172 | ehotk->inputdev->getkeycode = eeepc_getkeycode; | ||
1173 | ehotk->inputdev->setkeycode = eeepc_setkeycode; | ||
1174 | |||
1175 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
1176 | switch (key->type) { | ||
1177 | case KE_KEY: | ||
1178 | set_bit(EV_KEY, ehotk->inputdev->evbit); | ||
1179 | set_bit(key->keycode, ehotk->inputdev->keybit); | ||
1180 | break; | ||
1181 | } | ||
1182 | } | ||
1183 | result = input_register_device(ehotk->inputdev); | ||
1184 | if (result) { | ||
1185 | pr_info("Unable to register input device\n"); | ||
1186 | input_free_device(ehotk->inputdev); | ||
1184 | return result; | 1187 | return result; |
1185 | if (!ehotk) { | ||
1186 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1187 | return -ENODEV; | ||
1188 | } | 1188 | } |
1189 | return 0; | ||
1190 | } | ||
1191 | |||
1192 | static int eeepc_hotk_add(struct acpi_device *device) | ||
1193 | { | ||
1194 | struct device *dev; | ||
1195 | int result; | ||
1189 | 1196 | ||
1197 | if (!device) | ||
1198 | return -EINVAL; | ||
1199 | pr_notice(EEEPC_HOTK_NAME "\n"); | ||
1200 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | ||
1201 | if (!ehotk) | ||
1202 | return -ENOMEM; | ||
1203 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; | ||
1204 | ehotk->handle = device->handle; | ||
1205 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | ||
1206 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
1207 | device->driver_data = ehotk; | ||
1208 | ehotk->device = device; | ||
1209 | |||
1210 | result = eeepc_hotk_check(); | ||
1211 | if (result) | ||
1212 | goto fail_platform_driver; | ||
1190 | eeepc_enable_camera(); | 1213 | eeepc_enable_camera(); |
1191 | 1214 | ||
1192 | /* Register platform stuff */ | 1215 | /* Register platform stuff */ |
@@ -1216,6 +1239,10 @@ static int __init eeepc_laptop_init(void) | |||
1216 | pr_info("Backlight controlled by ACPI video " | 1239 | pr_info("Backlight controlled by ACPI video " |
1217 | "driver\n"); | 1240 | "driver\n"); |
1218 | 1241 | ||
1242 | result = eeepc_input_init(dev); | ||
1243 | if (result) | ||
1244 | goto fail_input; | ||
1245 | |||
1219 | result = eeepc_hwmon_init(dev); | 1246 | result = eeepc_hwmon_init(dev); |
1220 | if (result) | 1247 | if (result) |
1221 | goto fail_hwmon; | 1248 | goto fail_hwmon; |
@@ -1225,9 +1252,12 @@ static int __init eeepc_laptop_init(void) | |||
1225 | goto fail_rfkill; | 1252 | goto fail_rfkill; |
1226 | 1253 | ||
1227 | return 0; | 1254 | return 0; |
1255 | |||
1228 | fail_rfkill: | 1256 | fail_rfkill: |
1229 | eeepc_hwmon_exit(); | 1257 | eeepc_hwmon_exit(); |
1230 | fail_hwmon: | 1258 | fail_hwmon: |
1259 | eeepc_input_exit(); | ||
1260 | fail_input: | ||
1231 | eeepc_backlight_exit(); | 1261 | eeepc_backlight_exit(); |
1232 | fail_backlight: | 1262 | fail_backlight: |
1233 | sysfs_remove_group(&platform_device->dev.kobj, | 1263 | sysfs_remove_group(&platform_device->dev.kobj, |
@@ -1239,9 +1269,49 @@ fail_platform_device2: | |||
1239 | fail_platform_device1: | 1269 | fail_platform_device1: |
1240 | platform_driver_unregister(&platform_driver); | 1270 | platform_driver_unregister(&platform_driver); |
1241 | fail_platform_driver: | 1271 | fail_platform_driver: |
1242 | eeepc_input_exit(); | 1272 | kfree(ehotk); |
1273 | |||
1243 | return result; | 1274 | return result; |
1244 | } | 1275 | } |
1245 | 1276 | ||
1277 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
1278 | { | ||
1279 | if (!device || !acpi_driver_data(device)) | ||
1280 | return -EINVAL; | ||
1281 | |||
1282 | eeepc_backlight_exit(); | ||
1283 | eeepc_rfkill_exit(); | ||
1284 | eeepc_input_exit(); | ||
1285 | eeepc_hwmon_exit(); | ||
1286 | sysfs_remove_group(&platform_device->dev.kobj, | ||
1287 | &platform_attribute_group); | ||
1288 | platform_device_unregister(platform_device); | ||
1289 | platform_driver_unregister(&platform_driver); | ||
1290 | |||
1291 | kfree(ehotk); | ||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | static int __init eeepc_laptop_init(void) | ||
1296 | { | ||
1297 | int result; | ||
1298 | |||
1299 | if (acpi_disabled) | ||
1300 | return -ENODEV; | ||
1301 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | ||
1302 | if (result < 0) | ||
1303 | return result; | ||
1304 | if (!ehotk) { | ||
1305 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1306 | return -ENODEV; | ||
1307 | } | ||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1311 | static void __exit eeepc_laptop_exit(void) | ||
1312 | { | ||
1313 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1314 | } | ||
1315 | |||
1246 | module_init(eeepc_laptop_init); | 1316 | module_init(eeepc_laptop_init); |
1247 | module_exit(eeepc_laptop_exit); | 1317 | module_exit(eeepc_laptop_exit); |