aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2009-03-18 04:27:16 -0400
committerLen Brown <len.brown@intel.com>2009-03-27 21:56:45 -0400
commit1a7c618a3f7bef1a20ae740df512eeba21397fa5 (patch)
tree51626f0f394e01bdb662d9466db68386c731b06f /drivers
parentd80fb99fdcd56f4934f11cc44ca016463842dc8b (diff)
ACPI video: support _BQC/_BCL/_BCM methods that use index values
The input/output of _BQC/_BCL/_BCM control methods should be represented by a number between 0 and 100, and can be thought of as a percentage. But some buggy _BQC/_BCL/_BCM methods use the index values instead. http://bugzilla.kernel.org/show_bug.cgi?id=12302 http://bugzilla.kernel.org/show_bug.cgi?id=12249 http://bugzilla.kernel.org/show_bug.cgi?id=12037 Add the functionality to support such kind of BIOSes in ACPI video driver. Signed-off-by: Zhang Rui <rui.zhang@intel.com> Acked-by: Matthew Garrett <mjg59@srcf.ucam.org> Acked-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/video.c91
1 files changed, 70 insertions, 21 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index dc84970ce1e9..1f1625c51003 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -171,6 +171,9 @@ struct acpi_video_device_cap {
171struct acpi_video_brightness_flags { 171struct acpi_video_brightness_flags {
172 u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */ 172 u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */
173 u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/ 173 u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/
174 u8 _BCL_use_index:1; /* levels in _BCL are index values */
175 u8 _BCM_use_index:1; /* input of _BCM is an index value */
176 u8 _BQC_use_index:1; /* _BQC returns an index value */
174}; 177};
175 178
176struct acpi_video_device_brightness { 179struct acpi_video_device_brightness {
@@ -505,7 +508,8 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
505 device->brightness->curr = level; 508 device->brightness->curr = level;
506 for (state = 2; state < device->brightness->count; state++) 509 for (state = 2; state < device->brightness->count; state++)
507 if (level == device->brightness->levels[state]) { 510 if (level == device->brightness->levels[state]) {
508 device->backlight->props.brightness = state - 2; 511 if (device->backlight)
512 device->backlight->props.brightness = state - 2;
509 return 0; 513 return 0;
510 } 514 }
511 515
@@ -523,6 +527,13 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
523 status = acpi_evaluate_integer(device->dev->handle, "_BQC", 527 status = acpi_evaluate_integer(device->dev->handle, "_BQC",
524 NULL, level); 528 NULL, level);
525 if (ACPI_SUCCESS(status)) { 529 if (ACPI_SUCCESS(status)) {
530 if (device->brightness->flags._BQC_use_index) {
531 if (device->brightness->flags._BCL_reversed)
532 *level = device->brightness->count
533 - 3 - (*level);
534 *level = device->brightness->levels[*level + 2];
535
536 }
526 device->brightness->curr = *level; 537 device->brightness->curr = *level;
527 return 0; 538 return 0;
528 } else { 539 } else {
@@ -689,8 +700,10 @@ acpi_video_init_brightness(struct acpi_video_device *device)
689{ 700{
690 union acpi_object *obj = NULL; 701 union acpi_object *obj = NULL;
691 int i, max_level = 0, count = 0, level_ac_battery = 0; 702 int i, max_level = 0, count = 0, level_ac_battery = 0;
703 unsigned long long level, level_old;
692 union acpi_object *o; 704 union acpi_object *o;
693 struct acpi_video_device_brightness *br = NULL; 705 struct acpi_video_device_brightness *br = NULL;
706 int result = -EINVAL;
694 707
695 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { 708 if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
696 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " 709 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
@@ -704,13 +717,16 @@ acpi_video_init_brightness(struct acpi_video_device *device)
704 br = kzalloc(sizeof(*br), GFP_KERNEL); 717 br = kzalloc(sizeof(*br), GFP_KERNEL);
705 if (!br) { 718 if (!br) {
706 printk(KERN_ERR "can't allocate memory\n"); 719 printk(KERN_ERR "can't allocate memory\n");
720 result = -ENOMEM;
707 goto out; 721 goto out;
708 } 722 }
709 723
710 br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels), 724 br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels),
711 GFP_KERNEL); 725 GFP_KERNEL);
712 if (!br->levels) 726 if (!br->levels) {
727 result = -ENOMEM;
713 goto out_free; 728 goto out_free;
729 }
714 730
715 for (i = 0; i < obj->package.count; i++) { 731 for (i = 0; i < obj->package.count; i++) {
716 o = (union acpi_object *)&obj->package.elements[i]; 732 o = (union acpi_object *)&obj->package.elements[i];
@@ -756,10 +772,55 @@ acpi_video_init_brightness(struct acpi_video_device *device)
756 772
757 br->count = count; 773 br->count = count;
758 device->brightness = br; 774 device->brightness = br;
775
776 /* Check the input/output of _BQC/_BCL/_BCM */
777 if ((max_level < 100) && (max_level <= (count - 2)))
778 br->flags._BCL_use_index = 1;
779
780 /*
781 * _BCM is always consistent with _BCL,
782 * at least for all the laptops we have ever seen.
783 */
784 br->flags._BCM_use_index = br->flags._BCL_use_index;
785
786 /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
787 br->curr = max_level;
788 result = acpi_video_device_lcd_get_level_current(device, &level_old);
789 if (result)
790 goto out_free_levels;
791
792 result = acpi_video_device_lcd_set_level(device, br->curr);
793 if (result)
794 goto out_free_levels;
795
796 result = acpi_video_device_lcd_get_level_current(device, &level);
797 if (result)
798 goto out_free_levels;
799
800 if ((level != level_old) && !br->flags._BCM_use_index) {
801 /* Note:
802 * This piece of code does not work correctly if the current
803 * brightness levels is 0.
804 * But I guess boxes that boot with such a dark screen are rare
805 * and no more code is needed to cover this specifial case.
806 */
807
808 if (level_ac_battery != 2) {
809 /*
810 * For now, we don't support the _BCL like this:
811 * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16
812 * because we may mess up the index returned by _BQC.
813 * Plus: we have not got a box like this.
814 */
815 ACPI_ERROR((AE_INFO, "_BCL not supported\n"));
816 }
817 br->flags._BQC_use_index = 1;
818 }
819
759 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 820 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
760 "found %d brightness levels\n", count - 2)); 821 "found %d brightness levels\n", count - 2));
761 kfree(obj); 822 kfree(obj);
762 return max_level; 823 return result;
763 824
764out_free_levels: 825out_free_levels:
765 kfree(br->levels); 826 kfree(br->levels);
@@ -768,7 +829,7 @@ out_free:
768out: 829out:
769 device->brightness = NULL; 830 device->brightness = NULL;
770 kfree(obj); 831 kfree(obj);
771 return 0; 832 return result;
772} 833}
773 834
774/* 835/*
@@ -785,7 +846,6 @@ out:
785static void acpi_video_device_find_cap(struct acpi_video_device *device) 846static void acpi_video_device_find_cap(struct acpi_video_device *device)
786{ 847{
787 acpi_handle h_dummy1; 848 acpi_handle h_dummy1;
788 u32 max_level = 0;
789 849
790 850
791 memset(&device->cap, 0, sizeof(device->cap)); 851 memset(&device->cap, 0, sizeof(device->cap));
@@ -814,13 +874,14 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
814 device->cap._DSS = 1; 874 device->cap._DSS = 1;
815 } 875 }
816 876
817 if (acpi_video_backlight_support()) 877 if (acpi_video_backlight_support()) {
818 max_level = acpi_video_init_brightness(device);
819
820 if (device->cap._BCL && device->cap._BCM && max_level > 0) {
821 int result; 878 int result;
822 static int count = 0; 879 static int count = 0;
823 char *name; 880 char *name;
881
882 result = acpi_video_init_brightness(device);
883 if (result)
884 return;
824 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 885 name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
825 if (!name) 886 if (!name)
826 return; 887 return;
@@ -829,18 +890,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
829 device->backlight = backlight_device_register(name, 890 device->backlight = backlight_device_register(name,
830 NULL, device, &acpi_backlight_ops); 891 NULL, device, &acpi_backlight_ops);
831 device->backlight->props.max_brightness = device->brightness->count-3; 892 device->backlight->props.max_brightness = device->brightness->count-3;
832 /*
833 * If there exists the _BQC object, the _BQC object will be
834 * called to get the current backlight brightness. Otherwise
835 * the brightness will be set to the maximum.
836 */
837 if (device->cap._BQC)
838 device->backlight->props.brightness =
839 acpi_video_get_brightness(device->backlight);
840 else
841 device->backlight->props.brightness =
842 device->backlight->props.max_brightness;
843 backlight_update_status(device->backlight);
844 kfree(name); 893 kfree(name);
845 894
846 device->cdev = thermal_cooling_device_register("LCD", 895 device->cdev = thermal_cooling_device_register("LCD",