summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2018-04-11 04:48:32 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2018-04-11 04:48:32 +0000
commit3205e3f3fc34ebd1ddbb10ee8a36f144504cc3ee (patch)
tree2bdd8e89d1d3fb1bdd150a8bd2cf1973f83e2628 /sys/dev
parentc8805f60f4c1a147a9fae39c6b2ccedc50354ffd (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.c65
-rw-r--r--sys/dev/ic/ac97.c19
-rw-r--r--sys/dev/ic/ac97.h10
-rw-r--r--sys/dev/pci/azalia.c76
-rw-r--r--sys/dev/pci/cmpci.c7
-rw-r--r--sys/dev/pci/eap.c20
-rw-r--r--sys/dev/pci/esa.c3
-rw-r--r--sys/dev/pci/maestro.c4
-rw-r--r--sys/dev/pci/neo.c3
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;