diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 110 |
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); |
223 | static int acpi_video_device_lcd_get_level_current( | 223 | static 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); |
226 | static int acpi_video_get_next_level(struct acpi_video_device *device, | 226 | static int acpi_video_get_next_level(struct acpi_video_device *device, |
227 | u32 level_current, u32 event); | 227 | u32 level_current, u32 event); |
228 | static int acpi_video_switch_brightness(struct acpi_video_device *device, | 228 | static 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 | ||
461 | static unsigned long long | ||
462 | acpi_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 | |||
453 | static int | 486 | static int |
454 | acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, | 487 | acpi_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 | |||
742 | set_level: | 773 | set_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 | ||