diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-06-03 17:12:37 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-06-03 17:12:37 -0400 |
| commit | d9bd44933cb21faf2cfe09798c1a2c95563a0bcb (patch) | |
| tree | f16d3375cd246e2740651ffcf6cd8dbc30f2e0b4 | |
| parent | 0e36d43c9c87554cdb18aa865eec9edccda17324 (diff) | |
| parent | 0dc6b96ac20c538a28bd8442ae74b87fc6b6f6e0 (diff) | |
Merge branch 'acpi-video'
* acpi-video:
ACPI / video: Add 4 new models to the use_native_backlight DMI list
ACPI / video: Add use native backlight quirk for the ThinkPad W530
ACPI / video: Unregister the backlight device if a raw one shows up later
backlight: Add backlight device (un)registration notification
nouveau: Don't check acpi_video_backlight_support() before registering backlight
acer-wmi: Add Aspire 5741 to video_vendor_dmi_table
acer-wmi: Switch to acpi_video_unregister_backlight
ACPI / video: Add an acpi_video_unregister_backlight function
ACPI / video: Don't register acpi_video_resume notifier without backlight devices
ACPI / video: change acpi-video brightness_switch_enabled default to 0
| -rw-r--r-- | Documentation/kernel-parameters.txt | 2 | ||||
| -rw-r--r-- | drivers/acpi/video.c | 252 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_backlight.c | 9 | ||||
| -rw-r--r-- | drivers/platform/x86/acer-wmi.c | 10 | ||||
| -rw-r--r-- | drivers/video/backlight/backlight.c | 40 | ||||
| -rw-r--r-- | include/acpi/video.h | 2 | ||||
| -rw-r--r-- | include/linux/backlight.h | 7 |
7 files changed, 245 insertions, 77 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c6e72ee53903..0933ec4924d3 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -3481,7 +3481,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 3481 | the allocated input device; If set to 0, video driver | 3481 | the allocated input device; If set to 0, video driver |
| 3482 | will only send out the event without touching backlight | 3482 | will only send out the event without touching backlight |
| 3483 | brightness level. | 3483 | brightness level. |
| 3484 | default: 1 | 3484 | default: 0 |
| 3485 | 3485 | ||
| 3486 | virtio_mmio.device= | 3486 | virtio_mmio.device= |
| 3487 | [VMMIO] Memory mapped virtio (platform) device. | 3487 | [VMMIO] Memory mapped virtio (platform) device. |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f8bc5a755dda..101fb090dcb9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -68,7 +68,7 @@ MODULE_AUTHOR("Bruno Ducrot"); | |||
| 68 | MODULE_DESCRIPTION("ACPI Video Driver"); | 68 | MODULE_DESCRIPTION("ACPI Video Driver"); |
| 69 | MODULE_LICENSE("GPL"); | 69 | MODULE_LICENSE("GPL"); |
| 70 | 70 | ||
| 71 | static bool brightness_switch_enabled = 1; | 71 | static bool brightness_switch_enabled; |
| 72 | module_param(brightness_switch_enabled, bool, 0644); | 72 | module_param(brightness_switch_enabled, bool, 0644); |
| 73 | 73 | ||
| 74 | /* | 74 | /* |
| @@ -150,6 +150,8 @@ struct acpi_video_enumerated_device { | |||
| 150 | 150 | ||
| 151 | struct acpi_video_bus { | 151 | struct acpi_video_bus { |
| 152 | struct acpi_device *device; | 152 | struct acpi_device *device; |
| 153 | bool backlight_registered; | ||
| 154 | bool backlight_notifier_registered; | ||
| 153 | u8 dos_setting; | 155 | u8 dos_setting; |
| 154 | struct acpi_video_enumerated_device *attached_array; | 156 | struct acpi_video_enumerated_device *attached_array; |
| 155 | u8 attached_count; | 157 | u8 attached_count; |
| @@ -161,6 +163,7 @@ struct acpi_video_bus { | |||
| 161 | struct input_dev *input; | 163 | struct input_dev *input; |
| 162 | char phys[32]; /* for input device */ | 164 | char phys[32]; /* for input device */ |
| 163 | struct notifier_block pm_nb; | 165 | struct notifier_block pm_nb; |
| 166 | struct notifier_block backlight_nb; | ||
| 164 | }; | 167 | }; |
| 165 | 168 | ||
| 166 | struct acpi_video_device_flags { | 169 | struct acpi_video_device_flags { |
| @@ -473,6 +476,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 473 | }, | 476 | }, |
| 474 | { | 477 | { |
| 475 | .callback = video_set_use_native_backlight, | 478 | .callback = video_set_use_native_backlight, |
| 479 | .ident = "ThinkPad W530", | ||
| 480 | .matches = { | ||
| 481 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 482 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"), | ||
| 483 | }, | ||
| 484 | }, | ||
| 485 | { | ||
| 486 | .callback = video_set_use_native_backlight, | ||
| 476 | .ident = "ThinkPad X1 Carbon", | 487 | .ident = "ThinkPad X1 Carbon", |
| 477 | .matches = { | 488 | .matches = { |
| 478 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 489 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| @@ -488,6 +499,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 488 | }, | 499 | }, |
| 489 | }, | 500 | }, |
| 490 | { | 501 | { |
| 502 | .callback = video_set_use_native_backlight, | ||
| 503 | .ident = "Lenovo Yoga 2 11", | ||
| 504 | .matches = { | ||
| 505 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 506 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), | ||
| 507 | }, | ||
| 508 | }, | ||
| 509 | { | ||
| 491 | .callback = video_set_use_native_backlight, | 510 | .callback = video_set_use_native_backlight, |
| 492 | .ident = "Thinkpad Helix", | 511 | .ident = "Thinkpad Helix", |
| 493 | .matches = { | 512 | .matches = { |
| @@ -521,6 +540,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 521 | }, | 540 | }, |
| 522 | { | 541 | { |
| 523 | .callback = video_set_use_native_backlight, | 542 | .callback = video_set_use_native_backlight, |
| 543 | .ident = "Acer Aspire V5-171", | ||
| 544 | .matches = { | ||
| 545 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
| 546 | DMI_MATCH(DMI_PRODUCT_NAME, "V5-171"), | ||
| 547 | }, | ||
| 548 | }, | ||
| 549 | { | ||
| 550 | .callback = video_set_use_native_backlight, | ||
| 524 | .ident = "Acer Aspire V5-431", | 551 | .ident = "Acer Aspire V5-431", |
| 525 | .matches = { | 552 | .matches = { |
| 526 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 553 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| @@ -528,6 +555,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 528 | }, | 555 | }, |
| 529 | }, | 556 | }, |
| 530 | { | 557 | { |
| 558 | .callback = video_set_use_native_backlight, | ||
| 559 | .ident = "Acer Aspire V5-471G", | ||
| 560 | .matches = { | ||
| 561 | DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), | ||
| 562 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-471G"), | ||
| 563 | }, | ||
| 564 | }, | ||
| 565 | { | ||
| 531 | .callback = video_set_use_native_backlight, | 566 | .callback = video_set_use_native_backlight, |
| 532 | .ident = "HP ProBook 4340s", | 567 | .ident = "HP ProBook 4340s", |
| 533 | .matches = { | 568 | .matches = { |
| @@ -579,6 +614,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 579 | }, | 614 | }, |
| 580 | { | 615 | { |
| 581 | .callback = video_set_use_native_backlight, | 616 | .callback = video_set_use_native_backlight, |
| 617 | .ident = "HP EliteBook 8470p", | ||
| 618 | .matches = { | ||
| 619 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 620 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8470p"), | ||
| 621 | }, | ||
| 622 | }, | ||
| 623 | { | ||
| 624 | .callback = video_set_use_native_backlight, | ||
| 582 | .ident = "HP EliteBook 8780w", | 625 | .ident = "HP EliteBook 8780w", |
| 583 | .matches = { | 626 | .matches = { |
| 584 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 627 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| @@ -1658,88 +1701,92 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, | |||
| 1658 | 1701 | ||
| 1659 | static void acpi_video_dev_register_backlight(struct acpi_video_device *device) | 1702 | static void acpi_video_dev_register_backlight(struct acpi_video_device *device) |
| 1660 | { | 1703 | { |
| 1661 | if (acpi_video_verify_backlight_support()) { | 1704 | struct backlight_properties props; |
| 1662 | struct backlight_properties props; | 1705 | struct pci_dev *pdev; |
| 1663 | struct pci_dev *pdev; | 1706 | acpi_handle acpi_parent; |
| 1664 | acpi_handle acpi_parent; | 1707 | struct device *parent = NULL; |
| 1665 | struct device *parent = NULL; | 1708 | int result; |
| 1666 | int result; | 1709 | static int count; |
| 1667 | static int count; | 1710 | char *name; |
| 1668 | char *name; | ||
| 1669 | |||
| 1670 | result = acpi_video_init_brightness(device); | ||
| 1671 | if (result) | ||
| 1672 | return; | ||
| 1673 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); | ||
| 1674 | if (!name) | ||
| 1675 | return; | ||
| 1676 | count++; | ||
| 1677 | 1711 | ||
| 1678 | acpi_get_parent(device->dev->handle, &acpi_parent); | 1712 | result = acpi_video_init_brightness(device); |
| 1713 | if (result) | ||
| 1714 | return; | ||
| 1715 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); | ||
| 1716 | if (!name) | ||
| 1717 | return; | ||
| 1718 | count++; | ||
| 1679 | 1719 | ||
| 1680 | pdev = acpi_get_pci_dev(acpi_parent); | 1720 | acpi_get_parent(device->dev->handle, &acpi_parent); |
| 1681 | if (pdev) { | ||
| 1682 | parent = &pdev->dev; | ||
| 1683 | pci_dev_put(pdev); | ||
| 1684 | } | ||
| 1685 | 1721 | ||
| 1686 | memset(&props, 0, sizeof(struct backlight_properties)); | 1722 | pdev = acpi_get_pci_dev(acpi_parent); |
| 1687 | props.type = BACKLIGHT_FIRMWARE; | 1723 | if (pdev) { |
| 1688 | props.max_brightness = device->brightness->count - 3; | 1724 | parent = &pdev->dev; |
| 1689 | device->backlight = backlight_device_register(name, | 1725 | pci_dev_put(pdev); |
| 1690 | parent, | 1726 | } |
| 1691 | device, | ||
| 1692 | &acpi_backlight_ops, | ||
| 1693 | &props); | ||
| 1694 | kfree(name); | ||
| 1695 | if (IS_ERR(device->backlight)) | ||
| 1696 | return; | ||
| 1697 | 1727 | ||
| 1698 | /* | 1728 | memset(&props, 0, sizeof(struct backlight_properties)); |
| 1699 | * Save current brightness level in case we have to restore it | 1729 | props.type = BACKLIGHT_FIRMWARE; |
| 1700 | * before acpi_video_device_lcd_set_level() is called next time. | 1730 | props.max_brightness = device->brightness->count - 3; |
| 1701 | */ | 1731 | device->backlight = backlight_device_register(name, |
| 1702 | device->backlight->props.brightness = | 1732 | parent, |
| 1703 | acpi_video_get_brightness(device->backlight); | 1733 | device, |
| 1734 | &acpi_backlight_ops, | ||
| 1735 | &props); | ||
| 1736 | kfree(name); | ||
| 1737 | if (IS_ERR(device->backlight)) | ||
| 1738 | return; | ||
| 1704 | 1739 | ||
| 1705 | device->cooling_dev = thermal_cooling_device_register("LCD", | 1740 | /* |
| 1706 | device->dev, &video_cooling_ops); | 1741 | * Save current brightness level in case we have to restore it |
| 1707 | if (IS_ERR(device->cooling_dev)) { | 1742 | * before acpi_video_device_lcd_set_level() is called next time. |
| 1708 | /* | 1743 | */ |
| 1709 | * Set cooling_dev to NULL so we don't crash trying to | 1744 | device->backlight->props.brightness = |
| 1710 | * free it. | 1745 | acpi_video_get_brightness(device->backlight); |
| 1711 | * Also, why the hell we are returning early and | ||
| 1712 | * not attempt to register video output if cooling | ||
| 1713 | * device registration failed? | ||
| 1714 | * -- dtor | ||
| 1715 | */ | ||
| 1716 | device->cooling_dev = NULL; | ||
| 1717 | return; | ||
| 1718 | } | ||
| 1719 | 1746 | ||
| 1720 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", | 1747 | device->cooling_dev = thermal_cooling_device_register("LCD", |
| 1721 | device->cooling_dev->id); | 1748 | device->dev, &video_cooling_ops); |
| 1722 | result = sysfs_create_link(&device->dev->dev.kobj, | 1749 | if (IS_ERR(device->cooling_dev)) { |
| 1723 | &device->cooling_dev->device.kobj, | 1750 | /* |
| 1724 | "thermal_cooling"); | 1751 | * Set cooling_dev to NULL so we don't crash trying to free it. |
| 1725 | if (result) | 1752 | * Also, why the hell we are returning early and not attempt to |
| 1726 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1753 | * register video output if cooling device registration failed? |
| 1727 | result = sysfs_create_link(&device->cooling_dev->device.kobj, | 1754 | * -- dtor |
| 1728 | &device->dev->dev.kobj, "device"); | 1755 | */ |
| 1729 | if (result) | 1756 | device->cooling_dev = NULL; |
| 1730 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1757 | return; |
| 1731 | } | 1758 | } |
| 1759 | |||
| 1760 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", | ||
| 1761 | device->cooling_dev->id); | ||
| 1762 | result = sysfs_create_link(&device->dev->dev.kobj, | ||
| 1763 | &device->cooling_dev->device.kobj, | ||
| 1764 | "thermal_cooling"); | ||
| 1765 | if (result) | ||
| 1766 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 1767 | result = sysfs_create_link(&device->cooling_dev->device.kobj, | ||
| 1768 | &device->dev->dev.kobj, "device"); | ||
| 1769 | if (result) | ||
| 1770 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
| 1732 | } | 1771 | } |
| 1733 | 1772 | ||
| 1734 | static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) | 1773 | static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) |
| 1735 | { | 1774 | { |
| 1736 | struct acpi_video_device *dev; | 1775 | struct acpi_video_device *dev; |
| 1737 | 1776 | ||
| 1777 | if (video->backlight_registered) | ||
| 1778 | return 0; | ||
| 1779 | |||
| 1780 | if (!acpi_video_verify_backlight_support()) | ||
| 1781 | return 0; | ||
| 1782 | |||
| 1738 | mutex_lock(&video->device_list_lock); | 1783 | mutex_lock(&video->device_list_lock); |
| 1739 | list_for_each_entry(dev, &video->video_device_list, entry) | 1784 | list_for_each_entry(dev, &video->video_device_list, entry) |
| 1740 | acpi_video_dev_register_backlight(dev); | 1785 | acpi_video_dev_register_backlight(dev); |
| 1741 | mutex_unlock(&video->device_list_lock); | 1786 | mutex_unlock(&video->device_list_lock); |
| 1742 | 1787 | ||
| 1788 | video->backlight_registered = true; | ||
| 1789 | |||
| 1743 | video->pm_nb.notifier_call = acpi_video_resume; | 1790 | video->pm_nb.notifier_call = acpi_video_resume; |
| 1744 | video->pm_nb.priority = 0; | 1791 | video->pm_nb.priority = 0; |
| 1745 | return register_pm_notifier(&video->pm_nb); | 1792 | return register_pm_notifier(&video->pm_nb); |
| @@ -1767,13 +1814,20 @@ static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device | |||
| 1767 | static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) | 1814 | static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) |
| 1768 | { | 1815 | { |
| 1769 | struct acpi_video_device *dev; | 1816 | struct acpi_video_device *dev; |
| 1770 | int error = unregister_pm_notifier(&video->pm_nb); | 1817 | int error; |
| 1818 | |||
| 1819 | if (!video->backlight_registered) | ||
| 1820 | return 0; | ||
| 1821 | |||
| 1822 | error = unregister_pm_notifier(&video->pm_nb); | ||
| 1771 | 1823 | ||
| 1772 | mutex_lock(&video->device_list_lock); | 1824 | mutex_lock(&video->device_list_lock); |
| 1773 | list_for_each_entry(dev, &video->video_device_list, entry) | 1825 | list_for_each_entry(dev, &video->video_device_list, entry) |
| 1774 | acpi_video_dev_unregister_backlight(dev); | 1826 | acpi_video_dev_unregister_backlight(dev); |
| 1775 | mutex_unlock(&video->device_list_lock); | 1827 | mutex_unlock(&video->device_list_lock); |
| 1776 | 1828 | ||
| 1829 | video->backlight_registered = false; | ||
| 1830 | |||
| 1777 | return error; | 1831 | return error; |
| 1778 | } | 1832 | } |
| 1779 | 1833 | ||
| @@ -1867,6 +1921,56 @@ static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video) | |||
| 1867 | video->input = NULL; | 1921 | video->input = NULL; |
| 1868 | } | 1922 | } |
| 1869 | 1923 | ||
| 1924 | static int acpi_video_backlight_notify(struct notifier_block *nb, | ||
| 1925 | unsigned long val, void *bd) | ||
| 1926 | { | ||
| 1927 | struct backlight_device *backlight = bd; | ||
| 1928 | struct acpi_video_bus *video; | ||
| 1929 | |||
| 1930 | /* acpi_video_verify_backlight_support only cares about raw devices */ | ||
| 1931 | if (backlight->props.type != BACKLIGHT_RAW) | ||
| 1932 | return NOTIFY_DONE; | ||
| 1933 | |||
| 1934 | video = container_of(nb, struct acpi_video_bus, backlight_nb); | ||
| 1935 | |||
| 1936 | switch (val) { | ||
| 1937 | case BACKLIGHT_REGISTERED: | ||
| 1938 | if (!acpi_video_verify_backlight_support()) | ||
| 1939 | acpi_video_bus_unregister_backlight(video); | ||
| 1940 | break; | ||
| 1941 | case BACKLIGHT_UNREGISTERED: | ||
| 1942 | acpi_video_bus_register_backlight(video); | ||
| 1943 | break; | ||
| 1944 | } | ||
| 1945 | |||
| 1946 | return NOTIFY_OK; | ||
| 1947 | } | ||
| 1948 | |||
| 1949 | static int acpi_video_bus_add_backlight_notify_handler( | ||
| 1950 | struct acpi_video_bus *video) | ||
| 1951 | { | ||
| 1952 | int error; | ||
| 1953 | |||
| 1954 | video->backlight_nb.notifier_call = acpi_video_backlight_notify; | ||
| 1955 | video->backlight_nb.priority = 0; | ||
| 1956 | error = backlight_register_notifier(&video->backlight_nb); | ||
| 1957 | if (error == 0) | ||
| 1958 | video->backlight_notifier_registered = true; | ||
| 1959 | |||
| 1960 | return error; | ||
| 1961 | } | ||
| 1962 | |||
| 1963 | static int acpi_video_bus_remove_backlight_notify_handler( | ||
| 1964 | struct acpi_video_bus *video) | ||
| 1965 | { | ||
| 1966 | if (!video->backlight_notifier_registered) | ||
| 1967 | return 0; | ||
| 1968 | |||
| 1969 | video->backlight_notifier_registered = false; | ||
| 1970 | |||
| 1971 | return backlight_unregister_notifier(&video->backlight_nb); | ||
| 1972 | } | ||
| 1973 | |||
| 1870 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) | 1974 | static int acpi_video_bus_put_devices(struct acpi_video_bus *video) |
| 1871 | { | 1975 | { |
| 1872 | struct acpi_video_device *dev, *next; | 1976 | struct acpi_video_device *dev, *next; |
| @@ -1948,6 +2052,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
| 1948 | 2052 | ||
| 1949 | acpi_video_bus_register_backlight(video); | 2053 | acpi_video_bus_register_backlight(video); |
| 1950 | acpi_video_bus_add_notify_handler(video); | 2054 | acpi_video_bus_add_notify_handler(video); |
| 2055 | acpi_video_bus_add_backlight_notify_handler(video); | ||
| 1951 | 2056 | ||
| 1952 | return 0; | 2057 | return 0; |
| 1953 | 2058 | ||
| @@ -1971,6 +2076,7 @@ static int acpi_video_bus_remove(struct acpi_device *device) | |||
| 1971 | 2076 | ||
| 1972 | video = acpi_driver_data(device); | 2077 | video = acpi_driver_data(device); |
| 1973 | 2078 | ||
| 2079 | acpi_video_bus_remove_backlight_notify_handler(video); | ||
| 1974 | acpi_video_bus_remove_notify_handler(video); | 2080 | acpi_video_bus_remove_notify_handler(video); |
| 1975 | acpi_video_bus_unregister_backlight(video); | 2081 | acpi_video_bus_unregister_backlight(video); |
| 1976 | acpi_video_bus_put_devices(video); | 2082 | acpi_video_bus_put_devices(video); |
| @@ -2061,6 +2167,20 @@ void acpi_video_unregister(void) | |||
| 2061 | } | 2167 | } |
| 2062 | EXPORT_SYMBOL(acpi_video_unregister); | 2168 | EXPORT_SYMBOL(acpi_video_unregister); |
| 2063 | 2169 | ||
| 2170 | void acpi_video_unregister_backlight(void) | ||
| 2171 | { | ||
| 2172 | struct acpi_video_bus *video; | ||
| 2173 | |||
| 2174 | if (!register_count) | ||
| 2175 | return; | ||
| 2176 | |||
| 2177 | mutex_lock(&video_list_lock); | ||
| 2178 | list_for_each_entry(video, &video_bus_head, entry) | ||
| 2179 | acpi_video_bus_unregister_backlight(video); | ||
| 2180 | mutex_unlock(&video_list_lock); | ||
| 2181 | } | ||
| 2182 | EXPORT_SYMBOL(acpi_video_unregister_backlight); | ||
| 2183 | |||
| 2064 | /* | 2184 | /* |
| 2065 | * This is kind of nasty. Hardware using Intel chipsets may require | 2185 | * This is kind of nasty. Hardware using Intel chipsets may require |
| 2066 | * the video opregion code to be run first in order to initialise | 2186 | * the video opregion code to be run first in order to initialise |
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 630f6e84fc01..2c1e4aad7da3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include <linux/backlight.h> | 33 | #include <linux/backlight.h> |
| 34 | #include <linux/acpi.h> | ||
| 35 | 34 | ||
| 36 | #include "nouveau_drm.h" | 35 | #include "nouveau_drm.h" |
| 37 | #include "nouveau_reg.h" | 36 | #include "nouveau_reg.h" |
| @@ -222,14 +221,6 @@ nouveau_backlight_init(struct drm_device *dev) | |||
| 222 | struct nouveau_device *device = nv_device(drm->device); | 221 | struct nouveau_device *device = nv_device(drm->device); |
| 223 | struct drm_connector *connector; | 222 | struct drm_connector *connector; |
| 224 | 223 | ||
| 225 | #ifdef CONFIG_ACPI | ||
| 226 | if (acpi_video_backlight_support()) { | ||
| 227 | NV_INFO(drm, "ACPI backlight interface available, " | ||
| 228 | "not registering our own\n"); | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | #endif | ||
| 232 | |||
| 233 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 224 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
| 234 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && | 225 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && |
| 235 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) | 226 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index c91f69b39db4..bbf78b2d6d93 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
| @@ -570,6 +570,14 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { | |||
| 570 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), | 570 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), |
| 571 | }, | 571 | }, |
| 572 | }, | 572 | }, |
| 573 | { | ||
| 574 | .callback = video_set_backlight_video_vendor, | ||
| 575 | .ident = "Acer Aspire 5741", | ||
| 576 | .matches = { | ||
| 577 | DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), | ||
| 578 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"), | ||
| 579 | }, | ||
| 580 | }, | ||
| 573 | {} | 581 | {} |
| 574 | }; | 582 | }; |
| 575 | 583 | ||
| @@ -2228,7 +2236,7 @@ static int __init acer_wmi_init(void) | |||
| 2228 | pr_info("Brightness must be controlled by acpi video driver\n"); | 2236 | pr_info("Brightness must be controlled by acpi video driver\n"); |
| 2229 | } else { | 2237 | } else { |
| 2230 | pr_info("Disabling ACPI video driver\n"); | 2238 | pr_info("Disabling ACPI video driver\n"); |
| 2231 | acpi_video_unregister(); | 2239 | acpi_video_unregister_backlight(); |
| 2232 | } | 2240 | } |
| 2233 | 2241 | ||
| 2234 | if (wmi_has_guid(WMID_GUID3)) { | 2242 | if (wmi_has_guid(WMID_GUID3)) { |
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index bd2172c2d650..428089009cd5 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | static struct list_head backlight_dev_list; | 24 | static struct list_head backlight_dev_list; |
| 25 | static struct mutex backlight_dev_list_mutex; | 25 | static struct mutex backlight_dev_list_mutex; |
| 26 | static struct blocking_notifier_head backlight_notifier; | ||
| 26 | 27 | ||
| 27 | static const char *const backlight_types[] = { | 28 | static const char *const backlight_types[] = { |
| 28 | [BACKLIGHT_RAW] = "raw", | 29 | [BACKLIGHT_RAW] = "raw", |
| @@ -370,6 +371,9 @@ struct backlight_device *backlight_device_register(const char *name, | |||
| 370 | list_add(&new_bd->entry, &backlight_dev_list); | 371 | list_add(&new_bd->entry, &backlight_dev_list); |
| 371 | mutex_unlock(&backlight_dev_list_mutex); | 372 | mutex_unlock(&backlight_dev_list_mutex); |
| 372 | 373 | ||
| 374 | blocking_notifier_call_chain(&backlight_notifier, | ||
| 375 | BACKLIGHT_REGISTERED, new_bd); | ||
| 376 | |||
| 373 | return new_bd; | 377 | return new_bd; |
| 374 | } | 378 | } |
| 375 | EXPORT_SYMBOL(backlight_device_register); | 379 | EXPORT_SYMBOL(backlight_device_register); |
| @@ -413,6 +417,10 @@ void backlight_device_unregister(struct backlight_device *bd) | |||
| 413 | pmac_backlight = NULL; | 417 | pmac_backlight = NULL; |
| 414 | mutex_unlock(&pmac_backlight_mutex); | 418 | mutex_unlock(&pmac_backlight_mutex); |
| 415 | #endif | 419 | #endif |
| 420 | |||
| 421 | blocking_notifier_call_chain(&backlight_notifier, | ||
| 422 | BACKLIGHT_UNREGISTERED, bd); | ||
| 423 | |||
| 416 | mutex_lock(&bd->ops_lock); | 424 | mutex_lock(&bd->ops_lock); |
| 417 | bd->ops = NULL; | 425 | bd->ops = NULL; |
| 418 | mutex_unlock(&bd->ops_lock); | 426 | mutex_unlock(&bd->ops_lock); |
| @@ -438,6 +446,36 @@ static int devm_backlight_device_match(struct device *dev, void *res, | |||
| 438 | } | 446 | } |
| 439 | 447 | ||
| 440 | /** | 448 | /** |
| 449 | * backlight_register_notifier - get notified of backlight (un)registration | ||
| 450 | * @nb: notifier block with the notifier to call on backlight (un)registration | ||
| 451 | * | ||
| 452 | * @return 0 on success, otherwise a negative error code | ||
| 453 | * | ||
| 454 | * Register a notifier to get notified when backlight devices get registered | ||
| 455 | * or unregistered. | ||
| 456 | */ | ||
| 457 | int backlight_register_notifier(struct notifier_block *nb) | ||
| 458 | { | ||
| 459 | return blocking_notifier_chain_register(&backlight_notifier, nb); | ||
| 460 | } | ||
| 461 | EXPORT_SYMBOL(backlight_register_notifier); | ||
| 462 | |||
| 463 | /** | ||
| 464 | * backlight_unregister_notifier - unregister a backlight notifier | ||
| 465 | * @nb: notifier block to unregister | ||
| 466 | * | ||
| 467 | * @return 0 on success, otherwise a negative error code | ||
| 468 | * | ||
| 469 | * Register a notifier to get notified when backlight devices get registered | ||
| 470 | * or unregistered. | ||
| 471 | */ | ||
| 472 | int backlight_unregister_notifier(struct notifier_block *nb) | ||
| 473 | { | ||
| 474 | return blocking_notifier_chain_unregister(&backlight_notifier, nb); | ||
| 475 | } | ||
| 476 | EXPORT_SYMBOL(backlight_unregister_notifier); | ||
| 477 | |||
| 478 | /** | ||
| 441 | * devm_backlight_device_register - resource managed backlight_device_register() | 479 | * devm_backlight_device_register - resource managed backlight_device_register() |
| 442 | * @dev: the device to register | 480 | * @dev: the device to register |
| 443 | * @name: the name of the device | 481 | * @name: the name of the device |
| @@ -544,6 +582,8 @@ static int __init backlight_class_init(void) | |||
| 544 | backlight_class->pm = &backlight_class_dev_pm_ops; | 582 | backlight_class->pm = &backlight_class_dev_pm_ops; |
| 545 | INIT_LIST_HEAD(&backlight_dev_list); | 583 | INIT_LIST_HEAD(&backlight_dev_list); |
| 546 | mutex_init(&backlight_dev_list_mutex); | 584 | mutex_init(&backlight_dev_list_mutex); |
| 585 | BLOCKING_INIT_NOTIFIER_HEAD(&backlight_notifier); | ||
| 586 | |||
| 547 | return 0; | 587 | return 0; |
| 548 | } | 588 | } |
| 549 | 589 | ||
diff --git a/include/acpi/video.h b/include/acpi/video.h index 61109f2609fc..ea4c7bbded4d 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h | |||
| @@ -19,11 +19,13 @@ struct acpi_device; | |||
| 19 | #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) | 19 | #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) |
| 20 | extern int acpi_video_register(void); | 20 | extern int acpi_video_register(void); |
| 21 | extern void acpi_video_unregister(void); | 21 | extern void acpi_video_unregister(void); |
| 22 | extern void acpi_video_unregister_backlight(void); | ||
| 22 | extern int acpi_video_get_edid(struct acpi_device *device, int type, | 23 | extern int acpi_video_get_edid(struct acpi_device *device, int type, |
| 23 | int device_id, void **edid); | 24 | int device_id, void **edid); |
| 24 | #else | 25 | #else |
| 25 | static inline int acpi_video_register(void) { return 0; } | 26 | static inline int acpi_video_register(void) { return 0; } |
| 26 | static inline void acpi_video_unregister(void) { return; } | 27 | static inline void acpi_video_unregister(void) { return; } |
| 28 | static inline void acpi_video_unregister_backlight(void) { return; } | ||
| 27 | static inline int acpi_video_get_edid(struct acpi_device *device, int type, | 29 | static inline int acpi_video_get_edid(struct acpi_device *device, int type, |
| 28 | int device_id, void **edid) | 30 | int device_id, void **edid) |
| 29 | { | 31 | { |
diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 72647429adf6..adb14a8616df 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h | |||
| @@ -40,6 +40,11 @@ enum backlight_type { | |||
| 40 | BACKLIGHT_TYPE_MAX, | 40 | BACKLIGHT_TYPE_MAX, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | enum backlight_notification { | ||
| 44 | BACKLIGHT_REGISTERED, | ||
| 45 | BACKLIGHT_UNREGISTERED, | ||
| 46 | }; | ||
| 47 | |||
| 43 | struct backlight_device; | 48 | struct backlight_device; |
| 44 | struct fb_info; | 49 | struct fb_info; |
| 45 | 50 | ||
| @@ -133,6 +138,8 @@ extern void devm_backlight_device_unregister(struct device *dev, | |||
| 133 | extern void backlight_force_update(struct backlight_device *bd, | 138 | extern void backlight_force_update(struct backlight_device *bd, |
| 134 | enum backlight_update_reason reason); | 139 | enum backlight_update_reason reason); |
| 135 | extern bool backlight_device_registered(enum backlight_type type); | 140 | extern bool backlight_device_registered(enum backlight_type type); |
| 141 | extern int backlight_register_notifier(struct notifier_block *nb); | ||
| 142 | extern int backlight_unregister_notifier(struct notifier_block *nb); | ||
| 136 | 143 | ||
| 137 | #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) | 144 | #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) |
| 138 | 145 | ||
