diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/Kconfig | 26 | ||||
-rw-r--r-- | drivers/platform/x86/acer-wmi.c | 2 | ||||
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 355 | ||||
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 14 | ||||
-rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 390 |
5 files changed, 301 insertions, 486 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7232fe7104aa..77c6097ced80 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -277,31 +277,6 @@ config THINKPAD_ACPI_UNSAFE_LEDS | |||
277 | Say N here, unless you are building a kernel for your own | 277 | Say N here, unless you are building a kernel for your own |
278 | use, and need to control the important firmware LEDs. | 278 | use, and need to control the important firmware LEDs. |
279 | 279 | ||
280 | config THINKPAD_ACPI_DOCK | ||
281 | bool "Legacy Docking Station Support" | ||
282 | depends on THINKPAD_ACPI | ||
283 | depends on ACPI_DOCK=n | ||
284 | default n | ||
285 | ---help--- | ||
286 | Allows the thinkpad_acpi driver to handle docking station events. | ||
287 | This support was made obsolete by the generic ACPI docking station | ||
288 | support (CONFIG_ACPI_DOCK). It will allow locking and removing the | ||
289 | laptop from the docking station, but will not properly connect PCI | ||
290 | devices. | ||
291 | |||
292 | If you are not sure, say N here. | ||
293 | |||
294 | config THINKPAD_ACPI_BAY | ||
295 | bool "Legacy Removable Bay Support" | ||
296 | depends on THINKPAD_ACPI | ||
297 | default y | ||
298 | ---help--- | ||
299 | Allows the thinkpad_acpi driver to handle removable bays. It will | ||
300 | electrically disable the device in the bay, and also generate | ||
301 | notifications when the bay lever is ejected or inserted. | ||
302 | |||
303 | If you are not sure, say Y here. | ||
304 | |||
305 | config THINKPAD_ACPI_VIDEO | 280 | config THINKPAD_ACPI_VIDEO |
306 | bool "Video output control support" | 281 | bool "Video output control support" |
307 | depends on THINKPAD_ACPI | 282 | depends on THINKPAD_ACPI |
@@ -355,6 +330,7 @@ config EEEPC_LAPTOP | |||
355 | depends on INPUT | 330 | depends on INPUT |
356 | depends on EXPERIMENTAL | 331 | depends on EXPERIMENTAL |
357 | depends on RFKILL || RFKILL = n | 332 | depends on RFKILL || RFKILL = n |
333 | depends on HOTPLUG_PCI | ||
358 | select BACKLIGHT_CLASS_DEVICE | 334 | select BACKLIGHT_CLASS_DEVICE |
359 | select HWMON | 335 | select HWMON |
360 | ---help--- | 336 | ---help--- |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index be2fd6f91639..fb45f5ee8df1 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -973,7 +973,7 @@ static int acer_rfkill_set(void *data, bool blocked) | |||
973 | { | 973 | { |
974 | acpi_status status; | 974 | acpi_status status; |
975 | u32 cap = (unsigned long)data; | 975 | u32 cap = (unsigned long)data; |
976 | status = set_u32(!!blocked, cap); | 976 | status = set_u32(!blocked, cap); |
977 | if (ACPI_FAILURE(status)) | 977 | if (ACPI_FAILURE(status)) |
978 | return -ENODEV; | 978 | return -ENODEV; |
979 | return 0; | 979 | return 0; |
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 | ||
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 4ac2311c00af..a2ad53e15874 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -171,7 +171,7 @@ static int hp_wmi_tablet_state(void) | |||
171 | static int hp_wmi_set_block(void *data, bool blocked) | 171 | static int hp_wmi_set_block(void *data, bool blocked) |
172 | { | 172 | { |
173 | unsigned long b = (unsigned long) data; | 173 | unsigned long b = (unsigned long) data; |
174 | int query = BIT(b + 8) | ((!!blocked) << b); | 174 | int query = BIT(b + 8) | ((!blocked) << b); |
175 | 175 | ||
176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); | 176 | return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); |
177 | } | 177 | } |
@@ -520,11 +520,13 @@ static int hp_wmi_resume_handler(struct platform_device *device) | |||
520 | * the input layer will only actually pass it on if the state | 520 | * the input layer will only actually pass it on if the state |
521 | * changed. | 521 | * changed. |
522 | */ | 522 | */ |
523 | 523 | if (hp_wmi_input_dev) { | |
524 | input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); | 524 | input_report_switch(hp_wmi_input_dev, SW_DOCK, |
525 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, | 525 | hp_wmi_dock_state()); |
526 | hp_wmi_tablet_state()); | 526 | input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, |
527 | input_sync(hp_wmi_input_dev); | 527 | hp_wmi_tablet_state()); |
528 | input_sync(hp_wmi_input_dev); | ||
529 | } | ||
528 | 530 | ||
529 | return 0; | 531 | return 0; |
530 | } | 532 | } |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a463fd72c495..e85600852502 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -239,12 +239,6 @@ struct ibm_init_struct { | |||
239 | }; | 239 | }; |
240 | 240 | ||
241 | static struct { | 241 | static struct { |
242 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
243 | u32 bay_status:1; | ||
244 | u32 bay_eject:1; | ||
245 | u32 bay_status2:1; | ||
246 | u32 bay_eject2:1; | ||
247 | #endif | ||
248 | u32 bluetooth:1; | 242 | u32 bluetooth:1; |
249 | u32 hotkey:1; | 243 | u32 hotkey:1; |
250 | u32 hotkey_mask:1; | 244 | u32 hotkey_mask:1; |
@@ -589,18 +583,6 @@ static int acpi_ec_write(int i, u8 v) | |||
589 | return 1; | 583 | return 1; |
590 | } | 584 | } |
591 | 585 | ||
592 | #if defined(CONFIG_THINKPAD_ACPI_DOCK) || defined(CONFIG_THINKPAD_ACPI_BAY) | ||
593 | static int _sta(acpi_handle handle) | ||
594 | { | ||
595 | int status; | ||
596 | |||
597 | if (!handle || !acpi_evalf(handle, &status, "_STA", "d")) | ||
598 | status = 0; | ||
599 | |||
600 | return status; | ||
601 | } | ||
602 | #endif | ||
603 | |||
604 | static int issue_thinkpad_cmos_command(int cmos_cmd) | 586 | static int issue_thinkpad_cmos_command(int cmos_cmd) |
605 | { | 587 | { |
606 | if (!cmos_handle) | 588 | if (!cmos_handle) |
@@ -784,6 +766,8 @@ static int dispatch_procfs_write(struct file *file, | |||
784 | 766 | ||
785 | if (!ibm || !ibm->write) | 767 | if (!ibm || !ibm->write) |
786 | return -EINVAL; | 768 | return -EINVAL; |
769 | if (count > PAGE_SIZE - 2) | ||
770 | return -EINVAL; | ||
787 | 771 | ||
788 | kernbuf = kmalloc(count + 2, GFP_KERNEL); | 772 | kernbuf = kmalloc(count + 2, GFP_KERNEL); |
789 | if (!kernbuf) | 773 | if (!kernbuf) |
@@ -4442,293 +4426,6 @@ static struct ibm_struct light_driver_data = { | |||
4442 | }; | 4426 | }; |
4443 | 4427 | ||
4444 | /************************************************************************* | 4428 | /************************************************************************* |
4445 | * Dock subdriver | ||
4446 | */ | ||
4447 | |||
4448 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
4449 | |||
4450 | static void dock_notify(struct ibm_struct *ibm, u32 event); | ||
4451 | static int dock_read(char *p); | ||
4452 | static int dock_write(char *buf); | ||
4453 | |||
4454 | TPACPI_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ | ||
4455 | "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ | ||
4456 | "\\_SB.PCI0.PCI1.DOCK", /* all others */ | ||
4457 | "\\_SB.PCI.ISA.SLCE", /* 570 */ | ||
4458 | ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ | ||
4459 | |||
4460 | /* don't list other alternatives as we install a notify handler on the 570 */ | ||
4461 | TPACPI_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ | ||
4462 | |||
4463 | static const struct acpi_device_id ibm_pci_device_ids[] = { | ||
4464 | {PCI_ROOT_HID_STRING, 0}, | ||
4465 | {"", 0}, | ||
4466 | }; | ||
4467 | |||
4468 | static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { | ||
4469 | { | ||
4470 | .notify = dock_notify, | ||
4471 | .handle = &dock_handle, | ||
4472 | .type = ACPI_SYSTEM_NOTIFY, | ||
4473 | }, | ||
4474 | { | ||
4475 | /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. | ||
4476 | * We just use it to get notifications of dock hotplug | ||
4477 | * in very old thinkpads */ | ||
4478 | .hid = ibm_pci_device_ids, | ||
4479 | .notify = dock_notify, | ||
4480 | .handle = &pci_handle, | ||
4481 | .type = ACPI_SYSTEM_NOTIFY, | ||
4482 | }, | ||
4483 | }; | ||
4484 | |||
4485 | static struct ibm_struct dock_driver_data[2] = { | ||
4486 | { | ||
4487 | .name = "dock", | ||
4488 | .read = dock_read, | ||
4489 | .write = dock_write, | ||
4490 | .acpi = &ibm_dock_acpidriver[0], | ||
4491 | }, | ||
4492 | { | ||
4493 | .name = "dock", | ||
4494 | .acpi = &ibm_dock_acpidriver[1], | ||
4495 | }, | ||
4496 | }; | ||
4497 | |||
4498 | #define dock_docked() (_sta(dock_handle) & 1) | ||
4499 | |||
4500 | static int __init dock_init(struct ibm_init_struct *iibm) | ||
4501 | { | ||
4502 | vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n"); | ||
4503 | |||
4504 | TPACPI_ACPIHANDLE_INIT(dock); | ||
4505 | |||
4506 | vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n", | ||
4507 | str_supported(dock_handle != NULL)); | ||
4508 | |||
4509 | return (dock_handle)? 0 : 1; | ||
4510 | } | ||
4511 | |||
4512 | static int __init dock_init2(struct ibm_init_struct *iibm) | ||
4513 | { | ||
4514 | int dock2_needed; | ||
4515 | |||
4516 | vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n"); | ||
4517 | |||
4518 | if (dock_driver_data[0].flags.acpi_driver_registered && | ||
4519 | dock_driver_data[0].flags.acpi_notify_installed) { | ||
4520 | TPACPI_ACPIHANDLE_INIT(pci); | ||
4521 | dock2_needed = (pci_handle != NULL); | ||
4522 | vdbg_printk(TPACPI_DBG_INIT, | ||
4523 | "dock PCI handler for the TP 570 is %s\n", | ||
4524 | str_supported(dock2_needed)); | ||
4525 | } else { | ||
4526 | vdbg_printk(TPACPI_DBG_INIT, | ||
4527 | "dock subdriver part 2 not required\n"); | ||
4528 | dock2_needed = 0; | ||
4529 | } | ||
4530 | |||
4531 | return (dock2_needed)? 0 : 1; | ||
4532 | } | ||
4533 | |||
4534 | static void dock_notify(struct ibm_struct *ibm, u32 event) | ||
4535 | { | ||
4536 | int docked = dock_docked(); | ||
4537 | int pci = ibm->acpi->hid && ibm->acpi->device && | ||
4538 | acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids); | ||
4539 | int data; | ||
4540 | |||
4541 | if (event == 1 && !pci) /* 570 */ | ||
4542 | data = 1; /* button */ | ||
4543 | else if (event == 1 && pci) /* 570 */ | ||
4544 | data = 3; /* dock */ | ||
4545 | else if (event == 3 && docked) | ||
4546 | data = 1; /* button */ | ||
4547 | else if (event == 3 && !docked) | ||
4548 | data = 2; /* undock */ | ||
4549 | else if (event == 0 && docked) | ||
4550 | data = 3; /* dock */ | ||
4551 | else { | ||
4552 | printk(TPACPI_ERR "unknown dock event %d, status %d\n", | ||
4553 | event, _sta(dock_handle)); | ||
4554 | data = 0; /* unknown */ | ||
4555 | } | ||
4556 | acpi_bus_generate_proc_event(ibm->acpi->device, event, data); | ||
4557 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
4558 | dev_name(&ibm->acpi->device->dev), | ||
4559 | event, data); | ||
4560 | } | ||
4561 | |||
4562 | static int dock_read(char *p) | ||
4563 | { | ||
4564 | int len = 0; | ||
4565 | int docked = dock_docked(); | ||
4566 | |||
4567 | if (!dock_handle) | ||
4568 | len += sprintf(p + len, "status:\t\tnot supported\n"); | ||
4569 | else if (!docked) | ||
4570 | len += sprintf(p + len, "status:\t\tundocked\n"); | ||
4571 | else { | ||
4572 | len += sprintf(p + len, "status:\t\tdocked\n"); | ||
4573 | len += sprintf(p + len, "commands:\tdock, undock\n"); | ||
4574 | } | ||
4575 | |||
4576 | return len; | ||
4577 | } | ||
4578 | |||
4579 | static int dock_write(char *buf) | ||
4580 | { | ||
4581 | char *cmd; | ||
4582 | |||
4583 | if (!dock_docked()) | ||
4584 | return -ENODEV; | ||
4585 | |||
4586 | while ((cmd = next_cmd(&buf))) { | ||
4587 | if (strlencmp(cmd, "undock") == 0) { | ||
4588 | if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) || | ||
4589 | !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1)) | ||
4590 | return -EIO; | ||
4591 | } else if (strlencmp(cmd, "dock") == 0) { | ||
4592 | if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1)) | ||
4593 | return -EIO; | ||
4594 | } else | ||
4595 | return -EINVAL; | ||
4596 | } | ||
4597 | |||
4598 | return 0; | ||
4599 | } | ||
4600 | |||
4601 | #endif /* CONFIG_THINKPAD_ACPI_DOCK */ | ||
4602 | |||
4603 | /************************************************************************* | ||
4604 | * Bay subdriver | ||
4605 | */ | ||
4606 | |||
4607 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
4608 | |||
4609 | TPACPI_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ | ||
4610 | "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ | ||
4611 | "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ | ||
4612 | "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ | ||
4613 | ); /* A21e, R30, R31 */ | ||
4614 | TPACPI_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */ | ||
4615 | "_EJ0", /* all others */ | ||
4616 | ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */ | ||
4617 | TPACPI_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ | ||
4618 | "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */ | ||
4619 | ); /* all others */ | ||
4620 | TPACPI_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ | ||
4621 | "_EJ0", /* 770x */ | ||
4622 | ); /* all others */ | ||
4623 | |||
4624 | static int __init bay_init(struct ibm_init_struct *iibm) | ||
4625 | { | ||
4626 | vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n"); | ||
4627 | |||
4628 | TPACPI_ACPIHANDLE_INIT(bay); | ||
4629 | if (bay_handle) | ||
4630 | TPACPI_ACPIHANDLE_INIT(bay_ej); | ||
4631 | TPACPI_ACPIHANDLE_INIT(bay2); | ||
4632 | if (bay2_handle) | ||
4633 | TPACPI_ACPIHANDLE_INIT(bay2_ej); | ||
4634 | |||
4635 | tp_features.bay_status = bay_handle && | ||
4636 | acpi_evalf(bay_handle, NULL, "_STA", "qv"); | ||
4637 | tp_features.bay_status2 = bay2_handle && | ||
4638 | acpi_evalf(bay2_handle, NULL, "_STA", "qv"); | ||
4639 | |||
4640 | tp_features.bay_eject = bay_handle && bay_ej_handle && | ||
4641 | (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental); | ||
4642 | tp_features.bay_eject2 = bay2_handle && bay2_ej_handle && | ||
4643 | (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental); | ||
4644 | |||
4645 | vdbg_printk(TPACPI_DBG_INIT, | ||
4646 | "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n", | ||
4647 | str_supported(tp_features.bay_status), | ||
4648 | str_supported(tp_features.bay_eject), | ||
4649 | str_supported(tp_features.bay_status2), | ||
4650 | str_supported(tp_features.bay_eject2)); | ||
4651 | |||
4652 | return (tp_features.bay_status || tp_features.bay_eject || | ||
4653 | tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1; | ||
4654 | } | ||
4655 | |||
4656 | static void bay_notify(struct ibm_struct *ibm, u32 event) | ||
4657 | { | ||
4658 | acpi_bus_generate_proc_event(ibm->acpi->device, event, 0); | ||
4659 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
4660 | dev_name(&ibm->acpi->device->dev), | ||
4661 | event, 0); | ||
4662 | } | ||
4663 | |||
4664 | #define bay_occupied(b) (_sta(b##_handle) & 1) | ||
4665 | |||
4666 | static int bay_read(char *p) | ||
4667 | { | ||
4668 | int len = 0; | ||
4669 | int occupied = bay_occupied(bay); | ||
4670 | int occupied2 = bay_occupied(bay2); | ||
4671 | int eject, eject2; | ||
4672 | |||
4673 | len += sprintf(p + len, "status:\t\t%s\n", | ||
4674 | tp_features.bay_status ? | ||
4675 | (occupied ? "occupied" : "unoccupied") : | ||
4676 | "not supported"); | ||
4677 | if (tp_features.bay_status2) | ||
4678 | len += sprintf(p + len, "status2:\t%s\n", occupied2 ? | ||
4679 | "occupied" : "unoccupied"); | ||
4680 | |||
4681 | eject = tp_features.bay_eject && occupied; | ||
4682 | eject2 = tp_features.bay_eject2 && occupied2; | ||
4683 | |||
4684 | if (eject && eject2) | ||
4685 | len += sprintf(p + len, "commands:\teject, eject2\n"); | ||
4686 | else if (eject) | ||
4687 | len += sprintf(p + len, "commands:\teject\n"); | ||
4688 | else if (eject2) | ||
4689 | len += sprintf(p + len, "commands:\teject2\n"); | ||
4690 | |||
4691 | return len; | ||
4692 | } | ||
4693 | |||
4694 | static int bay_write(char *buf) | ||
4695 | { | ||
4696 | char *cmd; | ||
4697 | |||
4698 | if (!tp_features.bay_eject && !tp_features.bay_eject2) | ||
4699 | return -ENODEV; | ||
4700 | |||
4701 | while ((cmd = next_cmd(&buf))) { | ||
4702 | if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) { | ||
4703 | if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1)) | ||
4704 | return -EIO; | ||
4705 | } else if (tp_features.bay_eject2 && | ||
4706 | strlencmp(cmd, "eject2") == 0) { | ||
4707 | if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1)) | ||
4708 | return -EIO; | ||
4709 | } else | ||
4710 | return -EINVAL; | ||
4711 | } | ||
4712 | |||
4713 | return 0; | ||
4714 | } | ||
4715 | |||
4716 | static struct tp_acpi_drv_struct ibm_bay_acpidriver = { | ||
4717 | .notify = bay_notify, | ||
4718 | .handle = &bay_handle, | ||
4719 | .type = ACPI_SYSTEM_NOTIFY, | ||
4720 | }; | ||
4721 | |||
4722 | static struct ibm_struct bay_driver_data = { | ||
4723 | .name = "bay", | ||
4724 | .read = bay_read, | ||
4725 | .write = bay_write, | ||
4726 | .acpi = &ibm_bay_acpidriver, | ||
4727 | }; | ||
4728 | |||
4729 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ | ||
4730 | |||
4731 | /************************************************************************* | ||
4732 | * CMOS subdriver | 4429 | * CMOS subdriver |
4733 | */ | 4430 | */ |
4734 | 4431 | ||
@@ -5945,14 +5642,48 @@ static struct backlight_ops ibm_backlight_data = { | |||
5945 | 5642 | ||
5946 | /* --------------------------------------------------------------------- */ | 5643 | /* --------------------------------------------------------------------- */ |
5947 | 5644 | ||
5645 | /* | ||
5646 | * These are only useful for models that have only one possibility | ||
5647 | * of GPU. If the BIOS model handles both ATI and Intel, don't use | ||
5648 | * these quirks. | ||
5649 | */ | ||
5650 | #define TPACPI_BRGHT_Q_NOEC 0x0001 /* Must NOT use EC HBRV */ | ||
5651 | #define TPACPI_BRGHT_Q_EC 0x0002 /* Should or must use EC HBRV */ | ||
5652 | #define TPACPI_BRGHT_Q_ASK 0x8000 /* Ask for user report */ | ||
5653 | |||
5654 | static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { | ||
5655 | /* Models with ATI GPUs known to require ECNVRAM mode */ | ||
5656 | TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ | ||
5657 | |||
5658 | /* Models with ATI GPUs (waiting confirmation) */ | ||
5659 | TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
5660 | TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
5661 | TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
5662 | TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), | ||
5663 | |||
5664 | /* Models with Intel Extreme Graphics 2 (waiting confirmation) */ | ||
5665 | TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
5666 | TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
5667 | TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), | ||
5668 | |||
5669 | /* Models with Intel GMA900 */ | ||
5670 | TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ | ||
5671 | TPACPI_Q_IBM('7', '4', TPACPI_BRGHT_Q_NOEC), /* X41 */ | ||
5672 | TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC), /* X41 Tablet */ | ||
5673 | }; | ||
5674 | |||
5948 | static int __init brightness_init(struct ibm_init_struct *iibm) | 5675 | static int __init brightness_init(struct ibm_init_struct *iibm) |
5949 | { | 5676 | { |
5950 | int b; | 5677 | int b; |
5678 | unsigned long quirks; | ||
5951 | 5679 | ||
5952 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); | 5680 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); |
5953 | 5681 | ||
5954 | mutex_init(&brightness_mutex); | 5682 | mutex_init(&brightness_mutex); |
5955 | 5683 | ||
5684 | quirks = tpacpi_check_quirks(brightness_quirk_table, | ||
5685 | ARRAY_SIZE(brightness_quirk_table)); | ||
5686 | |||
5956 | /* | 5687 | /* |
5957 | * We always attempt to detect acpi support, so as to switch | 5688 | * We always attempt to detect acpi support, so as to switch |
5958 | * Lenovo Vista BIOS to ACPI brightness mode even if we are not | 5689 | * Lenovo Vista BIOS to ACPI brightness mode even if we are not |
@@ -6009,23 +5740,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
6009 | /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ | 5740 | /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ |
6010 | if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || | 5741 | if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || |
6011 | brightness_mode == TPACPI_BRGHT_MODE_MAX) { | 5742 | brightness_mode == TPACPI_BRGHT_MODE_MAX) { |
6012 | if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) { | 5743 | if (quirks & TPACPI_BRGHT_Q_EC) |
6013 | /* | 5744 | brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; |
6014 | * IBM models that define HBRV probably have | 5745 | else |
6015 | * EC-based backlight level control | ||
6016 | */ | ||
6017 | if (acpi_evalf(ec_handle, NULL, "HBRV", "qd")) | ||
6018 | /* T40-T43, R50-R52, R50e, R51e, X31-X41 */ | ||
6019 | brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; | ||
6020 | else | ||
6021 | /* all other IBM ThinkPads */ | ||
6022 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; | ||
6023 | } else | ||
6024 | /* All Lenovo ThinkPads */ | ||
6025 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; | 5746 | brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; |
6026 | 5747 | ||
6027 | dbg_printk(TPACPI_DBG_BRGHT, | 5748 | dbg_printk(TPACPI_DBG_BRGHT, |
6028 | "selected brightness_mode=%d\n", | 5749 | "driver auto-selected brightness_mode=%d\n", |
6029 | brightness_mode); | 5750 | brightness_mode); |
6030 | } | 5751 | } |
6031 | 5752 | ||
@@ -6052,6 +5773,15 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
6052 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, | 5773 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, |
6053 | "brightness is supported\n"); | 5774 | "brightness is supported\n"); |
6054 | 5775 | ||
5776 | if (quirks & TPACPI_BRGHT_Q_ASK) { | ||
5777 | printk(TPACPI_NOTICE | ||
5778 | "brightness: will use unverified default: " | ||
5779 | "brightness_mode=%d\n", brightness_mode); | ||
5780 | printk(TPACPI_NOTICE | ||
5781 | "brightness: please report to %s whether it works well " | ||
5782 | "or not on your ThinkPad\n", TPACPI_MAIL); | ||
5783 | } | ||
5784 | |||
6055 | ibm_backlight_device->props.max_brightness = | 5785 | ibm_backlight_device->props.max_brightness = |
6056 | (tp_features.bright_16levels)? 15 : 7; | 5786 | (tp_features.bright_16levels)? 15 : 7; |
6057 | ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; | 5787 | ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; |
@@ -7854,22 +7584,6 @@ static struct ibm_init_struct ibms_init[] __initdata = { | |||
7854 | .init = light_init, | 7584 | .init = light_init, |
7855 | .data = &light_driver_data, | 7585 | .data = &light_driver_data, |
7856 | }, | 7586 | }, |
7857 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
7858 | { | ||
7859 | .init = dock_init, | ||
7860 | .data = &dock_driver_data[0], | ||
7861 | }, | ||
7862 | { | ||
7863 | .init = dock_init2, | ||
7864 | .data = &dock_driver_data[1], | ||
7865 | }, | ||
7866 | #endif | ||
7867 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
7868 | { | ||
7869 | .init = bay_init, | ||
7870 | .data = &bay_driver_data, | ||
7871 | }, | ||
7872 | #endif | ||
7873 | { | 7587 | { |
7874 | .init = cmos_init, | 7588 | .init = cmos_init, |
7875 | .data = &cmos_driver_data, | 7589 | .data = &cmos_driver_data, |
@@ -7968,12 +7682,6 @@ TPACPI_PARAM(hotkey); | |||
7968 | TPACPI_PARAM(bluetooth); | 7682 | TPACPI_PARAM(bluetooth); |
7969 | TPACPI_PARAM(video); | 7683 | TPACPI_PARAM(video); |
7970 | TPACPI_PARAM(light); | 7684 | TPACPI_PARAM(light); |
7971 | #ifdef CONFIG_THINKPAD_ACPI_DOCK | ||
7972 | TPACPI_PARAM(dock); | ||
7973 | #endif | ||
7974 | #ifdef CONFIG_THINKPAD_ACPI_BAY | ||
7975 | TPACPI_PARAM(bay); | ||
7976 | #endif /* CONFIG_THINKPAD_ACPI_BAY */ | ||
7977 | TPACPI_PARAM(cmos); | 7685 | TPACPI_PARAM(cmos); |
7978 | TPACPI_PARAM(led); | 7686 | TPACPI_PARAM(led); |
7979 | TPACPI_PARAM(beep); | 7687 | TPACPI_PARAM(beep); |