[alsa-devel] [PATCH] Support for muting channels DAC with CA0106 - SB0570
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.
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@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@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
On Mon, 23 Jul 2007, Takashi Iwai wrote:
At Sat, 21 Jul 2007 17:10:08 -0700 (PDT), Thanks, the patch looks almost fine, but please fix the following minor issues:
- Try to avoid a magic number, e.g. >> 9.
Ok, I added a bunch of the fields from the WM8768 datasheet that could be useful.
- 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.
It will now return 0 if the value wasn't changed and also not do the unnecessary spi write.
- 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.
Also done. The loops that add the controls have long lines that didn't wrap well. So I made a second patch that converts the loop I added plus the two existing loops into a macro, which IMHO looks a lot nicer and reduces code duplication.
I also upped the version numbers and used snd_ctl_boolean_mono_info.
At Mon, 23 Jul 2007 16:43:14 -0700 (PDT), Trent Piepho wrote:
On Mon, 23 Jul 2007, Takashi Iwai wrote:
At Sat, 21 Jul 2007 17:10:08 -0700 (PDT), Thanks, the patch looks almost fine, but please fix the following minor issues:
- Try to avoid a magic number, e.g. >> 9.
Ok, I added a bunch of the fields from the WM8768 datasheet that could be useful.
Thanks, that's _much_ better.
- 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.
It will now return 0 if the value wasn't changed and also not do the unnecessary spi write.
- 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.
Also done. The loops that add the controls have long lines that didn't wrap well. So I made a second patch that converts the loop I added plus the two existing loops into a macro, which IMHO looks a lot nicer and reduces code duplication.
Yes. I fixed the macro to wrap with do {} while (0), and use temporary variables to be more safe.
Both patches are applied now to ALSA HG tree.
Takashi
participants (2)
-
Takashi Iwai
-
Trent Piepho