aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2010-10-21 22:02:06 -0400
committerLen Brown <len.brown@intel.com>2010-10-22 01:28:07 -0400
commit557d58687dcdee6bc00c1a8f1fd4e0eac8fefce9 (patch)
tree6a73fcf98ee0c78520f38aba6d053875bd2a3dc0 /drivers/acpi
parent03e7c3432d40d067476eaf49ede29128b637998f (diff)
ACPI battery: support percentage battery remaining capacity
According to the ACPI spec, some kinds of primary battery can report percentage battery remaining capacity directly to OS. In this case, it reports the LastFullChargedCapacity == 100, BatteryPresentRate = 0xFFFFFFFF, and BatteryRemaingCapacity a percentage value, which actually means RemainingBatteryPercentage. Now we found some battery follows this rule even if it's a rechargeable. https://bugzilla.kernel.org/show_bug.cgi?id=15979 Handle these batteries correctly in ACPI battery driver so that they won't break userspace. Signed-off-by: Zhang Rui <rui.zhang@intel.com> Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/battery.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 7b8787b490f6..0b2707ee094b 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -95,6 +95,7 @@ enum {
95 * due to bad math. 95 * due to bad math.
96 */ 96 */
97 ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, 97 ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
98 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
98}; 99};
99 100
100struct acpi_battery { 101struct acpi_battery {
@@ -405,6 +406,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
405 result = extract_package(battery, buffer.pointer, 406 result = extract_package(battery, buffer.pointer,
406 info_offsets, ARRAY_SIZE(info_offsets)); 407 info_offsets, ARRAY_SIZE(info_offsets));
407 kfree(buffer.pointer); 408 kfree(buffer.pointer);
409 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
410 battery->full_charge_capacity = battery->design_capacity;
408 return result; 411 return result;
409} 412}
410 413
@@ -441,6 +444,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
441 battery->rate_now != -1) 444 battery->rate_now != -1)
442 battery->rate_now = abs((s16)battery->rate_now); 445 battery->rate_now = abs((s16)battery->rate_now);
443 446
447 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
448 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
449 battery->capacity_now = (battery->capacity_now *
450 battery->full_charge_capacity) / 100;
444 return result; 451 return result;
445} 452}
446 453
@@ -552,6 +559,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
552 } 559 }
553} 560}
554 561
562/*
563 * According to the ACPI spec, some kinds of primary batteries can
564 * report percentage battery remaining capacity directly to OS.
565 * In this case, it reports the Last Full Charged Capacity == 100
566 * and BatteryPresentRate == 0xFFFFFFFF.
567 *
568 * Now we found some battery reports percentage remaining capacity
569 * even if it's rechargeable.
570 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
571 *
572 * Handle this correctly so that they won't break userspace.
573 */
574static void acpi_battery_quirks2(struct acpi_battery *battery)
575{
576 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
577 return ;
578
579 if (battery->full_charge_capacity == 100 &&
580 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
581 battery->capacity_now >=0 && battery->capacity_now <= 100) {
582 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
583 battery->full_charge_capacity = battery->design_capacity;
584 battery->capacity_now = (battery->capacity_now *
585 battery->full_charge_capacity) / 100;
586 }
587}
588
555static int acpi_battery_update(struct acpi_battery *battery) 589static int acpi_battery_update(struct acpi_battery *battery)
556{ 590{
557 int result, old_present = acpi_battery_present(battery); 591 int result, old_present = acpi_battery_present(battery);
@@ -573,7 +607,9 @@ static int acpi_battery_update(struct acpi_battery *battery)
573 } 607 }
574 if (!battery->bat.dev) 608 if (!battery->bat.dev)
575 sysfs_add_battery(battery); 609 sysfs_add_battery(battery);
576 return acpi_battery_get_state(battery); 610 result = acpi_battery_get_state(battery);
611 acpi_battery_quirks2(battery);
612 return result;
577} 613}
578 614
579/* -------------------------------------------------------------------------- 615/* --------------------------------------------------------------------------