xref: /openbsd-src/sys/dev/acpi/acpiasus.c (revision 471aeecfc619bc9b69519928152daf993376c2a1)
1*471aeecfSnaddy /* $OpenBSD: acpiasus.c,v 1.20 2022/04/06 18:59:27 naddy Exp $ */
2834f78e1Sjsing /* $NetBSD: asus_acpi.c,v 1.2.2.2 2008/04/03 12:42:37 mjf Exp $ */
39ee5300fSmarco /*
4834f78e1Sjsing  * Copyright (c) 2007, 2008 Jared D. McNeill <jmcneill@invisible.ca>
5834f78e1Sjsing  * All rights reserved.
6834f78e1Sjsing  *
7834f78e1Sjsing  * Redistribution and use in source and binary forms, with or without
8834f78e1Sjsing  * modification, are permitted provided that the following conditions
9834f78e1Sjsing  * are met:
10834f78e1Sjsing  * 1. Redistributions of source code must retain the above copyright
11834f78e1Sjsing  *    notice, this list of conditions and the following disclaimer.
12834f78e1Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
13834f78e1Sjsing  *    notice, this list of conditions and the following disclaimer in the
14834f78e1Sjsing  *    documentation and/or other materials provided with the distribution.
15834f78e1Sjsing  *
16834f78e1Sjsing  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17834f78e1Sjsing  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18834f78e1Sjsing  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19834f78e1Sjsing  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20834f78e1Sjsing  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21834f78e1Sjsing  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22834f78e1Sjsing  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23834f78e1Sjsing  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24834f78e1Sjsing  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25834f78e1Sjsing  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26834f78e1Sjsing  * POSSIBILITY OF SUCH DAMAGE.
27834f78e1Sjsing  */
28834f78e1Sjsing 
29834f78e1Sjsing /*
30834f78e1Sjsing  * ASUS ACPI hotkeys driver.
31834f78e1Sjsing  */
32834f78e1Sjsing 
33834f78e1Sjsing #include <sys/param.h>
34834f78e1Sjsing #include <sys/device.h>
35834f78e1Sjsing #include <sys/systm.h>
36834f78e1Sjsing 
37834f78e1Sjsing #include <dev/acpi/acpireg.h>
38834f78e1Sjsing #include <dev/acpi/acpivar.h>
39834f78e1Sjsing #include <dev/acpi/acpidev.h>
40834f78e1Sjsing #include <dev/acpi/amltypes.h>
41834f78e1Sjsing #include <dev/acpi/dsdt.h>
42834f78e1Sjsing 
43834f78e1Sjsing #include "audio.h"
44834f78e1Sjsing #include "wskbd.h"
45834f78e1Sjsing 
46834f78e1Sjsing struct acpiasus_softc {
47834f78e1Sjsing 	struct device		sc_dev;
48834f78e1Sjsing 
49834f78e1Sjsing 	struct acpi_softc	*sc_acpi;
50834f78e1Sjsing 	struct aml_node		*sc_devnode;
51834f78e1Sjsing };
52834f78e1Sjsing 
53a02c5301Srobert #define ASUS_NOTIFY_WIRELESSON		0x10
54a02c5301Srobert #define ASUS_NOTIFY_WIRELESSOFF		0x11
55a02c5301Srobert #define ASUS_NOTIFY_TASKSWITCH		0x12
56a02c5301Srobert #define ASUS_NOTIFY_VOLUMEMUTE		0x13
57a02c5301Srobert #define ASUS_NOTIFY_VOLUMEDOWN		0x14
58a02c5301Srobert #define ASUS_NOTIFY_VOLUMEUP		0x15
59a02c5301Srobert #define ASUS_NOTIFY_LCDSWITCHOFF0	0x16
60a02c5301Srobert #define ASUS_NOTIFY_LCDSWITCHOFF1	0x1a
61a02c5301Srobert #define ASUS_NOTIFY_LCDCHANGERES	0x1b
62a02c5301Srobert #define ASUS_NOTIFY_USERDEF0		0x1c
63a02c5301Srobert #define ASUS_NOTIFY_USERDEF1		0x1d
64a02c5301Srobert #define ASUS_NOTIFY_BRIGHTNESSLOW	0x20
65a02c5301Srobert #define ASUS_NOTIFY_BRIGHTNESSHIGH	0x2f
66a02c5301Srobert #define ASUS_NOTIFY_DISPLAYCYCLEDOWN	0x30
67a02c5301Srobert #define ASUS_NOTIFY_DISPLAYCYCLEUP	0x32
68834f78e1Sjsing 
69a02c5301Srobert #define ASUS_NOTIFY_POWERCONNECT	0x50
70a02c5301Srobert #define ASUS_NOTIFY_POWERDISCONNECT	0x51
719ec9c868Sjsing 
72834f78e1Sjsing #define	ASUS_SDSP_LCD			0x01
73834f78e1Sjsing #define	ASUS_SDSP_CRT			0x02
74834f78e1Sjsing #define	ASUS_SDSP_TV			0x04
75834f78e1Sjsing #define	ASUS_SDSP_DVI			0x08
76834f78e1Sjsing #define	ASUS_SDSP_ALL \
77834f78e1Sjsing 	(ASUS_SDSP_LCD | ASUS_SDSP_CRT | ASUS_SDSP_TV | ASUS_SDSP_DVI)
78834f78e1Sjsing 
79834f78e1Sjsing int	acpiasus_match(struct device *, void *, void *);
80834f78e1Sjsing void	acpiasus_attach(struct device *, struct device *, void *);
81834f78e1Sjsing void	acpiasus_init(struct device *);
82834f78e1Sjsing int	acpiasus_notify(struct aml_node *, int, void *);
8360e24e29Sderaadt int	acpiasus_activate(struct device *, int);
84834f78e1Sjsing 
85834f78e1Sjsing #if NAUDIO > 0 && NWSKBD > 0
86012023bfSmpi extern int wskbd_set_mixervolume(long, long);
87834f78e1Sjsing #endif
88834f78e1Sjsing 
89*471aeecfSnaddy const struct cfattach acpiasus_ca = {
9060e24e29Sderaadt 	sizeof(struct acpiasus_softc), acpiasus_match, acpiasus_attach,
913ea9bf37Spirofti 	NULL, acpiasus_activate
92834f78e1Sjsing };
93834f78e1Sjsing 
94834f78e1Sjsing struct cfdriver acpiasus_cd = {
95834f78e1Sjsing 	NULL, "acpiasus", DV_DULL
96834f78e1Sjsing };
97834f78e1Sjsing 
986bf9874fSjcs const char *acpiasus_hids[] = {
996bf9874fSjcs 	"ASUS010",
100128e94b2Smlarkin 	NULL
1016bf9874fSjcs };
1027df90d51Smarco 
103834f78e1Sjsing int
acpiasus_match(struct device * parent,void * match,void * aux)104834f78e1Sjsing acpiasus_match(struct device *parent, void *match, void *aux)
105834f78e1Sjsing {
106834f78e1Sjsing 	struct acpi_attach_args *aa = aux;
107834f78e1Sjsing 	struct cfdata *cf = match;
108834f78e1Sjsing 
1097df90d51Smarco 	return (acpi_matchhids(aa, acpiasus_hids, cf->cf_driver->cd_name));
110834f78e1Sjsing }
111834f78e1Sjsing 
112834f78e1Sjsing void
acpiasus_attach(struct device * parent,struct device * self,void * aux)113834f78e1Sjsing acpiasus_attach(struct device *parent, struct device *self, void *aux)
114834f78e1Sjsing {
115834f78e1Sjsing 	struct acpiasus_softc *sc = (struct acpiasus_softc *)self;
116834f78e1Sjsing 	struct acpi_attach_args *aa = aux;
117834f78e1Sjsing 
118834f78e1Sjsing 	sc->sc_acpi = (struct acpi_softc *)parent;
1193b455a03Smarco 	sc->sc_devnode = aa->aaa_node;
120834f78e1Sjsing 
121834f78e1Sjsing 	printf("\n");
122834f78e1Sjsing 
123834f78e1Sjsing 	acpiasus_init(self);
124834f78e1Sjsing 
1253b455a03Smarco 	aml_register_notify(sc->sc_devnode, aa->aaa_dev,
126834f78e1Sjsing 	    acpiasus_notify, sc, ACPIDEV_NOPOLL);
127834f78e1Sjsing }
128834f78e1Sjsing 
129834f78e1Sjsing void
acpiasus_init(struct device * self)130834f78e1Sjsing acpiasus_init(struct device *self)
131834f78e1Sjsing {
132834f78e1Sjsing 	struct acpiasus_softc *sc = (struct acpiasus_softc *)self;
133834f78e1Sjsing 	struct aml_value cmd;
134834f78e1Sjsing 	struct aml_value ret;
135834f78e1Sjsing 
1369ec9c868Sjsing 	bzero(&cmd, sizeof(cmd));
137834f78e1Sjsing 	cmd.type = AML_OBJTYPE_INTEGER;
138834f78e1Sjsing 	cmd.v_integer = 0x40;		/* Disable ASL display switching. */
139834f78e1Sjsing 
140834f78e1Sjsing 	if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "INIT", 1, &cmd, &ret))
141834f78e1Sjsing 		printf("%s: no INIT\n", DEVNAME(sc));
1429ec9c868Sjsing 	else
1439ec9c868Sjsing 		aml_freevalue(&ret);
144834f78e1Sjsing }
145834f78e1Sjsing 
146834f78e1Sjsing int
acpiasus_notify(struct aml_node * node,int notify,void * arg)147834f78e1Sjsing acpiasus_notify(struct aml_node *node, int notify, void *arg)
148834f78e1Sjsing {
149834f78e1Sjsing 	struct acpiasus_softc *sc = arg;
150834f78e1Sjsing 
151a02c5301Srobert 	if (notify >= ASUS_NOTIFY_BRIGHTNESSLOW &&
152a02c5301Srobert 	    notify <= ASUS_NOTIFY_BRIGHTNESSHIGH) {
153a02c5301Srobert #ifdef ACPIASUS_DEBUG
154834f78e1Sjsing 		printf("%s: brightness %d percent\n", DEVNAME(sc),
155834f78e1Sjsing 		    (notify & 0xf) * 100 / 0xf);
156834f78e1Sjsing #endif
157834f78e1Sjsing 		return 0;
158834f78e1Sjsing 	}
159834f78e1Sjsing 
160834f78e1Sjsing 	switch (notify) {
161a02c5301Srobert 	case ASUS_NOTIFY_WIRELESSON:	/* Handled by AML. */
162a02c5301Srobert 	case ASUS_NOTIFY_WIRELESSOFF:	/* Handled by AML. */
163834f78e1Sjsing 		break;
164a02c5301Srobert 	case ASUS_NOTIFY_TASKSWITCH:
165834f78e1Sjsing 		break;
166a02c5301Srobert 	case ASUS_NOTIFY_DISPLAYCYCLEDOWN:
167a02c5301Srobert 	case ASUS_NOTIFY_DISPLAYCYCLEUP:
168834f78e1Sjsing 		break;
169834f78e1Sjsing #if NAUDIO > 0 && NWSKBD > 0
170a02c5301Srobert 	case ASUS_NOTIFY_VOLUMEMUTE:
171012023bfSmpi 		wskbd_set_mixervolume(0, 1);
172834f78e1Sjsing 		break;
173a02c5301Srobert 	case ASUS_NOTIFY_VOLUMEDOWN:
174012023bfSmpi 		wskbd_set_mixervolume(-1, 1);
175834f78e1Sjsing 		break;
176a02c5301Srobert 	case ASUS_NOTIFY_VOLUMEUP:
177012023bfSmpi 		wskbd_set_mixervolume(1, 1);
178834f78e1Sjsing 		break;
179834f78e1Sjsing #else
180a02c5301Srobert 	case ASUS_NOTIFY_VOLUMEMUTE:
181a02c5301Srobert 	case ASUS_NOTIFY_VOLUMEDOWN:
182a02c5301Srobert 	case ASUS_NOTIFY_VOLUMEUP:
183834f78e1Sjsing 		break;
184834f78e1Sjsing #endif
185a02c5301Srobert 	case ASUS_NOTIFY_POWERCONNECT:
186a02c5301Srobert 	case ASUS_NOTIFY_POWERDISCONNECT:
187a02c5301Srobert 		break;
188a02c5301Srobert 
189a02c5301Srobert 	case ASUS_NOTIFY_LCDSWITCHOFF0:
190a02c5301Srobert 	case ASUS_NOTIFY_LCDSWITCHOFF1:
191a02c5301Srobert 		break;
192a02c5301Srobert 
193a02c5301Srobert 	case ASUS_NOTIFY_LCDCHANGERES:
194a02c5301Srobert 		break;
195a02c5301Srobert 
196a02c5301Srobert 	case ASUS_NOTIFY_USERDEF0:
197a02c5301Srobert 	case ASUS_NOTIFY_USERDEF1:
1989ec9c868Sjsing 		break;
1999ec9c868Sjsing 
200834f78e1Sjsing 	default:
201834f78e1Sjsing 		printf("%s: unknown event 0x%02x\n", DEVNAME(sc), notify);
202834f78e1Sjsing 		break;
203834f78e1Sjsing 	}
204834f78e1Sjsing 
205834f78e1Sjsing 	return 0;
206834f78e1Sjsing }
207834f78e1Sjsing 
20860e24e29Sderaadt int
acpiasus_activate(struct device * self,int act)20960e24e29Sderaadt acpiasus_activate(struct device *self, int act)
210834f78e1Sjsing {
21160e24e29Sderaadt 	struct acpiasus_softc *sc = (struct acpiasus_softc *)self;
212834f78e1Sjsing 	struct aml_value cmd;
213834f78e1Sjsing 	struct aml_value ret;
214834f78e1Sjsing 
21560e24e29Sderaadt 	switch (act) {
216b4b59f5cSderaadt 	case DVACT_WAKEUP:
21760e24e29Sderaadt 		acpiasus_init(self);
218834f78e1Sjsing 
2199ec9c868Sjsing 		bzero(&cmd, sizeof(cmd));
220834f78e1Sjsing 		cmd.type = AML_OBJTYPE_INTEGER;
221834f78e1Sjsing 		cmd.v_integer = ASUS_SDSP_LCD;
222834f78e1Sjsing 
223834f78e1Sjsing 		if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "SDSP", 1,
224834f78e1Sjsing 		    &cmd, &ret))
225834f78e1Sjsing 			printf("%s: no SDSP\n", DEVNAME(sc));
2269ec9c868Sjsing 		else
2279ec9c868Sjsing 			aml_freevalue(&ret);
228834f78e1Sjsing 		break;
229834f78e1Sjsing 	}
23060e24e29Sderaadt 	return (0);
231834f78e1Sjsing }
232