git: c6db719a548f - main - asmc: add sleep indicator LED control via sysctl

From: Abdelkader Boudih <seuros_at_FreeBSD.org>
Date: Sun, 06 Sep 2026 19:48:29 UTC
The branch main has been updated by seuros:

URL: https://cgit.FreeBSD.org/src/commit/?id=c6db719a548ff6d49564c68ef52c2cbe02b7db15

commit c6db719a548ff6d49564c68ef52c2cbe02b7db15
Author:     Abdelkader Boudih <seuros@FreeBSD.org>
AuthorDate: 2026-09-06 17:53:34 +0000
Commit:     Abdelkader Boudih <seuros@FreeBSD.org>
CommitDate: 2026-09-06 19:47:44 +0000

    asmc: add sleep indicator LED control via sysctl
    
    Add dev.asmc.0.sil sysctl to control the SIL LED via SMC keys
    MSLD (duty/brightness) and MSLS (state latch, must be set
    before re-enabling).
    
    MFC After: 1 week
    
    Reviewed by:    adrian
    Differential Revision:  https://reviews.freebsd.org/D58865
---
 sys/dev/asmc/asmc.c    | 45 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/asmc/asmcvar.h | 15 +++++++++++++--
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index 80412b9c8daf..4eaa3bf06252 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -126,6 +126,7 @@ static int 	asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS);
 static int 	asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS);
 static int 	asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS);
 static int	asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS);
+static int	asmc_sil_sysctl(SYSCTL_HANDLER_ARGS);
 
 static int	asmc_key_getinfo(device_t, const char *, uint8_t *, char *);
 
@@ -939,6 +940,16 @@ asmc_init(device_t dev)
 		    "Auto power-on after AC power loss (0=off, 1=on)");
 	}
 
+	/* Sleep Indicator LED (SIL) control via MSLD/MSLS keys. */
+	if (asmc_key_read(dev, ASMC_KEY_MSLD, buf, 1) == 0) {
+		SYSCTL_ADD_PROC(sysctlctx,
+		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+		    OID_AUTO, "sil",
+		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+		    dev, 0, asmc_sil_sysctl, "I",
+		    "Sleep indicator LED (0=off, 1=on)");
+	}
+
 	sc->sc_nfan = asmc_fan_count(dev);
 	if (sc->sc_nfan > ASMC_MAXFANS) {
 		device_printf(dev,
@@ -2538,6 +2549,40 @@ asmc_aupo_sysctl(SYSCTL_HANDLER_ARGS)
 	return (0);
 }
 
+/* Sleep Indicator LED (SIL) control; see ASMC_KEY_MSLD/MSLS in asmcvar.h. */
+static int
+asmc_sil_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	device_t dev = (device_t)arg1;
+	uint8_t msld;
+	int val, error;
+
+	if (asmc_key_read(dev, ASMC_KEY_MSLD, &msld, 1) != 0)
+		return (EIO);
+
+	/* MSLD 0xff means off, anything else means on */
+	val = (msld != 0xff) ? 1 : 0;
+	error = sysctl_handle_int(oidp, &val, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+
+	if (val != 0) {
+		/* Turn on: unlatch MSLS first, then set MSLD duty */
+		uint8_t msls = 0x01;
+		if (asmc_key_write(dev, ASMC_KEY_MSLS, &msls, 1) != 0)
+			return (EIO);
+		msld = 0x01;
+	} else {
+		/* Turn off: just set MSLD to 0xff */
+		msld = 0xff;
+	}
+
+	if (asmc_key_write(dev, ASMC_KEY_MSLD, &msld, 1) != 0)
+		return (EIO);
+
+	return (0);
+}
+
 static int
 asmc_backlight_update_status(device_t dev, struct backlight_props *props)
 {
diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h
index 940119e59774..76c17f4ba2dd 100644
--- a/sys/dev/asmc/asmcvar.h
+++ b/sys/dev/asmc/asmcvar.h
@@ -175,9 +175,20 @@ struct asmc_softc {
 #define ASMC_KEY_FANSAFESPEED0	"F0Sf"	/* RO; 2 bytes */
 
 /*
- * Clamshell.
+ * Sleep Indicator LED (SIL).
+ *
+ * MSLD controls the duty cycle of the front-panel sleep indicator LED.
+ *   0x00 = LED at idle brightness, 0xff = LED fully off.
+ * MSLS is the SIL state latch — must be written to 0x01 before MSLD
+ *   can re-enable the LED after it has been turned off.
+ *
+ * Protocol:   OFF = write MSLD 0xff
+ *             ON  = write MSLS 0x01, then write MSLD 0x01
+ *
+ * Present on all Intel Macs with a sleep indicator (laptops + Mac Mini).
  */
-#define ASMC_KEY_CLAMSHELL	"MSLD"	/* RO; 1 byte */
+#define ASMC_KEY_MSLD		"MSLD"	/* RW; 1 byte, SIL duty */
+#define ASMC_KEY_MSLS		"MSLS"	/* RW; 1 byte, SIL state latch */
 
 /*
  * Auto power-on after AC power loss (AUPO).