diff options
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 164 |
1 files changed, 144 insertions, 20 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9d93cb971e59..786ed8661cb0 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
32 | #include <linux/rfkill.h> | 32 | #include <linux/rfkill.h> |
33 | #include <linux/pci.h> | ||
33 | 34 | ||
34 | #define EEEPC_LAPTOP_VERSION "0.1" | 35 | #define EEEPC_LAPTOP_VERSION "0.1" |
35 | 36 | ||
@@ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = { | |||
161 | {KE_KEY, 0x13, KEY_MUTE }, | 162 | {KE_KEY, 0x13, KEY_MUTE }, |
162 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, | 163 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, |
163 | {KE_KEY, 0x15, KEY_VOLUMEUP }, | 164 | {KE_KEY, 0x15, KEY_VOLUMEUP }, |
165 | {KE_KEY, 0x1a, KEY_COFFEE }, | ||
166 | {KE_KEY, 0x1b, KEY_ZOOM }, | ||
167 | {KE_KEY, 0x1c, KEY_PROG2 }, | ||
168 | {KE_KEY, 0x1d, KEY_PROG3 }, | ||
164 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, | 169 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, |
165 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, | 170 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, |
166 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, | 171 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, |
@@ -510,7 +515,43 @@ static int eeepc_hotk_check(void) | |||
510 | static void notify_brn(void) | 515 | static void notify_brn(void) |
511 | { | 516 | { |
512 | struct backlight_device *bd = eeepc_backlight_device; | 517 | struct backlight_device *bd = eeepc_backlight_device; |
513 | bd->props.brightness = read_brightness(bd); | 518 | if (bd) |
519 | bd->props.brightness = read_brightness(bd); | ||
520 | } | ||
521 | |||
522 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | ||
523 | { | ||
524 | struct pci_dev *dev; | ||
525 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
526 | |||
527 | if (event != ACPI_NOTIFY_BUS_CHECK) | ||
528 | return; | ||
529 | |||
530 | if (!bus) { | ||
531 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | ||
532 | return; | ||
533 | } | ||
534 | |||
535 | if (get_acpi(CM_ASL_WLAN) == 1) { | ||
536 | dev = pci_get_slot(bus, 0); | ||
537 | if (dev) { | ||
538 | /* Device already present */ | ||
539 | pci_dev_put(dev); | ||
540 | return; | ||
541 | } | ||
542 | dev = pci_scan_single_device(bus, 0); | ||
543 | if (dev) { | ||
544 | pci_bus_assign_resources(bus); | ||
545 | if (pci_bus_add_device(dev)) | ||
546 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | ||
547 | } | ||
548 | } else { | ||
549 | dev = pci_get_slot(bus, 0); | ||
550 | if (dev) { | ||
551 | pci_remove_bus_device(dev); | ||
552 | pci_dev_put(dev); | ||
553 | } | ||
554 | } | ||
514 | } | 555 | } |
515 | 556 | ||
516 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 557 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) |
@@ -520,8 +561,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
520 | return; | 561 | return; |
521 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | 562 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) |
522 | notify_brn(); | 563 | notify_brn(); |
523 | acpi_bus_generate_proc_event(ehotk->device, event, | 564 | acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, |
524 | ehotk->event_count[event % 128]++); | 565 | dev_name(&ehotk->device->dev), event, |
566 | ehotk->event_count[event % 128]++); | ||
525 | if (ehotk->inputdev) { | 567 | if (ehotk->inputdev) { |
526 | key = eepc_get_entry_by_scancode(event); | 568 | key = eepc_get_entry_by_scancode(event); |
527 | if (key) { | 569 | if (key) { |
@@ -539,6 +581,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
539 | } | 581 | } |
540 | } | 582 | } |
541 | 583 | ||
584 | static int eeepc_register_rfkill_notifier(char *node) | ||
585 | { | ||
586 | acpi_status status = AE_OK; | ||
587 | acpi_handle handle; | ||
588 | |||
589 | status = acpi_get_handle(NULL, node, &handle); | ||
590 | |||
591 | if (ACPI_SUCCESS(status)) { | ||
592 | status = acpi_install_notify_handler(handle, | ||
593 | ACPI_SYSTEM_NOTIFY, | ||
594 | eeepc_rfkill_notify, | ||
595 | NULL); | ||
596 | if (ACPI_FAILURE(status)) | ||
597 | printk(EEEPC_WARNING | ||
598 | "Failed to register notify on %s\n", node); | ||
599 | } else | ||
600 | return -ENODEV; | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static void eeepc_unregister_rfkill_notifier(char *node) | ||
606 | { | ||
607 | acpi_status status = AE_OK; | ||
608 | acpi_handle handle; | ||
609 | |||
610 | status = acpi_get_handle(NULL, node, &handle); | ||
611 | |||
612 | if (ACPI_SUCCESS(status)) { | ||
613 | status = acpi_remove_notify_handler(handle, | ||
614 | ACPI_SYSTEM_NOTIFY, | ||
615 | eeepc_rfkill_notify); | ||
616 | if (ACPI_FAILURE(status)) | ||
617 | printk(EEEPC_ERR | ||
618 | "Error removing rfkill notify handler %s\n", | ||
619 | node); | ||
620 | } | ||
621 | } | ||
622 | |||
542 | static int eeepc_hotk_add(struct acpi_device *device) | 623 | static int eeepc_hotk_add(struct acpi_device *device) |
543 | { | 624 | { |
544 | acpi_status status = AE_OK; | 625 | acpi_status status = AE_OK; |
@@ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
558 | ehotk->device = device; | 639 | ehotk->device = device; |
559 | result = eeepc_hotk_check(); | 640 | result = eeepc_hotk_check(); |
560 | if (result) | 641 | if (result) |
561 | goto end; | 642 | goto ehotk_fail; |
562 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | 643 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, |
563 | eeepc_hotk_notify, ehotk); | 644 | eeepc_hotk_notify, ehotk); |
564 | if (ACPI_FAILURE(status)) | 645 | if (ACPI_FAILURE(status)) |
@@ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
569 | RFKILL_TYPE_WLAN); | 650 | RFKILL_TYPE_WLAN); |
570 | 651 | ||
571 | if (!ehotk->eeepc_wlan_rfkill) | 652 | if (!ehotk->eeepc_wlan_rfkill) |
572 | goto end; | 653 | goto wlan_fail; |
573 | 654 | ||
574 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; | 655 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; |
575 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; | 656 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; |
576 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; | 657 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; |
577 | if (get_acpi(CM_ASL_WLAN) == 1) | 658 | if (get_acpi(CM_ASL_WLAN) == 1) { |
578 | ehotk->eeepc_wlan_rfkill->state = | 659 | ehotk->eeepc_wlan_rfkill->state = |
579 | RFKILL_STATE_UNBLOCKED; | 660 | RFKILL_STATE_UNBLOCKED; |
580 | else | 661 | rfkill_set_default(RFKILL_TYPE_WLAN, |
662 | RFKILL_STATE_UNBLOCKED); | ||
663 | } else { | ||
581 | ehotk->eeepc_wlan_rfkill->state = | 664 | ehotk->eeepc_wlan_rfkill->state = |
582 | RFKILL_STATE_SOFT_BLOCKED; | 665 | RFKILL_STATE_SOFT_BLOCKED; |
583 | rfkill_register(ehotk->eeepc_wlan_rfkill); | 666 | rfkill_set_default(RFKILL_TYPE_WLAN, |
667 | RFKILL_STATE_SOFT_BLOCKED); | ||
668 | } | ||
669 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
670 | if (result) | ||
671 | goto wlan_fail; | ||
584 | } | 672 | } |
585 | 673 | ||
586 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | 674 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { |
@@ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
588 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); | 676 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); |
589 | 677 | ||
590 | if (!ehotk->eeepc_bluetooth_rfkill) | 678 | if (!ehotk->eeepc_bluetooth_rfkill) |
591 | goto end; | 679 | goto bluetooth_fail; |
592 | 680 | ||
593 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; | 681 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; |
594 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = | 682 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = |
595 | eeepc_bluetooth_rfkill_set; | 683 | eeepc_bluetooth_rfkill_set; |
596 | ehotk->eeepc_bluetooth_rfkill->get_state = | 684 | ehotk->eeepc_bluetooth_rfkill->get_state = |
597 | eeepc_bluetooth_rfkill_state; | 685 | eeepc_bluetooth_rfkill_state; |
598 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) | 686 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) { |
599 | ehotk->eeepc_bluetooth_rfkill->state = | 687 | ehotk->eeepc_bluetooth_rfkill->state = |
600 | RFKILL_STATE_UNBLOCKED; | 688 | RFKILL_STATE_UNBLOCKED; |
601 | else | 689 | rfkill_set_default(RFKILL_TYPE_BLUETOOTH, |
690 | RFKILL_STATE_UNBLOCKED); | ||
691 | } else { | ||
602 | ehotk->eeepc_bluetooth_rfkill->state = | 692 | ehotk->eeepc_bluetooth_rfkill->state = |
603 | RFKILL_STATE_SOFT_BLOCKED; | 693 | RFKILL_STATE_SOFT_BLOCKED; |
604 | rfkill_register(ehotk->eeepc_bluetooth_rfkill); | 694 | rfkill_set_default(RFKILL_TYPE_BLUETOOTH, |
605 | } | 695 | RFKILL_STATE_SOFT_BLOCKED); |
696 | } | ||
606 | 697 | ||
607 | end: | 698 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); |
608 | if (result) { | 699 | if (result) |
609 | kfree(ehotk); | 700 | goto bluetooth_fail; |
610 | ehotk = NULL; | ||
611 | } | 701 | } |
702 | |||
703 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
704 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
705 | |||
706 | return 0; | ||
707 | |||
708 | bluetooth_fail: | ||
709 | if (ehotk->eeepc_bluetooth_rfkill) | ||
710 | rfkill_free(ehotk->eeepc_bluetooth_rfkill); | ||
711 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
712 | ehotk->eeepc_wlan_rfkill = NULL; | ||
713 | wlan_fail: | ||
714 | if (ehotk->eeepc_wlan_rfkill) | ||
715 | rfkill_free(ehotk->eeepc_wlan_rfkill); | ||
716 | ehotk_fail: | ||
717 | kfree(ehotk); | ||
718 | ehotk = NULL; | ||
719 | |||
612 | return result; | 720 | return result; |
613 | } | 721 | } |
614 | 722 | ||
@@ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
622 | eeepc_hotk_notify); | 730 | eeepc_hotk_notify); |
623 | if (ACPI_FAILURE(status)) | 731 | if (ACPI_FAILURE(status)) |
624 | printk(EEEPC_ERR "Error removing notify handler\n"); | 732 | printk(EEEPC_ERR "Error removing notify handler\n"); |
733 | |||
734 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
735 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
736 | |||
625 | kfree(ehotk); | 737 | kfree(ehotk); |
626 | return 0; | 738 | return 0; |
627 | } | 739 | } |
@@ -737,13 +849,21 @@ static void eeepc_backlight_exit(void) | |||
737 | { | 849 | { |
738 | if (eeepc_backlight_device) | 850 | if (eeepc_backlight_device) |
739 | backlight_device_unregister(eeepc_backlight_device); | 851 | backlight_device_unregister(eeepc_backlight_device); |
740 | if (ehotk->inputdev) | 852 | eeepc_backlight_device = NULL; |
741 | input_unregister_device(ehotk->inputdev); | 853 | } |
854 | |||
855 | static void eeepc_rfkill_exit(void) | ||
856 | { | ||
742 | if (ehotk->eeepc_wlan_rfkill) | 857 | if (ehotk->eeepc_wlan_rfkill) |
743 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 858 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); |
744 | if (ehotk->eeepc_bluetooth_rfkill) | 859 | if (ehotk->eeepc_bluetooth_rfkill) |
745 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 860 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); |
746 | eeepc_backlight_device = NULL; | 861 | } |
862 | |||
863 | static void eeepc_input_exit(void) | ||
864 | { | ||
865 | if (ehotk->inputdev) | ||
866 | input_unregister_device(ehotk->inputdev); | ||
747 | } | 867 | } |
748 | 868 | ||
749 | static void eeepc_hwmon_exit(void) | 869 | static void eeepc_hwmon_exit(void) |
@@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void) | |||
762 | static void __exit eeepc_laptop_exit(void) | 882 | static void __exit eeepc_laptop_exit(void) |
763 | { | 883 | { |
764 | eeepc_backlight_exit(); | 884 | eeepc_backlight_exit(); |
885 | eeepc_rfkill_exit(); | ||
886 | eeepc_input_exit(); | ||
765 | eeepc_hwmon_exit(); | 887 | eeepc_hwmon_exit(); |
766 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 888 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
767 | sysfs_remove_group(&platform_device->dev.kobj, | 889 | sysfs_remove_group(&platform_device->dev.kobj, |
@@ -865,6 +987,8 @@ fail_platform_driver: | |||
865 | fail_hwmon: | 987 | fail_hwmon: |
866 | eeepc_backlight_exit(); | 988 | eeepc_backlight_exit(); |
867 | fail_backlight: | 989 | fail_backlight: |
990 | eeepc_input_exit(); | ||
991 | eeepc_rfkill_exit(); | ||
868 | return result; | 992 | return result; |
869 | } | 993 | } |
870 | 994 | ||