diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2009-01-02 00:25:34 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2009-01-02 00:25:34 +0000 |
commit | 3e69299544dc846e3a922197aa2f6781b8f21171 (patch) | |
tree | 205f749865a82fce1f50acb327827e50fd042a56 | |
parent | 81f15b13d06ed81770cdd87c12572e22d1946a02 (diff) |
- store information about relevant volume controls along both
recording and playback paths.
- select a subset of controls that are relevant in a default
configuration for each path.
-rw-r--r-- | sys/dev/pci/azalia.c | 163 | ||||
-rw-r--r-- | sys/dev/pci/azalia.h | 17 |
2 files changed, 176 insertions, 4 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index 1ab7e62f1de..6dceb7b96a1 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.c,v 1.104 2008/12/31 22:25:42 jakemsr Exp $ */ +/* $OpenBSD: azalia.c,v 1.105 2009/01/02 00:25:33 jakemsr Exp $ */ /* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */ /*- @@ -213,6 +213,7 @@ void azalia_codec_print_audiofunc(const codec_t *); void azalia_codec_print_groups(const codec_t *); int azalia_codec_init_hp_spkr(codec_t *); int azalia_codec_find_defdac(codec_t *, int, int); +int azalia_codec_init_volgroups(codec_t *); int azalia_widget_init(widget_t *, const codec_t *, int); int azalia_widget_label_widgets(codec_t *); @@ -1301,11 +1302,15 @@ azalia_codec_init(codec_t *this) if (err) return err; - err = this->mixer_init(this); + err = azalia_codec_init_hp_spkr(this); if (err) return err; - err = azalia_codec_init_hp_spkr(this); + err = azalia_codec_init_volgroups(this); + if (err) + return err; + + err = this->mixer_init(this); if (err) return err; @@ -1376,6 +1381,158 @@ azalia_codec_find_defdac(codec_t *this, int index, int depth) } int +azalia_codec_init_volgroups(codec_t *this) +{ + const widget_t *w; + uint32_t cap, result; + int i, j, dac, err; + + j = 0; + this->playvols.mask = 0; + FOR_EACH_WIDGET(this, i) { + w = &this->w[i]; + if (w->enable == 0) + continue; + if (w->mixer_class == AZ_CLASS_RECORD) + continue; + if (!(w->widgetcap & COP_AWCAP_OUTAMP)) + continue; + if ((COP_AMPCAP_NUMSTEPS(w->outamp_cap) == 0) && + !(w->outamp_cap & COP_AMPCAP_MUTE)) + continue; + this->playvols.mask |= (1 << j); + this->playvols.slaves[j++] = w->nid; + if (j >= AZ_MAX_VOL_SLAVES) + break; + } + this->playvols.nslaves = j; + + this->playvols.cur = 0; + for (i = 0; i < this->playvols.nslaves; i++) { + w = &this->w[this->playvols.slaves[i]]; + cap = w->outamp_cap; + dac = azalia_codec_find_defdac(this, w->nid, 0); + if (dac != this->dacs.groups[this->dacs.cur].conv[0] && + dac != this->hp_dac && dac != this->spkr_dac) + continue; + if ((cap & COP_AMPCAP_MUTE) && COP_AMPCAP_NUMSTEPS(cap)) { + if (w->type == COP_AWTYPE_PIN_COMPLEX) { + err = this->comresp(this, w->nid, + CORB_GET_PIN_WIDGET_CONTROL, 0, &result); + if (!err && (result & CORB_PWC_OUTPUT)) + this->playvols.cur |= (1 << i); + } else + this->playvols.cur |= (1 << i); + } + } + if (this->playvols.cur == 0) { + for (i = 0; i < this->playvols.nslaves; i++) { + w = &this->w[this->playvols.slaves[i]]; + dac = azalia_codec_find_defdac(this, w->nid, 0); + if (dac != this->dacs.groups[this->dacs.cur].conv[0] && + dac != this->hp_dac && dac != this->spkr_dac) + continue; + if (w->type == COP_AWTYPE_PIN_COMPLEX) { + err = this->comresp(this, w->nid, + CORB_GET_PIN_WIDGET_CONTROL, 0, &result); + if (!err && (result & CORB_PWC_OUTPUT)) + this->playvols.cur |= (1 << i); + } else { + this->playvols.cur |= (1 << i); + } + } + } + + this->playvols.master = this->audiofunc; + FOR_EACH_WIDGET(this, i) { + w = &this->w[i]; + if (w->type != COP_AWTYPE_VOLUME_KNOB) + continue; + if (!(w->widgetcap & COP_AWCAP_UNSOL)) + continue; + this->playvols.master = w->nid; + break; + } + + j = 0; + this->recvols.mask = 0; + FOR_EACH_WIDGET(this, i) { + w = &this->w[i]; + if (w->enable == 0) + continue; + if (w->type == COP_AWTYPE_AUDIO_INPUT || + w->type == COP_AWTYPE_PIN_COMPLEX) { + if (!(w->widgetcap & COP_AWCAP_INAMP)) + continue; + if ((COP_AMPCAP_NUMSTEPS(w->inamp_cap) == 0) && + !(w->inamp_cap & COP_AMPCAP_MUTE)) + continue; + } else if (w->type == COP_AWTYPE_AUDIO_MIXER || + w->type == COP_AWTYPE_AUDIO_SELECTOR) { + if (w->mixer_class != AZ_CLASS_RECORD) + continue; + if (!(w->widgetcap & COP_AWCAP_OUTAMP)) + continue; + if ((COP_AMPCAP_NUMSTEPS(w->outamp_cap) == 0) && + !(w->outamp_cap & COP_AMPCAP_MUTE)) + continue; + } else { + continue; + } + this->recvols.mask |= (1 << j); + this->recvols.slaves[j++] = w->nid; + if (j >= AZ_MAX_VOL_SLAVES) + break; + } + this->recvols.nslaves = j; + + this->recvols.cur = 0; + for (i = 0; i < this->recvols.nslaves; i++) { + w = &this->w[this->recvols.slaves[i]]; + cap = w->outamp_cap; + if (w->type == COP_AWTYPE_AUDIO_INPUT || + w->type != COP_AWTYPE_PIN_COMPLEX) + cap = w->inamp_cap; + else + if (w->mixer_class != AZ_CLASS_RECORD) + continue; + if ((cap & COP_AMPCAP_MUTE) && COP_AMPCAP_NUMSTEPS(cap)) { + if (w->type == COP_AWTYPE_PIN_COMPLEX) { + err = this->comresp(this, w->nid, + CORB_GET_PIN_WIDGET_CONTROL, 0, &result); + if (!err && !(result & CORB_PWC_OUTPUT)) + this->recvols.cur |= (1 << i); + } else + this->recvols.cur |= (1 << i); + } + } + if (this->recvols.cur == 0) { + for (i = 0; i < this->recvols.nslaves; i++) { + w = &this->w[this->recvols.slaves[i]]; + cap = w->outamp_cap; + if (w->type == COP_AWTYPE_AUDIO_INPUT || + w->type != COP_AWTYPE_PIN_COMPLEX) + cap = w->inamp_cap; + else + if (w->mixer_class != AZ_CLASS_RECORD) + continue; + if (w->type == COP_AWTYPE_PIN_COMPLEX) { + err = this->comresp(this, w->nid, + CORB_GET_PIN_WIDGET_CONTROL, 0, &result); + if (!err && !(result & CORB_PWC_OUTPUT)) + this->recvols.cur |= (1 << i); + } else { + this->recvols.cur |= (1 << i); + } + } + } + + this->recvols.master = this->audiofunc; + + return 0; +} + +int azalia_codec_delete(codec_t *this) { if (this->mixer_delete != NULL) diff --git a/sys/dev/pci/azalia.h b/sys/dev/pci/azalia.h index 032687f985b..24b900f1d18 100644 --- a/sys/dev/pci/azalia.h +++ b/sys/dev/pci/azalia.h @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.h,v 1.31 2008/12/31 13:13:39 jakemsr Exp $ */ +/* $OpenBSD: azalia.h,v 1.32 2009/01/02 00:25:33 jakemsr Exp $ */ /* $NetBSD: azalia.h,v 1.6 2006/01/16 14:15:26 kent Exp $ */ /*- @@ -486,6 +486,7 @@ #define HDA_MAX_CHANNELS 16 #define HDA_MAX_SENSE_PINS 16 +#define AZ_MAX_VOL_SLAVES 16 #define AZ_TAG_SPKR 0x01 #define AZ_CLASS_INPUT 0 @@ -594,6 +595,17 @@ typedef struct { convgroup_t groups[32]; } convgroupset_t; +typedef struct { + int master; + int vol_l; + int vol_r; + int mute; + nid_t slaves[AZ_MAX_VOL_SLAVES]; + int nslaves; + int mask; + int cur; +} volgroup_t; + typedef struct codec_t { int (*comresp)(const struct codec_t *, nid_t, uint32_t, uint32_t, uint32_t *); int (*init_dacgroup)(struct codec_t *); @@ -635,6 +647,9 @@ typedef struct codec_t { int spkr_dac; int spkr_muters; + volgroup_t playvols; + volgroup_t recvols; + nid_t sense_pins[HDA_MAX_SENSE_PINS]; int nsense_pins; |