diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/video.c | 123 |
1 files changed, 73 insertions, 50 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index d089c4519d45..64c889331f3b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -631,6 +631,76 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) | |||
631 | * device : video output device (LCD, CRT, ..) | 631 | * device : video output device (LCD, CRT, ..) |
632 | * | 632 | * |
633 | * Return Value: | 633 | * Return Value: |
634 | * Maximum brightness level | ||
635 | * | ||
636 | * Allocate and initialize device->brightness. | ||
637 | */ | ||
638 | |||
639 | static int | ||
640 | acpi_video_init_brightness(struct acpi_video_device *device) | ||
641 | { | ||
642 | union acpi_object *obj = NULL; | ||
643 | int i, max_level = 0, count = 0; | ||
644 | union acpi_object *o; | ||
645 | struct acpi_video_device_brightness *br = NULL; | ||
646 | |||
647 | if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { | ||
648 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " | ||
649 | "LCD brightness level\n")); | ||
650 | goto out; | ||
651 | } | ||
652 | |||
653 | if (obj->package.count < 2) | ||
654 | goto out; | ||
655 | |||
656 | br = kzalloc(sizeof(*br), GFP_KERNEL); | ||
657 | if (!br) { | ||
658 | printk(KERN_ERR "can't allocate memory\n"); | ||
659 | goto out; | ||
660 | } | ||
661 | |||
662 | br->levels = kmalloc(obj->package.count * sizeof *(br->levels), | ||
663 | GFP_KERNEL); | ||
664 | if (!br->levels) | ||
665 | goto out_free; | ||
666 | |||
667 | for (i = 0; i < obj->package.count; i++) { | ||
668 | o = (union acpi_object *)&obj->package.elements[i]; | ||
669 | if (o->type != ACPI_TYPE_INTEGER) { | ||
670 | printk(KERN_ERR PREFIX "Invalid data\n"); | ||
671 | continue; | ||
672 | } | ||
673 | br->levels[count] = (u32) o->integer.value; | ||
674 | |||
675 | if (br->levels[count] > max_level) | ||
676 | max_level = br->levels[count]; | ||
677 | count++; | ||
678 | } | ||
679 | |||
680 | if (count < 2) | ||
681 | goto out_free_levels; | ||
682 | |||
683 | br->count = count; | ||
684 | device->brightness = br; | ||
685 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); | ||
686 | kfree(obj); | ||
687 | return max_level; | ||
688 | |||
689 | out_free_levels: | ||
690 | kfree(br->levels); | ||
691 | out_free: | ||
692 | kfree(br); | ||
693 | out: | ||
694 | device->brightness = NULL; | ||
695 | kfree(obj); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * Arg: | ||
701 | * device : video output device (LCD, CRT, ..) | ||
702 | * | ||
703 | * Return Value: | ||
634 | * None | 704 | * None |
635 | * | 705 | * |
636 | * Find out all required AML methods defined under the output | 706 | * Find out all required AML methods defined under the output |
@@ -640,10 +710,7 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) | |||
640 | static void acpi_video_device_find_cap(struct acpi_video_device *device) | 710 | static void acpi_video_device_find_cap(struct acpi_video_device *device) |
641 | { | 711 | { |
642 | acpi_handle h_dummy1; | 712 | acpi_handle h_dummy1; |
643 | int i; | ||
644 | u32 max_level = 0; | 713 | u32 max_level = 0; |
645 | union acpi_object *obj = NULL; | ||
646 | struct acpi_video_device_brightness *br = NULL; | ||
647 | 714 | ||
648 | 715 | ||
649 | memset(&device->cap, 0, sizeof(device->cap)); | 716 | memset(&device->cap, 0, sizeof(device->cap)); |
@@ -672,53 +739,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
672 | device->cap._DSS = 1; | 739 | device->cap._DSS = 1; |
673 | } | 740 | } |
674 | 741 | ||
675 | if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { | 742 | max_level = acpi_video_init_brightness(device); |
676 | |||
677 | if (obj->package.count >= 2) { | ||
678 | int count = 0; | ||
679 | union acpi_object *o; | ||
680 | |||
681 | br = kzalloc(sizeof(*br), GFP_KERNEL); | ||
682 | if (!br) { | ||
683 | printk(KERN_ERR "can't allocate memory\n"); | ||
684 | } else { | ||
685 | br->levels = kmalloc(obj->package.count * | ||
686 | sizeof *(br->levels), GFP_KERNEL); | ||
687 | if (!br->levels) | ||
688 | goto out; | ||
689 | |||
690 | for (i = 0; i < obj->package.count; i++) { | ||
691 | o = (union acpi_object *)&obj->package. | ||
692 | elements[i]; | ||
693 | if (o->type != ACPI_TYPE_INTEGER) { | ||
694 | printk(KERN_ERR PREFIX "Invalid data\n"); | ||
695 | continue; | ||
696 | } | ||
697 | br->levels[count] = (u32) o->integer.value; | ||
698 | |||
699 | if (br->levels[count] > max_level) | ||
700 | max_level = br->levels[count]; | ||
701 | count++; | ||
702 | } | ||
703 | out: | ||
704 | if (count < 2) { | ||
705 | kfree(br->levels); | ||
706 | kfree(br); | ||
707 | } else { | ||
708 | br->count = count; | ||
709 | device->brightness = br; | ||
710 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
711 | "found %d brightness levels\n", | ||
712 | count)); | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | |||
717 | } else { | ||
718 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n")); | ||
719 | } | ||
720 | |||
721 | kfree(obj); | ||
722 | 743 | ||
723 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ | 744 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ |
724 | int result; | 745 | int result; |
@@ -1695,6 +1716,8 @@ static void | |||
1695 | acpi_video_switch_brightness(struct acpi_video_device *device, int event) | 1716 | acpi_video_switch_brightness(struct acpi_video_device *device, int event) |
1696 | { | 1717 | { |
1697 | unsigned long level_current, level_next; | 1718 | unsigned long level_current, level_next; |
1719 | if (!device->brightness) | ||
1720 | return; | ||
1698 | acpi_video_device_lcd_get_level_current(device, &level_current); | 1721 | acpi_video_device_lcd_get_level_current(device, &level_current); |
1699 | level_next = acpi_video_get_next_level(device, level_current, event); | 1722 | level_next = acpi_video_get_next_level(device, level_current, event); |
1700 | acpi_video_device_lcd_set_level(device, level_next); | 1723 | acpi_video_device_lcd_set_level(device, level_next); |