Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 557d5868 authored by Zhang Rui's avatar Zhang Rui Committed by Len Brown
Browse files

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: default avatarZhang Rui <rui.zhang@intel.com>
Tested-by: default avatarSitsofe Wheeler <sitsofe@yahoo.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 03e7c343
Loading
Loading
Loading
Loading
+37 −1
Original line number Original line Diff line number Diff line
@@ -95,6 +95,7 @@ enum {
	 * due to bad math.
	 * due to bad math.
	 */
	 */
	ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
	ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
	ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
};
};


struct acpi_battery {
struct acpi_battery {
@@ -405,6 +406,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
		result = extract_package(battery, buffer.pointer,
		result = extract_package(battery, buffer.pointer,
				info_offsets, ARRAY_SIZE(info_offsets));
				info_offsets, ARRAY_SIZE(info_offsets));
	kfree(buffer.pointer);
	kfree(buffer.pointer);
	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
		battery->full_charge_capacity = battery->design_capacity;
	return result;
	return result;
}
}


@@ -441,6 +444,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
	    battery->rate_now != -1)
	    battery->rate_now != -1)
		battery->rate_now = abs((s16)battery->rate_now);
		battery->rate_now = abs((s16)battery->rate_now);


	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
	    && battery->capacity_now >= 0 && battery->capacity_now <= 100)
		battery->capacity_now = (battery->capacity_now *
				battery->full_charge_capacity) / 100;
	return result;
	return result;
}
}


@@ -552,6 +559,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
	}
	}
}
}


/*
 * According to the ACPI spec, some kinds of primary batteries can
 * report percentage battery remaining capacity directly to OS.
 * In this case, it reports the Last Full Charged Capacity == 100
 * and BatteryPresentRate == 0xFFFFFFFF.
 *
 * Now we found some battery reports percentage remaining capacity
 * even if it's rechargeable.
 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
 *
 * Handle this correctly so that they won't break userspace.
 */
static void acpi_battery_quirks2(struct acpi_battery *battery)
{
	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
		return ;

        if (battery->full_charge_capacity == 100 &&
            battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
            battery->capacity_now >=0 && battery->capacity_now <= 100) {
		set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
		battery->full_charge_capacity = battery->design_capacity;
		battery->capacity_now = (battery->capacity_now *
				battery->full_charge_capacity) / 100;
	}
}

static int acpi_battery_update(struct acpi_battery *battery)
static int acpi_battery_update(struct acpi_battery *battery)
{
{
	int result, old_present = acpi_battery_present(battery);
	int result, old_present = acpi_battery_present(battery);
@@ -573,7 +607,9 @@ static int acpi_battery_update(struct acpi_battery *battery)
	}
	}
	if (!battery->bat.dev)
	if (!battery->bat.dev)
		sysfs_add_battery(battery);
		sysfs_add_battery(battery);
	return acpi_battery_get_state(battery);
	result = acpi_battery_get_state(battery);
	acpi_battery_quirks2(battery);
	return result;
}
}


/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------