aboutsummaryrefslogtreecommitdiffstats
path: root/sound
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
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')
-rw-r--r--sound/pci/ca0106/ca0106.h47
-rw-r--r--sound/pci/ca0106/ca0106_main.c11
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c69
3 files changed, 122 insertions, 5 deletions
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index a0420bc63f0b..7ad03c6afd42 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -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.21 4 * Version: 0.0.22
5 * 5 *
6 * FEATURES currently supported: 6 * FEATURES currently supported:
7 * See ca0106_main.c for features. 7 * See ca0106_main.c for features.
@@ -47,6 +47,8 @@
47 * Added GPIO info for SB Live 24bit. 47 * Added GPIO info for SB Live 24bit.
48 * 0.0.21 48 * 0.0.21
49 * Implement support for Line-in capture on SB Live 24bit. 49 * Implement support for Line-in capture on SB Live 24bit.
50 * 0.0.22
51 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
50 * 52 *
51 * 53 *
52 * This code was initally based on code from ALSA's emu10k1x.c which is: 54 * This code was initally based on code from ALSA's emu10k1x.c which is:
@@ -552,6 +554,44 @@
552#define CONTROL_CENTER_LFE_CHANNEL 1 554#define CONTROL_CENTER_LFE_CHANNEL 1
553#define CONTROL_UNKNOWN_CHANNEL 2 555#define CONTROL_UNKNOWN_CHANNEL 2
554 556
557
558/* Based on WM8768 Datasheet Rev 4.2 page 32 */
559#define SPI_REG_MASK 0x1ff /* 16-bit SPI writes have a 7-bit address */
560#define SPI_REG_SHIFT 9 /* followed by 9 bits of data */
561
562/* They really do label the bit for the 4th channel "4" and not "3" */
563#define SPI_DMUTE0_REG 9
564#define SPI_DMUTE1_REG 9
565#define SPI_DMUTE2_REG 9
566#define SPI_DMUTE4_REG 15
567#define SPI_DMUTE0_BIT 3
568#define SPI_DMUTE1_BIT 4
569#define SPI_DMUTE2_BIT 5
570#define SPI_DMUTE4_BIT 2
571
572#define SPI_PHASE0_REG 3
573#define SPI_PHASE1_REG 3
574#define SPI_PHASE2_REG 3
575#define SPI_PHASE4_REG 15
576#define SPI_PHASE0_BIT 6
577#define SPI_PHASE1_BIT 7
578#define SPI_PHASE2_BIT 8
579#define SPI_PHASE4_BIT 3
580
581#define SPI_PDWN_REG 2 /* power down all DACs */
582#define SPI_PDWN_BIT 2
583#define SPI_DACD0_REG 10 /* power down individual DACs */
584#define SPI_DACD1_REG 10
585#define SPI_DACD2_REG 10
586#define SPI_DACD4_REG 15
587#define SPI_DACD0_BIT 1
588#define SPI_DACD1_BIT 2
589#define SPI_DACD2_BIT 3
590#define SPI_DACD4_BIT 1
591
592#define SPI_PWRDNALL_REG 10 /* power down everything */
593#define SPI_PWRDNALL_BIT 4
594
555#include "ca_midi.h" 595#include "ca_midi.h"
556 596
557struct snd_ca0106; 597struct snd_ca0106;
@@ -611,6 +651,8 @@ struct snd_ca0106 {
611 651
612 struct snd_ca_midi midi; 652 struct snd_ca_midi midi;
613 struct snd_ca_midi midi2; 653 struct snd_ca_midi midi2;
654
655 u16 spi_dac_reg[16];
614}; 656};
615 657
616int snd_ca0106_mixer(struct snd_ca0106 *emu); 658int snd_ca0106_mixer(struct snd_ca0106 *emu);
@@ -627,4 +669,5 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
627 669
628int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); 670int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value);
629 671
630 672int snd_ca0106_spi_write(struct snd_ca0106 * emu,
673 unsigned int data);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 58ffa0cacfb1..512fda946c66 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.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.23 4 * Version: 0.0.24
5 * 5 *
6 * FEATURES currently supported: 6 * FEATURES currently supported:
7 * Front, Rear and Center/LFE. 7 * Front, Rear and Center/LFE.
@@ -79,6 +79,8 @@
79 * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 79 * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
80 * 0.0.23 80 * 0.0.23
81 * Implement support for Line-in capture on SB Live 24bit. 81 * Implement support for Line-in capture on SB Live 24bit.
82 * 0.0.24
83 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
82 * 84 *
83 * BUGS: 85 * BUGS:
84 * Some stability problems when unloading the snd-ca0106 kernel module. 86 * Some stability problems when unloading the snd-ca0106 kernel module.
@@ -1484,8 +1486,13 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
1484 int size, n; 1486 int size, n;
1485 1487
1486 size = ARRAY_SIZE(spi_dac_init); 1488 size = ARRAY_SIZE(spi_dac_init);
1487 for (n=0; n < size; n++) 1489 for (n = 0; n < size; n++) {
1490 int reg = spi_dac_init[n] >> SPI_REG_SHIFT;
1491
1488 snd_ca0106_spi_write(chip, spi_dac_init[n]); 1492 snd_ca0106_spi_write(chip, spi_dac_init[n]);
1493 if (reg < ARRAY_SIZE(chip->spi_dac_reg))
1494 chip->spi_dac_reg[reg] = spi_dac_init[n];
1495 }
1489 } 1496 }
1490 1497
1491 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, 1498 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
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