aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video.c
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2013-10-11 09:27:44 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-15 19:16:04 -0400
commit67b662e189f469c6d373f81d76b0ef0495940e99 (patch)
tree4ce943e175f5f8d4d540aa31301eb8dd2ef4b61b /drivers/acpi/video.c
parent5915a3db0c3983f1cd5e046bf70086c7d0c686d2 (diff)
ACPI / video: seperate backlight control and event interface
The backlight control and event delivery functionality provided by ACPI video module is mixed together and registered all during video device enumeration time. As a result, the two functionality are also removed together on module unload time or by the acpi_video_unregister function. The two functionalities are actually independent and one may be useful while the other one may be broken, so it is desirable to seperate the two functionalities such that it is clear and easy to disable one functionality without affecting the other one. APIs to selectively remove backlight control interface and/or event delivery functionality can be easily added once needed. Signed-off-by: Aaron Lu <aaron.lu@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r--drivers/acpi/video.c434
1 files changed, 245 insertions, 189 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index aebcf6355df4..3bd1eaa4ef90 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -89,6 +89,8 @@ static bool use_bios_initial_backlight = 1;
89module_param(use_bios_initial_backlight, bool, 0644); 89module_param(use_bios_initial_backlight, bool, 0644);
90 90
91static int register_count; 91static int register_count;
92static struct mutex video_list_lock;
93static struct list_head video_bus_head;
92static int acpi_video_bus_add(struct acpi_device *device); 94static int acpi_video_bus_add(struct acpi_device *device);
93static int acpi_video_bus_remove(struct acpi_device *device); 95static int acpi_video_bus_remove(struct acpi_device *device);
94static void acpi_video_bus_notify(struct acpi_device *device, u32 event); 96static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
@@ -157,6 +159,7 @@ struct acpi_video_bus {
157 struct acpi_video_bus_flags flags; 159 struct acpi_video_bus_flags flags;
158 struct list_head video_device_list; 160 struct list_head video_device_list;
159 struct mutex device_list_lock; /* protects video_device_list */ 161 struct mutex device_list_lock; /* protects video_device_list */
162 struct list_head entry;
160 struct input_dev *input; 163 struct input_dev *input;
161 char phys[32]; /* for input device */ 164 char phys[32]; /* for input device */
162 struct notifier_block pm_nb; 165 struct notifier_block pm_nb;
@@ -884,79 +887,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
884 887
885 if (acpi_has_method(device->dev->handle, "_DDC")) 888 if (acpi_has_method(device->dev->handle, "_DDC"))
886 device->cap._DDC = 1; 889 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} 890}
961 891
962/* 892/*
@@ -1143,13 +1073,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
1143 acpi_video_device_bind(video, data); 1073 acpi_video_device_bind(video, data);
1144 acpi_video_device_find_cap(data); 1074 acpi_video_device_find_cap(data);
1145 1075
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); 1076 mutex_lock(&video->device_list_lock);
1154 list_add_tail(&data->entry, &video->video_device_list); 1077 list_add_tail(&data->entry, &video->video_device_list);
1155 mutex_unlock(&video->device_list_lock); 1078 mutex_unlock(&video->device_list_lock);
@@ -1454,64 +1377,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
1454 return status; 1377 return status;
1455} 1378}
1456 1379
1457static 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
1488static 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 */ 1380/* acpi_video interface */
1516 1381
1517/* 1382/*
@@ -1536,7 +1401,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
1536 struct input_dev *input; 1401 struct input_dev *input;
1537 int keycode = 0; 1402 int keycode = 0;
1538 1403
1539 if (!video) 1404 if (!video || !video->input)
1540 return; 1405 return;
1541 1406
1542 input = video->input; 1407 input = video->input;
@@ -1691,12 +1556,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
1691 return AE_OK; 1556 return AE_OK;
1692} 1557}
1693 1558
1559static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
1560{
1561 if (acpi_video_backlight_support()) {
1562 struct backlight_properties props;
1563 struct pci_dev *pdev;
1564 acpi_handle acpi_parent;
1565 struct device *parent = NULL;
1566 int result;
1567 static int count;
1568 char *name;
1569
1570 result = acpi_video_init_brightness(device);
1571 if (result)
1572 return;
1573 name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
1574 if (!name)
1575 return;
1576 count++;
1577
1578 acpi_get_parent(device->dev->handle, &acpi_parent);
1579
1580 pdev = acpi_get_pci_dev(acpi_parent);
1581 if (pdev) {
1582 parent = &pdev->dev;
1583 pci_dev_put(pdev);
1584 }
1585
1586 memset(&props, 0, sizeof(struct backlight_properties));
1587 props.type = BACKLIGHT_FIRMWARE;
1588 props.max_brightness = device->brightness->count - 3;
1589 device->backlight = backlight_device_register(name,
1590 parent,
1591 device,
1592 &acpi_backlight_ops,
1593 &props);
1594 kfree(name);
1595 if (IS_ERR(device->backlight))
1596 return;
1597
1598 /*
1599 * Save current brightness level in case we have to restore it
1600 * before acpi_video_device_lcd_set_level() is called next time.
1601 */
1602 device->backlight->props.brightness =
1603 acpi_video_get_brightness(device->backlight);
1604
1605 device->cooling_dev = thermal_cooling_device_register("LCD",
1606 device->dev, &video_cooling_ops);
1607 if (IS_ERR(device->cooling_dev)) {
1608 /*
1609 * Set cooling_dev to NULL so we don't crash trying to
1610 * free it.
1611 * Also, why the hell we are returning early and
1612 * not attempt to register video output if cooling
1613 * device registration failed?
1614 * -- dtor
1615 */
1616 device->cooling_dev = NULL;
1617 return;
1618 }
1619
1620 dev_info(&device->dev->dev, "registered as cooling_device%d\n",
1621 device->cooling_dev->id);
1622 result = sysfs_create_link(&device->dev->dev.kobj,
1623 &device->cooling_dev->device.kobj,
1624 "thermal_cooling");
1625 if (result)
1626 printk(KERN_ERR PREFIX "Create sysfs link\n");
1627 result = sysfs_create_link(&device->cooling_dev->device.kobj,
1628 &device->dev->dev.kobj, "device");
1629 if (result)
1630 printk(KERN_ERR PREFIX "Create sysfs link\n");
1631 }
1632}
1633
1634static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
1635{
1636 struct acpi_video_device *dev;
1637
1638 mutex_lock(&video->device_list_lock);
1639 list_for_each_entry(dev, &video->video_device_list, entry)
1640 acpi_video_dev_register_backlight(dev);
1641 mutex_unlock(&video->device_list_lock);
1642
1643 video->pm_nb.notifier_call = acpi_video_resume;
1644 video->pm_nb.priority = 0;
1645 return register_pm_notifier(&video->pm_nb);
1646}
1647
1648static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device)
1649{
1650 if (device->backlight) {
1651 backlight_device_unregister(device->backlight);
1652 device->backlight = NULL;
1653 }
1654 if (device->brightness) {
1655 kfree(device->brightness->levels);
1656 kfree(device->brightness);
1657 device->brightness = NULL;
1658 }
1659 if (device->cooling_dev) {
1660 sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling");
1661 sysfs_remove_link(&device->cooling_dev->device.kobj, "device");
1662 thermal_cooling_device_unregister(device->cooling_dev);
1663 device->cooling_dev = NULL;
1664 }
1665}
1666
1667static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video)
1668{
1669 struct acpi_video_device *dev;
1670 int error = unregister_pm_notifier(&video->pm_nb);
1671
1672 mutex_lock(&video->device_list_lock);
1673 list_for_each_entry(dev, &video->video_device_list, entry)
1674 acpi_video_dev_unregister_backlight(dev);
1675 mutex_unlock(&video->device_list_lock);
1676
1677 return error;
1678}
1679
1680static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device)
1681{
1682 acpi_status status;
1683 struct acpi_device *adev = device->dev;
1684
1685 status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
1686 acpi_video_device_notify, device);
1687 if (ACPI_FAILURE(status))
1688 dev_err(&adev->dev, "Error installing notify handler\n");
1689 else
1690 device->flags.notify = 1;
1691}
1692
1693static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video)
1694{
1695 struct input_dev *input;
1696 struct acpi_video_device *dev;
1697 int error;
1698
1699 video->input = input = input_allocate_device();
1700 if (!input) {
1701 error = -ENOMEM;
1702 goto out;
1703 }
1704
1705 error = acpi_video_bus_start_devices(video);
1706 if (error)
1707 goto err_free_input;
1708
1709 snprintf(video->phys, sizeof(video->phys),
1710 "%s/video/input0", acpi_device_hid(video->device));
1711
1712 input->name = acpi_device_name(video->device);
1713 input->phys = video->phys;
1714 input->id.bustype = BUS_HOST;
1715 input->id.product = 0x06;
1716 input->dev.parent = &video->device->dev;
1717 input->evbit[0] = BIT(EV_KEY);
1718 set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
1719 set_bit(KEY_VIDEO_NEXT, input->keybit);
1720 set_bit(KEY_VIDEO_PREV, input->keybit);
1721 set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
1722 set_bit(KEY_BRIGHTNESSUP, input->keybit);
1723 set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
1724 set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
1725 set_bit(KEY_DISPLAY_OFF, input->keybit);
1726
1727 error = input_register_device(input);
1728 if (error)
1729 goto err_stop_dev;
1730
1731 mutex_lock(&video->device_list_lock);
1732 list_for_each_entry(dev, &video->video_device_list, entry)
1733 acpi_video_dev_add_notify_handler(dev);
1734 mutex_unlock(&video->device_list_lock);
1735
1736 return 0;
1737
1738err_stop_dev:
1739 acpi_video_bus_stop_devices(video);
1740err_free_input:
1741 input_free_device(input);
1742 video->input = NULL;
1743out:
1744 return error;
1745}
1746
1747static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev)
1748{
1749 if (dev->flags.notify) {
1750 acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY,
1751 acpi_video_device_notify);
1752 dev->flags.notify = 0;
1753 }
1754}
1755
1756static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
1757{
1758 struct acpi_video_device *dev;
1759
1760 mutex_lock(&video->device_list_lock);
1761 list_for_each_entry(dev, &video->video_device_list, entry)
1762 acpi_video_dev_remove_notify_handler(dev);
1763 mutex_unlock(&video->device_list_lock);
1764
1765 acpi_video_bus_stop_devices(video);
1766 input_unregister_device(video->input);
1767 video->input = NULL;
1768}
1769
1770static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
1771{
1772 struct acpi_video_device *dev, *next;
1773
1774 mutex_lock(&video->device_list_lock);
1775 list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
1776 list_del(&dev->entry);
1777 kfree(dev);
1778 }
1779 mutex_unlock(&video->device_list_lock);
1780
1781 return 0;
1782}
1783
1694static int instance; 1784static int instance;
1695 1785
1696static int acpi_video_bus_add(struct acpi_device *device) 1786static int acpi_video_bus_add(struct acpi_device *device)
1697{ 1787{
1698 struct acpi_video_bus *video; 1788 struct acpi_video_bus *video;
1699 struct input_dev *input;
1700 int error; 1789 int error;
1701 acpi_status status; 1790 acpi_status status;
1702 1791
@@ -1748,62 +1837,24 @@ static int acpi_video_bus_add(struct acpi_device *device)
1748 if (error) 1837 if (error)
1749 goto err_put_video; 1838 goto err_put_video;
1750 1839
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", 1840 printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
1780 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), 1841 ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
1781 video->flags.multihead ? "yes" : "no", 1842 video->flags.multihead ? "yes" : "no",
1782 video->flags.rom ? "yes" : "no", 1843 video->flags.rom ? "yes" : "no",
1783 video->flags.post ? "yes" : "no"); 1844 video->flags.post ? "yes" : "no");
1845 mutex_lock(&video_list_lock);
1846 list_add_tail(&video->entry, &video_bus_head);
1847 mutex_unlock(&video_list_lock);
1784 1848
1785 video->pm_nb.notifier_call = acpi_video_resume; 1849 acpi_video_bus_register_backlight(video);
1786 video->pm_nb.priority = 0; 1850 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 1851
1795 return 0; 1852 return 0;
1796 1853
1797 err_unregister_pm_notifier: 1854err_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); 1855 acpi_video_bus_put_devices(video);
1805 kfree(video->attached_array); 1856 kfree(video->attached_array);
1806 err_free_video: 1857err_free_video:
1807 kfree(video); 1858 kfree(video);
1808 device->driver_data = NULL; 1859 device->driver_data = NULL;
1809 1860
@@ -1820,12 +1871,14 @@ static int acpi_video_bus_remove(struct acpi_device *device)
1820 1871
1821 video = acpi_driver_data(device); 1872 video = acpi_driver_data(device);
1822 1873
1823 unregister_pm_notifier(&video->pm_nb); 1874 acpi_video_bus_remove_notify_handler(video);
1824 1875 acpi_video_bus_unregister_backlight(video);
1825 acpi_video_bus_stop_devices(video);
1826 acpi_video_bus_put_devices(video); 1876 acpi_video_bus_put_devices(video);
1827 1877
1828 input_unregister_device(video->input); 1878 mutex_lock(&video_list_lock);
1879 list_del(&video->entry);
1880 mutex_unlock(&video_list_lock);
1881
1829 kfree(video->attached_array); 1882 kfree(video->attached_array);
1830 kfree(video); 1883 kfree(video);
1831 1884
@@ -1874,6 +1927,9 @@ int acpi_video_register(void)
1874 return 0; 1927 return 0;
1875 } 1928 }
1876 1929
1930 mutex_init(&video_list_lock);
1931 INIT_LIST_HEAD(&video_bus_head);
1932
1877 result = acpi_bus_register_driver(&acpi_video_bus); 1933 result = acpi_bus_register_driver(&acpi_video_bus);
1878 if (result < 0) 1934 if (result < 0)
1879 return -ENODEV; 1935 return -ENODEV;