Line data Source code
1 : /* $OpenBSD: acpicbkbd.c,v 1.2 2016/07/27 02:26:26 jcs 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 : 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 0 : acpicbkbd_match(struct device *parent, void *match, void *aux)
74 : {
75 0 : struct acpi_attach_args *aaa = aux;
76 0 : struct cfdata *cf = match;
77 :
78 0 : return acpi_matchhids(aaa, acpicbkbd_hids, cf->cf_driver->cd_name);
79 : }
80 :
81 : void
82 0 : acpicbkbd_attach(struct device *parent, struct device *self, void *aux)
83 : {
84 0 : struct acpicbkbd_softc *sc = (struct acpicbkbd_softc *)self;
85 0 : struct acpi_attach_args *aa = aux;
86 :
87 0 : sc->sc_acpi = (struct acpi_softc *)parent;
88 0 : sc->sc_devnode = aa->aaa_node;
89 :
90 0 : printf(": %s", sc->sc_devnode->name);
91 :
92 0 : if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "KBQC",
93 0 : 0, NULL, &sc->sc_backlight) == 0) {
94 0 : wskbd_get_backlight = acpicbkbd_get_backlight;
95 0 : wskbd_set_backlight = acpicbkbd_set_backlight;
96 0 : } else
97 0 : printf(", no backlight control");
98 :
99 0 : printf("\n");
100 0 : }
101 :
102 : int
103 0 : acpicbkbd_activate(struct device *self, int act)
104 : {
105 0 : struct acpicbkbd_softc *sc = (struct acpicbkbd_softc *)self;
106 :
107 0 : switch (act) {
108 : case DVACT_WAKEUP:
109 : /* restore backlight to pre-suspend value */
110 0 : acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0);
111 :
112 0 : break;
113 : }
114 0 : return (0);
115 : }
116 :
117 : int
118 0 : acpicbkbd_get_backlight(struct wskbd_backlight *kbl)
119 : {
120 0 : struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0];
121 :
122 0 : KASSERT(sc != NULL);
123 :
124 0 : kbl->min = 0;
125 0 : kbl->max = ACPICBKBD_MAX_BACKLIGHT;
126 0 : kbl->curval = sc->sc_backlight;
127 :
128 0 : return 0;
129 : }
130 :
131 : int
132 0 : acpicbkbd_set_backlight(struct wskbd_backlight *kbl)
133 : {
134 0 : struct acpicbkbd_softc *sc = acpicbkbd_cd.cd_devs[0];
135 :
136 0 : KASSERT(sc != NULL);
137 :
138 0 : if (kbl->curval > ACPICBKBD_MAX_BACKLIGHT)
139 0 : return EINVAL;
140 :
141 0 : sc->sc_backlight = kbl->curval;
142 :
143 0 : acpi_addtask(sc->sc_acpi, acpicbkbd_write_backlight, sc, 0);
144 0 : acpi_wakeup(sc->sc_acpi);
145 :
146 0 : return 0;
147 0 : }
148 :
149 : void
150 0 : acpicbkbd_write_backlight(void *arg0, int arg1)
151 : {
152 0 : struct acpicbkbd_softc *sc = arg0;
153 0 : struct aml_value arg;
154 :
155 : DPRINTF(("%s: writing backlight of %lld\n", sc->sc_dev.dv_xname,
156 : sc->sc_backlight));
157 :
158 0 : memset(&arg, 0, sizeof(arg));
159 0 : arg.type = AML_OBJTYPE_INTEGER;
160 0 : arg.v_integer = sc->sc_backlight;
161 0 : aml_evalname(sc->sc_acpi, sc->sc_devnode, "KBCM", 1, &arg, NULL);
162 0 : }
|