xref: /openbsd-src/sys/dev/acpi/acpicbkbd.c (revision 471aeecfc619bc9b69519928152daf993376c2a1)
1*471aeecfSnaddy /* $OpenBSD: acpicbkbd.c,v 1.3 2022/04/06 18:59:27 naddy Exp $ */
26caabb8eSjcs /*
36caabb8eSjcs  * Copyright (c) 2016 joshua stein <jcs@openbsd.org>
46caabb8eSjcs  *
56caabb8eSjcs  * Permission to use, copy, modify, and/or distribute this software for any
66caabb8eSjcs  * purpose with or without fee is hereby granted, provided that the above
76caabb8eSjcs  * copyright notice and this permission notice appear in all copies.
86caabb8eSjcs  *
96caabb8eSjcs  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
106caabb8eSjcs  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
116caabb8eSjcs  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
126caabb8eSjcs  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
136caabb8eSjcs  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
146caabb8eSjcs  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
156caabb8eSjcs  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
166caabb8eSjcs  */
176caabb8eSjcs 
186caabb8eSjcs #include <sys/param.h>
196caabb8eSjcs #include <sys/systm.h>
206caabb8eSjcs 
216caabb8eSjcs #include <dev/acpi/acpivar.h>
226caabb8eSjcs #include <dev/acpi/amltypes.h>
236caabb8eSjcs #include <dev/acpi/dsdt.h>
246caabb8eSjcs 
256caabb8eSjcs #include <dev/wscons/wsconsio.h>
266caabb8eSjcs 
276800a44dSjcs /* #define ACPICBKBD_DEBUG */
286800a44dSjcs 
296caabb8eSjcs #ifdef ACPICBKBD_DEBUG
306caabb8eSjcs #define DPRINTF(x)	printf x
316caabb8eSjcs #else
326caabb8eSjcs #define DPRINTF(x)
336caabb8eSjcs #endif
346caabb8eSjcs 
356caabb8eSjcs #define ACPICBKBD_MAX_BACKLIGHT	100
366caabb8eSjcs 
376caabb8eSjcs struct acpicbkbd_softc {
386caabb8eSjcs 	struct device		sc_dev;
396caabb8eSjcs 	struct acpi_softc	*sc_acpi;
406caabb8eSjcs 	struct aml_node		*sc_devnode;
416caabb8eSjcs 
426caabb8eSjcs 	uint64_t		sc_backlight;
436caabb8eSjcs };
446caabb8eSjcs 
456caabb8eSjcs int	acpicbkbd_match(struct device *, void *, void *);
466caabb8eSjcs void	acpicbkbd_attach(struct device *, struct device *, void *);
476800a44dSjcs int	acpicbkbd_activate(struct device *, int);
486caabb8eSjcs 
496caabb8eSjcs int	acpicbkbd_get_backlight(struct wskbd_backlight *);
506caabb8eSjcs int	acpicbkbd_set_backlight(struct wskbd_backlight *);
516caabb8eSjcs void	acpicbkbd_write_backlight(void *, int);
526caabb8eSjcs extern int (*wskbd_get_backlight)(struct wskbd_backlight *);
536caabb8eSjcs extern int (*wskbd_set_backlight)(struct wskbd_backlight *);
546caabb8eSjcs 
55*471aeecfSnaddy const struct cfattach acpicbkbd_ca = {
566800a44dSjcs 	sizeof(struct acpicbkbd_softc),
576800a44dSjcs 	acpicbkbd_match,
586800a44dSjcs 	acpicbkbd_attach,
596800a44dSjcs 	NULL,
606800a44dSjcs 	acpicbkbd_activate,
616caabb8eSjcs };
626caabb8eSjcs 
636caabb8eSjcs struct cfdriver acpicbkbd_cd = {
646caabb8eSjcs 	NULL, "acpicbkbd", DV_DULL
656caabb8eSjcs };
666caabb8eSjcs 
676caabb8eSjcs const char *acpicbkbd_hids[] = {
686caabb8eSjcs 	"GOOG0002",
696caabb8eSjcs 	NULL
706caabb8eSjcs };
716caabb8eSjcs 
726caabb8eSjcs int
acpicbkbd_match(struct device * parent,void * match,void * aux)736caabb8eSjcs acpicbkbd_match(struct device *parent, void *match, void *aux)
746caabb8eSjcs {
756caabb8eSjcs 	struct acpi_attach_args *aaa = aux;
766caabb8eSjcs 	struct cfdata *cf = match;
776caabb8eSjcs 
786caabb8eSjcs 	return acpi_matchhids(aaa, acpicbkbd_hids, cf->cf_driver->cd_name);
796caabb8eSjcs }
806caabb8eSjcs 
816caabb8eSjcs void
acpicbkbd_attach(struct device * parent,struct device * self,void * aux)826caabb8eSjcs acpicbkbd_attach(struct device *parent, struct device *self, void *aux)
836caabb8eSjcs {
846caabb8eSjcs 	struct acpicbkbd_softc	*sc = (struct acpicbkbd_softc *)self;
856caabb8eSjcs 	struct acpi_attach_args *aa = aux;
866caabb8eSjcs 
876caabb8eSjcs 	sc->sc_acpi = (struct acpi_softc *)parent;
886caabb8eSjcs 	sc->sc_devnode = aa->aaa_node;
896caabb8eSjcs 
906caabb8eSjcs 	printf(": %s", sc->sc_devnode->name);
916caabb8eSjcs 
926caabb8eSjcs 	if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "KBQC",
936caabb8eSjcs 	    0, NULL, &sc->sc_backlight) == 0) {
946caabb8eSjcs 		wskbd_get_backlight = acpicbkbd_get_backlight;
956caabb8eSjcs 		wskbd_set_backlight = acpicbkbd_set_backlight;
966caabb8eSjcs 	} else
976caabb8eSjcs 		printf(", no backlight control");
986caabb8eSjcs 
996caabb8eSjcs 	printf("\n");
1006caabb8eSjcs }
1016caabb8eSjcs 
1026caabb8eSjcs int
acpicbkbd_activate(struct device * self,int act)1036800a44dSjcs acpicbkbd_activate(struct device *self, int act)
1046800a44dSjcs {
1056800a44dSjcs 	struct acpicbkbd_softc	*sc = (struct acpicbkbd_softc *)self;
1066800a44dSjcs 
1076800a44dSjcs 	switch (act) {
1086800a44dSjcs 	case DVACT_WAKEUP:
1096800a44dSjcs 		/* restore backlight to pre-suspend value */
1106800a44dSjcs 		acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0);
1116800a44dSjcs 
1126800a44dSjcs 		break;
1136800a44dSjcs 	}
1146800a44dSjcs 	return (0);
1156800a44dSjcs }
1166800a44dSjcs 
1176800a44dSjcs int
acpicbkbd_get_backlight(struct wskbd_backlight * kbl)1186caabb8eSjcs acpicbkbd_get_backlight(struct wskbd_backlight *kbl)
1196caabb8eSjcs {
1206caabb8eSjcs 	struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0];
1216caabb8eSjcs 
1226caabb8eSjcs 	KASSERT(sc != NULL);
1236caabb8eSjcs 
1246caabb8eSjcs 	kbl->min = 0;
1256caabb8eSjcs 	kbl->max = ACPICBKBD_MAX_BACKLIGHT;
1266caabb8eSjcs 	kbl->curval = sc->sc_backlight;
1276caabb8eSjcs 
1286caabb8eSjcs 	return 0;
1296caabb8eSjcs }
1306caabb8eSjcs 
1316caabb8eSjcs int
acpicbkbd_set_backlight(struct wskbd_backlight * kbl)1326caabb8eSjcs acpicbkbd_set_backlight(struct wskbd_backlight *kbl)
1336caabb8eSjcs {
1346caabb8eSjcs 	struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0];
1356caabb8eSjcs 
1366caabb8eSjcs 	KASSERT(sc != NULL);
1376caabb8eSjcs 
1386caabb8eSjcs 	if (kbl->curval > ACPICBKBD_MAX_BACKLIGHT)
1396caabb8eSjcs 		return EINVAL;
1406caabb8eSjcs 
1416caabb8eSjcs 	sc->sc_backlight = kbl->curval;
1426caabb8eSjcs 
1436caabb8eSjcs 	acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0);
1446caabb8eSjcs 	acpi_wakeup(sc->sc_acpi);
1456caabb8eSjcs 
1466caabb8eSjcs 	return 0;
1476caabb8eSjcs }
1486caabb8eSjcs 
1496caabb8eSjcs void
acpicbkbd_write_backlight(void * arg0,int arg1)1506caabb8eSjcs acpicbkbd_write_backlight(void *arg0, int arg1)
1516caabb8eSjcs {
1526caabb8eSjcs 	struct acpicbkbd_softc *sc = arg0;
1536caabb8eSjcs 	struct aml_value arg;
1546caabb8eSjcs 
1556800a44dSjcs 	DPRINTF(("%s: writing backlight of %lld\n", sc->sc_dev.dv_xname,
1566caabb8eSjcs 	    sc->sc_backlight));
1576caabb8eSjcs 
1586caabb8eSjcs 	memset(&arg, 0, sizeof(arg));
1596caabb8eSjcs 	arg.type = AML_OBJTYPE_INTEGER;
1606caabb8eSjcs 	arg.v_integer = sc->sc_backlight;
1616caabb8eSjcs 	aml_evalname(sc->sc_acpi, sc->sc_devnode, "KBCM", 1, &arg, NULL);
1626caabb8eSjcs }
163