diff options
Diffstat (limited to 'drivers/platform/x86/sony-laptop.c')
| -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) |
