aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLee, Chun-Yi <joeyli.kernel@gmail.com>2011-05-21 19:33:54 -0400
committerMatthew Garrett <mjg@redhat.com>2011-05-27 12:38:50 -0400
commit6d88ff0f8ef3529f68233d3963b2a7e07f8e4f69 (patch)
tree912af8d6b59aa899df34cdfe0cd0e6a93ea3c0e0 /drivers/platform
parentab6a931620cfa5c565b351d1982306c3c8b97f96 (diff)
acer-wmi: support to set communication device state by new wmid method
Have many Acer notebooks' BIOS already support new WMID_GUID3 method. On those machines, that will be better set communication device by evaluate WMID_GUID3 method. Tested on Acer Travelmate 8572 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@novell.com> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/acer-wmi.c111
1 files changed, 110 insertions, 1 deletions
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 48219117823b..5dc843bfc6c2 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -135,6 +135,7 @@ struct event_return_value {
135 */ 135 */
136#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */ 136#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */
137#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ 137#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */
138#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */
138#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ 139#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */
139 140
140struct lm_input_params { 141struct lm_input_params {
@@ -1142,6 +1143,114 @@ static acpi_status get_device_status(u32 *value, u32 cap)
1142 } 1143 }
1143} 1144}
1144 1145
1146static acpi_status wmid3_set_device_status(u32 value, u16 device)
1147{
1148 struct wmid3_gds_return_value return_value;
1149 acpi_status status;
1150 union acpi_object *obj;
1151 u16 devices;
1152 struct wmid3_gds_input_param params = {
1153 .function_num = 0x1,
1154 .hotkey_number = 0x01,
1155 .devices = ACER_WMID3_GDS_WIRELESS &
1156 ACER_WMID3_GDS_THREEG &
1157 ACER_WMID3_GDS_WIMAX &
1158 ACER_WMID3_GDS_BLUETOOTH,
1159 };
1160 struct acpi_buffer input = {
1161 sizeof(struct wmid3_gds_input_param),
1162 &params
1163 };
1164 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
1165 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
1166
1167 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
1168 if (ACPI_FAILURE(status))
1169 return status;
1170
1171 obj = output.pointer;
1172
1173 if (!obj)
1174 return AE_ERROR;
1175 else if (obj->type != ACPI_TYPE_BUFFER) {
1176 kfree(obj);
1177 return AE_ERROR;
1178 }
1179 if (obj->buffer.length != 8) {
1180 pr_warning("Unknown buffer length %d\n", obj->buffer.length);
1181 kfree(obj);
1182 return AE_ERROR;
1183 }
1184
1185 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
1186 kfree(obj);
1187
1188 if (return_value.error_code || return_value.ec_return_value) {
1189 pr_warning("Get Current Device Status failed: "
1190 "0x%x - 0x%x\n", return_value.error_code,
1191 return_value.ec_return_value);
1192 return status;
1193 }
1194
1195 devices = return_value.devices;
1196 params.function_num = 0x2;
1197 params.hotkey_number = 0x01;
1198 params.devices = (value) ? (devices | device) : (devices & ~device);
1199
1200 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
1201 if (ACPI_FAILURE(status))
1202 return status;
1203
1204 obj = output2.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 != 4) {
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("Set Device Status failed: "
1223 "0x%x - 0x%x\n", return_value.error_code,
1224 return_value.ec_return_value);
1225
1226 return status;
1227}
1228
1229static acpi_status set_device_status(u32 value, u32 cap)
1230{
1231 if (wmi_has_guid(WMID_GUID3)) {
1232 u16 device;
1233
1234 switch (cap) {
1235 case ACER_CAP_WIRELESS:
1236 device = ACER_WMID3_GDS_WIRELESS;
1237 break;
1238 case ACER_CAP_BLUETOOTH:
1239 device = ACER_WMID3_GDS_BLUETOOTH;
1240 break;
1241 case ACER_CAP_THREEG:
1242 device = ACER_WMID3_GDS_THREEG;
1243 break;
1244 default:
1245 return AE_ERROR;
1246 }
1247 return wmid3_set_device_status(value, device);
1248
1249 } else {
1250 return set_u32(value, cap);
1251 }
1252}
1253
1145/* 1254/*
1146 * Rfkill devices 1255 * Rfkill devices
1147 */ 1256 */
@@ -1178,7 +1287,7 @@ static int acer_rfkill_set(void *data, bool blocked)
1178 u32 cap = (unsigned long)data; 1287 u32 cap = (unsigned long)data;
1179 1288
1180 if (rfkill_inited) { 1289 if (rfkill_inited) {
1181 status = set_u32(!blocked, cap); 1290 status = set_device_status(!blocked, cap);
1182 if (ACPI_FAILURE(status)) 1291 if (ACPI_FAILURE(status))
1183 return -ENODEV; 1292 return -ENODEV;
1184 } 1293 }