git: f134662a1a57 - main - acpi_asus_wmi(4): Improve keyboard backlight support.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 17 Mar 2025 15:46:58 UTC
The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=f134662a1a5726d78880385002a03b8fe68805f6 commit f134662a1a5726d78880385002a03b8fe68805f6 Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2025-03-17 15:45:14 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2025-03-17 15:45:14 +0000 acpi_asus_wmi(4): Improve keyboard backlight support. - Fix maximal keyboard backlight level, Although Linux source code comment says that backlight level is encoded in 3 bits of data, actual code limits maximum level to 3. - Add backlight(9) support for keyboard - Turn off/on keyboard backlight on suspend/resume Sponsored by: Future Crew LLC MFC after: 1 month Reviewed by: mav Differential Revision: https://reviews.freebsd.org/D48983 --- share/man/man4/acpi_asus_wmi.4 | 10 ++- sys/dev/acpi_support/acpi_asus_wmi.c | 136 +++++++++++++++++++++++++++++++- sys/modules/acpi/acpi_asus_wmi/Makefile | 2 +- 3 files changed, 142 insertions(+), 6 deletions(-) diff --git a/share/man/man4/acpi_asus_wmi.4 b/share/man/man4/acpi_asus_wmi.4 index 7d6aeaca948b..721b73833484 100644 --- a/share/man/man4/acpi_asus_wmi.4 +++ b/share/man/man4/acpi_asus_wmi.4 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 2, 2012 +.Dd March 25, 2024 .Dt ACPI_ASUS_WMI 4 .Os .Sh NAME @@ -72,11 +72,19 @@ Number of other variables under the same sysctl branch are model-specific. Defaults for these variables can be set in .Xr sysctl.conf 5 , which is parsed at boot-time. +.Sh FILES +.Bl -tag -width "/dev/backlight/acpi_asus_wmi0" -compact +.It Pa /dev/backlight/acpi_asus_wmi0 +Keyboard +.Xr backlight 8 +device node. +.El .Sh SEE ALSO .Xr acpi 4 , .Xr acpi_asus 4 , .Xr acpi_video 4 , .Xr sysctl.conf 5 , +.Xr backlight 8 , .Xr devd 8 , .Xr sysctl 8 .Sh HISTORY diff --git a/sys/dev/acpi_support/acpi_asus_wmi.c b/sys/dev/acpi_support/acpi_asus_wmi.c index 80beee2fea7f..968de5fe5e87 100644 --- a/sys/dev/acpi_support/acpi_asus_wmi.c +++ b/sys/dev/acpi_support/acpi_asus_wmi.c @@ -42,6 +42,9 @@ #include <dev/acpica/acpivar.h> #include "acpi_wmi_if.h" +#include <dev/backlight/backlight.h> +#include "backlight_if.h" + #ifdef EVDEV_SUPPORT #include <dev/evdev/input.h> #include <dev/evdev/evdev.h> @@ -117,6 +120,8 @@ struct acpi_asus_wmi_softc { struct sysctl_oid *sysctl_tree; int dsts_id; int handle_keys; + struct cdev *kbd_bkl; + uint32_t kbd_bkl_level; #ifdef EVDEV_SUPPORT struct evdev_dev *evdev; #endif @@ -345,6 +350,8 @@ static void acpi_asus_wmi_identify(driver_t *driver, device_t parent); static int acpi_asus_wmi_probe(device_t dev); static int acpi_asus_wmi_attach(device_t dev); static int acpi_asus_wmi_detach(device_t dev); +static int acpi_asus_wmi_suspend(device_t dev); +static int acpi_asus_wmi_resume(device_t dev); static int acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id, @@ -357,12 +364,26 @@ static int acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc, static int acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc, UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval); static void acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context); +static int acpi_asus_wmi_backlight_update_status(device_t dev, + struct backlight_props *props); +static int acpi_asus_wmi_backlight_get_status(device_t dev, + struct backlight_props *props); +static int acpi_asus_wmi_backlight_get_info(device_t dev, + struct backlight_info *info); static device_method_t acpi_asus_wmi_methods[] = { + /* Device interface */ DEVMETHOD(device_identify, acpi_asus_wmi_identify), DEVMETHOD(device_probe, acpi_asus_wmi_probe), DEVMETHOD(device_attach, acpi_asus_wmi_attach), DEVMETHOD(device_detach, acpi_asus_wmi_detach), + DEVMETHOD(device_suspend, acpi_asus_wmi_suspend), + DEVMETHOD(device_resume, acpi_asus_wmi_resume), + + /* Backlight interface */ + DEVMETHOD(backlight_update_status, acpi_asus_wmi_backlight_update_status), + DEVMETHOD(backlight_get_status, acpi_asus_wmi_backlight_get_status), + DEVMETHOD(backlight_get_info, acpi_asus_wmi_backlight_get_info), DEVMETHOD_END }; @@ -376,10 +397,35 @@ static driver_t acpi_asus_wmi_driver = { DRIVER_MODULE(acpi_asus_wmi, acpi_wmi, acpi_asus_wmi_driver, 0, 0); MODULE_DEPEND(acpi_asus_wmi, acpi_wmi, 1, 1, 1); MODULE_DEPEND(acpi_asus_wmi, acpi, 1, 1, 1); +MODULE_DEPEND(acpi_asus_wmi, backlight, 1, 1, 1); #ifdef EVDEV_SUPPORT MODULE_DEPEND(acpi_asus_wmi, evdev, 1, 1, 1); #endif +static const uint32_t acpi_asus_wmi_backlight_levels[] = { 0, 33, 66, 100 }; + +static inline uint32_t +devstate_to_kbd_bkl_level(UINT32 val) +{ + return (acpi_asus_wmi_backlight_levels[val & 0x3]); +} + +static inline UINT32 +kbd_bkl_level_to_devstate(uint32_t bkl) +{ + UINT32 val; + int i; + + for (i = 0; i < nitems(acpi_asus_wmi_backlight_levels); i++) { + if (bkl < acpi_asus_wmi_backlight_levels[i]) + break; + } + val = (i - 1) & 0x3; + if (val != 0) + val |= 0x80; + return(val); +} + static void acpi_asus_wmi_identify(driver_t *driver, device_t parent) { @@ -418,6 +464,7 @@ acpi_asus_wmi_attach(device_t dev) struct acpi_asus_wmi_softc *sc; UINT32 val; int dev_id, i; + bool have_kbd_bkl = false; ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); @@ -502,6 +549,10 @@ next: if (val == 0) continue; break; + case ASUS_WMI_DEVID_KBD_BACKLIGHT: + sc->kbd_bkl_level = devstate_to_kbd_bkl_level(val); + have_kbd_bkl = true; + /* FALLTHROUGH */ default: if ((val & ASUS_WMI_DSTS_PRESENCE_BIT) == 0) continue; @@ -541,12 +592,22 @@ next: } if (evdev_register(sc->evdev) != 0) { + device_printf(dev, "Can not register evdev\n"); acpi_asus_wmi_detach(dev); return (ENXIO); } } #endif + if (have_kbd_bkl) { + sc->kbd_bkl = backlight_register("acpi_asus_wmi", dev); + if (sc->kbd_bkl == NULL) { + device_printf(dev, "Can not register backlight\n"); + acpi_asus_wmi_detach(dev); + return (ENXIO); + } + } + return (0); } @@ -557,6 +618,9 @@ acpi_asus_wmi_detach(device_t dev) ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); + if (sc->kbd_bkl != NULL) + backlight_destroy(sc->kbd_bkl); + if (sc->notify_guid) { ACPI_WMI_REMOVE_EVENT_HANDLER(dev, sc->notify_guid); #ifdef EVDEV_SUPPORT @@ -567,6 +631,34 @@ acpi_asus_wmi_detach(device_t dev) return (0); } +static int +acpi_asus_wmi_suspend(device_t dev) +{ + struct acpi_asus_wmi_softc *sc = device_get_softc(dev); + + if (sc->kbd_bkl != NULL) { + ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); + acpi_wpi_asus_set_devstate(sc, + ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, NULL); + } + + return (0); +} + +static int +acpi_asus_wmi_resume(device_t dev) +{ + struct acpi_asus_wmi_softc *sc = device_get_softc(dev); + + if (sc->kbd_bkl != NULL) { + ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); + acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT, + kbd_bkl_level_to_devstate(sc->kbd_bkl_level), NULL); + } + + return (0); +} + static int acpi_asus_wmi_sysctl(SYSCTL_HANDLER_ARGS) { @@ -615,7 +707,7 @@ acpi_asus_wmi_sysctl_get(struct acpi_asus_wmi_softc *sc, int dev_id) val &= ASUS_WMI_DSTS_BRIGHTNESS_MASK; break; case ASUS_WMI_DEVID_KBD_BACKLIGHT: - val &= 0x7; + val &= 0x3; break; default: if (val & ASUS_WMI_DSTS_UNKNOWN_BIT) @@ -636,7 +728,7 @@ acpi_asus_wmi_sysctl_set(struct acpi_asus_wmi_softc *sc, int dev_id, int arg, in switch(dev_id) { case ASUS_WMI_DEVID_KBD_BACKLIGHT: - arg = min(0x7, arg); + arg = min(0x3, arg); if (arg != 0) arg |= 0x80; break; @@ -701,9 +793,9 @@ acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context) if (code == 0xc4 || code == 0xc5) { acpi_wpi_asus_get_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT, &val); - val &= 0x7; + val &= 0x3; if (code == 0xc4) { - if (val < 0x7) + if (val < 0x3) val++; } else if (val > 0) val--; @@ -711,6 +803,7 @@ acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context) val |= 0x80; acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT, val, NULL); + sc->kbd_bkl_level = devstate_to_kbd_bkl_level(val); } /* Touchpad control. */ if (code == 0x6b) { @@ -767,3 +860,38 @@ acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc, return (acpi_asus_wmi_evaluate_method(sc->wmi_dev, ASUS_WMI_METHODID_DEVS, dev_id, ctrl_param, retval)); } + +static int +acpi_asus_wmi_backlight_update_status(device_t dev, struct backlight_props + *props) +{ + struct acpi_asus_wmi_softc *sc = device_get_softc(dev); + + acpi_wpi_asus_set_devstate(sc, ASUS_WMI_DEVID_KBD_BACKLIGHT, + kbd_bkl_level_to_devstate(props->brightness), NULL); + sc->kbd_bkl_level = props->brightness; + + return (0); +} + +static int +acpi_asus_wmi_backlight_get_status(device_t dev, struct backlight_props *props) +{ + struct acpi_asus_wmi_softc *sc = device_get_softc(dev); + + props->brightness = sc->kbd_bkl_level; + props->nlevels = nitems(acpi_asus_wmi_backlight_levels); + memcpy(props->levels, acpi_asus_wmi_backlight_levels, + sizeof(acpi_asus_wmi_backlight_levels)); + + return (0); +} + +static int +acpi_asus_wmi_backlight_get_info(device_t dev, struct backlight_info *info) +{ + info->type = BACKLIGHT_TYPE_KEYBOARD; + strlcpy(info->name, "ASUS Keyboard", BACKLIGHTMAXNAMELENGTH); + + return (0); +} diff --git a/sys/modules/acpi/acpi_asus_wmi/Makefile b/sys/modules/acpi/acpi_asus_wmi/Makefile index 552eef2ac479..3067bec099f5 100644 --- a/sys/modules/acpi/acpi_asus_wmi/Makefile +++ b/sys/modules/acpi/acpi_asus_wmi/Makefile @@ -3,6 +3,6 @@ KMOD= acpi_asus_wmi CFLAGS+=-I${SRCTOP}/sys/dev/acpi_support SRCS= acpi_asus_wmi.c opt_acpi.h acpi_if.h acpi_wmi_if.h device_if.h bus_if.h -SRCS+= opt_evdev.h +SRCS+= opt_evdev.h backlight_if.h .include <bsd.kmod.mk>