diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2018-04-11 04:48:32 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2018-04-11 04:48:32 +0000 |
commit | 3205e3f3fc34ebd1ddbb10ee8a36f144504cc3ee (patch) | |
tree | 2bdd8e89d1d3fb1bdd150a8bd2cf1973f83e2628 /sys/dev | |
parent | c8805f60f4c1a147a9fae39c6b2ccedc50354ffd (diff) |
Add mixer save/restore capability to the audio(4) driver and
use it during suspend/resume. Remove driver-specific mixer
save/restore bits that don't need to be duplicated in every
low-lever driver.
ok mpi
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/audio.c | 65 | ||||
-rw-r--r-- | sys/dev/ic/ac97.c | 19 | ||||
-rw-r--r-- | sys/dev/ic/ac97.h | 10 | ||||
-rw-r--r-- | sys/dev/pci/azalia.c | 76 | ||||
-rw-r--r-- | sys/dev/pci/cmpci.c | 7 | ||||
-rw-r--r-- | sys/dev/pci/eap.c | 20 | ||||
-rw-r--r-- | sys/dev/pci/esa.c | 3 | ||||
-rw-r--r-- | sys/dev/pci/maestro.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/neo.c | 3 |
9 files changed, 72 insertions, 135 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c index 9765b1d11a9..ce73f818233 100644 --- a/sys/dev/audio.c +++ b/sys/dev/audio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: audio.c,v 1.168 2018/03/21 07:02:02 ratchov Exp $ */ +/* $OpenBSD: audio.c,v 1.169 2018/04/11 04:48:31 ratchov Exp $ */ /* * Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org> * @@ -111,6 +111,8 @@ struct audio_softc { int offs; /* offset between play & rec dir */ void (*conv_enc)(unsigned char *, int); /* encode to native */ void (*conv_dec)(unsigned char *, int); /* decode to user */ + struct mixer_ctrl *mix_ents; /* mixer state for suspend/resume */ + int mix_nent; /* size of mixer state */ #if NWSKBD > 0 struct wskbd_vol spkr, mic; struct task wskbd_task; @@ -994,6 +996,8 @@ audio_attach(struct device *parent, struct device *self, void *aux) struct audio_softc *sc = (void *)self; struct audio_attach_args *sa = aux; struct audio_hw_if *ops = sa->hwif; + struct mixer_devinfo *mi; + struct mixer_ctrl *ent; void *arg = sa->hdl; int error; @@ -1053,12 +1057,57 @@ audio_attach(struct device *parent, struct device *self, void *aux) sc->round = 960; sc->nblks = 2; sc->play.pos = sc->play.xrun = sc->rec.pos = sc->rec.xrun = 0; + + /* + * allocate an array of mixer_ctrl structures to save the + * mixer state and prefill them. + */ + + mi = malloc(sizeof(struct mixer_devinfo), M_TEMP, M_WAITOK); + + sc->mix_nent = 0; + mi->index = 0; + while (1) { + if (sc->ops->query_devinfo(sc->arg, mi) != 0) + break; + switch (mi->type) { + case AUDIO_MIXER_SET: + case AUDIO_MIXER_ENUM: + case AUDIO_MIXER_VALUE: + sc->mix_nent++; + } + mi->index++; + } + + sc->mix_ents = mallocarray(sc->mix_nent, + sizeof(struct mixer_ctrl), M_DEVBUF, M_WAITOK); + + ent = sc->mix_ents; + mi->index = 0; + while (1) { + if (sc->ops->query_devinfo(sc->arg, mi) != 0) + break; + switch (mi->type) { + case AUDIO_MIXER_VALUE: + ent->un.value.num_channels = mi->un.v.num_channels; + /* FALLTHROUGH */ + case AUDIO_MIXER_SET: + case AUDIO_MIXER_ENUM: + ent->dev = mi->index; + ent->type = mi->type; + ent++; + } + mi->index++; + } + + free(mi, M_TEMP, sizeof(struct mixer_devinfo)); } int audio_activate(struct device *self, int act) { struct audio_softc *sc = (struct audio_softc *)self; + int i; switch (act) { case DVACT_QUIESCE: @@ -1081,12 +1130,25 @@ audio_activate(struct device *self, int act) */ if (sc->mode != 0 && sc->active) audio_stop_do(sc); + + /* + * save mixer state + */ + for (i = 0; i != sc->mix_nent; i++) + sc->ops->get_port(sc->arg, sc->mix_ents + i); + DPRINTF("%s: quiesce: active = %d\n", DEVNAME(sc), sc->active); break; case DVACT_WAKEUP: DPRINTF("%s: wakeup: active = %d\n", DEVNAME(sc), sc->active); /* + * restore mixer state + */ + for (i = 0; i != sc->mix_nent; i++) + sc->ops->set_port(sc->arg, sc->mix_ents + i); + + /* * keep buffer usage the same, but set start pointer to * the beginning of the buffer. * @@ -1156,6 +1218,7 @@ audio_detach(struct device *self, int flags) } /* free resources */ + free(sc->mix_ents, M_DEVBUF, sc->mix_nent * sizeof(struct mixer_ctrl)); audio_buf_done(sc, &sc->play); audio_buf_done(sc, &sc->rec); return 0; diff --git a/sys/dev/ic/ac97.c b/sys/dev/ic/ac97.c index db5a25bf414..89b82a9fee5 100644 --- a/sys/dev/ic/ac97.c +++ b/sys/dev/ic/ac97.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ac97.c,v 1.83 2017/08/22 10:41:59 mestre Exp $ */ +/* $OpenBSD: ac97.c,v 1.84 2018/04/11 04:48:31 ratchov Exp $ */ /* * Copyright (c) 1999, 2000 Constantine Sapuntzakis @@ -337,7 +337,6 @@ void ac97_unlock(struct ac97_codec_if *); int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *); int ac97_get_portnum_by_name(struct ac97_codec_if *, char *, char *, char *); -void ac97_restore_shadow(struct ac97_codec_if *); int ac97_set_rate(struct ac97_codec_if *codec_if, int target, u_long *rate); void ac97_set_clock(struct ac97_codec_if *codec_if, unsigned int clock); u_int16_t ac97_get_extcaps(struct ac97_codec_if *codec_if); @@ -355,7 +354,6 @@ struct ac97_codec_if_vtbl ac97civ = { ac97_mixer_set_port, ac97_query_devinfo, ac97_get_portnum_by_name, - ac97_restore_shadow, ac97_get_extcaps, ac97_set_rate, ac97_set_clock, @@ -646,19 +644,6 @@ ac97_setup_defaults(struct ac97_softc *as) } } -void -ac97_restore_shadow(struct ac97_codec_if *self) -{ - struct ac97_softc *as = (struct ac97_softc *)self; - int idx; - - for (idx = 0; idx < nitems(source_info); idx++) { - const struct ac97_source_info *si = &source_info[idx]; - - ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]); - } -} - int ac97_str_equal(const char *a, const char *b) { @@ -967,8 +952,6 @@ ac97_resume(struct ac97_host_if *host_if, struct ac97_codec_if *codec_if) host_if->write(host_if->arg, AC97_REG_RESET, 0); DELAY(10000); - codec_if->vtbl->restore_ports(codec_if); - if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA | AC97_EXT_AUDIO_SPDIF | AC97_EXT_AUDIO_VRM | AC97_EXT_AUDIO_CDAC | AC97_EXT_AUDIO_SDAC diff --git a/sys/dev/ic/ac97.h b/sys/dev/ic/ac97.h index df08f5ff938..0df86c085e9 100644 --- a/sys/dev/ic/ac97.h +++ b/sys/dev/ic/ac97.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ac97.h,v 1.26 2016/09/14 06:12:19 ratchov Exp $ */ +/* $OpenBSD: ac97.h,v 1.27 2018/04/11 04:48:31 ratchov Exp $ */ /* * Copyright (c) 1999 Constantine Sapuntzakis @@ -62,14 +62,6 @@ struct ac97_codec_if_vtbl { int (*query_devinfo)(struct ac97_codec_if *addr, mixer_devinfo_t *cp); int (*get_portnum_by_name)(struct ac97_codec_if *addr, char *class, char *device, char *qualifier); - - /* - * The AC97 codec driver records the various port settings. - * This function can be used to restore the port settings, e.g. - * after resume from a laptop suspend to disk. - */ - void (*restore_ports)(struct ac97_codec_if *addr); - u_int16_t (*get_caps)(struct ac97_codec_if *codec_if); int (*set_rate)(struct ac97_codec_if *codec_if, int target, u_long *rate); diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index a185fb6958e..31e45786575 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.c,v 1.241 2018/04/02 08:40:46 henning Exp $ */ +/* $OpenBSD: azalia.c,v 1.242 2018/04/11 04:48:31 ratchov Exp $ */ /* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */ /*- @@ -272,9 +272,6 @@ int azalia_params2fmt(const audio_params_t *, uint16_t *); int azalia_match_format(codec_t *, int, audio_params_t *); int azalia_set_params_sub(codec_t *, int, audio_params_t *); -void azalia_save_mixer(codec_t *); -void azalia_restore_mixer(codec_t *); - int azalia_suspend(azalia_t *); int azalia_resume(azalia_t *); int azalia_resume_codec(codec_t *); @@ -1357,7 +1354,6 @@ azalia_suspend(azalia_t *az) timeout_del(&az->unsol_to); - azalia_save_mixer(&az->codecs[az->codecno]); /* azalia_halt_{corb,rirb}() only fail if the {CORB,RIRB} can't * be stopped and azalia_init_{corb,rirb}(), which starts the * {CORB,RIRB}, first calls azalia_halt_{corb,rirb}(). If halt @@ -1421,8 +1417,6 @@ azalia_resume_codec(codec_t *this) return err; } - azalia_restore_mixer(this); - return(0); } @@ -1457,74 +1451,6 @@ azalia_resume(azalia_t *az) return 0; } -void -azalia_save_mixer(codec_t *this) -{ - mixer_item_t *m; - mixer_ctrl_t mc; - int i; - - for (i = 0; i < this->nmixers; i++) { - m = &this->mixers[i]; - if (m->nid == this->playvols.master) - continue; - mc.dev = i; - mc.type = m->devinfo.type; - azalia_mixer_get(this, m->nid, m->target, &mc); - switch (mc.type) { - case AUDIO_MIXER_ENUM: - m->saved.ord = mc.un.ord; - break; - case AUDIO_MIXER_SET: - m->saved.mask = mc.un.mask; - break; - case AUDIO_MIXER_VALUE: - m->saved.value = mc.un.value; - break; - case AUDIO_MIXER_CLASS: - break; - default: - DPRINTF(("%s: invalid mixer type in mixer %d\n", - __func__, mc.dev)); - break; - } - } -} - -void -azalia_restore_mixer(codec_t *this) -{ - mixer_item_t *m; - mixer_ctrl_t mc; - int i; - - for (i = 0; i < this->nmixers; i++) { - m = &this->mixers[i]; - if (m->nid == this->playvols.master) - continue; - mc.dev = i; - mc.type = m->devinfo.type; - switch (mc.type) { - case AUDIO_MIXER_ENUM: - mc.un.ord = m->saved.ord; - break; - case AUDIO_MIXER_SET: - mc.un.mask = m->saved.mask; - break; - case AUDIO_MIXER_VALUE: - mc.un.value = m->saved.value; - break; - case AUDIO_MIXER_CLASS: - break; - default: - DPRINTF(("%s: invalid mixer type in mixer %d\n", - __func__, mc.dev)); - continue; - } - azalia_mixer_set(this, m->nid, m->target, &mc); - } -} - /* ================================================================ * HDA codec functions * ================================================================ */ diff --git a/sys/dev/pci/cmpci.c b/sys/dev/pci/cmpci.c index 9ef3939823f..ec5043d749c 100644 --- a/sys/dev/pci/cmpci.c +++ b/sys/dev/pci/cmpci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmpci.c,v 1.42 2016/09/19 06:46:44 ratchov Exp $ */ +/* $OpenBSD: cmpci.c,v 1.43 2018/04/11 04:48:31 ratchov Exp $ */ /* $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $ */ /* @@ -528,12 +528,7 @@ cmpci_activate(struct device *self, int act) int cmpci_resume(struct cmpci_softc *sc) { - int i; - cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0); - for (i = 0; i < CMPCI_NDEVS; i++) - cmpci_set_mixer_gain(sc, i); - return 0; } diff --git a/sys/dev/pci/eap.c b/sys/dev/pci/eap.c index 69f71d044b2..f7df55bac1d 100644 --- a/sys/dev/pci/eap.c +++ b/sys/dev/pci/eap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eap.c,v 1.53 2016/09/19 06:46:44 ratchov Exp $ */ +/* $OpenBSD: eap.c,v 1.54 2018/04/11 04:48:31 ratchov Exp $ */ /* $NetBSD: eap.c,v 1.46 2001/09/03 15:07:37 reinoud Exp $ */ /* @@ -600,7 +600,6 @@ eap_attach(struct device *parent, struct device *self, void *aux) int eap_resume(struct eap_softc *sc) { - mixer_ctrl_t ctl; int i; if (!sc->sc_1371) { @@ -616,23 +615,6 @@ eap_resume(struct eap_softc *sc) eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); eap1370_write_codec(sc, AK_CS, 0x0); - bzero(&ctl, sizeof(ctl)); - - ctl.dev = EAP_RECORD_SOURCE; - ctl.type = AUDIO_MIXER_SET; - ctl.un.mask = sc->sc_record_source; - eap1370_hw_if.set_port(sc, &ctl); - - ctl.dev = EAP_INPUT_SOURCE; - ctl.type = AUDIO_MIXER_SET; - ctl.un.mask = sc->sc_input_source; - eap1370_hw_if.set_port(sc, &ctl); - - eap1370_set_mixer(sc, AK_MGAIN, sc->sc_mic_preamp); - - for (i = EAP_MASTER_VOL; i < EAP_MIC_VOL; i++) - eap1370_write_codec(sc, i, sc->sc_port[i]); - } else { /* clean slate */ diff --git a/sys/dev/pci/esa.c b/sys/dev/pci/esa.c index 9ee7837269e..ff4f65a8e6c 100644 --- a/sys/dev/pci/esa.c +++ b/sys/dev/pci/esa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: esa.c,v 1.33 2017/09/08 05:36:52 deraadt Exp $ */ +/* $OpenBSD: esa.c,v 1.34 2018/04/11 04:48:31 ratchov Exp $ */ /* $NetBSD: esa.c,v 1.12 2002/03/24 14:17:35 jmcneill Exp $ */ /* @@ -1514,7 +1514,6 @@ esa_activate(struct device *self, int act) break; case DVACT_RESUME: esa_resume(sc); - (sc->codec_if->vtbl->restore_ports)(sc->codec_if); break; } return 0; diff --git a/sys/dev/pci/maestro.c b/sys/dev/pci/maestro.c index d7426e230ac..f3523120203 100644 --- a/sys/dev/pci/maestro.c +++ b/sys/dev/pci/maestro.c @@ -1,4 +1,4 @@ -/* $OpenBSD: maestro.c,v 1.42 2016/09/19 06:46:44 ratchov Exp $ */ +/* $OpenBSD: maestro.c,v 1.43 2018/04/11 04:48:31 ratchov Exp $ */ /* $FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.3 2000/11/21 12:22:11 julian Exp $ */ /* * FreeBSD's ESS Agogo/Maestro driver @@ -1393,8 +1393,6 @@ maestro_activate(struct device *self, int act) DPRINTF(("maestro: power resume\n")); maestro_init(sc); /* Restore codec settings */ - if (sc->codec_if) - sc->codec_if->vtbl->restore_ports(sc->codec_if); if (sc->play.mode & MAESTRO_RUNNING) maestro_channel_start(&sc->play); if (sc->record.mode & MAESTRO_RUNNING) diff --git a/sys/dev/pci/neo.c b/sys/dev/pci/neo.c index aeb3a6d7006..721262ea80f 100644 --- a/sys/dev/pci/neo.c +++ b/sys/dev/pci/neo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neo.c,v 1.32 2016/09/19 06:46:44 ratchov Exp $ */ +/* $OpenBSD: neo.c,v 1.33 2018/04/11 04:48:31 ratchov Exp $ */ /* * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> @@ -612,7 +612,6 @@ neo_activate(struct device *self, int act) break; case DVACT_RESUME: nm_init(sc); - (sc->codec_if->vtbl->restore_ports)(sc->codec_if); break; } return 0; |