diff options
| -rw-r--r-- | drivers/acpi/video.c | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 3cdd0471bc63..ed192e5d82b6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -632,6 +632,56 @@ acpi_video_cmp_level(const void *a, const void *b) | |||
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | /* | 634 | /* |
| 635 | * Decides if _BQC/_BCQ for this system is usable | ||
| 636 | * | ||
| 637 | * We do this by changing the level first and then read out the current | ||
| 638 | * brightness level, if the value does not match, find out if it is using | ||
| 639 | * index. If not, clear the _BQC/_BCQ capability. | ||
| 640 | */ | ||
| 641 | static int acpi_video_bqc_quirk(struct acpi_video_device *device, | ||
| 642 | int max_level, int current_level) | ||
| 643 | { | ||
| 644 | struct acpi_video_device_brightness *br = device->brightness; | ||
| 645 | int result; | ||
| 646 | unsigned long long level; | ||
| 647 | int test_level; | ||
| 648 | |||
| 649 | /* don't mess with existing known broken systems */ | ||
| 650 | if (bqc_offset_aml_bug_workaround) | ||
| 651 | return 0; | ||
| 652 | |||
| 653 | /* | ||
| 654 | * Some systems always report current brightness level as maximum | ||
| 655 | * through _BQC, we need to test another value for them. | ||
| 656 | */ | ||
| 657 | test_level = current_level == max_level ? br->levels[2] : max_level; | ||
| 658 | |||
| 659 | result = acpi_video_device_lcd_set_level(device, test_level); | ||
| 660 | if (result) | ||
| 661 | return result; | ||
| 662 | |||
| 663 | result = acpi_video_device_lcd_get_level_current(device, &level, true); | ||
| 664 | if (result) | ||
| 665 | return result; | ||
| 666 | |||
| 667 | if (level != test_level) { | ||
| 668 | /* buggy _BQC found, need to find out if it uses index */ | ||
| 669 | if (level < br->count) { | ||
| 670 | if (br->flags._BCL_reversed) | ||
| 671 | level = br->count - 3 - level; | ||
| 672 | if (br->levels[level + 2] == test_level) | ||
| 673 | br->flags._BQC_use_index = 1; | ||
| 674 | } | ||
| 675 | |||
| 676 | if (!br->flags._BQC_use_index) | ||
| 677 | device->cap._BQC = device->cap._BCQ = 0; | ||
| 678 | } | ||
| 679 | |||
| 680 | return 0; | ||
| 681 | } | ||
| 682 | |||
| 683 | |||
| 684 | /* | ||
| 635 | * Arg: | 685 | * Arg: |
| 636 | * device : video output device (LCD, CRT, ..) | 686 | * device : video output device (LCD, CRT, ..) |
| 637 | * | 687 | * |
| @@ -742,18 +792,15 @@ acpi_video_init_brightness(struct acpi_video_device *device) | |||
| 742 | if (result) | 792 | if (result) |
| 743 | goto out_free_levels; | 793 | goto out_free_levels; |
| 744 | 794 | ||
| 745 | /* | 795 | result = acpi_video_bqc_quirk(device, max_level, level_old); |
| 746 | * Set the level to maximum and check if _BQC uses indexed value | ||
| 747 | */ | ||
| 748 | result = acpi_video_device_lcd_set_level(device, max_level); | ||
| 749 | if (result) | ||
| 750 | goto out_free_levels; | ||
| 751 | |||
| 752 | result = acpi_video_device_lcd_get_level_current(device, &level, true); | ||
| 753 | if (result) | 796 | if (result) |
| 754 | goto out_free_levels; | 797 | goto out_free_levels; |
| 755 | 798 | /* | |
| 756 | br->flags._BQC_use_index = (level == max_level ? 0 : 1); | 799 | * cap._BQC may get cleared due to _BQC is found to be broken |
| 800 | * in acpi_video_bqc_quirk, so check again here. | ||
| 801 | */ | ||
| 802 | if (!device->cap._BQC) | ||
| 803 | goto set_level; | ||
| 757 | 804 | ||
| 758 | if (use_bios_initial_backlight) { | 805 | if (use_bios_initial_backlight) { |
| 759 | level = acpi_video_bqc_value_to_level(device, level_old); | 806 | level = acpi_video_bqc_value_to_level(device, level_old); |
