diff options
Diffstat (limited to 'drivers/platform/x86/dell-laptop.c')
-rw-r--r-- | drivers/platform/x86/dell-laptop.c | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index c608b1d33f4a..fed4111ac31a 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
@@ -559,19 +559,45 @@ static void dell_update_rfkill(struct work_struct *ignored) | |||
559 | } | 559 | } |
560 | static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); | 560 | static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); |
561 | 561 | ||
562 | static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str, | ||
563 | struct serio *port) | ||
564 | { | ||
565 | static bool extended; | ||
566 | |||
567 | if (str & 0x20) | ||
568 | return false; | ||
569 | |||
570 | if (unlikely(data == 0xe0)) { | ||
571 | extended = true; | ||
572 | return false; | ||
573 | } else if (unlikely(extended)) { | ||
574 | switch (data) { | ||
575 | case 0x8: | ||
576 | schedule_delayed_work(&dell_rfkill_work, | ||
577 | round_jiffies_relative(HZ / 4)); | ||
578 | break; | ||
579 | } | ||
580 | extended = false; | ||
581 | } | ||
582 | |||
583 | return false; | ||
584 | } | ||
562 | 585 | ||
563 | static int __init dell_setup_rfkill(void) | 586 | static int __init dell_setup_rfkill(void) |
564 | { | 587 | { |
565 | int status; | 588 | int status, ret, whitelisted; |
566 | int ret; | ||
567 | const char *product; | 589 | const char *product; |
568 | 590 | ||
569 | /* | 591 | /* |
570 | * rfkill causes trouble on various non Latitudes, according to Dell | 592 | * rfkill support causes trouble on various models, mostly Inspirons. |
571 | * actually testing the rfkill functionality is only done on Latitudes. | 593 | * So we whitelist certain series, and don't support rfkill on others. |
572 | */ | 594 | */ |
595 | whitelisted = 0; | ||
573 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | 596 | product = dmi_get_system_info(DMI_PRODUCT_NAME); |
574 | if (!force_rfkill && (!product || strncmp(product, "Latitude", 8))) | 597 | if (product && (strncmp(product, "Latitude", 8) == 0 || |
598 | strncmp(product, "Precision", 9) == 0)) | ||
599 | whitelisted = 1; | ||
600 | if (!force_rfkill && !whitelisted) | ||
575 | return 0; | 601 | return 0; |
576 | 602 | ||
577 | get_buffer(); | 603 | get_buffer(); |
@@ -633,7 +659,16 @@ static int __init dell_setup_rfkill(void) | |||
633 | goto err_wwan; | 659 | goto err_wwan; |
634 | } | 660 | } |
635 | 661 | ||
662 | ret = i8042_install_filter(dell_laptop_i8042_filter); | ||
663 | if (ret) { | ||
664 | pr_warn("Unable to install key filter\n"); | ||
665 | goto err_filter; | ||
666 | } | ||
667 | |||
636 | return 0; | 668 | return 0; |
669 | err_filter: | ||
670 | if (wwan_rfkill) | ||
671 | rfkill_unregister(wwan_rfkill); | ||
637 | err_wwan: | 672 | err_wwan: |
638 | rfkill_destroy(wwan_rfkill); | 673 | rfkill_destroy(wwan_rfkill); |
639 | if (bluetooth_rfkill) | 674 | if (bluetooth_rfkill) |
@@ -684,7 +719,7 @@ static int dell_send_intensity(struct backlight_device *bd) | |||
684 | 719 | ||
685 | out: | 720 | out: |
686 | release_buffer(); | 721 | release_buffer(); |
687 | return 0; | 722 | return ret; |
688 | } | 723 | } |
689 | 724 | ||
690 | static int dell_get_intensity(struct backlight_device *bd) | 725 | static int dell_get_intensity(struct backlight_device *bd) |
@@ -755,30 +790,6 @@ static void touchpad_led_exit(void) | |||
755 | led_classdev_unregister(&touchpad_led); | 790 | led_classdev_unregister(&touchpad_led); |
756 | } | 791 | } |
757 | 792 | ||
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 | |||
782 | static int __init dell_init(void) | 793 | static int __init dell_init(void) |
783 | { | 794 | { |
784 | int max_intensity = 0; | 795 | int max_intensity = 0; |
@@ -828,12 +839,6 @@ static int __init dell_init(void) | |||
828 | goto fail_rfkill; | 839 | goto fail_rfkill; |
829 | } | 840 | } |
830 | 841 | ||
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 | |||
837 | if (quirks && quirks->touchpad_led) | 842 | if (quirks && quirks->touchpad_led) |
838 | touchpad_led_init(&platform_device->dev); | 843 | touchpad_led_init(&platform_device->dev); |
839 | 844 | ||
@@ -885,7 +890,6 @@ static int __init dell_init(void) | |||
885 | fail_backlight: | 890 | fail_backlight: |
886 | i8042_remove_filter(dell_laptop_i8042_filter); | 891 | i8042_remove_filter(dell_laptop_i8042_filter); |
887 | cancel_delayed_work_sync(&dell_rfkill_work); | 892 | cancel_delayed_work_sync(&dell_rfkill_work); |
888 | fail_filter: | ||
889 | dell_cleanup_rfkill(); | 893 | dell_cleanup_rfkill(); |
890 | fail_rfkill: | 894 | fail_rfkill: |
891 | free_page((unsigned long)bufferpage); | 895 | free_page((unsigned long)bufferpage); |