diff options
author | Len Brown <len.brown@intel.com> | 2009-04-05 01:40:06 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-04-05 01:40:06 -0400 |
commit | 12648810506eaa063dc23b66514fbb4796f34312 (patch) | |
tree | 4cd16290c9e1350d946a92ca8d5624cdd683b739 /drivers/acpi | |
parent | 7329e9356e5b46e11a1781dff2dc64c2e3284884 (diff) | |
parent | 03ae61dd5701092aabb60a8cae9929dbf8dc25c6 (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')
-rw-r--r-- | drivers/acpi/video.c | 279 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 3 |
2 files changed, 225 insertions, 57 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5259d502add6..100c8eeaa5dd 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -37,6 +37,8 @@ | |||
37 | #include <linux/thermal.h> | 37 | #include <linux/thermal.h> |
38 | #include <linux/video_output.h> | 38 | #include <linux/video_output.h> |
39 | #include <linux/sort.h> | 39 | #include <linux/sort.h> |
40 | #include <linux/pci.h> | ||
41 | #include <linux/pci_ids.h> | ||
40 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
41 | 43 | ||
42 | #include <acpi/acpi_bus.h> | 44 | #include <acpi/acpi_bus.h> |
@@ -162,16 +164,26 @@ struct acpi_video_device_cap { | |||
162 | u8 _BCL:1; /*Query list of brightness control levels supported */ | 164 | u8 _BCL:1; /*Query list of brightness control levels supported */ |
163 | u8 _BCM:1; /*Set the brightness level */ | 165 | u8 _BCM:1; /*Set the brightness level */ |
164 | u8 _BQC:1; /* Get current brightness level */ | 166 | u8 _BQC:1; /* Get current brightness level */ |
167 | u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */ | ||
165 | u8 _DDC:1; /*Return the EDID for this device */ | 168 | u8 _DDC:1; /*Return the EDID for this device */ |
166 | u8 _DCS:1; /*Return status of output device */ | 169 | u8 _DCS:1; /*Return status of output device */ |
167 | u8 _DGS:1; /*Query graphics state */ | 170 | u8 _DGS:1; /*Query graphics state */ |
168 | u8 _DSS:1; /*Device state set */ | 171 | u8 _DSS:1; /*Device state set */ |
169 | }; | 172 | }; |
170 | 173 | ||
174 | struct acpi_video_brightness_flags { | ||
175 | u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */ | ||
176 | u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/ | ||
177 | u8 _BCL_use_index:1; /* levels in _BCL are index values */ | ||
178 | u8 _BCM_use_index:1; /* input of _BCM is an index value */ | ||
179 | u8 _BQC_use_index:1; /* _BQC returns an index value */ | ||
180 | }; | ||
181 | |||
171 | struct acpi_video_device_brightness { | 182 | struct acpi_video_device_brightness { |
172 | int curr; | 183 | int curr; |
173 | int count; | 184 | int count; |
174 | int *levels; | 185 | int *levels; |
186 | struct acpi_video_brightness_flags flags; | ||
175 | }; | 187 | }; |
176 | 188 | ||
177 | struct acpi_video_device { | 189 | struct acpi_video_device { |
@@ -294,7 +306,7 @@ static int acpi_video_device_lcd_get_level_current( | |||
294 | unsigned long long *level); | 306 | unsigned long long *level); |
295 | static int acpi_video_get_next_level(struct acpi_video_device *device, | 307 | static int acpi_video_get_next_level(struct acpi_video_device *device, |
296 | u32 level_current, u32 event); | 308 | u32 level_current, u32 event); |
297 | static void acpi_video_switch_brightness(struct acpi_video_device *device, | 309 | static int acpi_video_switch_brightness(struct acpi_video_device *device, |
298 | int event); | 310 | int event); |
299 | static int acpi_video_device_get_state(struct acpi_video_device *device, | 311 | static int acpi_video_device_get_state(struct acpi_video_device *device, |
300 | unsigned long long *state); | 312 | unsigned long long *state); |
@@ -308,7 +320,9 @@ static int acpi_video_get_brightness(struct backlight_device *bd) | |||
308 | int i; | 320 | int i; |
309 | struct acpi_video_device *vd = | 321 | struct acpi_video_device *vd = |
310 | (struct acpi_video_device *)bl_get_data(bd); | 322 | (struct acpi_video_device *)bl_get_data(bd); |
311 | acpi_video_device_lcd_get_level_current(vd, &cur_level); | 323 | |
324 | if (acpi_video_device_lcd_get_level_current(vd, &cur_level)) | ||
325 | return -EINVAL; | ||
312 | for (i = 2; i < vd->brightness->count; i++) { | 326 | for (i = 2; i < vd->brightness->count; i++) { |
313 | if (vd->brightness->levels[i] == cur_level) | 327 | if (vd->brightness->levels[i] == cur_level) |
314 | /* The first two entries are special - see page 575 | 328 | /* The first two entries are special - see page 575 |
@@ -320,12 +334,12 @@ static int acpi_video_get_brightness(struct backlight_device *bd) | |||
320 | 334 | ||
321 | static int acpi_video_set_brightness(struct backlight_device *bd) | 335 | static int acpi_video_set_brightness(struct backlight_device *bd) |
322 | { | 336 | { |
323 | int request_level = bd->props.brightness+2; | 337 | int request_level = bd->props.brightness + 2; |
324 | struct acpi_video_device *vd = | 338 | struct acpi_video_device *vd = |
325 | (struct acpi_video_device *)bl_get_data(bd); | 339 | (struct acpi_video_device *)bl_get_data(bd); |
326 | acpi_video_device_lcd_set_level(vd, | 340 | |
327 | vd->brightness->levels[request_level]); | 341 | return acpi_video_device_lcd_set_level(vd, |
328 | return 0; | 342 | vd->brightness->levels[request_level]); |
329 | } | 343 | } |
330 | 344 | ||
331 | static struct backlight_ops acpi_backlight_ops = { | 345 | static struct backlight_ops acpi_backlight_ops = { |
@@ -376,7 +390,8 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned | |||
376 | unsigned long long level; | 390 | unsigned long long level; |
377 | int offset; | 391 | int offset; |
378 | 392 | ||
379 | acpi_video_device_lcd_get_level_current(video, &level); | 393 | if (acpi_video_device_lcd_get_level_current(video, &level)) |
394 | return -EINVAL; | ||
380 | for (offset = 2; offset < video->brightness->count; offset++) | 395 | for (offset = 2; offset < video->brightness->count; offset++) |
381 | if (level == video->brightness->levels[offset]) { | 396 | if (level == video->brightness->levels[offset]) { |
382 | *state = video->brightness->count - offset - 1; | 397 | *state = video->brightness->count - offset - 1; |
@@ -483,34 +498,68 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device, | |||
483 | static int | 498 | static int |
484 | acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) | 499 | acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) |
485 | { | 500 | { |
486 | int status = AE_OK; | 501 | int status; |
487 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 502 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
488 | struct acpi_object_list args = { 1, &arg0 }; | 503 | struct acpi_object_list args = { 1, &arg0 }; |
489 | int state; | 504 | int state; |
490 | 505 | ||
491 | |||
492 | arg0.integer.value = level; | 506 | arg0.integer.value = level; |
493 | 507 | ||
494 | if (device->cap._BCM) | 508 | status = acpi_evaluate_object(device->dev->handle, "_BCM", |
495 | status = acpi_evaluate_object(device->dev->handle, "_BCM", | 509 | &args, NULL); |
496 | &args, NULL); | 510 | if (ACPI_FAILURE(status)) { |
511 | ACPI_ERROR((AE_INFO, "Evaluating _BCM failed")); | ||
512 | return -EIO; | ||
513 | } | ||
514 | |||
497 | device->brightness->curr = level; | 515 | device->brightness->curr = level; |
498 | for (state = 2; state < device->brightness->count; state++) | 516 | for (state = 2; state < device->brightness->count; state++) |
499 | if (level == device->brightness->levels[state]) | 517 | if (level == device->brightness->levels[state]) { |
500 | device->backlight->props.brightness = state - 2; | 518 | if (device->backlight) |
519 | device->backlight->props.brightness = state - 2; | ||
520 | return 0; | ||
521 | } | ||
501 | 522 | ||
502 | return status; | 523 | ACPI_ERROR((AE_INFO, "Current brightness invalid")); |
524 | return -EINVAL; | ||
503 | } | 525 | } |
504 | 526 | ||
505 | static int | 527 | static int |
506 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | 528 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, |
507 | unsigned long long *level) | 529 | unsigned long long *level) |
508 | { | 530 | { |
509 | if (device->cap._BQC) | 531 | acpi_status status = AE_OK; |
510 | return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, | 532 | |
511 | level); | 533 | if (device->cap._BQC || device->cap._BCQ) { |
534 | char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; | ||
535 | |||
536 | status = acpi_evaluate_integer(device->dev->handle, buf, | ||
537 | NULL, level); | ||
538 | if (ACPI_SUCCESS(status)) { | ||
539 | if (device->brightness->flags._BQC_use_index) { | ||
540 | if (device->brightness->flags._BCL_reversed) | ||
541 | *level = device->brightness->count | ||
542 | - 3 - (*level); | ||
543 | *level = device->brightness->levels[*level + 2]; | ||
544 | |||
545 | } | ||
546 | device->brightness->curr = *level; | ||
547 | return 0; | ||
548 | } else { | ||
549 | /* Fixme: | ||
550 | * should we return an error or ignore this failure? | ||
551 | * dev->brightness->curr is a cached value which stores | ||
552 | * the correct current backlight level in most cases. | ||
553 | * ACPI video backlight still works w/ buggy _BQC. | ||
554 | * http://bugzilla.kernel.org/show_bug.cgi?id=12233 | ||
555 | */ | ||
556 | ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf)); | ||
557 | device->cap._BQC = device->cap._BCQ = 0; | ||
558 | } | ||
559 | } | ||
560 | |||
512 | *level = device->brightness->curr; | 561 | *level = device->brightness->curr; |
513 | return AE_OK; | 562 | return 0; |
514 | } | 563 | } |
515 | 564 | ||
516 | static int | 565 | static int |
@@ -659,9 +708,11 @@ static int | |||
659 | acpi_video_init_brightness(struct acpi_video_device *device) | 708 | acpi_video_init_brightness(struct acpi_video_device *device) |
660 | { | 709 | { |
661 | union acpi_object *obj = NULL; | 710 | union acpi_object *obj = NULL; |
662 | int i, max_level = 0, count = 0; | 711 | int i, max_level = 0, count = 0, level_ac_battery = 0; |
712 | unsigned long long level, level_old; | ||
663 | union acpi_object *o; | 713 | union acpi_object *o; |
664 | struct acpi_video_device_brightness *br = NULL; | 714 | struct acpi_video_device_brightness *br = NULL; |
715 | int result = -EINVAL; | ||
665 | 716 | ||
666 | if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { | 717 | if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { |
667 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " | 718 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " |
@@ -675,13 +726,16 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
675 | br = kzalloc(sizeof(*br), GFP_KERNEL); | 726 | br = kzalloc(sizeof(*br), GFP_KERNEL); |
676 | if (!br) { | 727 | if (!br) { |
677 | printk(KERN_ERR "can't allocate memory\n"); | 728 | printk(KERN_ERR "can't allocate memory\n"); |
729 | result = -ENOMEM; | ||
678 | goto out; | 730 | goto out; |
679 | } | 731 | } |
680 | 732 | ||
681 | br->levels = kmalloc(obj->package.count * sizeof *(br->levels), | 733 | br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels), |
682 | GFP_KERNEL); | 734 | GFP_KERNEL); |
683 | if (!br->levels) | 735 | if (!br->levels) { |
736 | result = -ENOMEM; | ||
684 | goto out_free; | 737 | goto out_free; |
738 | } | ||
685 | 739 | ||
686 | for (i = 0; i < obj->package.count; i++) { | 740 | for (i = 0; i < obj->package.count; i++) { |
687 | o = (union acpi_object *)&obj->package.elements[i]; | 741 | o = (union acpi_object *)&obj->package.elements[i]; |
@@ -696,18 +750,86 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
696 | count++; | 750 | count++; |
697 | } | 751 | } |
698 | 752 | ||
699 | /* don't sort the first two brightness levels */ | 753 | /* |
700 | sort(&br->levels[2], count - 2, sizeof(br->levels[2]), | 754 | * some buggy BIOS don't export the levels |
701 | acpi_video_cmp_level, NULL); | 755 | * when machine is on AC/Battery in _BCL package. |
702 | 756 | * In this case, the first two elements in _BCL packages | |
703 | if (count < 2) | 757 | * are also supported brightness levels that OS should take care of. |
704 | goto out_free_levels; | 758 | */ |
759 | for (i = 2; i < count; i++) | ||
760 | if (br->levels[i] == br->levels[0] || | ||
761 | br->levels[i] == br->levels[1]) | ||
762 | level_ac_battery++; | ||
763 | |||
764 | if (level_ac_battery < 2) { | ||
765 | level_ac_battery = 2 - level_ac_battery; | ||
766 | br->flags._BCL_no_ac_battery_levels = 1; | ||
767 | for (i = (count - 1 + level_ac_battery); i >= 2; i--) | ||
768 | br->levels[i] = br->levels[i - level_ac_battery]; | ||
769 | count += level_ac_battery; | ||
770 | } else if (level_ac_battery > 2) | ||
771 | ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n")); | ||
772 | |||
773 | /* Check if the _BCL package is in a reversed order */ | ||
774 | if (max_level == br->levels[2]) { | ||
775 | br->flags._BCL_reversed = 1; | ||
776 | sort(&br->levels[2], count - 2, sizeof(br->levels[2]), | ||
777 | acpi_video_cmp_level, NULL); | ||
778 | } else if (max_level != br->levels[count - 1]) | ||
779 | ACPI_ERROR((AE_INFO, | ||
780 | "Found unordered _BCL package\n")); | ||
705 | 781 | ||
706 | br->count = count; | 782 | br->count = count; |
707 | device->brightness = br; | 783 | device->brightness = br; |
708 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); | 784 | |
785 | /* Check the input/output of _BQC/_BCL/_BCM */ | ||
786 | if ((max_level < 100) && (max_level <= (count - 2))) | ||
787 | br->flags._BCL_use_index = 1; | ||
788 | |||
789 | /* | ||
790 | * _BCM is always consistent with _BCL, | ||
791 | * at least for all the laptops we have ever seen. | ||
792 | */ | ||
793 | br->flags._BCM_use_index = br->flags._BCL_use_index; | ||
794 | |||
795 | /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ | ||
796 | br->curr = max_level; | ||
797 | result = acpi_video_device_lcd_get_level_current(device, &level_old); | ||
798 | if (result) | ||
799 | goto out_free_levels; | ||
800 | |||
801 | result = acpi_video_device_lcd_set_level(device, br->curr); | ||
802 | if (result) | ||
803 | goto out_free_levels; | ||
804 | |||
805 | result = acpi_video_device_lcd_get_level_current(device, &level); | ||
806 | if (result) | ||
807 | goto out_free_levels; | ||
808 | |||
809 | if ((level != level_old) && !br->flags._BCM_use_index) { | ||
810 | /* Note: | ||
811 | * This piece of code does not work correctly if the current | ||
812 | * brightness levels is 0. | ||
813 | * But I guess boxes that boot with such a dark screen are rare | ||
814 | * and no more code is needed to cover this specifial case. | ||
815 | */ | ||
816 | |||
817 | if (level_ac_battery != 2) { | ||
818 | /* | ||
819 | * For now, we don't support the _BCL like this: | ||
820 | * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16 | ||
821 | * because we may mess up the index returned by _BQC. | ||
822 | * Plus: we have not got a box like this. | ||
823 | */ | ||
824 | ACPI_ERROR((AE_INFO, "_BCL not supported\n")); | ||
825 | } | ||
826 | br->flags._BQC_use_index = 1; | ||
827 | } | ||
828 | |||
829 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
830 | "found %d brightness levels\n", count - 2)); | ||
709 | kfree(obj); | 831 | kfree(obj); |
710 | return max_level; | 832 | return result; |
711 | 833 | ||
712 | out_free_levels: | 834 | out_free_levels: |
713 | kfree(br->levels); | 835 | kfree(br->levels); |
@@ -716,7 +838,7 @@ out_free: | |||
716 | out: | 838 | out: |
717 | device->brightness = NULL; | 839 | device->brightness = NULL; |
718 | kfree(obj); | 840 | kfree(obj); |
719 | return 0; | 841 | return result; |
720 | } | 842 | } |
721 | 843 | ||
722 | /* | 844 | /* |
@@ -733,7 +855,6 @@ out: | |||
733 | static void acpi_video_device_find_cap(struct acpi_video_device *device) | 855 | static void acpi_video_device_find_cap(struct acpi_video_device *device) |
734 | { | 856 | { |
735 | acpi_handle h_dummy1; | 857 | acpi_handle h_dummy1; |
736 | u32 max_level = 0; | ||
737 | 858 | ||
738 | 859 | ||
739 | memset(&device->cap, 0, sizeof(device->cap)); | 860 | memset(&device->cap, 0, sizeof(device->cap)); |
@@ -749,6 +870,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
749 | } | 870 | } |
750 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) | 871 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) |
751 | device->cap._BQC = 1; | 872 | device->cap._BQC = 1; |
873 | else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ", | ||
874 | &h_dummy1))) { | ||
875 | printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n"); | ||
876 | device->cap._BCQ = 1; | ||
877 | } | ||
878 | |||
752 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { | 879 | if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { |
753 | device->cap._DDC = 1; | 880 | device->cap._DDC = 1; |
754 | } | 881 | } |
@@ -762,13 +889,14 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
762 | device->cap._DSS = 1; | 889 | device->cap._DSS = 1; |
763 | } | 890 | } |
764 | 891 | ||
765 | if (acpi_video_backlight_support()) | 892 | if (acpi_video_backlight_support()) { |
766 | max_level = acpi_video_init_brightness(device); | ||
767 | |||
768 | if (device->cap._BCL && device->cap._BCM && max_level > 0) { | ||
769 | int result; | 893 | int result; |
770 | static int count = 0; | 894 | static int count = 0; |
771 | char *name; | 895 | char *name; |
896 | |||
897 | result = acpi_video_init_brightness(device); | ||
898 | if (result) | ||
899 | return; | ||
772 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 900 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); |
773 | if (!name) | 901 | if (!name) |
774 | return; | 902 | return; |
@@ -777,18 +905,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
777 | device->backlight = backlight_device_register(name, | 905 | device->backlight = backlight_device_register(name, |
778 | NULL, device, &acpi_backlight_ops); | 906 | NULL, device, &acpi_backlight_ops); |
779 | device->backlight->props.max_brightness = device->brightness->count-3; | 907 | device->backlight->props.max_brightness = device->brightness->count-3; |
780 | /* | ||
781 | * If there exists the _BQC object, the _BQC object will be | ||
782 | * called to get the current backlight brightness. Otherwise | ||
783 | * the brightness will be set to the maximum. | ||
784 | */ | ||
785 | if (device->cap._BQC) | ||
786 | device->backlight->props.brightness = | ||
787 | acpi_video_get_brightness(device->backlight); | ||
788 | else | ||
789 | device->backlight->props.brightness = | ||
790 | device->backlight->props.max_brightness; | ||
791 | backlight_update_status(device->backlight); | ||
792 | kfree(name); | 908 | kfree(name); |
793 | 909 | ||
794 | device->cdev = thermal_cooling_device_register("LCD", | 910 | device->cdev = thermal_cooling_device_register("LCD", |
@@ -1065,13 +1181,12 @@ acpi_video_device_write_brightness(struct file *file, | |||
1065 | /* validate through the list of available levels */ | 1181 | /* validate through the list of available levels */ |
1066 | for (i = 2; i < dev->brightness->count; i++) | 1182 | for (i = 2; i < dev->brightness->count; i++) |
1067 | if (level == dev->brightness->levels[i]) { | 1183 | if (level == dev->brightness->levels[i]) { |
1068 | if (ACPI_SUCCESS | 1184 | if (!acpi_video_device_lcd_set_level(dev, level)) |
1069 | (acpi_video_device_lcd_set_level(dev, level))) | 1185 | return count; |
1070 | dev->brightness->curr = level; | ||
1071 | break; | 1186 | break; |
1072 | } | 1187 | } |
1073 | 1188 | ||
1074 | return count; | 1189 | return -EINVAL; |
1075 | } | 1190 | } |
1076 | 1191 | ||
1077 | static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) | 1192 | static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) |
@@ -1753,15 +1868,29 @@ acpi_video_get_next_level(struct acpi_video_device *device, | |||
1753 | } | 1868 | } |
1754 | } | 1869 | } |
1755 | 1870 | ||
1756 | static void | 1871 | static int |
1757 | acpi_video_switch_brightness(struct acpi_video_device *device, int event) | 1872 | acpi_video_switch_brightness(struct acpi_video_device *device, int event) |
1758 | { | 1873 | { |
1759 | unsigned long long level_current, level_next; | 1874 | unsigned long long level_current, level_next; |
1875 | int result = -EINVAL; | ||
1876 | |||
1760 | if (!device->brightness) | 1877 | if (!device->brightness) |
1761 | return; | 1878 | goto out; |
1762 | acpi_video_device_lcd_get_level_current(device, &level_current); | 1879 | |
1880 | result = acpi_video_device_lcd_get_level_current(device, | ||
1881 | &level_current); | ||
1882 | if (result) | ||
1883 | goto out; | ||
1884 | |||
1763 | level_next = acpi_video_get_next_level(device, level_current, event); | 1885 | level_next = acpi_video_get_next_level(device, level_current, event); |
1764 | acpi_video_device_lcd_set_level(device, level_next); | 1886 | |
1887 | result = acpi_video_device_lcd_set_level(device, level_next); | ||
1888 | |||
1889 | out: | ||
1890 | if (result) | ||
1891 | printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); | ||
1892 | |||
1893 | return result; | ||
1765 | } | 1894 | } |
1766 | 1895 | ||
1767 | static int | 1896 | static int |
@@ -2128,7 +2257,27 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) | |||
2128 | return 0; | 2257 | return 0; |
2129 | } | 2258 | } |
2130 | 2259 | ||
2131 | static int __init acpi_video_init(void) | 2260 | static int __init intel_opregion_present(void) |
2261 | { | ||
2262 | #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) | ||
2263 | struct pci_dev *dev = NULL; | ||
2264 | u32 address; | ||
2265 | |||
2266 | for_each_pci_dev(dev) { | ||
2267 | if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | ||
2268 | continue; | ||
2269 | if (dev->vendor != PCI_VENDOR_ID_INTEL) | ||
2270 | continue; | ||
2271 | pci_read_config_dword(dev, 0xfc, &address); | ||
2272 | if (!address) | ||
2273 | continue; | ||
2274 | return 1; | ||
2275 | } | ||
2276 | #endif | ||
2277 | return 0; | ||
2278 | } | ||
2279 | |||
2280 | int acpi_video_register(void) | ||
2132 | { | 2281 | { |
2133 | int result = 0; | 2282 | int result = 0; |
2134 | 2283 | ||
@@ -2145,6 +2294,22 @@ static int __init acpi_video_init(void) | |||
2145 | 2294 | ||
2146 | return 0; | 2295 | return 0; |
2147 | } | 2296 | } |
2297 | EXPORT_SYMBOL(acpi_video_register); | ||
2298 | |||
2299 | /* | ||
2300 | * This is kind of nasty. Hardware using Intel chipsets may require | ||
2301 | * the video opregion code to be run first in order to initialise | ||
2302 | * state before any ACPI video calls are made. To handle this we defer | ||
2303 | * registration of the video class until the opregion code has run. | ||
2304 | */ | ||
2305 | |||
2306 | static int __init acpi_video_init(void) | ||
2307 | { | ||
2308 | if (intel_opregion_present()) | ||
2309 | return 0; | ||
2310 | |||
2311 | return acpi_video_register(); | ||
2312 | } | ||
2148 | 2313 | ||
2149 | static void __exit acpi_video_exit(void) | 2314 | static void __exit acpi_video_exit(void) |
2150 | { | 2315 | { |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 50e3d2dbf3af..09737275e25f 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -55,6 +55,9 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, | |||
55 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " | 55 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " |
56 | "support\n")); | 56 | "support\n")); |
57 | *cap |= ACPI_VIDEO_BACKLIGHT; | 57 | *cap |= ACPI_VIDEO_BACKLIGHT; |
58 | if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy))) | ||
59 | printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness " | ||
60 | "control misses _BQC function\n"); | ||
58 | /* We have backlight support, no need to scan further */ | 61 | /* We have backlight support, no need to scan further */ |
59 | return AE_CTRL_TERMINATE; | 62 | return AE_CTRL_TERMINATE; |
60 | } | 63 | } |