summaryrefslogtreecommitdiff
path: root/sys/dev/pci/azalia_codec.c
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2008-11-28 04:03:38 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2008-11-28 04:03:38 +0000
commit82cc23ac6fc632abcbbaca9ee7cc764b5bab0542 (patch)
treea955191584fd3c99de8f4eaa2f759e38f8022bf6 /sys/dev/pci/azalia_codec.c
parentb409ba887aaa9a3fe1a8233e858854db76bf9b75 (diff)
- use switch() instead of multiple if else
- put selectors that feed ADCs into the record class like we do for mixers - use azalia_nid_to_index more - shrink mixer items list by condensing mutes for multiple input sources into a single _source control of type AUDIO_MIXER_SET. for example, record.mix6_mic_mute=off record.mix6_mic2_mute=off record.mix6_line_mute=off record.mix6_hp_mute=off record.mix6_spkr_mute=off record.mix6_mix_mute=off is now represented as record.mix6_source=mic,mic2,line,hp,spkr,mix to mute all sources but the mic just do record.mix6_source=mic reduces mixer items by about 25% on my machine. also shortens the longest names.
Diffstat (limited to 'sys/dev/pci/azalia_codec.c')
-rw-r--r--sys/dev/pci/azalia_codec.c217
1 files changed, 162 insertions, 55 deletions
diff --git a/sys/dev/pci/azalia_codec.c b/sys/dev/pci/azalia_codec.c
index 8c0013b377f..7767111f4cc 100644
--- a/sys/dev/pci/azalia_codec.c
+++ b/sys/dev/pci/azalia_codec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: azalia_codec.c,v 1.71 2008/11/28 03:27:11 jakemsr Exp $ */
+/* $OpenBSD: azalia_codec.c,v 1.72 2008/11/28 04:03:37 jakemsr Exp $ */
/* $NetBSD: azalia_codec.c,v 1.8 2006/05/10 11:17:27 kent Exp $ */
/*-
@@ -554,25 +554,32 @@ azalia_generic_mixer_init(codec_t *this)
snprintf(d->label.name, sizeof(d->label.name),
"%s_source", w->name);
d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_AUDIO_MIXER)
+ switch (w->type) {
+ case COP_AWTYPE_AUDIO_INPUT:
d->mixer_class = AZ_CLASS_RECORD;
- else if (w->type == COP_AWTYPE_AUDIO_SELECTOR)
+ break;
+ case COP_AWTYPE_AUDIO_SELECTOR:
d->mixer_class = AZ_CLASS_INPUT;
- else
+ break;
+ default:
d->mixer_class = AZ_CLASS_OUTPUT;
+ break;
+ }
+ for (j = 0; j < naconns; j++) {
+ if (aconns[j] == w->nid) {
+ d->mixer_class = AZ_CLASS_RECORD;
+ break;
+ }
+ }
m->target = MI_TARGET_CONNLIST;
for (j = 0, k = 0; j < w->nconnections && k < 32; j++) {
- const widget_t *ww;
-
- if (!VALID_WIDGET_NID(w->connections[j], this))
- continue;
- ww = &this->w[w->connections[j]];
- if (!ww->enable)
+ l = azalia_nid_to_index(this,
+ w->connections[j]);
+ if (l == -1)
continue;
d->un.e.member[k].ord = j;
strlcpy(d->un.e.member[k].label.name,
- this->w[w->connections[j]].name,
- MAX_AUDIO_DEV_LEN);
+ this->w[l].name, MAX_AUDIO_DEV_LEN);
k++;
}
d->un.e.num_mem = k;
@@ -647,41 +654,35 @@ azalia_generic_mixer_init(codec_t *this)
AudioNon, MAX_AUDIO_DEV_LEN);
this->nmixers++;
} else {
- for (j = 0; j < w->nconnections; j++) {
- const widget_t *ww;
-
- MIXER_REG_PROLOG;
- if (!VALID_WIDGET_NID(w->connections[j],
- this))
- continue;
- ww = &this->w[w->connections[j]];
- if (!ww->enable)
- continue;
- snprintf(d->label.name, sizeof(d->label.name),
- "%s_%s_mute", w->name,
- this->w[w->connections[j]].name);
- d->type = AUDIO_MIXER_ENUM;
- if (w->type == COP_AWTYPE_AUDIO_INPUT)
- d->mixer_class = AZ_CLASS_RECORD;
- else
- d->mixer_class = AZ_CLASS_INPUT;
- for (k = 0; k < naconns; k++) {
- if (aconns[k] == w->nid) {
- d->mixer_class =
- AZ_CLASS_RECORD;
- break;
- }
+ MIXER_REG_PROLOG;
+ snprintf(d->label.name, sizeof(d->label.name),
+ "%s_source", w->name);
+ m->target = MI_TARGET_MUTESET;
+ d->type = AUDIO_MIXER_SET;
+ if (w->type == COP_AWTYPE_AUDIO_INPUT)
+ d->mixer_class = AZ_CLASS_RECORD;
+ else
+ d->mixer_class = AZ_CLASS_INPUT;
+ for (j = 0; j < naconns; j++) {
+ if (aconns[j] == w->nid) {
+ d->mixer_class =
+ AZ_CLASS_RECORD;
+ break;
}
- m->target = j;
- d->un.e.num_mem = 2;
- d->un.e.member[0].ord = 0;
- strlcpy(d->un.e.member[0].label.name,
- AudioNoff, MAX_AUDIO_DEV_LEN);
- d->un.e.member[1].ord = 1;
- strlcpy(d->un.e.member[1].label.name,
- AudioNon, MAX_AUDIO_DEV_LEN);
- this->nmixers++;
}
+ for (j = 0, l = 0;
+ j < w->nconnections && l < 32; j++) {
+ k = azalia_nid_to_index(this,
+ w->connections[j]);
+ if (k == -1)
+ continue;
+ d->un.s.member[l].mask = 1 << j;
+ strlcpy(d->un.s.member[l].label.name,
+ this->w[k].name, MAX_AUDIO_DEV_LEN);
+ l++;
+ }
+ d->un.s.num_mem = l;
+ this->nmixers++;
}
}
@@ -934,28 +935,27 @@ azalia_generic_mixer_fix_indexes(codec_t *this)
int
azalia_generic_mixer_default(codec_t *this)
{
- int i;
+ widget_t *w;
mixer_item_t *m;
+ mixer_ctrl_t mc;
+ int i, j, k;
+
/* unmute all */
for (i = 0; i < this->nmixers; i++) {
- mixer_ctrl_t mc;
-
m = &this->mixers[i];
if (!IS_MI_TARGET_INAMP(m->target) &&
m->target != MI_TARGET_OUTAMP)
continue;
if (m->devinfo.type != AUDIO_MIXER_ENUM)
continue;
+ bzero(&mc, sizeof(mc));
mc.dev = i;
mc.type = AUDIO_MIXER_ENUM;
- mc.un.ord = 0;
azalia_generic_mixer_set(this, m->nid, m->target, &mc);
}
/* set unextreme volume */
for (i = 0; i < this->nmixers; i++) {
- mixer_ctrl_t mc;
-
m = &this->mixers[i];
if (!IS_MI_TARGET_INAMP(m->target) &&
m->target != MI_TARGET_OUTAMP &&
@@ -963,6 +963,7 @@ azalia_generic_mixer_default(codec_t *this)
continue;
if (m->devinfo.type != AUDIO_MIXER_VALUE)
continue;
+ bzero(&mc, sizeof(mc));
mc.dev = i;
mc.type = AUDIO_MIXER_VALUE;
mc.un.value.num_channels = 1;
@@ -975,6 +976,31 @@ azalia_generic_mixer_default(codec_t *this)
azalia_generic_mixer_set(this, m->nid, m->target, &mc);
}
+ /* unmute all */
+ for (i = 0; i < this->nmixers; i++) {
+ m = &this->mixers[i];
+ if (m->target != MI_TARGET_MUTESET)
+ continue;
+ if (m->devinfo.type != AUDIO_MIXER_SET)
+ continue;
+ bzero(&mc, sizeof(mc));
+ mc.dev = i;
+ mc.type = AUDIO_MIXER_SET;
+ j = azalia_nid_to_index(this, m->nid);
+ if (j == -1) {
+ DPRINTF(("%s: invalid muteset nid\n", __func__));
+ return EINVAL;
+ }
+ w = &this->w[j];
+ for (j = 0; j < w->nconnections; j++) {
+ k = azalia_nid_to_index(this, w->connections[j]);
+ if (k == -1)
+ continue;
+ mc.un.mask |= 1 << j;
+ }
+ azalia_generic_mixer_set(this, m->nid, m->target, &mc);
+ }
+
return 0;
}
@@ -1097,11 +1123,12 @@ azalia_generic_mixer_delete(codec_t *this)
* @param mc mc->type must be set by the caller before the call
*/
int
-azalia_generic_mixer_get(const codec_t *this, nid_t nid, int target, mixer_ctrl_t *mc)
+azalia_generic_mixer_get(const codec_t *this, nid_t nid, int target,
+ mixer_ctrl_t *mc)
{
uint32_t result;
nid_t n;
- int err;
+ int i, j, err;
/* inamp mute */
if (IS_MI_TARGET_INAMP(target) && mc->type == AUDIO_MIXER_ENUM) {
@@ -1263,6 +1290,31 @@ azalia_generic_mixer_get(const codec_t *this, nid_t nid, int target, mixer_ctrl_
mc->un.ord = result & CORB_PS_PRESENCE ? 1 : 0;
}
+ /* mute set */
+ else if (target == MI_TARGET_MUTESET && mc->type == AUDIO_MIXER_SET) {
+ const widget_t *w;
+
+ i = azalia_nid_to_index(this, nid);
+ if (i == -1) {
+ DPRINTF(("%s: invalid muteset nid\n"));
+ return EINVAL;
+ }
+ w = &this->w[i];
+ mc->un.mask = 0;
+ for (i = 0; i < w->nconnections; i++) {
+ j = azalia_nid_to_index(this, w->connections[i]);
+ if (j == -1)
+ continue;
+ err = this->comresp(this, nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE,
+ CORB_GAGM_INPUT | CORB_GAGM_LEFT |
+ MI_TARGET_INAMP(i), &result);
+ if (err)
+ return err;
+ mc->un.mask |= (result & CORB_GAGM_MUTE) ? 0 : (1 << i);
+ }
+ }
+
else {
printf("%s: internal error in %s: target=%x\n",
XNAME(this), __func__, target);
@@ -1272,10 +1324,11 @@ azalia_generic_mixer_get(const codec_t *this, nid_t nid, int target, mixer_ctrl_
}
int
-azalia_generic_mixer_set(codec_t *this, nid_t nid, int target, const mixer_ctrl_t *mc)
+azalia_generic_mixer_set(codec_t *this, nid_t nid, int target,
+ const mixer_ctrl_t *mc)
{
uint32_t result, value;
- int err;
+ int i, j, err;
/* inamp mute */
if (IS_MI_TARGET_INAMP(target) && mc->type == AUDIO_MIXER_ENUM) {
@@ -1548,6 +1601,60 @@ azalia_generic_mixer_set(codec_t *this, nid_t nid, int target, const mixer_ctrl_
/* do nothing, control is read only */
}
+ else if (target == MI_TARGET_MUTESET && mc->type == AUDIO_MIXER_SET) {
+ const widget_t *w;
+
+ i = azalia_nid_to_index(this, nid);
+ if (i == -1) {
+ DPRINTF(("%s: invalid muteset nid\n"));
+ return EINVAL;
+ }
+ w = &this->w[i];
+ for (i = 0; i < w->nconnections; i++) {
+ j = azalia_nid_to_index(this, w->connections[i]);
+ if (j == -1)
+ continue;
+
+ /* We have to set stereo mute separately
+ * to keep each gain value.
+ */
+ err = this->comresp(this, nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE,
+ CORB_GAGM_INPUT | CORB_GAGM_LEFT |
+ MI_TARGET_INAMP(i), &result);
+ if (err)
+ return err;
+ value = CORB_AGM_INPUT | CORB_AGM_LEFT |
+ (i << CORB_AGM_INDEX_SHIFT) |
+ CORB_GAGM_GAIN(result);
+ if ((mc->un.mask & (1 << i)) == 0)
+ value |= CORB_AGM_MUTE;
+ err = this->comresp(this, nid,
+ CORB_SET_AMPLIFIER_GAIN_MUTE, value, &result);
+ if (err)
+ return err;
+
+ if (WIDGET_CHANNELS(w) == 2) {
+ err = this->comresp(this, nid,
+ CORB_GET_AMPLIFIER_GAIN_MUTE,
+ CORB_GAGM_INPUT | CORB_GAGM_RIGHT |
+ MI_TARGET_INAMP(i), &result);
+ if (err)
+ return err;
+ value = CORB_AGM_INPUT | CORB_AGM_RIGHT |
+ (i << CORB_AGM_INDEX_SHIFT) |
+ CORB_GAGM_GAIN(result);
+ if ((mc->un.mask & (1 << i)) == 0)
+ value |= CORB_AGM_MUTE;
+ err = this->comresp(this, nid,
+ CORB_SET_AMPLIFIER_GAIN_MUTE,
+ value, &result);
+ if (err)
+ return err;
+ }
+ }
+ }
+
else {
printf("%s: internal error in %s: target=%x\n",
XNAME(this), __func__, target);