ALSA: Add vmaster controls for Pmac 5500, iMac G3 SL, and PBook G3 Lombard
Risto Suominen [Tue, 20 Jan 2009 20:01:17 +0000 (22:01 +0200)]
Add virtual master controls for PowerMac 5500 (AWACS) and iMac G3 Slot-loading
and PowerBook G3 Lombard (Screamer).

Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

sound/ppc/Kconfig
sound/ppc/awacs.c

index 777de2b..bd2338a 100644 (file)
@@ -13,6 +13,7 @@ config SND_POWERMAC
        tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
        depends on I2C && INPUT && PPC_PMAC
        select SND_PCM
+       select SND_VMASTER
        help
          Say Y here to include support for the integrated sound device.
 
index 9abbf64..80df9b1 100644 (file)
@@ -608,9 +608,12 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = {
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] __initdata = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
-       AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
+};
+
+static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = {
+       AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
@@ -627,6 +630,10 @@ static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = {
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
+static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] __initdata = {
+       AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
+};
+
 static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = {
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
@@ -645,12 +652,19 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] __initdata = {
+       AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
 static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
 static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
 AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
 
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 __initdata =
+AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
+
 static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
        AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
@@ -868,6 +882,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
        int lombard = IS_LOMBARD;
        int imac;
        int err, vol;
+       struct snd_kcontrol *vmaster_sw, *vmaster_vol;
+       struct snd_kcontrol *master_vol, *speaker_vol;
 
        imac1 = IS_IMAC1;
        imac2 = IS_IMAC2;
@@ -968,19 +984,35 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
                                   snd_pmac_awacs_mixers2);
        if (err < 0)
                return err;
+       if (pm5500) {
+               err = build_mixers(chip,
+                                  ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500),
+                                  snd_pmac_awacs_mixers2_pmac5500);
+               if (err < 0)
+                       return err;
+       }
        if (pm7500)
                err = build_mixers(chip,
                                   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
                                   snd_pmac_awacs_mixers_pmac7500);
+       else if (pm5500)
+               err = snd_ctl_add(chip->card,
+                   (master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500,
+                                               chip)));
        else if (beige)
                err = build_mixers(chip,
                                   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),
                                   snd_pmac_screamer_mixers_beige);
-       else if (imac || lombard)
+       else if (imac || lombard) {
+               err = snd_ctl_add(chip->card,
+                   (master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo,
+                                               chip)));
+               if (err < 0)
+                       return err;
                err = build_mixers(chip,
                                   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),
                                   snd_pmac_screamer_mixers_imac);
-       else if (g4agp)
+       } else if (g4agp)
                err = build_mixers(chip,
                                   ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp),
                                   snd_pmac_screamer_mixers_g4agp);
@@ -992,6 +1024,8 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
                return err;
        chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard)
                        ? &snd_pmac_awacs_master_sw_imac
+                       : pm5500
+                       ? &snd_pmac_awacs_master_sw_pmac5500
                        : &snd_pmac_awacs_master_sw, chip);
        err = snd_ctl_add(chip->card, chip->master_sw_ctl);
        if (err < 0)
@@ -1023,8 +1057,9 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
 #endif /* PMAC_AMP_AVAIL */
        {
                /* route A = headphone, route C = speaker */
-               err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
-                                       snd_pmac_awacs_speaker_vol);
+               err = snd_ctl_add(chip->card,
+                   (speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol,
+                                               chip)));
                if (err < 0)
                        return err;
                chip->speaker_sw_ctl = snd_ctl_new1(imac1
@@ -1037,6 +1072,33 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
                        return err;
        }
 
+       if (pm5500 || imac || lombard) {
+               vmaster_sw = snd_ctl_make_virtual_master(
+                       "Master Playback Switch", (unsigned int *) NULL);
+               err = snd_ctl_add_slave_uncached(vmaster_sw,
+                                                chip->master_sw_ctl);
+               if (err < 0)
+                       return err;
+               err = snd_ctl_add_slave_uncached(vmaster_sw,
+                                                 chip->speaker_sw_ctl);
+               if (err < 0)
+                       return err;
+               err = snd_ctl_add(chip->card, vmaster_sw);
+               if (err < 0)
+                       return err;
+               vmaster_vol = snd_ctl_make_virtual_master(
+                       "Master Playback Volume", (unsigned int *) NULL);
+               err = snd_ctl_add_slave(vmaster_vol, master_vol);
+               if (err < 0)
+                       return err;
+               err = snd_ctl_add_slave(vmaster_vol, speaker_vol);
+               if (err < 0)
+                       return err;
+               err = snd_ctl_add(chip->card, vmaster_vol);
+               if (err < 0)
+                       return err;
+       }
+
        if (beige || g4agp)
                err = build_mixers(chip,
                                ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),