Line data Source code
1 : /* $OpenBSD: acpiac.c,v 1.31 2018/07/01 19:40:49 mlarkin 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_notify(struct aml_node *, int, void *);
37 :
38 : void acpiac_refresh(void *);
39 : int acpiac_getsta(struct acpiac_softc *);
40 :
41 : struct cfattach acpiac_ca = {
42 : sizeof(struct acpiac_softc), acpiac_match, acpiac_attach
43 : };
44 :
45 : struct cfdriver acpiac_cd = {
46 : NULL, "acpiac", DV_DULL
47 : };
48 :
49 : const char *acpiac_hids[] = {
50 : ACPI_DEV_AC,
51 : NULL
52 : };
53 :
54 : int
55 0 : acpiac_match(struct device *parent, void *match, void *aux)
56 : {
57 0 : struct acpi_attach_args *aa = aux;
58 0 : struct cfdata *cf = match;
59 :
60 : /* sanity */
61 0 : return (acpi_matchhids(aa, acpiac_hids, cf->cf_driver->cd_name));
62 : }
63 :
64 : void
65 0 : acpiac_attach(struct device *parent, struct device *self, void *aux)
66 : {
67 0 : struct acpiac_softc *sc = (struct acpiac_softc *)self;
68 0 : struct acpi_attach_args *aa = aux;
69 :
70 0 : sc->sc_acpi = (struct acpi_softc *)parent;
71 0 : sc->sc_devnode = aa->aaa_node;
72 :
73 0 : acpiac_getsta(sc);
74 0 : printf(": AC unit ");
75 0 : if (sc->sc_ac_stat == PSR_ONLINE)
76 0 : printf("online\n");
77 0 : else if (sc->sc_ac_stat == PSR_OFFLINE)
78 0 : printf("offline\n");
79 : else
80 0 : printf("in unknown state\n");
81 :
82 0 : strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
83 : sizeof(sc->sc_sensdev.xname));
84 0 : strlcpy(sc->sc_sens[0].desc, "power supply",
85 : sizeof(sc->sc_sens[0].desc));
86 0 : sc->sc_sens[0].type = SENSOR_INDICATOR;
87 0 : sensor_attach(&sc->sc_sensdev, &sc->sc_sens[0]);
88 0 : sensordev_install(&sc->sc_sensdev);
89 0 : sc->sc_sens[0].value = sc->sc_ac_stat;
90 :
91 0 : aml_register_notify(sc->sc_devnode, aa->aaa_dev,
92 0 : acpiac_notify, sc, ACPIDEV_NOPOLL);
93 0 : }
94 :
95 : void
96 0 : acpiac_refresh(void *arg)
97 : {
98 0 : struct acpiac_softc *sc = arg;
99 :
100 0 : acpiac_getsta(sc);
101 0 : sc->sc_sens[0].value = sc->sc_ac_stat;
102 0 : acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE);
103 0 : }
104 :
105 : int
106 0 : acpiac_getsta(struct acpiac_softc *sc)
107 : {
108 0 : int64_t sta;
109 :
110 0 : if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL, NULL)) {
111 : dnprintf(10, "%s: no _STA\n",
112 : DEVNAME(sc));
113 : }
114 :
115 0 : if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_PSR", 0, NULL, &sta)) {
116 : dnprintf(10, "%s: no _PSR\n",
117 : DEVNAME(sc));
118 0 : return (1);
119 : }
120 0 : sc->sc_ac_stat = sta;
121 0 : return (0);
122 0 : }
123 :
124 : int
125 0 : acpiac_notify(struct aml_node *node, int notify_type, void *arg)
126 : {
127 0 : struct acpiac_softc *sc = arg;
128 :
129 : dnprintf(10, "acpiac_notify: %.2x %s\n", notify_type,
130 : DEVNAME(sc));
131 :
132 0 : switch (notify_type) {
133 : case 0x00:
134 : case 0x01:
135 : case 0x81:
136 : /*
137 : * XXX some sony vaio's use the wrong notify type
138 : * work around it by honoring it as a 0x80
139 : */
140 : /* FALLTHROUGH */
141 : case 0x80:
142 0 : acpiac_refresh(sc);
143 : dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat);
144 0 : break;
145 : }
146 0 : return (0);
147 : }
|