diff options
Diffstat (limited to 'sys/dev/acpi_support')
| -rw-r--r-- | sys/dev/acpi_support/acpi_asus.c | 2 | ||||
| -rw-r--r-- | sys/dev/acpi_support/acpi_ibm.c | 7 | ||||
| -rw-r--r-- | sys/dev/acpi_support/acpi_panasonic.c | 36 | ||||
| -rw-r--r-- | sys/dev/acpi_support/acpi_system76.c | 592 |
4 files changed, 635 insertions, 2 deletions
diff --git a/sys/dev/acpi_support/acpi_asus.c b/sys/dev/acpi_support/acpi_asus.c index b9ba6650d2b7..975d7f93554a 100644 --- a/sys/dev/acpi_support/acpi_asus.c +++ b/sys/dev/acpi_support/acpi_asus.c @@ -517,7 +517,7 @@ static device_method_t acpi_asus_methods[] = { DEVMETHOD(device_probe, acpi_asus_probe), DEVMETHOD(device_attach, acpi_asus_attach), DEVMETHOD(device_detach, acpi_asus_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t acpi_asus_driver = { diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c index f895d48bb6d0..1221384e7d8a 100644 --- a/sys/dev/acpi_support/acpi_ibm.c +++ b/sys/dev/acpi_support/acpi_ibm.c @@ -1447,8 +1447,13 @@ acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg) ACPI_SERIAL_BEGIN(ibm); switch (arg) { + /* + * XXX "Suspend-to-RAM" here is as opposed to suspend-to-disk, but it is + * fine if our suspend sleep state transition request puts us in s2idle + * instead of suspend-to-RAM. + */ case IBM_EVENT_SUSPEND_TO_RAM: - power_pm_suspend(POWER_SLEEP_STATE_SUSPEND); + power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND); break; case IBM_EVENT_BLUETOOTH: diff --git a/sys/dev/acpi_support/acpi_panasonic.c b/sys/dev/acpi_support/acpi_panasonic.c index 67d51ea9bc1f..8fea47ee45e8 100644 --- a/sys/dev/acpi_support/acpi_panasonic.c +++ b/sys/dev/acpi_support/acpi_panasonic.c @@ -80,6 +80,8 @@ static int acpi_panasonic_probe(device_t dev); static int acpi_panasonic_attach(device_t dev); static int acpi_panasonic_detach(device_t dev); static int acpi_panasonic_shutdown(device_t dev); +static int acpi_panasonic_resume(device_t dev); +static void acpi_panasonic_clear_rfkill(device_t dev); static int acpi_panasonic_sysctl(SYSCTL_HANDLER_ARGS); static UINT64 acpi_panasonic_sinf(ACPI_HANDLE h, UINT64 index); static void acpi_panasonic_sset(ACPI_HANDLE h, UINT64 index, @@ -116,6 +118,7 @@ static device_method_t acpi_panasonic_methods[] = { DEVMETHOD(device_attach, acpi_panasonic_attach), DEVMETHOD(device_detach, acpi_panasonic_detach), DEVMETHOD(device_shutdown, acpi_panasonic_shutdown), + DEVMETHOD(device_resume, acpi_panasonic_resume), DEVMETHOD_END }; @@ -172,6 +175,8 @@ acpi_panasonic_attach(device_t dev) CTLFLAG_MPSAFE, sc, i, acpi_panasonic_sysctl, "I", ""); } + acpi_panasonic_clear_rfkill(dev); + #if 0 /* Activate hotkeys */ status = AcpiEvaluateObject(sc->handle, "", NULL, NULL); @@ -233,6 +238,37 @@ acpi_panasonic_shutdown(device_t dev) } static int +acpi_panasonic_resume(device_t dev) +{ + + acpi_panasonic_clear_rfkill(dev); + return (0); +} + +static void +acpi_panasonic_clear_rfkill(device_t dev) +{ + ACPI_HANDLE wlsw_handle; + ACPI_STATUS status; + + /* + * Call WLSW.SHRF to clear wireless RF_KILL on models that have it. + * On FZ-Y1 and similar models, the EC latches RF_KILL on shutdown + * and suspend, causing the wireless card to boot with hard block + * enabled. The SHRF method sets the EC state to deassert RF_KILL + * GPIO on mini-PCIe pin 20 via SMI (ASRV call with function + * 0x0F/0x03). + */ + status = AcpiGetHandle(NULL, "\\_SB.WLSW", &wlsw_handle); + if (ACPI_SUCCESS(status)) { + status = AcpiEvaluateObject(wlsw_handle, "SHRF", NULL, NULL); + if (ACPI_FAILURE(status) && bootverbose) + device_printf(dev, "WLSW.SHRF failed: %s\n", + AcpiFormatException(status)); + } +} + +static int acpi_panasonic_sysctl(SYSCTL_HANDLER_ARGS) { struct acpi_panasonic_softc *sc; diff --git a/sys/dev/acpi_support/acpi_system76.c b/sys/dev/acpi_support/acpi_system76.c new file mode 100644 index 000000000000..1ba287ccb85d --- /dev/null +++ b/sys/dev/acpi_support/acpi_system76.c @@ -0,0 +1,592 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_acpi.h" + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/sysctl.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> + +#include <dev/acpica/acpivar.h> +#include <dev/backlight/backlight.h> + +#include "backlight_if.h" + +#define _COMPONENT ACPI_OEM +ACPI_MODULE_NAME("system76") + +static char *system76_ids[] = { "17761776", NULL }; +ACPI_SERIAL_DECL(system76, "System76 ACPI management"); + +struct acpi_ctrl { + int val; + bool exists; +}; + +struct acpi_system76_softc { + device_t dev; + ACPI_HANDLE handle; + + struct acpi_ctrl kbb, /* S76_CTRL_KBB */ + kbc, /* S76_CTRL_KBC */ + bctl, /* S76_CTRL_BCTL */ + bcth; /* S76_CTRL_BCTH */ + + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + struct cdev *kbb_bkl; + uint8_t backlight_level; +}; + +static int acpi_system76_probe(device_t); +static int acpi_system76_attach(device_t); +static int acpi_system76_detach(device_t); +static int acpi_system76_suspend(device_t); +static int acpi_system76_resume(device_t); +static int acpi_system76_shutdown(device_t); +static void acpi_system76_init(struct acpi_system76_softc *); +static struct acpi_ctrl * + acpi_system76_ctrl_map(struct acpi_system76_softc *, int); +static int acpi_system76_update(struct acpi_system76_softc *, int, bool); +static int acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS); +static void acpi_system76_notify_handler(ACPI_HANDLE, uint32_t, void *); +static void acpi_system76_check(struct acpi_system76_softc *); +static int acpi_system76_backlight_update_status(device_t dev, + struct backlight_props *props); +static int acpi_system76_backlight_get_status(device_t dev, + struct backlight_props *props); +static int acpi_system76_backlight_get_info(device_t dev, + struct backlight_info *info); + +/* methods */ +enum { + S76_CTRL_KBB = 1, /* Keyboard Brightness */ + S76_CTRL_KBC = 2, /* Keyboard Color */ + S76_CTRL_BCTL = 3, /* Battery Charging Start Thresholds */ + S76_CTRL_BCTH = 4, /* Battery 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; +}; + +static const struct s76_ctrl_table s76_sysctl_table[] = { + [S76_CTRL_KBB] = { + .name = "keyboard_backlight", + .get_method = S76_CTRL_GKBB, + .set_method = S76_CTRL_SKBB, + .desc = "Keyboard Backlight", + }, + [S76_CTRL_KBC] = { + .name = "keyboard_color", + .get_method = S76_CTRL_GKBC, + .set_method = S76_CTRL_SKBC, + .desc = "Keyboard Color", + }, + [S76_CTRL_BCTL] = { + .name = "battery_charge_min", + .get_method = S76_CTRL_GBCT, + .set_method = S76_CTRL_SBCT, + .desc = "Start charging the battery when this threshold is reached (percentage)", + }, + [S76_CTRL_BCTH] = { + .name = "battery_charge_max", + .get_method = S76_CTRL_GBCT, + .set_method = S76_CTRL_SBCT, + .desc = "Stop charging the battery when this threshold is reached (percentage)", + }, +}; + +static device_method_t acpi_system76_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, acpi_system76_probe), + DEVMETHOD(device_attach, acpi_system76_attach), + DEVMETHOD(device_detach, acpi_system76_detach), + DEVMETHOD(device_suspend, acpi_system76_suspend), + DEVMETHOD(device_resume, acpi_system76_resume), + DEVMETHOD(device_shutdown, acpi_system76_shutdown), + + /* Backlight interface */ + DEVMETHOD(backlight_update_status, acpi_system76_backlight_update_status), + DEVMETHOD(backlight_get_status, acpi_system76_backlight_get_status), + DEVMETHOD(backlight_get_info, acpi_system76_backlight_get_info), + + DEVMETHOD_END +}; + +/* Notify event */ +#define ACPI_NOTIFY_BACKLIGHT_CHANGED 0x80 +#define ACPI_NOTIFY_COLOR_TOGGLE 0x81 +#define ACPI_NOTIFY_COLOR_DOWN 0x82 +#define ACPI_NOTIFY_COLOR_UP 0x83 +#define ACPI_NOTIFY_COLOR_CHANGED 0x84 + +static driver_t acpi_system76_driver = { + "acpi_system76", + acpi_system76_methods, + sizeof(struct acpi_system76_softc) +}; + +static const uint32_t acpi_system76_backlight_levels[] = { + 0, 6, 12, 18, 24, 30, 36, 42, + 48, 54, 60, 66, 72, 78, 84, 100 +}; + +static inline uint32_t +devstate_to_backlight(uint32_t val) +{ + return (acpi_system76_backlight_levels[val >> 4 & 0xf]); +} + +static inline uint32_t +backlight_to_devstate(uint32_t bkl) +{ + int i; + uint32_t val; + + for (i = 0; i < nitems(acpi_system76_backlight_levels); i++) { + if (bkl < acpi_system76_backlight_levels[i]) + break; + } + val = (i - 1) * 16; + if (val > 224) + val = 255; + return (val); +} + +/* + * Returns corresponding acpi_ctrl of softc from method + */ +static struct acpi_ctrl * +acpi_system76_ctrl_map(struct acpi_system76_softc *sc, int method) +{ + + switch (method) { + case S76_CTRL_KBB: + return (&sc->kbb); + case S76_CTRL_KBC: + return (&sc->kbc); + 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); + } +} + +static int +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); + + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + return (EINVAL); + + 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); + return (status); + } + + return (0); +} + +static void +acpi_system76_notify_update(void *arg) +{ + struct acpi_system76_softc *sc; + int method; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = (struct acpi_system76_softc *)device_get_softc(arg); + + ACPI_SERIAL_BEGIN(system76); + 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); + + if (sc->kbb_bkl != NULL) + sc->backlight_level = devstate_to_backlight(sc->kbb.val); +} + +static void +acpi_system76_check(struct acpi_system76_softc *sc) +{ + struct acpi_ctrl *ctrl; + int method; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + ACPI_SERIAL_ASSERT(system76); + + for (method = 1; method < S76_CTRL_MAX; method++) { + 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; + device_printf(sc->dev, "Driver can't control %s\n", + s76_sysctl_table[method].desc); + } else { + ctrl->exists = true; + acpi_system76_update(sc, method, false); + } + } +} + +static void +acpi_system76_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *ctx) +{ + + ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); + + switch (notify) { + case ACPI_NOTIFY_BACKLIGHT_CHANGED: + case ACPI_NOTIFY_COLOR_TOGGLE: + case ACPI_NOTIFY_COLOR_DOWN: + case ACPI_NOTIFY_COLOR_UP: + case ACPI_NOTIFY_COLOR_CHANGED: + AcpiOsExecute(OSL_NOTIFY_HANDLER, + acpi_system76_notify_update, ctx); + break; + default: + break; + } +} + +static int +acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS) +{ + struct acpi_ctrl *ctrl, *ctrl_cmp; + struct acpi_system76_softc *sc; + int val, method, error; + bool update; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = (struct acpi_system76_softc *)oidp->oid_arg1; + method = oidp->oid_arg2; + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + return (EINVAL); + + val = ctrl->val; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0) { + device_printf(sc->dev, "Driver query failed\n"); + return (error); + } + + if (req->newptr == NULL) { + /* + * ACPI will not notify us if battery 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); + if (sc->kbb_bkl != NULL) + sc->backlight_level = devstate_to_backlight(val); + 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; + } + + ACPI_SERIAL_BEGIN(system76); + error = acpi_system76_update(sc, method, update); + ACPI_SERIAL_END(system76); + return (error); +} + +static void +acpi_system76_init(struct acpi_system76_softc *sc) +{ + struct acpi_softc *acpi_sc; + struct acpi_ctrl *ctrl; + uint32_t method; + + ACPI_SERIAL_ASSERT(system76); + + acpi_system76_check(sc); + acpi_sc = acpi_device_get_parent_softc(sc->dev); + sysctl_ctx_init(&sc->sysctl_ctx); + sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, + SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "s76", + CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "system76 control"); + + for (method = 1; method < S76_CTRL_MAX; method++) { + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + continue; + + if (!ctrl->exists) + continue; + + if (method == S76_CTRL_KBB) { + sc->kbb_bkl = backlight_register("system76_keyboard", sc->dev); + if (sc->kbb_bkl == NULL) + device_printf(sc->dev, "Can not register backlight\n"); + else + sc->backlight_level = devstate_to_backlight(sc->kbb.val); + } + + SYSCTL_ADD_PROC(&sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, s76_sysctl_table[method].name, + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, + sc, method, acpi_system76_sysctl_handler, "IU", s76_sysctl_table[method].desc); + } +} + +static int +acpi_system76_backlight_update_status(device_t dev, struct backlight_props + *props) +{ + struct acpi_system76_softc *sc; + + sc = device_get_softc(dev); + if (sc->kbb.val != backlight_to_devstate(props->brightness)) { + sc->kbb.val = backlight_to_devstate(props->brightness); + acpi_system76_update(sc, S76_CTRL_KBB, true); + } + sc->backlight_level = props->brightness; + + return (0); +} + +static int +acpi_system76_backlight_get_status(device_t dev, struct backlight_props *props) +{ + struct acpi_system76_softc *sc; + + sc = device_get_softc(dev); + props->brightness = sc->backlight_level; + props->nlevels = nitems(acpi_system76_backlight_levels); + memcpy(props->levels, acpi_system76_backlight_levels, + sizeof(acpi_system76_backlight_levels)); + + return (0); +} + +static int +acpi_system76_backlight_get_info(device_t dev, struct backlight_info *info) +{ + info->type = BACKLIGHT_TYPE_KEYBOARD; + strlcpy(info->name, "System76 Keyboard", BACKLIGHTMAXNAMELENGTH); + + return (0); +} + +static int +acpi_system76_attach(device_t dev) +{ + struct acpi_system76_softc *sc; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = device_get_softc(dev); + sc->dev = dev; + sc->handle = acpi_get_handle(dev); + + AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, + acpi_system76_notify_handler, dev); + + ACPI_SERIAL_BEGIN(system76); + acpi_system76_init(sc); + ACPI_SERIAL_END(system76); + + return (0); +} + +static int +acpi_system76_detach(device_t dev) +{ + struct acpi_system76_softc *sc; + + sc = device_get_softc(dev); + if (sysctl_ctx_free(&sc->sysctl_ctx) != 0) + return (EBUSY); + + AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY, + acpi_system76_notify_handler); + + if (sc->kbb_bkl != NULL) + backlight_destroy(sc->kbb_bkl); + + return (0); +} + +static int +acpi_system76_suspend(device_t dev) +{ + struct acpi_system76_softc *sc; + struct acpi_ctrl *ctrl; + + sc = device_get_softc(dev); + if ((ctrl = acpi_system76_ctrl_map(sc, S76_CTRL_KBB)) != NULL) { + ctrl->val = 0; + acpi_system76_update(sc, S76_CTRL_KBB, true); + } + + return (0); +} + +static int +acpi_system76_resume(device_t dev) +{ + struct acpi_system76_softc *sc; + struct acpi_ctrl *ctrl; + + sc = device_get_softc(dev); + if ((ctrl = acpi_system76_ctrl_map(sc, S76_CTRL_KBB)) != NULL) { + ctrl->val = backlight_to_devstate(sc->backlight_level); + acpi_system76_update(sc, S76_CTRL_KBB, true); + } + + return (0); +} + +static int +acpi_system76_shutdown(device_t dev) +{ + return (acpi_system76_detach(dev)); +} + +static int +acpi_system76_probe(device_t dev) +{ + int rv; + + if (acpi_disabled("system76") || device_get_unit(dev) > 1) + return (ENXIO); + rv = ACPI_ID_PROBE(device_get_parent(dev), dev, system76_ids, NULL); + if (rv > 0) { + return (rv); + } + + return (BUS_PROBE_VENDOR); +} + +DRIVER_MODULE(acpi_system76, acpi, acpi_system76_driver, 0, 0); +MODULE_VERSION(acpi_system76, 1); +MODULE_DEPEND(acpi_system76, acpi, 1, 1, 1); +MODULE_DEPEND(acpi_system76, backlight, 1, 1, 1); |
