summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2009-01-02 00:25:34 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2009-01-02 00:25:34 +0000
commit3e69299544dc846e3a922197aa2f6781b8f21171 (patch)
tree205f749865a82fce1f50acb327827e50fd042a56
parent81f15b13d06ed81770cdd87c12572e22d1946a02 (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.c163
-rw-r--r--sys/dev/pci/azalia.h17
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;