git: f87ba4522ec9 - main - acpi_system76: Add support for battary charge thresholds
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 09 Mar 2026 09:21:49 UTC
The branch main has been updated by pouria:
URL: https://cgit.FreeBSD.org/src/commit/?id=f87ba4522ec9e7b2227b8f20f3a4d7c6a129da1c
commit f87ba4522ec9e7b2227b8f20f3a4d7c6a129da1c
Author: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
AuthorDate: 2026-03-07 18:33:43 +0000
Commit: Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-03-09 09:11:56 +0000
acpi_system76: Add support for battary charge thresholds
Reviewed by: wulf
Differential Revision: https://reviews.freebsd.org/D55710
---
sys/dev/acpi_support/acpi_system76.c | 147 +++++++++++++++++++++++++++--------
1 file changed, 116 insertions(+), 31 deletions(-)
diff --git a/sys/dev/acpi_support/acpi_system76.c b/sys/dev/acpi_support/acpi_system76.c
index c20725f0174e..9ae7d116be0b 100644
--- a/sys/dev/acpi_support/acpi_system76.c
+++ b/sys/dev/acpi_support/acpi_system76.c
@@ -54,7 +54,9 @@ struct acpi_system76_softc {
ACPI_HANDLE handle;
struct acpi_ctrl kbb, /* S76_CTRL_KBB */
- kbc; /* S76_CTRL_KBC */
+ kbc, /* S76_CTRL_KBC */
+ bctl, /* S76_CTRL_BCTL */
+ bcth; /* S76_CTRL_BCTH */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
@@ -72,19 +74,25 @@ static void acpi_system76_notify_handler(ACPI_HANDLE, uint32_t, void *);
static void acpi_system76_check(struct acpi_system76_softc *);
/* methods */
-#define S76_CTRL_KBB 1 /* Keyboard Brightness */
-#define S76_CTRL_KBC 2 /* Keyboard Color */
-#define S76_CTRL_MAX 3
+enum {
+ S76_CTRL_KBB = 1, /* Keyboard Brightness */
+ S76_CTRL_KBC = 2, /* Keyboard Color */
+ S76_CTRL_BCTL = 3, /* Battary Charging Start Thresholds */
+ S76_CTRL_BCTH = 4, /* Battary Charging End Thresholds */
+};
+#define S76_CTRL_MAX 5
struct s76_ctrl_table {
char *name;
char *get_method;
#define S76_CTRL_GKBB "\\_SB.S76D.GKBB"
#define S76_CTRL_GKBC "\\_SB.S76D.GKBC"
+#define S76_CTRL_GBCT "\\_SB.PCI0.LPCB.EC0.GBCT"
char *set_method;
#define S76_CTRL_SKBB "\\_SB.S76D.SKBB"
#define S76_CTRL_SKBC "\\_SB.S76D.SKBC"
+#define S76_CTRL_SBCT "\\_SB.PCI0.LPCB.EC0.SBCT"
char *desc;
};
@@ -102,6 +110,18 @@ static const struct s76_ctrl_table s76_sysctl_table[] = {
.set_method = S76_CTRL_SKBC,
.desc = "Keyboard Color",
},
+ [S76_CTRL_BCTL] = {
+ .name = "battary_thresholds_low",
+ .get_method = S76_CTRL_GBCT,
+ .set_method = S76_CTRL_SBCT,
+ .desc = "Battary charging start thresholds",
+ },
+ [S76_CTRL_BCTH] = {
+ .name = "battary_thresholds_high",
+ .get_method = S76_CTRL_GBCT,
+ .set_method = S76_CTRL_SBCT,
+ .desc = "Battary charging end thresholds",
+ },
};
static device_method_t acpi_system76_methods[] = {
@@ -135,10 +155,12 @@ acpi_system76_ctrl_map(struct acpi_system76_softc *sc, int method)
switch (method) {
case S76_CTRL_KBB:
return (&sc->kbb);
- break;
case S76_CTRL_KBC:
return (&sc->kbc);
- break;
+ case S76_CTRL_BCTL:
+ return (&sc->bctl);
+ case S76_CTRL_BCTH:
+ return (&sc->bcth);
default:
device_printf(sc->dev, "Driver received unknown method\n");
return (NULL);
@@ -150,6 +172,9 @@ acpi_system76_update(struct acpi_system76_softc *sc, int method, bool set)
{
struct acpi_ctrl *ctrl;
ACPI_STATUS status;
+ ACPI_BUFFER Buf;
+ ACPI_OBJECT Arg[2], Obj;
+ ACPI_OBJECT_LIST Args;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
ACPI_SERIAL_ASSERT(system76);
@@ -157,12 +182,41 @@ acpi_system76_update(struct acpi_system76_softc *sc, int method, bool set)
if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
return (EINVAL);
- if (set)
- status = acpi_SetInteger(sc->handle, s76_sysctl_table[method].set_method,
- ctrl->val);
- else
- status = acpi_GetInteger(sc->handle, s76_sysctl_table[method].get_method,
- &ctrl->val);
+ switch (method) {
+ case S76_CTRL_BCTL:
+ case S76_CTRL_BCTH:
+ Arg[0].Type = ACPI_TYPE_INTEGER;
+ Arg[0].Integer.Value = method == S76_CTRL_BCTH ? 1 : 0;
+ Args.Count = set ? 2 : 1;
+ Args.Pointer = Arg;
+ Buf.Length = sizeof(Obj);
+ Buf.Pointer = &Obj;
+
+ if (set) {
+ Arg[1].Type = ACPI_TYPE_INTEGER;
+ Arg[1].Integer.Value = ctrl->val;
+
+ status = AcpiEvaluateObject(sc->handle,
+ s76_sysctl_table[method].set_method, &Args, &Buf);
+ } else {
+ status = AcpiEvaluateObject(sc->handle,
+ s76_sysctl_table[method].get_method, &Args, &Buf);
+ if (ACPI_SUCCESS(status) &&
+ Obj.Type == ACPI_TYPE_INTEGER)
+ ctrl->val = Obj.Integer.Value;
+ }
+ break;
+ case S76_CTRL_KBB:
+ case S76_CTRL_KBC:
+ if (set)
+ status = acpi_SetInteger(sc->handle, s76_sysctl_table[method].set_method,
+ ctrl->val);
+ else
+ status = acpi_GetInteger(sc->handle, s76_sysctl_table[method].get_method,
+ &ctrl->val);
+ break;
+ }
+
if (ACPI_FAILURE(status)) {
device_printf(sc->dev, "Couldn't query method (%s)\n",
s76_sysctl_table[method].name);
@@ -183,8 +237,12 @@ acpi_system76_notify_update(void *arg)
sc = (struct acpi_system76_softc *)device_get_softc(arg);
ACPI_SERIAL_BEGIN(system76);
- for (method = 1; method < S76_CTRL_MAX; method++)
+ for (method = 1; method < S76_CTRL_MAX; method++) {
+ if (method == S76_CTRL_BCTL ||
+ method == S76_CTRL_BCTH)
+ continue;
acpi_system76_update(sc, method, false);
+ }
ACPI_SERIAL_END(system76);
}
@@ -201,6 +259,14 @@ acpi_system76_check(struct acpi_system76_softc *sc)
if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
continue;
+ /* available in all models */
+ if (method == S76_CTRL_BCTL ||
+ method == S76_CTRL_BCTH) {
+ ctrl->exists = true;
+ acpi_system76_update(sc, method, false);
+ continue;
+ }
+
if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
s76_sysctl_table[method].get_method, &ctrl->val))) {
ctrl->exists = false;
@@ -236,9 +302,10 @@ acpi_system76_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *ctx)
static int
acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
- struct acpi_ctrl *ctrl;
+ struct acpi_ctrl *ctrl, *ctrl_cmp;
struct acpi_system76_softc *sc;
int val, method, error;
+ bool update;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -253,27 +320,45 @@ acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS)
device_printf(sc->dev, "Driver query failed\n");
return (error);
}
- if (req->newptr == NULL)
- return (error);
- /* Input validation */
- switch (method) {
- case S76_CTRL_KBB:
- if (val > UINT8_MAX || val < 0)
- return (EINVAL);
- break;
- case S76_CTRL_KBC:
- if (val >= (1 << 24) || val < 0)
- return (EINVAL);
- break;
- default:
- break;
+ if (req->newptr == NULL) {
+ /*
+ * ACPI will not notify us if battary thresholds changes
+ * outside this module. Therefore, always fetch those values.
+ */
+ if (method != S76_CTRL_BCTL && method != S76_CTRL_BCTH)
+ return (error);
+ update = false;
+ } else {
+ /* Input validation */
+ switch (method) {
+ case S76_CTRL_KBB:
+ if (val > UINT8_MAX || val < 0)
+ return (EINVAL);
+ break;
+ case S76_CTRL_KBC:
+ if (val >= (1 << 24) || val < 0)
+ return (EINVAL);
+ break;
+ case S76_CTRL_BCTL:
+ if ((ctrl_cmp = acpi_system76_ctrl_map(sc, S76_CTRL_BCTH)) == NULL)
+ return (EINVAL);
+ if (val > 100 || val < 0 || val >= ctrl_cmp->val)
+ return (EINVAL);
+ break;
+ case S76_CTRL_BCTH:
+ if ((ctrl_cmp = acpi_system76_ctrl_map(sc, S76_CTRL_BCTL)) == NULL)
+ return (EINVAL);
+ if (val > 100 || val < 0 || val <= ctrl_cmp->val)
+ return (EINVAL);
+ break;
+ }
+ ctrl->val = val;
+ update = true;
}
- ctrl->val = val;
-
ACPI_SERIAL_BEGIN(system76);
- error = acpi_system76_update(sc, method, true);
+ error = acpi_system76_update(sc, method, update);
ACPI_SERIAL_END(system76);
return (error);
}