diff options
Diffstat (limited to 'drivers/input/misc')
-rw-r--r-- | drivers/input/misc/Kconfig | 12 | ||||
-rw-r--r-- | drivers/input/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/misc/ims-pcu.c | 258 | ||||
-rw-r--r-- | drivers/input/misc/pm8xxx-vibrator.c | 9 | ||||
-rw-r--r-- | drivers/input/misc/pmic8xxx-pwrkey.c | 33 | ||||
-rw-r--r-- | drivers/input/misc/sirfsoc-onkey.c | 111 | ||||
-rw-r--r-- | drivers/input/misc/soc_button_array.c | 218 | ||||
-rw-r--r-- | drivers/input/misc/uinput.c | 97 | ||||
-rw-r--r-- | drivers/input/misc/wistron_btns.c | 19 |
9 files changed, 679 insertions, 79 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7904ab05527a..f772981bdcdb 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -269,7 +269,7 @@ config INPUT_COBALT_BTNS | |||
269 | 269 | ||
270 | config INPUT_WISTRON_BTNS | 270 | config INPUT_WISTRON_BTNS |
271 | tristate "x86 Wistron laptop button interface" | 271 | tristate "x86 Wistron laptop button interface" |
272 | depends on X86 && !X86_64 | 272 | depends on X86_32 |
273 | select INPUT_POLLDEV | 273 | select INPUT_POLLDEV |
274 | select INPUT_SPARSEKMAP | 274 | select INPUT_SPARSEKMAP |
275 | select NEW_LEDS | 275 | select NEW_LEDS |
@@ -666,4 +666,14 @@ config INPUT_IDEAPAD_SLIDEBAR | |||
666 | To compile this driver as a module, choose M here: the | 666 | To compile this driver as a module, choose M here: the |
667 | module will be called ideapad_slidebar. | 667 | module will be called ideapad_slidebar. |
668 | 668 | ||
669 | config INPUT_SOC_BUTTON_ARRAY | ||
670 | tristate "Windows-compatible SoC Button Array" | ||
671 | depends on KEYBOARD_GPIO | ||
672 | help | ||
673 | Say Y here if you have a SoC-based tablet that originally | ||
674 | runs Windows 8. | ||
675 | |||
676 | To compile this driver as a module, choose M here: the | ||
677 | module will be called soc_button_array. | ||
678 | |||
669 | endif | 679 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index cda71fc52fb3..4955ad322a01 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -53,6 +53,7 @@ obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o | |||
53 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | 53 | obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o |
54 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 54 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
55 | obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o | 55 | obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o |
56 | obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o | ||
56 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 57 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
57 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 58 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
58 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o | 59 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o |
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index e204f26b0011..5a736397d9c8 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c | |||
@@ -51,6 +51,8 @@ struct ims_pcu_backlight { | |||
51 | #define IMS_PCU_BL_VERSION_LEN (9 + 1) | 51 | #define IMS_PCU_BL_VERSION_LEN (9 + 1) |
52 | #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) | 52 | #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) |
53 | 53 | ||
54 | #define IMS_PCU_PCU_B_DEVICE_ID 5 | ||
55 | |||
54 | #define IMS_PCU_BUF_SIZE 128 | 56 | #define IMS_PCU_BUF_SIZE 128 |
55 | 57 | ||
56 | struct ims_pcu { | 58 | struct ims_pcu { |
@@ -68,6 +70,9 @@ struct ims_pcu { | |||
68 | char bl_version[IMS_PCU_BL_VERSION_LEN]; | 70 | char bl_version[IMS_PCU_BL_VERSION_LEN]; |
69 | char reset_reason[IMS_PCU_BL_RESET_REASON_LEN]; | 71 | char reset_reason[IMS_PCU_BL_RESET_REASON_LEN]; |
70 | int update_firmware_status; | 72 | int update_firmware_status; |
73 | u8 device_id; | ||
74 | |||
75 | u8 ofn_reg_addr; | ||
71 | 76 | ||
72 | struct usb_interface *ctrl_intf; | 77 | struct usb_interface *ctrl_intf; |
73 | 78 | ||
@@ -371,6 +376,8 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) | |||
371 | #define IMS_PCU_CMD_GET_DEVICE_ID 0xae | 376 | #define IMS_PCU_CMD_GET_DEVICE_ID 0xae |
372 | #define IMS_PCU_CMD_SPECIAL_INFO 0xb0 | 377 | #define IMS_PCU_CMD_SPECIAL_INFO 0xb0 |
373 | #define IMS_PCU_CMD_BOOTLOADER 0xb1 /* Pass data to bootloader */ | 378 | #define IMS_PCU_CMD_BOOTLOADER 0xb1 /* Pass data to bootloader */ |
379 | #define IMS_PCU_CMD_OFN_SET_CONFIG 0xb3 | ||
380 | #define IMS_PCU_CMD_OFN_GET_CONFIG 0xb4 | ||
374 | 381 | ||
375 | /* PCU responses */ | 382 | /* PCU responses */ |
376 | #define IMS_PCU_RSP_STATUS 0xc0 | 383 | #define IMS_PCU_RSP_STATUS 0xc0 |
@@ -389,6 +396,9 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu) | |||
389 | #define IMS_PCU_RSP_GET_DEVICE_ID 0xce | 396 | #define IMS_PCU_RSP_GET_DEVICE_ID 0xce |
390 | #define IMS_PCU_RSP_SPECIAL_INFO 0xd0 | 397 | #define IMS_PCU_RSP_SPECIAL_INFO 0xd0 |
391 | #define IMS_PCU_RSP_BOOTLOADER 0xd1 /* Bootloader response */ | 398 | #define IMS_PCU_RSP_BOOTLOADER 0xd1 /* Bootloader response */ |
399 | #define IMS_PCU_RSP_OFN_SET_CONFIG 0xd2 | ||
400 | #define IMS_PCU_RSP_OFN_GET_CONFIG 0xd3 | ||
401 | |||
392 | 402 | ||
393 | #define IMS_PCU_RSP_EVNT_BUTTONS 0xe0 /* Unsolicited, button state */ | 403 | #define IMS_PCU_RSP_EVNT_BUTTONS 0xe0 /* Unsolicited, button state */ |
394 | #define IMS_PCU_GAMEPAD_MASK 0x0001ff80UL /* Bits 7 through 16 */ | 404 | #define IMS_PCU_GAMEPAD_MASK 0x0001ff80UL /* Bits 7 through 16 */ |
@@ -1256,6 +1266,225 @@ static struct attribute_group ims_pcu_attr_group = { | |||
1256 | .attrs = ims_pcu_attrs, | 1266 | .attrs = ims_pcu_attrs, |
1257 | }; | 1267 | }; |
1258 | 1268 | ||
1269 | /* Support for a separate OFN attribute group */ | ||
1270 | |||
1271 | #define OFN_REG_RESULT_OFFSET 2 | ||
1272 | |||
1273 | static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data) | ||
1274 | { | ||
1275 | int error; | ||
1276 | s16 result; | ||
1277 | |||
1278 | error = ims_pcu_execute_command(pcu, OFN_GET_CONFIG, | ||
1279 | &addr, sizeof(addr)); | ||
1280 | if (error) | ||
1281 | return error; | ||
1282 | |||
1283 | result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); | ||
1284 | if (result < 0) | ||
1285 | return -EIO; | ||
1286 | |||
1287 | /* We only need LSB */ | ||
1288 | *data = pcu->cmd_buf[OFN_REG_RESULT_OFFSET]; | ||
1289 | return 0; | ||
1290 | } | ||
1291 | |||
1292 | static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data) | ||
1293 | { | ||
1294 | u8 buffer[] = { addr, data }; | ||
1295 | int error; | ||
1296 | s16 result; | ||
1297 | |||
1298 | error = ims_pcu_execute_command(pcu, OFN_SET_CONFIG, | ||
1299 | &buffer, sizeof(buffer)); | ||
1300 | if (error) | ||
1301 | return error; | ||
1302 | |||
1303 | result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET); | ||
1304 | if (result < 0) | ||
1305 | return -EIO; | ||
1306 | |||
1307 | return 0; | ||
1308 | } | ||
1309 | |||
1310 | static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev, | ||
1311 | struct device_attribute *dattr, | ||
1312 | char *buf) | ||
1313 | { | ||
1314 | struct usb_interface *intf = to_usb_interface(dev); | ||
1315 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1316 | int error; | ||
1317 | u8 data; | ||
1318 | |||
1319 | mutex_lock(&pcu->cmd_mutex); | ||
1320 | error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); | ||
1321 | mutex_unlock(&pcu->cmd_mutex); | ||
1322 | |||
1323 | if (error) | ||
1324 | return error; | ||
1325 | |||
1326 | return scnprintf(buf, PAGE_SIZE, "%x\n", data); | ||
1327 | } | ||
1328 | |||
1329 | static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev, | ||
1330 | struct device_attribute *dattr, | ||
1331 | const char *buf, size_t count) | ||
1332 | { | ||
1333 | struct usb_interface *intf = to_usb_interface(dev); | ||
1334 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1335 | int error; | ||
1336 | u8 value; | ||
1337 | |||
1338 | error = kstrtou8(buf, 0, &value); | ||
1339 | if (error) | ||
1340 | return error; | ||
1341 | |||
1342 | mutex_lock(&pcu->cmd_mutex); | ||
1343 | error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); | ||
1344 | mutex_unlock(&pcu->cmd_mutex); | ||
1345 | |||
1346 | return error ?: count; | ||
1347 | } | ||
1348 | |||
1349 | static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR, | ||
1350 | ims_pcu_ofn_reg_data_show, ims_pcu_ofn_reg_data_store); | ||
1351 | |||
1352 | static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev, | ||
1353 | struct device_attribute *dattr, | ||
1354 | char *buf) | ||
1355 | { | ||
1356 | struct usb_interface *intf = to_usb_interface(dev); | ||
1357 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1358 | int error; | ||
1359 | |||
1360 | mutex_lock(&pcu->cmd_mutex); | ||
1361 | error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr); | ||
1362 | mutex_unlock(&pcu->cmd_mutex); | ||
1363 | |||
1364 | return error; | ||
1365 | } | ||
1366 | |||
1367 | static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, | ||
1368 | struct device_attribute *dattr, | ||
1369 | const char *buf, size_t count) | ||
1370 | { | ||
1371 | struct usb_interface *intf = to_usb_interface(dev); | ||
1372 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1373 | int error; | ||
1374 | u8 value; | ||
1375 | |||
1376 | error = kstrtou8(buf, 0, &value); | ||
1377 | if (error) | ||
1378 | return error; | ||
1379 | |||
1380 | mutex_lock(&pcu->cmd_mutex); | ||
1381 | pcu->ofn_reg_addr = value; | ||
1382 | mutex_unlock(&pcu->cmd_mutex); | ||
1383 | |||
1384 | return error ?: count; | ||
1385 | } | ||
1386 | |||
1387 | static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR, | ||
1388 | ims_pcu_ofn_reg_addr_show, ims_pcu_ofn_reg_addr_store); | ||
1389 | |||
1390 | struct ims_pcu_ofn_bit_attribute { | ||
1391 | struct device_attribute dattr; | ||
1392 | u8 addr; | ||
1393 | u8 nr; | ||
1394 | }; | ||
1395 | |||
1396 | static ssize_t ims_pcu_ofn_bit_show(struct device *dev, | ||
1397 | struct device_attribute *dattr, | ||
1398 | char *buf) | ||
1399 | { | ||
1400 | struct usb_interface *intf = to_usb_interface(dev); | ||
1401 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1402 | struct ims_pcu_ofn_bit_attribute *attr = | ||
1403 | container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); | ||
1404 | int error; | ||
1405 | u8 data; | ||
1406 | |||
1407 | mutex_lock(&pcu->cmd_mutex); | ||
1408 | error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); | ||
1409 | mutex_unlock(&pcu->cmd_mutex); | ||
1410 | |||
1411 | if (error) | ||
1412 | return error; | ||
1413 | |||
1414 | return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr))); | ||
1415 | } | ||
1416 | |||
1417 | static ssize_t ims_pcu_ofn_bit_store(struct device *dev, | ||
1418 | struct device_attribute *dattr, | ||
1419 | const char *buf, size_t count) | ||
1420 | { | ||
1421 | struct usb_interface *intf = to_usb_interface(dev); | ||
1422 | struct ims_pcu *pcu = usb_get_intfdata(intf); | ||
1423 | struct ims_pcu_ofn_bit_attribute *attr = | ||
1424 | container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr); | ||
1425 | int error; | ||
1426 | int value; | ||
1427 | u8 data; | ||
1428 | |||
1429 | error = kstrtoint(buf, 0, &value); | ||
1430 | if (error) | ||
1431 | return error; | ||
1432 | |||
1433 | if (value > 1) | ||
1434 | return -EINVAL; | ||
1435 | |||
1436 | mutex_lock(&pcu->cmd_mutex); | ||
1437 | |||
1438 | error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); | ||
1439 | if (!error) { | ||
1440 | if (value) | ||
1441 | data |= 1U << attr->nr; | ||
1442 | else | ||
1443 | data &= ~(1U << attr->nr); | ||
1444 | |||
1445 | error = ims_pcu_write_ofn_config(pcu, attr->addr, data); | ||
1446 | } | ||
1447 | |||
1448 | mutex_unlock(&pcu->cmd_mutex); | ||
1449 | |||
1450 | return error ?: count; | ||
1451 | } | ||
1452 | |||
1453 | #define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr) \ | ||
1454 | struct ims_pcu_ofn_bit_attribute ims_pcu_ofn_attr_##_field = { \ | ||
1455 | .dattr = __ATTR(_field, S_IWUSR | S_IRUGO, \ | ||
1456 | ims_pcu_ofn_bit_show, ims_pcu_ofn_bit_store), \ | ||
1457 | .addr = _addr, \ | ||
1458 | .nr = _nr, \ | ||
1459 | } | ||
1460 | |||
1461 | static IMS_PCU_OFN_BIT_ATTR(engine_enable, 0x60, 7); | ||
1462 | static IMS_PCU_OFN_BIT_ATTR(speed_enable, 0x60, 6); | ||
1463 | static IMS_PCU_OFN_BIT_ATTR(assert_enable, 0x60, 5); | ||
1464 | static IMS_PCU_OFN_BIT_ATTR(xyquant_enable, 0x60, 4); | ||
1465 | static IMS_PCU_OFN_BIT_ATTR(xyscale_enable, 0x60, 1); | ||
1466 | |||
1467 | static IMS_PCU_OFN_BIT_ATTR(scale_x2, 0x63, 6); | ||
1468 | static IMS_PCU_OFN_BIT_ATTR(scale_y2, 0x63, 7); | ||
1469 | |||
1470 | static struct attribute *ims_pcu_ofn_attrs[] = { | ||
1471 | &dev_attr_reg_data.attr, | ||
1472 | &dev_attr_reg_addr.attr, | ||
1473 | &ims_pcu_ofn_attr_engine_enable.dattr.attr, | ||
1474 | &ims_pcu_ofn_attr_speed_enable.dattr.attr, | ||
1475 | &ims_pcu_ofn_attr_assert_enable.dattr.attr, | ||
1476 | &ims_pcu_ofn_attr_xyquant_enable.dattr.attr, | ||
1477 | &ims_pcu_ofn_attr_xyscale_enable.dattr.attr, | ||
1478 | &ims_pcu_ofn_attr_scale_x2.dattr.attr, | ||
1479 | &ims_pcu_ofn_attr_scale_y2.dattr.attr, | ||
1480 | NULL | ||
1481 | }; | ||
1482 | |||
1483 | static struct attribute_group ims_pcu_ofn_attr_group = { | ||
1484 | .name = "ofn", | ||
1485 | .attrs = ims_pcu_ofn_attrs, | ||
1486 | }; | ||
1487 | |||
1259 | static void ims_pcu_irq(struct urb *urb) | 1488 | static void ims_pcu_irq(struct urb *urb) |
1260 | { | 1489 | { |
1261 | struct ims_pcu *pcu = urb->context; | 1490 | struct ims_pcu *pcu = urb->context; |
@@ -1624,7 +1853,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1624 | static atomic_t device_no = ATOMIC_INIT(0); | 1853 | static atomic_t device_no = ATOMIC_INIT(0); |
1625 | 1854 | ||
1626 | const struct ims_pcu_device_info *info; | 1855 | const struct ims_pcu_device_info *info; |
1627 | u8 device_id; | ||
1628 | int error; | 1856 | int error; |
1629 | 1857 | ||
1630 | error = ims_pcu_get_device_info(pcu); | 1858 | error = ims_pcu_get_device_info(pcu); |
@@ -1633,7 +1861,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1633 | return error; | 1861 | return error; |
1634 | } | 1862 | } |
1635 | 1863 | ||
1636 | error = ims_pcu_identify_type(pcu, &device_id); | 1864 | error = ims_pcu_identify_type(pcu, &pcu->device_id); |
1637 | if (error) { | 1865 | if (error) { |
1638 | dev_err(pcu->dev, | 1866 | dev_err(pcu->dev, |
1639 | "Failed to identify device, error: %d\n", error); | 1867 | "Failed to identify device, error: %d\n", error); |
@@ -1645,9 +1873,9 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1645 | return 0; | 1873 | return 0; |
1646 | } | 1874 | } |
1647 | 1875 | ||
1648 | if (device_id >= ARRAY_SIZE(ims_pcu_device_info) || | 1876 | if (pcu->device_id >= ARRAY_SIZE(ims_pcu_device_info) || |
1649 | !ims_pcu_device_info[device_id].keymap) { | 1877 | !ims_pcu_device_info[pcu->device_id].keymap) { |
1650 | dev_err(pcu->dev, "Device ID %d is not valid\n", device_id); | 1878 | dev_err(pcu->dev, "Device ID %d is not valid\n", pcu->device_id); |
1651 | /* Same as above, punt to userspace */ | 1879 | /* Same as above, punt to userspace */ |
1652 | return 0; | 1880 | return 0; |
1653 | } | 1881 | } |
@@ -1655,11 +1883,21 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1655 | /* Device appears to be operable, complete initialization */ | 1883 | /* Device appears to be operable, complete initialization */ |
1656 | pcu->device_no = atomic_inc_return(&device_no) - 1; | 1884 | pcu->device_no = atomic_inc_return(&device_no) - 1; |
1657 | 1885 | ||
1886 | /* | ||
1887 | * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor | ||
1888 | */ | ||
1889 | if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) { | ||
1890 | error = sysfs_create_group(&pcu->dev->kobj, | ||
1891 | &ims_pcu_ofn_attr_group); | ||
1892 | if (error) | ||
1893 | return error; | ||
1894 | } | ||
1895 | |||
1658 | error = ims_pcu_setup_backlight(pcu); | 1896 | error = ims_pcu_setup_backlight(pcu); |
1659 | if (error) | 1897 | if (error) |
1660 | return error; | 1898 | return error; |
1661 | 1899 | ||
1662 | info = &ims_pcu_device_info[device_id]; | 1900 | info = &ims_pcu_device_info[pcu->device_id]; |
1663 | error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len); | 1901 | error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len); |
1664 | if (error) | 1902 | if (error) |
1665 | goto err_destroy_backlight; | 1903 | goto err_destroy_backlight; |
@@ -1674,10 +1912,10 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) | |||
1674 | 1912 | ||
1675 | return 0; | 1913 | return 0; |
1676 | 1914 | ||
1677 | err_destroy_backlight: | ||
1678 | ims_pcu_destroy_backlight(pcu); | ||
1679 | err_destroy_buttons: | 1915 | err_destroy_buttons: |
1680 | ims_pcu_destroy_buttons(pcu); | 1916 | ims_pcu_destroy_buttons(pcu); |
1917 | err_destroy_backlight: | ||
1918 | ims_pcu_destroy_backlight(pcu); | ||
1681 | return error; | 1919 | return error; |
1682 | } | 1920 | } |
1683 | 1921 | ||
@@ -1691,6 +1929,10 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu) | |||
1691 | ims_pcu_destroy_gamepad(pcu); | 1929 | ims_pcu_destroy_gamepad(pcu); |
1692 | ims_pcu_destroy_buttons(pcu); | 1930 | ims_pcu_destroy_buttons(pcu); |
1693 | ims_pcu_destroy_backlight(pcu); | 1931 | ims_pcu_destroy_backlight(pcu); |
1932 | |||
1933 | if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) | ||
1934 | sysfs_remove_group(&pcu->dev->kobj, | ||
1935 | &ims_pcu_ofn_attr_group); | ||
1694 | } | 1936 | } |
1695 | } | 1937 | } |
1696 | 1938 | ||
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index b88b7cbf93e2..6a915ba31bba 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c | |||
@@ -142,7 +142,6 @@ static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data, | |||
142 | } | 142 | } |
143 | 143 | ||
144 | static int pm8xxx_vib_probe(struct platform_device *pdev) | 144 | static int pm8xxx_vib_probe(struct platform_device *pdev) |
145 | |||
146 | { | 145 | { |
147 | struct pm8xxx_vib *vib; | 146 | struct pm8xxx_vib *vib; |
148 | struct input_dev *input_dev; | 147 | struct input_dev *input_dev; |
@@ -214,12 +213,20 @@ static int pm8xxx_vib_suspend(struct device *dev) | |||
214 | 213 | ||
215 | static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); | 214 | static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); |
216 | 215 | ||
216 | static const struct of_device_id pm8xxx_vib_id_table[] = { | ||
217 | { .compatible = "qcom,pm8058-vib" }, | ||
218 | { .compatible = "qcom,pm8921-vib" }, | ||
219 | { } | ||
220 | }; | ||
221 | MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table); | ||
222 | |||
217 | static struct platform_driver pm8xxx_vib_driver = { | 223 | static struct platform_driver pm8xxx_vib_driver = { |
218 | .probe = pm8xxx_vib_probe, | 224 | .probe = pm8xxx_vib_probe, |
219 | .driver = { | 225 | .driver = { |
220 | .name = "pm8xxx-vib", | 226 | .name = "pm8xxx-vib", |
221 | .owner = THIS_MODULE, | 227 | .owner = THIS_MODULE, |
222 | .pm = &pm8xxx_vib_pm_ops, | 228 | .pm = &pm8xxx_vib_pm_ops, |
229 | .of_match_table = pm8xxx_vib_id_table, | ||
223 | }, | 230 | }, |
224 | }; | 231 | }; |
225 | module_platform_driver(pm8xxx_vib_driver); | 232 | module_platform_driver(pm8xxx_vib_driver); |
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 0e1a05f95858..1cb8fda7a166 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c | |||
@@ -19,8 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
21 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
22 | 22 | #include <linux/of.h> | |
23 | #include <linux/input/pmic8xxx-pwrkey.h> | ||
24 | 23 | ||
25 | #define PON_CNTL_1 0x1C | 24 | #define PON_CNTL_1 0x1C |
26 | #define PON_CNTL_PULL_UP BIT(7) | 25 | #define PON_CNTL_PULL_UP BIT(7) |
@@ -89,15 +88,15 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
89 | unsigned int pon_cntl; | 88 | unsigned int pon_cntl; |
90 | struct regmap *regmap; | 89 | struct regmap *regmap; |
91 | struct pmic8xxx_pwrkey *pwrkey; | 90 | struct pmic8xxx_pwrkey *pwrkey; |
92 | const struct pm8xxx_pwrkey_platform_data *pdata = | 91 | u32 kpd_delay; |
93 | dev_get_platdata(&pdev->dev); | 92 | bool pull_up; |
94 | 93 | ||
95 | if (!pdata) { | 94 | if (of_property_read_u32(pdev->dev.of_node, "debounce", &kpd_delay)) |
96 | dev_err(&pdev->dev, "power key platform data not supplied\n"); | 95 | kpd_delay = 0; |
97 | return -EINVAL; | ||
98 | } | ||
99 | 96 | ||
100 | if (pdata->kpd_trigger_delay_us > 62500) { | 97 | pull_up = of_property_read_bool(pdev->dev.of_node, "pull-up"); |
98 | |||
99 | if (kpd_delay > 62500) { | ||
101 | dev_err(&pdev->dev, "invalid power key trigger delay\n"); | 100 | dev_err(&pdev->dev, "invalid power key trigger delay\n"); |
102 | return -EINVAL; | 101 | return -EINVAL; |
103 | } | 102 | } |
@@ -125,7 +124,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
125 | pwr->name = "pmic8xxx_pwrkey"; | 124 | pwr->name = "pmic8xxx_pwrkey"; |
126 | pwr->phys = "pmic8xxx_pwrkey/input0"; | 125 | pwr->phys = "pmic8xxx_pwrkey/input0"; |
127 | 126 | ||
128 | delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC; | 127 | delay = (kpd_delay << 10) / USEC_PER_SEC; |
129 | delay = 1 + ilog2(delay); | 128 | delay = 1 + ilog2(delay); |
130 | 129 | ||
131 | err = regmap_read(regmap, PON_CNTL_1, &pon_cntl); | 130 | err = regmap_read(regmap, PON_CNTL_1, &pon_cntl); |
@@ -136,7 +135,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
136 | 135 | ||
137 | pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; | 136 | pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; |
138 | pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); | 137 | pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); |
139 | if (pdata->pull_up) | 138 | if (pull_up) |
140 | pon_cntl |= PON_CNTL_PULL_UP; | 139 | pon_cntl |= PON_CNTL_PULL_UP; |
141 | else | 140 | else |
142 | pon_cntl &= ~PON_CNTL_PULL_UP; | 141 | pon_cntl &= ~PON_CNTL_PULL_UP; |
@@ -172,7 +171,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) | |||
172 | } | 171 | } |
173 | 172 | ||
174 | platform_set_drvdata(pdev, pwrkey); | 173 | platform_set_drvdata(pdev, pwrkey); |
175 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 174 | device_init_wakeup(&pdev->dev, 1); |
176 | 175 | ||
177 | return 0; | 176 | return 0; |
178 | } | 177 | } |
@@ -184,13 +183,21 @@ static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) | |||
184 | return 0; | 183 | return 0; |
185 | } | 184 | } |
186 | 185 | ||
186 | static const struct of_device_id pm8xxx_pwr_key_id_table[] = { | ||
187 | { .compatible = "qcom,pm8058-pwrkey" }, | ||
188 | { .compatible = "qcom,pm8921-pwrkey" }, | ||
189 | { } | ||
190 | }; | ||
191 | MODULE_DEVICE_TABLE(of, pm8xxx_pwr_key_id_table); | ||
192 | |||
187 | static struct platform_driver pmic8xxx_pwrkey_driver = { | 193 | static struct platform_driver pmic8xxx_pwrkey_driver = { |
188 | .probe = pmic8xxx_pwrkey_probe, | 194 | .probe = pmic8xxx_pwrkey_probe, |
189 | .remove = pmic8xxx_pwrkey_remove, | 195 | .remove = pmic8xxx_pwrkey_remove, |
190 | .driver = { | 196 | .driver = { |
191 | .name = PM8XXX_PWRKEY_DEV_NAME, | 197 | .name = "pm8xxx-pwrkey", |
192 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
193 | .pm = &pm8xxx_pwr_key_pm_ops, | 199 | .pm = &pm8xxx_pwr_key_pm_ops, |
200 | .of_match_table = pm8xxx_pwr_key_id_table, | ||
194 | }, | 201 | }, |
195 | }; | 202 | }; |
196 | module_platform_driver(pmic8xxx_pwrkey_driver); | 203 | module_platform_driver(pmic8xxx_pwrkey_driver); |
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index e8897c36d21b..e4104f9b2e6d 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Power key driver for SiRF PrimaII | 2 | * Power key driver for SiRF PrimaII |
3 | * | 3 | * |
4 | * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company. | 4 | * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group |
5 | * company. | ||
5 | * | 6 | * |
6 | * Licensed under GPLv2 or later. | 7 | * Licensed under GPLv2 or later. |
7 | */ | 8 | */ |
@@ -13,16 +14,41 @@ | |||
13 | #include <linux/input.h> | 14 | #include <linux/input.h> |
14 | #include <linux/rtc/sirfsoc_rtciobrg.h> | 15 | #include <linux/rtc/sirfsoc_rtciobrg.h> |
15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/workqueue.h> | ||
16 | 18 | ||
17 | struct sirfsoc_pwrc_drvdata { | 19 | struct sirfsoc_pwrc_drvdata { |
18 | u32 pwrc_base; | 20 | u32 pwrc_base; |
19 | struct input_dev *input; | 21 | struct input_dev *input; |
22 | struct delayed_work work; | ||
20 | }; | 23 | }; |
21 | 24 | ||
22 | #define PWRC_ON_KEY_BIT (1 << 0) | 25 | #define PWRC_ON_KEY_BIT (1 << 0) |
23 | 26 | ||
24 | #define PWRC_INT_STATUS 0xc | 27 | #define PWRC_INT_STATUS 0xc |
25 | #define PWRC_INT_MASK 0x10 | 28 | #define PWRC_INT_MASK 0x10 |
29 | #define PWRC_PIN_STATUS 0x14 | ||
30 | #define PWRC_KEY_DETECT_UP_TIME 20 /* ms*/ | ||
31 | |||
32 | static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv) | ||
33 | { | ||
34 | u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + | ||
35 | PWRC_PIN_STATUS); | ||
36 | return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */ | ||
37 | } | ||
38 | |||
39 | static void sirfsoc_pwrc_report_event(struct work_struct *work) | ||
40 | { | ||
41 | struct sirfsoc_pwrc_drvdata *pwrcdrv = | ||
42 | container_of(work, struct sirfsoc_pwrc_drvdata, work.work); | ||
43 | |||
44 | if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) { | ||
45 | schedule_delayed_work(&pwrcdrv->work, | ||
46 | msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); | ||
47 | } else { | ||
48 | input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0); | ||
49 | input_sync(pwrcdrv->input); | ||
50 | } | ||
51 | } | ||
26 | 52 | ||
27 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | 53 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) |
28 | { | 54 | { |
@@ -34,21 +60,44 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | |||
34 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, | 60 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, |
35 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); | 61 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); |
36 | 62 | ||
37 | /* | 63 | input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1); |
38 | * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c | ||
39 | * to queue a SUSPEND APM event | ||
40 | */ | ||
41 | input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); | ||
42 | input_sync(pwrcdrv->input); | 64 | input_sync(pwrcdrv->input); |
43 | 65 | schedule_delayed_work(&pwrcdrv->work, | |
44 | /* | 66 | msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); |
45 | * Todo: report KEY_POWER event for Android platforms, Android PowerManager | ||
46 | * will handle the suspend and powerdown/hibernation | ||
47 | */ | ||
48 | 67 | ||
49 | return IRQ_HANDLED; | 68 | return IRQ_HANDLED; |
50 | } | 69 | } |
51 | 70 | ||
71 | static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv, | ||
72 | bool enable) | ||
73 | { | ||
74 | u32 int_mask; | ||
75 | |||
76 | int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
77 | if (enable) | ||
78 | int_mask |= PWRC_ON_KEY_BIT; | ||
79 | else | ||
80 | int_mask &= ~PWRC_ON_KEY_BIT; | ||
81 | sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
82 | } | ||
83 | |||
84 | static int sirfsoc_pwrc_open(struct input_dev *input) | ||
85 | { | ||
86 | struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); | ||
87 | |||
88 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void sirfsoc_pwrc_close(struct input_dev *input) | ||
94 | { | ||
95 | struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); | ||
96 | |||
97 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); | ||
98 | cancel_delayed_work_sync(&pwrcdrv->work); | ||
99 | } | ||
100 | |||
52 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { | 101 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { |
53 | { .compatible = "sirf,prima2-pwrc" }, | 102 | { .compatible = "sirf,prima2-pwrc" }, |
54 | {}, | 103 | {}, |
@@ -70,7 +119,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
70 | } | 119 | } |
71 | 120 | ||
72 | /* | 121 | /* |
73 | * we can't use of_iomap because pwrc is not mapped in memory, | 122 | * We can't use of_iomap because pwrc is not mapped in memory, |
74 | * the so-called base address is only offset in rtciobrg | 123 | * the so-called base address is only offset in rtciobrg |
75 | */ | 124 | */ |
76 | error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); | 125 | error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base); |
@@ -86,11 +135,22 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
86 | 135 | ||
87 | pwrcdrv->input->name = "sirfsoc pwrckey"; | 136 | pwrcdrv->input->name = "sirfsoc pwrckey"; |
88 | pwrcdrv->input->phys = "pwrc/input0"; | 137 | pwrcdrv->input->phys = "pwrc/input0"; |
89 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); | 138 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY); |
139 | input_set_capability(pwrcdrv->input, EV_KEY, KEY_POWER); | ||
140 | |||
141 | INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event); | ||
142 | |||
143 | pwrcdrv->input->open = sirfsoc_pwrc_open; | ||
144 | pwrcdrv->input->close = sirfsoc_pwrc_close; | ||
145 | |||
146 | input_set_drvdata(pwrcdrv->input, pwrcdrv); | ||
147 | |||
148 | /* Make sure the device is quiesced */ | ||
149 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); | ||
90 | 150 | ||
91 | irq = platform_get_irq(pdev, 0); | 151 | irq = platform_get_irq(pdev, 0); |
92 | error = devm_request_irq(&pdev->dev, irq, | 152 | error = devm_request_irq(&pdev->dev, irq, |
93 | sirfsoc_pwrc_isr, IRQF_SHARED, | 153 | sirfsoc_pwrc_isr, 0, |
94 | "sirfsoc_pwrc_int", pwrcdrv); | 154 | "sirfsoc_pwrc_int", pwrcdrv); |
95 | if (error) { | 155 | if (error) { |
96 | dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", | 156 | dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n", |
@@ -98,11 +158,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
98 | return error; | 158 | return error; |
99 | } | 159 | } |
100 | 160 | ||
101 | sirfsoc_rtc_iobrg_writel( | ||
102 | sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) | | ||
103 | PWRC_ON_KEY_BIT, | ||
104 | pwrcdrv->pwrc_base + PWRC_INT_MASK); | ||
105 | |||
106 | error = input_register_device(pwrcdrv->input); | 161 | error = input_register_device(pwrcdrv->input); |
107 | if (error) { | 162 | if (error) { |
108 | dev_err(&pdev->dev, | 163 | dev_err(&pdev->dev, |
@@ -111,7 +166,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
111 | return error; | 166 | return error; |
112 | } | 167 | } |
113 | 168 | ||
114 | platform_set_drvdata(pdev, pwrcdrv); | 169 | dev_set_drvdata(&pdev->dev, pwrcdrv); |
115 | device_init_wakeup(&pdev->dev, 1); | 170 | device_init_wakeup(&pdev->dev, 1); |
116 | 171 | ||
117 | return 0; | 172 | return 0; |
@@ -125,25 +180,25 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev) | |||
125 | } | 180 | } |
126 | 181 | ||
127 | #ifdef CONFIG_PM_SLEEP | 182 | #ifdef CONFIG_PM_SLEEP |
128 | static int pwrc_resume(struct device *dev) | 183 | static int sirfsoc_pwrc_resume(struct device *dev) |
129 | { | 184 | { |
130 | struct platform_device *pdev = to_platform_device(dev); | 185 | struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev); |
131 | struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev); | 186 | struct input_dev *input = pwrcdrv->input; |
132 | 187 | ||
133 | /* | 188 | /* |
134 | * Do not mask pwrc interrupt as we want pwrc work as a wakeup source | 189 | * Do not mask pwrc interrupt as we want pwrc work as a wakeup source |
135 | * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c | 190 | * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c |
136 | */ | 191 | */ |
137 | sirfsoc_rtc_iobrg_writel( | 192 | mutex_lock(&input->mutex); |
138 | sirfsoc_rtc_iobrg_readl( | 193 | if (input->users) |
139 | pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT, | 194 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true); |
140 | pwrcdrv->pwrc_base + PWRC_INT_MASK); | 195 | mutex_unlock(&input->mutex); |
141 | 196 | ||
142 | return 0; | 197 | return 0; |
143 | } | 198 | } |
144 | #endif | 199 | #endif |
145 | 200 | ||
146 | static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume); | 201 | static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume); |
147 | 202 | ||
148 | static struct platform_driver sirfsoc_pwrc_driver = { | 203 | static struct platform_driver sirfsoc_pwrc_driver = { |
149 | .probe = sirfsoc_pwrc_probe, | 204 | .probe = sirfsoc_pwrc_probe, |
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c new file mode 100644 index 000000000000..08ead2aaede5 --- /dev/null +++ b/drivers/input/misc/soc_button_array.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * Supports for the button array on SoC tablets originally running | ||
3 | * Windows 8. | ||
4 | * | ||
5 | * (C) Copyright 2014 Intel Corporation | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; version 2 | ||
10 | * of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/input.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/acpi.h> | ||
18 | #include <linux/gpio/consumer.h> | ||
19 | #include <linux/gpio_keys.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/pnp.h> | ||
23 | |||
24 | /* | ||
25 | * Definition of buttons on the tablet. The ACPI index of each button | ||
26 | * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC | ||
27 | * Platforms" | ||
28 | */ | ||
29 | #define MAX_NBUTTONS 5 | ||
30 | |||
31 | struct soc_button_info { | ||
32 | const char *name; | ||
33 | int acpi_index; | ||
34 | unsigned int event_type; | ||
35 | unsigned int event_code; | ||
36 | bool autorepeat; | ||
37 | bool wakeup; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * Some of the buttons like volume up/down are auto repeat, while others | ||
42 | * are not. To support both, we register two platform devices, and put | ||
43 | * buttons into them based on whether the key should be auto repeat. | ||
44 | */ | ||
45 | #define BUTTON_TYPES 2 | ||
46 | |||
47 | struct soc_button_data { | ||
48 | struct platform_device *children[BUTTON_TYPES]; | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * Get the Nth GPIO number from the ACPI object. | ||
53 | */ | ||
54 | static int soc_button_lookup_gpio(struct device *dev, int acpi_index) | ||
55 | { | ||
56 | struct gpio_desc *desc; | ||
57 | int gpio; | ||
58 | |||
59 | desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index); | ||
60 | if (IS_ERR(desc)) | ||
61 | return PTR_ERR(desc); | ||
62 | |||
63 | gpio = desc_to_gpio(desc); | ||
64 | |||
65 | gpiod_put(desc); | ||
66 | |||
67 | return gpio; | ||
68 | } | ||
69 | |||
70 | static struct platform_device * | ||
71 | soc_button_device_create(struct pnp_dev *pdev, | ||
72 | const struct soc_button_info *button_info, | ||
73 | bool autorepeat) | ||
74 | { | ||
75 | const struct soc_button_info *info; | ||
76 | struct platform_device *pd; | ||
77 | struct gpio_keys_button *gpio_keys; | ||
78 | struct gpio_keys_platform_data *gpio_keys_pdata; | ||
79 | int n_buttons = 0; | ||
80 | int gpio; | ||
81 | int error; | ||
82 | |||
83 | gpio_keys_pdata = devm_kzalloc(&pdev->dev, | ||
84 | sizeof(*gpio_keys_pdata) + | ||
85 | sizeof(*gpio_keys) * MAX_NBUTTONS, | ||
86 | GFP_KERNEL); | ||
87 | gpio_keys = (void *)(gpio_keys_pdata + 1); | ||
88 | |||
89 | for (info = button_info; info->name; info++) { | ||
90 | if (info->autorepeat != autorepeat) | ||
91 | continue; | ||
92 | |||
93 | gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index); | ||
94 | if (gpio < 0) | ||
95 | continue; | ||
96 | |||
97 | gpio_keys[n_buttons].type = info->event_type; | ||
98 | gpio_keys[n_buttons].code = info->event_code; | ||
99 | gpio_keys[n_buttons].gpio = gpio; | ||
100 | gpio_keys[n_buttons].active_low = 1; | ||
101 | gpio_keys[n_buttons].desc = info->name; | ||
102 | gpio_keys[n_buttons].wakeup = info->wakeup; | ||
103 | n_buttons++; | ||
104 | } | ||
105 | |||
106 | if (n_buttons == 0) { | ||
107 | error = -ENODEV; | ||
108 | goto err_free_mem; | ||
109 | } | ||
110 | |||
111 | gpio_keys_pdata->buttons = gpio_keys; | ||
112 | gpio_keys_pdata->nbuttons = n_buttons; | ||
113 | gpio_keys_pdata->rep = autorepeat; | ||
114 | |||
115 | pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO); | ||
116 | if (!pd) { | ||
117 | error = -ENOMEM; | ||
118 | goto err_free_mem; | ||
119 | } | ||
120 | |||
121 | error = platform_device_add_data(pd, gpio_keys_pdata, | ||
122 | sizeof(*gpio_keys_pdata)); | ||
123 | if (error) | ||
124 | goto err_free_pdev; | ||
125 | |||
126 | error = platform_device_add(pd); | ||
127 | if (error) | ||
128 | goto err_free_pdev; | ||
129 | |||
130 | return pd; | ||
131 | |||
132 | err_free_pdev: | ||
133 | platform_device_put(pd); | ||
134 | err_free_mem: | ||
135 | devm_kfree(&pdev->dev, gpio_keys_pdata); | ||
136 | return ERR_PTR(error); | ||
137 | } | ||
138 | |||
139 | static void soc_button_remove(struct pnp_dev *pdev) | ||
140 | { | ||
141 | struct soc_button_data *priv = pnp_get_drvdata(pdev); | ||
142 | int i; | ||
143 | |||
144 | for (i = 0; i < BUTTON_TYPES; i++) | ||
145 | if (priv->children[i]) | ||
146 | platform_device_unregister(priv->children[i]); | ||
147 | } | ||
148 | |||
149 | static int soc_button_pnp_probe(struct pnp_dev *pdev, | ||
150 | const struct pnp_device_id *id) | ||
151 | { | ||
152 | const struct soc_button_info *button_info = (void *)id->driver_data; | ||
153 | struct soc_button_data *priv; | ||
154 | struct platform_device *pd; | ||
155 | int i; | ||
156 | int error; | ||
157 | |||
158 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
159 | if (!priv) | ||
160 | return -ENOMEM; | ||
161 | |||
162 | pnp_set_drvdata(pdev, priv); | ||
163 | |||
164 | for (i = 0; i < BUTTON_TYPES; i++) { | ||
165 | pd = soc_button_device_create(pdev, button_info, i == 0); | ||
166 | if (IS_ERR(pd)) { | ||
167 | error = PTR_ERR(pd); | ||
168 | if (error != -ENODEV) { | ||
169 | soc_button_remove(pdev); | ||
170 | return error; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | priv->children[i] = pd; | ||
175 | } | ||
176 | |||
177 | if (!priv->children[0] && !priv->children[1]) | ||
178 | return -ENODEV; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static struct soc_button_info soc_button_PNP0C40[] = { | ||
184 | { "power", 0, EV_KEY, KEY_POWER, false, true }, | ||
185 | { "home", 1, EV_KEY, KEY_HOME, false, true }, | ||
186 | { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false }, | ||
187 | { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false }, | ||
188 | { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false }, | ||
189 | { } | ||
190 | }; | ||
191 | |||
192 | static const struct pnp_device_id soc_button_pnp_match[] = { | ||
193 | { .id = "PNP0C40", .driver_data = (long)soc_button_PNP0C40 }, | ||
194 | { .id = "" } | ||
195 | }; | ||
196 | MODULE_DEVICE_TABLE(pnp, soc_button_pnp_match); | ||
197 | |||
198 | static struct pnp_driver soc_button_pnp_driver = { | ||
199 | .name = KBUILD_MODNAME, | ||
200 | .id_table = soc_button_pnp_match, | ||
201 | .probe = soc_button_pnp_probe, | ||
202 | .remove = soc_button_remove, | ||
203 | }; | ||
204 | |||
205 | static int __init soc_button_init(void) | ||
206 | { | ||
207 | return pnp_register_driver(&soc_button_pnp_driver); | ||
208 | } | ||
209 | |||
210 | static void __exit soc_button_exit(void) | ||
211 | { | ||
212 | pnp_unregister_driver(&soc_button_pnp_driver); | ||
213 | } | ||
214 | |||
215 | module_init(soc_button_init); | ||
216 | module_exit(soc_button_exit); | ||
217 | |||
218 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 772835938a52..856936247500 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> | 20 | * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> |
21 | * | 21 | * |
22 | * Changes/Revisions: | 22 | * Changes/Revisions: |
23 | * 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>) | ||
24 | * - add UI_GET_SYSNAME ioctl | ||
23 | * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) | 25 | * 0.3 09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>) |
24 | * - updated ff support for the changes in kernel interface | 26 | * - updated ff support for the changes in kernel interface |
25 | * - added MODULE_VERSION | 27 | * - added MODULE_VERSION |
@@ -670,6 +672,31 @@ static int uinput_ff_upload_from_user(const char __user *buffer, | |||
670 | __ret; \ | 672 | __ret; \ |
671 | }) | 673 | }) |
672 | 674 | ||
675 | static int uinput_str_to_user(void __user *dest, const char *str, | ||
676 | unsigned int maxlen) | ||
677 | { | ||
678 | char __user *p = dest; | ||
679 | int len, ret; | ||
680 | |||
681 | if (!str) | ||
682 | return -ENOENT; | ||
683 | |||
684 | if (maxlen == 0) | ||
685 | return -EINVAL; | ||
686 | |||
687 | len = strlen(str) + 1; | ||
688 | if (len > maxlen) | ||
689 | len = maxlen; | ||
690 | |||
691 | ret = copy_to_user(p, str, len); | ||
692 | if (ret) | ||
693 | return -EFAULT; | ||
694 | |||
695 | /* force terminating '\0' */ | ||
696 | ret = put_user(0, p + len - 1); | ||
697 | return ret ? -EFAULT : len; | ||
698 | } | ||
699 | |||
673 | static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | 700 | static long uinput_ioctl_handler(struct file *file, unsigned int cmd, |
674 | unsigned long arg, void __user *p) | 701 | unsigned long arg, void __user *p) |
675 | { | 702 | { |
@@ -679,6 +706,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
679 | struct uinput_ff_erase ff_erase; | 706 | struct uinput_ff_erase ff_erase; |
680 | struct uinput_request *req; | 707 | struct uinput_request *req; |
681 | char *phys; | 708 | char *phys; |
709 | const char *name; | ||
710 | unsigned int size; | ||
682 | 711 | ||
683 | retval = mutex_lock_interruptible(&udev->mutex); | 712 | retval = mutex_lock_interruptible(&udev->mutex); |
684 | if (retval) | 713 | if (retval) |
@@ -693,51 +722,51 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
693 | switch (cmd) { | 722 | switch (cmd) { |
694 | case UI_DEV_CREATE: | 723 | case UI_DEV_CREATE: |
695 | retval = uinput_create_device(udev); | 724 | retval = uinput_create_device(udev); |
696 | break; | 725 | goto out; |
697 | 726 | ||
698 | case UI_DEV_DESTROY: | 727 | case UI_DEV_DESTROY: |
699 | uinput_destroy_device(udev); | 728 | uinput_destroy_device(udev); |
700 | break; | 729 | goto out; |
701 | 730 | ||
702 | case UI_SET_EVBIT: | 731 | case UI_SET_EVBIT: |
703 | retval = uinput_set_bit(arg, evbit, EV_MAX); | 732 | retval = uinput_set_bit(arg, evbit, EV_MAX); |
704 | break; | 733 | goto out; |
705 | 734 | ||
706 | case UI_SET_KEYBIT: | 735 | case UI_SET_KEYBIT: |
707 | retval = uinput_set_bit(arg, keybit, KEY_MAX); | 736 | retval = uinput_set_bit(arg, keybit, KEY_MAX); |
708 | break; | 737 | goto out; |
709 | 738 | ||
710 | case UI_SET_RELBIT: | 739 | case UI_SET_RELBIT: |
711 | retval = uinput_set_bit(arg, relbit, REL_MAX); | 740 | retval = uinput_set_bit(arg, relbit, REL_MAX); |
712 | break; | 741 | goto out; |
713 | 742 | ||
714 | case UI_SET_ABSBIT: | 743 | case UI_SET_ABSBIT: |
715 | retval = uinput_set_bit(arg, absbit, ABS_MAX); | 744 | retval = uinput_set_bit(arg, absbit, ABS_MAX); |
716 | break; | 745 | goto out; |
717 | 746 | ||
718 | case UI_SET_MSCBIT: | 747 | case UI_SET_MSCBIT: |
719 | retval = uinput_set_bit(arg, mscbit, MSC_MAX); | 748 | retval = uinput_set_bit(arg, mscbit, MSC_MAX); |
720 | break; | 749 | goto out; |
721 | 750 | ||
722 | case UI_SET_LEDBIT: | 751 | case UI_SET_LEDBIT: |
723 | retval = uinput_set_bit(arg, ledbit, LED_MAX); | 752 | retval = uinput_set_bit(arg, ledbit, LED_MAX); |
724 | break; | 753 | goto out; |
725 | 754 | ||
726 | case UI_SET_SNDBIT: | 755 | case UI_SET_SNDBIT: |
727 | retval = uinput_set_bit(arg, sndbit, SND_MAX); | 756 | retval = uinput_set_bit(arg, sndbit, SND_MAX); |
728 | break; | 757 | goto out; |
729 | 758 | ||
730 | case UI_SET_FFBIT: | 759 | case UI_SET_FFBIT: |
731 | retval = uinput_set_bit(arg, ffbit, FF_MAX); | 760 | retval = uinput_set_bit(arg, ffbit, FF_MAX); |
732 | break; | 761 | goto out; |
733 | 762 | ||
734 | case UI_SET_SWBIT: | 763 | case UI_SET_SWBIT: |
735 | retval = uinput_set_bit(arg, swbit, SW_MAX); | 764 | retval = uinput_set_bit(arg, swbit, SW_MAX); |
736 | break; | 765 | goto out; |
737 | 766 | ||
738 | case UI_SET_PROPBIT: | 767 | case UI_SET_PROPBIT: |
739 | retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); | 768 | retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX); |
740 | break; | 769 | goto out; |
741 | 770 | ||
742 | case UI_SET_PHYS: | 771 | case UI_SET_PHYS: |
743 | if (udev->state == UIST_CREATED) { | 772 | if (udev->state == UIST_CREATED) { |
@@ -753,18 +782,18 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
753 | 782 | ||
754 | kfree(udev->dev->phys); | 783 | kfree(udev->dev->phys); |
755 | udev->dev->phys = phys; | 784 | udev->dev->phys = phys; |
756 | break; | 785 | goto out; |
757 | 786 | ||
758 | case UI_BEGIN_FF_UPLOAD: | 787 | case UI_BEGIN_FF_UPLOAD: |
759 | retval = uinput_ff_upload_from_user(p, &ff_up); | 788 | retval = uinput_ff_upload_from_user(p, &ff_up); |
760 | if (retval) | 789 | if (retval) |
761 | break; | 790 | goto out; |
762 | 791 | ||
763 | req = uinput_request_find(udev, ff_up.request_id); | 792 | req = uinput_request_find(udev, ff_up.request_id); |
764 | if (!req || req->code != UI_FF_UPLOAD || | 793 | if (!req || req->code != UI_FF_UPLOAD || |
765 | !req->u.upload.effect) { | 794 | !req->u.upload.effect) { |
766 | retval = -EINVAL; | 795 | retval = -EINVAL; |
767 | break; | 796 | goto out; |
768 | } | 797 | } |
769 | 798 | ||
770 | ff_up.retval = 0; | 799 | ff_up.retval = 0; |
@@ -775,65 +804,77 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
775 | memset(&ff_up.old, 0, sizeof(struct ff_effect)); | 804 | memset(&ff_up.old, 0, sizeof(struct ff_effect)); |
776 | 805 | ||
777 | retval = uinput_ff_upload_to_user(p, &ff_up); | 806 | retval = uinput_ff_upload_to_user(p, &ff_up); |
778 | break; | 807 | goto out; |
779 | 808 | ||
780 | case UI_BEGIN_FF_ERASE: | 809 | case UI_BEGIN_FF_ERASE: |
781 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { | 810 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { |
782 | retval = -EFAULT; | 811 | retval = -EFAULT; |
783 | break; | 812 | goto out; |
784 | } | 813 | } |
785 | 814 | ||
786 | req = uinput_request_find(udev, ff_erase.request_id); | 815 | req = uinput_request_find(udev, ff_erase.request_id); |
787 | if (!req || req->code != UI_FF_ERASE) { | 816 | if (!req || req->code != UI_FF_ERASE) { |
788 | retval = -EINVAL; | 817 | retval = -EINVAL; |
789 | break; | 818 | goto out; |
790 | } | 819 | } |
791 | 820 | ||
792 | ff_erase.retval = 0; | 821 | ff_erase.retval = 0; |
793 | ff_erase.effect_id = req->u.effect_id; | 822 | ff_erase.effect_id = req->u.effect_id; |
794 | if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) { | 823 | if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) { |
795 | retval = -EFAULT; | 824 | retval = -EFAULT; |
796 | break; | 825 | goto out; |
797 | } | 826 | } |
798 | 827 | ||
799 | break; | 828 | goto out; |
800 | 829 | ||
801 | case UI_END_FF_UPLOAD: | 830 | case UI_END_FF_UPLOAD: |
802 | retval = uinput_ff_upload_from_user(p, &ff_up); | 831 | retval = uinput_ff_upload_from_user(p, &ff_up); |
803 | if (retval) | 832 | if (retval) |
804 | break; | 833 | goto out; |
805 | 834 | ||
806 | req = uinput_request_find(udev, ff_up.request_id); | 835 | req = uinput_request_find(udev, ff_up.request_id); |
807 | if (!req || req->code != UI_FF_UPLOAD || | 836 | if (!req || req->code != UI_FF_UPLOAD || |
808 | !req->u.upload.effect) { | 837 | !req->u.upload.effect) { |
809 | retval = -EINVAL; | 838 | retval = -EINVAL; |
810 | break; | 839 | goto out; |
811 | } | 840 | } |
812 | 841 | ||
813 | req->retval = ff_up.retval; | 842 | req->retval = ff_up.retval; |
814 | uinput_request_done(udev, req); | 843 | uinput_request_done(udev, req); |
815 | break; | 844 | goto out; |
816 | 845 | ||
817 | case UI_END_FF_ERASE: | 846 | case UI_END_FF_ERASE: |
818 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { | 847 | if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) { |
819 | retval = -EFAULT; | 848 | retval = -EFAULT; |
820 | break; | 849 | goto out; |
821 | } | 850 | } |
822 | 851 | ||
823 | req = uinput_request_find(udev, ff_erase.request_id); | 852 | req = uinput_request_find(udev, ff_erase.request_id); |
824 | if (!req || req->code != UI_FF_ERASE) { | 853 | if (!req || req->code != UI_FF_ERASE) { |
825 | retval = -EINVAL; | 854 | retval = -EINVAL; |
826 | break; | 855 | goto out; |
827 | } | 856 | } |
828 | 857 | ||
829 | req->retval = ff_erase.retval; | 858 | req->retval = ff_erase.retval; |
830 | uinput_request_done(udev, req); | 859 | uinput_request_done(udev, req); |
831 | break; | 860 | goto out; |
861 | } | ||
832 | 862 | ||
833 | default: | 863 | size = _IOC_SIZE(cmd); |
834 | retval = -EINVAL; | 864 | |
865 | /* Now check variable-length commands */ | ||
866 | switch (cmd & ~IOCSIZE_MASK) { | ||
867 | case UI_GET_SYSNAME(0): | ||
868 | if (udev->state != UIST_CREATED) { | ||
869 | retval = -ENOENT; | ||
870 | goto out; | ||
871 | } | ||
872 | name = dev_name(&udev->dev->dev); | ||
873 | retval = uinput_str_to_user(p, name, size); | ||
874 | goto out; | ||
835 | } | 875 | } |
836 | 876 | ||
877 | retval = -EINVAL; | ||
837 | out: | 878 | out: |
838 | mutex_unlock(&udev->mutex); | 879 | mutex_unlock(&udev->mutex); |
839 | return retval; | 880 | return retval; |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index b6505454bcc4..7b7add5061a5 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = { | |||
277 | { KE_END, 0 } | 277 | { KE_END, 0 } |
278 | }; | 278 | }; |
279 | 279 | ||
280 | static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = { | ||
281 | { KE_KEY, 0x01, {KEY_HELP} }, /* Fn+F1 */ | ||
282 | { KE_KEY, 0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */ | ||
283 | { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ | ||
284 | { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ | ||
285 | { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ | ||
286 | { KE_WIFI, 0x78 }, /* satelite dish button */ | ||
287 | { KE_END, FE_WIFI_LED } | ||
288 | }; | ||
289 | |||
280 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { | 290 | static struct key_entry keymap_fujitsu_n3510[] __initdata = { |
281 | { KE_KEY, 0x11, {KEY_PROG1} }, | 291 | { KE_KEY, 0x11, {KEY_PROG1} }, |
282 | { KE_KEY, 0x12, {KEY_PROG2} }, | 292 | { KE_KEY, 0x12, {KEY_PROG2} }, |
@@ -654,6 +664,15 @@ static const struct dmi_system_id dmi_ids[] __initconst = { | |||
654 | .driver_data = keymap_fs_amilo_pro_v3505 | 664 | .driver_data = keymap_fs_amilo_pro_v3505 |
655 | }, | 665 | }, |
656 | { | 666 | { |
667 | /* Fujitsu-Siemens Amilo Pro Edition V8210 */ | ||
668 | .callback = dmi_matched, | ||
669 | .matches = { | ||
670 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
671 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"), | ||
672 | }, | ||
673 | .driver_data = keymap_fs_amilo_pro_v8210 | ||
674 | }, | ||
675 | { | ||
657 | /* Fujitsu-Siemens Amilo M7400 */ | 676 | /* Fujitsu-Siemens Amilo M7400 */ |
658 | .callback = dmi_matched, | 677 | .callback = dmi_matched, |
659 | .matches = { | 678 | .matches = { |