diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 461 |
1 files changed, 266 insertions, 195 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index aebcf6355df4..18dbdff4656e 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -88,7 +88,16 @@ module_param(allow_duplicates, bool, 0644); | |||
88 | static bool use_bios_initial_backlight = 1; | 88 | static bool use_bios_initial_backlight = 1; |
89 | module_param(use_bios_initial_backlight, bool, 0644); | 89 | module_param(use_bios_initial_backlight, bool, 0644); |
90 | 90 | ||
91 | /* | ||
92 | * For Windows 8 systems: if set ture and the GPU driver has | ||
93 | * registered a backlight interface, skip registering ACPI video's. | ||
94 | */ | ||
95 | static bool use_native_backlight = false; | ||
96 | module_param(use_native_backlight, bool, 0644); | ||
97 | |||
91 | static int register_count; | 98 | static int register_count; |
99 | static struct mutex video_list_lock; | ||
100 | static struct list_head video_bus_head; | ||
92 | static int acpi_video_bus_add(struct acpi_device *device); | 101 | static int acpi_video_bus_add(struct acpi_device *device); |
93 | static int acpi_video_bus_remove(struct acpi_device *device); | 102 | static int acpi_video_bus_remove(struct acpi_device *device); |
94 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event); | 103 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event); |
@@ -157,6 +166,7 @@ struct acpi_video_bus { | |||
157 | struct acpi_video_bus_flags flags; | 166 | struct acpi_video_bus_flags flags; |
158 | struct list_head video_device_list; | 167 | struct list_head video_device_list; |
159 | struct mutex device_list_lock; /* protects video_device_list */ | 168 | struct mutex device_list_lock; /* protects video_device_list */ |
169 | struct list_head entry; | ||
160 | struct input_dev *input; | 170 | struct input_dev *input; |
161 | char phys[32]; /* for input device */ | 171 | char phys[32]; /* for input device */ |
162 | struct notifier_block pm_nb; | 172 | struct notifier_block pm_nb; |
@@ -229,6 +239,14 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, | |||
229 | static int acpi_video_switch_brightness(struct acpi_video_device *device, | 239 | static int acpi_video_switch_brightness(struct acpi_video_device *device, |
230 | int event); | 240 | int event); |
231 | 241 | ||
242 | static bool acpi_video_verify_backlight_support(void) | ||
243 | { | ||
244 | if (acpi_osi_is_win8() && use_native_backlight && | ||
245 | backlight_device_registered(BACKLIGHT_RAW)) | ||
246 | return false; | ||
247 | return acpi_video_backlight_support(); | ||
248 | } | ||
249 | |||
232 | /* backlight device sysfs support */ | 250 | /* backlight device sysfs support */ |
233 | static int acpi_video_get_brightness(struct backlight_device *bd) | 251 | static int acpi_video_get_brightness(struct backlight_device *bd) |
234 | { | 252 | { |
@@ -830,9 +848,9 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
830 | * or an index). Set the backlight to max_level in this case. | 848 | * or an index). Set the backlight to max_level in this case. |
831 | */ | 849 | */ |
832 | for (i = 2; i < br->count; i++) | 850 | for (i = 2; i < br->count; i++) |
833 | if (level_old == br->levels[i]) | 851 | if (level == br->levels[i]) |
834 | break; | 852 | break; |
835 | if (i == br->count) | 853 | if (i == br->count || !level) |
836 | level = max_level; | 854 | level = max_level; |
837 | } | 855 | } |
838 | 856 | ||
@@ -884,79 +902,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
884 | 902 | ||
885 | if (acpi_has_method(device->dev->handle, "_DDC")) | 903 | if (acpi_has_method(device->dev->handle, "_DDC")) |
886 | device->cap._DDC = 1; | 904 | device->cap._DDC = 1; |
887 | |||
888 | if (acpi_video_backlight_support()) { | ||
889 | struct backlight_properties props; | ||
890 | struct pci_dev *pdev; | ||
891 | acpi_handle acpi_parent; | ||
892 | struct device *parent = NULL; | ||
893 | int result; | ||
894 | static int count; | ||
895 | char *name; | ||
896 | |||
897 | result = acpi_video_init_brightness(device); | ||
898 | if (result) | ||
899 | return; | ||
900 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); | ||
901 | if (!name) | ||
902 | return; | ||
903 | count++; | ||
904 | |||
905 | acpi_get_parent(device->dev->handle, &acpi_parent); | ||
906 | |||
907 | pdev = acpi_get_pci_dev(acpi_parent); | ||
908 | if (pdev) { | ||
909 | parent = &pdev->dev; | ||
910 | pci_dev_put(pdev); | ||
911 | } | ||
912 | |||
913 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
914 | props.type = BACKLIGHT_FIRMWARE; | ||
915 | props.max_brightness = device->brightness->count - 3; | ||
916 | device->backlight = backlight_device_register(name, | ||
917 | parent, | ||
918 | device, | ||
919 | &acpi_backlight_ops, | ||
920 | &props); | ||
921 | kfree(name); | ||
922 | if (IS_ERR(device->backlight)) | ||
923 | return; | ||
924 | |||
925 | /* | ||
926 | * Save current brightness level in case we have to restore it | ||
927 | * before acpi_video_device_lcd_set_level() is called next time. | ||
928 | */ | ||
929 | device->backlight->props.brightness = | ||
930 | acpi_video_get_brightness(device->backlight); | ||
931 | |||
932 | device->cooling_dev = thermal_cooling_device_register("LCD", | ||
933 | device->dev, &video_cooling_ops); | ||
934 | if (IS_ERR(device->cooling_dev)) { | ||
935 | /* | ||
936 | * Set cooling_dev to NULL so we don't crash trying to | ||
937 | * free it. | ||
938 | * Also, why the hell we are returning early and | ||
939 | * not attempt to register video output if cooling | ||
940 | * device registration failed? | ||
941 | * -- dtor | ||
942 | */ | ||
943 | device->cooling_dev = NULL; | ||
944 | return; | ||
945 | } | ||
946 | |||
947 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", | ||
948 | device->cooling_dev->id); | ||
949 | result = sysfs_create_link(&device->dev->dev.kobj, | ||
950 | &device->cooling_dev->device.kobj, | ||
951 | "thermal_cooling"); | ||
952 | if (result) | ||
953 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
954 | result = sysfs_create_link(&device->cooling_dev->device.kobj, | ||
955 | &device->dev->dev.kobj, "device"); | ||
956 | if (result) | ||
957 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
958 | |||
959 | } | ||
960 | } | 905 | } |
961 | 906 | ||
962 | /* | 907 | /* |
@@ -1143,13 +1088,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1143 | acpi_video_device_bind(video, data); | 1088 | acpi_video_device_bind(video, data); |
1144 | acpi_video_device_find_cap(data); | 1089 | acpi_video_device_find_cap(data); |
1145 | 1090 | ||
1146 | status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, | ||
1147 | acpi_video_device_notify, data); | ||
1148 | if (ACPI_FAILURE(status)) | ||
1149 | dev_err(&device->dev, "Error installing notify handler\n"); | ||
1150 | else | ||
1151 | data->flags.notify = 1; | ||
1152 | |||
1153 | mutex_lock(&video->device_list_lock); | 1091 | mutex_lock(&video->device_list_lock); |
1154 | list_add_tail(&data->entry, &video->video_device_list); | 1092 | list_add_tail(&data->entry, &video->video_device_list); |
1155 | mutex_unlock(&video->device_list_lock); | 1093 | mutex_unlock(&video->device_list_lock); |
@@ -1333,8 +1271,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) | |||
1333 | unsigned long long level_current, level_next; | 1271 | unsigned long long level_current, level_next; |
1334 | int result = -EINVAL; | 1272 | int result = -EINVAL; |
1335 | 1273 | ||
1336 | /* no warning message if acpi_backlight=vendor is used */ | 1274 | /* no warning message if acpi_backlight=vendor or a quirk is used */ |
1337 | if (!acpi_video_backlight_support()) | 1275 | if (!acpi_video_verify_backlight_support()) |
1338 | return 0; | 1276 | return 0; |
1339 | 1277 | ||
1340 | if (!device->brightness) | 1278 | if (!device->brightness) |
@@ -1454,64 +1392,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, | |||
1454 | return status; | 1392 | return status; |
1455 | } | 1393 | } |
1456 | 1394 | ||
1457 | static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | ||
1458 | { | ||
1459 | acpi_status status; | ||
1460 | |||
1461 | if (!device || !device->video) | ||
1462 | return -ENOENT; | ||
1463 | |||
1464 | if (device->flags.notify) { | ||
1465 | status = acpi_remove_notify_handler(device->dev->handle, | ||
1466 | ACPI_DEVICE_NOTIFY, acpi_video_device_notify); | ||
1467 | if (ACPI_FAILURE(status)) | ||
1468 | dev_err(&device->dev->dev, | ||
1469 | "Can't remove video notify handler\n"); | ||
1470 | } | ||
1471 | |||
1472 | if (device->backlight) { | ||
1473 | backlight_device_unregister(device->backlight); | ||
1474 | device->backlight = NULL; | ||
1475 | } | ||
1476 | if (device->cooling_dev) { | ||
1477 | sysfs_remove_link(&device->dev->dev.kobj, | ||
1478 | "thermal_cooling"); | ||
1479 | sysfs_remove_link(&device->cooling_dev->device.kobj, | ||
1480 | "device"); | ||
1481 | thermal_cooling_device_unregister(device->cooling_dev); | ||
1482 | device->cooling_dev = NULL; | ||
1483 | } | ||
1484 | |||
1485 | return 0; | ||
1486 | } | ||
1487 | |||
1488 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | ||
1489 | { | ||
1490 | int status; | ||
1491 | struct acpi_video_device *dev, *next; | ||
1492 | |||
1493 | mutex_lock(&video->device_list_lock); | ||
1494 | |||
1495 | list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { | ||
1496 | |||
1497 | status = acpi_video_bus_put_one_device(dev); | ||
1498 | if (ACPI_FAILURE(status)) | ||
1499 | printk(KERN_WARNING PREFIX | ||
1500 | "hhuuhhuu bug in acpi video driver.\n"); | ||
1501 | |||
1502 | if (dev->brightness) { | ||
1503 | kfree(dev->brightness->levels); | ||
1504 | kfree(dev->brightness); | ||
1505 | } | ||
1506 | list_del(&dev->entry); | ||
1507 | kfree(dev); | ||
1508 | } | ||
1509 | |||
1510 | mutex_unlock(&video->device_list_lock); | ||
1511 | |||
1512 | return 0; | ||
1513 | } | ||
1514 | |||
1515 | /* acpi_video interface */ | 1395 | /* acpi_video interface */ |
1516 | 1396 | ||
1517 | /* | 1397 | /* |
@@ -1521,13 +1401,13 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | |||
1521 | static int acpi_video_bus_start_devices(struct acpi_video_bus *video) | 1401 | static int acpi_video_bus_start_devices(struct acpi_video_bus *video) |
1522 | { | 1402 | { |
1523 | return acpi_video_bus_DOS(video, 0, | 1403 | return acpi_video_bus_DOS(video, 0, |
1524 | acpi_video_backlight_quirks() ? 1 : 0); | 1404 | acpi_osi_is_win8() ? 1 : 0); |
1525 | } | 1405 | } |
1526 | 1406 | ||
1527 | static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) | 1407 | static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) |
1528 | { | 1408 | { |
1529 | return acpi_video_bus_DOS(video, 0, | 1409 | return acpi_video_bus_DOS(video, 0, |
1530 | acpi_video_backlight_quirks() ? 0 : 1); | 1410 | acpi_osi_is_win8() ? 0 : 1); |
1531 | } | 1411 | } |
1532 | 1412 | ||
1533 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event) | 1413 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event) |
@@ -1536,7 +1416,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) | |||
1536 | struct input_dev *input; | 1416 | struct input_dev *input; |
1537 | int keycode = 0; | 1417 | int keycode = 0; |
1538 | 1418 | ||
1539 | if (!video) | 1419 | if (!video || !video->input) |
1540 | return; | 1420 | return; |
1541 | 1421 | ||
1542 | input = video->input; | 1422 | input = video->input; |
@@ -1691,12 +1571,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, | |||
1691 | return AE_OK; | 1571 | return AE_OK; |
1692 | } | 1572 | } |
1693 | 1573 | ||
1574 | static void acpi_video_dev_register_backlight(struct acpi_video_device *device) | ||
1575 | { | ||
1576 | if (acpi_video_verify_backlight_support()) { | ||
1577 | struct backlight_properties props; | ||
1578 | struct pci_dev *pdev; | ||
1579 | acpi_handle acpi_parent; | ||
1580 | struct device *parent = NULL; | ||
1581 | int result; | ||
1582 | static int count; | ||
1583 | char *name; | ||
1584 | |||
1585 | result = acpi_video_init_brightness(device); | ||
1586 | if (result) | ||
1587 | return; | ||
1588 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); | ||
1589 | if (!name) | ||
1590 | return; | ||
1591 | count++; | ||
1592 | |||
1593 | acpi_get_parent(device->dev->handle, &acpi_parent); | ||
1594 | |||
1595 | pdev = acpi_get_pci_dev(acpi_parent); | ||
1596 | if (pdev) { | ||
1597 | parent = &pdev->dev; | ||
1598 | pci_dev_put(pdev); | ||
1599 | } | ||
1600 | |||
1601 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
1602 | props.type = BACKLIGHT_FIRMWARE; | ||
1603 | props.max_brightness = device->brightness->count - 3; | ||
1604 | device->backlight = backlight_device_register(name, | ||
1605 | parent, | ||
1606 | device, | ||
1607 | &acpi_backlight_ops, | ||
1608 | &props); | ||
1609 | kfree(name); | ||
1610 | if (IS_ERR(device->backlight)) | ||
1611 | return; | ||
1612 | |||
1613 | /* | ||
1614 | * Save current brightness level in case we have to restore it | ||
1615 | * before acpi_video_device_lcd_set_level() is called next time. | ||
1616 | */ | ||
1617 | device->backlight->props.brightness = | ||
1618 | acpi_video_get_brightness(device->backlight); | ||
1619 | |||
1620 | device->cooling_dev = thermal_cooling_device_register("LCD", | ||
1621 | device->dev, &video_cooling_ops); | ||
1622 | if (IS_ERR(device->cooling_dev)) { | ||
1623 | /* | ||
1624 | * Set cooling_dev to NULL so we don't crash trying to | ||
1625 | * free it. | ||
1626 | * Also, why the hell we are returning early and | ||
1627 | * not attempt to register video output if cooling | ||
1628 | * device registration failed? | ||
1629 | * -- dtor | ||
1630 | */ | ||
1631 | device->cooling_dev = NULL; | ||
1632 | return; | ||
1633 | } | ||
1634 | |||
1635 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", | ||
1636 | device->cooling_dev->id); | ||
1637 | result = sysfs_create_link(&device->dev->dev.kobj, | ||
1638 | &device->cooling_dev->device.kobj, | ||
1639 | "thermal_cooling"); | ||
1640 | if (result) | ||
1641 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
1642 | result = sysfs_create_link(&device->cooling_dev->device.kobj, | ||
1643 | &device->dev->dev.kobj, "device"); | ||
1644 | if (result) | ||
1645 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
1646 | } | ||
1647 | } | ||
1648 | |||
1649 | static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) | ||
1650 | { | ||
1651 | struct acpi_video_device *dev; | ||
1652 | |||
1653 | mutex_lock(&video->device_list_lock); | ||
1654 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
1655 | acpi_video_dev_register_backlight(dev); | ||
1656 | mutex_unlock(&video->device_list_lock); | ||
1657 | |||
1658 | video->pm_nb.notifier_call = acpi_video_resume; | ||
1659 | video->pm_nb.priority = 0; | ||
1660 | return register_pm_notifier(&video->pm_nb); | ||
1661 | } | ||
1662 | |||
1663 | static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device) | ||
1664 | { | ||
1665 | if (device->backlight) { | ||
1666 | backlight_device_unregister(device->backlight); | ||
1667 | device->backlight = NULL; | ||
1668 | } | ||
1669 | if (device->brightness) { | ||
1670 | kfree(device->brightness->levels); | ||
1671 | kfree(device->brightness); | ||
1672 | device->brightness = NULL; | ||
1673 | } | ||
1674 | if (device->cooling_dev) { | ||
1675 | sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); | ||
1676 | sysfs_remove_link(&device->cooling_dev->device.kobj, "device"); | ||
1677 | thermal_cooling_device_unregister(device->cooling_dev); | ||
1678 | device->cooling_dev = NULL; | ||
1679 | } | ||
1680 | } | ||
1681 | |||
1682 | static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) | ||
1683 | { | ||
1684 | struct acpi_video_device *dev; | ||
1685 | int error = unregister_pm_notifier(&video->pm_nb); | ||
1686 | |||
1687 | mutex_lock(&video->device_list_lock); | ||
1688 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
1689 | acpi_video_dev_unregister_backlight(dev); | ||
1690 | mutex_unlock(&video->device_list_lock); | ||
1691 | |||
1692 | return error; | ||
1693 | } | ||
1694 | |||
1695 | static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device) | ||
1696 | { | ||
1697 | acpi_status status; | ||
1698 | struct acpi_device *adev = device->dev; | ||
1699 | |||
1700 | status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, | ||
1701 | acpi_video_device_notify, device); | ||
1702 | if (ACPI_FAILURE(status)) | ||
1703 | dev_err(&adev->dev, "Error installing notify handler\n"); | ||
1704 | else | ||
1705 | device->flags.notify = 1; | ||
1706 | } | ||
1707 | |||
1708 | static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video) | ||
1709 | { | ||
1710 | struct input_dev *input; | ||
1711 | struct acpi_video_device *dev; | ||
1712 | int error; | ||
1713 | |||
1714 | video->input = input = input_allocate_device(); | ||
1715 | if (!input) { | ||
1716 | error = -ENOMEM; | ||
1717 | goto out; | ||
1718 | } | ||
1719 | |||
1720 | error = acpi_video_bus_start_devices(video); | ||
1721 | if (error) | ||
1722 | goto err_free_input; | ||
1723 | |||
1724 | snprintf(video->phys, sizeof(video->phys), | ||
1725 | "%s/video/input0", acpi_device_hid(video->device)); | ||
1726 | |||
1727 | input->name = acpi_device_name(video->device); | ||
1728 | input->phys = video->phys; | ||
1729 | input->id.bustype = BUS_HOST; | ||
1730 | input->id.product = 0x06; | ||
1731 | input->dev.parent = &video->device->dev; | ||
1732 | input->evbit[0] = BIT(EV_KEY); | ||
1733 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | ||
1734 | set_bit(KEY_VIDEO_NEXT, input->keybit); | ||
1735 | set_bit(KEY_VIDEO_PREV, input->keybit); | ||
1736 | set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); | ||
1737 | set_bit(KEY_BRIGHTNESSUP, input->keybit); | ||
1738 | set_bit(KEY_BRIGHTNESSDOWN, input->keybit); | ||
1739 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | ||
1740 | set_bit(KEY_DISPLAY_OFF, input->keybit); | ||
1741 | |||
1742 | error = input_register_device(input); | ||
1743 | if (error) | ||
1744 | goto err_stop_dev; | ||
1745 | |||
1746 | mutex_lock(&video->device_list_lock); | ||
1747 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
1748 | acpi_video_dev_add_notify_handler(dev); | ||
1749 | mutex_unlock(&video->device_list_lock); | ||
1750 | |||
1751 | return 0; | ||
1752 | |||
1753 | err_stop_dev: | ||
1754 | acpi_video_bus_stop_devices(video); | ||
1755 | err_free_input: | ||
1756 | input_free_device(input); | ||
1757 | video->input = NULL; | ||
1758 | out: | ||
1759 | return error; | ||
1760 | } | ||
1761 | |||
1762 | static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev) | ||
1763 | { | ||
1764 | if (dev->flags.notify) { | ||
1765 | acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY, | ||
1766 | acpi_video_device_notify); | ||
1767 | dev->flags.notify = 0; | ||
1768 | } | ||
1769 | } | ||
1770 | |||
1771 | static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video) | ||
1772 | { | ||
1773 | struct acpi_video_device *dev; | ||
1774 | |||
1775 | mutex_lock(&video->device_list_lock); | ||
1776 | list_for_each_entry(dev, &video->video_device_list, entry) | ||
1777 | acpi_video_dev_remove_notify_handler(dev); | ||
1778 | mutex_unlock(&video->device_list_lock); | ||
1779 | |||
1780 | acpi_video_bus_stop_devices(video); | ||
1781 | input_unregister_device(video->input); | ||
1782 | video->input = NULL; | ||
1783 | } | ||
1784 | |||
1785 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | ||
1786 | { | ||
1787 | struct acpi_video_device *dev, *next; | ||
1788 | |||
1789 | mutex_lock(&video->device_list_lock); | ||
1790 | list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { | ||
1791 | list_del(&dev->entry); | ||
1792 | kfree(dev); | ||
1793 | } | ||
1794 | mutex_unlock(&video->device_list_lock); | ||
1795 | |||
1796 | return 0; | ||
1797 | } | ||
1798 | |||
1694 | static int instance; | 1799 | static int instance; |
1695 | 1800 | ||
1696 | static int acpi_video_bus_add(struct acpi_device *device) | 1801 | static int acpi_video_bus_add(struct acpi_device *device) |
1697 | { | 1802 | { |
1698 | struct acpi_video_bus *video; | 1803 | struct acpi_video_bus *video; |
1699 | struct input_dev *input; | ||
1700 | int error; | 1804 | int error; |
1701 | acpi_status status; | 1805 | acpi_status status; |
1702 | 1806 | ||
@@ -1748,62 +1852,24 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1748 | if (error) | 1852 | if (error) |
1749 | goto err_put_video; | 1853 | goto err_put_video; |
1750 | 1854 | ||
1751 | video->input = input = input_allocate_device(); | ||
1752 | if (!input) { | ||
1753 | error = -ENOMEM; | ||
1754 | goto err_put_video; | ||
1755 | } | ||
1756 | |||
1757 | error = acpi_video_bus_start_devices(video); | ||
1758 | if (error) | ||
1759 | goto err_free_input_dev; | ||
1760 | |||
1761 | snprintf(video->phys, sizeof(video->phys), | ||
1762 | "%s/video/input0", acpi_device_hid(video->device)); | ||
1763 | |||
1764 | input->name = acpi_device_name(video->device); | ||
1765 | input->phys = video->phys; | ||
1766 | input->id.bustype = BUS_HOST; | ||
1767 | input->id.product = 0x06; | ||
1768 | input->dev.parent = &device->dev; | ||
1769 | input->evbit[0] = BIT(EV_KEY); | ||
1770 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | ||
1771 | set_bit(KEY_VIDEO_NEXT, input->keybit); | ||
1772 | set_bit(KEY_VIDEO_PREV, input->keybit); | ||
1773 | set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit); | ||
1774 | set_bit(KEY_BRIGHTNESSUP, input->keybit); | ||
1775 | set_bit(KEY_BRIGHTNESSDOWN, input->keybit); | ||
1776 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | ||
1777 | set_bit(KEY_DISPLAY_OFF, input->keybit); | ||
1778 | |||
1779 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1855 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1780 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1856 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
1781 | video->flags.multihead ? "yes" : "no", | 1857 | video->flags.multihead ? "yes" : "no", |
1782 | video->flags.rom ? "yes" : "no", | 1858 | video->flags.rom ? "yes" : "no", |
1783 | video->flags.post ? "yes" : "no"); | 1859 | video->flags.post ? "yes" : "no"); |
1860 | mutex_lock(&video_list_lock); | ||
1861 | list_add_tail(&video->entry, &video_bus_head); | ||
1862 | mutex_unlock(&video_list_lock); | ||
1784 | 1863 | ||
1785 | video->pm_nb.notifier_call = acpi_video_resume; | 1864 | acpi_video_bus_register_backlight(video); |
1786 | video->pm_nb.priority = 0; | 1865 | acpi_video_bus_add_notify_handler(video); |
1787 | error = register_pm_notifier(&video->pm_nb); | ||
1788 | if (error) | ||
1789 | goto err_stop_video; | ||
1790 | |||
1791 | error = input_register_device(input); | ||
1792 | if (error) | ||
1793 | goto err_unregister_pm_notifier; | ||
1794 | 1866 | ||
1795 | return 0; | 1867 | return 0; |
1796 | 1868 | ||
1797 | err_unregister_pm_notifier: | 1869 | err_put_video: |
1798 | unregister_pm_notifier(&video->pm_nb); | ||
1799 | err_stop_video: | ||
1800 | acpi_video_bus_stop_devices(video); | ||
1801 | err_free_input_dev: | ||
1802 | input_free_device(input); | ||
1803 | err_put_video: | ||
1804 | acpi_video_bus_put_devices(video); | 1870 | acpi_video_bus_put_devices(video); |
1805 | kfree(video->attached_array); | 1871 | kfree(video->attached_array); |
1806 | err_free_video: | 1872 | err_free_video: |
1807 | kfree(video); | 1873 | kfree(video); |
1808 | device->driver_data = NULL; | 1874 | device->driver_data = NULL; |
1809 | 1875 | ||
@@ -1820,12 +1886,14 @@ static int acpi_video_bus_remove(struct acpi_device *device) | |||
1820 | 1886 | ||
1821 | video = acpi_driver_data(device); | 1887 | video = acpi_driver_data(device); |
1822 | 1888 | ||
1823 | unregister_pm_notifier(&video->pm_nb); | 1889 | acpi_video_bus_remove_notify_handler(video); |
1824 | 1890 | acpi_video_bus_unregister_backlight(video); | |
1825 | acpi_video_bus_stop_devices(video); | ||
1826 | acpi_video_bus_put_devices(video); | 1891 | acpi_video_bus_put_devices(video); |
1827 | 1892 | ||
1828 | input_unregister_device(video->input); | 1893 | mutex_lock(&video_list_lock); |
1894 | list_del(&video->entry); | ||
1895 | mutex_unlock(&video_list_lock); | ||
1896 | |||
1829 | kfree(video->attached_array); | 1897 | kfree(video->attached_array); |
1830 | kfree(video); | 1898 | kfree(video); |
1831 | 1899 | ||
@@ -1874,6 +1942,9 @@ int acpi_video_register(void) | |||
1874 | return 0; | 1942 | return 0; |
1875 | } | 1943 | } |
1876 | 1944 | ||
1945 | mutex_init(&video_list_lock); | ||
1946 | INIT_LIST_HEAD(&video_bus_head); | ||
1947 | |||
1877 | result = acpi_bus_register_driver(&acpi_video_bus); | 1948 | result = acpi_bus_register_driver(&acpi_video_bus); |
1878 | if (result < 0) | 1949 | if (result < 0) |
1879 | return -ENODEV; | 1950 | return -ENODEV; |