diff options
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 355 |
1 files changed, 242 insertions, 113 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 4207b26ff990..222ffb892f22 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -31,6 +33,7 @@ | |||
31 | #include <linux/input.h> | 33 | #include <linux/input.h> |
32 | #include <linux/rfkill.h> | 34 | #include <linux/rfkill.h> |
33 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | ||
34 | 37 | ||
35 | #define EEEPC_LAPTOP_VERSION "0.1" | 38 | #define EEEPC_LAPTOP_VERSION "0.1" |
36 | 39 | ||
@@ -40,11 +43,6 @@ | |||
40 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" | 43 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" |
41 | #define EEEPC_HOTK_HID "ASUS010" | 44 | #define EEEPC_HOTK_HID "ASUS010" |
42 | 45 | ||
43 | #define EEEPC_LOG EEEPC_HOTK_FILE ": " | ||
44 | #define EEEPC_ERR KERN_ERR EEEPC_LOG | ||
45 | #define EEEPC_WARNING KERN_WARNING EEEPC_LOG | ||
46 | #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG | ||
47 | #define EEEPC_INFO KERN_INFO EEEPC_LOG | ||
48 | 46 | ||
49 | /* | 47 | /* |
50 | * Definitions for Asus EeePC | 48 | * Definitions for Asus EeePC |
@@ -141,8 +139,11 @@ struct eeepc_hotk { | |||
141 | u16 event_count[128]; /* count for each event */ | 139 | u16 event_count[128]; /* count for each event */ |
142 | struct input_dev *inputdev; | 140 | struct input_dev *inputdev; |
143 | u16 *keycode_map; | 141 | u16 *keycode_map; |
144 | struct rfkill *eeepc_wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
145 | struct rfkill *eeepc_bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
144 | struct rfkill *wwan3g_rfkill; | ||
145 | struct hotplug_slot *hotplug_slot; | ||
146 | struct work_struct hotplug_work; | ||
146 | }; | 147 | }; |
147 | 148 | ||
148 | /* The actual device the driver binds to */ | 149 | /* The actual device the driver binds to */ |
@@ -213,6 +214,15 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
213 | }, | 214 | }, |
214 | }; | 215 | }; |
215 | 216 | ||
217 | /* PCI hotplug ops */ | ||
218 | static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); | ||
219 | |||
220 | static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { | ||
221 | .owner = THIS_MODULE, | ||
222 | .get_adapter_status = eeepc_get_adapter_status, | ||
223 | .get_power_status = eeepc_get_adapter_status, | ||
224 | }; | ||
225 | |||
216 | /* The backlight device /sys/class/backlight */ | 226 | /* The backlight device /sys/class/backlight */ |
217 | static struct backlight_device *eeepc_backlight_device; | 227 | static struct backlight_device *eeepc_backlight_device; |
218 | 228 | ||
@@ -274,20 +284,20 @@ static int set_acpi(int cm, int value) | |||
274 | if (method == NULL) | 284 | if (method == NULL) |
275 | return -ENODEV; | 285 | return -ENODEV; |
276 | if (write_acpi_int(ehotk->handle, method, value, NULL)) | 286 | if (write_acpi_int(ehotk->handle, method, value, NULL)) |
277 | printk(EEEPC_WARNING "Error writing %s\n", method); | 287 | pr_warning("Error writing %s\n", method); |
278 | } | 288 | } |
279 | return 0; | 289 | return 0; |
280 | } | 290 | } |
281 | 291 | ||
282 | static int get_acpi(int cm) | 292 | static int get_acpi(int cm) |
283 | { | 293 | { |
284 | int value = -1; | 294 | int value = -ENODEV; |
285 | if ((ehotk->cm_supported & (0x1 << cm))) { | 295 | if ((ehotk->cm_supported & (0x1 << cm))) { |
286 | const char *method = cm_getv[cm]; | 296 | const char *method = cm_getv[cm]; |
287 | if (method == NULL) | 297 | if (method == NULL) |
288 | return -ENODEV; | 298 | return -ENODEV; |
289 | if (read_acpi_int(ehotk->handle, method, &value)) | 299 | if (read_acpi_int(ehotk->handle, method, &value)) |
290 | printk(EEEPC_WARNING "Error reading %s\n", method); | 300 | pr_warning("Error reading %s\n", method); |
291 | } | 301 | } |
292 | return value; | 302 | return value; |
293 | } | 303 | } |
@@ -359,13 +369,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) | |||
359 | 369 | ||
360 | rv = parse_arg(buf, count, &value); | 370 | rv = parse_arg(buf, count, &value); |
361 | if (rv > 0) | 371 | if (rv > 0) |
362 | set_acpi(cm, value); | 372 | value = set_acpi(cm, value); |
373 | if (value < 0) | ||
374 | return value; | ||
363 | return rv; | 375 | return rv; |
364 | } | 376 | } |
365 | 377 | ||
366 | static ssize_t show_sys_acpi(int cm, char *buf) | 378 | static ssize_t show_sys_acpi(int cm, char *buf) |
367 | { | 379 | { |
368 | return sprintf(buf, "%d\n", get_acpi(cm)); | 380 | int value = get_acpi(cm); |
381 | |||
382 | if (value < 0) | ||
383 | return value; | ||
384 | return sprintf(buf, "%d\n", value); | ||
369 | } | 385 | } |
370 | 386 | ||
371 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ | 387 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ |
@@ -539,6 +555,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
539 | return -EINVAL; | 555 | return -EINVAL; |
540 | } | 556 | } |
541 | 557 | ||
558 | static void cmsg_quirk(int cm, const char *name) | ||
559 | { | ||
560 | int dummy; | ||
561 | |||
562 | /* Some BIOSes do not report cm although it is avaliable. | ||
563 | Check if cm_getv[cm] works and, if yes, assume cm should be set. */ | ||
564 | if (!(ehotk->cm_supported & (1 << cm)) | ||
565 | && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) { | ||
566 | pr_info("%s (%x) not reported by BIOS," | ||
567 | " enabling anyway\n", name, 1 << cm); | ||
568 | ehotk->cm_supported |= 1 << cm; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | static void cmsg_quirks(void) | ||
573 | { | ||
574 | cmsg_quirk(CM_ASL_LID, "LID"); | ||
575 | cmsg_quirk(CM_ASL_TYPE, "TYPE"); | ||
576 | cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER"); | ||
577 | cmsg_quirk(CM_ASL_TPD, "TPD"); | ||
578 | } | ||
579 | |||
542 | static int eeepc_hotk_check(void) | 580 | static int eeepc_hotk_check(void) |
543 | { | 581 | { |
544 | const struct key_entry *key; | 582 | const struct key_entry *key; |
@@ -551,26 +589,24 @@ static int eeepc_hotk_check(void) | |||
551 | if (ehotk->device->status.present) { | 589 | if (ehotk->device->status.present) { |
552 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, | 590 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, |
553 | &buffer)) { | 591 | &buffer)) { |
554 | printk(EEEPC_ERR "Hotkey initialization failed\n"); | 592 | pr_err("Hotkey initialization failed\n"); |
555 | return -ENODEV; | 593 | return -ENODEV; |
556 | } else { | 594 | } else { |
557 | printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", | 595 | pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag); |
558 | ehotk->init_flag); | ||
559 | } | 596 | } |
560 | /* get control methods supported */ | 597 | /* get control methods supported */ |
561 | if (read_acpi_int(ehotk->handle, "CMSG" | 598 | if (read_acpi_int(ehotk->handle, "CMSG" |
562 | , &ehotk->cm_supported)) { | 599 | , &ehotk->cm_supported)) { |
563 | printk(EEEPC_ERR | 600 | pr_err("Get control methods supported failed\n"); |
564 | "Get control methods supported failed\n"); | ||
565 | return -ENODEV; | 601 | return -ENODEV; |
566 | } else { | 602 | } else { |
567 | printk(EEEPC_INFO | 603 | cmsg_quirks(); |
568 | "Get control methods supported: 0x%x\n", | 604 | pr_info("Get control methods supported: 0x%x\n", |
569 | ehotk->cm_supported); | 605 | ehotk->cm_supported); |
570 | } | 606 | } |
571 | ehotk->inputdev = input_allocate_device(); | 607 | ehotk->inputdev = input_allocate_device(); |
572 | if (!ehotk->inputdev) { | 608 | if (!ehotk->inputdev) { |
573 | printk(EEEPC_INFO "Unable to allocate input device\n"); | 609 | pr_info("Unable to allocate input device\n"); |
574 | return 0; | 610 | return 0; |
575 | } | 611 | } |
576 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | 612 | ehotk->inputdev->name = "Asus EeePC extra buttons"; |
@@ -589,12 +625,12 @@ static int eeepc_hotk_check(void) | |||
589 | } | 625 | } |
590 | result = input_register_device(ehotk->inputdev); | 626 | result = input_register_device(ehotk->inputdev); |
591 | if (result) { | 627 | if (result) { |
592 | printk(EEEPC_INFO "Unable to register input device\n"); | 628 | pr_info("Unable to register input device\n"); |
593 | input_free_device(ehotk->inputdev); | 629 | input_free_device(ehotk->inputdev); |
594 | return 0; | 630 | return 0; |
595 | } | 631 | } |
596 | } else { | 632 | } else { |
597 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | 633 | pr_err("Hotkey device not present, aborting\n"); |
598 | return -EINVAL; | 634 | return -EINVAL; |
599 | } | 635 | } |
600 | return 0; | 636 | return 0; |
@@ -612,14 +648,27 @@ static int notify_brn(void) | |||
612 | return -1; | 648 | return -1; |
613 | } | 649 | } |
614 | 650 | ||
615 | static void eeepc_rfkill_hotplug(void) | 651 | static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, |
652 | u8 *value) | ||
653 | { | ||
654 | int val = get_acpi(CM_ASL_WLAN); | ||
655 | |||
656 | if (val == 1 || val == 0) | ||
657 | *value = val; | ||
658 | else | ||
659 | return -EINVAL; | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static void eeepc_hotplug_work(struct work_struct *work) | ||
616 | { | 665 | { |
617 | struct pci_dev *dev; | 666 | struct pci_dev *dev; |
618 | struct pci_bus *bus = pci_find_bus(0, 1); | 667 | struct pci_bus *bus = pci_find_bus(0, 1); |
619 | bool blocked; | 668 | bool blocked; |
620 | 669 | ||
621 | if (!bus) { | 670 | if (!bus) { |
622 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | 671 | pr_warning("Unable to find PCI bus 1?\n"); |
623 | return; | 672 | return; |
624 | } | 673 | } |
625 | 674 | ||
@@ -635,7 +684,7 @@ static void eeepc_rfkill_hotplug(void) | |||
635 | if (dev) { | 684 | if (dev) { |
636 | pci_bus_assign_resources(bus); | 685 | pci_bus_assign_resources(bus); |
637 | if (pci_bus_add_device(dev)) | 686 | if (pci_bus_add_device(dev)) |
638 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | 687 | pr_err("Unable to hotplug wifi\n"); |
639 | } | 688 | } |
640 | } else { | 689 | } else { |
641 | dev = pci_get_slot(bus, 0); | 690 | dev = pci_get_slot(bus, 0); |
@@ -645,7 +694,7 @@ static void eeepc_rfkill_hotplug(void) | |||
645 | } | 694 | } |
646 | } | 695 | } |
647 | 696 | ||
648 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); | 697 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
649 | } | 698 | } |
650 | 699 | ||
651 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 700 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
@@ -653,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | |||
653 | if (event != ACPI_NOTIFY_BUS_CHECK) | 702 | if (event != ACPI_NOTIFY_BUS_CHECK) |
654 | return; | 703 | return; |
655 | 704 | ||
656 | eeepc_rfkill_hotplug(); | 705 | schedule_work(&ehotk->hotplug_work); |
657 | } | 706 | } |
658 | 707 | ||
659 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) | 708 | static void eeepc_hotk_notify(struct acpi_device *device, u32 event) |
@@ -718,8 +767,7 @@ static int eeepc_register_rfkill_notifier(char *node) | |||
718 | eeepc_rfkill_notify, | 767 | eeepc_rfkill_notify, |
719 | NULL); | 768 | NULL); |
720 | if (ACPI_FAILURE(status)) | 769 | if (ACPI_FAILURE(status)) |
721 | printk(EEEPC_WARNING | 770 | pr_warning("Failed to register notify on %s\n", node); |
722 | "Failed to register notify on %s\n", node); | ||
723 | } else | 771 | } else |
724 | return -ENODEV; | 772 | return -ENODEV; |
725 | 773 | ||
@@ -738,19 +786,66 @@ static void eeepc_unregister_rfkill_notifier(char *node) | |||
738 | ACPI_SYSTEM_NOTIFY, | 786 | ACPI_SYSTEM_NOTIFY, |
739 | eeepc_rfkill_notify); | 787 | eeepc_rfkill_notify); |
740 | if (ACPI_FAILURE(status)) | 788 | if (ACPI_FAILURE(status)) |
741 | printk(EEEPC_ERR | 789 | pr_err("Error removing rfkill notify handler %s\n", |
742 | "Error removing rfkill notify handler %s\n", | ||
743 | node); | 790 | node); |
744 | } | 791 | } |
745 | } | 792 | } |
746 | 793 | ||
794 | static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) | ||
795 | { | ||
796 | kfree(hotplug_slot->info); | ||
797 | kfree(hotplug_slot); | ||
798 | } | ||
799 | |||
800 | static int eeepc_setup_pci_hotplug(void) | ||
801 | { | ||
802 | int ret = -ENOMEM; | ||
803 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
804 | |||
805 | if (!bus) { | ||
806 | pr_err("Unable to find wifi PCI bus\n"); | ||
807 | return -ENODEV; | ||
808 | } | ||
809 | |||
810 | ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | ||
811 | if (!ehotk->hotplug_slot) | ||
812 | goto error_slot; | ||
813 | |||
814 | ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), | ||
815 | GFP_KERNEL); | ||
816 | if (!ehotk->hotplug_slot->info) | ||
817 | goto error_info; | ||
818 | |||
819 | ehotk->hotplug_slot->private = ehotk; | ||
820 | ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; | ||
821 | ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; | ||
822 | eeepc_get_adapter_status(ehotk->hotplug_slot, | ||
823 | &ehotk->hotplug_slot->info->adapter_status); | ||
824 | |||
825 | ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); | ||
826 | if (ret) { | ||
827 | pr_err("Unable to register hotplug slot - %d\n", ret); | ||
828 | goto error_register; | ||
829 | } | ||
830 | |||
831 | return 0; | ||
832 | |||
833 | error_register: | ||
834 | kfree(ehotk->hotplug_slot->info); | ||
835 | error_info: | ||
836 | kfree(ehotk->hotplug_slot); | ||
837 | ehotk->hotplug_slot = NULL; | ||
838 | error_slot: | ||
839 | return ret; | ||
840 | } | ||
841 | |||
747 | static int eeepc_hotk_add(struct acpi_device *device) | 842 | static int eeepc_hotk_add(struct acpi_device *device) |
748 | { | 843 | { |
749 | int result; | 844 | int result; |
750 | 845 | ||
751 | if (!device) | 846 | if (!device) |
752 | return -EINVAL; | 847 | return -EINVAL; |
753 | printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); | 848 | pr_notice(EEEPC_HOTK_NAME "\n"); |
754 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | 849 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); |
755 | if (!ehotk) | 850 | if (!ehotk) |
756 | return -ENOMEM; | 851 | return -ENOMEM; |
@@ -764,53 +859,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
764 | if (result) | 859 | if (result) |
765 | goto ehotk_fail; | 860 | goto ehotk_fail; |
766 | 861 | ||
767 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
768 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
769 | |||
770 | if (get_acpi(CM_ASL_WLAN) != -1) { | ||
771 | ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", | ||
772 | &device->dev, | ||
773 | RFKILL_TYPE_WLAN, | ||
774 | &eeepc_rfkill_ops, | ||
775 | (void *)CM_ASL_WLAN); | ||
776 | |||
777 | if (!ehotk->eeepc_wlan_rfkill) | ||
778 | goto wlan_fail; | ||
779 | |||
780 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, | ||
781 | get_acpi(CM_ASL_WLAN) != 1); | ||
782 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
783 | if (result) | ||
784 | goto wlan_fail; | ||
785 | } | ||
786 | |||
787 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | ||
788 | ehotk->eeepc_bluetooth_rfkill = | ||
789 | rfkill_alloc("eeepc-bluetooth", | ||
790 | &device->dev, | ||
791 | RFKILL_TYPE_BLUETOOTH, | ||
792 | &eeepc_rfkill_ops, | ||
793 | (void *)CM_ASL_BLUETOOTH); | ||
794 | |||
795 | if (!ehotk->eeepc_bluetooth_rfkill) | ||
796 | goto bluetooth_fail; | ||
797 | |||
798 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, | ||
799 | get_acpi(CM_ASL_BLUETOOTH) != 1); | ||
800 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||
801 | if (result) | ||
802 | goto bluetooth_fail; | ||
803 | } | ||
804 | |||
805 | return 0; | 862 | return 0; |
806 | 863 | ||
807 | bluetooth_fail: | ||
808 | rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); | ||
809 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
810 | wlan_fail: | ||
811 | rfkill_destroy(ehotk->eeepc_wlan_rfkill); | ||
812 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
813 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
814 | ehotk_fail: | 864 | ehotk_fail: |
815 | kfree(ehotk); | 865 | kfree(ehotk); |
816 | ehotk = NULL; | 866 | ehotk = NULL; |
@@ -823,16 +873,13 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
823 | if (!device || !acpi_driver_data(device)) | 873 | if (!device || !acpi_driver_data(device)) |
824 | return -EINVAL; | 874 | return -EINVAL; |
825 | 875 | ||
826 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
827 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
828 | |||
829 | kfree(ehotk); | 876 | kfree(ehotk); |
830 | return 0; | 877 | return 0; |
831 | } | 878 | } |
832 | 879 | ||
833 | static int eeepc_hotk_resume(struct acpi_device *device) | 880 | static int eeepc_hotk_resume(struct acpi_device *device) |
834 | { | 881 | { |
835 | if (ehotk->eeepc_wlan_rfkill) { | 882 | if (ehotk->wlan_rfkill) { |
836 | bool wlan; | 883 | bool wlan; |
837 | 884 | ||
838 | /* Workaround - it seems that _PTS disables the wireless | 885 | /* Workaround - it seems that _PTS disables the wireless |
@@ -844,14 +891,13 @@ static int eeepc_hotk_resume(struct acpi_device *device) | |||
844 | wlan = get_acpi(CM_ASL_WLAN); | 891 | wlan = get_acpi(CM_ASL_WLAN); |
845 | set_acpi(CM_ASL_WLAN, wlan); | 892 | set_acpi(CM_ASL_WLAN, wlan); |
846 | 893 | ||
847 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 894 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); |
848 | wlan != 1); | ||
849 | 895 | ||
850 | eeepc_rfkill_hotplug(); | 896 | schedule_work(&ehotk->hotplug_work); |
851 | } | 897 | } |
852 | 898 | ||
853 | if (ehotk->eeepc_bluetooth_rfkill) | 899 | if (ehotk->bluetooth_rfkill) |
854 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 900 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
855 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 901 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
856 | 902 | ||
857 | return 0; | 903 | return 0; |
@@ -973,10 +1019,16 @@ static void eeepc_backlight_exit(void) | |||
973 | 1019 | ||
974 | static void eeepc_rfkill_exit(void) | 1020 | static void eeepc_rfkill_exit(void) |
975 | { | 1021 | { |
976 | if (ehotk->eeepc_wlan_rfkill) | 1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
977 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 1023 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
978 | if (ehotk->eeepc_bluetooth_rfkill) | 1024 | if (ehotk->wlan_rfkill) |
979 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 1025 | rfkill_unregister(ehotk->wlan_rfkill); |
1026 | if (ehotk->bluetooth_rfkill) | ||
1027 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
1028 | if (ehotk->wwan3g_rfkill) | ||
1029 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
1030 | if (ehotk->hotplug_slot) | ||
1031 | pci_hp_deregister(ehotk->hotplug_slot); | ||
980 | } | 1032 | } |
981 | 1033 | ||
982 | static void eeepc_input_exit(void) | 1034 | static void eeepc_input_exit(void) |
@@ -1011,6 +1063,77 @@ static void __exit eeepc_laptop_exit(void) | |||
1011 | platform_driver_unregister(&platform_driver); | 1063 | platform_driver_unregister(&platform_driver); |
1012 | } | 1064 | } |
1013 | 1065 | ||
1066 | static int eeepc_new_rfkill(struct rfkill **rfkill, | ||
1067 | const char *name, struct device *dev, | ||
1068 | enum rfkill_type type, int cm) | ||
1069 | { | ||
1070 | int result; | ||
1071 | |||
1072 | result = get_acpi(cm); | ||
1073 | if (result < 0) | ||
1074 | return result; | ||
1075 | |||
1076 | *rfkill = rfkill_alloc(name, dev, type, | ||
1077 | &eeepc_rfkill_ops, (void *)(unsigned long)cm); | ||
1078 | |||
1079 | if (!*rfkill) | ||
1080 | return -EINVAL; | ||
1081 | |||
1082 | rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); | ||
1083 | result = rfkill_register(*rfkill); | ||
1084 | if (result) { | ||
1085 | rfkill_destroy(*rfkill); | ||
1086 | *rfkill = NULL; | ||
1087 | return result; | ||
1088 | } | ||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | static int eeepc_rfkill_init(struct device *dev) | ||
1094 | { | ||
1095 | int result = 0; | ||
1096 | |||
1097 | INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work); | ||
1098 | |||
1099 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
1100 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
1101 | |||
1102 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | ||
1103 | "eeepc-wlan", dev, | ||
1104 | RFKILL_TYPE_WLAN, CM_ASL_WLAN); | ||
1105 | |||
1106 | if (result && result != -ENODEV) | ||
1107 | goto exit; | ||
1108 | |||
1109 | result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill, | ||
1110 | "eeepc-bluetooth", dev, | ||
1111 | RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH); | ||
1112 | |||
1113 | if (result && result != -ENODEV) | ||
1114 | goto exit; | ||
1115 | |||
1116 | result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, | ||
1117 | "eeepc-wwan3g", dev, | ||
1118 | RFKILL_TYPE_WWAN, CM_ASL_3G); | ||
1119 | |||
1120 | if (result && result != -ENODEV) | ||
1121 | goto exit; | ||
1122 | |||
1123 | result = eeepc_setup_pci_hotplug(); | ||
1124 | /* | ||
1125 | * If we get -EBUSY then something else is handling the PCI hotplug - | ||
1126 | * don't fail in this case | ||
1127 | */ | ||
1128 | if (result == -EBUSY) | ||
1129 | result = 0; | ||
1130 | |||
1131 | exit: | ||
1132 | if (result && result != -ENODEV) | ||
1133 | eeepc_rfkill_exit(); | ||
1134 | return result; | ||
1135 | } | ||
1136 | |||
1014 | static int eeepc_backlight_init(struct device *dev) | 1137 | static int eeepc_backlight_init(struct device *dev) |
1015 | { | 1138 | { |
1016 | struct backlight_device *bd; | 1139 | struct backlight_device *bd; |
@@ -1018,8 +1141,7 @@ static int eeepc_backlight_init(struct device *dev) | |||
1018 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | 1141 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, |
1019 | NULL, &eeepcbl_ops); | 1142 | NULL, &eeepcbl_ops); |
1020 | if (IS_ERR(bd)) { | 1143 | if (IS_ERR(bd)) { |
1021 | printk(EEEPC_ERR | 1144 | pr_err("Could not register eeepc backlight device\n"); |
1022 | "Could not register eeepc backlight device\n"); | ||
1023 | eeepc_backlight_device = NULL; | 1145 | eeepc_backlight_device = NULL; |
1024 | return PTR_ERR(bd); | 1146 | return PTR_ERR(bd); |
1025 | } | 1147 | } |
@@ -1038,8 +1160,7 @@ static int eeepc_hwmon_init(struct device *dev) | |||
1038 | 1160 | ||
1039 | hwmon = hwmon_device_register(dev); | 1161 | hwmon = hwmon_device_register(dev); |
1040 | if (IS_ERR(hwmon)) { | 1162 | if (IS_ERR(hwmon)) { |
1041 | printk(EEEPC_ERR | 1163 | pr_err("Could not register eeepc hwmon device\n"); |
1042 | "Could not register eeepc hwmon device\n"); | ||
1043 | eeepc_hwmon_device = NULL; | 1164 | eeepc_hwmon_device = NULL; |
1044 | return PTR_ERR(hwmon); | 1165 | return PTR_ERR(hwmon); |
1045 | } | 1166 | } |
@@ -1065,19 +1186,6 @@ static int __init eeepc_laptop_init(void) | |||
1065 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 1186 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
1066 | return -ENODEV; | 1187 | return -ENODEV; |
1067 | } | 1188 | } |
1068 | dev = acpi_get_physical_device(ehotk->device->handle); | ||
1069 | |||
1070 | if (!acpi_video_backlight_support()) { | ||
1071 | result = eeepc_backlight_init(dev); | ||
1072 | if (result) | ||
1073 | goto fail_backlight; | ||
1074 | } else | ||
1075 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
1076 | "driver\n"); | ||
1077 | |||
1078 | result = eeepc_hwmon_init(dev); | ||
1079 | if (result) | ||
1080 | goto fail_hwmon; | ||
1081 | 1189 | ||
1082 | eeepc_enable_camera(); | 1190 | eeepc_enable_camera(); |
1083 | 1191 | ||
@@ -1097,7 +1205,33 @@ static int __init eeepc_laptop_init(void) | |||
1097 | &platform_attribute_group); | 1205 | &platform_attribute_group); |
1098 | if (result) | 1206 | if (result) |
1099 | goto fail_sysfs; | 1207 | goto fail_sysfs; |
1208 | |||
1209 | dev = &platform_device->dev; | ||
1210 | |||
1211 | if (!acpi_video_backlight_support()) { | ||
1212 | result = eeepc_backlight_init(dev); | ||
1213 | if (result) | ||
1214 | goto fail_backlight; | ||
1215 | } else | ||
1216 | pr_info("Backlight controlled by ACPI video " | ||
1217 | "driver\n"); | ||
1218 | |||
1219 | result = eeepc_hwmon_init(dev); | ||
1220 | if (result) | ||
1221 | goto fail_hwmon; | ||
1222 | |||
1223 | result = eeepc_rfkill_init(dev); | ||
1224 | if (result) | ||
1225 | goto fail_rfkill; | ||
1226 | |||
1100 | return 0; | 1227 | return 0; |
1228 | fail_rfkill: | ||
1229 | eeepc_hwmon_exit(); | ||
1230 | fail_hwmon: | ||
1231 | eeepc_backlight_exit(); | ||
1232 | fail_backlight: | ||
1233 | sysfs_remove_group(&platform_device->dev.kobj, | ||
1234 | &platform_attribute_group); | ||
1101 | fail_sysfs: | 1235 | fail_sysfs: |
1102 | platform_device_del(platform_device); | 1236 | platform_device_del(platform_device); |
1103 | fail_platform_device2: | 1237 | fail_platform_device2: |
@@ -1105,12 +1239,7 @@ fail_platform_device2: | |||
1105 | fail_platform_device1: | 1239 | fail_platform_device1: |
1106 | platform_driver_unregister(&platform_driver); | 1240 | platform_driver_unregister(&platform_driver); |
1107 | fail_platform_driver: | 1241 | fail_platform_driver: |
1108 | eeepc_hwmon_exit(); | ||
1109 | fail_hwmon: | ||
1110 | eeepc_backlight_exit(); | ||
1111 | fail_backlight: | ||
1112 | eeepc_input_exit(); | 1242 | eeepc_input_exit(); |
1113 | eeepc_rfkill_exit(); | ||
1114 | return result; | 1243 | return result; |
1115 | } | 1244 | } |
1116 | 1245 | ||