aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/acer-wmi.c416
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
881static 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 &params
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
929static 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
949static 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 &params
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
1032static 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
880static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) 1052static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
881{ 1053{
882 struct hotkey_function_type_aa *type_aa; 1054 struct hotkey_function_type_aa *type_aa;
@@ -922,17 +1094,11 @@ static acpi_status WMID_set_capabilities(void)
922 return AE_ERROR; 1094 return AE_ERROR;
923 } 1095 }
924 1096
925 dmi_walk(type_aa_dmi_decode, NULL); 1097 interface->capability |= ACER_CAP_WIRELESS;
926 if (!has_type_aa) {