Current-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: hdaudio(4) "mixerctl -a" -> panic



mpumford%black-star.demon.co.uk@localhost said:
> The value in the step part of the amplifier capabilities is a step
> size  in 0.25db increments where a value of zero maps to 0.25db step
> rate and  1 is 0.5db.

I meant the number of steps which was 0. (It is called just "step"
in the code which is somewhat misleading.)
Just looked it up in the spec -- this means that the amplifier
gain cannot be changed. I think that in this case no mixer variable
should be created for the gain. Probably the amplifier has at least
the capability to "mute" the channel then, and a mixer variable should
be created for that (as azalia does).
I'm playing with the appended patch -- it still has the strange effect
on my laptop that unmuting activates the internal speaker even if an
external one is connected. I don't understand yet how things are
wired together.

best regards
Matthias



------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
Forschungszentrum Juelich GmbH
52425 Juelich
Sitz der Gesellschaft: Juelich
Eingetragen im Handelsregister des Amtsgerichts Dueren Nr. HR B 3498
Vorsitzende des Aufsichtsrats: MinDir'in Baerbel Brumme-Bothe
Geschaeftsfuehrung: Prof. Dr. Achim Bachem (Vorsitzender),
Dr. Ulrich Krafft (stellv. Vorsitzender), Prof. Dr.-Ing. Harald Bolt,
Prof. Dr. Sebastian M. Schmidt
------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
#
# old_revision [7f31056b0cd0586ef5a507e0cf6c6a83408f7191]
#
# patch "sys/dev/pci/hdaudio/hdaudio_afg.c"
#  from [8990c8145447763c436993bd1d7dd3b2b39e5f9f]
#    to [c871be6b0691492d24062510984d2f1a9b709e94]
#
============================================================
--- sys/dev/pci/hdaudio/hdaudio_afg.c   8990c8145447763c436993bd1d7dd3b2b39e5f9f
+++ sys/dev/pci/hdaudio/hdaudio_afg.c   c871be6b0691492d24062510984d2f1a9b709e94
@@ -637,12 +637,14 @@ hdaudio_afg_widget_getcaps(struct hdaudi
 
        w->w_waspin = false;
 
+#if 0
        if (COP_CFG_DEFAULT_DEVICE(config) == COP_DEVICE_SPEAKER &&
            (wcap & (COP_AWCAP_INAMP_PRESENT|COP_AWCAP_OUTAMP_PRESENT)) == 0) {
                wcap &= ~COP_AWCAP_TYPE_MASK;
                wcap |= (COP_AWCAP_TYPE_BEEP_GENERATOR << COP_AWCAP_TYPE_SHIFT);
                w->w_waspin = true;
        }
+#endif
 
        return wcap;
 }
@@ -2355,6 +2357,75 @@ static void
 }
 
 static void
