xref: /openbsd-src/sys/dev/acpi/acpisurface.c (revision 674f03e5c4ecfc019c9af4c0aad680e8eaae9d0b)
1*674f03e5Sderaadt /*	$OpenBSD: acpisurface.c,v 1.3 2024/08/15 17:30:40 deraadt Exp $	*/
2144c780aSmlarkin /*
3144c780aSmlarkin  * Copyright (c) 2018 Mike Larkin <mlarkin@openbsd.org>
4144c780aSmlarkin  *
5144c780aSmlarkin  * Permission to use, copy, modify, and distribute this software for any
6144c780aSmlarkin  * purpose with or without fee is hereby granted, provided that the above
7144c780aSmlarkin  * copyright notice and this permission notice appear in all copies.
8144c780aSmlarkin  *
9144c780aSmlarkin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10144c780aSmlarkin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11144c780aSmlarkin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12144c780aSmlarkin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13144c780aSmlarkin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14144c780aSmlarkin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15144c780aSmlarkin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16144c780aSmlarkin  */
17144c780aSmlarkin 
18144c780aSmlarkin #include <sys/param.h>
19144c780aSmlarkin #include <sys/systm.h>
20144c780aSmlarkin 
21144c780aSmlarkin #include <dev/acpi/acpireg.h>
22144c780aSmlarkin #include <dev/acpi/acpivar.h>
23144c780aSmlarkin #include <dev/acpi/acpidev.h>
24144c780aSmlarkin #include <dev/acpi/amltypes.h>
25144c780aSmlarkin #include <dev/acpi/dsdt.h>
26144c780aSmlarkin 
27144c780aSmlarkin #include "audio.h"
28144c780aSmlarkin #include "wskbd.h"
29144c780aSmlarkin 
30144c780aSmlarkin /* #define ACPISURFACE_DEBUG */
31144c780aSmlarkin 
32144c780aSmlarkin #ifdef ACPISURFACE_DEBUG
33144c780aSmlarkin #define DPRINTF(x...)   do { printf(x); } while(0)
34144c780aSmlarkin #else
35144c780aSmlarkin #define DPRINTF(x...)
36144c780aSmlarkin #endif /* ACPISURFACE_DEBUG */
37144c780aSmlarkin 
38144c780aSmlarkin #define	SURFACE_ACCESSORY_REMOVED	0xC8
39144c780aSmlarkin #define	SURFACE_WINDOWS_KEY_PRESSED	0xC4
40144c780aSmlarkin #define SURFACE_WINDOWS_KEY_RELEASED	0xC5
41144c780aSmlarkin #define SURFACE_VOLUME_UP_PRESSED	0xC0
42144c780aSmlarkin #define SURFACE_VOLUME_UP_RELEASED	0xC1
43144c780aSmlarkin #define SURFACE_VOLUME_DOWN_PRESSED	0xC2
44144c780aSmlarkin #define SURFACE_VOLUME_DOWN_RELEASED	0xC3
45144c780aSmlarkin #define SURFACE_POWER_BUTTON_PRESSED	0xC6
46144c780aSmlarkin #define SURFACE_POWER_BUTTON_RELEASED	0xC7
47144c780aSmlarkin 
48144c780aSmlarkin struct acpisurface_softc {
49144c780aSmlarkin 	struct device		 sc_dev;
50144c780aSmlarkin 
51144c780aSmlarkin 	struct acpiec_softc     *sc_ec;
52144c780aSmlarkin 	struct acpi_softc	*sc_acpi;
53144c780aSmlarkin 	struct aml_node		*sc_devnode;
54144c780aSmlarkin };
55144c780aSmlarkin 
56144c780aSmlarkin int	surface_match(struct device *, void *, void *);
57144c780aSmlarkin void	surface_attach(struct device *, struct device *, void *);
58144c780aSmlarkin int	surface_hotkey(struct aml_node *, int, void *);
59144c780aSmlarkin 
60144c780aSmlarkin #if NAUDIO > 0 && NWSKBD > 0
61144c780aSmlarkin extern int wskbd_set_mixervolume(long, long);
62144c780aSmlarkin #endif
63144c780aSmlarkin 
64471aeecfSnaddy const struct cfattach acpisurface_ca = {
65144c780aSmlarkin 	sizeof(struct acpisurface_softc), surface_match, surface_attach,
66144c780aSmlarkin 	NULL, NULL
67144c780aSmlarkin };
68144c780aSmlarkin 
69144c780aSmlarkin struct cfdriver acpisurface_cd = {
70144c780aSmlarkin 	NULL, "acpisurface", DV_DULL
71144c780aSmlarkin };
72144c780aSmlarkin 
73144c780aSmlarkin const char *acpisurface_hids[] = {
74144c780aSmlarkin 	"MSHW0040",
75144c780aSmlarkin 	NULL
76144c780aSmlarkin };
77144c780aSmlarkin 
78144c780aSmlarkin int
79144c780aSmlarkin surface_match(struct device *parent, void *match, void *aux)
80144c780aSmlarkin {
81144c780aSmlarkin 	struct acpi_attach_args	*aa = aux;
82144c780aSmlarkin 	struct cfdata *cf = match;
83144c780aSmlarkin 
84144c780aSmlarkin 	if (!acpi_matchhids(aa, acpisurface_hids, cf->cf_driver->cd_name))
85144c780aSmlarkin 		return (0);
86144c780aSmlarkin 
87144c780aSmlarkin 	return (1);
88144c780aSmlarkin }
89144c780aSmlarkin 
90144c780aSmlarkin void
91144c780aSmlarkin surface_attach(struct device *parent, struct device *self, void *aux)
92144c780aSmlarkin {
93144c780aSmlarkin 	struct acpisurface_softc *sc = (struct acpisurface_softc *)self;
94144c780aSmlarkin 	struct acpi_attach_args	*aa = aux;
95144c780aSmlarkin 
96144c780aSmlarkin 	sc->sc_acpi = (struct acpi_softc *)parent;
97144c780aSmlarkin 	sc->sc_devnode = aa->aaa_node;
98144c780aSmlarkin 
99144c780aSmlarkin 	printf("\n");
100144c780aSmlarkin 
101144c780aSmlarkin 	/* Run surface_hotkey on button presses */
102144c780aSmlarkin 	aml_register_notify(sc->sc_devnode, aa->aaa_dev,
103144c780aSmlarkin 	    surface_hotkey, sc, ACPIDEV_NOPOLL);
104144c780aSmlarkin }
105144c780aSmlarkin 
106144c780aSmlarkin int
107144c780aSmlarkin surface_hotkey(struct aml_node *node, int notify_type, void *arg)
108144c780aSmlarkin {
109144c780aSmlarkin 	struct acpisurface_softc *sc = arg;
110144c780aSmlarkin 
111144c780aSmlarkin 	switch (notify_type) {
112144c780aSmlarkin 	case SURFACE_ACCESSORY_REMOVED:
113144c780aSmlarkin 		DPRINTF("%s: accessory removed\n", __func__);
114144c780aSmlarkin 		break;
115144c780aSmlarkin 	case SURFACE_VOLUME_UP_PRESSED:
116144c780aSmlarkin 		DPRINTF("%s: volume up pressed\n", __func__);
117144c780aSmlarkin #if NAUDIO > 0 && NWSKBD > 0
118144c780aSmlarkin 		wskbd_set_mixervolume(1, 10);
119144c780aSmlarkin #endif
120144c780aSmlarkin 		break;
121144c780aSmlarkin 	case SURFACE_VOLUME_UP_RELEASED:
122144c780aSmlarkin 		DPRINTF("%s: volume up released\n", __func__);
123144c780aSmlarkin 		break;
124144c780aSmlarkin 	case SURFACE_VOLUME_DOWN_PRESSED:
125144c780aSmlarkin 		DPRINTF("%s: volume down pressed\n", __func__);
126144c780aSmlarkin #if NAUDIO > 0 && NWSKBD > 0
127144c780aSmlarkin 		wskbd_set_mixervolume(-1, 10);
128144c780aSmlarkin #endif
129144c780aSmlarkin 		break;
130144c780aSmlarkin 	case SURFACE_VOLUME_DOWN_RELEASED:
131144c780aSmlarkin 		DPRINTF("%s: volume down released\n", __func__);
132144c780aSmlarkin 		break;
133144c780aSmlarkin 	case SURFACE_POWER_BUTTON_PRESSED:
134144c780aSmlarkin 		DPRINTF("%s: power button pressed\n", __func__);
135144c780aSmlarkin 		break;
136144c780aSmlarkin 	case SURFACE_POWER_BUTTON_RELEASED:
137144c780aSmlarkin 		DPRINTF("%s: power button released\n", __func__);
138144c780aSmlarkin 		acpi_addtask(sc->sc_acpi, acpi_powerdown_task,
139144c780aSmlarkin 		    sc->sc_acpi, 0);
140144c780aSmlarkin 		break;
141144c780aSmlarkin 	case SURFACE_WINDOWS_KEY_PRESSED:
142144c780aSmlarkin 		DPRINTF("%s: windows key pressed\n", __func__);
143144c780aSmlarkin 		break;
144144c780aSmlarkin 	case SURFACE_WINDOWS_KEY_RELEASED:
145144c780aSmlarkin 		DPRINTF("%s: windows key released\n", __func__);
146144c780aSmlarkin 		break;
147144c780aSmlarkin 	default:
148144c780aSmlarkin 		DPRINTF("%s: unknown notification 0x%x\n", __func__,
149144c780aSmlarkin 		    notify_type);
150144c780aSmlarkin 	}
151144c780aSmlarkin 
152144c780aSmlarkin 	return (0);
153144c780aSmlarkin }
154