diff options
22 files changed, 477 insertions, 62 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 8285ed4676b6..f216db847022 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2142,6 +2142,11 @@ L: linux-usb@vger.kernel.org | |||
2142 | S: Maintained | 2142 | S: Maintained |
2143 | F: drivers/usb/chipidea/ | 2143 | F: drivers/usb/chipidea/ |
2144 | 2144 | ||
2145 | CHROME HARDWARE PLATFORM SUPPORT | ||
2146 | M: Olof Johansson <olof@lixom.net> | ||
2147 | S: Maintained | ||
2148 | F: drivers/platform/chrome/ | ||
2149 | |||
2145 | CISCO VIC ETHERNET NIC DRIVER | 2150 | CISCO VIC ETHERNET NIC DRIVER |
2146 | M: Christian Benvenuti <benve@cisco.com> | 2151 | M: Christian Benvenuti <benve@cisco.com> |
2147 | M: Sujith Sankar <ssujith@cisco.com> | 2152 | M: Sujith Sankar <ssujith@cisco.com> |
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 69616aeaa966..09fde58b12e0 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig | |||
@@ -5,3 +5,4 @@ if GOLDFISH | |||
5 | source "drivers/platform/goldfish/Kconfig" | 5 | source "drivers/platform/goldfish/Kconfig" |
6 | endif | 6 | endif |
7 | 7 | ||
8 | source "drivers/platform/chrome/Kconfig" | ||
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile index 8a44a4cd6d1e..3656b7b17b99 100644 --- a/drivers/platform/Makefile +++ b/drivers/platform/Makefile | |||
@@ -5,3 +5,4 @@ | |||
5 | obj-$(CONFIG_X86) += x86/ | 5 | obj-$(CONFIG_X86) += x86/ |
6 | obj-$(CONFIG_OLPC) += olpc/ | 6 | obj-$(CONFIG_OLPC) += olpc/ |
7 | obj-$(CONFIG_GOLDFISH) += goldfish/ | 7 | obj-$(CONFIG_GOLDFISH) += goldfish/ |
8 | obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ | ||
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig new file mode 100644 index 000000000000..b13303e75a34 --- /dev/null +++ b/drivers/platform/chrome/Kconfig | |||
@@ -0,0 +1,28 @@ | |||
1 | # | ||
2 | # Platform support for Chrome OS hardware (Chromebooks and Chromeboxes) | ||
3 | # | ||
4 | |||
5 | menuconfig CHROME_PLATFORMS | ||
6 | bool "Platform support for Chrome hardware" | ||
7 | depends on X86 | ||
8 | ---help--- | ||
9 | Say Y here to get to see options for platform support for | ||
10 | various Chromebooks and Chromeboxes. This option alone does | ||
11 | not add any kernel code. | ||
12 | |||
13 | If you say N, all options in this submenu will be skipped and disabled. | ||
14 | |||
15 | if CHROME_PLATFORMS | ||
16 | |||
17 | config CHROMEOS_LAPTOP | ||
18 | tristate "Chrome OS Laptop" | ||
19 | depends on I2C | ||
20 | depends on DMI | ||
21 | ---help--- | ||
22 | This driver instantiates i2c and smbus devices such as | ||
23 | light sensors and touchpads. | ||
24 | |||
25 | If you have a supported Chromebook, choose Y or M here. | ||
26 | The module will be called chromeos_laptop. | ||
27 | |||
28 | endif # CHROMEOS_PLATFORMS | ||
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile new file mode 100644 index 000000000000..015e9195e226 --- /dev/null +++ b/drivers/platform/chrome/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | |||
2 | obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o | ||
diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 3e5b4497a1d0..3e5b4497a1d0 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c | |||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b51a7460cc49..d9dcd37b5a52 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -79,17 +79,6 @@ config ASUS_LAPTOP | |||
79 | 79 | ||
80 | If you have an ACPI-compatible ASUS laptop, say Y or M here. | 80 | If you have an ACPI-compatible ASUS laptop, say Y or M here. |
81 | 81 | ||
82 | config CHROMEOS_LAPTOP | ||
83 | tristate "Chrome OS Laptop" | ||
84 | depends on I2C | ||
85 | depends on DMI | ||
86 | ---help--- | ||
87 | This driver instantiates i2c and smbus devices such as | ||
88 | light sensors and touchpads. | ||
89 | |||
90 | If you have a supported Chromebook, choose Y or M here. | ||
91 | The module will be called chromeos_laptop. | ||
92 | |||
93 | config DELL_LAPTOP | 82 | config DELL_LAPTOP |
94 | tristate "Dell Laptop Extras" | 83 | tristate "Dell Laptop Extras" |
95 | depends on X86 | 84 | depends on X86 |
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 5dbe19324351..f0e6aa407ffb 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile | |||
@@ -50,7 +50,6 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON) += intel_mid_powerbtn.o | |||
50 | obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o | 50 | obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o |
51 | obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o | 51 | obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o |
52 | obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o | 52 | obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o |
53 | obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o | ||
54 | obj-$(CONFIG_INTEL_RST) += intel-rst.o | 53 | obj-$(CONFIG_INTEL_RST) += intel-rst.o |
55 | obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o | 54 | obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o |
56 | 55 | ||
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 0e9c169b42f8..594323a926cf 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -1494,10 +1494,9 @@ static int asus_input_init(struct asus_laptop *asus) | |||
1494 | int error; | 1494 | int error; |
1495 | 1495 | ||
1496 | input = input_allocate_device(); | 1496 | input = input_allocate_device(); |
1497 | if (!input) { | 1497 | if (!input) |
1498 | pr_warn("Unable to allocate input device\n"); | ||
1499 | return -ENOMEM; | 1498 | return -ENOMEM; |
1500 | } | 1499 | |
1501 | input->name = "Asus Laptop extra buttons"; | 1500 | input->name = "Asus Laptop extra buttons"; |
1502 | input->phys = ASUS_LAPTOP_FILE "/input0"; | 1501 | input->phys = ASUS_LAPTOP_FILE "/input0"; |
1503 | input->id.bustype = BUS_HOST; | 1502 | input->id.bustype = BUS_HOST; |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index bb77e18b3dd4..c608b1d33f4a 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/dmi.h> | 22 | #include <linux/dmi.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/rfkill.h> | ||
24 | #include <linux/power_supply.h> | 25 | #include <linux/power_supply.h> |
25 | #include <linux/acpi.h> | 26 | #include <linux/acpi.h> |
26 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
@@ -89,6 +90,13 @@ static struct platform_driver platform_driver = { | |||
89 | 90 | ||
90 | static struct platform_device *platform_device; | 91 | static struct platform_device *platform_device; |
91 | static struct backlight_device *dell_backlight_device; | 92 | static struct backlight_device *dell_backlight_device; |
93 | static struct rfkill *wifi_rfkill; | ||
94 | static struct rfkill *bluetooth_rfkill; | ||
95 | static struct rfkill *wwan_rfkill; | ||
96 | static bool force_rfkill; | ||
97 | |||
98 | module_param(force_rfkill, bool, 0444); | ||
99 | MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models"); | ||
92 | 100 | ||
93 | static const struct dmi_system_id dell_device_table[] __initconst = { | 101 | static const struct dmi_system_id dell_device_table[] __initconst = { |
94 | { | 102 | { |
@@ -355,6 +363,108 @@ dell_send_request(struct calling_interface_buffer *buffer, int class, | |||
355 | return buffer; | 363 | return buffer; |
356 | } | 364 | } |
357 | 365 | ||
366 | /* Derived from information in DellWirelessCtl.cpp: | ||
367 | Class 17, select 11 is radio control. It returns an array of 32-bit values. | ||
368 | |||
369 | Input byte 0 = 0: Wireless information | ||
370 | |||
371 | result[0]: return code | ||
372 | result[1]: | ||
373 | Bit 0: Hardware switch supported | ||
374 | Bit 1: Wifi locator supported | ||
375 | Bit 2: Wifi is supported | ||
376 | Bit 3: Bluetooth is supported | ||
377 | Bit 4: WWAN is supported | ||
378 | Bit 5: Wireless keyboard supported | ||
379 | Bits 6-7: Reserved | ||
380 | Bit 8: Wifi is installed | ||
381 | Bit 9: Bluetooth is installed | ||
382 | Bit 10: WWAN is installed | ||
383 | Bits 11-15: Reserved | ||
384 | Bit 16: Hardware switch is on | ||
385 | Bit 17: Wifi is blocked | ||
386 | Bit 18: Bluetooth is blocked | ||
387 | Bit 19: WWAN is blocked | ||
388 | Bits 20-31: Reserved | ||
389 | result[2]: NVRAM size in bytes | ||
390 | result[3]: NVRAM format version number | ||
391 | |||
392 | Input byte 0 = 2: Wireless switch configuration | ||
393 | result[0]: return code | ||
394 | result[1]: | ||
395 | Bit 0: Wifi controlled by switch | ||
396 | Bit 1: Bluetooth controlled by switch | ||
397 | Bit 2: WWAN controlled by switch | ||
398 | Bits 3-6: Reserved | ||
399 | Bit 7: Wireless switch config locked | ||
400 | Bit 8: Wifi locator enabled | ||
401 | Bits 9-14: Reserved | ||
402 | Bit 15: Wifi locator setting locked | ||
403 | Bits 16-31: Reserved | ||
404 | */ | ||
405 | |||
406 | static int dell_rfkill_set(void *data, bool blocked) | ||
407 | { | ||
408 | int disable = blocked ? 1 : 0; | ||
409 | unsigned long radio = (unsigned long)data; | ||
410 | int hwswitch_bit = (unsigned long)data - 1; | ||
411 | |||
412 | get_buffer(); | ||
413 | dell_send_request(buffer, 17, 11); | ||
414 | |||
415 | /* If the hardware switch controls this radio, and the hardware | ||
416 | switch is disabled, always disable the radio */ | ||
417 | if ((hwswitch_state & BIT(hwswitch_bit)) && | ||
418 | !(buffer->output[1] & BIT(16))) | ||
419 | disable = 1; | ||
420 | |||
421 | buffer->input[0] = (1 | (radio<<8) | (disable << 16)); | ||
422 | dell_send_request(buffer, 17, 11); | ||
423 | |||
424 | release_buffer(); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* Must be called with the buffer held */ | ||
429 | static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, | ||
430 | int status) | ||
431 | { | ||
432 | if (status & BIT(0)) { | ||
433 | /* Has hw-switch, sync sw_state to BIOS */ | ||
434 | int block = rfkill_blocked(rfkill); | ||
435 | buffer->input[0] = (1 | (radio << 8) | (block << 16)); | ||
436 | dell_send_request(buffer, 17, 11); | ||
437 | } else { | ||
438 | /* No hw-switch, sync BIOS state to sw_state */ | ||
439 | rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio, | ||
444 | int status) | ||
445 | { | ||
446 | if (hwswitch_state & (BIT(radio - 1))) | ||
447 | rfkill_set_hw_state(rfkill, !(status & BIT(16))); | ||
448 | } | ||
449 | |||
450 | static void dell_rfkill_query(struct rfkill *rfkill, void *data) | ||
451 | { | ||
452 | int status; | ||
453 | |||
454 | get_buffer(); | ||
455 | dell_send_request(buffer, 17, 11); | ||
456 | status = buffer->output[1]; | ||
457 | |||
458 | dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status); | ||
459 | |||
460 | release_buffer(); | ||
461 | } | ||
462 | |||
463 | static const struct rfkill_ops dell_rfkill_ops = { | ||
464 | .set_block = dell_rfkill_set, | ||
465 | .query = dell_rfkill_query, | ||
466 | }; | ||
467 | |||
358 | static struct dentry *dell_laptop_dir; | 468 | static struct dentry *dell_laptop_dir; |
359 | 469 | ||
360 | static int dell_debugfs_show(struct seq_file *s, void *data) | 470 | static int dell_debugfs_show(struct seq_file *s, void *data) |
@@ -424,6 +534,136 @@ static const struct file_operations dell_debugfs_fops = { | |||
424 | .release = single_release, | 534 | .release = single_release, |
425 | }; | 535 | }; |
426 | 536 | ||
537 | static void dell_update_rfkill(struct work_struct *ignored) | ||
538 | { | ||
539 | int status; | ||
540 | |||
541 | get_buffer(); | ||
542 | dell_send_request(buffer, 17, 11); | ||
543 | status = buffer->output[1]; | ||
544 | |||
545 | if (wifi_rfkill) { | ||
546 | dell_rfkill_update_hw_state(wifi_rfkill, 1, status); | ||
547 | dell_rfkill_update_sw_state(wifi_rfkill, 1, status); | ||
548 | } | ||
549 | if (bluetooth_rfkill) { | ||
550 | dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status); | ||
551 | dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); | ||
552 | } | ||
553 | if (wwan_rfkill) { | ||
554 | dell_rfkill_update_hw_state(wwan_rfkill, 3, status); | ||
555 | dell_rfkill_update_sw_state(wwan_rfkill, 3, status); | ||
556 | } | ||
557 | |||
558 | release_buffer(); | ||
559 | } | ||
560 | static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); | ||
561 | |||
562 | |||
563 | static int __init dell_setup_rfkill(void) | ||
564 | { | ||
565 | int status; | ||
566 | int ret; | ||
567 | const char *product; | ||
568 | |||
569 | /* | ||
570 | * rfkill causes trouble on various non Latitudes, according to Dell | ||
571 | * actually testing the rfkill functionality is only done on Latitudes. | ||
572 | */ | ||
573 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
574 | if (!force_rfkill && (!product || strncmp(product, "Latitude", 8))) | ||
575 | return 0; | ||
576 | |||
577 | get_buffer(); | ||
578 | dell_send_request(buffer, 17, 11); | ||
579 | status = buffer->output[1]; | ||
580 | buffer->input[0] = 0x2; | ||
581 | dell_send_request(buffer, 17, 11); | ||
582 | hwswitch_state = buffer->output[1]; | ||
583 | release_buffer(); | ||
584 | |||
585 | if (!(status & BIT(0))) { | ||
586 | if (force_rfkill) { | ||
587 | /* No hwsitch, clear all hw-controlled bits */ | ||
588 | hwswitch_state &= ~7; | ||
589 | } else { | ||
590 | /* rfkill is only tested on laptops with a hwswitch */ | ||
591 | return 0; | ||
592 | } | ||
593 | } | ||
594 | |||
595 | if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { | ||
596 | wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, | ||
597 | RFKILL_TYPE_WLAN, | ||
598 | &dell_rfkill_ops, (void *) 1); | ||
599 | if (!wifi_rfkill) { | ||
600 | ret = -ENOMEM; | ||
601 | goto err_wifi; | ||
602 | } | ||
603 | ret = rfkill_register(wifi_rfkill); | ||
604 | if (ret) | ||
605 | goto err_wifi; | ||
606 | } | ||
607 | |||
608 | if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { | ||
609 | bluetooth_rfkill = rfkill_alloc("dell-bluetooth", | ||
610 | &platform_device->dev, | ||
611 | RFKILL_TYPE_BLUETOOTH, | ||
612 | &dell_rfkill_ops, (void *) 2); | ||
613 | if (!bluetooth_rfkill) { | ||
614 | ret = -ENOMEM; | ||
615 | goto err_bluetooth; | ||
616 | } | ||
617 | ret = rfkill_register(bluetooth_rfkill); | ||
618 | if (ret) | ||
619 | goto err_bluetooth; | ||
620 | } | ||
621 | |||
622 | if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { | ||
623 | wwan_rfkill = rfkill_alloc("dell-wwan", | ||
624 | &platform_device->dev, | ||
625 | RFKILL_TYPE_WWAN, | ||
626 | &dell_rfkill_ops, (void *) 3); | ||
627 | if (!wwan_rfkill) { | ||
628 | ret = -ENOMEM; | ||
629 | goto err_wwan; | ||
630 | } | ||
631 | ret = rfkill_register(wwan_rfkill); | ||
632 | if (ret) | ||
633 | goto err_wwan; | ||
634 | } | ||
635 | |||
636 | return 0; | ||
637 | err_wwan: | ||
638 | rfkill_destroy(wwan_rfkill); | ||
639 | if (bluetooth_rfkill) | ||
640 | rfkill_unregister(bluetooth_rfkill); | ||
641 | err_bluetooth: | ||
642 | rfkill_destroy(bluetooth_rfkill); | ||
643 | if (wifi_rfkill) | ||
644 | rfkill_unregister(wifi_rfkill); | ||
645 | err_wifi: | ||
646 | rfkill_destroy(wifi_rfkill); | ||
647 | |||
648 | return ret; | ||
649 | } | ||
650 | |||
651 | static void dell_cleanup_rfkill(void) | ||
652 | { | ||
653 | if (wifi_rfkill) { | ||
654 | rfkill_unregister(wifi_rfkill); | ||
655 | rfkill_destroy(wifi_rfkill); | ||
656 | } | ||
657 | if (bluetooth_rfkill) { | ||
658 | rfkill_unregister(bluetooth_rfkill); | ||
659 | rfkill_destroy(bluetooth_rfkill); | ||
660 | } | ||
661 | if (wwan_rfkill) { | ||
662 | rfkill_unregister(wwan_rfkill); | ||
663 | rfkill_destroy(wwan_rfkill); | ||
664 | } | ||
665 | } | ||
666 | |||
427 | static int dell_send_intensity(struct backlight_device *bd) | 667 | static int dell_send_intensity(struct backlight_device *bd) |
428 | { | 668 | { |
429 | int ret = 0; | 669 | int ret = 0; |
@@ -515,6 +755,30 @@ static void touchpad_led_exit(void) | |||
515 | led_classdev_unregister(&touchpad_led); | 755 | led_classdev_unregister(&touchpad_led); |
516 | } | 756 | } |
517 | 757 | ||
758 | static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, | ||
759 | struct serio *port) | ||
760 | { | ||
761 | static bool extended; | ||
762 | |||
763 | if (str & 0x20) | ||
764 | return false; | ||
765 | |||
766 | if (unlikely(data == 0xe0)) { | ||
767 | extended = true; | ||
768 | return false; | ||
769 | } else if (unlikely(extended)) { | ||
770 | switch (data) { | ||
771 | case 0x8: | ||
772 | schedule_delayed_work(&dell_rfkill_work, | ||
773 | round_jiffies_relative(HZ / 4)); | ||
774 | break; | ||
775 | } | ||
776 | extended = false; | ||
777 | } | ||
778 | |||
779 | return false; | ||
780 | } | ||
781 | |||
518 | static int __init dell_init(void) | 782 | static int __init dell_init(void) |
519 | { | 783 | { |
520 | int max_intensity = 0; | 784 | int max_intensity = 0; |
@@ -557,10 +821,26 @@ static int __init dell_init(void) | |||
557 | } | 821 | } |
558 | buffer = page_address(bufferpage); | 822 | buffer = page_address(bufferpage); |
559 | 823 | ||
824 | ret = dell_setup_rfkill(); | ||
825 | |||
826 | if (ret) { | ||
827 | pr_warn("Unable to setup rfkill\n"); | ||
828 | goto fail_rfkill; | ||
829 | } | ||
830 | |||
831 | ret = i8042_install_filter(dell_laptop_i8042_filter); | ||
832 | if (ret) { | ||
833 | pr_warn("Unable to install key filter\n"); | ||
834 | goto fail_filter; | ||
835 | } | ||
836 | |||
560 | if (quirks && quirks->touchpad_led) | 837 | if (quirks && quirks->touchpad_led) |
561 | touchpad_led_init(&platform_device->dev); | 838 | touchpad_led_init(&platform_device->dev); |
562 | 839 | ||
563 | dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); | 840 | dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); |
841 | if (dell_laptop_dir != NULL) | ||
842 | debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, | ||
843 | &dell_debugfs_fops); | ||
564 | 844 | ||
565 | #ifdef CONFIG_ACPI | 845 | #ifdef CONFIG_ACPI |
566 | /* In the event of an ACPI backlight being available, don't | 846 | /* In the event of an ACPI backlight being available, don't |
@@ -603,6 +883,11 @@ static int __init dell_init(void) | |||
603 | return 0; | 883 | return 0; |
604 | 884 | ||
605 | fail_backlight: | 885 | fail_backlight: |
886 | i8042_remove_filter(dell_laptop_i8042_filter); | ||
887 | cancel_delayed_work_sync(&dell_rfkill_work); | ||
888 | fail_filter: | ||
889 | dell_cleanup_rfkill(); | ||
890 | fail_rfkill: | ||
606 | free_page((unsigned long)bufferpage); | 891 | free_page((unsigned long)bufferpage); |
607 | fail_buffer: | 892 | fail_buffer: |
608 | platform_device_del(platform_device); | 893 | platform_device_del(platform_device); |
@@ -620,7 +905,10 @@ static void __exit dell_exit(void) | |||
620 | debugfs_remove_recursive(dell_laptop_dir); | 905 | debugfs_remove_recursive(dell_laptop_dir); |
621 | if (quirks && quirks->touchpad_led) | 906 | if (quirks && quirks->touchpad_led) |
622 | touchpad_led_exit(); | 907 | touchpad_led_exit(); |
908 | i8042_remove_filter(dell_laptop_i8042_filter); | ||
909 | cancel_delayed_work_sync(&dell_rfkill_work); | ||
623 | backlight_device_unregister(dell_backlight_device); | 910 | backlight_device_unregister(dell_backlight_device); |
911 | dell_cleanup_rfkill(); | ||
624 | if (platform_device) { | 912 | if (platform_device) { |
625 | platform_device_unregister(platform_device); | 913 | platform_device_unregister(platform_device); |
626 | platform_driver_unregister(&platform_driver); | 914 | platform_driver_unregister(&platform_driver); |
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index fa9a2171cc13..60e0900bc117 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c | |||
@@ -130,7 +130,8 @@ static const u16 bios_to_linux_keycode[256] __initconst = { | |||
130 | KEY_BRIGHTNESSUP, KEY_UNKNOWN, KEY_KBDILLUMTOGGLE, | 130 | KEY_BRIGHTNESSUP, KEY_UNKNOWN, KEY_KBDILLUMTOGGLE, |
131 | KEY_UNKNOWN, KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN, | 131 | KEY_UNKNOWN, KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN, |
132 | KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_PROG2, | 132 | KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_PROG2, |
133 | KEY_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 133 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
134 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_MICMUTE, | ||
134 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 135 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
135 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 137 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -139,8 +140,8 @@ static const u16 bios_to_linux_keycode[256] __initconst = { | |||
139 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 140 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
140 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 141 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
141 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 142 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
142 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 143 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
143 | KEY_PROG3 | 144 | 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PROG3 |
144 | }; | 145 | }; |
145 | 146 | ||
146 | static struct input_dev *dell_wmi_input_dev; | 147 | static struct input_dev *dell_wmi_input_dev; |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index aefcc32e5634..dec68e7a99c7 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -1203,10 +1203,8 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc) | |||
1203 | int error; | 1203 | int error; |
1204 | 1204 | ||
1205 | input = input_allocate_device(); | 1205 | input = input_allocate_device(); |
1206 | if (!input) { | 1206 | if (!input) |
1207 | pr_info("Unable to allocate input device\n"); | ||
1208 | return -ENOMEM; | 1207 | return -ENOMEM; |
1209 | } | ||
1210 | 1208 | ||
1211 | input->name = "Asus EeePC extra buttons"; | 1209 | input->name = "Asus EeePC extra buttons"; |
1212 | input->phys = EEEPC_LAPTOP_FILE "/input0"; | 1210 | input->phys = EEEPC_LAPTOP_FILE "/input0"; |
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 1c86fa0857c8..8ba8956b5a48 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -54,6 +54,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); | |||
54 | #define HPWMI_HARDWARE_QUERY 0x4 | 54 | #define HPWMI_HARDWARE_QUERY 0x4 |
55 | #define HPWMI_WIRELESS_QUERY 0x5 | 55 | #define HPWMI_WIRELESS_QUERY 0x5 |
56 | #define HPWMI_HOTKEY_QUERY 0xc | 56 | #define HPWMI_HOTKEY_QUERY 0xc |
57 | #define HPWMI_FEATURE_QUERY 0xd | ||
57 | #define HPWMI_WIRELESS2_QUERY 0x1b | 58 | #define HPWMI_WIRELESS2_QUERY 0x1b |
58 | #define HPWMI_POSTCODEERROR_QUERY 0x2a | 59 | #define HPWMI_POSTCODEERROR_QUERY 0x2a |
59 | 60 | ||
@@ -292,6 +293,17 @@ static int hp_wmi_tablet_state(void) | |||
292 | return (state & 0x4) ? 1 : 0; | 293 | return (state & 0x4) ? 1 : 0; |
293 | } | 294 | } |
294 | 295 | ||
296 | static int hp_wmi_bios_2009_later(void) | ||
297 | { | ||
298 | int state = 0; | ||
299 | int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, | ||
300 | sizeof(state), sizeof(state)); | ||
301 | if (ret) | ||
302 | return ret; | ||
303 | |||
304 | return (state & 0x10) ? 1 : 0; | ||
305 | } | ||
306 | |||
295 | static int hp_wmi_set_block(void *data, bool blocked) | 307 | static int hp_wmi_set_block(void *data, bool blocked) |
296 | { | 308 | { |
297 | enum hp_wmi_radio r = (enum hp_wmi_radio) data; | 309 | enum hp_wmi_radio r = (enum hp_wmi_radio) data; |
@@ -871,7 +883,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
871 | gps_rfkill = NULL; | 883 | gps_rfkill = NULL; |
872 | rfkill2_count = 0; | 884 | rfkill2_count = 0; |
873 | 885 | ||
874 | if (hp_wmi_rfkill_setup(device)) | 886 | if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device)) |
875 | hp_wmi_rfkill2_setup(device); | 887 | hp_wmi_rfkill2_setup(device); |
876 | 888 | ||
877 | err = device_create_file(&device->dev, &dev_attr_display); | 889 | err = device_create_file(&device->dev, &dev_attr_display); |
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 6788acc22ab9..19ec95147f69 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -570,10 +570,8 @@ static int ideapad_input_init(struct ideapad_private *priv) | |||
570 | int error; | 570 | int error; |
571 | 571 | ||
572 | inputdev = input_allocate_device(); | 572 | inputdev = input_allocate_device(); |
573 | if (!inputdev) { | 573 | if (!inputdev) |
574 | pr_info("Unable to allocate input device\n"); | ||
575 | return -ENOMEM; | 574 | return -ENOMEM; |
576 | } | ||
577 | 575 | ||
578 | inputdev->name = "Ideapad extra buttons"; | 576 | inputdev->name = "Ideapad extra buttons"; |
579 | inputdev->phys = "ideapad/input0"; | 577 | inputdev->phys = "ideapad/input0"; |
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c index 6b18aba82cfa..8d6775266d66 100644 --- a/drivers/platform/x86/intel_mid_powerbtn.c +++ b/drivers/platform/x86/intel_mid_powerbtn.c | |||
@@ -66,10 +66,8 @@ static int mfld_pb_probe(struct platform_device *pdev) | |||
66 | return -EINVAL; | 66 | return -EINVAL; |
67 | 67 | ||
68 | input = input_allocate_device(); | 68 | input = input_allocate_device(); |
69 | if (!input) { | 69 | if (!input) |
70 | dev_err(&pdev->dev, "Input device allocation error\n"); | ||
71 | return -ENOMEM; | 70 | return -ENOMEM; |
72 | } | ||
73 | 71 | ||
74 | input->name = pdev->name; | 72 | input->name = pdev->name; |
75 | input->phys = "power-button/input0"; | 73 | input->phys = "power-button/input0"; |
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index d654f831410d..60ea476a9130 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c | |||
@@ -58,12 +58,56 @@ | |||
58 | * message handler is called within firmware. | 58 | * message handler is called within firmware. |
59 | */ | 59 | */ |
60 | 60 | ||
61 | #define IPC_BASE_ADDR 0xFF11C000 /* IPC1 base register address */ | ||
62 | #define IPC_MAX_ADDR 0x100 /* Maximum IPC regisers */ | ||
63 | #define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */ | 61 | #define IPC_WWBUF_SIZE 20 /* IPC Write buffer Size */ |
64 | #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */ | 62 | #define IPC_RWBUF_SIZE 20 /* IPC Read buffer Size */ |
65 | #define IPC_I2C_BASE 0xFF12B000 /* I2C control register base address */ | 63 | #define IPC_IOC 0x100 /* IPC command register IOC bit */ |
66 | #define IPC_I2C_MAX_ADDR 0x10 /* Maximum I2C regisers */ | 64 | |
65 | enum { | ||
66 | SCU_IPC_LINCROFT, | ||
67 | SCU_IPC_PENWELL, | ||
68 | SCU_IPC_CLOVERVIEW, | ||
69 | SCU_IPC_TANGIER, | ||
70 | }; | ||
71 | |||
72 | /* intel scu ipc driver data*/ | ||
73 | struct intel_scu_ipc_pdata_t { | ||
74 | u32 ipc_base; | ||
75 | u32 i2c_base; | ||
76 | u32 ipc_len; | ||
77 | u32 i2c_len; | ||
78 | u8 irq_mode; | ||
79 | }; | ||
80 | |||
81 | static struct intel_scu_ipc_pdata_t intel_scu_ipc_pdata[] = { | ||
82 | [SCU_IPC_LINCROFT] = { | ||
83 | .ipc_base = 0xff11c000, | ||
84 | .i2c_base = 0xff12b000, | ||
85 | .ipc_len = 0x100, | ||
86 | .i2c_len = 0x10, | ||
87 | .irq_mode = 0, | ||
88 | }, | ||
89 | [SCU_IPC_PENWELL] = { | ||
90 | .ipc_base = 0xff11c000, | ||
91 | .i2c_base = 0xff12b000, | ||
92 | .ipc_len = 0x100, | ||
93 | .i2c_len = 0x10, | ||
94 | .irq_mode = 1, | ||
95 | }, | ||
96 | [SCU_IPC_CLOVERVIEW] = { | ||
97 | .ipc_base = 0xff11c000, | ||
98 | .i2c_base = 0xff12b000, | ||
99 | .ipc_len = 0x100, | ||
100 | .i2c_len = 0x10, | ||
101 | .irq_mode = 1, | ||
102 | }, | ||
103 | [SCU_IPC_TANGIER] = { | ||
104 | .ipc_base = 0xff009000, | ||
105 | .i2c_base = 0xff00d000, | ||
106 | .ipc_len = 0x100, | ||
107 | .i2c_len = 0x10, | ||
108 | .irq_mode = 0, | ||
109 | }, | ||
110 | }; | ||
67 | 111 | ||
68 | static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id); | 112 | static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id); |
69 | static void ipc_remove(struct pci_dev *pdev); | 113 | static void ipc_remove(struct pci_dev *pdev); |
@@ -72,6 +116,8 @@ struct intel_scu_ipc_dev { | |||
72 | struct pci_dev *pdev; | 116 | struct pci_dev *pdev; |
73 | void __iomem *ipc_base; | 117 | void __iomem *ipc_base; |
74 | void __iomem *i2c_base; | 118 | void __iomem *i2c_base; |
119 | struct completion cmd_complete; | ||
120 | u8 irq_mode; | ||
75 | }; | 121 | }; |
76 | 122 | ||
77 | static struct intel_scu_ipc_dev ipcdev; /* Only one for now */ | 123 | static struct intel_scu_ipc_dev ipcdev; /* Only one for now */ |
@@ -98,6 +144,10 @@ static DEFINE_MUTEX(ipclock); /* lock used to prevent multiple call to SCU */ | |||
98 | */ | 144 | */ |
99 | static inline void ipc_command(u32 cmd) /* Send ipc command */ | 145 | static inline void ipc_command(u32 cmd) /* Send ipc command */ |
100 | { | 146 | { |
147 | if (ipcdev.irq_mode) { | ||
148 | reinit_completion(&ipcdev.cmd_complete); | ||
149 | writel(cmd | IPC_IOC, ipcdev.ipc_base); | ||
150 | } | ||
101 | writel(cmd, ipcdev.ipc_base); | 151 | writel(cmd, ipcdev.ipc_base); |
102 | } | 152 | } |
103 | 153 | ||
@@ -156,6 +206,30 @@ static inline int busy_loop(void) /* Wait till scu status is busy */ | |||
156 | return 0; | 206 | return 0; |
157 | } | 207 | } |
158 | 208 | ||
209 | /* Wait till ipc ioc interrupt is received or timeout in 3 HZ */ | ||
210 | static inline int ipc_wait_for_interrupt(void) | ||
211 | { | ||
212 | int status; | ||
213 | |||
214 | if (!wait_for_completion_timeout(&ipcdev.cmd_complete, 3 * HZ)) { | ||
215 | struct device *dev = &ipcdev.pdev->dev; | ||
216 | dev_err(dev, "IPC timed out\n"); | ||
217 | return -ETIMEDOUT; | ||
218 | } | ||
219 | |||
220 | status = ipc_read_status(); | ||
221 | |||
222 | if ((status >> 1) & 1) | ||
223 | return -EIO; | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | int intel_scu_ipc_check_status(void) | ||
229 | { | ||
230 | return ipcdev.irq_mode ? ipc_wait_for_interrupt() : busy_loop(); | ||
231 | } | ||
232 | |||
159 | /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ | 233 | /* Read/Write power control(PMIC in Langwell, MSIC in PenWell) registers */ |
160 | static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) | 234 | static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) |
161 | { | 235 | { |
@@ -196,8 +270,8 @@ static int pwr_reg_rdwr(u16 *addr, u8 *data, u32 count, u32 op, u32 id) | |||
196 | ipc_command(4 << 16 | id << 12 | 0 << 8 | op); | 270 | ipc_command(4 << 16 | id << 12 | 0 << 8 | op); |
197 | } | 271 | } |
198 | 272 | ||
199 | err = busy_loop(); | 273 | err = intel_scu_ipc_check_status(); |
200 | if (id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ | 274 | if (!err && id == IPC_CMD_PCNTRL_R) { /* Read rbuf */ |
201 | /* Workaround: values are read as 0 without memcpy_fromio */ | 275 | /* Workaround: values are read as 0 without memcpy_fromio */ |
202 | memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16); | 276 | memcpy_fromio(cbuf, ipcdev.ipc_base + 0x90, 16); |
203 | for (nc = 0; nc < count; nc++) | 277 | for (nc = 0; nc < count; nc++) |
@@ -391,7 +465,7 @@ int intel_scu_ipc_simple_command(int cmd, int sub) | |||
391 | return -ENODEV; | 465 | return -ENODEV; |
392 | } | 466 | } |
393 | ipc_command(sub << 12 | cmd); | 467 | ipc_command(sub << 12 | cmd); |
394 | err = busy_loop(); | 468 | err = intel_scu_ipc_check_status(); |
395 | mutex_unlock(&ipclock); | 469 | mutex_unlock(&ipclock); |
396 | return err; | 470 | return err; |
397 | } | 471 | } |
@@ -425,10 +499,12 @@ int intel_scu_ipc_command(int cmd, int sub, u32 *in, int inlen, | |||
425 | ipc_data_writel(*in++, 4 * i); | 499 | ipc_data_writel(*in++, 4 * i); |
426 | 500 | ||
427 | ipc_command((inlen << 16) | (sub << 12) | cmd); | 501 | ipc_command((inlen << 16) | (sub << 12) | cmd); |
428 | err = busy_loop(); | 502 | err = intel_scu_ipc_check_status(); |
429 | 503 | ||
430 | for (i = 0; i < outlen; i++) | 504 | if (!err) { |
431 | *out++ = ipc_data_readl(4 * i); | 505 | for (i = 0; i < outlen; i++) |
506 | *out++ = ipc_data_readl(4 * i); | ||
507 | } | ||
432 | 508 | ||
433 | mutex_unlock(&ipclock); | 509 | mutex_unlock(&ipclock); |
434 | return err; | 510 | return err; |
@@ -491,6 +567,9 @@ EXPORT_SYMBOL(intel_scu_ipc_i2c_cntrl); | |||
491 | */ | 567 | */ |
492 | static irqreturn_t ioc(int irq, void *dev_id) | 568 | static irqreturn_t ioc(int irq, void *dev_id) |
493 | { | 569 | { |
570 | if (ipcdev.irq_mode) | ||
571 | complete(&ipcdev.cmd_complete); | ||
572 | |||
494 | return IRQ_HANDLED; | 573 | return IRQ_HANDLED; |
495 | } | 574 | } |
496 | 575 | ||
@@ -504,13 +583,18 @@ static irqreturn_t ioc(int irq, void *dev_id) | |||
504 | */ | 583 | */ |
505 | static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id) | 584 | static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id) |
506 | { | 585 | { |
507 | int err; | 586 | int err, pid; |
587 | struct intel_scu_ipc_pdata_t *pdata; | ||
508 | resource_size_t pci_resource; | 588 | resource_size_t pci_resource; |
509 | 589 | ||
510 | if (ipcdev.pdev) /* We support only one SCU */ | 590 | if (ipcdev.pdev) /* We support only one SCU */ |
511 | return -EBUSY; | 591 | return -EBUSY; |
512 | 592 | ||
593 | pid = id->driver_data; | ||
594 | pdata = &intel_scu_ipc_pdata[pid]; | ||
595 | |||
513 | ipcdev.pdev = pci_dev_get(dev); | 596 | ipcdev.pdev = pci_dev_get(dev); |
597 | ipcdev.irq_mode = pdata->irq_mode; | ||
514 | 598 | ||
515 | err = pci_enable_device(dev); | 599 | err = pci_enable_device(dev); |
516 | if (err) | 600 | if (err) |
@@ -524,14 +608,16 @@ static int ipc_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
524 | if (!pci_resource) | 608 | if (!pci_resource) |
525 | return -ENOMEM; | 609 | return -ENOMEM; |
526 | 610 | ||
611 | init_completion(&ipcdev.cmd_complete); | ||
612 | |||
527 | if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev)) | 613 | if (request_irq(dev->irq, ioc, 0, "intel_scu_ipc", &ipcdev)) |
528 | return -EBUSY; | 614 | return -EBUSY; |
529 | 615 | ||
530 | ipcdev.ipc_base = ioremap_nocache(IPC_BASE_ADDR, IPC_MAX_ADDR); | 616 | ipcdev.ipc_base = ioremap_nocache(pdata->ipc_base, pdata->ipc_len); |
531 | if (!ipcdev.ipc_base) | 617 | if (!ipcdev.ipc_base) |
532 | return -ENOMEM; | 618 | return -ENOMEM; |
533 | 619 | ||
534 | ipcdev.i2c_base = ioremap_nocache(IPC_I2C_BASE, IPC_I2C_MAX_ADDR); | 620 | ipcdev.i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len); |
535 | if (!ipcdev.i2c_base) { | 621 | if (!ipcdev.i2c_base) { |
536 | iounmap(ipcdev.ipc_base); | 622 | iounmap(ipcdev.ipc_base); |
537 | return -ENOMEM; | 623 | return -ENOMEM; |
@@ -564,7 +650,10 @@ static void ipc_remove(struct pci_dev *pdev) | |||
564 | } | 650 | } |
565 | 651 | ||
566 | static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { | 652 | static DEFINE_PCI_DEVICE_TABLE(pci_ids) = { |
567 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)}, | 653 | {PCI_VDEVICE(INTEL, 0x082a), SCU_IPC_LINCROFT}, |
654 | {PCI_VDEVICE(INTEL, 0x080e), SCU_IPC_PENWELL}, | ||
655 | {PCI_VDEVICE(INTEL, 0x08ea), SCU_IPC_CLOVERVIEW}, | ||
656 | {PCI_VDEVICE(INTEL, 0x11a0), SCU_IPC_TANGIER}, | ||
568 | { 0,} | 657 | { 0,} |
569 | }; | 658 | }; |
570 | MODULE_DEVICE_TABLE(pci, pci_ids); | 659 | MODULE_DEVICE_TABLE(pci, pci_ids); |
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 10d12b221601..3008fd20572e 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c | |||
@@ -490,11 +490,8 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc) | |||
490 | int error; | 490 | int error; |
491 | 491 | ||
492 | input_dev = input_allocate_device(); | 492 | input_dev = input_allocate_device(); |
493 | if (!input_dev) { | 493 | if (!input_dev) |
494 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
495 | "Couldn't allocate input device for hotkey")); | ||
496 | return -ENOMEM; | 494 | return -ENOMEM; |
497 | } | ||
498 | 495 | ||
499 | input_dev->name = ACPI_PCC_DRIVER_NAME; | 496 | input_dev->name = ACPI_PCC_DRIVER_NAME; |
500 | input_dev->phys = ACPI_PCC_INPUT_PHYS; | 497 | input_dev->phys = ACPI_PCC_INPUT_PHYS; |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 47caab0ea7a1..c45c60f7ea2f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -145,7 +145,8 @@ static void sony_nc_thermal_resume(void); | |||
145 | #endif | 145 | #endif |
146 | static int sony_nc_kbd_backlight_setup(struct platform_device *pd, | 146 | static int sony_nc_kbd_backlight_setup(struct platform_device *pd, |
147 | unsigned int handle); | 147 | unsigned int handle); |
148 | static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); | 148 | static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd, |
149 | unsigned int handle); | ||
149 | 150 | ||
150 | static int sony_nc_battery_care_setup(struct platform_device *pd, | 151 | static int sony_nc_battery_care_setup(struct platform_device *pd, |
151 | unsigned int handle); | 152 | unsigned int handle); |
@@ -304,8 +305,8 @@ static int sony_laptop_input_keycode_map[] = { | |||
304 | KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ | 305 | KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ |
305 | KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ | 306 | KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ |
306 | KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ | 307 | KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ |
307 | KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */ | 308 | KEY_FN_1, /* 17 SONYPI_EVENT_FNKEY_1 */ |
308 | KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */ | 309 | KEY_FN_2, /* 18 SONYPI_EVENT_FNKEY_2 */ |
309 | KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ | 310 | KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ |
310 | KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ | 311 | KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ |
311 | KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ | 312 | KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ |
@@ -1444,7 +1445,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd) | |||
1444 | case 0x014b: | 1445 | case 0x014b: |
1445 | case 0x014c: | 1446 | case 0x014c: |
1446 | case 0x0163: | 1447 | case 0x0163: |
1447 | sony_nc_kbd_backlight_cleanup(pd); | 1448 | sony_nc_kbd_backlight_cleanup(pd, handle); |
1448 | break; | 1449 | break; |
1449 | default: | 1450 | default: |
1450 | continue; | 1451 | continue; |
@@ -1822,6 +1823,12 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd, | |||
1822 | int result; | 1823 | int result; |
1823 | int ret = 0; | 1824 | int ret = 0; |
1824 | 1825 | ||
1826 | if (kbdbl_ctl) { | ||
1827 | pr_warn("handle 0x%.4x: keyboard backlight setup already done for 0x%.4x\n", | ||
1828 | handle, kbdbl_ctl->handle); | ||
1829 | return -EBUSY; | ||
1830 | } | ||
1831 | |||
1825 | /* verify the kbd backlight presence, these handles are not used for | 1832 | /* verify the kbd backlight presence, these handles are not used for |
1826 | * keyboard backlight only | 1833 | * keyboard backlight only |
1827 | */ | 1834 | */ |
@@ -1881,9 +1888,10 @@ outkzalloc: | |||
1881 | return ret; | 1888 | return ret; |
1882 | } | 1889 | } |
1883 | 1890 | ||
1884 | static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd) | 1891 | static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd, |
1892 | unsigned int handle) | ||
1885 | { | 1893 | { |
1886 | if (kbdbl_ctl) { | 1894 | if (kbdbl_ctl && handle == kbdbl_ctl->handle) { |
1887 | device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); | 1895 | device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr); |
1888 | device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr); | 1896 | device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr); |
1889 | kfree(kbdbl_ctl); | 1897 | kfree(kbdbl_ctl); |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 05e046aa5e31..58b0274d24cc 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -6438,7 +6438,12 @@ static struct ibm_struct brightness_driver_data = { | |||
6438 | #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" | 6438 | #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" |
6439 | #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME | 6439 | #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME |
6440 | 6440 | ||
6441 | static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */ | 6441 | #if SNDRV_CARDS <= 32 |
6442 | #define DEFAULT_ALSA_IDX ~((1 << (SNDRV_CARDS - 3)) - 1) | ||
6443 | #else | ||
6444 | #define DEFAULT_ALSA_IDX ~((1 << (32 - 3)) - 1) | ||
6445 | #endif | ||
6446 | static int alsa_index = DEFAULT_ALSA_IDX; /* last three slots */ | ||
6442 | static char *alsa_id = "ThinkPadEC"; | 6447 | static char *alsa_id = "ThinkPadEC"; |
6443 | static bool alsa_enable = SNDRV_DEFAULT_ENABLE1; | 6448 | static bool alsa_enable = SNDRV_DEFAULT_ENABLE1; |
6444 | 6449 | ||
@@ -9163,7 +9168,6 @@ static int __init thinkpad_acpi_module_init(void) | |||
9163 | mutex_init(&tpacpi_inputdev_send_mutex); | 9168 | mutex_init(&tpacpi_inputdev_send_mutex); |
9164 | tpacpi_inputdev = input_allocate_device(); | 9169 | tpacpi_inputdev = input_allocate_device(); |
9165 | if (!tpacpi_inputdev) { | 9170 | if (!tpacpi_inputdev) { |
9166 | pr_err("unable to allocate input device\n"); | ||
9167 | thinkpad_acpi_module_exit(); | 9171 | thinkpad_acpi_module_exit(); |
9168 | return -ENOMEM; | 9172 | return -ENOMEM; |
9169 | } else { | 9173 | } else { |
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 67897c8740ba..e597de05e6c2 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c | |||
@@ -97,10 +97,8 @@ static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) | |||
97 | int error; | 97 | int error; |
98 | 98 | ||
99 | input = input_allocate_device(); | 99 | input = input_allocate_device(); |
100 | if (!input) { | 100 | if (!input) |
101 | pr_err("Unable to allocate input device\n"); | ||
102 | return -ENOMEM; | 101 | return -ENOMEM; |
103 | } | ||
104 | 102 | ||
105 | input->name = "Topstar Laptop extra buttons"; | 103 | input->name = "Topstar Laptop extra buttons"; |
106 | input->phys = "topstar/input0"; | 104 | input->phys = "topstar/input0"; |
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 0cfadb65f7c6..7fce391818d3 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -975,10 +975,8 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) | |||
975 | u32 hci_result; | 975 | u32 hci_result; |
976 | 976 | ||
977 | dev->hotkey_dev = input_allocate_device(); | 977 | dev->hotkey_dev = input_allocate_device(); |
978 | if (!dev->hotkey_dev) { | 978 | if (!dev->hotkey_dev) |
979 | pr_info("Unable to register input device\n"); | ||
980 | return -ENOMEM; | 979 | return -ENOMEM; |
981 | } | ||
982 | 980 | ||
983 | dev->hotkey_dev->name = "Toshiba input device"; | 981 | dev->hotkey_dev->name = "Toshiba input device"; |
984 | dev->hotkey_dev->phys = "toshiba_acpi/input0"; | 982 | dev->hotkey_dev->phys = "toshiba_acpi/input0"; |
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 62e8c221d01e..c2e7b2657aeb 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c | |||
@@ -672,8 +672,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | |||
672 | struct wmi_block *wblock; | 672 | struct wmi_block *wblock; |
673 | 673 | ||
674 | wblock = dev_get_drvdata(dev); | 674 | wblock = dev_get_drvdata(dev); |
675 | if (!wblock) | 675 | if (!wblock) { |
676 | return -ENOMEM; | 676 | strcat(buf, "\n"); |
677 | return strlen(buf); | ||
678 | } | ||
677 | 679 | ||
678 | wmi_gtoa(wblock->gblock.guid, guid_string); | 680 | wmi_gtoa(wblock->gblock.guid, guid_string); |
679 | 681 | ||