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) { 1098 if (devices & 0x40)
927 interface->capability |= ACER_CAP_WIRELESS; 1099 interface->capability |= ACER_CAP_THREEG;
928 if (devices & 0x40) 1100 if (devices & 0x10)
929 interface->capability |= ACER_CAP_THREEG; 1101 interface->capability |= ACER_CAP_BLUETOOTH;
930 if (devices & 0x10)
931 interface->capability |= ACER_CAP_BLUETOOTH;
932 }
933
934 /* WMID always provides brightness methods */
935 interface->capability |= ACER_CAP_BRIGHTNESS;
936 1102
937 if (!(devices & 0x20)) 1103 if (!(devices & 0x20))
938 max_brightness = 0x9; 1104 max_brightness = 0x9;
@@ -945,6 +1111,10 @@ static struct wmi_interface wmid_interface = {
945 .type = ACER_WMID, 1111 .type = ACER_WMID,
946}; 1112};
947 1113
1114static struct wmi_interface wmid_v2_interface = {
1115 .type = ACER_WMID_v2,
1116};
1117
948/* 1118/*
949 * Generic Device (interface-independent) 1119 * Generic Device (interface-independent)
950 */ 1120 */
@@ -965,6 +1135,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
965 case ACER_WMID: 1135 case ACER_WMID:
966 status = WMID_get_u32(value, cap, interface); 1136 status = WMID_get_u32(value, cap, interface);
967 break; 1137 break;
1138 case ACER_WMID_v2:
1139 if (cap & (ACER_CAP_WIRELESS |
1140 ACER_CAP_BLUETOOTH |
1141 ACER_CAP_THREEG))
1142 status = wmid_v2_get_u32(value, cap);
1143 else if (wmi_has_guid(WMID_GUID2))
1144 status = WMID_get_u32(value, cap, interface);
1145 break;
968 } 1146 }
969 1147
970 return status; 1148 return status;
@@ -998,6 +1176,13 @@ static acpi_status set_u32(u32 value, u32 cap)
998 } 1176 }
999 case ACER_WMID: 1177 case ACER_WMID:
1000 return WMID_set_u32(value, cap, interface); 1178 return WMID_set_u32(value, cap, interface);
1179 case ACER_WMID_v2:
1180 if (cap & (ACER_CAP_WIRELESS |
1181 ACER_CAP_BLUETOOTH |
1182 ACER_CAP_THREEG))
1183 return wmid_v2_set_u32(value, cap);
1184 else if (wmi_has_guid(WMID_GUID2))
1185 return WMID_set_u32(value, cap, interface);
1001 default: 1186 default:
1002 return AE_BAD_PARAMETER; 1187 return AE_BAD_PARAMETER;
1003 } 1188 }
@@ -1104,186 +1289,6 @@ static void acer_backlight_exit(void)
1104 backlight_device_unregister(acer_backlight_device); 1289 backlight_device_unregister(acer_backlight_device);
1105} 1290}
1106 1291
1107static acpi_status wmid3_get_device_status(u32 *value, u16 device)
1108{
1109 struct wmid3_gds_return_value return_value;
1110 acpi_status status;
1111 union acpi_object *obj;
1112 struct wmid3_gds_input_param params = {
1113 .function_num = 0x1,
1114 .hotkey_number = 0x01,
1115 .devices = device,
1116 };
1117 struct acpi_buffer input = {
1118 sizeof(struct wmid3_gds_input_param),
1119 &params
1120 };
1121 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1122
1123 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1124 if (ACPI_FAILURE(status))
1125 return status;
1126
1127 obj = output.pointer;
1128
1129 if (!obj)
1130 return AE_ERROR;
1131 else if (obj->type != ACPI_TYPE_BUFFER) {
1132 kfree(obj);
1133 return AE_ERROR;
1134 }
1135 if (obj->buffer.length != 8) {
1136 pr_warn("Unknown buffer length %d\n", obj->buffer.length);
1137 kfree(obj);
1138 return AE_ERROR;
1139 }
1140
1141 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1142 kfree(obj);
1143
1144 if (return_value.error_code || return_value.ec_return_value)
1145 pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
1146 return_value.error_code,
1147 return_value.ec_return_value);
1148 else
1149 *value = !!(return_value.devices & device);
1150
1151 return status;
1152}
1153
1154static acpi_status get_device_status(u32 *value, u32 cap)
1155{
1156 if (wmi_has_guid(WMID_GUID3)) {
1157 u16 device;
1158
1159 switch (cap) {
1160 case ACER_CAP_WIRELESS:
1161 device = ACER_WMID3_GDS_WIRELESS;
1162 break;
1163 case ACER_CAP_BLUETOOTH:
1164 device = ACER_WMID3_GDS_BLUETOOTH;
1165 break;
1166 case ACER_CAP_THREEG:
1167 device = ACER_WMID3_GDS_THREEG;
1168 break;
1169 default:
1170 return AE_ERROR;
1171 }
1172 return wmid3_get_device_status(value, device);
1173
1174 } else {
1175 return get_u32(value, cap);
1176 }
1177}
1178
1179static acpi_status wmid3_set_device_status(u32 value, u16 device)
1180{
1181 struct wmid3_gds_return_value return_value;
1182 acpi_status status;
1183 union acpi_object *obj;
1184 u16 devices;
1185 struct wmid3_gds_input_param params = {
1186 .function_num = 0x1,
1187 .hotkey_number = 0x01,
1188 .devices = ACER_WMID3_GDS_WIRELESS |
1189 ACER_WMID3_GDS_THREEG |
1190 ACER_WMID3_GDS_WIMAX |
1191 ACER_WMID3_GDS_BLUETOOTH,
1192 };
1193 struct acpi_buffer input = {
1194 sizeof(struct wmid3_gds_input_param),
1195 &params
1196 };
1197 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1198 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1199
1200 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1201 if (ACPI_FAILURE(status))
1202 return status;
1203
1204 obj = output.pointer;
1205
1206 if (!obj)
1207 return AE_ERROR;
1208 else if (obj->type != ACPI_TYPE_BUFFER) {
1209 kfree(obj);
1210 return AE_ERROR;
1211 }
1212 if (obj->buffer.length != 8) {
1213 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1214 kfree(obj);
1215 return AE_ERROR;
1216 }
1217
1218 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1219 kfree(obj);
1220
1221 if (return_value.error_code || return_value.ec_return_value) {
1222 pr_warning("Get Current Device Status failed: "
1223 "0x%x - 0x%x\n", return_value.error_code,
1224 return_value.ec_return_value);
1225 return status;
1226 }
1227
1228 devices = return_value.devices;
1229 params.function_num = 0x2;
1230 params.hotkey_number = 0x01;
1231 params.devices = (value) ? (devices | device) : (devices & ~device);
1232
1233 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1234 if (ACPI_FAILURE(status))
1235 return status;
1236
1237 obj = output2.pointer;
1238
1239 if (!obj)
1240 return AE_ERROR;
1241 else if (obj->type != ACPI_TYPE_BUFFER) {
1242 kfree(obj);
1243 return AE_ERROR;
1244 }
1245 if (obj->buffer.length != 4) {
1246 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1247 kfree(obj);
1248 return AE_ERROR;
1249 }
1250
1251 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1252 kfree(obj);
1253
1254 if (return_value.error_code || return_value.ec_return_value)
1255 pr_warning("Set Device Status failed: "
1256 "0x%x - 0x%x\n", return_value.error_code,
1257 return_value.ec_return_value);
1258
1259 return status;
1260}
1261
1262static acpi_status set_device_status(u32 value, u32 cap)
1263{
1264 if (wmi_has_guid(WMID_GUID3)) {
1265 u16 device;
1266
1267 switch (cap) {
1268 case ACER_CAP_WIRELESS:
1269 device = ACER_WMID3_GDS_WIRELESS;
1270 break;
1271 case ACER_CAP_BLUETOOTH:
1272 device = ACER_WMID3_GDS_BLUETOOTH;
1273 break;
1274 case ACER_CAP_THREEG:
1275 device = ACER_WMID3_GDS_THREEG;
1276 break;
1277 default:
1278 return AE_ERROR;
1279 }
1280 return wmid3_set_device_status(value, device);
1281
1282 } else {
1283 return set_u32(value, cap);
1284 }
1285}
1286
1287/* 1292/*
1288 * Rfkill devices 1293 * Rfkill devices
1289 */ 1294 */
@@ -1311,8 +1316,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
1311 } 1316 }
1312 1317
1313 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) { 1318 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
1314 status = wmid3_get_device_status(&state, 1319 status = get_u32(&state, ACER_WMID3_GDS_THREEG);
1315 ACER_WMID3_GDS_THREEG);
1316 if (ACPI_SUCCESS(status)) 1320 if (ACPI_SUCCESS(status))
1317 rfkill_set_sw_state(threeg_rfkill, !state); 1321 rfkill_set_sw_state(threeg_rfkill, !state);
1318 } 1322 }
@@ -1326,7 +1330,7 @@ static int acer_rfkill_set(void *data, bool blocked)
1326 u32 cap = (unsigned long)data; 1330 u32 cap = (unsigned long)data;
1327 1331
1328 if (rfkill_inited) { 1332 if (rfkill_inited) {
1329 status = set_device_status(!blocked, cap); 1333 status = set_u32(!blocked, cap);
1330 if (ACPI_FAILURE(status)) 1334 if (ACPI_FAILURE(status))
1331 return -ENODEV; 1335 return -ENODEV;
1332 } 1336 }
@@ -1353,7 +1357,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
1353 if (!rfkill_dev) 1357 if (!rfkill_dev)
1354 return ERR_PTR(-ENOMEM); 1358 return ERR_PTR(-ENOMEM);
1355 1359
1356 status = get_device_status(&state, cap); 1360 status = get_u32(&state, cap);
1357 1361
1358 err = rfkill_register(rfkill_dev); 1362 err = rfkill_register(rfkill_dev);
1359 if (err) { 1363 if (err) {
@@ -1457,11 +1461,7 @@ static ssize_t show_bool_threeg(struct device *dev,
1457 1461
1458 pr_info("This threeg sysfs will be removed in 2012" 1462 pr_info("This threeg sysfs will be removed in 2012"
1459 " - used by: %s\n", current->comm); 1463 " - used by: %s\n", current->comm);
1460 if (wmi_has_guid(WMID_GUID3)) 1464 status = get_u32(&result, ACER_CAP_THREEG);
1461 status = wmid3_get_device_status(&result,
1462 ACER_WMID3_GDS_THREEG);
1463 else
1464 status = get_u32(&result, ACER_CAP_THREEG);
1465 if (ACPI_SUCCESS(status)) 1465 if (ACPI_SUCCESS(status))
1466 return sprintf(buf, "%u\n", result); 1466 return sprintf(buf, "%u\n", result);
1467 return sprintf(buf, "Read error\n"); 1467 return sprintf(buf, "Read error\n");
@@ -1493,6 +1493,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1493 return sprintf(buf, "AMW0 v2\n"); 1493 return sprintf(buf, "AMW0 v2\n");
1494 case ACER_WMID: 1494 case ACER_WMID:
1495 return sprintf(buf, "WMID\n"); 1495 return sprintf(buf, "WMID\n");
1496 case ACER_WMID_v2:
1497 return sprintf(buf, "WMID v2\n");
1496 default: 1498 default:
1497 return sprintf(buf, "Error!\n"); 1499 return sprintf(buf, "Error!\n");
1498 } 1500 }
@@ -1912,12 +1914,20 @@ static int __init acer_wmi_init(void)
1912 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) 1914 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
1913 interface = &wmid_interface; 1915 interface = &wmid_interface;
1914 1916
1917 if (wmi_has_guid(WMID_GUID3))
1918 interface = &wmid_v2_interface;
1919
1920 if (interface)
1921 dmi_walk(type_aa_dmi_decode, NULL);
1922
1915 if (wmi_has_guid(WMID_GUID2) && interface) { 1923 if (wmi_has_guid(WMID_GUID2) && interface) {
1916 if (ACPI_FAILURE(WMID_set_capabilities())) { 1924 if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
1917 pr_err("Unable to detect available WMID devices\n"); 1925 pr_err("Unable to detect available WMID devices\n");
1918 return -ENODEV; 1926 return -ENODEV;
1919 } 1927 }
1920 } else if (!wmi_has_guid(WMID_GUID2) && interface) { 1928 /* WMID always provides brightness methods */
1929 interface->capability |= ACER_CAP_BRIGHTNESS;
1930 } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
1921 pr_err("No WMID device detection method found\n"); 1931 pr_err("No WMID device detection method found\n");
1922 return -ENODEV; 1932 return -ENODEV;
1923 } 1933 }
@@ -1941,7 +1951,7 @@ static int __init acer_wmi_init(void)
1941 1951
1942 set_quirks(); 1952 set_quirks();
1943 1953
1944 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { 1954 if (acpi_video_backlight_support()) {
1945 interface->capability &= ~ACER_CAP_BRIGHTNESS; 1955 interface->capability &= ~ACER_CAP_BRIGHTNESS;
1946 pr_info("Brightness must be controlled by " 1956 pr_info("Brightness must be controlled by "
1947 "generic video driver\n"); 1957 "generic video driver\n");