# HG changeset patch # User Trent Piepho # Date 1185062879 25200 # Node ID 2c3514f4607b69271148337af15be55d3205af70 # Parent 04b7771f7c31709e9d1883264bcde7e34781a590 ca0106: Add analog mute controls for cards with SPI DAC Add four mute controls for the analog output channels for cards that use a spi dac, like SB0570 SB Live! 24-bit / Audigy SE. The Wolfson dac doesn't support muting each channel so the controls are mono. The chip state struct gets a 32-byte array to act as a shadow of the spi dac registers. Only two registers are used for mute, but more would be needed for de-emphasis, DAC power down, phase inversion, and other features. diff -r 04b7771f7c31 -r 2c3514f4607b pci/ca0106/ca0106.h --- a/pci/ca0106/ca0106.h Fri Jul 20 10:52:46 2007 +0200 +++ b/pci/ca0106/ca0106.h Sat Jul 21 17:07:59 2007 -0700 @@ -611,6 +611,8 @@ struct snd_ca0106 { struct snd_ca_midi midi; struct snd_ca_midi midi2; + + u16 spi_dac_reg[16]; }; int snd_ca0106_mixer(struct snd_ca0106 *emu); @@ -627,4 +629,5 @@ void snd_ca0106_ptr_write(struct snd_ca0 int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); - +int snd_ca0106_spi_write(struct snd_ca0106 * emu, + unsigned int data); diff -r 04b7771f7c31 -r 2c3514f4607b pci/ca0106/ca0106_main.c --- a/pci/ca0106/ca0106_main.c Fri Jul 20 10:52:46 2007 +0200 +++ b/pci/ca0106/ca0106_main.c Sat Jul 21 17:07:59 2007 -0700 @@ -1475,8 +1475,11 @@ static int __devinit snd_ca0106_create(i int size, n; size = ARRAY_SIZE(spi_dac_init); - for (n=0; n < size; n++) + for (n=0; n < size; n++) { snd_ca0106_spi_write(chip, spi_dac_init[n]); + if ((spi_dac_init[n]>>9) < ARRAY_SIZE(chip->spi_dac_reg)) + chip->spi_dac_reg[spi_dac_init[n]>>9] = spi_dac_init[n]; + } } if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, diff -r 04b7771f7c31 -r 2c3514f4607b pci/ca0106/ca0106_mixer.c --- a/pci/ca0106/ca0106_mixer.c Fri Jul 20 10:52:46 2007 +0200 +++ b/pci/ca0106/ca0106_mixer.c Sat Jul 21 17:07:59 2007 -0700 @@ -470,6 +470,41 @@ static int snd_ca0106_i2c_volume_put(str return change; } +static int spi_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int spi_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + unsigned int reg = kcontrol->private_value >> 9; + unsigned int bit = kcontrol->private_value & 0x1ff; + + ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); + return 0; +} + +static int spi_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); + unsigned int reg = kcontrol->private_value >> 9; + unsigned int bit = kcontrol->private_value & 0x1ff; + int ret; + + if (ucontrol->value.integer.value[0]) + emu->spi_dac_reg[reg] &= ~bit; + else + emu->spi_dac_reg[reg] |= bit; + + ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); + return ret ? -1 : 1; +} + #define CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -560,6 +595,23 @@ static struct snd_kcontrol_new snd_ca010 I2C_VOLUME("Mic Capture Volume", 1), I2C_VOLUME("Line in Capture Volume", 2), 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<<9) | (1<details->spi_dac == 1) { + for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_spi_dac_ctls); i++) { + err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_spi_dac_ctls[i], emu)); + if (err < 0) + return err; + } + } return 0; }