+buildmixer_value(struct hdaudio_mixer *mx, struct hdaudio_control *ctl,
+                int type)
+{
+
+       mx->mx_ctl = ctl;
+       mx->mx_di.type = AUDIO_MIXER_VALUE;
+       mx->mx_di.prev = mx->mx_di.next = AUDIO_MIXER_LAST;
+       mx->mx_di.un.v.num_channels = 2;        /* XXX */
+       mx->mx_di.un.v.delta = 256 / (ctl->ctl_step + 1);
+       strcpy(mx->mx_di.label.name, hdaudio_afg_mixer_names[type]);
+       switch (type) {
+       case HDAUDIO_MIXER_VOLUME:
+       case HDAUDIO_MIXER_BASS:
+       case HDAUDIO_MIXER_TREBLE:
+       case HDAUDIO_MIXER_OGAIN:
+               mx->mx_di.mixer_class =
+                       HDAUDIO_MIXER_CLASS_OUTPUTS;
+               break;
+       case HDAUDIO_MIXER_MIC:
+       case HDAUDIO_MIXER_MONITOR:
+               mx->mx_di.mixer_class =
+                       HDAUDIO_MIXER_CLASS_RECORD;
+               break;
+       default:
+               mx->mx_di.mixer_class =
+                       HDAUDIO_MIXER_CLASS_INPUTS;
+               break;
+       }
+       strcpy(mx->mx_di.un.v.units.name, AudioNvolume);
+}
+
+static void
+buildmixer_mute(struct hdaudio_mixer *mx, struct hdaudio_control *ctl,
+               int type)
+{
+
+       mx->mx_ctl = ctl;
+       mx->mx_di.type = AUDIO_MIXER_ENUM;
+       mx->mx_di.prev = mx->mx_di.next = AUDIO_MIXER_LAST;
+       mx->mx_di.un.e.num_mem = 2;
+       mx->mx_di.un.e.member[0].ord = 0;
+       strlcpy(mx->mx_di.un.e.member[0].label.name, AudioNoff,
+               MAX_AUDIO_DEV_LEN);
+       mx->mx_di.un.e.member[1].ord = 1;
+       strlcpy(mx->mx_di.un.e.member[1].label.name, AudioNon,
+               MAX_AUDIO_DEV_LEN);
+       strcpy(mx->mx_di.label.name, hdaudio_afg_mixer_names[type]);
+       strlcat(mx->mx_di.label.name, ".mute", MAX_AUDIO_DEV_LEN);
+       switch (type) {
+       case HDAUDIO_MIXER_VOLUME:
+       case HDAUDIO_MIXER_BASS:
+       case HDAUDIO_MIXER_TREBLE:
+       case HDAUDIO_MIXER_OGAIN:
+               mx->mx_di.mixer_class =
+                       HDAUDIO_MIXER_CLASS_OUTPUTS;
+               break;
+       case HDAUDIO_MIXER_MIC:
+       case HDAUDIO_MIXER_MONITOR:
+               mx->mx_di.mixer_class =
+                       HDAUDIO_MIXER_CLASS_RECORD;
+               break;
+       default:
+               mx->mx_di.mixer_class =
+                       HDAUDIO_MIXER_CLASS_INPUTS;
+               break;
+       }
+}
+
+static void
 hdaudio_afg_build_mixers(struct hdaudio_afg_softc *sc)
 {
        struct hdaudio_mixer *mx;
@@ -2375,7 +2446,7 @@ hdaudio_afg_build_mixers(struct hdaudio_
        }
        for (i = 0; i < HDAUDIO_MIXER_NRDEVICES; i++) {
                if (audiomask & (1 << i))
-                       ++nmixers;
+                       nmixers += 2; /* value and mute */
        }
        /* XXXJDM TODO: softvol */
        /* Declare master volume if needed */
@@ -2461,40 +2532,16 @@ hdaudio_afg_build_mixers(struct hdaudio_
                }
                if (ctl == NULL)
                        continue;
-               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) {
-               case HDAUDIO_MIXER_VOLUME:
-               case HDAUDIO_MIXER_BASS:
-               case HDAUDIO_MIXER_TREBLE:
-               case HDAUDIO_MIXER_OGAIN:
-                       mx[index].mx_di.mixer_class =
-                           HDAUDIO_MIXER_CLASS_OUTPUTS;
-                       hda_trace(sc, "  adding outputs.%s\n",
-                           mx[index].mx_di.label.name);
-                       break;
-               case HDAUDIO_MIXER_MIC:
-               case HDAUDIO_MIXER_MONITOR:
-                       mx[index].mx_di.mixer_class =
-                           HDAUDIO_MIXER_CLASS_RECORD;
-                       hda_trace(sc, "  adding record.%s\n",
-                           mx[index].mx_di.label.name);
-                       break;
-               default:
-                       mx[index].mx_di.mixer_class =
-                           HDAUDIO_MIXER_CLASS_INPUTS;
-                       hda_trace(sc, "  adding inputs.%s\n",
-                           mx[index].mx_di.label.name);
-                       break;
+               if (ctl->ctl_step) {
+                       mx[index].mx_di.index = index;
+                       buildmixer_value(&mx[index], ctl, i);
+                       ++index;
                }
-               strcpy(mx[index].mx_di.un.v.units.name, AudioNvolume);
-               
-               ++index;
+               if (ctl->ctl_mute) {
+                       mx[index].mx_di.index = index;
+                       buildmixer_mute(&mx[index], ctl, i);
+                       ++index;
+               }
        }
 
        /* DAC selector */
@@ -3356,6 +3403,8 @@ hdaudio_afg_set_port(void *opaque, mixer
        struct hdaudio_mixer *mx;
        struct hdaudio_control *ctl;
        int i, divisor;
+       uint32_t mute;
+       int left, right;
 
        if (mc->dev < 0 || mc->dev >= sc->sc_nmixers)
                return EINVAL;
@@ -3385,15 +3434,18 @@ hdaudio_afg_set_port(void *opaque, mixer
                return 0;
        }
 
-       if (ctl->ctl_step == 0)
-               divisor = 128; /* ??? - just avoid div by 0 */
-       else
+       mute = HDAUDIO_AMP_MUTE_DEFAULT;
+       left = right = HDAUDIO_AMP_VOL_DEFAULT;
+
+       if (mc->type == AUDIO_MIXER_VALUE) {
+               KASSERT(ctl->ctl_step != 0);
                divisor = 255 / ctl->ctl_step;
+               left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] / divisor;
+               right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] / divisor;
+       } else if (mc->type == AUDIO_MIXER_ENUM)
+               mute = mc->un.ord;
 
-       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);
-           
+       hdaudio_afg_control_amp_set(ctl, mute, left, right);
        return 0;
 }
 
@@ -3435,13 +3487,16 @@ hdaudio_afg_get_port(void *opaque, mixer
                return 0;
        }
 
-       if (ctl->ctl_step == 0)
-               factor = 128; /* ??? - just avoid div by 0 */
-       else
+       if (mc->type == AUDIO_MIXER_VALUE) {
+               KASSERT(ctl->ctl_step != 0);
                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;
+               mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
+                       ctl->ctl_left * factor;
+               mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
+                       ctl->ctl_right * factor;
+       } else if (mc->type == AUDIO_MIXER_ENUM) {
+               mc->un.ord = ctl->ctl_muted;
+       }
        return 0;
 }
 


Home | Main Index | Thread Index | Old Index