aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sony-laptop.c')
-rw-r--r--drivers/misc/sony-laptop.c186
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
1197struct sonypi_eventtypes {
1198 u8 data;
1199 unsigned long mask;
1200 struct sonypi_event *events;
1201};
1202
1203struct 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
1197struct sony_pic_dev { 1213struct 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
1211static struct sony_pic_dev spic_dev = { 1226static 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
1373static struct sonypi_eventtypes { 1388static 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 }, 1401static 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 }, 1418static 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
1414static int sony_pic_detect_device_type(void) 1428static 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
1449static 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
2378found: 2414found:
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) {