summaryrefslogtreecommitdiff
path: root/sound/pci
diff options
context:
space:
mode:
authorJames Courtier-Dutton <James@superbug.co.uk>2005-12-21 14:06:08 (GMT)
committerJaroslav Kysela <perex@suse.cz>2006-01-03 11:31:01 (GMT)
commit27fe864ec9e61041fc0b6f680207ae84f359b502 (patch)
tree19392d34e5f076e47192f8a9acf877ef50adc881 /sound/pci
parenta5875159dd6cec0ec743971343aee8dceac281d7 (diff)
downloadlinux-27fe864ec9e61041fc0b6f680207ae84f359b502.tar.xz
[ALSA] snd-emu10k1: Removes some distortion from Audigy 2 ZS Notebook.
Modules: EMU10K1/EMU10K2 driver Description: Part way to fix ALSA bug#927 Add support for the SPI interface on the CA0108 chip. This is used to control the registers on the DAC. Headphone output tested. Other outputs and Capture not tested yet. Note: The red LED does not come on, but sound is still OK. Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c28
-rw-r--r--sound/pci/emu10k1/io.c36
2 files changed, 63 insertions, 1 deletions
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index f8e2ccd..eb09370 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -181,7 +181,32 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
outl(tmp, emu->port + A_IOCFG);
}
-
+ if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */
+ u32 tmp;
+ tmp = snd_emu10k1_spi_write(emu, 0x00ff);
+ tmp = snd_emu10k1_spi_write(emu, 0x02ff);
+ tmp = snd_emu10k1_spi_write(emu, 0x0400);
+ tmp = snd_emu10k1_spi_write(emu, 0x0520);
+ tmp = snd_emu10k1_spi_write(emu, 0x0600);
+ tmp = snd_emu10k1_spi_write(emu, 0x08ff);
+ tmp = snd_emu10k1_spi_write(emu, 0x0aff);
+ tmp = snd_emu10k1_spi_write(emu, 0x0cff);
+ tmp = snd_emu10k1_spi_write(emu, 0x0eff);
+ tmp = snd_emu10k1_spi_write(emu, 0x10ff);
+ tmp = snd_emu10k1_spi_write(emu, 0x1200);
+ tmp = snd_emu10k1_spi_write(emu, 0x1400);
+ tmp = snd_emu10k1_spi_write(emu, 0x1480);
+ tmp = snd_emu10k1_spi_write(emu, 0x1800);
+ tmp = snd_emu10k1_spi_write(emu, 0x1aff);
+ tmp = snd_emu10k1_spi_write(emu, 0x1cff);
+ tmp = snd_emu10k1_spi_write(emu, 0x1e00);
+ tmp = snd_emu10k1_spi_write(emu, 0x0530);
+ tmp = snd_emu10k1_spi_write(emu, 0x0602);
+ tmp = snd_emu10k1_spi_write(emu, 0x0622);
+ tmp = snd_emu10k1_spi_write(emu, 0x1400);
+ snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10);
+ }
+
snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
@@ -747,6 +772,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.emu10k2_chip = 1,
.ca0108_chip = 1,
.ca_cardbus_chip = 1,
+ .spi_dac = 1,
.spk71 = 1} ,
{.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 5d116dd..7d0cb9d 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -29,6 +29,7 @@
#include <linux/time.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
+#include <linux/delay.h>
unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
{
@@ -123,6 +124,41 @@ void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
+int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
+ unsigned int data)
+{
+ unsigned int reset, set;
+ unsigned int reg, tmp;
+ int n, result;
+ if (emu->card_capabilities->ca0108_chip) {
+ reg=0x3c; /* PTR20, reg 0x3c */
+ } else {
+ return 1; /* For other cards types the SPI register is currently unknown. */
+ }
+ if (data > 0xffff) return 1; /* Only 16bit values allowed */
+
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
+ reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
+ set = reset | 0x10000; /* Set xxx1xxxx */
+ snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */
+ snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
+ result = 1;
+ /* Wait for status bit to return to 0 */
+ for (n=0;n<100;n++) {
+ udelay(10);
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
+ if (!(tmp & 0x10000)) {
+ result=0;
+ break;
+ }
+ }
+ if (result) return 1; /* Timed out */
+ snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */
+ return 0;
+}
+
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
{
unsigned long flags;