Skip to content

Commit

Permalink
[ALSA] snd-emu10k1: Removes some distortion from Audigy 2 ZS Notebook.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
James Courtier-Dutton authored and Jaroslav Kysela committed Jan 3, 2006
1 parent a587515 commit 27fe864
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/sound/emu10k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,8 @@ struct snd_emu_chip_details {
unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */
unsigned char ecard; /* APS EEPROM */
unsigned char emu1212m; /* EMU 1212m card */
unsigned char spi_dac; /* SPI interface for DAC */
unsigned char i2c_adc; /* I2C interface for ADC */
const char *driver;
const char *name;
const char *id; /* for backward compatibility - can be NULL if not needed */
Expand Down Expand Up @@ -1203,6 +1205,7 @@ unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, un
void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
Expand Down
28 changes: 27 additions & 1 deletion sound/pci/emu10k1/emu10k1_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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]",
Expand Down
36 changes: 36 additions & 0 deletions sound/pci/emu10k1/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 27fe864

Please sign in to comment.