diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index ab06143672bc..d7ff61c0d571 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -79,6 +79,7 @@ module_param(brightness_switch_enabled, bool, 0644); | |||
79 | static int acpi_video_bus_add(struct acpi_device *device); | 79 | static int acpi_video_bus_add(struct acpi_device *device); |
80 | 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); | 81 | static int acpi_video_resume(struct acpi_device *device); |
82 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event); | ||
82 | 83 | ||
83 | static const struct acpi_device_id video_device_ids[] = { | 84 | static const struct acpi_device_id video_device_ids[] = { |
84 | {ACPI_VIDEO_HID, 0}, | 85 | {ACPI_VIDEO_HID, 0}, |
@@ -94,6 +95,7 @@ static struct acpi_driver acpi_video_bus = { | |||
94 | .add = acpi_video_bus_add, | 95 | .add = acpi_video_bus_add, |
95 | .remove = acpi_video_bus_remove, | 96 | .remove = acpi_video_bus_remove, |
96 | .resume = acpi_video_resume, | 97 | .resume = acpi_video_resume, |
98 | .notify = acpi_video_bus_notify, | ||
97 | }, | 99 | }, |
98 | }; | 100 | }; |
99 | 101 | ||
@@ -768,10 +770,12 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
768 | * In this case, the first two elements in _BCL packages | 770 | * In this case, the first two elements in _BCL packages |
769 | * are also supported brightness levels that OS should take care of. | 771 | * are also supported brightness levels that OS should take care of. |
770 | */ | 772 | */ |
771 | for (i = 2; i < count; i++) | 773 | for (i = 2; i < count; i++) { |
772 | if (br->levels[i] == br->levels[0] || | 774 | if (br->levels[i] == br->levels[0]) |
773 | br->levels[i] == br->levels[1]) | ||
774 | level_ac_battery++; | 775 | level_ac_battery++; |
776 | if (br->levels[i] == br->levels[1]) | ||
777 | level_ac_battery++; | ||
778 | } | ||
775 | 779 | ||
776 | if (level_ac_battery < 2) { | 780 | if (level_ac_battery < 2) { |
777 | level_ac_battery = 2 - level_ac_battery; | 781 | level_ac_battery = 2 - level_ac_battery; |
@@ -805,12 +809,19 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
805 | br->flags._BCM_use_index = br->flags._BCL_use_index; | 809 | br->flags._BCM_use_index = br->flags._BCL_use_index; |
806 | 810 | ||
807 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ | 811 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ |
808 | br->curr = max_level; | 812 | br->curr = level_old = max_level; |
813 | |||
814 | if (!device->cap._BQC) | ||
815 | goto set_level; | ||
816 | |||
809 | result = acpi_video_device_lcd_get_level_current(device, &level_old); | 817 | result = acpi_video_device_lcd_get_level_current(device, &level_old); |
810 | if (result) | 818 | if (result) |
811 | goto out_free_levels; | 819 | goto out_free_levels; |
812 | 820 | ||
813 | result = acpi_video_device_lcd_set_level(device, br->curr); | 821 | /* |
822 | * Set the level to maximum and check if _BQC uses indexed value | ||
823 | */ | ||
824 | result = acpi_video_device_lcd_set_level(device, max_level); | ||
814 | if (result) | 825 | if (result) |
815 | goto out_free_levels; | 826 | goto out_free_levels; |
816 | 827 | ||
@@ -818,25 +829,19 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
818 | if (result) | 829 | if (result) |
819 | goto out_free_levels; | 830 | goto out_free_levels; |
820 | 831 | ||
821 | if ((level != level_old) && !br->flags._BCM_use_index) { | 832 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); |
822 | /* Note: | 833 | |
823 | * This piece of code does not work correctly if the current | 834 | if (!br->flags._BQC_use_index) |
824 | * brightness levels is 0. | 835 | goto set_level; |
825 | * But I guess boxes that boot with such a dark screen are rare | 836 | |
826 | * and no more code is needed to cover this specifial case. | 837 | if (br->flags._BCL_reversed) |
827 | */ | 838 | level_old = (br->count - 1) - level_old; |
828 | 839 | level_old = br->levels[level_old]; | |
829 | if (level_ac_battery != 2) { | 840 | |
830 | /* | 841 | set_level: |
831 | * For now, we don't support the _BCL like this: | 842 | result = acpi_video_device_lcd_set_level(device, level_old); |
832 | * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16 | 843 | if (result) |
833 | * because we may mess up the index returned by _BQC. | 844 | goto out_free_levels; |
834 | * Plus: we have not got a box like this. | ||
835 | */ | ||
836 | ACPI_ERROR((AE_INFO, "_BCL not supported\n")); | ||
837 | } | ||
838 | br->flags._BQC_use_index = 1; | ||
839 | } | ||
840 | 845 | ||
841 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 846 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
842 | "found %d brightness levels\n", count - 2)); | 847 | "found %d brightness levels\n", count - 2)); |
@@ -1986,17 +1991,15 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) | |||
1986 | return acpi_video_bus_DOS(video, 0, 1); | 1991 | return acpi_video_bus_DOS(video, 0, 1); |
1987 | } | 1992 | } |
1988 | 1993 | ||
1989 | static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) | 1994 | static void acpi_video_bus_notify(struct acpi_device *device, u32 event) |
1990 | { | 1995 | { |
1991 | struct acpi_video_bus *video = data; | 1996 | struct acpi_video_bus *video = acpi_driver_data(device); |
1992 | struct acpi_device *device = NULL; | ||
1993 | struct input_dev *input; | 1997 | struct input_dev *input; |
1994 | int keycode; | 1998 | int keycode; |
1995 | 1999 | ||
1996 | if (!video) | 2000 | if (!video) |
1997 | return; | 2001 | return; |
1998 | 2002 | ||
1999 | device = video->device; | ||
2000 | input = video->input; | 2003 | input = video->input; |
2001 | 2004 | ||
2002 | switch (event) { | 2005 | switch (event) { |
@@ -2127,7 +2130,6 @@ static int acpi_video_resume(struct acpi_device *device) | |||
2127 | 2130 | ||
2128 | static int acpi_video_bus_add(struct acpi_device *device) | 2131 | static int acpi_video_bus_add(struct acpi_device *device) |
2129 | { | 2132 | { |
2130 | acpi_status status; | ||
2131 | struct acpi_video_bus *video; | 2133 | struct acpi_video_bus *video; |
2132 | struct input_dev *input; | 2134 | struct input_dev *input; |
2133 | int error; | 2135 | int error; |
@@ -2169,20 +2171,10 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
2169 | acpi_video_bus_get_devices(video, device); | 2171 | acpi_video_bus_get_devices(video, device); |
2170 | acpi_video_bus_start_devices(video); | 2172 | acpi_video_bus_start_devices(video); |
2171 | 2173 | ||
2172 | status = acpi_install_notify_handler(device->handle, | ||
2173 | ACPI_DEVICE_NOTIFY, | ||
2174 | acpi_video_bus_notify, video); | ||
2175 | if (ACPI_FAILURE(status)) { | ||
2176 | printk(KERN_ERR PREFIX | ||
2177 | "Error installing notify handler\n"); | ||
2178 | error = -ENODEV; | ||
2179 | goto err_stop_video; | ||
2180 | } | ||
2181 | |||
2182 | video->input = input = input_allocate_device(); | 2174 | video->input = input = input_allocate_device(); |
2183 | if (!input) { | 2175 | if (!input) { |
2184 | error = -ENOMEM; | 2176 | error = -ENOMEM; |
2185 | goto err_uninstall_notify; | 2177 | goto err_stop_video; |
2186 | } | 2178 | } |
2187 | 2179 | ||
2188 | snprintf(video->phys, sizeof(video->phys), | 2180 | snprintf(video->phys, sizeof(video->phys), |
@@ -2218,9 +2210,6 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
2218 | 2210 | ||
2219 | err_free_input_dev: | 2211 | err_free_input_dev: |
2220 | input_free_device(input); | 2212 | input_free_device(input); |
2221 | err_uninstall_notify: | ||
2222 | acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, | ||
2223 | acpi_video_bus_notify); | ||
2224 | err_stop_video: | 2213 | err_stop_video: |
2225 | acpi_video_bus_stop_devices(video); | 2214 | acpi_video_bus_stop_devices(video); |
2226 | acpi_video_bus_put_devices(video); | 2215 | acpi_video_bus_put_devices(video); |
@@ -2235,7 +2224,6 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
2235 | 2224 | ||
2236 | static int acpi_video_bus_remove(struct acpi_device *device, int type) | 2225 | static int acpi_video_bus_remove(struct acpi_device *device, int type) |
2237 | { | 2226 | { |
2238 | acpi_status status = 0; | ||
2239 | struct acpi_video_bus *video = NULL; | 2227 | struct acpi_video_bus *video = NULL; |
2240 | 2228 | ||
2241 | 2229 | ||
@@ -2245,11 +2233,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
2245 | video = acpi_driver_data(device); | 2233 | video = acpi_driver_data(device); |
2246 | 2234 | ||
2247 | acpi_video_bus_stop_devices(video); | 2235 | acpi_video_bus_stop_devices(video); |
2248 | |||
2249 | status = acpi_remove_notify_handler(video->device->handle, | ||
2250 | ACPI_DEVICE_NOTIFY, | ||
2251 | acpi_video_bus_notify); | ||
2252 | |||
2253 | acpi_video_bus_put_devices(video); | 2236 | acpi_video_bus_put_devices(video); |
2254 | acpi_video_bus_remove_fs(device); | 2237 | acpi_video_bus_remove_fs(device); |
2255 | 2238 | ||
@@ -2313,7 +2296,7 @@ static int __init acpi_video_init(void) | |||
2313 | return acpi_video_register(); | 2296 | return acpi_video_register(); |
2314 | } | 2297 | } |
2315 | 2298 | ||
2316 | static void __exit acpi_video_exit(void) | 2299 | void __exit acpi_video_exit(void) |
2317 | { | 2300 | { |
2318 | 2301 | ||
2319 | acpi_bus_unregister_driver(&acpi_video_bus); | 2302 | acpi_bus_unregister_driver(&acpi_video_bus); |
@@ -2322,6 +2305,7 @@ static void __exit acpi_video_exit(void) | |||
2322 | 2305 | ||
2323 | return; | 2306 | return; |
2324 | } | 2307 | } |
2308 | EXPORT_SYMBOL(acpi_video_exit); | ||
2325 | 2309 | ||
2326 | module_init(acpi_video_init); | 2310 | module_init(acpi_video_init); |
2327 | module_exit(acpi_video_exit); | 2311 | module_exit(acpi_video_exit); |