1cdad5580SPouria Mousavizadeh Tehrani /*-
2cdad5580SPouria Mousavizadeh Tehrani * SPDX-License-Identifier: BSD-2-Clause
3cdad5580SPouria Mousavizadeh Tehrani *
4cdad5580SPouria Mousavizadeh Tehrani * Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
5cdad5580SPouria Mousavizadeh Tehrani * All rights reserved.
6cdad5580SPouria Mousavizadeh Tehrani *
7cdad5580SPouria Mousavizadeh Tehrani * Redistribution and use in source and binary forms, with or without
8cdad5580SPouria Mousavizadeh Tehrani * modification, are permitted provided that the following conditions
9cdad5580SPouria Mousavizadeh Tehrani * are met:
10cdad5580SPouria Mousavizadeh Tehrani * 1. Redistributions of source code must retain the above copyright
11cdad5580SPouria Mousavizadeh Tehrani * notice, this list of conditions and the following disclaimer.
12cdad5580SPouria Mousavizadeh Tehrani * 2. Redistributions in binary form must reproduce the above copyright
13cdad5580SPouria Mousavizadeh Tehrani * notice, this list of conditions and the following disclaimer in the
14cdad5580SPouria Mousavizadeh Tehrani * documentation and/or other materials provided with the distribution.
15cdad5580SPouria Mousavizadeh Tehrani *
16cdad5580SPouria Mousavizadeh Tehrani * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17cdad5580SPouria Mousavizadeh Tehrani * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18cdad5580SPouria Mousavizadeh Tehrani * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19cdad5580SPouria Mousavizadeh Tehrani * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20cdad5580SPouria Mousavizadeh Tehrani * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21cdad5580SPouria Mousavizadeh Tehrani * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22cdad5580SPouria Mousavizadeh Tehrani * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23cdad5580SPouria Mousavizadeh Tehrani * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24cdad5580SPouria Mousavizadeh Tehrani * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25cdad5580SPouria Mousavizadeh Tehrani * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26cdad5580SPouria Mousavizadeh Tehrani * SUCH DAMAGE.
27cdad5580SPouria Mousavizadeh Tehrani */
28cdad5580SPouria Mousavizadeh Tehrani
29fa4f625eSPouria Mousavizadeh Tehrani #include "opt_acpi.h"
30*f9146417SPouria Mousavizadeh Tehrani
31cdad5580SPouria Mousavizadeh Tehrani #include <sys/param.h>
32cdad5580SPouria Mousavizadeh Tehrani #include <sys/bus.h>
33*f9146417SPouria Mousavizadeh Tehrani #include <sys/kernel.h>
34cdad5580SPouria Mousavizadeh Tehrani #include <sys/module.h>
35*f9146417SPouria Mousavizadeh Tehrani #include <sys/sysctl.h>
36cdad5580SPouria Mousavizadeh Tehrani
37cdad5580SPouria Mousavizadeh Tehrani #include <contrib/dev/acpica/include/acpi.h>
38fa4f625eSPouria Mousavizadeh Tehrani #include <contrib/dev/acpica/include/accommon.h>
39cdad5580SPouria Mousavizadeh Tehrani
40cdad5580SPouria Mousavizadeh Tehrani #include <dev/acpica/acpivar.h>
41105869a2SPouria Mousavizadeh Tehrani #include <dev/backlight/backlight.h>
42*f9146417SPouria Mousavizadeh Tehrani
43105869a2SPouria Mousavizadeh Tehrani #include "backlight_if.h"
44105869a2SPouria Mousavizadeh Tehrani
45cdad5580SPouria Mousavizadeh Tehrani #define _COMPONENT ACPI_OEM
46cdad5580SPouria Mousavizadeh Tehrani ACPI_MODULE_NAME("system76")
47cdad5580SPouria Mousavizadeh Tehrani
48cdad5580SPouria Mousavizadeh Tehrani static char *system76_ids[] = { "17761776", NULL };
49cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_DECL(system76, "System76 ACPI management");
50cdad5580SPouria Mousavizadeh Tehrani
51cdad5580SPouria Mousavizadeh Tehrani struct acpi_ctrl {
52cdad5580SPouria Mousavizadeh Tehrani int val;
53cdad5580SPouria Mousavizadeh Tehrani bool exists;
54cdad5580SPouria Mousavizadeh Tehrani };
55cdad5580SPouria Mousavizadeh Tehrani
56cdad5580SPouria Mousavizadeh Tehrani struct acpi_system76_softc {
57cdad5580SPouria Mousavizadeh Tehrani device_t dev;
58cdad5580SPouria Mousavizadeh Tehrani ACPI_HANDLE handle;
59cdad5580SPouria Mousavizadeh Tehrani
60cdad5580SPouria Mousavizadeh Tehrani struct acpi_ctrl kbb, /* S76_CTRL_KBB */
61f87ba452SPouria Mousavizadeh Tehrani kbc, /* S76_CTRL_KBC */
62f87ba452SPouria Mousavizadeh Tehrani bctl, /* S76_CTRL_BCTL */
63f87ba452SPouria Mousavizadeh Tehrani bcth; /* S76_CTRL_BCTH */
64cdad5580SPouria Mousavizadeh Tehrani
65cdad5580SPouria Mousavizadeh Tehrani struct sysctl_ctx_list sysctl_ctx;
66cdad5580SPouria Mousavizadeh Tehrani struct sysctl_oid *sysctl_tree;
67105869a2SPouria Mousavizadeh Tehrani struct cdev *kbb_bkl;
68105869a2SPouria Mousavizadeh Tehrani uint8_t backlight_level;
69cdad5580SPouria Mousavizadeh Tehrani };
70cdad5580SPouria Mousavizadeh Tehrani
71cdad5580SPouria Mousavizadeh Tehrani static int acpi_system76_probe(device_t);
72cdad5580SPouria Mousavizadeh Tehrani static int acpi_system76_attach(device_t);
73cdad5580SPouria Mousavizadeh Tehrani static int acpi_system76_detach(device_t);
74105869a2SPouria Mousavizadeh Tehrani static int acpi_system76_suspend(device_t);
75105869a2SPouria Mousavizadeh Tehrani static int acpi_system76_resume(device_t);
76105869a2SPouria Mousavizadeh Tehrani static int acpi_system76_shutdown(device_t);
77cdad5580SPouria Mousavizadeh Tehrani static void acpi_system76_init(struct acpi_system76_softc *);
78cdad5580SPouria Mousavizadeh Tehrani static struct acpi_ctrl *
79cdad5580SPouria Mousavizadeh Tehrani acpi_system76_ctrl_map(struct acpi_system76_softc *, int);
80cdad5580SPouria Mousavizadeh Tehrani static int acpi_system76_update(struct acpi_system76_softc *, int, bool);
81cdad5580SPouria Mousavizadeh Tehrani static int acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS);
82cdad5580SPouria Mousavizadeh Tehrani static void acpi_system76_notify_handler(ACPI_HANDLE, uint32_t, void *);
83cdad5580SPouria Mousavizadeh Tehrani static void acpi_system76_check(struct acpi_system76_softc *);
84105869a2SPouria Mousavizadeh Tehrani static int acpi_system76_backlight_update_status(device_t dev,
85105869a2SPouria Mousavizadeh Tehrani struct backlight_props *props);
86105869a2SPouria Mousavizadeh Tehrani static int acpi_system76_backlight_get_status(device_t dev,
87105869a2SPouria Mousavizadeh Tehrani struct backlight_props *props);
88105869a2SPouria Mousavizadeh Tehrani static int acpi_system76_backlight_get_info(device_t dev,
89105869a2SPouria Mousavizadeh Tehrani struct backlight_info *info);
90cdad5580SPouria Mousavizadeh Tehrani
91cdad5580SPouria Mousavizadeh Tehrani /* methods */
92f87ba452SPouria Mousavizadeh Tehrani enum {
93f87ba452SPouria Mousavizadeh Tehrani S76_CTRL_KBB = 1, /* Keyboard Brightness */
94f87ba452SPouria Mousavizadeh Tehrani S76_CTRL_KBC = 2, /* Keyboard Color */
95*f9146417SPouria Mousavizadeh Tehrani S76_CTRL_BCTL = 3, /* Battery Charging Start Thresholds */
96*f9146417SPouria Mousavizadeh Tehrani S76_CTRL_BCTH = 4, /* Battery Charging End Thresholds */
97f87ba452SPouria Mousavizadeh Tehrani };
98f87ba452SPouria Mousavizadeh Tehrani #define S76_CTRL_MAX 5
99cdad5580SPouria Mousavizadeh Tehrani
100cdad5580SPouria Mousavizadeh Tehrani struct s76_ctrl_table {
101cdad5580SPouria Mousavizadeh Tehrani char *name;
102cdad5580SPouria Mousavizadeh Tehrani char *get_method;
103cdad5580SPouria Mousavizadeh Tehrani #define S76_CTRL_GKBB "\\_SB.S76D.GKBB"
104cdad5580SPouria Mousavizadeh Tehrani #define S76_CTRL_GKBC "\\_SB.S76D.GKBC"
105f87ba452SPouria Mousavizadeh Tehrani #define S76_CTRL_GBCT "\\_SB.PCI0.LPCB.EC0.GBCT"
106cdad5580SPouria Mousavizadeh Tehrani
107cdad5580SPouria Mousavizadeh Tehrani char *set_method;
108cdad5580SPouria Mousavizadeh Tehrani #define S76_CTRL_SKBB "\\_SB.S76D.SKBB"
109cdad5580SPouria Mousavizadeh Tehrani #define S76_CTRL_SKBC "\\_SB.S76D.SKBC"
110f87ba452SPouria Mousavizadeh Tehrani #define S76_CTRL_SBCT "\\_SB.PCI0.LPCB.EC0.SBCT"
111cdad5580SPouria Mousavizadeh Tehrani
112cdad5580SPouria Mousavizadeh Tehrani char *desc;
113cdad5580SPouria Mousavizadeh Tehrani };
114cdad5580SPouria Mousavizadeh Tehrani
115cdad5580SPouria Mousavizadeh Tehrani static const struct s76_ctrl_table s76_sysctl_table[] = {
116cdad5580SPouria Mousavizadeh Tehrani [S76_CTRL_KBB] = {
117cdad5580SPouria Mousavizadeh Tehrani .name = "keyboard_backlight",
118cdad5580SPouria Mousavizadeh Tehrani .get_method = S76_CTRL_GKBB,
119cdad5580SPouria Mousavizadeh Tehrani .set_method = S76_CTRL_SKBB,
120cdad5580SPouria Mousavizadeh Tehrani .desc = "Keyboard Backlight",
121cdad5580SPouria Mousavizadeh Tehrani },
122cdad5580SPouria Mousavizadeh Tehrani [S76_CTRL_KBC] = {
123cdad5580SPouria Mousavizadeh Tehrani .name = "keyboard_color",
124cdad5580SPouria Mousavizadeh Tehrani .get_method = S76_CTRL_GKBC,
125cdad5580SPouria Mousavizadeh Tehrani .set_method = S76_CTRL_SKBC,
126cdad5580SPouria Mousavizadeh Tehrani .desc = "Keyboard Color",
127cdad5580SPouria Mousavizadeh Tehrani },
128f87ba452SPouria Mousavizadeh Tehrani [S76_CTRL_BCTL] = {
129*f9146417SPouria Mousavizadeh Tehrani .name = "battery_charge_min",
130f87ba452SPouria Mousavizadeh Tehrani .get_method = S76_CTRL_GBCT,
131f87ba452SPouria Mousavizadeh Tehrani .set_method = S76_CTRL_SBCT,
132*f9146417SPouria Mousavizadeh Tehrani .desc = "Start charging the battery when this threshold is reached (percentage)",
133f87ba452SPouria Mousavizadeh Tehrani },
134f87ba452SPouria Mousavizadeh Tehrani [S76_CTRL_BCTH] = {
135*f9146417SPouria Mousavizadeh Tehrani .name = "battery_charge_max",
136f87ba452SPouria Mousavizadeh Tehrani .get_method = S76_CTRL_GBCT,
137f87ba452SPouria Mousavizadeh Tehrani .set_method = S76_CTRL_SBCT,
138*f9146417SPouria Mousavizadeh Tehrani .desc = "Stop charging the battery when this threshold is reached (percentage)",
139f87ba452SPouria Mousavizadeh Tehrani },
140cdad5580SPouria Mousavizadeh Tehrani };
141cdad5580SPouria Mousavizadeh Tehrani
142cdad5580SPouria Mousavizadeh Tehrani static device_method_t acpi_system76_methods[] = {
143105869a2SPouria Mousavizadeh Tehrani /* Device interface */
144cdad5580SPouria Mousavizadeh Tehrani DEVMETHOD(device_probe, acpi_system76_probe),
145cdad5580SPouria Mousavizadeh Tehrani DEVMETHOD(device_attach, acpi_system76_attach),
146cdad5580SPouria Mousavizadeh Tehrani DEVMETHOD(device_detach, acpi_system76_detach),
147105869a2SPouria Mousavizadeh Tehrani DEVMETHOD(device_suspend, acpi_system76_suspend),
148105869a2SPouria Mousavizadeh Tehrani DEVMETHOD(device_resume, acpi_system76_resume),
149105869a2SPouria Mousavizadeh Tehrani DEVMETHOD(device_shutdown, acpi_system76_shutdown),
150105869a2SPouria Mousavizadeh Tehrani
151105869a2SPouria Mousavizadeh Tehrani /* Backlight interface */
152105869a2SPouria Mousavizadeh Tehrani DEVMETHOD(backlight_update_status, acpi_system76_backlight_update_status),
153105869a2SPouria Mousavizadeh Tehrani DEVMETHOD(backlight_get_status, acpi_system76_backlight_get_status),
154105869a2SPouria Mousavizadeh Tehrani DEVMETHOD(backlight_get_info, acpi_system76_backlight_get_info),
155cdad5580SPouria Mousavizadeh Tehrani
156cdad5580SPouria Mousavizadeh Tehrani DEVMETHOD_END
157cdad5580SPouria Mousavizadeh Tehrani };
158cdad5580SPouria Mousavizadeh Tehrani
159cdad5580SPouria Mousavizadeh Tehrani /* Notify event */
160cdad5580SPouria Mousavizadeh Tehrani #define ACPI_NOTIFY_BACKLIGHT_CHANGED 0x80
161cdad5580SPouria Mousavizadeh Tehrani #define ACPI_NOTIFY_COLOR_TOGGLE 0x81
162cdad5580SPouria Mousavizadeh Tehrani #define ACPI_NOTIFY_COLOR_DOWN 0x82
163cdad5580SPouria Mousavizadeh Tehrani #define ACPI_NOTIFY_COLOR_UP 0x83
164cdad5580SPouria Mousavizadeh Tehrani #define ACPI_NOTIFY_COLOR_CHANGED 0x84
165cdad5580SPouria Mousavizadeh Tehrani
166cdad5580SPouria Mousavizadeh Tehrani static driver_t acpi_system76_driver = {
167cdad5580SPouria Mousavizadeh Tehrani "acpi_system76",
168cdad5580SPouria Mousavizadeh Tehrani acpi_system76_methods,
169cdad5580SPouria Mousavizadeh Tehrani sizeof(struct acpi_system76_softc)
170cdad5580SPouria Mousavizadeh Tehrani };
171cdad5580SPouria Mousavizadeh Tehrani
172105869a2SPouria Mousavizadeh Tehrani static const uint32_t acpi_system76_backlight_levels[] = {
173105869a2SPouria Mousavizadeh Tehrani 0, 6, 12, 18, 24, 30, 36, 42,
174105869a2SPouria Mousavizadeh Tehrani 48, 54, 60, 66, 72, 78, 84, 100
175105869a2SPouria Mousavizadeh Tehrani };
176105869a2SPouria Mousavizadeh Tehrani
177105869a2SPouria Mousavizadeh Tehrani static inline uint32_t
devstate_to_backlight(uint32_t val)178105869a2SPouria Mousavizadeh Tehrani devstate_to_backlight(uint32_t val)
179105869a2SPouria Mousavizadeh Tehrani {
180105869a2SPouria Mousavizadeh Tehrani return (acpi_system76_backlight_levels[val >> 4 & 0xf]);
181105869a2SPouria Mousavizadeh Tehrani }
182105869a2SPouria Mousavizadeh Tehrani
183105869a2SPouria Mousavizadeh Tehrani static inline uint32_t
backlight_to_devstate(uint32_t bkl)184105869a2SPouria Mousavizadeh Tehrani backlight_to_devstate(uint32_t bkl)
185105869a2SPouria Mousavizadeh Tehrani {
186105869a2SPouria Mousavizadeh Tehrani int i;
187105869a2SPouria Mousavizadeh Tehrani uint32_t val;
188105869a2SPouria Mousavizadeh Tehrani
189105869a2SPouria Mousavizadeh Tehrani for (i = 0; i < nitems(acpi_system76_backlight_levels); i++) {
190105869a2SPouria Mousavizadeh Tehrani if (bkl < acpi_system76_backlight_levels[i])
191105869a2SPouria Mousavizadeh Tehrani break;
192105869a2SPouria Mousavizadeh Tehrani }
193105869a2SPouria Mousavizadeh Tehrani val = (i - 1) * 16;
194105869a2SPouria Mousavizadeh Tehrani if (val > 224)
195105869a2SPouria Mousavizadeh Tehrani val = 255;
196105869a2SPouria Mousavizadeh Tehrani return (val);
197105869a2SPouria Mousavizadeh Tehrani }
198105869a2SPouria Mousavizadeh Tehrani
199cdad5580SPouria Mousavizadeh Tehrani /*
200cdad5580SPouria Mousavizadeh Tehrani * Returns corresponding acpi_ctrl of softc from method
201cdad5580SPouria Mousavizadeh Tehrani */
202cdad5580SPouria Mousavizadeh Tehrani static struct acpi_ctrl *
acpi_system76_ctrl_map(struct acpi_system76_softc * sc,int method)203cdad5580SPouria Mousavizadeh Tehrani acpi_system76_ctrl_map(struct acpi_system76_softc *sc, int method)
204cdad5580SPouria Mousavizadeh Tehrani {
205cdad5580SPouria Mousavizadeh Tehrani
206cdad5580SPouria Mousavizadeh Tehrani switch (method) {
207cdad5580SPouria Mousavizadeh Tehrani case S76_CTRL_KBB:
208cdad5580SPouria Mousavizadeh Tehrani return (&sc->kbb);
209cdad5580SPouria Mousavizadeh Tehrani case S76_CTRL_KBC:
210cdad5580SPouria Mousavizadeh Tehrani return (&sc->kbc);
211f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_BCTL:
212f87ba452SPouria Mousavizadeh Tehrani return (&sc->bctl);
213f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_BCTH:
214f87ba452SPouria Mousavizadeh Tehrani return (&sc->bcth);
215cdad5580SPouria Mousavizadeh Tehrani default:
216cdad5580SPouria Mousavizadeh Tehrani device_printf(sc->dev, "Driver received unknown method\n");
217cdad5580SPouria Mousavizadeh Tehrani return (NULL);
218cdad5580SPouria Mousavizadeh Tehrani }
219cdad5580SPouria Mousavizadeh Tehrani }
220cdad5580SPouria Mousavizadeh Tehrani
221cdad5580SPouria Mousavizadeh Tehrani static int
acpi_system76_update(struct acpi_system76_softc * sc,int method,bool set)222cdad5580SPouria Mousavizadeh Tehrani acpi_system76_update(struct acpi_system76_softc *sc, int method, bool set)
223cdad5580SPouria Mousavizadeh Tehrani {
224cdad5580SPouria Mousavizadeh Tehrani struct acpi_ctrl *ctrl;
225cdad5580SPouria Mousavizadeh Tehrani ACPI_STATUS status;
226f87ba452SPouria Mousavizadeh Tehrani ACPI_BUFFER Buf;
227f87ba452SPouria Mousavizadeh Tehrani ACPI_OBJECT Arg[2], Obj;
228f87ba452SPouria Mousavizadeh Tehrani ACPI_OBJECT_LIST Args;
229cdad5580SPouria Mousavizadeh Tehrani
230cdad5580SPouria Mousavizadeh Tehrani ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
231cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_ASSERT(system76);
232cdad5580SPouria Mousavizadeh Tehrani
233cdad5580SPouria Mousavizadeh Tehrani if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
234cdad5580SPouria Mousavizadeh Tehrani return (EINVAL);
235cdad5580SPouria Mousavizadeh Tehrani
236f87ba452SPouria Mousavizadeh Tehrani switch (method) {
237f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_BCTL:
238f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_BCTH:
239f87ba452SPouria Mousavizadeh Tehrani Arg[0].Type = ACPI_TYPE_INTEGER;
240f87ba452SPouria Mousavizadeh Tehrani Arg[0].Integer.Value = method == S76_CTRL_BCTH ? 1 : 0;
241f87ba452SPouria Mousavizadeh Tehrani Args.Count = set ? 2 : 1;
242f87ba452SPouria Mousavizadeh Tehrani Args.Pointer = Arg;
243f87ba452SPouria Mousavizadeh Tehrani Buf.Length = sizeof(Obj);
244f87ba452SPouria Mousavizadeh Tehrani Buf.Pointer = &Obj;
245f87ba452SPouria Mousavizadeh Tehrani
246f87ba452SPouria Mousavizadeh Tehrani if (set) {
247f87ba452SPouria Mousavizadeh Tehrani Arg[1].Type = ACPI_TYPE_INTEGER;
248f87ba452SPouria Mousavizadeh Tehrani Arg[1].Integer.Value = ctrl->val;
249f87ba452SPouria Mousavizadeh Tehrani
250f87ba452SPouria Mousavizadeh Tehrani status = AcpiEvaluateObject(sc->handle,
251f87ba452SPouria Mousavizadeh Tehrani s76_sysctl_table[method].set_method, &Args, &Buf);
252f87ba452SPouria Mousavizadeh Tehrani } else {
253f87ba452SPouria Mousavizadeh Tehrani status = AcpiEvaluateObject(sc->handle,
254f87ba452SPouria Mousavizadeh Tehrani s76_sysctl_table[method].get_method, &Args, &Buf);
255f87ba452SPouria Mousavizadeh Tehrani if (ACPI_SUCCESS(status) &&
256f87ba452SPouria Mousavizadeh Tehrani Obj.Type == ACPI_TYPE_INTEGER)
257f87ba452SPouria Mousavizadeh Tehrani ctrl->val = Obj.Integer.Value;
258f87ba452SPouria Mousavizadeh Tehrani }
259f87ba452SPouria Mousavizadeh Tehrani break;
260f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_KBB:
261f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_KBC:
262cdad5580SPouria Mousavizadeh Tehrani if (set)
263cdad5580SPouria Mousavizadeh Tehrani status = acpi_SetInteger(sc->handle, s76_sysctl_table[method].set_method,
264cdad5580SPouria Mousavizadeh Tehrani ctrl->val);
265cdad5580SPouria Mousavizadeh Tehrani else
266cdad5580SPouria Mousavizadeh Tehrani status = acpi_GetInteger(sc->handle, s76_sysctl_table[method].get_method,
267cdad5580SPouria Mousavizadeh Tehrani &ctrl->val);
268f87ba452SPouria Mousavizadeh Tehrani break;
269f87ba452SPouria Mousavizadeh Tehrani }
270f87ba452SPouria Mousavizadeh Tehrani
271cdad5580SPouria Mousavizadeh Tehrani if (ACPI_FAILURE(status)) {
272cdad5580SPouria Mousavizadeh Tehrani device_printf(sc->dev, "Couldn't query method (%s)\n",
273cdad5580SPouria Mousavizadeh Tehrani s76_sysctl_table[method].name);
274cdad5580SPouria Mousavizadeh Tehrani return (status);
275cdad5580SPouria Mousavizadeh Tehrani }
276cdad5580SPouria Mousavizadeh Tehrani
277cdad5580SPouria Mousavizadeh Tehrani return (0);
278cdad5580SPouria Mousavizadeh Tehrani }
279cdad5580SPouria Mousavizadeh Tehrani
280cdad5580SPouria Mousavizadeh Tehrani static void
acpi_system76_notify_update(void * arg)281cdad5580SPouria Mousavizadeh Tehrani acpi_system76_notify_update(void *arg)
282cdad5580SPouria Mousavizadeh Tehrani {
283cdad5580SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
284cdad5580SPouria Mousavizadeh Tehrani int method;
285cdad5580SPouria Mousavizadeh Tehrani
286cdad5580SPouria Mousavizadeh Tehrani ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
287cdad5580SPouria Mousavizadeh Tehrani
288cdad5580SPouria Mousavizadeh Tehrani sc = (struct acpi_system76_softc *)device_get_softc(arg);
289cdad5580SPouria Mousavizadeh Tehrani
290cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_BEGIN(system76);
291f87ba452SPouria Mousavizadeh Tehrani for (method = 1; method < S76_CTRL_MAX; method++) {
292f87ba452SPouria Mousavizadeh Tehrani if (method == S76_CTRL_BCTL ||
293f87ba452SPouria Mousavizadeh Tehrani method == S76_CTRL_BCTH)
294f87ba452SPouria Mousavizadeh Tehrani continue;
295cdad5580SPouria Mousavizadeh Tehrani acpi_system76_update(sc, method, false);
296f87ba452SPouria Mousavizadeh Tehrani }
297cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_END(system76);
298105869a2SPouria Mousavizadeh Tehrani
299105869a2SPouria Mousavizadeh Tehrani if (sc->kbb_bkl != NULL)
300105869a2SPouria Mousavizadeh Tehrani sc->backlight_level = devstate_to_backlight(sc->kbb.val);
301cdad5580SPouria Mousavizadeh Tehrani }
302cdad5580SPouria Mousavizadeh Tehrani
303cdad5580SPouria Mousavizadeh Tehrani static void
acpi_system76_check(struct acpi_system76_softc * sc)304cdad5580SPouria Mousavizadeh Tehrani acpi_system76_check(struct acpi_system76_softc *sc)
305cdad5580SPouria Mousavizadeh Tehrani {
306cdad5580SPouria Mousavizadeh Tehrani struct acpi_ctrl *ctrl;
307cdad5580SPouria Mousavizadeh Tehrani int method;
308cdad5580SPouria Mousavizadeh Tehrani
309cdad5580SPouria Mousavizadeh Tehrani ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
310cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_ASSERT(system76);
311cdad5580SPouria Mousavizadeh Tehrani
312cdad5580SPouria Mousavizadeh Tehrani for (method = 1; method < S76_CTRL_MAX; method++) {
313cdad5580SPouria Mousavizadeh Tehrani if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
314cdad5580SPouria Mousavizadeh Tehrani continue;
315cdad5580SPouria Mousavizadeh Tehrani
316f87ba452SPouria Mousavizadeh Tehrani /* available in all models */
317f87ba452SPouria Mousavizadeh Tehrani if (method == S76_CTRL_BCTL ||
318f87ba452SPouria Mousavizadeh Tehrani method == S76_CTRL_BCTH) {
319f87ba452SPouria Mousavizadeh Tehrani ctrl->exists = true;
320f87ba452SPouria Mousavizadeh Tehrani acpi_system76_update(sc, method, false);
321f87ba452SPouria Mousavizadeh Tehrani continue;
322f87ba452SPouria Mousavizadeh Tehrani }
323f87ba452SPouria Mousavizadeh Tehrani
324cdad5580SPouria Mousavizadeh Tehrani if (ACPI_FAILURE(acpi_GetInteger(sc->handle,
325cdad5580SPouria Mousavizadeh Tehrani s76_sysctl_table[method].get_method, &ctrl->val))) {
326cdad5580SPouria Mousavizadeh Tehrani ctrl->exists = false;
327cdad5580SPouria Mousavizadeh Tehrani device_printf(sc->dev, "Driver can't control %s\n",
328cdad5580SPouria Mousavizadeh Tehrani s76_sysctl_table[method].desc);
329cdad5580SPouria Mousavizadeh Tehrani } else {
330cdad5580SPouria Mousavizadeh Tehrani ctrl->exists = true;
331cdad5580SPouria Mousavizadeh Tehrani acpi_system76_update(sc, method, false);
332cdad5580SPouria Mousavizadeh Tehrani }
333cdad5580SPouria Mousavizadeh Tehrani }
334cdad5580SPouria Mousavizadeh Tehrani }
335cdad5580SPouria Mousavizadeh Tehrani
336cdad5580SPouria Mousavizadeh Tehrani static void
acpi_system76_notify_handler(ACPI_HANDLE handle,uint32_t notify,void * ctx)337cdad5580SPouria Mousavizadeh Tehrani acpi_system76_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *ctx)
338cdad5580SPouria Mousavizadeh Tehrani {
339cdad5580SPouria Mousavizadeh Tehrani
340cdad5580SPouria Mousavizadeh Tehrani ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
341cdad5580SPouria Mousavizadeh Tehrani
342cdad5580SPouria Mousavizadeh Tehrani switch (notify) {
343cdad5580SPouria Mousavizadeh Tehrani case ACPI_NOTIFY_BACKLIGHT_CHANGED:
344cdad5580SPouria Mousavizadeh Tehrani case ACPI_NOTIFY_COLOR_TOGGLE:
345cdad5580SPouria Mousavizadeh Tehrani case ACPI_NOTIFY_COLOR_DOWN:
346cdad5580SPouria Mousavizadeh Tehrani case ACPI_NOTIFY_COLOR_UP:
347cdad5580SPouria Mousavizadeh Tehrani case ACPI_NOTIFY_COLOR_CHANGED:
348cdad5580SPouria Mousavizadeh Tehrani AcpiOsExecute(OSL_NOTIFY_HANDLER,
349cdad5580SPouria Mousavizadeh Tehrani acpi_system76_notify_update, ctx);
350cdad5580SPouria Mousavizadeh Tehrani break;
351cdad5580SPouria Mousavizadeh Tehrani default:
352cdad5580SPouria Mousavizadeh Tehrani break;
353cdad5580SPouria Mousavizadeh Tehrani }
354cdad5580SPouria Mousavizadeh Tehrani }
355cdad5580SPouria Mousavizadeh Tehrani
356cdad5580SPouria Mousavizadeh Tehrani static int
acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS)357cdad5580SPouria Mousavizadeh Tehrani acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS)
358cdad5580SPouria Mousavizadeh Tehrani {
359f87ba452SPouria Mousavizadeh Tehrani struct acpi_ctrl *ctrl, *ctrl_cmp;
360cdad5580SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
361cdad5580SPouria Mousavizadeh Tehrani int val, method, error;
362f87ba452SPouria Mousavizadeh Tehrani bool update;
363cdad5580SPouria Mousavizadeh Tehrani
364cdad5580SPouria Mousavizadeh Tehrani ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
365cdad5580SPouria Mousavizadeh Tehrani
366cdad5580SPouria Mousavizadeh Tehrani sc = (struct acpi_system76_softc *)oidp->oid_arg1;
367cdad5580SPouria Mousavizadeh Tehrani method = oidp->oid_arg2;
368cdad5580SPouria Mousavizadeh Tehrani if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
369cdad5580SPouria Mousavizadeh Tehrani return (EINVAL);
370cdad5580SPouria Mousavizadeh Tehrani
371cdad5580SPouria Mousavizadeh Tehrani val = ctrl->val;
372cdad5580SPouria Mousavizadeh Tehrani error = sysctl_handle_int(oidp, &val, 0, req);
373cdad5580SPouria Mousavizadeh Tehrani if (error != 0) {
374cdad5580SPouria Mousavizadeh Tehrani device_printf(sc->dev, "Driver query failed\n");
375cdad5580SPouria Mousavizadeh Tehrani return (error);
376cdad5580SPouria Mousavizadeh Tehrani }
377cdad5580SPouria Mousavizadeh Tehrani
378f87ba452SPouria Mousavizadeh Tehrani if (req->newptr == NULL) {
379f87ba452SPouria Mousavizadeh Tehrani /*
380*f9146417SPouria Mousavizadeh Tehrani * ACPI will not notify us if battery thresholds changes
381f87ba452SPouria Mousavizadeh Tehrani * outside this module. Therefore, always fetch those values.
382f87ba452SPouria Mousavizadeh Tehrani */
383f87ba452SPouria Mousavizadeh Tehrani if (method != S76_CTRL_BCTL && method != S76_CTRL_BCTH)
384f87ba452SPouria Mousavizadeh Tehrani return (error);
385f87ba452SPouria Mousavizadeh Tehrani update = false;
386f87ba452SPouria Mousavizadeh Tehrani } else {
387cdad5580SPouria Mousavizadeh Tehrani /* Input validation */
388cdad5580SPouria Mousavizadeh Tehrani switch (method) {
389cdad5580SPouria Mousavizadeh Tehrani case S76_CTRL_KBB:
390cdad5580SPouria Mousavizadeh Tehrani if (val > UINT8_MAX || val < 0)
391cdad5580SPouria Mousavizadeh Tehrani return (EINVAL);
392105869a2SPouria Mousavizadeh Tehrani if (sc->kbb_bkl != NULL)
393105869a2SPouria Mousavizadeh Tehrani sc->backlight_level = devstate_to_backlight(val);
394cdad5580SPouria Mousavizadeh Tehrani break;
395cdad5580SPouria Mousavizadeh Tehrani case S76_CTRL_KBC:
396cdad5580SPouria Mousavizadeh Tehrani if (val >= (1 << 24) || val < 0)
397cdad5580SPouria Mousavizadeh Tehrani return (EINVAL);
398cdad5580SPouria Mousavizadeh Tehrani break;
399f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_BCTL:
400f87ba452SPouria Mousavizadeh Tehrani if ((ctrl_cmp = acpi_system76_ctrl_map(sc, S76_CTRL_BCTH)) == NULL)
401f87ba452SPouria Mousavizadeh Tehrani return (EINVAL);
402f87ba452SPouria Mousavizadeh Tehrani if (val > 100 || val < 0 || val >= ctrl_cmp->val)
403f87ba452SPouria Mousavizadeh Tehrani return (EINVAL);
404f87ba452SPouria Mousavizadeh Tehrani break;
405f87ba452SPouria Mousavizadeh Tehrani case S76_CTRL_BCTH:
406f87ba452SPouria Mousavizadeh Tehrani if ((ctrl_cmp = acpi_system76_ctrl_map(sc, S76_CTRL_BCTL)) == NULL)
407f87ba452SPouria Mousavizadeh Tehrani return (EINVAL);
408f87ba452SPouria Mousavizadeh Tehrani if (val > 100 || val < 0 || val <= ctrl_cmp->val)
409f87ba452SPouria Mousavizadeh Tehrani return (EINVAL);
410cdad5580SPouria Mousavizadeh Tehrani break;
411cdad5580SPouria Mousavizadeh Tehrani }
412cdad5580SPouria Mousavizadeh Tehrani ctrl->val = val;
413f87ba452SPouria Mousavizadeh Tehrani update = true;
414f87ba452SPouria Mousavizadeh Tehrani }
415cdad5580SPouria Mousavizadeh Tehrani
416cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_BEGIN(system76);
417f87ba452SPouria Mousavizadeh Tehrani error = acpi_system76_update(sc, method, update);
418cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_END(system76);
419cdad5580SPouria Mousavizadeh Tehrani return (error);
420cdad5580SPouria Mousavizadeh Tehrani }
421cdad5580SPouria Mousavizadeh Tehrani
422cdad5580SPouria Mousavizadeh Tehrani static void
acpi_system76_init(struct acpi_system76_softc * sc)423cdad5580SPouria Mousavizadeh Tehrani acpi_system76_init(struct acpi_system76_softc *sc)
424cdad5580SPouria Mousavizadeh Tehrani {
425cdad5580SPouria Mousavizadeh Tehrani struct acpi_softc *acpi_sc;
426cdad5580SPouria Mousavizadeh Tehrani struct acpi_ctrl *ctrl;
427cdad5580SPouria Mousavizadeh Tehrani uint32_t method;
428cdad5580SPouria Mousavizadeh Tehrani
429cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_ASSERT(system76);
430cdad5580SPouria Mousavizadeh Tehrani
431cdad5580SPouria Mousavizadeh Tehrani acpi_system76_check(sc);
432cdad5580SPouria Mousavizadeh Tehrani acpi_sc = acpi_device_get_parent_softc(sc->dev);
433cdad5580SPouria Mousavizadeh Tehrani sysctl_ctx_init(&sc->sysctl_ctx);
434cdad5580SPouria Mousavizadeh Tehrani sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
435cdad5580SPouria Mousavizadeh Tehrani SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "s76",
436cdad5580SPouria Mousavizadeh Tehrani CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "system76 control");
437cdad5580SPouria Mousavizadeh Tehrani
438cdad5580SPouria Mousavizadeh Tehrani for (method = 1; method < S76_CTRL_MAX; method++) {
439cdad5580SPouria Mousavizadeh Tehrani if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL)
440cdad5580SPouria Mousavizadeh Tehrani continue;
441cdad5580SPouria Mousavizadeh Tehrani
442cdad5580SPouria Mousavizadeh Tehrani if (!ctrl->exists)
443cdad5580SPouria Mousavizadeh Tehrani continue;
444cdad5580SPouria Mousavizadeh Tehrani
445105869a2SPouria Mousavizadeh Tehrani if (method == S76_CTRL_KBB) {
446105869a2SPouria Mousavizadeh Tehrani sc->kbb_bkl = backlight_register("system76_keyboard", sc->dev);
447105869a2SPouria Mousavizadeh Tehrani if (sc->kbb_bkl == NULL)
448105869a2SPouria Mousavizadeh Tehrani device_printf(sc->dev, "Can not register backlight\n");
449105869a2SPouria Mousavizadeh Tehrani else
450105869a2SPouria Mousavizadeh Tehrani sc->backlight_level = devstate_to_backlight(sc->kbb.val);
451105869a2SPouria Mousavizadeh Tehrani }
452105869a2SPouria Mousavizadeh Tehrani
453cdad5580SPouria Mousavizadeh Tehrani SYSCTL_ADD_PROC(&sc->sysctl_ctx,
454cdad5580SPouria Mousavizadeh Tehrani SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, s76_sysctl_table[method].name,
455cdad5580SPouria Mousavizadeh Tehrani CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
456cdad5580SPouria Mousavizadeh Tehrani sc, method, acpi_system76_sysctl_handler, "IU", s76_sysctl_table[method].desc);
457cdad5580SPouria Mousavizadeh Tehrani }
458cdad5580SPouria Mousavizadeh Tehrani }
459cdad5580SPouria Mousavizadeh Tehrani
460cdad5580SPouria Mousavizadeh Tehrani static int
acpi_system76_backlight_update_status(device_t dev,struct backlight_props * props)461105869a2SPouria Mousavizadeh Tehrani acpi_system76_backlight_update_status(device_t dev, struct backlight_props
462105869a2SPouria Mousavizadeh Tehrani *props)
463105869a2SPouria Mousavizadeh Tehrani {
464105869a2SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
465105869a2SPouria Mousavizadeh Tehrani
466105869a2SPouria Mousavizadeh Tehrani sc = device_get_softc(dev);
467105869a2SPouria Mousavizadeh Tehrani if (sc->kbb.val != backlight_to_devstate(props->brightness)) {
468105869a2SPouria Mousavizadeh Tehrani sc->kbb.val = backlight_to_devstate(props->brightness);
469105869a2SPouria Mousavizadeh Tehrani acpi_system76_update(sc, S76_CTRL_KBB, true);
470105869a2SPouria Mousavizadeh Tehrani }
471105869a2SPouria Mousavizadeh Tehrani sc->backlight_level = props->brightness;
472105869a2SPouria Mousavizadeh Tehrani
473105869a2SPouria Mousavizadeh Tehrani return (0);
474105869a2SPouria Mousavizadeh Tehrani }
475105869a2SPouria Mousavizadeh Tehrani
476105869a2SPouria Mousavizadeh Tehrani static int
acpi_system76_backlight_get_status(device_t dev,struct backlight_props * props)477105869a2SPouria Mousavizadeh Tehrani acpi_system76_backlight_get_status(device_t dev, struct backlight_props *props)
478105869a2SPouria Mousavizadeh Tehrani {
479105869a2SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
480105869a2SPouria Mousavizadeh Tehrani
481105869a2SPouria Mousavizadeh Tehrani sc = device_get_softc(dev);
482105869a2SPouria Mousavizadeh Tehrani props->brightness = sc->backlight_level;
483105869a2SPouria Mousavizadeh Tehrani props->nlevels = nitems(acpi_system76_backlight_levels);
484105869a2SPouria Mousavizadeh Tehrani memcpy(props->levels, acpi_system76_backlight_levels,
485105869a2SPouria Mousavizadeh Tehrani sizeof(acpi_system76_backlight_levels));
486105869a2SPouria Mousavizadeh Tehrani
487105869a2SPouria Mousavizadeh Tehrani return (0);
488105869a2SPouria Mousavizadeh Tehrani }
489105869a2SPouria Mousavizadeh Tehrani
490105869a2SPouria Mousavizadeh Tehrani static int
acpi_system76_backlight_get_info(device_t dev,struct backlight_info * info)491105869a2SPouria Mousavizadeh Tehrani acpi_system76_backlight_get_info(device_t dev, struct backlight_info *info)
492105869a2SPouria Mousavizadeh Tehrani {
493105869a2SPouria Mousavizadeh Tehrani info->type = BACKLIGHT_TYPE_KEYBOARD;
494105869a2SPouria Mousavizadeh Tehrani strlcpy(info->name, "System76 Keyboard", BACKLIGHTMAXNAMELENGTH);
495105869a2SPouria Mousavizadeh Tehrani
496105869a2SPouria Mousavizadeh Tehrani return (0);
497105869a2SPouria Mousavizadeh Tehrani }
498105869a2SPouria Mousavizadeh Tehrani
499105869a2SPouria Mousavizadeh Tehrani static int
acpi_system76_attach(device_t dev)500cdad5580SPouria Mousavizadeh Tehrani acpi_system76_attach(device_t dev)
501cdad5580SPouria Mousavizadeh Tehrani {
502cdad5580SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
503cdad5580SPouria Mousavizadeh Tehrani
504cdad5580SPouria Mousavizadeh Tehrani ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
505cdad5580SPouria Mousavizadeh Tehrani
506cdad5580SPouria Mousavizadeh Tehrani sc = device_get_softc(dev);
507cdad5580SPouria Mousavizadeh Tehrani sc->dev = dev;
508cdad5580SPouria Mousavizadeh Tehrani sc->handle = acpi_get_handle(dev);
509cdad5580SPouria Mousavizadeh Tehrani
510cdad5580SPouria Mousavizadeh Tehrani AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
511cdad5580SPouria Mousavizadeh Tehrani acpi_system76_notify_handler, dev);
512cdad5580SPouria Mousavizadeh Tehrani
513cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_BEGIN(system76);
514cdad5580SPouria Mousavizadeh Tehrani acpi_system76_init(sc);
515cdad5580SPouria Mousavizadeh Tehrani ACPI_SERIAL_END(system76);
516cdad5580SPouria Mousavizadeh Tehrani
517cdad5580SPouria Mousavizadeh Tehrani return (0);
518cdad5580SPouria Mousavizadeh Tehrani }
519cdad5580SPouria Mousavizadeh Tehrani
520cdad5580SPouria Mousavizadeh Tehrani static int
acpi_system76_detach(device_t dev)521cdad5580SPouria Mousavizadeh Tehrani acpi_system76_detach(device_t dev)
522cdad5580SPouria Mousavizadeh Tehrani {
523cdad5580SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
524cdad5580SPouria Mousavizadeh Tehrani
525cdad5580SPouria Mousavizadeh Tehrani sc = device_get_softc(dev);
526cdad5580SPouria Mousavizadeh Tehrani if (sysctl_ctx_free(&sc->sysctl_ctx) != 0)
527cdad5580SPouria Mousavizadeh Tehrani return (EBUSY);
528cdad5580SPouria Mousavizadeh Tehrani
529105869a2SPouria Mousavizadeh Tehrani AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY,
530105869a2SPouria Mousavizadeh Tehrani acpi_system76_notify_handler);
531105869a2SPouria Mousavizadeh Tehrani
532105869a2SPouria Mousavizadeh Tehrani if (sc->kbb_bkl != NULL)
533105869a2SPouria Mousavizadeh Tehrani backlight_destroy(sc->kbb_bkl);
534105869a2SPouria Mousavizadeh Tehrani
535cdad5580SPouria Mousavizadeh Tehrani return (0);
536cdad5580SPouria Mousavizadeh Tehrani }
537cdad5580SPouria Mousavizadeh Tehrani
538cdad5580SPouria Mousavizadeh Tehrani static int
acpi_system76_suspend(device_t dev)539105869a2SPouria Mousavizadeh Tehrani acpi_system76_suspend(device_t dev)
540105869a2SPouria Mousavizadeh Tehrani {
541105869a2SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
542105869a2SPouria Mousavizadeh Tehrani struct acpi_ctrl *ctrl;
543105869a2SPouria Mousavizadeh Tehrani
544105869a2SPouria Mousavizadeh Tehrani sc = device_get_softc(dev);
545105869a2SPouria Mousavizadeh Tehrani if ((ctrl = acpi_system76_ctrl_map(sc, S76_CTRL_KBB)) != NULL) {
546105869a2SPouria Mousavizadeh Tehrani ctrl->val = 0;
547105869a2SPouria Mousavizadeh Tehrani acpi_system76_update(sc, S76_CTRL_KBB, true);
548105869a2SPouria Mousavizadeh Tehrani }
549105869a2SPouria Mousavizadeh Tehrani
550105869a2SPouria Mousavizadeh Tehrani return (0);
551105869a2SPouria Mousavizadeh Tehrani }
552105869a2SPouria Mousavizadeh Tehrani
553105869a2SPouria Mousavizadeh Tehrani static int
acpi_system76_resume(device_t dev)554105869a2SPouria Mousavizadeh Tehrani acpi_system76_resume(device_t dev)
555105869a2SPouria Mousavizadeh Tehrani {
556105869a2SPouria Mousavizadeh Tehrani struct acpi_system76_softc *sc;
557105869a2SPouria Mousavizadeh Tehrani struct acpi_ctrl *ctrl;
558105869a2SPouria Mousavizadeh Tehrani
559105869a2SPouria Mousavizadeh Tehrani sc = device_get_softc(dev);
560105869a2SPouria Mousavizadeh Tehrani if ((ctrl = acpi_system76_ctrl_map(sc, S76_CTRL_KBB)) != NULL) {
561105869a2SPouria Mousavizadeh Tehrani ctrl->val = backlight_to_devstate(sc->backlight_level);
562105869a2SPouria Mousavizadeh Tehrani acpi_system76_update(sc, S76_CTRL_KBB, true);
563105869a2SPouria Mousavizadeh Tehrani }
564105869a2SPouria Mousavizadeh Tehrani
565105869a2SPouria Mousavizadeh Tehrani return (0);
566105869a2SPouria Mousavizadeh Tehrani }
567105869a2SPouria Mousavizadeh Tehrani
568105869a2SPouria Mousavizadeh Tehrani static int
acpi_system76_shutdown(device_t dev)569105869a2SPouria Mousavizadeh Tehrani acpi_system76_shutdown(device_t dev)
570105869a2SPouria Mousavizadeh Tehrani {
571105869a2SPouria Mousavizadeh Tehrani return (acpi_system76_detach(dev));
572105869a2SPouria Mousavizadeh Tehrani }
573105869a2SPouria Mousavizadeh Tehrani
574105869a2SPouria Mousavizadeh Tehrani static int
acpi_system76_probe(device_t dev)575cdad5580SPouria Mousavizadeh Tehrani acpi_system76_probe(device_t dev)
576cdad5580SPouria Mousavizadeh Tehrani {
577cdad5580SPouria Mousavizadeh Tehrani int rv;
578cdad5580SPouria Mousavizadeh Tehrani
579cdad5580SPouria Mousavizadeh Tehrani if (acpi_disabled("system76") || device_get_unit(dev) > 1)
580cdad5580SPouria Mousavizadeh Tehrani return (ENXIO);
581cdad5580SPouria Mousavizadeh Tehrani rv = ACPI_ID_PROBE(device_get_parent(dev), dev, system76_ids, NULL);
582cdad5580SPouria Mousavizadeh Tehrani if (rv > 0) {
583cdad5580SPouria Mousavizadeh Tehrani return (rv);
584cdad5580SPouria Mousavizadeh Tehrani }
585cdad5580SPouria Mousavizadeh Tehrani
586cdad5580SPouria Mousavizadeh Tehrani return (BUS_PROBE_VENDOR);
587cdad5580SPouria Mousavizadeh Tehrani }
588cdad5580SPouria Mousavizadeh Tehrani
589cdad5580SPouria Mousavizadeh Tehrani DRIVER_MODULE(acpi_system76, acpi, acpi_system76_driver, 0, 0);
590cdad5580SPouria Mousavizadeh Tehrani MODULE_VERSION(acpi_system76, 1);
591cdad5580SPouria Mousavizadeh Tehrani MODULE_DEPEND(acpi_system76, acpi, 1, 1, 1);
592105869a2SPouria Mousavizadeh Tehrani MODULE_DEPEND(acpi_system76, backlight, 1, 1, 1);
593