diff options
author | 2016-10-04 23:02:03 +0000 | |
---|---|---|
committer | 2016-10-04 23:02:03 +0000 | |
commit | f07ad920038298678ac8358268a14ad4467b172e (patch) | |
tree | fc3f965445c4d9e79d72c3b1f4f8184eb1475b69 | |
parent | Zap stray whitespace. (diff) | |
download | wireguard-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.c | 44 | ||||
-rw-r--r-- | sys/dev/audio.c | 40 |
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) { |