aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sony-laptop.c
diff options
context:
space:
mode:
authorMattia Dongili <malattia@linux.it>2008-01-14 04:05:43 -0500
committerLen Brown <len.brown@intel.com>2008-01-24 00:47:19 -0500
commitde9204300112dea10ca3d3cc76858cee61043e47 (patch)
treef42f289f49f1d79c18bdd0640758f7cacf62a87e /drivers/misc/sony-laptop.c
parent88877c2a2ebd0e554496efb23e7dc8ade661d289 (diff)
sony-laptop: refactor model types
Create mini drivers and allow callbacks for each model to be specified. Following patches will make use of this feature to handle specific cases instead of just executing code and hope not to break other models. Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Len Brown <len.brown@intel.com>
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) {