]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - sound/pci/ca0106/ca0106_mixer.c
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / sound / pci / ca0106 / ca0106_mixer.c
index 85fd315d99990d6cba86001840d5cd7389975e2a..630aa499818947f79f0bd7aba8f750c3a4942de9 100644 (file)
@@ -676,28 +676,65 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata =
         I2C_VOLUME("Aux Capture Volume", 3),
 };
 
-#define SPI_SWITCH(xname,reg,bit) \
-{                                                              \
-       .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,    \
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
-       .info   = spi_mute_info,                                \
-       .get    = spi_mute_get,                                 \
-       .put    = spi_mute_put,                                 \
-       .private_value = (reg<<SPI_REG_SHIFT) | (bit)           \
-}
-
-static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
-__devinitdata = {
-       SPI_SWITCH("Analog Front Playback Switch",
-                  SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
-       SPI_SWITCH("Analog Rear Playback Switch",
-                  SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
-       SPI_SWITCH("Analog Center/LFE Playback Switch",
-                  SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
-       SPI_SWITCH("Analog Side Playback Switch",
-                  SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
+static const int spi_dmute_reg[] = {
+       SPI_DMUTE0_REG,
+       SPI_DMUTE1_REG,
+       SPI_DMUTE2_REG,
+       0,
+       SPI_DMUTE4_REG,
+};
+static const int spi_dmute_bit[] = {
+       SPI_DMUTE0_BIT,
+       SPI_DMUTE1_BIT,
+       SPI_DMUTE2_BIT,
+       0,
+       SPI_DMUTE4_BIT,
 };
 
+static struct snd_kcontrol_new __devinit
+snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
+                             int channel_id)
+{
+       struct snd_kcontrol_new spi_switch = {0};
+       int reg, bit;
+       int dac_id;
+
+       spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+       spi_switch.info = spi_mute_info;
+       spi_switch.get = spi_mute_get;
+       spi_switch.put = spi_mute_put;
+
+       switch (channel_id) {
+       case PCM_FRONT_CHANNEL:
+               spi_switch.name = "Analog Front Playback Switch";
+               dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
+               break;
+       case PCM_REAR_CHANNEL:
+               spi_switch.name = "Analog Rear Playback Switch";
+               dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
+               break;
+       case PCM_CENTER_LFE_CHANNEL:
+               spi_switch.name = "Analog Center/LFE Playback Switch";
+               dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
+               break;
+       case PCM_UNKNOWN_CHANNEL:
+               spi_switch.name = "Analog Side Playback Switch";
+               dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
+               break;
+       default:
+               /* Unused channel */
+               spi_switch.name = NULL;
+               dac_id = 0;
+       }
+       reg = spi_dmute_reg[dac_id];
+       bit = spi_dmute_bit[dac_id];
+
+       spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
+
+       return spi_switch;
+}
+
 static int __devinit remove_ctl(struct snd_card *card, const char *name)
 {
        struct snd_ctl_elem_id id;
@@ -832,8 +869,18 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
                if (err < 0)
                        return err;
        }
-       if (emu->details->spi_dac == 1)
-               ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
+       if (emu->details->spi_dac) {
+               int i;
+               for (i = 0;; i++) {
+                       struct snd_kcontrol_new ctl;
+                       ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
+                       if (!ctl.name)
+                               break;
+                       err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
+                       if (err < 0)
+                               return err;
+               }
+       }
 
        /* Create virtual master controls */
        vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
@@ -845,7 +892,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
                return err;
        add_slaves(card, vmaster, slave_vols);
 
-       if (emu->details->spi_dac == 1) {
+       if (emu->details->spi_dac) {
                vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
                                                      NULL);
                if (!vmaster)