diff options
Diffstat (limited to 'drivers/misc/sony-laptop.c')
-rw-r--r-- | drivers/misc/sony-laptop.c | 186 |
1 files changed, 104 insertions, 82 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 7a32b355869b..a650f25d76c5 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -1194,18 +1194,33 @@ struct sony_pic_irq { | |||
1194 | struct list_head list; | 1194 | struct list_head list; |
1195 | }; | 1195 | }; |
1196 | 1196 | ||
1197 | struct sonypi_eventtypes { | ||
1198 | u8 data; | ||
1199 | unsigned long mask; | ||
1200 | struct sonypi_event *events; | ||
1201 | }; | ||
1202 | |||
1203 | struct device_ctrl { | ||
1204 | int model; | ||
1205 | int (*handle_irq)(void); | ||
1206 | u16 evport_offset; | ||
1207 | u8 has_camera; | ||
1208 | u8 has_bluetooth; | ||
1209 | u8 has_wwan; | ||
1210 | struct sonypi_eventtypes *event_types; | ||
1211 | }; | ||
1212 | |||
1197 | struct sony_pic_dev { | 1213 | struct sony_pic_dev { |
1198 | int model; | 1214 | struct device_ctrl *control; |
1199 | u16 evport_offset; | ||
1200 | u8 camera_power; | ||
1201 | u8 bluetooth_power; | ||
1202 | u8 wwan_power; | ||
1203 | struct acpi_device *acpi_dev; | 1215 | struct acpi_device *acpi_dev; |
1204 | struct sony_pic_irq *cur_irq; | 1216 | struct sony_pic_irq *cur_irq; |
1205 | struct sony_pic_ioport *cur_ioport; | 1217 | struct sony_pic_ioport *cur_ioport; |
1206 | struct list_head interrupts; | 1218 | struct list_head interrupts; |
1207 | struct list_head ioports; | 1219 | struct list_head ioports; |
1208 | struct mutex lock; | 1220 | struct mutex lock; |
1221 | u8 camera_power; | ||
1222 | u8 bluetooth_power; | ||
1223 | u8 wwan_power; | ||
1209 | }; | 1224 | }; |
1210 | 1225 | ||
1211 | static struct sony_pic_dev spic_dev = { | 1226 | static struct sony_pic_dev spic_dev = { |
@@ -1370,74 +1385,92 @@ static struct sonypi_event sonypi_batteryev[] = { | |||
1370 | { 0, 0 } | 1385 | { 0, 0 } |
1371 | }; | 1386 | }; |
1372 | 1387 | ||
1373 | static struct sonypi_eventtypes { | 1388 | static struct sonypi_eventtypes type1_events[] = { |
1374 | int model; | 1389 | { 0, 0xffffffff, sonypi_releaseev }, |
1375 | u8 data; | 1390 | { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, |
1376 | unsigned long mask; | 1391 | { 0x30, SONYPI_LID_MASK, sonypi_lidev }, |
1377 | struct sonypi_event * events; | 1392 | { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, |
1378 | } sony_pic_eventtypes[] = { | 1393 | { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, |
1379 | { SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev }, | 1394 | { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, |
1380 | { SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, | 1395 | { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, |
1381 | { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev }, | 1396 | { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1382 | { SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, | 1397 | { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1383 | { SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, | 1398 | { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1384 | { SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | 1399 | { 0 }, |
1385 | { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, | 1400 | }; |
1386 | { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1401 | static struct sonypi_eventtypes type2_events[] = { |
1387 | { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1402 | { 0, 0xffffffff, sonypi_releaseev }, |
1388 | { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1403 | { 0x38, SONYPI_LID_MASK, sonypi_lidev }, |
1389 | 1404 | { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, | |
1390 | { SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev }, | 1405 | { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, |
1391 | { SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev }, | 1406 | { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, |
1392 | { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, | 1407 | { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, |
1393 | { SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, | 1408 | { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1394 | { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | 1409 | { 0x11, SONYPI_BACK_MASK, sonypi_backev }, |
1395 | { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, | 1410 | { 0x21, SONYPI_HELP_MASK, sonypi_helpev }, |
1396 | { SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1411 | { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, |
1397 | { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, | 1412 | { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, |
1398 | { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, | 1413 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1399 | { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, | 1414 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1400 | { SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, | 1415 | { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1401 | { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1416 | { 0 }, |
1402 | { SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1417 | }; |
1403 | { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1418 | static struct sonypi_eventtypes type3_events[] = { |
1404 | 1419 | { 0, 0xffffffff, sonypi_releaseev }, | |
1405 | { SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev }, | 1420 | { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, |
1406 | { SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | 1421 | { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, |
1407 | { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, | 1422 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1408 | { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1423 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1409 | { SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1424 | { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1410 | { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1425 | { 0 }, |
1411 | { 0 } | ||
1412 | }; | 1426 | }; |
1413 | 1427 | ||
1414 | static int sony_pic_detect_device_type(void) | 1428 | static struct device_ctrl spic_types[] = { |
1429 | { | ||
1430 | .model = SONYPI_DEVICE_TYPE1, | ||
1431 | .handle_irq = NULL, | ||
1432 | .evport_offset = SONYPI_TYPE1_OFFSET, | ||
1433 | .event_types = type1_events, | ||
1434 | }, | ||
1435 | { | ||
1436 | .model = SONYPI_DEVICE_TYPE2, | ||
1437 | .handle_irq = NULL, | ||
1438 | .evport_offset = SONYPI_TYPE2_OFFSET, | ||
1439 | .event_types = type2_events, | ||
1440 | }, | ||
1441 | { | ||
1442 | .model = SONYPI_DEVICE_TYPE3, | ||
1443 | .handle_irq = NULL, | ||
1444 | .evport_offset = SONYPI_TYPE3_OFFSET, | ||
1445 | .event_types = type3_events, | ||
1446 | }, | ||
1447 | }; | ||
1448 | |||
1449 | static void sony_pic_detect_device_type(struct sony_pic_dev *dev) | ||
1415 | { | 1450 | { |
1416 | struct pci_dev *pcidev; | 1451 | struct pci_dev *pcidev; |
1417 | int model = 0; | ||
1418 | 1452 | ||
1419 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1453 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1420 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) | 1454 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) |
1421 | model = SONYPI_DEVICE_TYPE1; | 1455 | dev->control = &spic_types[0]; |
1422 | 1456 | ||
1423 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1457 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1424 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | 1458 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) |
1425 | model = SONYPI_DEVICE_TYPE3; | 1459 | dev->control = &spic_types[2]; |
1426 | 1460 | ||
1427 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1461 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1428 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) | 1462 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) |
1429 | model = SONYPI_DEVICE_TYPE3; | 1463 | dev->control = &spic_types[2]; |
1430 | 1464 | ||
1431 | else | 1465 | else |
1432 | model = SONYPI_DEVICE_TYPE2; | 1466 | dev->control = &spic_types[1]; |
1433 | 1467 | ||
1434 | if (pcidev) | 1468 | if (pcidev) |
1435 | pci_dev_put(pcidev); | 1469 | pci_dev_put(pcidev); |
1436 | 1470 | ||
1437 | printk(KERN_INFO DRV_PFX "detected Type%d model\n", | 1471 | printk(KERN_INFO DRV_PFX "detected Type%d model\n", |
1438 | model == SONYPI_DEVICE_TYPE1 ? 1 : | 1472 | dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : |
1439 | model == SONYPI_DEVICE_TYPE2 ? 2 : 3); | 1473 | dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); |
1440 | return model; | ||
1441 | } | 1474 | } |
1442 | 1475 | ||
1443 | #define ITERATIONS_LONG 10000 | 1476 | #define ITERATIONS_LONG 10000 |
@@ -2263,7 +2296,7 @@ static int sony_pic_enable(struct acpi_device *device, | |||
2263 | buffer.pointer = resource; | 2296 | buffer.pointer = resource; |
2264 | 2297 | ||
2265 | /* setup Type 1 resources */ | 2298 | /* setup Type 1 resources */ |
2266 | if (spic_dev.model == SONYPI_DEVICE_TYPE1) { | 2299 | if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) { |
2267 | 2300 | ||
2268 | /* setup io resources */ | 2301 | /* setup io resources */ |
2269 | resource->res1.type = ACPI_RESOURCE_TYPE_IO; | 2302 | resource->res1.type = ACPI_RESOURCE_TYPE_IO; |
@@ -2345,39 +2378,42 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) | |||
2345 | if (dev->cur_ioport->io2.minimum) | 2378 | if (dev->cur_ioport->io2.minimum) |
2346 | data_mask = inb_p(dev->cur_ioport->io2.minimum); | 2379 | data_mask = inb_p(dev->cur_ioport->io2.minimum); |
2347 | else | 2380 | else |
2348 | data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset); | 2381 | data_mask = inb_p(dev->cur_ioport->io1.minimum + |
2382 | dev->control->evport_offset); | ||
2349 | 2383 | ||
2350 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", | 2384 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", |
2351 | ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset); | 2385 | ev, data_mask, dev->cur_ioport->io1.minimum, |
2386 | dev->control->evport_offset); | ||
2352 | 2387 | ||
2353 | if (ev == 0x00 || ev == 0xff) | 2388 | if (ev == 0x00 || ev == 0xff) |
2354 | return IRQ_HANDLED; | 2389 | return IRQ_HANDLED; |
2355 | 2390 | ||
2356 | for (i = 0; sony_pic_eventtypes[i].model; i++) { | 2391 | for (i = 0; dev->control->event_types[i].mask; i++) { |
2357 | 2392 | ||
2358 | if (spic_dev.model != sony_pic_eventtypes[i].model) | 2393 | if ((data_mask & dev->control->event_types[i].data) != |
2394 | dev->control->event_types[i].data) | ||
2359 | continue; | 2395 | continue; |
2360 | 2396 | ||
2361 | if ((data_mask & sony_pic_eventtypes[i].data) != | 2397 | if (!(mask & dev->control->event_types[i].mask)) |
2362 | sony_pic_eventtypes[i].data) | ||
2363 | continue; | 2398 | continue; |
2364 | 2399 | ||
2365 | if (!(mask & sony_pic_eventtypes[i].mask)) | 2400 | for (j = 0; dev->control->event_types[i].events[j].event; j++) { |
2366 | continue; | 2401 | if (ev == dev->control->event_types[i].events[j].data) { |
2367 | |||
2368 | for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) { | ||
2369 | if (ev == sony_pic_eventtypes[i].events[j].data) { | ||
2370 | device_event = | 2402 | device_event = |
2371 | sony_pic_eventtypes[i].events[j].event; | 2403 | dev->control-> |
2404 | event_types[i].events[j].event; | ||
2372 | goto found; | 2405 | goto found; |
2373 | } | 2406 | } |
2374 | } | 2407 | } |
2375 | } | 2408 | } |
2409 | dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", | ||
2410 | ev, data_mask, dev->cur_ioport->io1.minimum, | ||
2411 | dev->control->evport_offset); | ||
2376 | return IRQ_HANDLED; | 2412 | return IRQ_HANDLED; |
2377 | 2413 | ||
2378 | found: | 2414 | found: |
2379 | sony_laptop_report_input_event(device_event); | 2415 | sony_laptop_report_input_event(device_event); |
2380 | acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event); | 2416 | acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); |
2381 | sonypi_compat_report_event(device_event); | 2417 | sonypi_compat_report_event(device_event); |
2382 | 2418 | ||
2383 | return IRQ_HANDLED; | 2419 | return IRQ_HANDLED; |
@@ -2439,23 +2475,9 @@ static int sony_pic_add(struct acpi_device *device) | |||
2439 | 2475 | ||
2440 | spic_dev.acpi_dev = device; | 2476 | spic_dev.acpi_dev = device; |
2441 | strcpy(acpi_device_class(device), "sony/hotkey"); | 2477 | strcpy(acpi_device_class(device), "sony/hotkey"); |
2442 | spic_dev.model = sony_pic_detect_device_type(); | 2478 | sony_pic_detect_device_type(&spic_dev); |
2443 | mutex_init(&spic_dev.lock); | 2479 | mutex_init(&spic_dev.lock); |
2444 | 2480 | ||
2445 | /* model specific characteristics */ | ||
2446 | switch(spic_dev.model) { | ||
2447 | case SONYPI_DEVICE_TYPE1: | ||
2448 | spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; | ||
2449 | break; | ||
2450 | case SONYPI_DEVICE_TYPE3: | ||
2451 | spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; | ||
2452 | break; | ||
2453 | case SONYPI_DEVICE_TYPE2: | ||
2454 | default: | ||
2455 | spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; | ||
2456 | break; | ||
2457 | } | ||
2458 | |||
2459 | /* read _PRS resources */ | 2481 | /* read _PRS resources */ |
2460 | result = sony_pic_possible_resources(device); | 2482 | result = sony_pic_possible_resources(device); |
2461 | if (result) { | 2483 | if (result) { |