diff options
author | Lee, Chun-Yi <jlee@novell.com> | 2010-05-12 12:58:10 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-05-20 09:45:56 -0400 |
commit | 339e75329a447363658d08833bf9f98909f419cd (patch) | |
tree | 3552e57ca6298c538a935019365dd44c94c3286f | |
parent | 3bb970214fce6495573843e4b7b786f8ea94cd70 (diff) |
msi-laptop: Add i8042 filter to sync sw state with BIOS when function key pressed
There have some MSI netbook change devices state by EC when user press
wlan/bluetooth/wwan function keys. So, add a i8042 filter to sync sw
state with BIOS when function keys pressed.
Signed-off-by: Lee, Chun-Yi <jlee@novell.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/platform/x86/msi-laptop.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 34bec2e26843..b08a108c9776 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <linux/backlight.h> | 59 | #include <linux/backlight.h> |
60 | #include <linux/platform_device.h> | 60 | #include <linux/platform_device.h> |
61 | #include <linux/rfkill.h> | 61 | #include <linux/rfkill.h> |
62 | #include <linux/i8042.h> | ||
62 | 63 | ||
63 | #define MSI_DRIVER_VERSION "0.5" | 64 | #define MSI_DRIVER_VERSION "0.5" |
64 | 65 | ||
@@ -581,6 +582,46 @@ static void rfkill_cleanup(void) | |||
581 | } | 582 | } |
582 | } | 583 | } |
583 | 584 | ||
585 | static void msi_update_rfkill(struct work_struct *ignored) | ||
586 | { | ||
587 | get_wireless_state_ec_standard(); | ||
588 | |||
589 | if (rfk_wlan) | ||
590 | rfkill_set_sw_state(rfk_wlan, !wlan_s); | ||
591 | if (rfk_bluetooth) | ||
592 | rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s); | ||
593 | if (rfk_threeg) | ||
594 | rfkill_set_sw_state(rfk_threeg, !threeg_s); | ||
595 | } | ||
596 | static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill); | ||
597 | |||
598 | static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, | ||
599 | struct serio *port) | ||
600 | { | ||
601 | static bool extended; | ||
602 | |||
603 | if (str & 0x20) | ||
604 | return false; | ||
605 | |||
606 | /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan*/ | ||
607 | if (unlikely(data == 0xe0)) { | ||
608 | extended = true; | ||
609 | return false; | ||
610 | } else if (unlikely(extended)) { | ||
611 | switch (data) { | ||
612 | case 0x54: | ||
613 | case 0x62: | ||
614 | case 0x76: | ||
615 | schedule_delayed_work(&msi_rfkill_work, | ||
616 | round_jiffies_relative(0.5 * HZ)); | ||
617 | break; | ||
618 | } | ||
619 | extended = false; | ||
620 | } | ||
621 | |||
622 | return false; | ||
623 | } | ||
624 | |||
584 | static void msi_init_rfkill(struct work_struct *ignored) | 625 | static void msi_init_rfkill(struct work_struct *ignored) |
585 | { | 626 | { |
586 | if (rfk_wlan) { | 627 | if (rfk_wlan) { |
@@ -706,9 +747,24 @@ static int load_scm_model_init(struct platform_device *sdev) | |||
706 | /* initial rfkill */ | 747 | /* initial rfkill */ |
707 | result = rfkill_init(sdev); | 748 | result = rfkill_init(sdev); |
708 | if (result < 0) | 749 | if (result < 0) |
709 | return result; | 750 | goto fail_rfkill; |
751 | |||
752 | result = i8042_install_filter(msi_laptop_i8042_filter); | ||
753 | if (result) { | ||
754 | printk(KERN_ERR | ||
755 | "msi-laptop: Unable to install key filter\n"); | ||
756 | goto fail_filter; | ||
757 | } | ||
710 | 758 | ||
711 | return 0; | 759 | return 0; |
760 | |||
761 | fail_filter: | ||
762 | rfkill_cleanup(); | ||
763 | |||
764 | fail_rfkill: | ||
765 | |||
766 | return result; | ||
767 | |||
712 | } | 768 | } |
713 | 769 | ||
714 | static int __init msi_init(void) | 770 | static int __init msi_init(void) |
@@ -819,6 +875,7 @@ static void __exit msi_cleanup(void) | |||
819 | platform_driver_unregister(&msipf_driver); | 875 | platform_driver_unregister(&msipf_driver); |
820 | backlight_device_unregister(msibl_device); | 876 | backlight_device_unregister(msibl_device); |
821 | 877 | ||
878 | i8042_remove_filter(msi_laptop_i8042_filter); | ||
822 | rfkill_cleanup(); | 879 | rfkill_cleanup(); |
823 | 880 | ||
824 | /* Enable automatic brightness control again */ | 881 | /* Enable automatic brightness control again */ |