diff options
| author | Lee, Chun-Yi <joeyli.kernel@gmail.com> | 2011-08-18 06:47:32 -0400 |
|---|---|---|
| committer | Matthew Garrett <mjg@redhat.com> | 2011-10-24 10:52:42 -0400 |
| commit | 72e71de15fceb0fd7cdfd8bb35f4f8aa8b0e20b5 (patch) | |
| tree | 4cc927743212e1b6743003255b977b396adffd4d /drivers | |
| parent | 6a0d89c2641671a5d29d262dbc7db8e403b543be (diff) | |
acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks
There have new acer notebooks' BIOS provide new WMID_GUID3 and
ACERWMID_EVENT_GUID methods.
Some of machines still keep the old WMID_GUID1 method but more and
more machines were already removed old wmi methods from DSDT.
So, this patch add a new ACER_WMID_v2 interface flag to represent
new acer notebooks, the following is definition:
+ ACER_WMID:
It means this machine only provides WMID_GUID1/2 methods.
+ ACER_WMID_v2:
It means this machine provide new WMID_GUID3 and WMID_EVENT_GUID
methods.
Some ACER_WMID_v2 machines also provide old WMID_GUID1/2 methods,
but we still query/set communication device's state by new
WMID_GUID3 method.
Tested on Acer Travelmate 8572
Tested on Acer Aspire 4739Z
Tested-by: AceLan Kao <acelan.kao@canonical.com>
Cc: Carlos Corbacho <carlos@strangeworlds.co.uk>
Cc: Matthew Garrett <mjg@redhat.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
Cc: Corentin Chary <corentincj@iksaif.net>
Cc: Thomas Renninger <trenn@suse.de>
Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/platform/x86/acer-wmi.c | 416 |
1 files changed, 213 insertions, 203 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index fc7c9733bba5..017b1a7eac8e 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -190,6 +190,7 @@ enum interface_flags { | |||
| 190 | ACER_AMW0, | 190 | ACER_AMW0, |
| 191 | ACER_AMW0_V2, | 191 | ACER_AMW0_V2, |
| 192 | ACER_WMID, | 192 | ACER_WMID, |
| 193 | ACER_WMID_v2, | ||
| 193 | }; | 194 | }; |
| 194 | 195 | ||
| 195 | #define ACER_DEFAULT_WIRELESS 0 | 196 | #define ACER_DEFAULT_WIRELESS 0 |
| @@ -877,6 +878,177 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
| 877 | return WMI_execute_u32(method_id, (u32)value, NULL); | 878 | return WMI_execute_u32(method_id, (u32)value, NULL); |
| 878 | } | 879 | } |
| 879 | 880 | ||
| 881 | static acpi_status wmid3_get_device_status(u32 *value, u16 device) | ||
| 882 | { | ||
| 883 | struct wmid3_gds_return_value return_value; | ||
| 884 | acpi_status status; | ||
| 885 | union acpi_object *obj; | ||
| 886 | struct wmid3_gds_input_param params = { | ||
| 887 | .function_num = 0x1, | ||
| 888 | .hotkey_number = 0x01, | ||
| 889 | .devices = device, | ||
| 890 | }; | ||
| 891 | struct acpi_buffer input = { | ||
| 892 | sizeof(struct wmid3_gds_input_param), | ||
| 893 | ¶ms | ||
| 894 | }; | ||
| 895 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 896 | |||
| 897 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); | ||
| 898 | if (ACPI_FAILURE(status)) | ||
| 899 | return status; | ||
| 900 | |||
| 901 | obj = output.pointer; | ||
| 902 | |||
| 903 | if (!obj) | ||
| 904 | return AE_ERROR; | ||
| 905 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
| 906 | kfree(obj); | ||
| 907 | return AE_ERROR; | ||
| 908 | } | ||
| 909 | if (obj->buffer.length != 8) { | ||
| 910 | pr_warn("Unknown buffer length %d\n", obj->buffer.length); | ||
| 911 | kfree(obj); | ||
| 912 | return AE_ERROR; | ||
| 913 | } | ||
| 914 | |||
| 915 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
| 916 | kfree(obj); | ||
| 917 | |||
| 918 | if (return_value.error_code || return_value.ec_return_value) | ||
| 919 | pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n", | ||
| 920 | device, | ||
| 921 | return_value.error_code, | ||
| 922 | return_value.ec_return_value); | ||
| 923 | else | ||
| 924 | *value = !!(return_value.devices & device); | ||
| 925 | |||
| 926 | return status; | ||
| 927 | } | ||
| 928 | |||
| 929 | static acpi_status wmid_v2_get_u32(u32 *value, u32 cap) | ||
| 930 | { | ||
| 931 | u16 device; | ||
| 932 | |||
| 933 | switch (cap) { | ||
| 934 | case ACER_CAP_WIRELESS: | ||
| 935 | device = ACER_WMID3_GDS_WIRELESS; | ||
| 936 | break; | ||
| 937 | case ACER_CAP_BLUETOOTH: | ||
| 938 | device = ACER_WMID3_GDS_BLUETOOTH; | ||
| 939 | break; | ||
| 940 | case ACER_CAP_THREEG: | ||
| 941 | device = ACER_WMID3_GDS_THREEG; | ||
| 942 | break; | ||
| 943 | default: | ||
| 944 | return AE_ERROR; | ||
| 945 | } | ||
| 946 | return wmid3_get_device_status(value, device); | ||
| 947 | } | ||
| 948 | |||
| 949 | static acpi_status wmid3_set_device_status(u32 value, u16 device) | ||
| 950 | { | ||
| 951 | struct wmid3_gds_return_value return_value; | ||
| 952 | acpi_status status; | ||
| 953 | union acpi_object *obj; | ||
| 954 | u16 devices; | ||
| 955 | struct wmid3_gds_input_param params = { | ||
| 956 | .function_num = 0x1, | ||
| 957 | .hotkey_number = 0x01, | ||
| 958 | .devices = ACER_WMID3_GDS_WIRELESS | | ||
| 959 | ACER_WMID3_GDS_THREEG | | ||
| 960 | ACER_WMID3_GDS_WIMAX | | ||
| 961 | ACER_WMID3_GDS_BLUETOOTH, | ||
| 962 | }; | ||
| 963 | struct acpi_buffer input = { | ||
| 964 | sizeof(struct wmid3_gds_input_param), | ||
| 965 | ¶ms | ||
| 966 | }; | ||
| 967 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 968 | struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 969 | |||
| 970 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); | ||
| 971 | if (ACPI_FAILURE(status)) | ||
| 972 | return status; | ||
| 973 | |||
| 974 | obj = output.pointer; | ||
| 975 | |||
| 976 | if (!obj) | ||
| 977 | return AE_ERROR; | ||
| 978 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
| 979 | kfree(obj); | ||
| 980 | return AE_ERROR; | ||
| 981 | } | ||
| 982 | if (obj->buffer.length != 8) { | ||
| 983 | pr_warning("Unknown buffer length %d\n", obj->buffer.length); | ||
| 984 | kfree(obj); | ||
| 985 | return AE_ERROR; | ||
| 986 | } | ||
| 987 | |||
| 988 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
| 989 | kfree(obj); | ||
| 990 | |||
| 991 | if (return_value.error_code || return_value.ec_return_value) { | ||
| 992 | pr_warning("Get Current Device Status failed: " | ||
| 993 | "0x%x - 0x%x\n", return_value.error_code, | ||
| 994 | return_value.ec_return_value); | ||
| 995 | return status; | ||
| 996 | } | ||
| 997 | |||
| 998 | devices = return_value.devices; | ||
| 999 | params.function_num = 0x2; | ||
| 1000 | params.hotkey_number = 0x01; | ||
| 1001 | params.devices = (value) ? (devices | device) : (devices & ~device); | ||
| 1002 | |||
| 1003 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2); | ||
| 1004 | if (ACPI_FAILURE(status)) | ||
| 1005 | return status; | ||
| 1006 | |||
| 1007 | obj = output2.pointer; | ||
| 1008 | |||
| 1009 | if (!obj) | ||
| 1010 | return AE_ERROR; | ||
| 1011 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
| 1012 | kfree(obj); | ||
| 1013 | return AE_ERROR; | ||
| 1014 | } | ||
| 1015 | if (obj->buffer.length != 4) { | ||
| 1016 | pr_warning("Unknown buffer length %d\n", obj->buffer.length); | ||
| 1017 | kfree(obj); | ||
| 1018 | return AE_ERROR; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
| 1022 | kfree(obj); | ||
| 1023 | |||
| 1024 | if (return_value.error_code || return_value.ec_return_value) | ||
| 1025 | pr_warning("Set Device Status failed: " | ||
| 1026 | "0x%x - 0x%x\n", return_value.error_code, | ||
| 1027 | return_value.ec_return_value); | ||
| 1028 | |||
| 1029 | return status; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | static acpi_status wmid_v2_set_u32(u32 value, u32 cap) | ||
| 1033 | { | ||
| 1034 | u16 device; | ||
| 1035 | |||
| 1036 | switch (cap) { | ||
| 1037 | case ACER_CAP_WIRELESS: | ||
| 1038 | device = ACER_WMID3_GDS_WIRELESS; | ||
| 1039 | break; | ||
| 1040 | case ACER_CAP_BLUETOOTH: | ||
| 1041 | device = ACER_WMID3_GDS_BLUETOOTH; | ||
| 1042 | break; | ||
| 1043 | case ACER_CAP_THREEG: | ||
| 1044 | device = ACER_WMID3_GDS_THREEG; | ||
| 1045 | break; | ||
| 1046 | default: | ||
| 1047 | return AE_ERROR; | ||
| 1048 | } | ||
| 1049 | return wmid3_set_device_status(value, device); | ||
| 1050 | } | ||
| 1051 | |||
| 880 | static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | 1052 | static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) |
| 881 | { | 1053 | { |
