aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattia Dongili <malattia@linux.it>2009-12-16 10:08:36 -0500
committerLen Brown <len.brown@intel.com>2009-12-23 22:58:47 -0500
commit528809c35faebd8c50a4722c85ab8610725875cc (patch)
tree67ba535e6275f4a63111c494e6cd9aebef20d6dd
parentd5a664a311c1957a75bec1808cae0f10d606c378 (diff)
sony-laptop: enumerate rfkill devices using SN06
SN06 makes sure we get back a longer buffer which seems to be necessary going forward as the SNC devices describes more and more devices (or features more precisely). Moreover SN06 should be called with only the descriptor offset to make sure we hit the rfkill controlling function (F124 or F135) with a 0 argument to get a full list of features. Signed-off-by: Mattia Dongili <malattia@linux.it> Tested-by: Miguel Rodríguez Pérez <miguelrp@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
-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)