aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r--drivers/acpi/video.c92
1 files changed, 67 insertions, 25 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index cd4fb7543a90..810cca90ca7f 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -538,6 +538,41 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
538 return -EINVAL; 538 return -EINVAL;
539} 539}
540 540
541/*
542 * For some buggy _BQC methods, we need to add a constant value to
543 * the _BQC return value to get the actual current brightness level
544 */
545
546static int bqc_offset_aml_bug_workaround;
547static int __init video_set_bqc_offset(const struct dmi_system_id *d)
548{
549 bqc_offset_aml_bug_workaround = 9;
550 return 0;
551}
552
553static struct dmi_system_id video_dmi_table[] __initdata = {
554 /*
555 * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
556 */
557 {
558 .callback = video_set_bqc_offset,
559 .ident = "Acer Aspire 5720",
560 .matches = {
561 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
562 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
563 },
564 },
565 {
566 .callback = video_set_bqc_offset,
567 .ident = "Acer Aspire 5710Z",
568 .matches = {
569 DMI_MATCH(DMI_BOARD_VENDOR, "Acer"),
570 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710Z"),
571 },
572 },
573 {}
574};
575
541static int 576static int
542acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 577acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
543 unsigned long long *level) 578 unsigned long long *level)
@@ -557,6 +592,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
557 *level = device->brightness->levels[*level + 2]; 592 *level = device->brightness->levels[*level + 2];
558 593
559 } 594 }
595 *level += bqc_offset_aml_bug_workaround;
560 device->brightness->curr = *level; 596 device->brightness->curr = *level;
561 return 0; 597 return 0;
562 } else { 598 } else {
@@ -770,10 +806,12 @@ acpi_video_init_brightness(struct acpi_video_device *device)
770 * In this case, the first two elements in _BCL packages 806 * In this case, the first two elements in _BCL packages
771 * are also supported brightness levels that OS should take care of. 807 * are also supported brightness levels that OS should take care of.
772 */ 808 */
773 for (i = 2; i < count; i++) 809 for (i = 2; i < count; i++) {
774 if (br->levels[i] == br->levels[0] || 810 if (br->levels[i] == br->levels[0])
775 br->levels[i] == br->levels[1]) 811 level_ac_battery++;
812 if (br->levels[i] == br->levels[1])
776 level_ac_battery++; 813 level_ac_battery++;
814 }
777 815
778 if (level_ac_battery < 2) { 816 if (level_ac_battery < 2) {
779 level_ac_battery = 2 - level_ac_battery; 817 level_ac_battery = 2 - level_ac_battery;
@@ -807,12 +845,19 @@ acpi_video_init_brightness(struct acpi_video_device *device)
807 br->flags._BCM_use_index = br->flags._BCL_use_index; 845 br->flags._BCM_use_index = br->flags._BCL_use_index;
808 846
809 /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ 847 /* _BQC uses INDEX while _BCL uses VALUE in some laptops */
810 br->curr = max_level; 848 br->curr = level_old = max_level;
849
850 if (!device->cap._BQC)
851 goto set_level;
852
811 result = acpi_video_device_lcd_get_level_current(device, &level_old); 853 result = acpi_video_device_lcd_get_level_current(device, &level_old);
812 if (result) 854 if (result)
813 goto out_free_levels; 855 goto out_free_levels;
814 856
815 result = acpi_video_device_lcd_set_level(device, br->curr); 857 /*
858 * Set the level to maximum and check if _BQC uses indexed value
859 */
860 result = acpi_video_device_lcd_set_level(device, max_level);
816 if (result) 861 if (result)
817 goto out_free_levels; 862 goto out_free_levels;
818 863
@@ -820,25 +865,19 @@ acpi_video_init_brightness(struct acpi_video_device *device)
820 if (result) 865 if (result)
821 goto out_free_levels; 866 goto out_free_levels;
822 867
823 if ((level != level_old) && !br->flags._BCM_use_index) { 868 br->flags._BQC_use_index = (level == max_level ? 0 : 1);
824 /* Note: 869
825 * This piece of code does not work correctly if the current 870 if (!br->flags._BQC_use_index)
826 * brightness levels is 0. 871 goto set_level;
827 * But I guess boxes that boot with such a dark screen are rare 872
828 * and no more code is needed to cover this specifial case. 873 if (br->flags._BCL_reversed)
829 */ 874 level_old = (br->count - 1) - level_old;
830 875 level_old = br->levels[level_old];
831 if (level_ac_battery != 2) { 876
832 /* 877set_level:
833 * For now, we don't support the _BCL like this: 878 result = acpi_video_device_lcd_set_level(device, level_old);
834 * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16 879 if (result)
835 * because we may mess up the index returned by _BQC. 880 goto out_free_levels;
836 * Plus: we have not got a box like this.
837 */
838 ACPI_ERROR((AE_INFO, "_BCL not supported\n"));
839 }
840 br->flags._BQC_use_index = 1;
841 }
842 881
843 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 882 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
844 "found %d brightness levels\n", count - 2)); 883 "found %d brightness levels\n", count - 2));
@@ -2287,13 +2326,15 @@ EXPORT_SYMBOL(acpi_video_register);
2287 2326
2288static int __init acpi_video_init(void) 2327static int __init acpi_video_init(void)
2289{ 2328{
2329 dmi_check_system(video_dmi_table);
2330
2290 if (intel_opregion_present()) 2331 if (intel_opregion_present())
2291 return 0; 2332 return 0;
2292 2333
2293 return acpi_video_register(); 2334 return acpi_video_register();
2294} 2335}
2295 2336
2296static void __exit acpi_video_exit(void) 2337void __exit acpi_video_exit(void)
2297{ 2338{
2298 2339
2299 acpi_bus_unregister_driver(&acpi_video_bus); 2340 acpi_bus_unregister_driver(&acpi_video_bus);
@@ -2302,6 +2343,7 @@ static void __exit acpi_video_exit(void)
2302 2343
2303 return; 2344 return;
2304} 2345}
2346EXPORT_SYMBOL(acpi_video_exit);
2305 2347
2306module_init(acpi_video_init); 2348module_init(acpi_video_init);
2307module_exit(acpi_video_exit); 2349module_exit(acpi_video_exit);