* [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck
@ 2026-09-23 8:29 Umang Jain
2026-09-23 8:29 ` [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method Umang Jain
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Umang Jain @ 2026-09-23 8:29 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown
Cc: linux-acpi, linux-kernel, kernel-dev, Umang Jain
Short series to query Battery charge time ("_BCT") from ACPI tables
(1/2).
Patch 2/2 handles the case where steamdeck devices can report "Charging"
even when low power PSU is connected which is discharging the device.
Changes in v2:
- comment improvements
- split off BCT method handling into separate patch
v1:
https://lore.kernel.org/all/20260918135628.2322188-1-uajain@igalia.com/
Umang Jain (2):
acpi: battery: Query Battery charge time ("_BCT") method
acpi: battery: Handle Valve steamdeck devices quirk
drivers/acpi/battery.c | 45 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 44 insertions(+), 1 deletion(-)
--
2.55.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method
2026-09-23 8:29 [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
@ 2026-09-23 8:29 ` Umang Jain
2026-10-12 15:15 ` Rafael J. Wysocki (Intel)
2026-09-23 8:29 ` [PATCH v2 2/2] acpi: battery: Handle Valve steamdeck devices quirk Umang Jain
2026-10-10 16:57 ` [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
2 siblings, 1 reply; 6+ messages in thread
From: Umang Jain @ 2026-09-23 8:29 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown
Cc: linux-acpi, linux-kernel, kernel-dev, Umang Jain
Add plumbing for querying the Battery Charge Time ("_BCT") method.
If present, set ACPI_BATTERY_BCT_PRESENT in battery flags to denote
that the method is supported in ACPI.
Signed-off-by: Umang Jain <uajain@igalia.com>
---
drivers/acpi/battery.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 670853ec3a4d..a1b7a821abaf 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -76,6 +76,7 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids);
enum {
ACPI_BATTERY_ALARM_PRESENT,
ACPI_BATTERY_XINFO_PRESENT,
+ ACPI_BATTERY_BCT_PRESENT,
ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
/* On Lenovo Thinkpad models from 2010 and 2011, the power unit
* switches between mWh and mAh depending on whether the system
@@ -110,6 +111,7 @@ struct acpi_battery {
struct mutex property_lock; /* Protects properties below. */
unsigned long update_time;
+ unsigned long long charge_time;
int revision;
int rate_now;
int capacity_now;
@@ -613,6 +615,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
int result = 0;
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
+
+ arg0.integer.value = 100;
lockdep_assert_held(&battery->property_lock);
@@ -638,6 +644,15 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
battery->update_time = jiffies;
kfree(buffer.pointer);
+ if (test_bit(ACPI_BATTERY_BCT_PRESENT, &battery->flags)) {
+ status = acpi_evaluate_integer(battery->device->handle, "_BCT",
+ &args, &battery->charge_time);
+ if (ACPI_FAILURE(status))
+ acpi_handle_info(battery->device->handle,
+ "_BCT evaluation failed: %s",
+ acpi_format_exception(status));
+ }
+
/* For buggy DSDTs that report negative 16-bit values for either
* charging or discharging current and/or report 0 as 65536
* due to bad math.
@@ -1083,6 +1098,8 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
if (result)
return result;
acpi_battery_init_alarm(battery);
+ if (acpi_has_method(battery->device->handle, "_BCT"))
+ set_bit(ACPI_BATTERY_BCT_PRESENT, &battery->flags);
}
result = acpi_battery_get_state(battery);
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] acpi: battery: Handle Valve steamdeck devices quirk
2026-09-23 8:29 [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
2026-09-23 8:29 ` [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method Umang Jain
@ 2026-09-23 8:29 ` Umang Jain
2026-10-12 15:19 ` Rafael J. Wysocki (Intel)
2026-10-10 16:57 ` [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
2 siblings, 1 reply; 6+ messages in thread
From: Umang Jain @ 2026-09-23 8:29 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown
Cc: linux-acpi, linux-kernel, kernel-dev, Umang Jain
Valve steamdeck devices can report battery status as
charging, even when low-powered power supply is connected
to the device. The battery status is reported as charging
through sysfs, even though in reality, it is discharging.
To handle this case, we introduce a battery quirk for steamdeck
devices ACPI_BATTERY_QUIRK_VALVE_STEAMDECK. Additionally, it has been
found that on such devices, Battery Charge Time ("_BCT") is reported
accurately, hence use that information for report charging vs
discharging status. Battery Charge Time("_BCT") with an eligible power
supply unit will have valid values whereas with a low-powered supply
unit, it shall report ACPI_BATTERY_VALUE_UNKNOWN. Use this as a
differentiator to determine, whether the battery of steamdeck devices
is really charging or not.
Signed-off-by: Umang Jain <uajain@igalia.com>
---
drivers/acpi/battery.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index a1b7a821abaf..8defafd2b7c7 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -95,6 +95,14 @@ enum {
* on a full charge, but showing degradation in full charge cap.
*/
ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
+ /*
+ * Valve steamdeck devices can get discharged even when battery status
+ * is charging. This happens typically when low power supply unit is
+ * connected. To accurately determine this scenario, we shall read
+ * battery charge time ("_BCT"). This is the key differentiator to
+ * determine whether the steamdeck is actually charging or not.
+ */
+ ACPI_BATTERY_QUIRK_VALVE_STEAMDECK,
};
struct acpi_battery {
@@ -236,7 +244,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
: POWER_SUPPLY_STATUS_DISCHARGING;
return 0;
}
- else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
+ else if (battery->state & ACPI_BATTERY_STATE_CHARGING) {
/* Check the rate and capacity to validate the status. */
if (!acpi_battery_is_full(battery) ||
(battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
@@ -246,6 +254,12 @@ static int acpi_battery_get_property(struct power_supply *psy,
/* Full and zero rate. */
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
+
+ if (test_bit(ACPI_BATTERY_QUIRK_VALVE_STEAMDECK, &battery->flags) &&
+ test_bit(ACPI_BATTERY_BCT_PRESENT, &battery->flags) &&
+ battery->charge_time == ACPI_BATTERY_VALUE_UNKNOWN)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
else if (battery->state & ACPI_BATTERY_STATE_CHARGE_LIMITING)
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
else if (acpi_battery_is_charged(battery))
@@ -1072,6 +1086,18 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
battery->capacity_now = battery->full_charge_capacity;
}
+
+ if (test_bit(ACPI_BATTERY_QUIRK_VALVE_STEAMDECK, &battery->flags))
+ return;
+
+ if (dmi_name_in_vendors("Valve")) {
+ const char *name;
+
+ name = dmi_get_system_info(DMI_PRODUCT_NAME);
+ if ((name && (!strncmp("Jupiter", name, 7))) ||
+ (name && (!strncmp("Galileo", name, 7))))
+ set_bit(ACPI_BATTERY_QUIRK_VALVE_STEAMDECK, &battery->flags);
+ }
}
static int acpi_battery_update(struct acpi_battery *battery, bool resume)
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck
2026-09-23 8:29 [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
2026-09-23 8:29 ` [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method Umang Jain
2026-09-23 8:29 ` [PATCH v2 2/2] acpi: battery: Handle Valve steamdeck devices quirk Umang Jain
@ 2026-10-10 16:57 ` Umang Jain
2 siblings, 0 replies; 6+ messages in thread
From: Umang Jain @ 2026-10-10 16:57 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown; +Cc: linux-acpi, linux-kernel
Hello,
Gentle ping for some review?
Thanks,
Umang
On 2026-09-23 10:29, Umang Jain wrote:
> Short series to query Battery charge time ("_BCT") from ACPI tables
> (1/2).
>
> Patch 2/2 handles the case where steamdeck devices can report "Charging"
> even when low power PSU is connected which is discharging the device.
>
> Changes in v2:
> - comment improvements
> - split off BCT method handling into separate patch
>
> v1:
> https://lore.kernel.org/all/20260918135628.2322188-1-uajain@igalia.com/
>
> Umang Jain (2):
> acpi: battery: Query Battery charge time ("_BCT") method
> acpi: battery: Handle Valve steamdeck devices quirk
>
> drivers/acpi/battery.c | 45 +++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 44 insertions(+), 1 deletion(-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method
2026-09-23 8:29 ` [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method Umang Jain
@ 2026-10-12 15:15 ` Rafael J. Wysocki (Intel)
0 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-10-12 15:15 UTC (permalink / raw)
To: Umang Jain
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
kernel-dev
On Wed, Sep 23, 2026 at 10:28 AM Umang Jain <uajain@igalia.com> wrote:
>
> Add plumbing for querying the Battery Charge Time ("_BCT") method.
> If present, set ACPI_BATTERY_BCT_PRESENT in battery flags to denote
> that the method is supported in ACPI.
>
> Signed-off-by: Umang Jain <uajain@igalia.com>
> ---
> drivers/acpi/battery.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
> index 670853ec3a4d..a1b7a821abaf 100644
> --- a/drivers/acpi/battery.c
> +++ b/drivers/acpi/battery.c
> @@ -76,6 +76,7 @@ MODULE_DEVICE_TABLE(acpi, battery_device_ids);
> enum {
> ACPI_BATTERY_ALARM_PRESENT,
> ACPI_BATTERY_XINFO_PRESENT,
> + ACPI_BATTERY_BCT_PRESENT,
> ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
> /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
> * switches between mWh and mAh depending on whether the system
> @@ -110,6 +111,7 @@ struct acpi_battery {
>
> struct mutex property_lock; /* Protects properties below. */
> unsigned long update_time;
> + unsigned long long charge_time;
This doesn't need to be unsigned long long. As per the spec, unsigned
int should be sufficient.
> int revision;
> int rate_now;
> int capacity_now;
> @@ -613,6 +615,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
> int result = 0;
> acpi_status status = 0;
> struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> + union acpi_object arg0 = { ACPI_TYPE_INTEGER };
> + struct acpi_object_list args = { 1, &arg0 };
> +
> + arg0.integer.value = 100;
Please move the definitions of the variables related to _BCT
evaluation to the code block where it gets evaluated.
>
> lockdep_assert_held(&battery->property_lock);
>
> @@ -638,6 +644,15 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
> battery->update_time = jiffies;
> kfree(buffer.pointer);
>
> + if (test_bit(ACPI_BATTERY_BCT_PRESENT, &battery->flags)) {
> + status = acpi_evaluate_integer(battery->device->handle, "_BCT",
> + &args, &battery->charge_time);
Currently, you only need to evaluate _BCT to implement the quirk in
the second patch AFAICS, so it is not useful to evaluate _BCT if the
quirk is not going to be used. Any chance to rearrange the code to
avoid evaluating _BCT when it is not needed?
> + if (ACPI_FAILURE(status))
> + acpi_handle_info(battery->device->handle,
> + "_BCT evaluation failed: %s",
> + acpi_format_exception(status));
Missing indentation.
> + }
> +
> /* For buggy DSDTs that report negative 16-bit values for either
> * charging or discharging current and/or report 0 as 65536
> * due to bad math.
> @@ -1083,6 +1098,8 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
> if (result)
> return result;
> acpi_battery_init_alarm(battery);
> + if (acpi_has_method(battery->device->handle, "_BCT"))
> + set_bit(ACPI_BATTERY_BCT_PRESENT, &battery->flags);
> }
>
> result = acpi_battery_get_state(battery);
> --
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] acpi: battery: Handle Valve steamdeck devices quirk
2026-09-23 8:29 ` [PATCH v2 2/2] acpi: battery: Handle Valve steamdeck devices quirk Umang Jain
@ 2026-10-12 15:19 ` Rafael J. Wysocki (Intel)
0 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki (Intel) @ 2026-10-12 15:19 UTC (permalink / raw)
To: Umang Jain
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
kernel-dev
On Wed, Sep 23, 2026 at 10:28 AM Umang Jain <uajain@igalia.com> wrote:
>
> Valve steamdeck devices can report battery status as
> charging, even when low-powered power supply is connected
> to the device. The battery status is reported as charging
> through sysfs, even though in reality, it is discharging.
>
> To handle this case, we introduce a battery quirk for steamdeck
> devices ACPI_BATTERY_QUIRK_VALVE_STEAMDECK. Additionally, it has been
> found that on such devices, Battery Charge Time ("_BCT") is reported
> accurately, hence use that information for report charging vs
> discharging status. Battery Charge Time("_BCT") with an eligible power
> supply unit will have valid values whereas with a low-powered supply
> unit, it shall report ACPI_BATTERY_VALUE_UNKNOWN. Use this as a
> differentiator to determine, whether the battery of steamdeck devices
> is really charging or not.
>
> Signed-off-by: Umang Jain <uajain@igalia.com>
> ---
> drivers/acpi/battery.c | 28 +++++++++++++++++++++++++++-
> 1 file changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
> index a1b7a821abaf..8defafd2b7c7 100644
> --- a/drivers/acpi/battery.c
> +++ b/drivers/acpi/battery.c
> @@ -95,6 +95,14 @@ enum {
> * on a full charge, but showing degradation in full charge cap.
> */
> ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
> + /*
> + * Valve steamdeck devices can get discharged even when battery status
> + * is charging. This happens typically when low power supply unit is
> + * connected. To accurately determine this scenario, we shall read
> + * battery charge time ("_BCT"). This is the key differentiator to
> + * determine whether the steamdeck is actually charging or not.
> + */
> + ACPI_BATTERY_QUIRK_VALVE_STEAMDECK,
> };
>
> struct acpi_battery {
> @@ -236,7 +244,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
> : POWER_SUPPLY_STATUS_DISCHARGING;
> return 0;
> }
> - else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
> + else if (battery->state & ACPI_BATTERY_STATE_CHARGING) {
> /* Check the rate and capacity to validate the status. */
> if (!acpi_battery_is_full(battery) ||
> (battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
> @@ -246,6 +254,12 @@ static int acpi_battery_get_property(struct power_supply *psy,
> /* Full and zero rate. */
> val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
> }
> +
> + if (test_bit(ACPI_BATTERY_QUIRK_VALVE_STEAMDECK, &battery->flags) &&
> + test_bit(ACPI_BATTERY_BCT_PRESENT, &battery->flags) &&
> + battery->charge_time == ACPI_BATTERY_VALUE_UNKNOWN)
Would it be practical to evaluate _BCT here without storing
charge_time in the battery object?
> + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
> + }
> else if (battery->state & ACPI_BATTERY_STATE_CHARGE_LIMITING)
> val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
> else if (acpi_battery_is_charged(battery))
> @@ -1072,6 +1086,18 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
> set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
> battery->capacity_now = battery->full_charge_capacity;
> }
> +
> + if (test_bit(ACPI_BATTERY_QUIRK_VALVE_STEAMDECK, &battery->flags))
> + return;
> +
> + if (dmi_name_in_vendors("Valve")) {
> + const char *name;
> +
> + name = dmi_get_system_info(DMI_PRODUCT_NAME);
> + if ((name && (!strncmp("Jupiter", name, 7))) ||
> + (name && (!strncmp("Galileo", name, 7))))
> + set_bit(ACPI_BATTERY_QUIRK_VALVE_STEAMDECK, &battery->flags);
> + }
> }
>
> static int acpi_battery_update(struct acpi_battery *battery, bool resume)
> --
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-12 15:21 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-23 8:29 [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
2026-09-23 8:29 ` [PATCH v2 1/2] acpi: battery: Query Battery charge time ("_BCT") method Umang Jain
2026-10-12 15:15 ` Rafael J. Wysocki (Intel)
2026-09-23 8:29 ` [PATCH v2 2/2] acpi: battery: Handle Valve steamdeck devices quirk Umang Jain
2026-10-12 15:19 ` Rafael J. Wysocki (Intel)
2026-10-10 16:57 ` [PATCH v2 0/2] acpi: battery: Query BCT method and steamdeck Umang Jain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox