diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 01:42:14 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 01:42:14 -0400 |
commit | 7c27fd19b6d985957424348361afa066ff4c74d8 (patch) | |
tree | 276063bee8ebb64088e274fd152d0c40e6573372 /drivers | |
parent | 336d63b8a3cadc1c678f4b16d6105633c7f6af75 (diff) | |
parent | 16dd55f309cf69a648ca3b1fc04b3b6f079c8be0 (diff) |
Merge branch 'sony-laptop' into release
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 531 |
2 files changed, 394 insertions, 138 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index d45c6ab729f8..eb6908a6fe0b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -165,6 +165,7 @@ config SONY_LAPTOP | |||
165 | depends on ACPI | 165 | depends on ACPI |
166 | select BACKLIGHT_CLASS_DEVICE | 166 | select BACKLIGHT_CLASS_DEVICE |
167 | depends on INPUT | 167 | depends on INPUT |
168 | depends on RFKILL | ||
168 | ---help--- | 169 | ---help--- |
169 | This mini-driver drives the SNC and SPIC devices present in the ACPI | 170 | This mini-driver drives the SNC and SPIC devices present in the ACPI |
170 | BIOS of the Sony Vaio laptops. | 171 | BIOS of the Sony Vaio laptops. |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 537959d07148..e02edf68a68e 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * ACPI Sony Notebook Control Driver (SNC and SPIC) | 2 | * ACPI Sony Notebook Control Driver (SNC and SPIC) |
3 | * | 3 | * |
4 | * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> | 4 | * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> |
5 | * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> | 5 | * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it> |
6 | * | 6 | * |
7 | * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c | 7 | * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c |
8 | * which are copyrighted by their respective authors. | 8 | * which are copyrighted by their respective authors. |
@@ -46,7 +46,6 @@ | |||
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/moduleparam.h> | 47 | #include <linux/moduleparam.h> |
48 | #include <linux/init.h> | 48 | #include <linux/init.h> |
49 | #include <linux/smp_lock.h> | ||
50 | #include <linux/types.h> | 49 | #include <linux/types.h> |
51 | #include <linux/backlight.h> | 50 | #include <linux/backlight.h> |
52 | #include <linux/platform_device.h> | 51 | #include <linux/platform_device.h> |
@@ -64,6 +63,7 @@ | |||
64 | #include <asm/uaccess.h> | 63 | #include <asm/uaccess.h> |
65 | #include <linux/sonypi.h> | 64 | #include <linux/sonypi.h> |
66 | #include <linux/sony-laptop.h> | 65 | #include <linux/sony-laptop.h> |
66 | #include <linux/rfkill.h> | ||
67 | #ifdef CONFIG_SONYPI_COMPAT | 67 | #ifdef CONFIG_SONYPI_COMPAT |
68 | #include <linux/poll.h> | 68 | #include <linux/poll.h> |
69 | #include <linux/miscdevice.h> | 69 | #include <linux/miscdevice.h> |
@@ -123,6 +123,18 @@ MODULE_PARM_DESC(minor, | |||
123 | "default is -1 (automatic)"); | 123 | "default is -1 (automatic)"); |
124 | #endif | 124 | #endif |
125 | 125 | ||
126 | enum sony_nc_rfkill { | ||
127 | SONY_WIFI, | ||
128 | SONY_BLUETOOTH, | ||
129 | SONY_WWAN, | ||
130 | SONY_WIMAX, | ||
131 | SONY_RFKILL_MAX, | ||
132 | }; | ||
133 | |||
134 | static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; | ||
135 | static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; | ||
136 | static void sony_nc_rfkill_update(void); | ||
137 | |||
126 | /*********** Input Devices ***********/ | 138 | /*********** Input Devices ***********/ |
127 | 139 | ||
128 | #define SONY_LAPTOP_BUF_SIZE 128 | 140 | #define SONY_LAPTOP_BUF_SIZE 128 |
@@ -134,6 +146,7 @@ struct sony_laptop_input_s { | |||
134 | spinlock_t fifo_lock; | 146 | spinlock_t fifo_lock; |
135 | struct workqueue_struct *wq; | 147 | struct workqueue_struct *wq; |
136 | }; | 148 | }; |
149 | |||
137 | static struct sony_laptop_input_s sony_laptop_input = { | 150 | static struct sony_laptop_input_s sony_laptop_input = { |
138 | .users = ATOMIC_INIT(0), | 151 | .users = ATOMIC_INIT(0), |
139 | }; | 152 | }; |
@@ -211,6 +224,14 @@ static int sony_laptop_input_index[] = { | |||
211 | 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ | 224 | 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ |
212 | 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ | 225 | 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ |
213 | 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ | 226 | 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ |
227 | 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */ | ||
228 | 52, /* 65 SONYPI_EVENT_MODEKEY_PRESSED */ | ||
229 | 53, /* 66 SONYPI_EVENT_PKEY_P4 */ | ||
230 | 54, /* 67 SONYPI_EVENT_PKEY_P5 */ | ||
231 | 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */ | ||
232 | 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ | ||
233 | 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ | ||
234 | -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ | ||
214 | }; | 235 | }; |
215 | 236 | ||
216 | static int sony_laptop_input_keycode_map[] = { | 237 | static int sony_laptop_input_keycode_map[] = { |
@@ -264,7 +285,14 @@ static int sony_laptop_input_keycode_map[] = { | |||
264 | KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ | 285 | KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ |
265 | KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ | 286 | KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ |
266 | KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ | 287 | KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ |
267 | KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ | 288 | KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ |
289 | KEY_EJECTCD, /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ | ||
290 | KEY_F13, /* 52 SONYPI_EVENT_MODEKEY_PRESSED */ | ||
291 | KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */ | ||
292 | KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */ | ||
293 | KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ | ||
294 | KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ | ||
295 | KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ | ||
268 | }; | 296 | }; |
269 | 297 | ||
270 | /* release buttons after a short delay if pressed */ | 298 | /* release buttons after a short delay if pressed */ |
@@ -369,7 +397,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) | |||
369 | sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); | 397 | sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); |
370 | if (!sony_laptop_input.wq) { | 398 | if (!sony_laptop_input.wq) { |
371 | printk(KERN_ERR DRV_PFX | 399 | printk(KERN_ERR DRV_PFX |
372 | "Unabe to create workqueue.\n"); | 400 | "Unable to create workqueue.\n"); |
373 | error = -ENXIO; | 401 | error = -ENXIO; |
374 | goto err_free_kfifo; | 402 | goto err_free_kfifo; |
375 | } | 403 | } |
@@ -689,6 +717,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, | |||
689 | return -1; | 717 | return -1; |
690 | } | 718 | } |
691 | 719 | ||
720 | static int sony_find_snc_handle(int handle) | ||
721 | { | ||
722 | int i; | ||
723 | int result; | ||
724 | |||
725 | for (i = 0x20; i < 0x30; i++) { | ||
726 | acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); | ||
727 | if (result == handle) | ||
728 | return i-0x20; | ||
729 | } | ||
730 | |||
731 | return -1; | ||
732 | } | ||
733 | |||
734 | static int sony_call_snc_handle(int handle, int argument, int *result) | ||
735 | { | ||
736 | int offset = sony_find_snc_handle(handle); | ||
737 | |||
738 | if (offset < 0) | ||
739 | return -1; | ||
740 | |||
741 | return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, | ||
742 | result); | ||
743 | } | ||
744 | |||
692 | /* | 745 | /* |
693 | * sony_nc_values input/output validate functions | 746 | * sony_nc_values input/output validate functions |
694 | */ | 747 | */ |
@@ -809,87 +862,53 @@ struct sony_nc_event { | |||
809 | u8 event; | 862 | u8 event; |
810 | }; | 863 | }; |
811 | 864 | ||
812 | static struct sony_nc_event *sony_nc_events; | 865 | static struct sony_nc_event sony_100_events[] = { |
813 | 866 | { 0x90, SONYPI_EVENT_PKEY_P1 }, | |
814 | /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence | 867 | { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
815 | * for Fn keys | 868 | { 0x91, SONYPI_EVENT_PKEY_P2 }, |
816 | */ | 869 | { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
817 | static int sony_nc_C_enable(const struct dmi_system_id *id) | ||
818 | { | ||
819 | int result = 0; | ||
820 | |||
821 | printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); | ||
822 | |||
823 | sony_nc_events = id->driver_data; | ||
824 | |||
825 | if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 | ||
826 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 | ||
827 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 | ||
828 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 | ||
829 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 | ||
830 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { | ||
831 | printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " | ||
832 | "functionalities may be missing\n"); | ||
833 | return 1; | ||
834 | } | ||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | static struct sony_nc_event sony_C_events[] = { | ||
839 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, | 870 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, |
840 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, | 871 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, |
872 | { 0x82, SONYPI_EVENT_FNKEY_F2 }, | ||
873 | { 0x02, SONYPI_EVENT_FNKEY_RELEASED }, | ||
874 | { 0x83, SONYPI_EVENT_FNKEY_F3 }, | ||
875 | { 0x03, SONYPI_EVENT_FNKEY_RELEASED }, | ||
876 | { 0x84, SONYPI_EVENT_FNKEY_F4 }, | ||
877 | { 0x04, SONYPI_EVENT_FNKEY_RELEASED }, | ||
841 | { 0x85, SONYPI_EVENT_FNKEY_F5 }, | 878 | { 0x85, SONYPI_EVENT_FNKEY_F5 }, |
842 | { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, | 879 | { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, |
843 | { 0x86, SONYPI_EVENT_FNKEY_F6 }, | 880 | { 0x86, SONYPI_EVENT_FNKEY_F6 }, |
844 | { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, | 881 | { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, |
845 | { 0x87, SONYPI_EVENT_FNKEY_F7 }, | 882 | { 0x87, SONYPI_EVENT_FNKEY_F7 }, |
846 | { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, | 883 | { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, |
884 | { 0x89, SONYPI_EVENT_FNKEY_F9 }, | ||
885 | { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, | ||
847 | { 0x8A, SONYPI_EVENT_FNKEY_F10 }, | 886 | { 0x8A, SONYPI_EVENT_FNKEY_F10 }, |
848 | { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, | 887 | { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, |
849 | { 0x8C, SONYPI_EVENT_FNKEY_F12 }, | 888 | { 0x8C, SONYPI_EVENT_FNKEY_F12 }, |
850 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, | 889 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, |
890 | { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, | ||
891 | { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, | ||
851 | { 0, 0 }, | 892 | { 0, 0 }, |
852 | }; | 893 | }; |
853 | 894 | ||
854 | /* SNC-only model map */ | 895 | static struct sony_nc_event sony_127_events[] = { |
855 | static const struct dmi_system_id sony_nc_ids[] = { | 896 | { 0x81, SONYPI_EVENT_MODEKEY_PRESSED }, |
856 | { | 897 | { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
857 | .ident = "Sony Vaio FE Series", | 898 | { 0x82, SONYPI_EVENT_PKEY_P1 }, |
858 | .callback = sony_nc_C_enable, | 899 | { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
859 | .driver_data = sony_C_events, | 900 | { 0x83, SONYPI_EVENT_PKEY_P2 }, |
860 | .matches = { | 901 | { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
861 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 902 | { 0x84, SONYPI_EVENT_PKEY_P3 }, |
862 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), | 903 | { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
863 | }, | 904 | { 0x85, SONYPI_EVENT_PKEY_P4 }, |
864 | }, | 905 | { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
865 | { | 906 | { 0x86, SONYPI_EVENT_PKEY_P5 }, |
866 | .ident = "Sony Vaio FZ Series", | 907 | { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
867 | .callback = sony_nc_C_enable, | 908 | { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
868 | .driver_data = sony_C_events, | 909 | { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED }, |
869 | .matches = { | 910 | { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
870 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 911 | { 0, 0 }, |
871 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"), | ||
872 | }, | ||
873 | }, | ||
874 | { | ||
875 | .ident = "Sony Vaio C Series", | ||
876 | .callback = sony_nc_C_enable, | ||
877 | .driver_data = sony_C_events, | ||
878 | .matches = { | ||
879 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
880 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), | ||
881 | }, | ||
882 | }, | ||
883 | { | ||
884 | .ident = "Sony Vaio N Series", | ||
885 | .callback = sony_nc_C_enable, | ||
886 | .driver_data = sony_C_events, | ||
887 | .matches = { | ||
888 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
889 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), | ||
890 | }, | ||
891 | }, | ||
892 | { } | ||
893 | }; | 912 | }; |
894 | 913 | ||
895 | /* | 914 | /* |
@@ -897,38 +916,59 @@ static const struct dmi_system_id sony_nc_ids[] = { | |||
897 | */ | 916 | */ |
898 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) | 917 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) |
899 | { | 918 | { |
900 | struct sony_nc_event *evmap; | ||
901 | u32 ev = event; | 919 | u32 ev = event; |
902 | int result; | ||
903 | 920 | ||
904 | if (ev == 0x92) { | 921 | if (ev >= 0x90) { |
905 | /* read the key pressed from EC.GECR | 922 | /* New-style event */ |
906 | * A call to SN07 with 0x0202 will do it as well respecting | 923 | int result; |
907 | * the current protocol on different OSes | 924 | int key_handle = 0; |
908 | * | 925 | ev -= 0x90; |
909 | * Note: the path for GECR may be | 926 | |
910 | * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) | 927 | if (sony_find_snc_handle(0x100) == ev) |
911 | * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) | 928 | key_handle = 0x100; |
912 | * | 929 | if (sony_find_snc_handle(0x127) == ev) |
913 | * TODO: we may want to do the same for the older GHKE -need | 930 | key_handle = 0x127; |
914 | * dmi list- so this snippet may become one more callback. | 931 | |
915 | */ | 932 | if (key_handle) { |
916 | if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) | 933 | struct sony_nc_event *key_event; |
917 | dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); | 934 | |
918 | else | 935 | if (sony_call_snc_handle(key_handle, 0x200, &result)) { |
919 | ev = result & 0xFF; | 936 | dprintk("sony_acpi_notify, unable to decode" |
920 | } | 937 | " event 0x%.2x 0x%.2x\n", key_handle, |
938 | ev); | ||
939 | /* restore the original event */ | ||
940 | ev = event; | ||
941 | } else { | ||
942 | ev = result & 0xFF; | ||
943 | |||
944 | if (key_handle == 0x100) | ||
945 | key_event = sony_100_events; | ||
946 | else | ||
947 | key_event = sony_127_events; | ||
948 | |||
949 | for (; key_event->data; key_event++) { | ||
950 | if (key_event->data == ev) { | ||
951 | ev = key_event->event; | ||
952 | break; | ||
953 | } | ||
954 | } | ||
921 | 955 | ||
922 | if (sony_nc_events) | 956 | if (!key_event->data) |
923 | for (evmap = sony_nc_events; evmap->event; evmap++) { | 957 | printk(KERN_INFO DRV_PFX |
924 | if (evmap->data == ev) { | 958 | "Unknown event: 0x%x 0x%x\n", |
925 | ev = evmap->event; | 959 | key_handle, |
926 | break; | 960 | ev); |
961 | else | ||
962 | sony_laptop_report_input_event(ev); | ||
927 | } | 963 | } |
964 | } else if (sony_find_snc_handle(0x124) == ev) { | ||
965 | sony_nc_rfkill_update(); | ||
966 | return; | ||
928 | } | 967 | } |
968 | } else | ||
969 | sony_laptop_report_input_event(ev); | ||
929 | 970 | ||
930 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); | 971 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); |
931 | sony_laptop_report_input_event(ev); | ||
932 | acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); | 972 | acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); |
933 | } | 973 | } |
934 | 974 | ||
@@ -953,9 +993,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, | |||
953 | /* | 993 | /* |
954 | * ACPI device | 994 | * ACPI device |
955 | */ | 995 | */ |
996 | static int sony_nc_function_setup(struct acpi_device *device) | ||
997 | { | ||
998 | int result; | ||
999 | |||
1000 | /* Enable all events */ | ||
1001 | acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); | ||
1002 | |||
1003 | /* Setup hotkeys */ | ||
1004 | sony_call_snc_handle(0x0100, 0, &result); | ||
1005 | sony_call_snc_handle(0x0101, 0, &result); | ||
1006 | sony_call_snc_handle(0x0102, 0x100, &result); | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
956 | static int sony_nc_resume(struct acpi_device *device) | 1011 | static int sony_nc_resume(struct acpi_device *device) |
957 | { | 1012 | { |
958 | struct sony_nc_value *item; | 1013 | struct sony_nc_value *item; |
1014 | acpi_handle handle; | ||
959 | 1015 | ||
960 | for (item = sony_nc_values; item->name; item++) { | 1016 | for (item = sony_nc_values; item->name; item++) { |
961 | int ret; | 1017 | int ret; |
@@ -970,13 +1026,188 @@ static int sony_nc_resume(struct acpi_device *device) | |||
970 | } | 1026 | } |
971 | } | 1027 | } |
972 | 1028 | ||
1029 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", | ||
1030 | &handle))) { | ||
1031 | if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) | ||
1032 | dprintk("ECON Method failed\n"); | ||
1033 | } | ||
1034 | |||
1035 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", | ||
1036 | &handle))) { | ||
1037 | dprintk("Doing SNC setup\n"); | ||
1038 | sony_nc_function_setup(device); | ||
1039 | } | ||
1040 | |||
973 | /* set the last requested brightness level */ | 1041 | /* set the last requested brightness level */ |
974 | if (sony_backlight_device && | 1042 | if (sony_backlight_device && |
975 | !sony_backlight_update_status(sony_backlight_device)) | 1043 | !sony_backlight_update_status(sony_backlight_device)) |
976 | printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); | 1044 | printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); |
977 | 1045 | ||
978 | /* re-initialize models with specific requirements */ | 1046 | return 0; |
979 | dmi_check_system(sony_nc_ids); | 1047 | } |
1048 | |||
1049 | static void sony_nc_rfkill_cleanup(void) | ||
1050 | { | ||
1051 | int i; | ||
1052 | |||
1053 | for (i = 0; i < SONY_RFKILL_MAX; i++) { | ||
1054 | if (sony_rfkill_devices[i]) | ||
1055 | rfkill_unregister(sony_rfkill_devices[i]); | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) | ||
1060 | { | ||
1061 | int result; | ||
1062 | int argument = sony_rfkill_address[(long) data]; | ||
1063 | |||
1064 | sony_call_snc_handle(0x124, 0x200, &result); | ||
1065 | if (result & 0x1) { | ||
1066 | sony_call_snc_handle(0x124, argument, &result); | ||
1067 | if (result & 0xf) | ||
1068 | *state = RFKILL_STATE_UNBLOCKED; | ||
1069 | else | ||
1070 | *state = RFKILL_STATE_SOFT_BLOCKED; | ||
1071 | } else { | ||
1072 | *state = RFKILL_STATE_HARD_BLOCKED; | ||
1073 | } | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | static int sony_nc_rfkill_set(void *data, enum rfkill_state state) | ||
1079 | { | ||
1080 | int result; | ||
1081 | int argument = sony_rfkill_address[(long) data] + 0x100; | ||
1082 | |||
1083 | if (state == RFKILL_STATE_UNBLOCKED) | ||
1084 | argument |= 0xff0000; | ||
1085 | |||
1086 | return sony_call_snc_handle(0x124, argument, &result); | ||
1087 | } | ||
1088 | |||
1089 | static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) | ||
1090 | { | ||
1091 | int err = 0; | ||
1092 | struct rfkill *sony_wifi_rfkill; | ||
1093 | |||
1094 | sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); | ||
1095 | if (!sony_wifi_rfkill) | ||
1096 | return -1; | ||
1097 | sony_wifi_rfkill->name = "sony-wifi"; | ||
1098 | sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set; | ||
1099 | sony_wifi_rfkill->get_state = sony_nc_rfkill_get; | ||
1100 | sony_wifi_rfkill->user_claim_unsupported = 1; | ||
1101 | sony_wifi_rfkill->data = (void *)SONY_WIFI; | ||
1102 | err = rfkill_register(sony_wifi_rfkill); | ||
1103 | if (err) | ||
1104 | rfkill_free(sony_wifi_rfkill); | ||
1105 | else | ||
1106 | sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill; | ||
1107 | return err; | ||
1108 | } | ||
1109 | |||
1110 | static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) | ||
1111 | { | ||
1112 | int err = 0; | ||
1113 | struct rfkill *sony_bluetooth_rfkill; | ||
1114 | |||
1115 | sony_bluetooth_rfkill = rfkill_allocate(&device->dev, | ||
1116 | RFKILL_TYPE_BLUETOOTH); | ||
1117 | if (!sony_bluetooth_rfkill) | ||
1118 | return -1; | ||
1119 | sony_bluetooth_rfkill->name = "sony-bluetooth"; | ||
1120 | sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; | ||
1121 | sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; | ||
1122 | sony_bluetooth_rfkill->user_claim_unsupported = 1; | ||
1123 | sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; | ||
1124 | err = rfkill_register(sony_bluetooth_rfkill); | ||
1125 | if (err) | ||
1126 | rfkill_free(sony_bluetooth_rfkill); | ||
1127 | else | ||
1128 | sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; | ||
1129 | return err; | ||
1130 | } | ||
1131 | |||
1132 | static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) | ||
1133 | { | ||
1134 | int err = 0; | ||
1135 | struct rfkill *sony_wwan_rfkill; | ||
1136 | |||
1137 | sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); | ||
1138 | if (!sony_wwan_rfkill) | ||
1139 | return -1; | ||
1140 | sony_wwan_rfkill->name = "sony-wwan"; | ||
1141 | sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set; | ||
1142 | sony_wwan_rfkill->get_state = sony_nc_rfkill_get; | ||
1143 | sony_wwan_rfkill->user_claim_unsupported = 1; | ||
1144 | sony_wwan_rfkill->data = (void *)SONY_WWAN; | ||
1145 | err = rfkill_register(sony_wwan_rfkill); | ||
1146 | if (err) | ||
1147 | rfkill_free(sony_wwan_rfkill); | ||
1148 | else | ||
1149 | sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill; | ||
1150 | return err; | ||
1151 | } | ||
1152 | |||
1153 | static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) | ||
1154 | { | ||
1155 | int err = 0; | ||
1156 | struct rfkill *sony_wimax_rfkill; | ||
1157 | |||
1158 | sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); | ||
1159 | if (!sony_wimax_rfkill) | ||
1160 | return -1; | ||
1161 | sony_wimax_rfkill->name = "sony-wimax"; | ||
1162 | sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set; | ||
1163 | sony_wimax_rfkill->get_state = sony_nc_rfkill_get; | ||
1164 | sony_wimax_rfkill->user_claim_unsupported = 1; | ||
1165 | sony_wimax_rfkill->data = (void *)SONY_WIMAX; | ||
1166 | err = rfkill_register(sony_wimax_rfkill); | ||
1167 | if (err) | ||
1168 | rfkill_free(sony_wimax_rfkill); | ||
1169 | else | ||
1170 | sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill; | ||
1171 | return err; | ||
1172 | } | ||
1173 | |||
1174 | static void sony_nc_rfkill_update() | ||
1175 | { | ||
1176 | int i; | ||
1177 | enum rfkill_state state; | ||
1178 | |||
1179 | for (i = 0; i < SONY_RFKILL_MAX; i++) { | ||
1180 | if (sony_rfkill_devices[i]) { | ||
1181 | sony_rfkill_devices[i]-> | ||
1182 | get_state(sony_rfkill_devices[i]->data, | ||
1183 | &state); | ||
1184 | rfkill_force_state(sony_rfkill_devices[i], state); | ||
1185 | } | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | static int sony_nc_rfkill_setup(struct acpi_device *device) | ||
1190 | { | ||
1191 | int result, ret; | ||
1192 | |||
1193 | if (sony_find_snc_handle(0x124) == -1) | ||
1194 | return -1; | ||
1195 | |||
1196 | ret = sony_call_snc_handle(0x124, 0xb00, &result); | ||
1197 | if (ret) { | ||
1198 | printk(KERN_INFO DRV_PFX | ||
1199 | "Unable to enumerate rfkill devices: %x\n", ret); | ||
1200 | return ret; | ||
1201 | } | ||
1202 | |||
1203 | if (result & 0x1) | ||
1204 | sony_nc_setup_wifi_rfkill(device); | ||
1205 | if (result & 0x2) | ||
1206 | sony_nc_setup_bluetooth_rfkill(device); | ||
1207 | if (result & 0x1c) | ||
1208 | sony_nc_setup_wwan_rfkill(device); | ||
1209 | if (result & 0x20) | ||
1210 | sony_nc_setup_wimax_rfkill(device); | ||
980 | 1211 | ||
981 | return 0; | 1212 | return 0; |
982 | } | 1213 | } |
@@ -1024,11 +1255,24 @@ static int sony_nc_add(struct acpi_device *device) | |||
1024 | dprintk("_INI Method failed\n"); | 1255 | dprintk("_INI Method failed\n"); |
1025 | } | 1256 | } |
1026 | 1257 | ||
1258 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", | ||
1259 | &handle))) { | ||
1260 | if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) | ||
1261 | dprintk("ECON Method failed\n"); | ||
1262 | } | ||
1263 | |||
1264 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", | ||
1265 | &handle))) { | ||
1266 | dprintk("Doing SNC setup\n"); | ||
1267 | sony_nc_function_setup(device); | ||
1268 | sony_nc_rfkill_setup(device); | ||
1269 | } | ||
1270 | |||
1027 | /* setup input devices and helper fifo */ | 1271 | /* setup input devices and helper fifo */ |
1028 | result = sony_laptop_setup_input(device); | 1272 | result = sony_laptop_setup_input(device); |
1029 | if (result) { | 1273 | if (result) { |
1030 | printk(KERN_ERR DRV_PFX | 1274 | printk(KERN_ERR DRV_PFX |
1031 | "Unabe to create input devices.\n"); | 1275 | "Unable to create input devices.\n"); |
1032 | goto outwalk; | 1276 | goto outwalk; |
1033 | } | 1277 | } |
1034 | 1278 | ||
@@ -1063,9 +1307,6 @@ static int sony_nc_add(struct acpi_device *device) | |||
1063 | 1307 | ||
1064 | } | 1308 | } |
1065 | 1309 | ||
1066 | /* initialize models with specific requirements */ | ||
1067 | dmi_check_system(sony_nc_ids); | ||
1068 | |||
1069 | result = sony_pf_add(); | 1310 | result = sony_pf_add(); |
1070 | if (result) | 1311 | if (result) |
1071 | goto outbacklight; | 1312 | goto outbacklight; |
@@ -1131,6 +1372,7 @@ static int sony_nc_add(struct acpi_device *device) | |||
1131 | sony_laptop_remove_input(); | 1372 | sony_laptop_remove_input(); |
1132 | 1373 | ||
1133 | outwalk: | 1374 | outwalk: |
1375 | sony_nc_rfkill_cleanup(); | ||
1134 | return result; | 1376 | return result; |
1135 | } | 1377 | } |
1136 | 1378 | ||
@@ -1156,6 +1398,7 @@ static int sony_nc_remove(struct acpi_device *device, int type) | |||
1156 | 1398 | ||
1157 | sony_pf_remove(); | 1399 | sony_pf_remove(); |
1158 | sony_laptop_remove_input(); | 1400 | sony_laptop_remove_input(); |
1401 | sony_nc_rfkill_cleanup(); | ||
1159 | dprintk(SONY_NC_DRIVER_NAME " removed.\n"); | 1402 | dprintk(SONY_NC_DRIVER_NAME " removed.\n"); |
1160 | 1403 | ||
1161 | return 0; | 1404 | return 0; |
@@ -1195,7 +1438,6 @@ static struct acpi_driver sony_nc_driver = { | |||
1195 | #define SONYPI_TYPE1_OFFSET 0x04 | 1438 | #define SONYPI_TYPE1_OFFSET 0x04 |
1196 | #define SONYPI_TYPE2_OFFSET 0x12 | 1439 | #define SONYPI_TYPE2_OFFSET 0x12 |
1197 | #define SONYPI_TYPE3_OFFSET 0x12 | 1440 | #define SONYPI_TYPE3_OFFSET 0x12 |
1198 | #define SONYPI_TYPE4_OFFSET 0x12 | ||
1199 | 1441 | ||
1200 | struct sony_pic_ioport { | 1442 | struct sony_pic_ioport { |
1201 | struct acpi_resource_io io1; | 1443 | struct acpi_resource_io io1; |
@@ -1328,6 +1570,7 @@ static struct sonypi_event sonypi_pkeyev[] = { | |||
1328 | { 0x01, SONYPI_EVENT_PKEY_P1 }, | 1570 | { 0x01, SONYPI_EVENT_PKEY_P1 }, |
1329 | { 0x02, SONYPI_EVENT_PKEY_P2 }, | 1571 | { 0x02, SONYPI_EVENT_PKEY_P2 }, |
1330 | { 0x04, SONYPI_EVENT_PKEY_P3 }, | 1572 | { 0x04, SONYPI_EVENT_PKEY_P3 }, |
1573 | { 0x20, SONYPI_EVENT_PKEY_P1 }, | ||
1331 | { 0, 0 } | 1574 | { 0, 0 } |
1332 | }; | 1575 | }; |
1333 | 1576 | ||
@@ -1371,6 +1614,7 @@ static struct sonypi_event sonypi_zoomev[] = { | |||
1371 | { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, | 1614 | { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, |
1372 | { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, | 1615 | { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, |
1373 | { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, | 1616 | { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, |
1617 | { 0x04, SONYPI_EVENT_ZOOM_PRESSED }, | ||
1374 | { 0, 0 } | 1618 | { 0, 0 } |
1375 | }; | 1619 | }; |
1376 | 1620 | ||
@@ -1401,6 +1645,19 @@ static struct sonypi_event sonypi_batteryev[] = { | |||
1401 | { 0, 0 } | 1645 | { 0, 0 } |
1402 | }; | 1646 | }; |
1403 | 1647 | ||
1648 | /* The set of possible volume events */ | ||
1649 | static struct sonypi_event sonypi_volumeev[] = { | ||
1650 | { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED }, | ||
1651 | { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED }, | ||
1652 | { 0, 0 } | ||
1653 | }; | ||
1654 | |||
1655 | /* The set of possible brightness events */ | ||
1656 | static struct sonypi_event sonypi_brightnessev[] = { | ||
1657 | { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED }, | ||
1658 | { 0, 0 } | ||
1659 | }; | ||
1660 | |||
1404 | static struct sonypi_eventtypes type1_events[] = { | 1661 | static struct sonypi_eventtypes type1_events[] = { |
1405 | { 0, 0xffffffff, sonypi_releaseev }, | 1662 | { 0, 0xffffffff, sonypi_releaseev }, |
1406 | { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, | 1663 | { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, |
@@ -1438,17 +1695,11 @@ static struct sonypi_eventtypes type3_events[] = { | |||
1438 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1695 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1439 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1696 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1440 | { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1697 | { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1441 | { 0 }, | ||
1442 | }; | ||
1443 | static struct sonypi_eventtypes type4_events[] = { | ||
1444 | { 0, 0xffffffff, sonypi_releaseev }, | ||
1445 | { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | ||
1446 | { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, | ||
1447 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | ||
1448 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | ||
1449 | { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1698 | { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1450 | { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, | 1699 | { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, |
1451 | { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, | 1700 | { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, |
1701 | { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev }, | ||
1702 | { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev }, | ||
1452 | { 0 }, | 1703 | { 0 }, |
1453 | }; | 1704 | }; |
1454 | 1705 | ||
@@ -1511,11 +1762,11 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) | |||
1511 | /* | 1762 | /* |
1512 | * minidrivers for SPIC models | 1763 | * minidrivers for SPIC models |
1513 | */ | 1764 | */ |
1514 | static int type4_handle_irq(const u8 data_mask, const u8 ev) | 1765 | static int type3_handle_irq(const u8 data_mask, const u8 ev) |
1515 | { | 1766 | { |
1516 | /* | 1767 | /* |
1517 | * 0x31 could mean we have to take some extra action and wait for | 1768 | * 0x31 could mean we have to take some extra action and wait for |
1518 | * the next irq for some Type4 models, it will generate a new | 1769 | * the next irq for some Type3 models, it will generate a new |
1519 | * irq and we can read new data from the device: | 1770 | * irq and we can read new data from the device: |
1520 | * - 0x5c and 0x5f requires 0xA0 | 1771 | * - 0x5c and 0x5f requires 0xA0 |
1521 | * - 0x61 requires 0xB3 | 1772 | * - 0x61 requires 0xB3 |
@@ -1545,16 +1796,10 @@ static struct device_ctrl spic_types[] = { | |||
1545 | }, | 1796 | }, |
1546 | { | 1797 | { |
1547 | .model = SONYPI_DEVICE_TYPE3, | 1798 | .model = SONYPI_DEVICE_TYPE3, |
1548 | .handle_irq = NULL, | 1799 | .handle_irq = type3_handle_irq, |
1549 | .evport_offset = SONYPI_TYPE3_OFFSET, | 1800 | .evport_offset = SONYPI_TYPE3_OFFSET, |
1550 | .event_types = type3_events, | 1801 | .event_types = type3_events, |
1551 | }, | 1802 | }, |
1552 | { | ||
1553 | .model = SONYPI_DEVICE_TYPE4, | ||
1554 | .handle_irq = type4_handle_irq, | ||
1555 | .evport_offset = SONYPI_TYPE4_OFFSET, | ||
1556 | .event_types = type4_events, | ||
1557 | }, | ||
1558 | }; | 1803 | }; |
1559 | 1804 | ||
1560 | static void sony_pic_detect_device_type(struct sony_pic_dev *dev) | 1805 | static void sony_pic_detect_device_type(struct sony_pic_dev *dev) |
@@ -1578,14 +1823,21 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev) | |||
1578 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1823 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1579 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL); | 1824 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL); |
1580 | if (pcidev) { | 1825 | if (pcidev) { |
1581 | dev->control = &spic_types[3]; | 1826 | dev->control = &spic_types[2]; |
1582 | goto out; | 1827 | goto out; |
1583 | } | 1828 | } |
1584 | 1829 | ||
1585 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1830 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1586 | PCI_DEVICE_ID_INTEL_ICH8_4, NULL); | 1831 | PCI_DEVICE_ID_INTEL_ICH8_4, NULL); |
1587 | if (pcidev) { | 1832 | if (pcidev) { |
1588 | dev->control = &spic_types[3]; | 1833 | dev->control = &spic_types[2]; |
1834 | goto out; | ||
1835 | } | ||
1836 | |||
1837 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1838 | PCI_DEVICE_ID_INTEL_ICH9_1, NULL); | ||
1839 | if (pcidev) { | ||
1840 | dev->control = &spic_types[2]; | ||
1589 | goto out; | 1841 | goto out; |
1590 | } | 1842 | } |
1591 | 1843 | ||
@@ -1598,8 +1850,7 @@ out: | |||
1598 | 1850 | ||
1599 | printk(KERN_INFO DRV_PFX "detected Type%d model\n", | 1851 | printk(KERN_INFO DRV_PFX "detected Type%d model\n", |
1600 | dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : | 1852 | dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : |
1601 | dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : | 1853 | dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); |
1602 | dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); | ||
1603 | } | 1854 | } |
1604 | 1855 | ||
1605 | /* camera tests and poweron/poweroff */ | 1856 | /* camera tests and poweron/poweroff */ |
@@ -1754,17 +2005,14 @@ int sony_pic_camera_command(int command, u8 value) | |||
1754 | EXPORT_SYMBOL(sony_pic_camera_command); | 2005 | EXPORT_SYMBOL(sony_pic_camera_command); |
1755 | 2006 | ||
1756 | /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ | 2007 | /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ |
1757 | static void sony_pic_set_wwanpower(u8 state) | 2008 | static void __sony_pic_set_wwanpower(u8 state) |
1758 | { | 2009 | { |
1759 | state = !!state; | 2010 | state = !!state; |
1760 | mutex_lock(&spic_dev.lock); | 2011 | if (spic_dev.wwan_power == state) |
1761 | if (spic_dev.wwan_power == state) { | ||
1762 | mutex_unlock(&spic_dev.lock); | ||
1763 | return; | 2012 | return; |
1764 | } | ||
1765 | sony_pic_call2(0xB0, state); | 2013 | sony_pic_call2(0xB0, state); |
2014 | sony_pic_call1(0x82); | ||
1766 | spic_dev.wwan_power = state; | 2015 | spic_dev.wwan_power = state; |
1767 | mutex_unlock(&spic_dev.lock); | ||
1768 | } | 2016 | } |
1769 | 2017 | ||
1770 | static ssize_t sony_pic_wwanpower_store(struct device *dev, | 2018 | static ssize_t sony_pic_wwanpower_store(struct device *dev, |
@@ -1776,7 +2024,9 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev, | |||
1776 | return -EINVAL; | 2024 | return -EINVAL; |
1777 | 2025 | ||
1778 | value = simple_strtoul(buffer, NULL, 10); | 2026 | value = simple_strtoul(buffer, NULL, 10); |
1779 | sony_pic_set_wwanpower(value); | 2027 | mutex_lock(&spic_dev.lock); |
2028 | __sony_pic_set_wwanpower(value); | ||
2029 | mutex_unlock(&spic_dev.lock); | ||
1780 | 2030 | ||
1781 | return count; | 2031 | return count; |
1782 | } | 2032 | } |
@@ -1934,10 +2184,15 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) | |||
1934 | static int sonypi_misc_open(struct inode *inode, struct file *file) | 2184 | static int sonypi_misc_open(struct inode *inode, struct file *file) |
1935 | { | 2185 | { |
1936 | /* Flush input queue on first open */ | 2186 | /* Flush input queue on first open */ |
1937 | lock_kernel(); | 2187 | unsigned long flags; |
2188 | |||
2189 | spin_lock_irqsave(sonypi_compat.fifo->lock, flags); | ||
2190 | |||
1938 | if (atomic_inc_return(&sonypi_compat.open_count) == 1) | 2191 | if (atomic_inc_return(&sonypi_compat.open_count) == 1) |
1939 | kfifo_reset(sonypi_compat.fifo); | 2192 | __kfifo_reset(sonypi_compat.fifo); |
1940 | unlock_kernel(); | 2193 | |
2194 | spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); | ||
2195 | |||
1941 | return 0; | 2196 | return 0; |
1942 | } | 2197 | } |
1943 | 2198 | ||
@@ -1990,8 +2245,8 @@ static int ec_read16(u8 addr, u16 *value) | |||
1990 | return 0; | 2245 | return 0; |
1991 | } | 2246 | } |
1992 | 2247 | ||
1993 | static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, | 2248 | static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, |
1994 | unsigned int cmd, unsigned long arg) | 2249 | unsigned long arg) |
1995 | { | 2250 | { |
1996 | int ret = 0; | 2251 | int ret = 0; |
1997 | void __user *argp = (void __user *)arg; | 2252 | void __user *argp = (void __user *)arg; |
@@ -2125,7 +2380,7 @@ static const struct file_operations sonypi_misc_fops = { | |||
2125 | .open = sonypi_misc_open, | 2380 | .open = sonypi_misc_open, |
2126 | .release = sonypi_misc_release, | 2381 | .release = sonypi_misc_release, |
2127 | .fasync = sonypi_misc_fasync, | 2382 | .fasync = sonypi_misc_fasync, |
2128 | .ioctl = sonypi_misc_ioctl, | 2383 | .unlocked_ioctl = sonypi_misc_ioctl, |
2129 | }; | 2384 | }; |
2130 | 2385 | ||
2131 | static struct miscdevice sonypi_misc_device = { | 2386 | static struct miscdevice sonypi_misc_device = { |
@@ -2566,7 +2821,7 @@ static int sony_pic_add(struct acpi_device *device) | |||
2566 | result = sony_pic_possible_resources(device); | 2821 | result = sony_pic_possible_resources(device); |
2567 | if (result) { | 2822 | if (result) { |
2568 | printk(KERN_ERR DRV_PFX | 2823 | printk(KERN_ERR DRV_PFX |
2569 | "Unabe to read possible resources.\n"); | 2824 | "Unable to read possible resources.\n"); |
2570 | goto err_free_resources; | 2825 | goto err_free_resources; |
2571 | } | 2826 | } |
2572 | 2827 | ||
@@ -2574,7 +2829,7 @@ static int sony_pic_add(struct acpi_device *device) | |||
2574 | result = sony_laptop_setup_input(device); | 2829 | result = sony_laptop_setup_input(device); |
2575 | if (result) { | 2830 | if (result) { |
2576 | printk(KERN_ERR DRV_PFX | 2831 | printk(KERN_ERR DRV_PFX |
2577 | "Unabe to create input devices.\n"); | 2832 | "Unable to create input devices.\n"); |
2578 | goto err_free_resources; | 2833 | goto err_free_resources; |
2579 | } | 2834 | } |
2580 | 2835 | ||