aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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