[alsa-devel] [PATCH] Support for muting channels DAC with CA0106 - SB0570

Takashi Iwai tiwai at suse.de
Mon Jul 23 14:51:25 CEST 2007


At Sat, 21 Jul 2007 17:10:08 -0700 (PDT),
Trent Piepho wrote:
> 
> This patch adds mute controls for the analog output channels.  It does this
> by sending SPI commands to the DAC on cards like the SB live 24-bit /
> Audigy SE that have an SPI DAC.
> [2  <text/plain; US-ASCII (base64)>]
> # HG changeset patch
> # User Trent Piepho <xyzzy at speakeasy.org>
> # 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.

Thanks, the patch looks almost fine, but please fix the following
minor issues:

- Try to avoid a magic number, e.g. >> 9.
- put callback should return 0 for non-changed value, a positive
  (usually 1) when the value is changed, and a negative error code for
  errors.
- Try to keep lines within 80 chars (to follow the standard coding
  style).  I know that other codes there are not, but don't care now.
  We'll fix them later, too.


Takashi

> 
> 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<<bit)			\
> +}
> +
> +static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] __devinitdata = {
> +	SPI_SWITCH("Analog Front Playback Switch", 15, 2),
> +	SPI_SWITCH("Analog Rear Playback Switch", 9, 3),
> +	SPI_SWITCH("Analog Center/LFE Playback Switch", 9, 5),
> +	SPI_SWITCH("Analog Side Playback Switch", 9, 4),
>  };
>  
>  static int __devinit remove_ctl(struct snd_card *card, const char *name)
> @@ -658,6 +710,13 @@ int __devinit snd_ca0106_mixer(struct sn
>  		if (err < 0)
>  			return err;
>  	}
> +	if (emu->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;
>  }
>  
> [3  <text/plain; us-ascii (7bit)>]
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel


More information about the Alsa-devel mailing list