aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/eeepc-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
-rw-r--r--drivers/platform/x86/eeepc-laptop.c168
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)
510static void notify_brn(void) 515static 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
522static 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
516static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) 557static 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
588static 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
609static 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
542static int eeepc_hotk_add(struct acpi_device *device) 627static 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
859static 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
867static void eeepc_input_exit(void)
868{
869 if (ehotk->inputdev)
870 input_unregister_device(ehotk->inputdev);
747} 871}
748 872
749static void eeepc_hwmon_exit(void) 873static void eeepc_hwmon_exit(void)
@@ -762,6 +886,8 @@ static void eeepc_hwmon_exit(void)
762static void __exit eeepc_laptop_exit(void) 886static 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:
865fail_hwmon: 991fail_hwmon:
866 eeepc_backlight_exit(); 992 eeepc_backlight_exit();
867fail_backlight: 993fail_backlight:
994 eeepc_input_exit();
995 eeepc_rfkill_exit();
868 return result; 996 return result;
869} 997}
870 998