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.c110
1 files changed, 71 insertions, 39 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 313f959413dc..3cdd0471bc63 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -222,7 +222,7 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device,
222 int level); 222 int level);
223static int acpi_video_device_lcd_get_level_current( 223static int acpi_video_device_lcd_get_level_current(
224 struct acpi_video_device *device, 224 struct acpi_video_device *device,
225 unsigned long long *level, int init); 225 unsigned long long *level, bool raw);
226static int acpi_video_get_next_level(struct acpi_video_device *device, 226static int acpi_video_get_next_level(struct acpi_video_device *device,
227 u32 level_current, u32 event); 227 u32 level_current, u32 event);
228static int acpi_video_switch_brightness(struct acpi_video_device *device, 228static int acpi_video_switch_brightness(struct acpi_video_device *device,
@@ -236,7 +236,7 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
236 struct acpi_video_device *vd = 236 struct acpi_video_device *vd =
237 (struct acpi_video_device *)bl_get_data(bd); 237 (struct acpi_video_device *)bl_get_data(bd);
238 238
239 if (acpi_video_device_lcd_get_level_current(vd, &cur_level, 0)) 239 if (acpi_video_device_lcd_get_level_current(vd, &cur_level, false))
240 return -EINVAL; 240 return -EINVAL;
241 for (i = 2; i < vd->brightness->count; i++) { 241 for (i = 2; i < vd->brightness->count; i++) {
242 if (vd->brightness->levels[i] == cur_level) 242 if (vd->brightness->levels[i] == cur_level)
@@ -281,7 +281,7 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig
281 unsigned long long level; 281 unsigned long long level;
282 int offset; 282 int offset;
283 283
284 if (acpi_video_device_lcd_get_level_current(video, &level, 0)) 284 if (acpi_video_device_lcd_get_level_current(video, &level, false))
285 return -EINVAL; 285 return -EINVAL;
286 for (offset = 2; offset < video->brightness->count; offset++) 286 for (offset = 2; offset < video->brightness->count; offset++)
287 if (level == video->brightness->levels[offset]) { 287 if (level == video->brightness->levels[offset]) {
@@ -447,12 +447,45 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
447 DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), 447 DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
448 }, 448 },
449 }, 449 },
450 {
451 .callback = video_ignore_initial_backlight,
452 .ident = "HP Pavilion dm4",
453 .matches = {
454 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
455 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dm4 Notebook PC"),
456 },
457 },
450 {} 458 {}
451}; 459};
452 460
461static unsigned long long
462acpi_video_bqc_value_to_level(struct acpi_video_device *device,
463 unsigned long long bqc_value)
464{
465 unsigned long long level;
466
467 if (device->brightness->flags._BQC_use_index) {
468 /*
469 * _BQC returns an index that doesn't account for
470 * the first 2 items with special meaning, so we need
471 * to compensate for that by offsetting ourselves
472 */
473 if (device->brightness->flags._BCL_reversed)
474 bqc_value = device->brightness->count - 3 - bqc_value;
475
476 level = device->brightness->levels[bqc_value + 2];
477 } else {
478 level = bqc_value;
479 }
480
481 level += bqc_offset_aml_bug_workaround;
482
483 return level;
484}
485
453static int 486static int
454acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, 487acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
455 unsigned long long *level, int init) 488 unsigned long long *level, bool raw)
456{ 489{
457 acpi_status status = AE_OK; 490 acpi_status status = AE_OK;
458 int i; 491 int i;
@@ -463,29 +496,30 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device,
463 status = acpi_evaluate_integer(device->dev->handle, buf, 496 status = acpi_evaluate_integer(device->dev->handle, buf,
464 NULL, level); 497 NULL, level);
465 if (ACPI_SUCCESS(status)) { 498 if (ACPI_SUCCESS(status)) {
466 if (device->brightness->flags._BQC_use_index) { 499 if (raw) {
467 if (device->brightness->flags._BCL_reversed) 500 /*
468 *level = device->brightness->count 501 * Caller has indicated he wants the raw
469 - 3 - (*level); 502 * value returned by _BQC, so don't furtherly
470 *level = device->brightness->levels[*level + 2]; 503 * mess with the value.
471 504 */
505 return 0;
472 } 506 }
473 *level += bqc_offset_aml_bug_workaround; 507
508 *level = acpi_video_bqc_value_to_level(device, *level);
509
474 for (i = 2; i < device->brightness->count; i++) 510 for (i = 2; i < device->brightness->count; i++)
475 if (device->brightness->levels[i] == *level) { 511 if (device->brightness->levels[i] == *level) {
476 device->brightness->curr = *level; 512 device->brightness->curr = *level;
477 return 0; 513 return 0;
478 } 514 }
479 if (!init) { 515 /*
480 /* 516 * BQC returned an invalid level.
481 * BQC returned an invalid level. 517 * Stop using it.
482 * Stop using it. 518 */
483 */ 519 ACPI_WARNING((AE_INFO,
484 ACPI_WARNING((AE_INFO, 520 "%s returned an invalid level",
485 "%s returned an invalid level", 521 buf));
486 buf)); 522 device->cap._BQC = device->cap._BCQ = 0;
487 device->cap._BQC = device->cap._BCQ = 0;
488 }
489 } else { 523 } else {
490 /* Fixme: 524 /* Fixme:
491 * should we return an error or ignore this failure? 525 * should we return an error or ignore this failure?
@@ -703,7 +737,8 @@ acpi_video_init_brightness(struct acpi_video_device *device)
703 if (!device->cap._BQC) 737 if (!device->cap._BQC)
704 goto set_level; 738 goto set_level;
705 739
706 result = acpi_video_device_lcd_get_level_current(device, &level_old, 1); 740 result = acpi_video_device_lcd_get_level_current(device,
741 &level_old, true);
707 if (result) 742 if (result)
708 goto out_free_levels; 743 goto out_free_levels;
709 744
@@ -714,31 +749,27 @@ acpi_video_init_brightness(struct acpi_video_device *device)
714 if (result) 749 if (result)
715 goto out_free_levels; 750 goto out_free_levels;
716 751
717 result = acpi_video_device_lcd_get_level_current(device, &level, 0); 752 result = acpi_video_device_lcd_get_level_current(device, &level, true);
718 if (result) 753 if (result)
719 goto out_free_levels; 754 goto out_free_levels;
720 755
721 br->flags._BQC_use_index = (level == max_level ? 0 : 1); 756 br->flags._BQC_use_index = (level == max_level ? 0 : 1);
722 757
723 if (!br->flags._BQC_use_index) { 758 if (use_bios_initial_backlight) {
759 level = acpi_video_bqc_value_to_level(device, level_old);
724 /* 760 /*
725 * Set the backlight to the initial state. 761 * On some buggy laptops, _BQC returns an uninitialized
726 * On some buggy laptops, _BQC returns an uninitialized value 762 * value when invoked for the first time, i.e.
727 * when invoked for the first time, i.e. level_old is invalid. 763 * level_old is invalid (no matter whether it's a level
728 * set the backlight to max_level in this case 764 * or an index). Set the backlight to max_level in this case.
729 */ 765 */
730 if (use_bios_initial_backlight) { 766 for (i = 2; i < br->count; i++)
731 for (i = 2; i < br->count; i++) 767 if (level_old == br->levels[i])
732 if (level_old == br->levels[i]) 768 break;
733 level = level_old; 769 if (i == br->count)
734 } 770 level = max_level;
735 goto set_level;
736 } 771 }
737 772
738 if (br->flags._BCL_reversed)
739 level_old = (br->count - 1) - level_old;
740 level = br->levels[level_old];
741
742set_level: 773set_level:
743 result = acpi_video_device_lcd_set_level(device, level); 774 result = acpi_video_device_lcd_set_level(device, level);
744 if (result) 775 if (result)
@@ -1268,7 +1299,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
1268 goto out; 1299 goto out;
1269 1300
1270 result = acpi_video_device_lcd_get_level_current(device, 1301 result = acpi_video_device_lcd_get_level_current(device,
1271 &level_current, 0); 1302 &level_current,
1303 false);
1272 if (result) 1304 if (result)
1273 goto out; 1305 goto out;
1274 1306