diff options
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 76 |
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 | ||
1159 | static int sony_nc_rfkill_setup(struct acpi_device *device) | 1159 | static 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", ¶ms, | ||
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 | |||
1223 | out_no_enum: | ||
1224 | kfree(buffer.pointer); | ||
1225 | return; | ||
1188 | } | 1226 | } |
1189 | 1227 | ||
1190 | static int sony_nc_add(struct acpi_device *device) | 1228 | static int sony_nc_add(struct acpi_device *device) |