aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/acer-wmi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-31 19:10:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-31 19:10:33 -0400
commit91e67a996c60a347ad7b918a74efb0f6b3b274c3 (patch)
tree05fd872079b1199d112cc7508faf81b8490dd83f /drivers/platform/x86/acer-wmi.c
parent1eb63378354ac37b7e27d256bbf84684751bac32 (diff)
parent1d1fc8a75fec3a2b29cc5864d45c5d03048f62e0 (diff)
Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86
* 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: (45 commits) acer-wmi: replaced the hard coded bitmap by the communication devices bitmap from SMBIOS acer-wmi: check the existence of internal wireless device when set capability acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks sony-laptop:irq: Remove IRQF_DISABLED asus-laptop: Add rfkill support for Pegatron Lucid tablet asus-laptop: pega_accel - Report accelerometer orientation change through udev asus-laptop: fix module description asus-laptop: hide leds on Pegatron Lucid asus-laptop: Pegatron Lucid accelerometer asus-laptop: allow boot time control of Pegatron ALS sensor Platform: samsung_laptop: add support for X520 machines. platform: samsung_laptop: add dmi information for Samsung R700 laptops hp_accel: Add axis-mapping for HP ProBook / EliteBook hp_accel: Add a new PNP id WMI: properly cleanup devices to avoid crashes ideapad: remove sysfs node for cfg ideapad: add debugfs support ideapad: add event for Novo key ideapad: change parameter of ideapad_sync_rfk_state ideapad: define vpc commands ...
Diffstat (limited to 'drivers/platform/x86/acer-wmi.c')
-rw-r--r--drivers/platform/x86/acer-wmi.c488
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;
205static int force_series; 206static int force_series;
206static bool ec_raw_mode; 207static bool ec_raw_mode;
207static bool has_type_aa; 208static bool has_type_aa;
209static u16 commun_func_bitmap;
208 210
209module_param(mailled, int, 0444); 211module_param(mailled, int, 0444);
210module_param(brightness, int, 0444); 212module_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
882static 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 &params
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
930static 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
950static 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 &params
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
1030static 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
871static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) 1050static 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
1115static 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
1098static 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 &params
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
1145static 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
1170static 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 &params
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
1253static 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
1360static int acer_rfkill_init(struct device *dev) 1375static 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
1417error_threeg:
1418 if (has_cap(ACER_CAP_BLUETOOTH)) {
1419 rfkill_unregister(bluetooth_rfkill);
1420 rfkill_destroy(bluetooth_rfkill);
1421 }
1422error_bluetooth:
1423 if (has_cap(ACER_CAP_WIRELESS)) {
1424 rfkill_unregister(wireless_rfkill);
1425 rfkill_destroy(wireless_rfkill);
1426 }
1427error_wireless:
1428 return err;
1398} 1429}
1399 1430
1400static void acer_rfkill_exit(void) 1431static 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");