On 05/05/11(Thu) 15:59, Martin Pieuchot wrote:
> The following diff adds the possibility to mute the master channel on
> any i2s based card. As a side effect the "mute key" on the keyboard now
> works as expected.
> 
> Comments, Ok?

New diff, should fix mixerctl crash with chipsets that don't support
bass nor treble.

Index: dev/i2s.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/i2s.c,v
retrieving revision 1.19
diff -u -p -r1.19 i2s.c
--- dev/i2s.c   4 May 2011 15:50:49 -0000       1.19
+++ dev/i2s.c   5 May 2011 14:00:23 -0000
@@ -155,6 +155,7 @@ i2s_attach(struct device *parent, struct
        printf(": irq %d,%d,%d\n", cirq, oirq, iirq);
 
        i2s_set_rate(sc, 44100);
+       sc->sc_mute = 0;
        i2s_gpio_init(sc, ca->ca_node, parent);
 }
 
@@ -512,15 +513,14 @@ enum {
        I2S_VOL_OUTPUT,
        I2S_INPUT_SELECT,
        I2S_VOL_INPUT,
+       I2S_MUTE,               /* should be before bass/treble */
        I2S_BASS,
        I2S_TREBLE,
        I2S_ENUM_LAST
 };
 
 int
-i2s_set_port(h, mc)
-       void *h;
-       mixer_ctrl_t *mc;
+i2s_set_port(void *h, mixer_ctrl_t *mc)
 {
        struct i2s_softc *sc = h;
        int l, r;
@@ -553,6 +553,30 @@ i2s_set_port(h, mc)
                (*sc->sc_setvolume)(sc, l, r);
                return 0;
 
+       case I2S_MUTE:
+               if (mc->type != AUDIO_MIXER_ENUM)
+                       return (EINVAL);
+
+               sc->sc_mute = (mc->un.ord != 0);
+
+               if (sc->sc_mute) {
+                       if (sc->sc_output_mask & 1 << 0)
+                               i2s_mute_speaker(sc, 1);
+                       if (sc->sc_output_mask & 1 << 1)
+                               i2s_mute_headphone(sc, 1);
+                       if (sc->sc_output_mask & 1 << 2)
+                               i2s_mute_lineout(sc, 1);
+               } else {
+                       if (sc->sc_output_mask & 1 << 0)
+                               i2s_mute_speaker(sc, 0);
+                       if (sc->sc_output_mask & 1 << 1)
+                               i2s_mute_headphone(sc, 0);
+                       if (sc->sc_output_mask & 1 << 2)
+                               i2s_mute_lineout(sc, 0);
+               }
+
+               return (0);
+
        case I2S_BASS:
                if (sc->sc_setbass != NULL)
                        (*sc->sc_setbass)(sc, l);
@@ -589,9 +613,7 @@ i2s_set_port(h, mc)
 }
 
 int
-i2s_get_port(h, mc)
-       void *h;
-       mixer_ctrl_t *mc;
+i2s_get_port(void *h, mixer_ctrl_t *mc)
 {
        struct i2s_softc *sc = h;
 
@@ -607,6 +629,10 @@ i2s_get_port(h, mc)
                mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_vol_r;
                return 0;
 
+       case I2S_MUTE:
+               mc->un.ord = sc->sc_mute;
+               return (0);
+
        case I2S_INPUT_SELECT:
                mc->un.mask = sc->sc_record_source;
                return 0;
@@ -670,13 +696,29 @@ i2s_query_devinfo(void *h, mixer_devinfo
                dip->mixer_class = I2S_OUTPUT_CLASS;
                strlcpy(dip->label.name, AudioNmaster, sizeof(dip->label.name));
                dip->type = AUDIO_MIXER_VALUE;
-               dip->prev = dip->next = AUDIO_MIXER_LAST;
+               dip->prev = AUDIO_MIXER_LAST;
+               dip->next = I2S_MUTE;
                dip->un.v.num_channels = 2;
                dip->un.v.delta = 8;
                strlcpy(dip->un.v.units.name, AudioNvolume,
                    sizeof(dip->un.v.units.name));
                return 0;
 
+       case I2S_MUTE:
+               dip->mixer_class = I2S_OUTPUT_CLASS;
+               dip->prev = I2S_VOL_OUTPUT;
+               dip->next = AUDIO_MIXER_LAST;
+               strlcpy(dip->label.name, AudioNmute, sizeof(dip->label.name));
+               dip->type = AUDIO_MIXER_ENUM;
+               dip->un.e.num_mem = 2;
+               strlcpy(dip->un.e.member[0].label.name, AudioNoff,
+                   sizeof dip->un.e.member[0].label.name);
+               dip->un.e.member[0].ord = 0;
+               strlcpy(dip->un.e.member[1].label.name, AudioNon,
+                   sizeof dip->un.e.member[1].label.name);
+               dip->un.e.member[1].ord = 1;
+               return (0);
+ 
        case I2S_INPUT_SELECT:
                dip->mixer_class = I2S_RECORD_CLASS;
                strlcpy(dip->label.name, AudioNsource, sizeof(dip->label.name));
@@ -1086,7 +1128,8 @@ i2s_cint(v)
        if (((sense & 0x02) >> 1) == headphone_detect_active) {
                DPRINTF(("headphone is inserted\n"));
                sc->sc_output_mask |= 1 << 1;
-               i2s_mute_headphone(sc, 0);
+               if (!sc->sc_mute)
+                       i2s_mute_headphone(sc, 0);
        } else {
                DPRINTF(("headphone is NOT inserted\n"));
        }
@@ -1100,14 +1143,16 @@ i2s_cint(v)
        if (((sense & 0x02) >> 1) == lineout_detect_active) {
                DPRINTF(("lineout is inserted\n"));
                sc->sc_output_mask |= 1 << 2;
-               i2s_mute_lineout(sc, 0);
+               if (!sc->sc_mute)
+                       i2s_mute_lineout(sc, 0);
        } else {
                DPRINTF(("lineout is NOT inserted\n"));
        }
 
        if (sc->sc_output_mask == 0) {
                sc->sc_output_mask |= 1 << 0;
-               i2s_mute_speaker(sc, 0);
+               if (!sc->sc_mute)
+                       i2s_mute_speaker(sc, 0);
        }
 
        return 1;
Index: dev/i2svar.h
===================================================================
RCS file: /cvs/src/sys/arch/macppc/dev/i2svar.h,v
retrieving revision 1.6
diff -u -p -r1.6 i2svar.h
--- dev/i2svar.h        26 Feb 2010 21:53:43 -0000      1.6
+++ dev/i2svar.h        5 May 2011 14:00:23 -0000
@@ -70,6 +70,7 @@ struct i2s_softc {
        u_int sc_vol_r;
        u_int sc_bass;
        u_int sc_treble;
+       u_int sc_mute;
 
        bus_dma_tag_t sc_dmat;
        dbdma_regmap_t *sc_odma;

Reply via email to