Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci/hdaudio PR# kern/42110: No mute control on hdaud...
details: https://anonhg.NetBSD.org/src/rev/b7ef47a93613
branches: trunk
changeset: 747664:b7ef47a93613
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Sat Sep 26 17:05:01 2009 +0000
description:
PR# kern/42110: No mute control on hdaudio(4)
PR# kern/42028: hdaudio: mplayer can't change volume
Since the driver is not limited to OSS mixer APIs, allow for duplicate
mixer nodes with the same role. Resolves a regression where certain
controls may no longer be available that were previously possible with
azalia(4). Part of a fix for 42028. While here, add .mute controls to
address 42110.
diffstat:
sys/dev/pci/hdaudio/hdaudio_afg.c | 159 +++++++++++++++++++++++++++----------
1 files changed, 113 insertions(+), 46 deletions(-)
diffs (246 lines):
diff -r 1cb558a87109 -r b7ef47a93613 sys/dev/pci/hdaudio/hdaudio_afg.c
--- a/sys/dev/pci/hdaudio/hdaudio_afg.c Sat Sep 26 16:07:51 2009 +0000
+++ b/sys/dev/pci/hdaudio/hdaudio_afg.c Sat Sep 26 17:05:01 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_afg.c,v 1.13 2009/09/26 11:51:29 jmcneill Exp $ */
+/* $NetBSD: hdaudio_afg.c,v 1.14 2009/09/26 17:05:01 jmcneill Exp $ */
/*
* Copyright (c) 2009 Precedence Technologies Ltd <support%precedence.co.uk@localhost>
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.13 2009/09/26 11:51:29 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.14 2009/09/26 17:05:01 jmcneill Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -2365,20 +2365,22 @@
int nmixers = 0;
int i, j, index = 0;
int ndac, nadc;
- int numgpio;
- bool needmasterctl = false;
+ int ctrlcnt[HDAUDIO_MIXER_NRDEVICES];
+
+ memset(ctrlcnt, 0, sizeof(ctrlcnt));
/* Count the number of required mixers */
for (i = 0; i < sc->sc_nctls; i++) {
ctl = &sc->sc_ctls[i];
- if (ctl->ctl_enable == false)
+ if (ctl->ctl_enable == false ||
+ ctl->ctl_audiomask == 0)
continue;
audiomask |= ctl->ctl_audiomask;
- }
- for (i = 0; i < HDAUDIO_MIXER_NRDEVICES; i++) {
- if (audiomask & (1 << i))
+ ++nmixers;
+ if (ctl->ctl_mute)
++nmixers;
}
+
/* XXXJDM TODO: softvol */
/* Declare master volume if needed */
if ((audiomask & (HDAUDIO_MASK(VOLUME) | HDAUDIO_MASK(PCM))) ==
@@ -2387,8 +2389,9 @@
for (i = 0; i < sc->sc_nctls; i++) {
if (sc->sc_ctls[i].ctl_audiomask == HDAUDIO_MASK(PCM)) {
masterctl = &sc->sc_ctls[i];
- needmasterctl = true;
++nmixers;
+ if (masterctl->ctl_mute)
+ ++nmixers;
break;
}
}
@@ -2407,8 +2410,6 @@
else if (sc->sc_assocs[i].as_dir == HDAUDIO_PINDIR_IN)
++nadc;
}
- /* count GPIOs */
- numgpio = COP_GPIO_COUNT_NUM_GPIO(sc->sc_p.gpio_cnt);
/* Make room for selectors */
if (ndac > 0)
@@ -2417,7 +2418,7 @@
++nmixers;
hda_trace(sc, " need %d mixers (3 classes%s)\n",
- nmixers, needmasterctl ? " + fake master" : "");
+ nmixers, masterctl ? " + fake master" : "");
/* Allocate memory for the mixers */
mx = kmem_zalloc(nmixers * sizeof(*mx), KM_SLEEP);
@@ -2444,33 +2445,62 @@
++index;
}
+ /* Shadow master control */
+ if (masterctl != NULL) {
+ mx[index].mx_ctl = masterctl;
+ mx[index].mx_di.index = index;
+ mx[index].mx_di.type = AUDIO_MIXER_VALUE;
+ mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
+ mx[index].mx_di.un.v.num_channels = 2; /* XXX */
+ mx[index].mx_di.mixer_class = HDAUDIO_MIXER_CLASS_OUTPUTS;
+ mx[index].mx_di.un.v.delta = 256 / (masterctl->ctl_step + 1);
+ strcpy(mx[index].mx_di.label.name, AudioNmaster);
+ strcpy(mx[index].mx_di.un.v.units.name, AudioNvolume);
+ hda_trace(sc, " adding outputs.%s\n",
+ mx[index].mx_di.label.name);
+ ++index;
+ if (masterctl->ctl_mute) {
+ mx[index] = mx[index - 1];
+ mx[index].mx_di.index = index;
+ mx[index].mx_di.type = AUDIO_MIXER_ENUM;
+ mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
+ strcpy(mx[index].mx_di.label.name, AudioNmaster "." AudioNmute);
+ mx[index].mx_di.un.e.num_mem = 2;
+ strcpy(mx[index].mx_di.un.e.member[0].label.name, AudioNoff);
+ mx[index].mx_di.un.e.member[0].ord = 0;
+ strcpy(mx[index].mx_di.un.e.member[1].label.name, AudioNon);
+ mx[index].mx_di.un.e.member[1].ord = 1;
+ ++index;
+ }
+ }
+
/* Build volume mixers */
- for (i = 0; i < HDAUDIO_MIXER_NRDEVICES; i++) {
- if ((audiomask & (1 << i)) == 0)
+ for (i = 0; i < sc->sc_nctls; i++) {
+ uint32_t audiodev;
+
+ ctl = &sc->sc_ctls[i];
+ if (ctl->ctl_enable == false ||
+ ctl->ctl_audiomask == 0)
continue;
- ctl = NULL;
- for (j = 0; j < sc->sc_nctls; j++) {
- if (sc->sc_ctls[j].ctl_enable == false)
- continue;
- if (sc->sc_ctls[j].ctl_audiomask & (1 << i)) {
- ctl = &sc->sc_ctls[j];
- break;
- }
- }
- if (ctl == NULL && i == HDAUDIO_MIXER_VOLUME &&
- needmasterctl == true) {
- ctl = masterctl;
- }
- if (ctl == NULL)
- continue;
+ audiodev = ffs(ctl->ctl_audiomask) - 1;
mx[index].mx_ctl = ctl;
mx[index].mx_di.index = index;
mx[index].mx_di.type = AUDIO_MIXER_VALUE;
mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
mx[index].mx_di.un.v.num_channels = 2; /* XXX */
mx[index].mx_di.un.v.delta = 256 / (ctl->ctl_step + 1);
- strcpy(mx[index].mx_di.label.name, hdaudio_afg_mixer_names[i]);
- switch (i) {
+ if (ctrlcnt[audiodev] > 0)
+ snprintf(mx[index].mx_di.label.name,
+ sizeof(mx[index].mx_di.label.name),
+ "%s%d",
+ hdaudio_afg_mixer_names[audiodev],
+ ctrlcnt[audiodev] + 1);
+ else
+ strcpy(mx[index].mx_di.label.name,
+ hdaudio_afg_mixer_names[audiodev]);
+ ctrlcnt[audiodev]++;
+
+ switch (audiodev) {
case HDAUDIO_MIXER_VOLUME:
case HDAUDIO_MIXER_BASS:
case HDAUDIO_MIXER_TREBLE:
@@ -2497,6 +2527,23 @@
strcpy(mx[index].mx_di.un.v.units.name, AudioNvolume);
++index;
+
+ if (ctl->ctl_mute) {
+ mx[index] = mx[index - 1];
+ mx[index].mx_di.index = index;
+ mx[index].mx_di.type = AUDIO_MIXER_ENUM;
+ mx[index].mx_di.prev = mx[index].mx_di.next = AUDIO_MIXER_LAST;
+ snprintf(mx[index].mx_di.label.name,
+ sizeof(mx[index].mx_di.label.name),
+ "%s." AudioNmute,
+ mx[index - 1].mx_di.label.name);
+ mx[index].mx_di.un.e.num_mem = 2;
+ strcpy(mx[index].mx_di.un.e.member[0].label.name, AudioNoff);
+ mx[index].mx_di.un.e.member[0].ord = 0;
+ strcpy(mx[index].mx_di.un.e.member[1].label.name, AudioNon);
+ mx[index].mx_di.un.e.member[1].ord = 1;
+ ++index;
+ }
}
/* DAC selector */
@@ -3350,14 +3397,25 @@
return 0;
}
- if (ctl->ctl_step == 0)
- divisor = 128; /* ??? - just avoid div by 0 */
- else
- divisor = 255 / ctl->ctl_step;
-
- hdaudio_afg_control_amp_set(ctl, HDAUDIO_AMP_MUTE_NONE,
- mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] / divisor,
- mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] / divisor);
+ switch (mx->mx_di.type) {
+ case AUDIO_MIXER_VALUE:
+ if (ctl->ctl_step == 0)
+ divisor = 128; /* ??? - just avoid div by 0 */
+ else
+ divisor = 255 / ctl->ctl_step;
+
+ hdaudio_afg_control_amp_set(ctl, HDAUDIO_AMP_MUTE_NONE,
+ mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] / divisor,
+ mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] / divisor);
+ break;
+ case AUDIO_MIXER_ENUM:
+ hdaudio_afg_control_amp_set(ctl,
+ mc->un.ord ? HDAUDIO_AMP_MUTE_ALL : HDAUDIO_AMP_MUTE_NONE,
+ ctl->ctl_left, ctl->ctl_right);
+ break;
+ default:
+ return ENXIO;
+ }
return 0;
}
@@ -3400,13 +3458,22 @@
return 0;
}
- if (ctl->ctl_step == 0)
- factor = 128; /* ??? - just avoid div by 0 */
- else
- factor = 255 / ctl->ctl_step;
-
- mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ctl->ctl_left * factor;
- mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = ctl->ctl_right * factor;
+ switch (mx->mx_di.type) {
+ case AUDIO_MIXER_VALUE:
+ if (ctl->ctl_step == 0)
+ factor = 128; /* ??? - just avoid div by 0 */
+ else
+ factor = 255 / ctl->ctl_step;
+
+ mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = ctl->ctl_left * factor;
+ mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = ctl->ctl_right * factor;
+ break;
+ case AUDIO_MIXER_ENUM:
+ mc->un.ord = (ctl->ctl_muted || ctl->ctl_forcemute) ? 1 : 0;
+ break;
+ default:
+ return ENXIO;
+ }
return 0;
}
Home |
Main Index |
Thread Index |
Old Index