diff options
author | Len Brown <len.brown@intel.com> | 2009-09-19 02:31:39 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-09-19 02:31:39 -0400 |
commit | 193a6dec1c0246a80b6d0101e4f351ccf877bcac (patch) | |
tree | 2f0f0ff70241ae8c9dc0c07c3369c0bf96956b14 /drivers/acpi/video.c | |
parent | 53de5356be3ac62c22ae1da266943059b169d9b1 (diff) | |
parent | 90c53ca426cb93d15eefea79dcf6bd15ad3ffeb4 (diff) |
Merge branch 'video' into release
Conflicts:
drivers/acpi/video.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 76 |
1 files changed, 50 insertions, 26 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 902fd526f32..94b1a4c5aba 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -200,7 +200,7 @@ struct acpi_video_device { | |||
200 | struct acpi_device *dev; | 200 | struct acpi_device *dev; |
201 | struct acpi_video_device_brightness *brightness; | 201 | struct acpi_video_device_brightness *brightness; |
202 | struct backlight_device *backlight; | 202 | struct backlight_device *backlight; |
203 | struct thermal_cooling_device *cdev; | 203 | struct thermal_cooling_device *cooling_dev; |
204 | struct output_device *output_dev; | 204 | struct output_device *output_dev; |
205 | }; | 205 | }; |
206 | 206 | ||
@@ -389,20 +389,20 @@ static struct output_properties acpi_output_properties = { | |||
389 | 389 | ||
390 | 390 | ||
391 | /* thermal cooling device callbacks */ | 391 | /* thermal cooling device callbacks */ |
392 | static int video_get_max_state(struct thermal_cooling_device *cdev, unsigned | 392 | static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned |
393 | long *state) | 393 | long *state) |
394 | { | 394 | { |
395 | struct acpi_device *device = cdev->devdata; | 395 | struct acpi_device *device = cooling_dev->devdata; |
396 | struct acpi_video_device *video = acpi_driver_data(device); | 396 | struct acpi_video_device *video = acpi_driver_data(device); |
397 | 397 | ||
398 | *state = video->brightness->count - 3; | 398 | *state = video->brightness->count - 3; |
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned | 402 | static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsigned |
403 | long *state) | 403 | long *state) |
404 | { | 404 | { |
405 | struct acpi_device *device = cdev->devdata; | 405 | struct acpi_device *device = cooling_dev->devdata; |
406 | struct acpi_video_device *video = acpi_driver_data(device); | 406 | struct acpi_video_device *video = acpi_driver_data(device); |
407 | unsigned long long level; | 407 | unsigned long long level; |
408 | int offset; | 408 | int offset; |
@@ -419,9 +419,9 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned | |||
419 | } | 419 | } |
420 | 420 | ||
421 | static int | 421 | static int |
422 | video_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) | 422 | video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state) |
423 | { | 423 | { |
424 | struct acpi_device *device = cdev->devdata; | 424 | struct acpi_device *device = cooling_dev->devdata; |
425 | struct acpi_video_device *video = acpi_driver_data(device); | 425 | struct acpi_video_device *video = acpi_driver_data(device); |
426 | int level; | 426 | int level; |
427 | 427 | ||
@@ -605,6 +605,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | |||
605 | unsigned long long *level) | 605 | unsigned long long *level) |
606 | { | 606 | { |
607 | acpi_status status = AE_OK; | 607 | acpi_status status = AE_OK; |
608 | int i; | ||
608 | 609 | ||
609 | if (device->cap._BQC || device->cap._BCQ) { | 610 | if (device->cap._BQC || device->cap._BCQ) { |
610 | char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; | 611 | char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; |
@@ -620,8 +621,15 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | |||
620 | 621 | ||
621 | } | 622 | } |
622 | *level += bqc_offset_aml_bug_workaround; | 623 | *level += bqc_offset_aml_bug_workaround; |
623 | device->brightness->curr = *level; | 624 | for (i = 2; i < device->brightness->count; i++) |
624 | return 0; | 625 | if (device->brightness->levels[i] == *level) { |
626 | device->brightness->curr = *level; | ||
627 | return 0; | ||
628 | } | ||
629 | /* BQC returned an invalid level. Stop using it. */ | ||
630 | ACPI_WARNING((AE_INFO, "%s returned an invalid level", | ||
631 | buf)); | ||
632 | device->cap._BQC = device->cap._BCQ = 0; | ||
625 | } else { | 633 | } else { |
626 | /* Fixme: | 634 | /* Fixme: |
627 | * should we return an error or ignore this failure? | 635 | * should we return an error or ignore this failure? |
@@ -872,7 +880,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
872 | br->flags._BCM_use_index = br->flags._BCL_use_index; | 880 | br->flags._BCM_use_index = br->flags._BCL_use_index; |
873 | 881 | ||
874 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ | 882 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ |
875 | br->curr = level_old = max_level; | 883 | br->curr = level = max_level; |
876 | 884 | ||
877 | if (!device->cap._BQC) | 885 | if (!device->cap._BQC) |
878 | goto set_level; | 886 | goto set_level; |
@@ -894,15 +902,25 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
894 | 902 | ||
895 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); | 903 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); |
896 | 904 | ||
897 | if (!br->flags._BQC_use_index) | 905 | if (!br->flags._BQC_use_index) { |
906 | /* | ||
907 | * Set the backlight to the initial state. | ||
908 | * On some buggy laptops, _BQC returns an uninitialized value | ||
909 | * when invoked for the first time, i.e. level_old is invalid. | ||
910 | * set the backlight to max_level in this case | ||
911 | */ | ||
912 | for (i = 2; i < br->count; i++) | ||
913 | if (level_old == br->levels[i]) | ||
914 | level = level_old; | ||
898 | goto set_level; | 915 | goto set_level; |
916 | } | ||
899 | 917 | ||
900 | if (br->flags._BCL_reversed) | 918 | if (br->flags._BCL_reversed) |
901 | level_old = (br->count - 1) - level_old; | 919 | level_old = (br->count - 1) - level_old; |
902 | level_old = br->levels[level_old]; | 920 | level = br->levels[level_old]; |
903 | 921 | ||
904 | set_level: | 922 | set_level: |
905 | result = acpi_video_device_lcd_set_level(device, level_old); | 923 | result = acpi_video_device_lcd_set_level(device, level); |
906 | if (result) | 924 | if (result) |
907 | goto out_free_levels; | 925 | goto out_free_levels; |
908 | 926 | ||
@@ -936,9 +954,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
936 | { | 954 | { |
937 | acpi_handle h_dummy1; | 955 | acpi_handle h_dummy1; |
938 | 956 | ||
939 | |||
940 | memset(&device->cap, 0, sizeof(device->cap)); | ||
941 | |||
942 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { | 957 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { |
943 | device->cap._ADR = 1; | 958 | device->cap._ADR = 1; |
944 | } | 959 | } |
@@ -992,19 +1007,29 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
992 | if (result) | 1007 | if (result) |
993 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1008 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
994 | 1009 | ||
995 | device->cdev = thermal_cooling_device_register("LCD", | 1010 | device->cooling_dev = thermal_cooling_device_register("LCD", |
996 | device->dev, &video_cooling_ops); | 1011 | device->dev, &video_cooling_ops); |
997 | if (IS_ERR(device->cdev)) | 1012 | if (IS_ERR(device->cooling_dev)) { |
1013 | /* | ||
1014 | * Set cooling_dev to NULL so we don't crash trying to | ||
1015 | * free it. | ||
1016 | * Also, why the hell we are returning early and | ||
1017 | * not attempt to register video output if cooling | ||
1018 | * device registration failed? | ||
1019 | * -- dtor | ||
1020 | */ | ||
1021 | device->cooling_dev = NULL; | ||
998 | return; | 1022 | return; |
1023 | } | ||
999 | 1024 | ||
1000 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", | 1025 | dev_info(&device->dev->dev, "registered as cooling_device%d\n", |
1001 | device->cdev->id); | 1026 | device->cooling_dev->id); |
1002 | result = sysfs_create_link(&device->dev->dev.kobj, | 1027 | result = sysfs_create_link(&device->dev->dev.kobj, |
1003 | &device->cdev->device.kobj, | 1028 | &device->cooling_dev->device.kobj, |
1004 | "thermal_cooling"); | 1029 | "thermal_cooling"); |
1005 | if (result) | 1030 | if (result) |
1006 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1031 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
1007 | result = sysfs_create_link(&device->cdev->device.kobj, | 1032 | result = sysfs_create_link(&device->cooling_dev->device.kobj, |
1008 | &device->dev->dev.kobj, "device"); | 1033 | &device->dev->dev.kobj, "device"); |
1009 | if (result) | 1034 | if (result) |
1010 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 1035 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
@@ -1041,7 +1066,6 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) | |||
1041 | { | 1066 | { |
1042 | acpi_handle h_dummy1; | 1067 | acpi_handle h_dummy1; |
1043 | 1068 | ||
1044 | memset(&video->cap, 0, sizeof(video->cap)); | ||
1045 | if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { | 1069 | if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { |
1046 | video->cap._DOS = 1; | 1070 | video->cap._DOS = 1; |
1047 | } | 1071 | } |
@@ -2011,13 +2035,13 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
2011 | backlight_device_unregister(device->backlight); | 2035 | backlight_device_unregister(device->backlight); |
2012 | device->backlight = NULL; | 2036 | device->backlight = NULL; |
2013 | } | 2037 | } |
2014 | if (device->cdev) { | 2038 | if (device->cooling_dev) { |
2015 | sysfs_remove_link(&device->dev->dev.kobj, | 2039 | sysfs_remove_link(&device->dev->dev.kobj, |
2016 | "thermal_cooling"); | 2040 | "thermal_cooling"); |
2017 | sysfs_remove_link(&device->cdev->device.kobj, | 2041 | sysfs_remove_link(&device->cooling_dev->device.kobj, |
2018 | "device"); | 2042 | "device"); |
2019 | thermal_cooling_device_unregister(device->cdev); | 2043 | thermal_cooling_device_unregister(device->cooling_dev); |
2020 | device->cdev = NULL; | 2044 | device->cooling_dev = NULL; |
2021 | } | 2045 | } |
2022 | video_output_unregister(device->output_dev); | 2046 | video_output_unregister(device->output_dev); |
2023 | 2047 | ||