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 | ||