aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ca0106/ca0106_mixer.c
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-07-24 06:06:16 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:57:55 -0400
commitb18cd538a92247307247a53f57c477edbcedbb79 (patch)
tree0fd32216c26bc78f95be8b8f56052e370f7f7f43 /sound/pci/ca0106/ca0106_mixer.c
parent69b311a4dabc9163288be1fe993cb7db47541e67 (diff)
[ALSA] ca0106: Add analog mute controls for cards with SPI DAC
Add four mute controls for the analog output channels for cards that use an SPI DAC, like the SB0570 SB Live! 24-bit / Audigy SE. The Wolfson DAC doesn't support muting left/right 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 analog gain, de-emphasis, DAC power down, phase inversion, and other features. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/ca0106/ca0106_mixer.c')
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index a135b9c4c3c8..7fbfe17438b4 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> 2 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
3 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit 3 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
4 * Version: 0.0.17 4 * Version: 0.0.18
5 * 5 *
6 * FEATURES currently supported: 6 * FEATURES currently supported:
7 * See ca0106_main.c for features. 7 * See ca0106_main.c for features.
@@ -39,6 +39,8 @@
39 * Modified Copyright message. 39 * Modified Copyright message.
40 * 0.0.17 40 * 0.0.17
41 * Implement Mic and Line in Capture. 41 * Implement Mic and Line in Capture.
42 * 0.0.18
43 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
42 * 44 *
43 * This code was initally based on code from ALSA's emu10k1x.c which is: 45 * This code was initally based on code from ALSA's emu10k1x.c which is:
44 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> 46 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
@@ -462,6 +464,42 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
462 return change; 464 return change;
463} 465}
464 466
467#define spi_mute_info snd_ctl_boolean_mono_info
468
469static int spi_mute_get(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
471{
472 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
473 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
474 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
475
476 ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
477 return 0;
478}
479
480static int spi_mute_put(struct snd_kcontrol *kcontrol,
481 struct snd_ctl_elem_value *ucontrol)
482{
483 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
484 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
485 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
486 int ret;
487
488 ret = emu->spi_dac_reg[reg] & bit;
489 if (ucontrol->value.integer.value[0]) {
490 if (!ret) /* bit already cleared, do nothing */
491 return 0;
492 emu->spi_dac_reg[reg] &= ~bit;
493 } else {
494 if (ret) /* bit already set, do nothing */
495 return 0;
496 emu->spi_dac_reg[reg] |= bit;
497 }
498
499 ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
500 return ret ? -1 : 1;
501}
502
465#define CA_VOLUME(xname,chid,reg) \ 503#define CA_VOLUME(xname,chid,reg) \
466{ \ 504{ \
467 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 505 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -554,6 +592,28 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata =
554 I2C_VOLUME("Aux Capture Volume", 3), 592 I2C_VOLUME("Aux Capture Volume", 3),
555}; 593};
556 594
595#define SPI_SWITCH(xname,reg,bit) \
596{ \
597 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
598 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
599 .info = spi_mute_info, \
600 .get = spi_mute_get, \
601 .put = spi_mute_put, \
602 .private_value = (reg<<SPI_REG_SHIFT) | (1<<bit) \
603}
604
605static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
606__devinitdata = {
607 SPI_SWITCH("Analog Front Playback Switch",
608 SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
609 SPI_SWITCH("Analog Rear Playback Switch",
610 SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
611 SPI_SWITCH("Analog Center/LFE Playback Switch",
612 SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
613 SPI_SWITCH("Analog Side Playback Switch",
614 SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
615};
616
557static int __devinit remove_ctl(struct snd_card *card, const char *name) 617static int __devinit remove_ctl(struct snd_card *card, const char *name)
558{ 618{
559 struct snd_ctl_elem_id id; 619 struct snd_ctl_elem_id id;
@@ -650,6 +710,13 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
650 if (err < 0) 710 if (err < 0)
651 return err; 711 return err;
652 } 712 }
713 if (emu->details->spi_dac == 1) {
714 for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_spi_dac_ctls); i++) {
715 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_spi_dac_ctls[i], emu));
716 if (err < 0)
717 return err;
718 }
719 }
653 return 0; 720 return 0;
654} 721}
655 722