Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sony-laptop: add Type4 model

Recent Vaio models (UX, SZ and presumably TZ and others) add more
events and a slightly different handling of Fn key events for
additional hotkeys (s1, s2, zoom-in/out, etc.).

Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Mattia Dongili and committed by
Len Brown
3eb8749a 425ef5d7

+186 -111
+184 -111
drivers/misc/sony-laptop.c
··· 146 146 * and input layer indexes in the keymap 147 147 */ 148 148 static int sony_laptop_input_index[] = { 149 - -1, /* no event */ 150 - -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ 151 - -1, /* SONYPI_EVENT_JOGDIAL_UP */ 152 - -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ 153 - -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ 154 - -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ 155 - -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ 156 - 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ 157 - 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ 158 - 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 159 - 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 160 - 4, /* SONYPI_EVENT_FNKEY_ESC */ 161 - 5, /* SONYPI_EVENT_FNKEY_F1 */ 162 - 6, /* SONYPI_EVENT_FNKEY_F2 */ 163 - 7, /* SONYPI_EVENT_FNKEY_F3 */ 164 - 8, /* SONYPI_EVENT_FNKEY_F4 */ 165 - 9, /* SONYPI_EVENT_FNKEY_F5 */ 166 - 10, /* SONYPI_EVENT_FNKEY_F6 */ 167 - 11, /* SONYPI_EVENT_FNKEY_F7 */ 168 - 12, /* SONYPI_EVENT_FNKEY_F8 */ 169 - 13, /* SONYPI_EVENT_FNKEY_F9 */ 170 - 14, /* SONYPI_EVENT_FNKEY_F10 */ 171 - 15, /* SONYPI_EVENT_FNKEY_F11 */ 172 - 16, /* SONYPI_EVENT_FNKEY_F12 */ 173 - 17, /* SONYPI_EVENT_FNKEY_1 */ 174 - 18, /* SONYPI_EVENT_FNKEY_2 */ 175 - 19, /* SONYPI_EVENT_FNKEY_D */ 176 - 20, /* SONYPI_EVENT_FNKEY_E */ 177 - 21, /* SONYPI_EVENT_FNKEY_F */ 178 - 22, /* SONYPI_EVENT_FNKEY_S */ 179 - 23, /* SONYPI_EVENT_FNKEY_B */ 180 - 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ 181 - 25, /* SONYPI_EVENT_PKEY_P1 */ 182 - 26, /* SONYPI_EVENT_PKEY_P2 */ 183 - 27, /* SONYPI_EVENT_PKEY_P3 */ 184 - 28, /* SONYPI_EVENT_BACK_PRESSED */ 185 - -1, /* SONYPI_EVENT_LID_CLOSED */ 186 - -1, /* SONYPI_EVENT_LID_OPENED */ 187 - 29, /* SONYPI_EVENT_BLUETOOTH_ON */ 188 - 30, /* SONYPI_EVENT_BLUETOOTH_OFF */ 189 - 31, /* SONYPI_EVENT_HELP_PRESSED */ 190 - 32, /* SONYPI_EVENT_FNKEY_ONLY */ 191 - 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 192 - 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */ 193 - 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 194 - 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 195 - 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 196 - 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */ 197 - 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 198 - 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 199 - 41, /* SONYPI_EVENT_ZOOM_PRESSED */ 200 - 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */ 201 - 43, /* SONYPI_EVENT_MEYE_FACE */ 202 - 44, /* SONYPI_EVENT_MEYE_OPPOSITE */ 203 - 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */ 204 - 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */ 205 - -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */ 206 - -1, /* SONYPI_EVENT_BATTERY_INSERT */ 207 - -1, /* SONYPI_EVENT_BATTERY_REMOVE */ 208 - -1, /* SONYPI_EVENT_FNKEY_RELEASED */ 209 - 47, /* SONYPI_EVENT_WIRELESS_ON */ 210 - 48, /* SONYPI_EVENT_WIRELESS_OFF */ 149 + -1, /* 0 no event */ 150 + -1, /* 1 SONYPI_EVENT_JOGDIAL_DOWN */ 151 + -1, /* 2 SONYPI_EVENT_JOGDIAL_UP */ 152 + -1, /* 3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ 153 + -1, /* 4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */ 154 + -1, /* 5 SONYPI_EVENT_JOGDIAL_PRESSED */ 155 + -1, /* 6 SONYPI_EVENT_JOGDIAL_RELEASED */ 156 + 0, /* 7 SONYPI_EVENT_CAPTURE_PRESSED */ 157 + 1, /* 8 SONYPI_EVENT_CAPTURE_RELEASED */ 158 + 2, /* 9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 159 + 3, /* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 160 + 4, /* 11 SONYPI_EVENT_FNKEY_ESC */ 161 + 5, /* 12 SONYPI_EVENT_FNKEY_F1 */ 162 + 6, /* 13 SONYPI_EVENT_FNKEY_F2 */ 163 + 7, /* 14 SONYPI_EVENT_FNKEY_F3 */ 164 + 8, /* 15 SONYPI_EVENT_FNKEY_F4 */ 165 + 9, /* 16 SONYPI_EVENT_FNKEY_F5 */ 166 + 10, /* 17 SONYPI_EVENT_FNKEY_F6 */ 167 + 11, /* 18 SONYPI_EVENT_FNKEY_F7 */ 168 + 12, /* 19 SONYPI_EVENT_FNKEY_F8 */ 169 + 13, /* 20 SONYPI_EVENT_FNKEY_F9 */ 170 + 14, /* 21 SONYPI_EVENT_FNKEY_F10 */ 171 + 15, /* 22 SONYPI_EVENT_FNKEY_F11 */ 172 + 16, /* 23 SONYPI_EVENT_FNKEY_F12 */ 173 + 17, /* 24 SONYPI_EVENT_FNKEY_1 */ 174 + 18, /* 25 SONYPI_EVENT_FNKEY_2 */ 175 + 19, /* 26 SONYPI_EVENT_FNKEY_D */ 176 + 20, /* 27 SONYPI_EVENT_FNKEY_E */ 177 + 21, /* 28 SONYPI_EVENT_FNKEY_F */ 178 + 22, /* 29 SONYPI_EVENT_FNKEY_S */ 179 + 23, /* 30 SONYPI_EVENT_FNKEY_B */ 180 + 24, /* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */ 181 + 25, /* 32 SONYPI_EVENT_PKEY_P1 */ 182 + 26, /* 33 SONYPI_EVENT_PKEY_P2 */ 183 + 27, /* 34 SONYPI_EVENT_PKEY_P3 */ 184 + 28, /* 35 SONYPI_EVENT_BACK_PRESSED */ 185 + -1, /* 36 SONYPI_EVENT_LID_CLOSED */ 186 + -1, /* 37 SONYPI_EVENT_LID_OPENED */ 187 + 29, /* 38 SONYPI_EVENT_BLUETOOTH_ON */ 188 + 30, /* 39 SONYPI_EVENT_BLUETOOTH_OFF */ 189 + 31, /* 40 SONYPI_EVENT_HELP_PRESSED */ 190 + 32, /* 41 SONYPI_EVENT_FNKEY_ONLY */ 191 + 33, /* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 192 + 34, /* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */ 193 + 35, /* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 194 + 36, /* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 195 + 37, /* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 196 + 38, /* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */ 197 + 39, /* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 198 + 40, /* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 199 + 41, /* 50 SONYPI_EVENT_ZOOM_PRESSED */ 200 + 42, /* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */ 201 + 43, /* 52 SONYPI_EVENT_MEYE_FACE */ 202 + 44, /* 53 SONYPI_EVENT_MEYE_OPPOSITE */ 203 + 45, /* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */ 204 + 46, /* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */ 205 + -1, /* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */ 206 + -1, /* 57 SONYPI_EVENT_BATTERY_INSERT */ 207 + -1, /* 58 SONYPI_EVENT_BATTERY_REMOVE */ 208 + -1, /* 59 SONYPI_EVENT_FNKEY_RELEASED */ 209 + 47, /* 60 SONYPI_EVENT_WIRELESS_ON */ 210 + 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 211 + 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 212 + 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 211 213 }; 212 214 213 215 static int sony_laptop_input_keycode_map[] = { ··· 262 260 KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ 263 261 KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ 264 262 KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ 263 + KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ 264 + KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 265 265 }; 266 266 267 267 /* release buttons after a short delay if pressed */ ··· 1182 1178 #define SONYPI_DEVICE_TYPE1 0x00000001 1183 1179 #define SONYPI_DEVICE_TYPE2 0x00000002 1184 1180 #define SONYPI_DEVICE_TYPE3 0x00000004 1181 + #define SONYPI_DEVICE_TYPE4 0x00000008 1185 1182 1186 1183 #define SONYPI_TYPE1_OFFSET 0x04 1187 1184 #define SONYPI_TYPE2_OFFSET 0x12 1188 1185 #define SONYPI_TYPE3_OFFSET 0x12 1186 + #define SONYPI_TYPE4_OFFSET 0x12 1189 1187 1190 1188 struct sony_pic_ioport { 1191 1189 struct acpi_resource_io io1; ··· 1208 1202 1209 1203 struct device_ctrl { 1210 1204 int model; 1211 - int (*handle_irq)(void); 1205 + int (*handle_irq)(const u8, const u8); 1212 1206 u16 evport_offset; 1213 1207 u8 has_camera; 1214 1208 u8 has_bluetooth; ··· 1283 1277 static struct sonypi_event sonypi_captureev[] = { 1284 1278 { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, 1285 1279 { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, 1280 + { 0x40, SONYPI_EVENT_CAPTURE_PRESSED }, 1286 1281 { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, 1287 1282 { 0, 0 } 1288 1283 }; ··· 1320 1313 { 0x01, SONYPI_EVENT_PKEY_P1 }, 1321 1314 { 0x02, SONYPI_EVENT_PKEY_P2 }, 1322 1315 { 0x04, SONYPI_EVENT_PKEY_P3 }, 1323 - { 0x5c, SONYPI_EVENT_PKEY_P1 }, 1324 1316 { 0, 0 } 1325 1317 }; 1326 1318 ··· 1361 1355 /* The set of possible zoom events */ 1362 1356 static struct sonypi_event sonypi_zoomev[] = { 1363 1357 { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, 1358 + { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, 1359 + { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, 1364 1360 { 0, 0 } 1365 1361 }; 1366 1362 ··· 1432 1424 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1433 1425 { 0 }, 1434 1426 }; 1435 - 1436 - static struct device_ctrl spic_types[] = { 1437 - { 1438 - .model = SONYPI_DEVICE_TYPE1, 1439 - .handle_irq = NULL, 1440 - .evport_offset = SONYPI_TYPE1_OFFSET, 1441 - .event_types = type1_events, 1442 - }, 1443 - { 1444 - .model = SONYPI_DEVICE_TYPE2, 1445 - .handle_irq = NULL, 1446 - .evport_offset = SONYPI_TYPE2_OFFSET, 1447 - .event_types = type2_events, 1448 - }, 1449 - { 1450 - .model = SONYPI_DEVICE_TYPE3, 1451 - .handle_irq = NULL, 1452 - .evport_offset = SONYPI_TYPE3_OFFSET, 1453 - .event_types = type3_events, 1454 - }, 1427 + static struct sonypi_eventtypes type4_events[] = { 1428 + { 0, 0xffffffff, sonypi_releaseev }, 1429 + { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, 1430 + { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, 1431 + { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 1432 + { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 1433 + { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1434 + { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, 1435 + { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, 1436 + { 0 }, 1455 1437 }; 1456 1438 1457 - static void sony_pic_detect_device_type(struct sony_pic_dev *dev) 1458 - { 1459 - struct pci_dev *pcidev; 1460 - 1461 - if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1462 - PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) 1463 - dev->control = &spic_types[0]; 1464 - 1465 - else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1466 - PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) 1467 - dev->control = &spic_types[2]; 1468 - 1469 - else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1470 - PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) 1471 - dev->control = &spic_types[2]; 1472 - 1473 - else 1474 - dev->control = &spic_types[1]; 1475 - 1476 - if (pcidev) 1477 - pci_dev_put(pcidev); 1478 - 1479 - printk(KERN_INFO DRV_PFX "detected Type%d model\n", 1480 - dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : 1481 - dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); 1482 - } 1483 - 1439 + /* low level spic calls */ 1484 1440 #define ITERATIONS_LONG 10000 1485 1441 #define ITERATIONS_SHORT 10 1486 1442 #define wait_on_command(command, iterations) { \ ··· 1498 1526 dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", 1499 1527 dev, fn, v, v1); 1500 1528 return v1; 1529 + } 1530 + 1531 + /* 1532 + * minidrivers for SPIC models 1533 + */ 1534 + static int type4_handle_irq(const u8 data_mask, const u8 ev) 1535 + { 1536 + /* 1537 + * 0x31 could mean we have to take some extra action and wait for 1538 + * the next irq for some Type4 models, it will generate a new 1539 + * irq and we can read new data from the device: 1540 + * - 0x5c and 0x5f requires 0xA0 1541 + * - 0x61 requires 0xB3 1542 + */ 1543 + if (data_mask == 0x31) { 1544 + if (ev == 0x5c || ev == 0x5f) 1545 + sony_pic_call1(0xA0); 1546 + else if (ev == 0x61) 1547 + sony_pic_call1(0xB3); 1548 + return 0; 1549 + } 1550 + return 1; 1551 + } 1552 + 1553 + static struct device_ctrl spic_types[] = { 1554 + { 1555 + .model = SONYPI_DEVICE_TYPE1, 1556 + .handle_irq = NULL, 1557 + .evport_offset = SONYPI_TYPE1_OFFSET, 1558 + .event_types = type1_events, 1559 + }, 1560 + { 1561 + .model = SONYPI_DEVICE_TYPE2, 1562 + .handle_irq = NULL, 1563 + .evport_offset = SONYPI_TYPE2_OFFSET, 1564 + .event_types = type2_events, 1565 + }, 1566 + { 1567 + .model = SONYPI_DEVICE_TYPE3, 1568 + .handle_irq = NULL, 1569 + .evport_offset = SONYPI_TYPE3_OFFSET, 1570 + .event_types = type3_events, 1571 + }, 1572 + { 1573 + .model = SONYPI_DEVICE_TYPE4, 1574 + .handle_irq = type4_handle_irq, 1575 + .evport_offset = SONYPI_TYPE4_OFFSET, 1576 + .event_types = type4_events, 1577 + }, 1578 + }; 1579 + 1580 + static void sony_pic_detect_device_type(struct sony_pic_dev *dev) 1581 + { 1582 + struct pci_dev *pcidev; 1583 + 1584 + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1585 + PCI_DEVICE_ID_INTEL_82371AB_3, NULL); 1586 + if (pcidev) { 1587 + dev->control = &spic_types[0]; 1588 + goto out; 1589 + } 1590 + 1591 + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1592 + PCI_DEVICE_ID_INTEL_ICH6_1, NULL); 1593 + if (pcidev) { 1594 + dev->control = &spic_types[2]; 1595 + goto out; 1596 + } 1597 + 1598 + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1599 + PCI_DEVICE_ID_INTEL_ICH7_1, NULL); 1600 + if (pcidev) { 1601 + dev->control = &spic_types[3]; 1602 + goto out; 1603 + } 1604 + 1605 + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1606 + PCI_DEVICE_ID_INTEL_ICH8_4, NULL); 1607 + if (pcidev) { 1608 + dev->control = &spic_types[3]; 1609 + goto out; 1610 + } 1611 + 1612 + /* default */ 1613 + dev->control = &spic_types[1]; 1614 + 1615 + out: 1616 + if (pcidev) 1617 + pci_dev_put(pcidev); 1618 + 1619 + printk(KERN_INFO DRV_PFX "detected Type%d model\n", 1620 + dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : 1621 + dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 1622 + dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); 1501 1623 } 1502 1624 1503 1625 /* camera tests and poweron/poweroff */ ··· 2472 2406 } 2473 2407 } 2474 2408 } 2409 + /* Still not able to decode the event try to pass 2410 + * it over to the minidriver 2411 + */ 2412 + if (dev->control->handle_irq && 2413 + dev->control->handle_irq(data_mask, ev) == 0) 2414 + return IRQ_HANDLED; 2415 + 2475 2416 dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 2476 2417 ev, data_mask, dev->cur_ioport->io1.minimum, 2477 2418 dev->control->evport_offset);
+2
include/linux/sonypi.h
··· 101 101 #define SONYPI_EVENT_FNKEY_RELEASED 59 102 102 #define SONYPI_EVENT_WIRELESS_ON 60 103 103 #define SONYPI_EVENT_WIRELESS_OFF 61 104 + #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 105 + #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 104 106 105 107 /* get/set brightness */ 106 108 #define SONYPI_IOCGBRT _IOR('v', 0, __u8)