1 /* $OpenBSD: acpicbkbd.c,v 1.3 2022/04/06 18:59:27 naddy Exp $ */ 2 /* 3 * Copyright (c) 2016 joshua stein <jcs@openbsd.org> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 21 #include <dev/acpi/acpivar.h> 22 #include <dev/acpi/amltypes.h> 23 #include <dev/acpi/dsdt.h> 24 25 #include <dev/wscons/wsconsio.h> 26 27 /* #define ACPICBKBD_DEBUG */ 28 29 #ifdef ACPICBKBD_DEBUG 30 #define DPRINTF(x) printf x 31 #else 32 #define DPRINTF(x) 33 #endif 34 35 #define ACPICBKBD_MAX_BACKLIGHT 100 36 37 struct acpicbkbd_softc { 38 struct device sc_dev; 39 struct acpi_softc *sc_acpi; 40 struct aml_node *sc_devnode; 41 42 uint64_t sc_backlight; 43 }; 44 45 int acpicbkbd_match(struct device *, void *, void *); 46 void acpicbkbd_attach(struct device *, struct device *, void *); 47 int acpicbkbd_activate(struct device *, int); 48 49 int acpicbkbd_get_backlight(struct wskbd_backlight *); 50 int acpicbkbd_set_backlight(struct wskbd_backlight *); 51 void acpicbkbd_write_backlight(void *, int); 52 extern int (*wskbd_get_backlight)(struct wskbd_backlight *); 53 extern int (*wskbd_set_backlight)(struct wskbd_backlight *); 54 55 const struct cfattach acpicbkbd_ca = { 56 sizeof(struct acpicbkbd_softc), 57 acpicbkbd_match, 58 acpicbkbd_attach, 59 NULL, 60 acpicbkbd_activate, 61 }; 62 63 struct cfdriver acpicbkbd_cd = { 64 NULL, "acpicbkbd", DV_DULL 65 }; 66 67 const char *acpicbkbd_hids[] = { 68 "GOOG0002", 69 NULL 70 }; 71 72 int 73 acpicbkbd_match(struct device *parent, void *match, void *aux) 74 { 75 struct acpi_attach_args *aaa = aux; 76 struct cfdata *cf = match; 77 78 return acpi_matchhids(aaa, acpicbkbd_hids, cf->cf_driver->cd_name); 79 } 80 81 void 82 acpicbkbd_attach(struct device *parent, struct device *self, void *aux) 83 { 84 struct acpicbkbd_softc *sc = (struct acpicbkbd_softc *)self; 85 struct acpi_attach_args *aa = aux; 86 87 sc->sc_acpi = (struct acpi_softc *)parent; 88 sc->sc_devnode = aa->aaa_node; 89 90 printf(": %s", sc->sc_devnode->name); 91 92 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "KBQC", 93 0, NULL, &sc->sc_backlight) == 0) { 94 wskbd_get_backlight = acpicbkbd_get_backlight; 95 wskbd_set_backlight = acpicbkbd_set_backlight; 96 } else 97 printf(", no backlight control"); 98 99 printf("\n"); 100 } 101 102 int 103 acpicbkbd_activate(struct device *self, int act) 104 { 105 struct acpicbkbd_softc *sc = (struct acpicbkbd_softc *)self; 106 107 switch (act) { 108 case DVACT_WAKEUP: 109 /* restore backlight to pre-suspend value */ 110 acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0); 111 112 break; 113 } 114 return (0); 115 } 116 117 int 118 acpicbkbd_get_backlight(struct wskbd_backlight *kbl) 119 { 120 struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0]; 121 122 KASSERT(sc != NULL); 123 124 kbl->min = 0; 125 kbl->max = ACPICBKBD_MAX_BACKLIGHT; 126 kbl->curval = sc->sc_backlight; 127 128 return 0; 129 } 130 131 int 132 acpicbkbd_set_backlight(struct wskbd_backlight *kbl) 133 { 134 struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0]; 135 136 KASSERT(sc != NULL); 137 138 if (kbl->curval > ACPICBKBD_MAX_BACKLIGHT) 139 return EINVAL; 140 141 sc->sc_backlight = kbl->curval; 142 143 acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0); 144 acpi_wakeup(sc->sc_acpi); 145 146 return 0; 147 } 148 149 void 150 acpicbkbd_write_backlight(void *arg0, int arg1) 151 { 152 struct acpicbkbd_softc *sc = arg0; 153 struct aml_value arg; 154 155 DPRINTF(("%s: writing backlight of %lld\n", sc->sc_dev.dv_xname, 156 sc->sc_backlight)); 157 158 memset(&arg, 0, sizeof(arg)); 159 arg.type = AML_OBJTYPE_INTEGER; 160 arg.v_integer = sc->sc_backlight; 161 aml_evalname(sc->sc_acpi, sc->sc_devnode, "KBCM", 1, &arg, NULL); 162 } 163