summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2016-10-04 23:02:03 +0000
committerderaadt <deraadt@openbsd.org>2016-10-04 23:02:03 +0000
commitf07ad920038298678ac8358268a14ad4467b172e (patch)
treefc3f965445c4d9e79d72c3b1f4f8184eb1475b69
parentZap stray whitespace. (diff)
downloadwireguard-openbsd-f07ad920038298678ac8358268a14ad4467b172e.tar.xz
wireguard-openbsd-f07ad920038298678ac8358268a14ad4467b172e.zip
At acpithinkpad attach time determine the value of the mute, and defer
telling the audio subsystem about this later on in boot. (Mute state is maintained by the BIOS over a suspend, hibernate, reboot, etc -- this may be last missing piece of the puzzle we tore our hair out in Brisbane) diagnosis and code by Anton Lindqvist, ok ratchov
-rw-r--r--sys/dev/acpi/acpithinkpad.c44
-rw-r--r--sys/dev/audio.c40
2 files changed, 78 insertions, 6 deletions
diff --git a/sys/dev/acpi/acpithinkpad.c b/sys/dev/acpi/acpithinkpad.c
index 04731bbc3e3..5d5ad752a7e 100644
--- a/sys/dev/acpi/acpithinkpad.c
+++ b/sys/dev/acpi/acpithinkpad.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpithinkpad.c,v 1.52 2016/05/05 05:12:49 jsg Exp $ */
+/* $OpenBSD: acpithinkpad.c,v 1.53 2016/10/04 23:02:05 deraadt Exp $ */
/*
* Copyright (c) 2008 joshua stein <jcs@openbsd.org>
*
@@ -105,6 +105,8 @@
#define THINKPAD_NSENSORS 9
#define THINKPAD_NTEMPSENSORS 8
+#define THINKPAD_ECOFFSET_VOLUME 0x30
+#define THINKPAD_ECOFFSET_VOLUME_MUTE_MASK 0x40
#define THINKPAD_ECOFFSET_FANLO 0x84
#define THINKPAD_ECOFFSET_FANHI 0x85
@@ -163,6 +165,9 @@ void thinkpad_sensor_attach(struct acpithinkpad_softc *sc);
void thinkpad_sensor_refresh(void *);
#if NAUDIO > 0 && NWSKBD > 0
+void thinkpad_attach_deferred(void *);
+int thinkpad_get_volume_mute(struct acpithinkpad_softc *);
+extern int wskbd_set_mixermute(long, long);
extern int wskbd_set_mixervolume(long, long);
#endif
@@ -258,6 +263,12 @@ thinkpad_attach(struct device *parent, struct device *self, void *aux)
printf("\n");
+#if NAUDIO > 0 && NWSKBD > 0
+ /* Defer speaker mute */
+ if (thinkpad_get_volume_mute(sc) == 1)
+ startuphook_establish(thinkpad_attach_deferred, sc);
+#endif
+
/* Set event mask to receive everything */
thinkpad_enable_events(sc);
thinkpad_sensor_attach(sc);
@@ -589,12 +600,20 @@ thinkpad_activate(struct device *self, int act)
struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self;
int64_t res;
+#if NAUDIO > 0 && NWSKBD > 0
+ int mute;
+#endif
- switch(act) {
+ switch (act) {
case DVACT_WAKEUP:
if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "GTRW",
0, NULL, &res) == 0)
thinkpad_adaptive_change(sc);
+#if NAUDIO > 0 && NWSKBD > 0
+ mute = thinkpad_get_volume_mute(sc);
+ if (mute != -1)
+ wskbd_set_mixermute(mute, 1);
+#endif
break;
}
return (0);
@@ -722,3 +741,24 @@ thinkpad_set_param(struct wsdisplay_param *dp)
return -1;
}
}
+
+#if NAUDIO > 0 && NWSKBD > 0
+void
+thinkpad_attach_deferred(void *v __unused)
+{
+ wskbd_set_mixermute(1, 1);
+}
+
+int
+thinkpad_get_volume_mute(struct acpithinkpad_softc *sc)
+{
+ u_int8_t vol = 0;
+
+ if (sc->sc_acpi->sc_ec == NULL)
+ return (-1);
+
+ acpiec_read(sc->sc_acpi->sc_ec, THINKPAD_ECOFFSET_VOLUME, 1, &vol);
+ return ((vol & THINKPAD_ECOFFSET_VOLUME_MUTE_MASK) ==
+ THINKPAD_ECOFFSET_VOLUME_MUTE_MASK);
+}
+#endif
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index d3a5892d523..cd8d0834b0b 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: audio.c,v 1.153 2016/09/19 06:46:43 ratchov Exp $ */
+/* $OpenBSD: audio.c,v 1.154 2016/10/04 23:02:03 deraadt Exp $ */
/*
* Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
*
@@ -80,7 +80,10 @@ struct wskbd_vol
int step; /* increment/decrement step */
int nch; /* channels in the value control */
int val_pending; /* pending change of val */
- int mute_pending; /* pending mute toggles */
+ int mute_pending; /* pending change of mute */
+#define WSKBD_MUTE_TOGGLE 1
+#define WSKBD_MUTE_DISABLE 2
+#define WSKBD_MUTE_ENABLE 3
};
#endif
@@ -1885,7 +1888,17 @@ wskbd_mixer_update(struct audio_softc *sc, struct wskbd_vol *vol)
DPRINTF("%s: get mute err = %d\n", DEVNAME(sc), error);
return;
}
- ctrl.un.ord = ctrl.un.ord ^ mute_pending;
+ switch (mute_pending) {
+ case WSKBD_MUTE_TOGGLE:
+ ctrl.un.ord = !ctrl.un.ord;
+ break;
+ case WSKBD_MUTE_DISABLE:
+ ctrl.un.ord = 0;
+ break;
+ case WSKBD_MUTE_ENABLE:
+ ctrl.un.ord = 1;
+ break;
+ }
DPRINTFN(1, "%s: wskbd mute setting to %d\n",
DEVNAME(sc), ctrl.un.ord);
error = sc->ops->set_port(sc->arg, &ctrl);
@@ -1936,6 +1949,25 @@ wskbd_mixer_cb(void *addr)
}
int
+wskbd_set_mixermute(long mute, long out)
+{
+ struct audio_softc *sc;
+ struct wskbd_vol *vol;
+
+ sc = (struct audio_softc *)device_lookup(&audio_cd, 0);
+ if (sc == NULL)
+ return ENODEV;
+ vol = out ? &sc->spkr : &sc->mic;
+ vol->mute_pending = mute ? WSKBD_MUTE_ENABLE : WSKBD_MUTE_DISABLE;
+ if (!sc->wskbd_taskset) {
+ task_set(&sc->wskbd_task, wskbd_mixer_cb, sc);
+ task_add(systq, &sc->wskbd_task);
+ sc->wskbd_taskset = 1;
+ }
+ return 0;
+}
+
+int
wskbd_set_mixervolume(long dir, long out)
{
struct audio_softc *sc;
@@ -1946,7 +1978,7 @@ wskbd_set_mixervolume(long dir, long out)
return ENODEV;
vol = out ? &sc->spkr : &sc->mic;
if (dir == 0)
- vol->mute_pending ^= 1;
+ vol->mute_pending ^= WSKBD_MUTE_TOGGLE;
else
vol->val_pending += dir;
if (!sc->wskbd_taskset) {