diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/event.c | 28 | ||||
-rw-r--r-- | drivers/acpi/video.c | 135 |
2 files changed, 94 insertions, 69 deletions
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 5c95863f8fa9..5479dc0eeeec 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c | |||
@@ -109,6 +109,34 @@ static const struct file_operations acpi_system_event_ops = { | |||
109 | }; | 109 | }; |
110 | #endif /* CONFIG_ACPI_PROC_EVENT */ | 110 | #endif /* CONFIG_ACPI_PROC_EVENT */ |
111 | 111 | ||
112 | /* ACPI notifier chain */ | ||
113 | BLOCKING_NOTIFIER_HEAD(acpi_chain_head); | ||
114 | |||
115 | int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) | ||
116 | { | ||
117 | struct acpi_bus_event event; | ||
118 | |||
119 | strcpy(event.device_class, dev->pnp.device_class); | ||
120 | strcpy(event.bus_id, dev->pnp.bus_id); | ||
121 | event.type = type; | ||
122 | event.data = data; | ||
123 | return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event) | ||
124 | == NOTIFY_BAD) ? -EINVAL : 0; | ||
125 | } | ||
126 | EXPORT_SYMBOL(acpi_notifier_call_chain); | ||
127 | |||
128 | int register_acpi_notifier(struct notifier_block *nb) | ||
129 | { | ||
130 | return blocking_notifier_chain_register(&acpi_chain_head, nb); | ||
131 | } | ||
132 | EXPORT_SYMBOL(register_acpi_notifier); | ||
133 | |||
134 | int unregister_acpi_notifier(struct notifier_block *nb) | ||
135 | { | ||
136 | return blocking_notifier_chain_unregister(&acpi_chain_head, nb); | ||
137 | } | ||
138 | EXPORT_SYMBOL(unregister_acpi_notifier); | ||
139 | |||
112 | #ifdef CONFIG_NET | 140 | #ifdef CONFIG_NET |
113 | static unsigned int acpi_event_seqnum; | 141 | static unsigned int acpi_event_seqnum; |
114 | struct acpi_genl_event { | 142 | struct acpi_genl_event { |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 82815cff15a9..7f714fa2a454 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -73,8 +73,12 @@ MODULE_AUTHOR("Bruno Ducrot"); | |||
73 | MODULE_DESCRIPTION("ACPI Video Driver"); | 73 | MODULE_DESCRIPTION("ACPI Video Driver"); |
74 | MODULE_LICENSE("GPL"); | 74 | MODULE_LICENSE("GPL"); |
75 | 75 | ||
76 | static int brightness_switch_enabled = 1; | ||
77 | module_param(brightness_switch_enabled, bool, 0644); | ||
78 | |||
76 | static int acpi_video_bus_add(struct acpi_device *device); | 79 | static int acpi_video_bus_add(struct acpi_device *device); |
77 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 80 | static int acpi_video_bus_remove(struct acpi_device *device, int type); |
81 | static int acpi_video_resume(struct acpi_device *device); | ||
78 | 82 | ||
79 | static const struct acpi_device_id video_device_ids[] = { | 83 | static const struct acpi_device_id video_device_ids[] = { |
80 | {ACPI_VIDEO_HID, 0}, | 84 | {ACPI_VIDEO_HID, 0}, |
@@ -89,6 +93,7 @@ static struct acpi_driver acpi_video_bus = { | |||
89 | .ops = { | 93 | .ops = { |
90 | .add = acpi_video_bus_add, | 94 | .add = acpi_video_bus_add, |
91 | .remove = acpi_video_bus_remove, | 95 | .remove = acpi_video_bus_remove, |
96 | .resume = acpi_video_resume, | ||
92 | }, | 97 | }, |
93 | }; | 98 | }; |
94 | 99 | ||
@@ -275,7 +280,6 @@ static void acpi_video_device_rebind(struct acpi_video_bus *video); | |||
275 | static void acpi_video_device_bind(struct acpi_video_bus *video, | 280 | static void acpi_video_device_bind(struct acpi_video_bus *video, |
276 | struct acpi_video_device *device); | 281 | struct acpi_video_device *device); |
277 | static int acpi_video_device_enumerate(struct acpi_video_bus *video); | 282 | static int acpi_video_device_enumerate(struct acpi_video_bus *video); |
278 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event); | ||
279 | static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, | 283 | static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, |
280 | int level); | 284 | int level); |
281 | static int acpi_video_device_lcd_get_level_current( | 285 | static int acpi_video_device_lcd_get_level_current( |
@@ -800,11 +804,40 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
800 | static int acpi_video_bus_check(struct acpi_video_bus *video) | 804 | static int acpi_video_bus_check(struct acpi_video_bus *video) |
801 | { | 805 | { |
802 | acpi_status status = -ENOENT; | 806 | acpi_status status = -ENOENT; |
803 | 807 | long device_id; | |
808 | struct device *dev; | ||
809 | struct acpi_device *device; | ||
804 | 810 | ||
805 | if (!video) | 811 | if (!video) |
806 | return -EINVAL; | 812 | return -EINVAL; |
807 | 813 | ||
814 | device = video->device; | ||
815 | |||
816 | status = | ||
817 | acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); | ||
818 | |||
819 | if (!ACPI_SUCCESS(status)) | ||
820 | return -ENODEV; | ||
821 | |||
822 | /* We need to attempt to determine whether the _ADR refers to a | ||
823 | PCI device or not. There's no terribly good way to do this, | ||
824 | so the best we can hope for is to assume that there'll never | ||
825 | be a video device in the host bridge */ | ||
826 | if (device_id >= 0x10000) { | ||
827 | /* It looks like a PCI device. Does it exist? */ | ||
828 | dev = acpi_get_physical_device(device->handle); | ||
829 | } else { | ||
830 | /* It doesn't look like a PCI device. Does its parent | ||
831 | exist? */ | ||
832 | acpi_handle phandle; | ||
833 | if (acpi_get_parent(device->handle, &phandle)) | ||
834 | return -ENODEV; | ||
835 | dev = acpi_get_physical_device(phandle); | ||
836 | } | ||
837 | if (!dev) | ||
838 | return -ENODEV; | ||
839 | put_device(dev); | ||
840 | |||
808 | /* Since there is no HID, CID and so on for VGA driver, we have | 841 | /* Since there is no HID, CID and so on for VGA driver, we have |
809 | * to check well known required nodes. | 842 | * to check well known required nodes. |
810 | */ | 843 | */ |
@@ -1683,64 +1716,6 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1683 | return status; | 1716 | return status; |
1684 | } | 1717 | } |
1685 | 1718 | ||
1686 | /* | ||
1687 | * Arg: | ||
1688 | * video : video bus device | ||
1689 | * event : notify event | ||
1690 | * | ||
1691 | * Return: | ||
1692 | * < 0 : error | ||
1693 | * | ||
1694 | * 1. Find out the current active output device. | ||
1695 | * 2. Identify the next output device to switch to. | ||
1696 | * 3. call _DSS to do actual switch. | ||
1697 | */ | ||
1698 | |||
1699 | static int acpi_video_switch_output(struct acpi_video_bus *video, int event) | ||
1700 | { | ||
1701 | struct list_head *node; | ||
1702 | struct acpi_video_device *dev = NULL; | ||
1703 | struct acpi_video_device *dev_next = NULL; | ||
1704 | struct acpi_video_device *dev_prev = NULL; | ||
1705 | unsigned long state; | ||
1706 | int status = 0; | ||
1707 | |||
1708 | mutex_lock(&video->device_list_lock); | ||
1709 | |||
1710 | list_for_each(node, &video->video_device_list) { | ||
1711 | dev = container_of(node, struct acpi_video_device, entry); | ||
1712 | status = acpi_video_device_get_state(dev, &state); | ||
1713 | if (state & 0x2) { | ||
1714 | dev_next = container_of(node->next, | ||
1715 | struct acpi_video_device, entry); | ||
1716 | dev_prev = container_of(node->prev, | ||
1717 | struct acpi_video_device, entry); | ||
1718 | goto out; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | dev_next = container_of(node->next, struct acpi_video_device, entry); | ||
1723 | dev_prev = container_of(node->prev, struct acpi_video_device, entry); | ||
1724 | |||
1725 | out: | ||
1726 | mutex_unlock(&video->device_list_lock); | ||
1727 | |||
1728 | switch (event) { | ||
1729 | case ACPI_VIDEO_NOTIFY_CYCLE: | ||
1730 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: | ||
1731 | acpi_video_device_set_state(dev, 0); | ||
1732 | acpi_video_device_set_state(dev_next, 0x80000001); | ||
1733 | break; | ||
1734 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: | ||
1735 | acpi_video_device_set_state(dev, 0); | ||
1736 | acpi_video_device_set_state(dev_prev, 0x80000001); | ||
1737 | default: | ||
1738 | break; | ||
1739 | } | ||
1740 | |||
1741 | return status; | ||
1742 | } | ||
1743 | |||
1744 | static int | 1719 | static int |
1745 | acpi_video_get_next_level(struct acpi_video_device *device, | 1720 | acpi_video_get_next_level(struct acpi_video_device *device, |
1746 | u32 level_current, u32 event) | 1721 | u32 level_current, u32 event) |
@@ -1908,23 +1883,19 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1908 | * connector. */ | 1883 | * connector. */ |
1909 | acpi_video_device_enumerate(video); | 1884 | acpi_video_device_enumerate(video); |
1910 | acpi_video_device_rebind(video); | 1885 | acpi_video_device_rebind(video); |
1911 | acpi_video_switch_output(video, event); | ||
1912 | acpi_bus_generate_proc_event(device, event, 0); | 1886 | acpi_bus_generate_proc_event(device, event, 0); |
1913 | keycode = KEY_SWITCHVIDEOMODE; | 1887 | keycode = KEY_SWITCHVIDEOMODE; |
1914 | break; | 1888 | break; |
1915 | 1889 | ||
1916 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ | 1890 | case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ |
1917 | acpi_video_switch_output(video, event); | ||
1918 | acpi_bus_generate_proc_event(device, event, 0); | 1891 | acpi_bus_generate_proc_event(device, event, 0); |
1919 | keycode = KEY_SWITCHVIDEOMODE; | 1892 | keycode = KEY_SWITCHVIDEOMODE; |
1920 | break; | 1893 | break; |
1921 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ | 1894 | case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ |
1922 | acpi_video_switch_output(video, event); | ||
1923 | acpi_bus_generate_proc_event(device, event, 0); | 1895 | acpi_bus_generate_proc_event(device, event, 0); |
1924 | keycode = KEY_VIDEO_NEXT; | 1896 | keycode = KEY_VIDEO_NEXT; |
1925 | break; | 1897 | break; |
1926 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ | 1898 | case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ |
1927 | acpi_video_switch_output(video, event); | ||
1928 | acpi_bus_generate_proc_event(device, event, 0); | 1899 | acpi_bus_generate_proc_event(device, event, 0); |
1929 | keycode = KEY_VIDEO_PREV; | 1900 | keycode = KEY_VIDEO_PREV; |
1930 | break; | 1901 | break; |
@@ -1936,6 +1907,7 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | |||
1936 | break; | 1907 | break; |
1937 | } | 1908 | } |
1938 | 1909 | ||
1910 | acpi_notifier_call_chain(device, event, 0); | ||
1939 | input_report_key(input, keycode, 1); | 1911 | input_report_key(input, keycode, 1); |
1940 | input_sync(input); | 1912 | input_sync(input); |
1941 | input_report_key(input, keycode, 0); | 1913 | input_report_key(input, keycode, 0); |
@@ -1961,27 +1933,32 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1961 | 1933 | ||
1962 | switch (event) { | 1934 | switch (event) { |
1963 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ | 1935 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ |
1964 | acpi_video_switch_brightness(video_device, event); | 1936 | if (brightness_switch_enabled) |
1937 | acpi_video_switch_brightness(video_device, event); | ||
1965 | acpi_bus_generate_proc_event(device, event, 0); | 1938 | acpi_bus_generate_proc_event(device, event, 0); |
1966 | keycode = KEY_BRIGHTNESS_CYCLE; | 1939 | keycode = KEY_BRIGHTNESS_CYCLE; |
1967 | break; | 1940 | break; |
1968 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ | 1941 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ |
1969 | acpi_video_switch_brightness(video_device, event); | 1942 | if (brightness_switch_enabled) |
1943 | acpi_video_switch_brightness(video_device, event); | ||
1970 | acpi_bus_generate_proc_event(device, event, 0); | 1944 | acpi_bus_generate_proc_event(device, event, 0); |
1971 | keycode = KEY_BRIGHTNESSUP; | 1945 | keycode = KEY_BRIGHTNESSUP; |
1972 | break; | 1946 | break; |
1973 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ | 1947 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ |
1974 | acpi_video_switch_brightness(video_device, event); | 1948 | if (brightness_switch_enabled) |
1949 | acpi_video_switch_brightness(video_device, event); | ||
1975 | acpi_bus_generate_proc_event(device, event, 0); | 1950 | acpi_bus_generate_proc_event(device, event, 0); |
1976 | keycode = KEY_BRIGHTNESSDOWN; | 1951 | keycode = KEY_BRIGHTNESSDOWN; |
1977 | break; | 1952 | break; |
1978 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ | 1953 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ |
1979 | acpi_video_switch_brightness(video_device, event); | 1954 | if (brightness_switch_enabled) |
1955 | acpi_video_switch_brightness(video_device, event); | ||
1980 | acpi_bus_generate_proc_event(device, event, 0); | 1956 | acpi_bus_generate_proc_event(device, event, 0); |
1981 | keycode = KEY_BRIGHTNESS_ZERO; | 1957 | keycode = KEY_BRIGHTNESS_ZERO; |
1982 | break; | 1958 | break; |
1983 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ | 1959 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ |
1984 | acpi_video_switch_brightness(video_device, event); | 1960 | if (brightness_switch_enabled) |
1961 | acpi_video_switch_brightness(video_device, event); | ||
1985 | acpi_bus_generate_proc_event(device, event, 0); | 1962 | acpi_bus_generate_proc_event(device, event, 0); |
1986 | keycode = KEY_DISPLAY_OFF; | 1963 | keycode = KEY_DISPLAY_OFF; |
1987 | break; | 1964 | break; |
@@ -1992,6 +1969,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1992 | break; | 1969 | break; |
1993 | } | 1970 | } |
1994 | 1971 | ||
1972 | acpi_notifier_call_chain(device, event, 0); | ||
1995 | input_report_key(input, keycode, 1); | 1973 | input_report_key(input, keycode, 1); |
1996 | input_sync(input); | 1974 | input_sync(input); |
1997 | input_report_key(input, keycode, 0); | 1975 | input_report_key(input, keycode, 0); |
@@ -2001,6 +1979,25 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
2001 | } | 1979 | } |
2002 | 1980 | ||
2003 | static int instance; | 1981 | static int instance; |
1982 | static int acpi_video_resume(struct acpi_device *device) | ||
1983 | { | ||
1984 | struct acpi_video_bus *video; | ||
1985 | struct acpi_video_device *video_device; | ||
1986 | int i; | ||
1987 | |||
1988 | if (!device || !acpi_driver_data(device)) | ||
1989 | return -EINVAL; | ||
1990 | |||
1991 | video = acpi_driver_data(device); | ||
1992 | |||
1993 | for (i = 0; i < video->attached_count; i++) { | ||
1994 | video_device = video->attached_array[i].bind_info; | ||
1995 | if (video_device && video_device->backlight) | ||
1996 | acpi_video_set_brightness(video_device->backlight); | ||
1997 | } | ||
1998 | return AE_OK; | ||
1999 | } | ||
2000 | |||
2004 | static int acpi_video_bus_add(struct acpi_device *device) | 2001 | static int acpi_video_bus_add(struct acpi_device *device) |
2005 | { | 2002 | { |
2006 | acpi_status status; | 2003 | acpi_status status; |