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 /drivers | |
| 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>
Diffstat (limited to 'drivers')
| -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 */ |
