diff options
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 168 |
1 files changed, 148 insertions, 20 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9d93cb971e59..6f54fd1757cd 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,18 +515,59 @@ 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) |
517 | { | 558 | { |
518 | static struct key_entry *key; | 559 | static struct key_entry *key; |
560 | u16 count; | ||
561 | |||
519 | if (!ehotk) | 562 | if (!ehotk) |
520 | return; | 563 | return; |
521 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | 564 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) |
522 | notify_brn(); | 565 | notify_brn(); |
523 | acpi_bus_generate_proc_event(ehotk->device, event, | 566 | count = ehotk->event_count[event % 128]++; |
524 | ehotk->event_count[event % 128]++); | 567 | acpi_bus_generate_proc_event(ehotk->device, event, count); |
568 | acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, | ||
569 | dev_name(&ehotk->device->dev), event, | ||
570 | count); | ||
525 | if (ehotk->inputdev) { | 571 | if (ehotk->inputdev) { |
526 | key = eepc_get_entry_by_scancode(event); | 572 | key = eepc_get_entry_by_scancode(event); |
527 | if (key) { | 573 | if (key) { |
@@ -539,6 +585,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
539 | } | 585 | } |
540 | } | 586 | } |
541 | 587 | ||
588 | static int eeepc_register_rfkill_notifier(char *node) | ||
589 | { | ||
590 | acpi_status status = AE_OK; | ||
591 | acpi_handle handle; | ||
592 | |||
593 | status = acpi_get_handle(NULL, node, &handle); | ||
594 | |||
595 | if (ACPI_SUCCESS(status)) { | ||
596 | status = acpi_install_notify_handler(handle, | ||
597 | ACPI_SYSTEM_NOTIFY, | ||
598 | eeepc_rfkill_notify, | ||
599 | NULL); | ||
600 | if (ACPI_FAILURE(status)) | ||
601 | printk(EEEPC_WARNING | ||
602 | "Failed to register notify on %s\n", node); | ||
603 | } else | ||
604 | return -ENODEV; | ||
605 | |||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static void eeepc_unregister_rfkill_notifier(char *node) | ||
610 | { | ||
611 | acpi_status status = AE_OK; | ||
612 | acpi_handle handle; | ||
613 | |||
614 | status = acpi_get_handle(NULL, node, &handle); | ||
615 | |||
616 | if (ACPI_SUCCESS(status)) { | ||
617 | status = acpi_remove_notify_handler(handle, | ||
618 | ACPI_SYSTEM_NOTIFY, | ||
619 | eeepc_rfkill_notify); | ||
620 | if (ACPI_FAILURE(status)) | ||
621 | printk(EEEPC_ERR | ||
622 | "Error removing rfkill notify handler %s\n", | ||
623 | node); | ||
624 | } | ||
625 | } | ||
626 | |||
542 | static int eeepc_hotk_add(struct acpi_device *device) | 627 | static int eeepc_hotk_add(struct acpi_device *device) |
543 | { | 628 | { |
544 | acpi_status status = AE_OK; | 629 | acpi_status status = AE_OK; |
@@ -558,7 +643,7 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
558 | ehotk->device = device; | 643 | ehotk->device = device; |
559 | result = eeepc_hotk_check(); | 644 | result = eeepc_hotk_check(); |
560 | if (result) | 645 | if (result) |
561 | goto end; | 646 | goto ehotk_fail; |
562 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | 647 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, |
563 | eeepc_hotk_notify, ehotk); | 648 | eeepc_hotk_notify, ehotk); |
564 | if (ACPI_FAILURE(status)) | 649 | if (ACPI_FAILURE(status)) |
@@ -569,18 +654,25 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
569 | RFKILL_TYPE_WLAN); | 654 | RFKILL_TYPE_WLAN); |
570 | 655 | ||
571 | if (!ehotk->eeepc_wlan_rfkill) | 656 | if (!ehotk->eeepc_wlan_rfkill) |
572 | goto end; | 657 | goto wlan_fail; |
573 | 658 | ||
574 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; | 659 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; |
575 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; | 660 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; |
576 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; | 661 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; |
577 | if (get_acpi(CM_ASL_WLAN) == 1) | 662 | if (get_acpi(CM_ASL_WLAN) == 1) { |
578 | ehotk->eeepc_wlan_rfkill->state = | 663 | ehotk->eeepc_wlan_rfkill->state = |
579 | RFKILL_STATE_UNBLOCKED; | 664 | RFKILL_STATE_UNBLOCKED; |
580 | else | 665 | rfkill_set_default(RFKILL_TYPE_WLAN, |
666 | RFKILL_STATE_UNBLOCKED); | ||
667 | } else { | ||
581 | ehotk->eeepc_wlan_rfkill->state = | 668 | ehotk->eeepc_wlan_rfkill->state = |
582 | RFKILL_STATE_SOFT_BLOCKED; | 669 | RFKILL_STATE_SOFT_BLOCKED; |
583 | rfkill_register(ehotk->eeepc_wlan_rfkill); | 670 | rfkill_set_default(RFKILL_TYPE_WLAN, |
671 | RFKILL_STATE_SOFT_BLOCKED); | ||
672 | } | ||
673 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
674 | if (result) | ||
675 | goto wlan_fail; | ||
584 | } | 676 | } |
585 | 677 | ||
586 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | 678 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { |
@@ -588,27 +680,47 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
588 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); | 680 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); |
589 | 681 | ||
590 | if (!ehotk->eeepc_bluetooth_rfkill) | 682 | if (!ehotk->eeepc_bluetooth_rfkill) |
591 | goto end; | 683 | goto bluetooth_fail; |
592 | 684 | ||
593 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; | 685 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; |
594 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = | 686 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = |
595 | eeepc_bluetooth_rfkill_set; | 687 | eeepc_bluetooth_rfkill_set; |
596 | ehotk->eeepc_bluetooth_rfkill->get_state = | 688 | ehotk->eeepc_bluetooth_rfkill->get_state = |
597 | eeepc_bluetooth_rfkill_state; | 689 | eeepc_bluetooth_rfkill_state; |
598 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) | 690 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) { |
599 | ehotk->eeepc_bluetooth_rfkill->state = | 691 | ehotk->eeepc_bluetooth_rfkill->state = |
600 | RFKILL_STATE_UNBLOCKED; | 692 | RFKILL_STATE_UNBLOCKED; |
601 | else | 693 | rfkill_set_default(RFKILL_TYPE_BLUETOOTH, |
694 | RFKILL_STATE_UNBLOCKED); | ||
695 | } else { | ||
602 | ehotk->eeepc_bluetooth_rfkill->state = | 696 | ehotk->eeepc_bluetooth_rfkill->state = |
603 | RFKILL_STATE_SOFT_BLOCKED; | 697 | RFKILL_STATE_SOFT_BLOCKED; |
604 | rfkill_register(ehotk->eeepc_bluetooth_rfkill); | 698 | rfkill_set_default(RFKILL_TYPE_BLUETOOTH, |
605 | } | 699 | RFKILL_STATE_SOFT_BLOCKED); |
700 | } | ||
606 | 701 | ||
607 | end: | 702 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); |
608 | if (result) { | 703 | if (result) |
609 | kfree(ehotk); | 704 | goto bluetooth_fail; |
610 | ehotk = NULL; | ||
611 | } | 705 | } |
706 | |||
707 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
708 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
709 | |||
710 | return 0; | ||
711 | |||
712 | bluetooth_fail: | ||
713 | if (ehotk->eeepc_bluetooth_rfkill) | ||
714 | rfkill_free(ehotk->eeepc_bluetooth_rfkill); | ||
715 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
716 | ehotk->eeepc_wlan_rfkill = NULL; | ||
717 | wlan_fail: | ||
718 | if (ehotk->eeepc_wlan_rfkill) | ||
719 | rfkill_free(ehotk->eeepc_wlan_rfkill); | ||
720 | ehotk_fail: | ||
721 | kfree(ehotk); | ||
722 | ehotk = NULL; | ||
723 | |||
612 | return result; | 724 | return result; |
613 | } | 725 | } |
614 | 726 | ||
@@ -622,6 +734,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
622 | eeepc_hotk_notify); | 734 | eeepc_hotk_notify); |
623 | if (ACPI_FAILURE(status)) | 735 | if (ACPI_FAILURE(status)) |
624 | printk(EEEPC_ERR "Error removing notify handler\n"); | 736 | printk(EEEPC_ERR "Error removing notify handler\n"); |
737 | |||
738 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
739 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
740 | |||
625 | kfree(ehotk); | 741 | kfree(ehotk); |
626 | return 0; | 742 | return 0; |
627 | } | 743 | } |
@@ -737,13 +853,21 @@ static void eeepc_backlight_exit(void) | |||
737 | { | 853 | { |
738 | if (eeepc_backlight_device) | 854 | if (eeepc_backlight_device) |
739 | backlight_device_unregister(eeepc_backlight_device); | 855 | backlight_device_unregister(eeepc_backlight_device); |
740 | if (ehotk->inputdev) | 856 | eeepc_backlight_device = NULL; |
741 | input_unregister_device(ehotk->inputdev); | 857 | } |
858 | |||
859 | static void eeepc_rfkill_exit(void) | ||
860 | { | ||
742 | if (ehotk->eeepc_wlan_rfkill) | 861 | if (ehotk->eeepc_wlan_rfkill) |
743 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 862 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); |
744 | if (ehotk->eeepc_bluetooth_rfkill) | 863 | if (ehotk->eeepc_bluetooth_rfkill) |
745 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 864 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); |
746 | eeepc_backlight_device = NULL; | 865 | } |
866 | |||
867 | static void eeepc_input_exit(void) | ||
868 | { | ||
869 | if (ehotk->inputdev) | ||
870 | input_unregister_device(ehotk->inputdev); | ||
747 | } | 871 | } |
748 | 872 | ||
749 | static void eeepc_hwmon_exit(void) | 873 | static void eeepc_hwmon_exit(void) |
@@ -762,6 +886,8 @@ static void eeepc_hwmon_exit(void) | |||
762 | static void __exit eeepc_laptop_exit(void) | 886 | static void __exit eeepc_laptop_exit(void) |
763 | { | 887 | { |
764 | eeepc_backlight_exit(); | 888 | eeepc_backlight_exit(); |
889 | eeepc_rfkill_exit(); | ||
890 | eeepc_input_exit(); | ||
765 | eeepc_hwmon_exit(); | 891 | eeepc_hwmon_exit(); |
766 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 892 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
767 | sysfs_remove_group(&platform_device->dev.kobj, | 893 | sysfs_remove_group(&platform_device->dev.kobj, |
@@ -865,6 +991,8 @@ fail_platform_driver: | |||
865 | fail_hwmon: | 991 | fail_hwmon: |
866 | eeepc_backlight_exit(); | 992 | eeepc_backlight_exit(); |
867 | fail_backlight: | 993 | fail_backlight: |
994 | eeepc_input_exit(); | ||
995 | eeepc_rfkill_exit(); | ||
868 | return result; | 996 | return result; |
869 | } | 997 | } |
870 | 998 | ||