1 /* $OpenBSD: acpiac.c,v 1.33 2020/06/10 22:26:40 jca Exp $ */ 2 /* 3 * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> 4 * 5 * Permission to use, copy, modify, and 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/event.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 24 #include <machine/bus.h> 25 #include <machine/apmvar.h> 26 27 #include <dev/acpi/acpireg.h> 28 #include <dev/acpi/acpivar.h> 29 #include <dev/acpi/acpidev.h> 30 #include <dev/acpi/dsdt.h> 31 32 #include <sys/sensors.h> 33 34 int acpiac_match(struct device *, void *, void *); 35 void acpiac_attach(struct device *, struct device *, void *); 36 int acpiac_activate(struct device *, int); 37 int acpiac_notify(struct aml_node *, int, void *); 38 39 void acpiac_refresh(void *); 40 int acpiac_getpsr(struct acpiac_softc *); 41 42 struct cfattach acpiac_ca = { 43 sizeof(struct acpiac_softc), 44 acpiac_match, 45 acpiac_attach, 46 NULL, 47 acpiac_activate, 48 }; 49 50 struct cfdriver acpiac_cd = { 51 NULL, "acpiac", DV_DULL 52 }; 53 54 const char *acpiac_hids[] = { 55 ACPI_DEV_AC, 56 NULL 57 }; 58 59 int 60 acpiac_match(struct device *parent, void *match, void *aux) 61 { 62 struct acpi_attach_args *aa = aux; 63 struct cfdata *cf = match; 64 65 /* sanity */ 66 return (acpi_matchhids(aa, acpiac_hids, cf->cf_driver->cd_name)); 67 } 68 69 void 70 acpiac_attach(struct device *parent, struct device *self, void *aux) 71 { 72 struct acpiac_softc *sc = (struct acpiac_softc *)self; 73 struct acpi_attach_args *aa = aux; 74 75 sc->sc_acpi = (struct acpi_softc *)parent; 76 sc->sc_devnode = aa->aaa_node; 77 78 acpiac_getpsr(sc); 79 printf(": AC unit "); 80 if (sc->sc_ac_stat == PSR_ONLINE) 81 printf("online\n"); 82 else if (sc->sc_ac_stat == PSR_OFFLINE) 83 printf("offline\n"); 84 else 85 printf("in unknown state\n"); 86 87 strlcpy(sc->sc_sensdev.xname, DEVNAME(sc), 88 sizeof(sc->sc_sensdev.xname)); 89 strlcpy(sc->sc_sens[0].desc, "power supply", 90 sizeof(sc->sc_sens[0].desc)); 91 sc->sc_sens[0].type = SENSOR_INDICATOR; 92 sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]); 93 sensordev_install(&sc->sc_sensdev); 94 sc->sc_sens[0].value = sc->sc_ac_stat; 95 96 aml_register_notify(sc->sc_devnode, aa->aaa_dev, 97 acpiac_notify, sc, ACPIDEV_NOPOLL); 98 } 99 100 int 101 acpiac_activate(struct device *self, int act) 102 { 103 struct acpiac_softc *sc = (struct acpiac_softc *)self; 104 105 switch (act) { 106 case DVACT_WAKEUP: 107 acpiac_refresh(sc); 108 dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); 109 break; 110 } 111 112 return (0); 113 } 114 115 void 116 acpiac_refresh(void *arg) 117 { 118 struct acpiac_softc *sc = arg; 119 120 acpiac_getpsr(sc); 121 sc->sc_sens[0].value = sc->sc_ac_stat; 122 } 123 124 int 125 acpiac_getpsr(struct acpiac_softc *sc) 126 { 127 int64_t psr; 128 129 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_PSR", 0, NULL, &psr)) { 130 dnprintf(10, "%s: no _PSR\n", 131 DEVNAME(sc)); 132 return (1); 133 } 134 sc->sc_ac_stat = psr; 135 136 return (0); 137 } 138 139 int 140 acpiac_notify(struct aml_node *node, int notify_type, void *arg) 141 { 142 struct acpiac_softc *sc = arg; 143 144 dnprintf(10, "acpiac_notify: %.2x %s\n", notify_type, 145 DEVNAME(sc)); 146 147 switch (notify_type) { 148 case 0x00: 149 case 0x01: 150 case 0x81: 151 /* 152 * XXX some sony vaio's use the wrong notify type 153 * work around it by honoring it as a 0x80 154 */ 155 /* FALLTHROUGH */ 156 case 0x80: 157 acpiac_refresh(sc); 158 acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE); 159 dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); 160 break; 161 } 162 return (0); 163 } 164