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, 146 insertions, 22 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 02fe2b8b8939..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
@@ -90,7 +91,7 @@ enum {
90}; 91};
91 92
92static const char *cm_getv[] = { 93static const char *cm_getv[] = {
93 "WLDG", NULL, NULL, NULL, 94 "WLDG", "BTHG", NULL, NULL,
94 "CAMG", NULL, NULL, NULL, 95 "CAMG", NULL, NULL, NULL,
95 NULL, "PBLG", NULL, NULL, 96 NULL, "PBLG", NULL, NULL,
96 "CFVG", NULL, NULL, NULL, 97 "CFVG", NULL, NULL, NULL,
@@ -99,7 +100,7 @@ static const char *cm_getv[] = {
99}; 100};
100 101
101static const char *cm_setv[] = { 102static const char *cm_setv[] = {
102 "WLDS", NULL, NULL, NULL, 103 "WLDS", "BTHS", NULL, NULL,
103 "CAMS", NULL, NULL, NULL, 104 "CAMS", NULL, NULL, NULL,
104 "SDSP", "PBLS", "HDPS", NULL, 105 "SDSP", "PBLS", "HDPS", NULL,
105 "CFVS", NULL, NULL, NULL, 106 "CFVS", NULL, NULL, NULL,
@@ -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)
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)
@@ -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
584static 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
605static 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
542static int eeepc_hotk_add(struct acpi_device *device) 623static 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
855static 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
863static void eeepc_input_exit(void)
864{
865 if (ehotk->inputdev)
866 input_unregister_device(ehotk->inputdev);
747} 867}
748 868
749static void eeepc_hwmon_exit(void) 869static void eeepc_hwmon_exit(void)
@@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void)
762static void __exit eeepc_laptop_exit(void) 882static 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:
865fail_hwmon: 987fail_hwmon:
866 eeepc_backlight_exit(); 988 eeepc_backlight_exit();
867fail_backlight: 989fail_backlight:
990 eeepc_input_exit();
991 eeepc_rfkill_exit();
868 return result; 992 return result;
869} 993}
870 994