diff options
Diffstat (limited to 'drivers/platform/x86/acer-wmi.c')
-rw-r--r-- | drivers/platform/x86/acer-wmi.c | 488 |
1 files changed, 264 insertions, 224 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index af2bb20cb2fb..b848277171a4 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 |
@@ -205,6 +206,7 @@ static int threeg = -1; | |||
205 | static int force_series; | 206 | static int force_series; |
206 | static bool ec_raw_mode; | 207 | static bool ec_raw_mode; |
207 | static bool has_type_aa; | 208 | static bool has_type_aa; |
209 | static u16 commun_func_bitmap; | ||
208 | 210 | ||
209 | module_param(mailled, int, 0444); | 211 | module_param(mailled, int, 0444); |
210 | module_param(brightness, int, 0444); | 212 | module_param(brightness, int, 0444); |
@@ -464,6 +466,15 @@ static struct dmi_system_id acer_quirks[] = { | |||
464 | }, | 466 | }, |
465 | .driver_data = &quirk_lenovo_ideapad_s205, | 467 | .driver_data = &quirk_lenovo_ideapad_s205, |
466 | }, | 468 | }, |
469 | { | ||
470 | .callback = dmi_matched, | ||
471 | .ident = "Lenovo 3000 N200", | ||
472 | .matches = { | ||
473 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
474 | DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"), | ||
475 | }, | ||
476 | .driver_data = &quirk_fujitsu_amilo_li_1718, | ||
477 | }, | ||
467 | {} | 478 | {} |
468 | }; | 479 | }; |
469 | 480 | ||
@@ -868,6 +879,174 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
868 | return WMI_execute_u32(method_id, (u32)value, NULL); | 879 | return WMI_execute_u32(method_id, (u32)value, NULL); |
869 | } | 880 | } |
870 | 881 | ||
882 | static acpi_status wmid3_get_device_status(u32 *value, u16 device) | ||
883 | { | ||
884 | struct wmid3_gds_return_value return_value; | ||
885 | acpi_status status; | ||
886 | union acpi_object *obj; | ||
887 | struct wmid3_gds_input_param params = { | ||
888 | .function_num = 0x1, | ||
889 | .hotkey_number = 0x01, | ||
890 | .devices = device, | ||
891 | }; | ||
892 | struct acpi_buffer input = { | ||
893 | sizeof(struct wmid3_gds_input_param), | ||
894 | ¶ms | ||
895 | }; | ||
896 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
897 | |||
898 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); | ||
899 | if (ACPI_FAILURE(status)) | ||
900 | return status; | ||
901 | |||
902 | obj = output.pointer; | ||
903 | |||
904 | if (!obj) | ||
905 | return AE_ERROR; | ||
906 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
907 | kfree(obj); | ||
908 | return AE_ERROR; | ||
909 | } | ||
910 | if (obj->buffer.length != 8) { | ||
911 | pr_warn("Unknown buffer length %d\n", obj->buffer.length); | ||
912 | kfree(obj); | ||
913 | return AE_ERROR; | ||
914 | } | ||
915 | |||
916 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
917 | kfree(obj); | ||
918 | |||
919 | if (return_value.error_code || return_value.ec_return_value) | ||
920 | pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n", | ||
921 | device, | ||
922 | return_value.error_code, | ||
923 | return_value.ec_return_value); | ||
924 | else | ||
925 | *value = !!(return_value.devices & device); | ||
926 | |||
927 | return status; | ||
928 | } | ||
929 | |||
930 | static acpi_status wmid_v2_get_u32(u32 *value, u32 cap) | ||
931 | { | ||
932 | u16 device; | ||
933 | |||
934 | switch (cap) { | ||
935 | case ACER_CAP_WIRELESS: | ||
936 | device = ACER_WMID3_GDS_WIRELESS; | ||
937 | break; | ||
938 | case ACER_CAP_BLUETOOTH: | ||
939 | device = ACER_WMID3_GDS_BLUETOOTH; | ||
940 | break; | ||
941 | case ACER_CAP_THREEG: | ||
942 | device = ACER_WMID3_GDS_THREEG; | ||
943 | break; | ||
944 | default: | ||
945 | return AE_ERROR; | ||
946 | } | ||
947 | return wmid3_get_device_status(value, device); | ||
948 | } | ||
949 | |||
950 | static acpi_status wmid3_set_device_status(u32 value, u16 device) | ||
951 | { | ||
952 | struct wmid3_gds_return_value return_value; | ||
953 | acpi_status status; | ||
954 | union acpi_object *obj; | ||
955 | u16 devices; | ||
956 | struct wmid3_gds_input_param params = { | ||
957 | .function_num = 0x1, | ||
958 | .hotkey_number = 0x01, | ||
959 | .devices = commun_func_bitmap, | ||
960 | }; | ||
961 | struct acpi_buffer input = { | ||
962 | sizeof(struct wmid3_gds_input_param), | ||
963 | ¶ms | ||
964 | }; | ||
965 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
966 | struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
967 | |||
968 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); | ||
969 | if (ACPI_FAILURE(status)) | ||
970 | return status; | ||
971 | |||
972 | obj = output.pointer; | ||
973 | |||
974 | if (!obj) | ||
975 | return AE_ERROR; | ||
976 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
977 | kfree(obj); | ||
978 | return AE_ERROR; | ||
979 | } | ||
980 | if (obj->buffer.length != 8) { | ||
981 | pr_warning("Unknown buffer length %d\n", obj->buffer.length); | ||
982 | kfree(obj); | ||
983 | return AE_ERROR; | ||
984 | } | ||
985 | |||
986 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
987 | kfree(obj); | ||
988 | |||
989 | if (return_value.error_code || return_value.ec_return_value) { | ||
990 | pr_warning("Get Current Device Status failed: " | ||
991 | "0x%x - 0x%x\n", return_value.error_code, | ||
992 | return_value.ec_return_value); | ||
993 | return status; | ||
994 | } | ||
995 | |||
996 | devices = return_value.devices; | ||
997 | params.function_num = 0x2; | ||
998 | params.hotkey_number = 0x01; | ||
999 | params.devices = (value) ? (devices | device) : (devices & ~device); | ||
1000 | |||
1001 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2); | ||
1002 | if (ACPI_FAILURE(status)) | ||
1003 | return status; | ||
1004 | |||
1005 | obj = output2.pointer; | ||
1006 | |||
1007 | if (!obj) | ||
1008 | return AE_ERROR; | ||
1009 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
1010 | kfree(obj); | ||
1011 | return AE_ERROR; | ||
1012 | } | ||
1013 | if (obj->buffer.length != 4) { | ||
1014 | pr_warning("Unknown buffer length %d\n", obj->buffer.length); | ||
1015 | kfree(obj); | ||
1016 | return AE_ERROR; | ||
1017 | } | ||
1018 | |||
1019 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
1020 | kfree(obj); | ||
1021 | |||
1022 | if (return_value.error_code || return_value.ec_return_value) | ||
1023 | pr_warning("Set Device Status failed: " | ||
1024 | "0x%x - 0x%x\n", return_value.error_code, | ||
1025 | return_value.ec_return_value); | ||
1026 | |||
1027 | return status; | ||
1028 | } | ||
1029 | |||
1030 | static acpi_status wmid_v2_set_u32(u32 value, u32 cap) | ||
1031 | { | ||
1032 | u16 device; | ||
1033 | |||
1034 | switch (cap) { | ||
1035 | case ACER_CAP_WIRELESS: | ||
1036 | device = ACER_WMID3_GDS_WIRELESS; | ||
1037 | break; | ||
1038 | case ACER_CAP_BLUETOOTH: | ||
1039 | device = ACER_WMID3_GDS_BLUETOOTH; | ||
1040 | break; | ||
1041 | case ACER_CAP_THREEG: | ||
1042 | device = ACER_WMID3_GDS_THREEG; | ||
1043 | break; | ||
1044 | default: | ||
1045 | return AE_ERROR; | ||
1046 | } | ||
1047 | return wmid3_set_device_status(value, device); | ||
1048 | } | ||
1049 | |||
871 | static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | 1050 | static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) |
872 | { | 1051 | { |
873 | struct hotkey_function_type_aa *type_aa; | 1052 | struct hotkey_function_type_aa *type_aa; |
@@ -881,6 +1060,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) | |||
881 | 1060 | ||
882 | pr_info("Function bitmap for Communication Button: 0x%x\n", | 1061 | pr_info("Function bitmap for Communication Button: 0x%x\n", |
883 | type_aa->commun_func_bitmap); | 1062 | type_aa->commun_func_bitmap); |
1063 | commun_func_bitmap = type_aa->commun_func_bitmap; | ||
884 | 1064 | ||
885 | if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS) | 1065 | if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS) |
886 | interface->capability |= ACER_CAP_WIRELESS; | 1066 | interface->capability |= ACER_CAP_WIRELESS; |
@@ -913,17 +1093,13 @@ static acpi_status WMID_set_capabilities(void) | |||
913 | return AE_ERROR; | 1093 | return AE_ERROR; |
914 | } | 1094 | } |
915 | 1095 | ||
916 | dmi_walk(type_aa_dmi_decode, NULL); | 1096 | pr_info("Function bitmap for Communication Device: 0x%x\n", devices); |
917 | if (!has_type_aa) { | 1097 | if (devices & 0x07) |
918 | interface->capability |= ACER_CAP_WIRELESS; | 1098 | interface->capability |= ACER_CAP_WIRELESS; |
919 | if (devices & 0x40) | 1099 | if (devices & 0x40) |
920 | interface->capability |= ACER_CAP_THREEG; | 1100 | interface->capability |= ACER_CAP_THREEG; |
921 | if (devices & 0x10) | 1101 | if (devices & 0x10) |
922 | interface->capability |= ACER_CAP_BLUETOOTH; | 1102 | interface->capability |= ACER_CAP_BLUETOOTH; |
923 | } | ||
924 | |||
925 | /* WMID always provides brightness methods */ | ||
926 | interface->capability |= ACER_CAP_BRIGHTNESS; | ||
927 | 1103 | ||
928 | if (!(devices & 0x20)) | 1104 | if (!(devices & 0x20)) |
929 | max_brightness = 0x9; | 1105 | max_brightness = 0x9; |
@@ -936,6 +1112,10 @@ static struct wmi_interface wmid_interface = { | |||
936 | .type = ACER_WMID, | 1112 | .type = ACER_WMID, |
937 | }; | 1113 | }; |
938 | 1114 | ||
1115 | static struct wmi_interface wmid_v2_interface = { | ||
1116 | .type = ACER_WMID_v2, | ||
1117 | }; | ||
1118 | |||
939 | /* | 1119 | /* |
940 | * Generic Device (interface-independent) | 1120 | * Generic Device (interface-independent) |
941 | */ | 1121 | */ |
@@ -956,6 +1136,14 @@ static acpi_status get_u32(u32 *value, u32 cap) | |||
956 | case ACER_WMID: | 1136 | case ACER_WMID: |
957 | status = WMID_get_u32(value, cap, interface); | 1137 | status = WMID_get_u32(value, cap, interface); |
958 | break; | 1138 | break; |
1139 | case ACER_WMID_v2: | ||
1140 | if (cap & (ACER_CAP_WIRELESS | | ||
1141 | ACER_CAP_BLUETOOTH | | ||
1142 | ACER_CAP_THREEG)) | ||
1143 | status = wmid_v2_get_u32(value, cap); | ||
1144 | else if (wmi_has_guid(WMID_GUID2)) | ||
1145 | status = WMID_get_u32(value, cap, interface); | ||
1146 | break; | ||
959 | } | 1147 | } |
960 | 1148 | ||
961 | return status; | 1149 | return status; |
@@ -989,6 +1177,13 @@ static acpi_status set_u32(u32 value, u32 cap) | |||
989 | } | 1177 | } |
990 | case ACER_WMID: | 1178 | case ACER_WMID: |
991 | return WMID_set_u32(value, cap, interface); | 1179 | return WMID_set_u32(value, cap, interface); |
1180 | case ACER_WMID_v2: | ||
1181 | if (cap & (ACER_CAP_WIRELESS | | ||
1182 | ACER_CAP_BLUETOOTH | | ||
1183 | ACER_CAP_THREEG)) | ||
1184 | return wmid_v2_set_u32(value, cap); | ||
1185 | else if (wmi_has_guid(WMID_GUID2)) | ||
1186 | return WMID_set_u32(value, cap, interface); | ||
992 | default: | 1187 | default: |
993 | return AE_BAD_PARAMETER; | 1188 | return AE_BAD_PARAMETER; |
994 | } | 1189 | } |
@@ -1095,186 +1290,6 @@ static void acer_backlight_exit(void) | |||
1095 | backlight_device_unregister(acer_backlight_device); | 1290 | backlight_device_unregister(acer_backlight_device); |
1096 | } | 1291 | } |
1097 | 1292 | ||
1098 | static acpi_status wmid3_get_device_status(u32 *value, u16 device) | ||
1099 | { | ||
1100 | struct wmid3_gds_return_value return_value; | ||
1101 | acpi_status status; | ||
1102 | union acpi_object *obj; | ||
1103 | struct wmid3_gds_input_param params = { | ||
1104 | .function_num = 0x1, | ||
1105 | .hotkey_number = 0x01, | ||
1106 | .devices = device, | ||
1107 | }; | ||
1108 | struct acpi_buffer input = { | ||
1109 | sizeof(struct wmid3_gds_input_param), | ||
1110 | ¶ms | ||
1111 | }; | ||
1112 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
1113 | |||
1114 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); | ||
1115 | if (ACPI_FAILURE(status)) | ||
1116 | return status; | ||
1117 | |||
1118 | obj = output.pointer; | ||
1119 | |||
1120 | if (!obj) | ||
1121 | return AE_ERROR; | ||
1122 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
1123 | kfree(obj); | ||
1124 | return AE_ERROR; | ||
1125 | } | ||
1126 | if (obj->buffer.length != 8) { | ||
1127 | pr_warn("Unknown buffer length %d\n", obj->buffer.length); | ||
1128 | kfree(obj); | ||
1129 | return AE_ERROR; | ||
1130 | } | ||
1131 | |||
1132 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
1133 | kfree(obj); | ||
1134 | |||
1135 | if (return_value.error_code || return_value.ec_return_value) | ||
1136 | pr_warn("Get Device Status failed: 0x%x - 0x%x\n", | ||
1137 | return_value.error_code, | ||
1138 | return_value.ec_return_value); | ||
1139 | else | ||
1140 | *value = !!(return_value.devices & device); | ||
1141 | |||
1142 | return status; | ||
1143 | } | ||
1144 | |||
1145 | static acpi_status get_device_status(u32 *value, u32 cap) | ||
1146 | { | ||
1147 | if (wmi_has_guid(WMID_GUID3)) { | ||
1148 | u16 device; | ||
1149 | |||
1150 | switch (cap) { | ||
1151 | case ACER_CAP_WIRELESS: | ||
1152 | device = ACER_WMID3_GDS_WIRELESS; | ||
1153 | break; | ||
1154 | case ACER_CAP_BLUETOOTH: | ||
1155 | device = ACER_WMID3_GDS_BLUETOOTH; | ||
1156 | break; | ||
1157 | case ACER_CAP_THREEG: | ||
1158 | device = ACER_WMID3_GDS_THREEG; | ||
1159 | break; | ||
1160 | default: | ||
1161 | return AE_ERROR; | ||
1162 | } | ||
1163 | return wmid3_get_device_status(value, device); | ||
1164 | |||
1165 | } else { | ||
1166 | return get_u32(value, cap); | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | static acpi_status wmid3_set_device_status(u32 value, u16 device) | ||
1171 | { | ||
1172 | struct wmid3_gds_return_value return_value; | ||
1173 | acpi_status status; | ||
1174 | union acpi_object *obj; | ||
1175 | u16 devices; | ||
1176 | struct wmid3_gds_input_param params = { | ||
1177 | .function_num = 0x1, | ||
1178 | .hotkey_number = 0x01, | ||
1179 | .devices = ACER_WMID3_GDS_WIRELESS | | ||
1180 | ACER_WMID3_GDS_THREEG | | ||
1181 | ACER_WMID3_GDS_WIMAX | | ||
1182 | ACER_WMID3_GDS_BLUETOOTH, | ||
1183 | }; | ||
1184 | struct acpi_buffer input = { | ||
1185 | sizeof(struct wmid3_gds_input_param), | ||
1186 | ¶ms | ||
1187 | }; | ||
1188 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
1189 | struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
1190 | |||
1191 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output); | ||
1192 | if (ACPI_FAILURE(status)) | ||
1193 | return status; | ||
1194 | |||
1195 | obj = output.pointer; | ||
1196 | |||
1197 | if (!obj) | ||
1198 | return AE_ERROR; | ||
1199 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
1200 | kfree(obj); | ||
1201 | return AE_ERROR; | ||
1202 | } | ||
1203 | if (obj->buffer.length != 8) { | ||
1204 | pr_warning("Unknown buffer length %d\n", obj->buffer.length); | ||
1205 | kfree(obj); | ||
1206 | return AE_ERROR; | ||
1207 | } | ||
1208 | |||
1209 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
1210 | kfree(obj); | ||
1211 | |||
1212 | if (return_value.error_code || return_value.ec_return_value) { | ||
1213 | pr_warning("Get Current Device Status failed: " | ||
1214 | "0x%x - 0x%x\n", return_value.error_code, | ||
1215 | return_value.ec_return_value); | ||
1216 | return status; | ||
1217 | } | ||
1218 | |||
1219 | devices = return_value.devices; | ||
1220 | params.function_num = 0x2; | ||
1221 | params.hotkey_number = 0x01; | ||
1222 | params.devices = (value) ? (devices | device) : (devices & ~device); | ||
1223 | |||
1224 | status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2); | ||
1225 | if (ACPI_FAILURE(status)) | ||
1226 | return status; | ||
1227 | |||
1228 | obj = output2.pointer; | ||
1229 | |||
1230 | if (!obj) | ||
1231 | return AE_ERROR; | ||
1232 | else if (obj->type != ACPI_TYPE_BUFFER) { | ||
1233 | kfree(obj); | ||
1234 | return AE_ERROR; | ||
1235 | } | ||
1236 | if (obj->buffer.length != 4) { | ||
1237 | pr_warning("Unknown buffer length %d\n", obj->buffer.length); | ||
1238 | kfree(obj); | ||
1239 | return AE_ERROR; | ||
1240 | } | ||
1241 | |||
1242 | return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer); | ||
1243 | kfree(obj); | ||
1244 | |||
1245 | if (return_value.error_code || return_value.ec_return_value) | ||
1246 | pr_warning("Set Device Status failed: " | ||
1247 | "0x%x - 0x%x\n", return_value.error_code, | ||
1248 | return_value.ec_return_value); | ||
1249 | |||
1250 | return status; | ||
1251 | } | ||
1252 | |||
1253 | static acpi_status set_device_status(u32 value, u32 cap) | ||
1254 | { | ||
1255 | if (wmi_has_guid(WMID_GUID3)) { | ||
1256 | u16 device; | ||
1257 | |||
1258 | switch (cap) { | ||
1259 | case ACER_CAP_WIRELESS: | ||
1260 | device = ACER_WMID3_GDS_WIRELESS; | ||
1261 | break; | ||
1262 | case ACER_CAP_BLUETOOTH: | ||
1263 | device = ACER_WMID3_GDS_BLUETOOTH; | ||
1264 | break; | ||
1265 | case ACER_CAP_THREEG: | ||
1266 | device = ACER_WMID3_GDS_THREEG; | ||
1267 | break; | ||
1268 | default: | ||
1269 | return AE_ERROR; | ||
1270 | } | ||
1271 | return wmid3_set_device_status(value, device); | ||
1272 | |||
1273 | } else { | ||
1274 | return set_u32(value, cap); | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | /* | 1293 | /* |
1279 | * Rfkill devices | 1294 | * Rfkill devices |
1280 | */ | 1295 | */ |
@@ -1285,12 +1300,13 @@ static void acer_rfkill_update(struct work_struct *ignored) | |||
1285 | u32 state; | 1300 | u32 state; |
1286 | acpi_status status; | 1301 | acpi_status status; |
1287 | 1302 | ||
1288 | status = get_u32(&state, ACER_CAP_WIRELESS); | 1303 | if (has_cap(ACER_CAP_WIRELESS)) { |
1289 | if (ACPI_SUCCESS(status)) { | 1304 | status = get_u32(&state, ACER_CAP_WIRELESS); |
1290 | if (quirks->wireless == 3) { | 1305 | if (ACPI_SUCCESS(status)) { |
1291 | rfkill_set_hw_state(wireless_rfkill, !state); | 1306 | if (quirks->wireless == 3) |
1292 | } else { | 1307 | rfkill_set_hw_state(wireless_rfkill, !state); |
1293 | rfkill_set_sw_state(wireless_rfkill, !state); | 1308 | else |
1309 | rfkill_set_sw_state(wireless_rfkill, !state); | ||
1294 | } | 1310 | } |
1295 | } | 1311 | } |
1296 | 1312 | ||
@@ -1301,8 +1317,7 @@ static void acer_rfkill_update(struct work_struct *ignored) | |||
1301 | } | 1317 | } |
1302 | 1318 | ||
1303 | if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) { | 1319 | if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) { |
1304 | status = wmid3_get_device_status(&state, | 1320 | status = get_u32(&state, ACER_WMID3_GDS_THREEG); |
1305 | ACER_WMID3_GDS_THREEG); | ||
1306 | if (ACPI_SUCCESS(status)) | 1321 | if (ACPI_SUCCESS(status)) |
1307 | rfkill_set_sw_state(threeg_rfkill, !state); | 1322 | rfkill_set_sw_state(threeg_rfkill, !state); |
1308 | } | 1323 | } |
@@ -1316,7 +1331,7 @@ static int acer_rfkill_set(void *data, bool blocked) | |||
1316 | u32 cap = (unsigned long)data; | 1331 | u32 cap = (unsigned long)data; |
1317 | 1332 | ||
1318 | if (rfkill_inited) { | 1333 | if (rfkill_inited) { |
1319 | status = set_device_status(!blocked, cap); | 1334 | status = set_u32(!blocked, cap); |
1320 | if (ACPI_FAILURE(status)) | 1335 | if (ACPI_FAILURE(status)) |
1321 | return -ENODEV; | 1336 | return -ENODEV; |
1322 | } | 1337 | } |
@@ -1343,7 +1358,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev, | |||
1343 | if (!rfkill_dev) | 1358 | if (!rfkill_dev) |
1344 | return ERR_PTR(-ENOMEM); | 1359 | return ERR_PTR(-ENOMEM); |
1345 | 1360 | ||
1346 | status = get_device_status(&state, cap); | 1361 | status = get_u32(&state, cap); |
1347 | 1362 | ||
1348 | err = rfkill_register(rfkill_dev); | 1363 | err = rfkill_register(rfkill_dev); |
1349 | if (err) { | 1364 | if (err) { |
@@ -1359,19 +1374,24 @@ static struct rfkill *acer_rfkill_register(struct device *dev, | |||
1359 | 1374 | ||
1360 | static int acer_rfkill_init(struct device *dev) | 1375 | static int acer_rfkill_init(struct device *dev) |
1361 | { | 1376 | { |
1362 | wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN, | 1377 | int err; |
1363 | "acer-wireless", ACER_CAP_WIRELESS); | 1378 | |
1364 | if (IS_ERR(wireless_rfkill)) | 1379 | if (has_cap(ACER_CAP_WIRELESS)) { |
1365 | return PTR_ERR(wireless_rfkill); | 1380 | wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN, |
1381 | "acer-wireless", ACER_CAP_WIRELESS); | ||
1382 | if (IS_ERR(wireless_rfkill)) { | ||
1383 | err = PTR_ERR(wireless_rfkill); | ||
1384 | goto error_wireless; | ||
1385 | } | ||
1386 | } | ||
1366 | 1387 | ||
1367 | if (has_cap(ACER_CAP_BLUETOOTH)) { | 1388 | if (has_cap(ACER_CAP_BLUETOOTH)) { |
1368 | bluetooth_rfkill = acer_rfkill_register(dev, | 1389 | bluetooth_rfkill = acer_rfkill_register(dev, |
1369 | RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", | 1390 | RFKILL_TYPE_BLUETOOTH, "acer-bluetooth", |
1370 | ACER_CAP_BLUETOOTH); | 1391 | ACER_CAP_BLUETOOTH); |
1371 | if (IS_ERR(bluetooth_rfkill)) { | 1392 | if (IS_ERR(bluetooth_rfkill)) { |
1372 | rfkill_unregister(wireless_rfkill); | 1393 | err = PTR_ERR(bluetooth_rfkill); |
1373 | rfkill_destroy(wireless_rfkill); | 1394 | goto error_bluetooth; |
1374 | return PTR_ERR(bluetooth_rfkill); | ||
1375 | } | 1395 | } |
1376 | } | 1396 | } |
1377 | 1397 | ||
@@ -1380,30 +1400,44 @@ static int acer_rfkill_init(struct device *dev) | |||
1380 | RFKILL_TYPE_WWAN, "acer-threeg", | 1400 | RFKILL_TYPE_WWAN, "acer-threeg", |
1381 | ACER_CAP_THREEG); | 1401 | ACER_CAP_THREEG); |
1382 | if (IS_ERR(threeg_rfkill)) { | 1402 | if (IS_ERR(threeg_rfkill)) { |
1383 | rfkill_unregister(wireless_rfkill); | 1403 | err = PTR_ERR(threeg_rfkill); |
1384 | rfkill_destroy(wireless_rfkill); | 1404 | goto error_threeg; |
1385 | rfkill_unregister(bluetooth_rfkill); | ||
1386 | rfkill_destroy(bluetooth_rfkill); | ||
1387 | return PTR_ERR(threeg_rfkill); | ||
1388 | } | 1405 | } |
1389 | } | 1406 | } |
1390 | 1407 | ||
1391 | rfkill_inited = true; | 1408 | rfkill_inited = true; |
1392 | 1409 | ||
1393 | if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) | 1410 | if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) && |
1411 | has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG)) | ||
1394 | schedule_delayed_work(&acer_rfkill_work, | 1412 | schedule_delayed_work(&acer_rfkill_work, |
1395 | round_jiffies_relative(HZ)); | 1413 | round_jiffies_relative(HZ)); |
1396 | 1414 | ||
1397 | return 0; | 1415 | return 0; |
1416 | |||
1417 | error_threeg: | ||
1418 | if (has_cap(ACER_CAP_BLUETOOTH)) { | ||
1419 | rfkill_unregister(bluetooth_rfkill); | ||
1420 | rfkill_destroy(bluetooth_rfkill); | ||
1421 | } | ||
1422 | error_bluetooth: | ||
1423 | if (has_cap(ACER_CAP_WIRELESS)) { | ||
1424 | rfkill_unregister(wireless_rfkill); | ||
1425 | rfkill_destroy(wireless_rfkill); | ||
1426 | } | ||
1427 | error_wireless: | ||
1428 | return err; | ||
1398 | } | 1429 | } |
1399 | 1430 | ||
1400 | static void acer_rfkill_exit(void) | 1431 | static void acer_rfkill_exit(void) |
1401 | { | 1432 | { |
1402 | if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) | 1433 | if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) && |
1434 | has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG)) | ||
1403 | cancel_delayed_work_sync(&acer_rfkill_work); | 1435 | cancel_delayed_work_sync(&acer_rfkill_work); |
1404 | 1436 | ||
1405 | rfkill_unregister(wireless_rfkill); | 1437 | if (has_cap(ACER_CAP_WIRELESS)) { |
1406 | rfkill_destroy(wireless_rfkill); | 1438 | rfkill_unregister(wireless_rfkill); |
1439 | rfkill_destroy(wireless_rfkill); | ||
1440 | } | ||
1407 | 1441 | ||
1408 | if (has_cap(ACER_CAP_BLUETOOTH)) { | 1442 | if (has_cap(ACER_CAP_BLUETOOTH)) { |
1409 | rfkill_unregister(bluetooth_rfkill); | 1443 | rfkill_unregister(bluetooth_rfkill); |
@@ -1428,11 +1462,7 @@ static ssize_t show_bool_threeg(struct device *dev, | |||
1428 | 1462 | ||
1429 | pr_info("This threeg sysfs will be removed in 2012" | 1463 | pr_info("This threeg sysfs will be removed in 2012" |
1430 | " - used by: %s\n", current->comm); | 1464 | " - used by: %s\n", current->comm); |
1431 | if (wmi_has_guid(WMID_GUID3)) | 1465 | status = get_u32(&result, ACER_CAP_THREEG); |
1432 | status = wmid3_get_device_status(&result, | ||
1433 | ACER_WMID3_GDS_THREEG); | ||
1434 | else | ||
1435 | status = get_u32(&result, ACER_CAP_THREEG); | ||
1436 | if (ACPI_SUCCESS(status)) | 1466 | if (ACPI_SUCCESS(status)) |
1437 | return sprintf(buf, "%u\n", result); | 1467 | return sprintf(buf, "%u\n", result); |
1438 | return sprintf(buf, "Read error\n"); | 1468 | return sprintf(buf, "Read error\n"); |
@@ -1464,6 +1494,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr, | |||
1464 | return sprintf(buf, "AMW0 v2\n"); | 1494 | return sprintf(buf, "AMW0 v2\n"); |
1465 | case ACER_WMID: | 1495 | case ACER_WMID: |
1466 | return sprintf(buf, "WMID\n"); | 1496 | return sprintf(buf, "WMID\n"); |
1497 | case ACER_WMID_v2: | ||
1498 | return sprintf(buf, "WMID v2\n"); | ||
1467 | default: | 1499 | default: |
1468 | return sprintf(buf, "Error!\n"); | 1500 | return sprintf(buf, "Error!\n"); |
1469 | } | 1501 | } |
@@ -1883,12 +1915,20 @@ static int __init acer_wmi_init(void) | |||
1883 | if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) | 1915 | if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) |
1884 | interface = &wmid_interface; | 1916 | interface = &wmid_interface; |
1885 | 1917 | ||
1918 | if (wmi_has_guid(WMID_GUID3)) | ||
1919 | interface = &wmid_v2_interface; | ||
1920 | |||
1921 | if (interface) | ||
1922 | dmi_walk(type_aa_dmi_decode, NULL); | ||
1923 | |||
1886 | if (wmi_has_guid(WMID_GUID2) && interface) { | 1924 | if (wmi_has_guid(WMID_GUID2) && interface) { |
1887 | if (ACPI_FAILURE(WMID_set_capabilities())) { | 1925 | if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) { |
1888 | pr_err("Unable to detect available WMID devices\n"); | 1926 | pr_err("Unable to detect available WMID devices\n"); |
1889 | return -ENODEV; | 1927 | return -ENODEV; |
1890 | } | 1928 | } |
1891 | } else if (!wmi_has_guid(WMID_GUID2) && interface) { | 1929 | /* WMID always provides brightness methods */ |
1930 | interface->capability |= ACER_CAP_BRIGHTNESS; | ||
1931 | } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) { | ||
1892 | pr_err("No WMID device detection method found\n"); | 1932 | pr_err("No WMID device detection method found\n"); |
1893 | return -ENODEV; | 1933 | return -ENODEV; |
1894 | } | 1934 | } |
@@ -1912,7 +1952,7 @@ static int __init acer_wmi_init(void) | |||
1912 | 1952 | ||
1913 | set_quirks(); | 1953 | set_quirks(); |
1914 | 1954 | ||
1915 | if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { | 1955 | if (acpi_video_backlight_support()) { |
1916 | interface->capability &= ~ACER_CAP_BRIGHTNESS; | 1956 | interface->capability &= ~ACER_CAP_BRIGHTNESS; |
1917 | pr_info("Brightness must be controlled by " | 1957 | pr_info("Brightness must be controlled by " |
1918 | "generic video driver\n"); | 1958 | "generic video driver\n"); |