aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/sony-laptop.c76
1 files changed, 57 insertions, 19 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 1144686a33f5..49f3fe0ac59c 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1156,35 +1156,73 @@ static void sony_nc_rfkill_update()
1156 } 1156 }
1157} 1157}
1158 1158
1159static int sony_nc_rfkill_setup(struct acpi_device *device) 1159static void sony_nc_rfkill_setup(struct acpi_device *device)
1160{ 1160{
1161 int result, ret; 1161 int offset;
1162 u8 dev_code, i;
1163 acpi_status status;
1164 struct acpi_object_list params;
1165 union acpi_object in_obj;
1166 union acpi_object *device_enum;
1167 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1162 1168
1163 if (sony_find_snc_handle(0x124) == -1) { 1169 offset = sony_find_snc_handle(0x124);
1164 if (sony_find_snc_handle(0x135) == -1) 1170 if (offset == -1) {
1165 return -1; 1171 offset = sony_find_snc_handle(0x135);
1172 if (offset == -1)
1173 return;
1166 else 1174 else
1167 sony_rfkill_handle = 0x135; 1175 sony_rfkill_handle = 0x135;
1168 } else 1176 } else
1169 sony_rfkill_handle = 0x124; 1177 sony_rfkill_handle = 0x124;
1178 dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle);
1170 1179
1171 ret = sony_call_snc_handle(sony_rfkill_handle, 0xb00, &result); 1180 /* need to read the whole buffer returned by the acpi call to SN06
1172 if (ret) { 1181 * here otherwise we may miss some features
1173 printk(KERN_INFO DRV_PFX 1182 */
1174 "Unable to enumerate rfkill devices: %x\n", ret); 1183 params.count = 1;
1175 return ret; 1184 params.pointer = &in_obj;
1185 in_obj.type = ACPI_TYPE_INTEGER;
1186 in_obj.integer.value = offset;
1187 status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
1188 &buffer);
1189 if (ACPI_FAILURE(status)) {
1190 dprintk("Radio device enumeration failed\n");
1191 return;
1176 } 1192 }
1177 1193
1178 if (result & 0x1) 1194 device_enum = (union acpi_object *) buffer.pointer;
1179 sony_nc_setup_rfkill(device, SONY_WIFI); 1195 if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) {
1180 if (result & 0x2) 1196 printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n",
1181 sony_nc_setup_rfkill(device, SONY_BLUETOOTH); 1197 device_enum->type);
1182 if (result & 0x1c) 1198 goto out_no_enum;
1183 sony_nc_setup_rfkill(device, SONY_WWAN); 1199 }
1184 if (result & 0x20)
1185 sony_nc_setup_rfkill(device, SONY_WIMAX);
1186 1200
1187 return 0; 1201 /* the buffer is filled with magic numbers describing the devices
1202 * available, 0xff terminates the enumeration
1203 */
1204 while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff &&
1205 i < device_enum->buffer.length) {
1206 i++;
1207 dprintk("Radio devices, looking at 0x%.2x\n", dev_code);
1208
1209 if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI])
1210 sony_nc_setup_rfkill(device, SONY_WIFI);
1211
1212 if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH])
1213 sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
1214
1215 if ((0xf0 & dev_code) == 0x20 &&
1216 !sony_rfkill_devices[SONY_WWAN])
1217 sony_nc_setup_rfkill(device, SONY_WWAN);
1218
1219 if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX])
1220 sony_nc_setup_rfkill(device, SONY_WIMAX);
1221 }
1222
1223out_no_enum:
1224 kfree(buffer.pointer);
1225 return;
1188} 1226}
1189 1227
1190static int sony_nc_add(struct acpi_device *device) 1228static int sony_nc_add(struct acpi_device *device)