summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorJames Courtier-Dutton <James@superbug.co.uk>2005-12-21 22:26:26 +0100
committerJaroslav Kysela <perex@suse.cz>2006-01-03 12:31:08 +0100
commitaad9095322c0c7d9637f29b71167458c36a4cdf6 (patch)
treef321047c62f3583a3a3990db6a8d165682b454d8 /sound
parent18f3c59f2b14225bd23c41a87a5eec39439bc8b9 (diff)
downloadlinux-aad9095322c0c7d9637f29b71167458c36a4cdf6.tar.gz
linux-aad9095322c0c7d9637f29b71167458c36a4cdf6.tar.xz
[ALSA] snd-ca0106: Fix SPI driver code. Fixes speaker output.
Modules: CA0106 driver Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/ca0106/ca0106_main.c72
1 files changed, 57 insertions, 15 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 1cf6f1fa98b1..6ed7c0bfa091 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -284,20 +284,38 @@ void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-int snd_ca0106_spi_write(struct snd_ca0106 *emu,
- u32 value)
+int snd_ca0106_spi_write(struct snd_ca0106 * emu,
+ unsigned int data)
{
- snd_ca0106_ptr_write(emu, SPI, 0, value);
+ unsigned int reset, set;
+ unsigned int reg, tmp;
+ int n, result;
+ reg = SPI;
+ if (data > 0xffff) /* Only 16bit values allowed */
+ return 1;
+ tmp = snd_ca0106_ptr_read(emu, reg, 0);
+ reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
+ set = reset | 0x10000; /* Set xxx1xxxx */
+ snd_ca0106_ptr_write(emu, reg, 0, reset | data);
+ tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
+ snd_ca0106_ptr_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_ca0106_ptr_read(emu, reg, 0);
+ if (!(tmp & 0x10000)) {
+ result = 0;
+ break;
+ }
+ }
+ if (result) /* Timed out */
+ return 1;
+ snd_ca0106_ptr_write(emu, reg, 0, reset | data);
+ tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
return 0;
}
-int snd_ca0106_spi_read(struct snd_ca0106 *emu,
- u32 *value)
-{
- *value = snd_ca0106_ptr_read(emu, SPI, 0);
- return 0;
-}
-
int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
u32 reg,
u32 value)
@@ -1148,6 +1166,30 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s
return 0;
}
+static unsigned int spi_dac_init[] = {
+ 0x00ff,
+ 0x02ff,
+ 0x0400,
+ 0x0520,
+ 0x0600,
+ 0x08ff,
+ 0x0aff,
+ 0x0cff,
+ 0x0eff,
+ 0x10ff,
+ 0x1200,
+ 0x1400,
+ 0x1480,
+ 0x1800,
+ 0x1aff,
+ 0x1cff,
+ 0x1e00,
+ 0x0530,
+ 0x0602,
+ 0x0622,
+ 0x1400,
+};
+
static int __devinit snd_ca0106_create(struct snd_card *card,
struct pci_dev *pci,
struct snd_ca0106 **rchip)
@@ -1330,11 +1372,11 @@ static int __devinit snd_ca0106_create(struct snd_card *card,
snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
}
if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
- u32 tmp;
- snd_ca0106_spi_write(chip, 0xf0622); /* Enable speakers output. */
- snd_ca0106_spi_read(chip, &tmp); /* Read the value. */
- snd_ca0106_spi_write(chip, 0xe1400);
- snd_ca0106_spi_read(chip, &tmp); /* Read the value. */
+ int size, n;
+
+ size = ARRAY_SIZE(spi_dac_init);
+ for (n=0; n < size; n++)
+ snd_ca0106_spi_write(chip, spi_dac_init[n]);
}
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,