Update of /cvsroot/alsa/alsa-kernel/pci/trident
In directory sc8-pr-cvs1:/tmp/cvs-serv10997/pci/trident
Modified Files:
trident_main.c trident_memory.c
Log Message:
[PATCH: trident-sgbuf.dif]
- use sgbuf for trident 4DNX.
- fixed suspend/resume, initializing the chip correctly now.
- fixed typos.
- removed virt_to_phys().
Index: trident_main.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/trident/trident_main.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- trident_main.c 7 Jan 2003 10:36:32 -0000 1.22
+++ trident_main.c 7 Jan 2003 10:49:12 -0000 1.23
@@ -41,6 +41,7 @@
#include <sound/control.h>
#include <sound/trident.h>
#include <sound/asoundef.h>
+#include <sound/pcm_sgbuf.h>
#include <asm/io.h>
@@ -756,16 +757,19 @@
snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
int err;
- if ((err = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params))) < 0)
- return err;
- if (err > 0 && trident->tlb.entries) {
- if (voice->memblk)
- snd_trident_free_pages(trident, voice->memblk);
- spin_lock_irq(&trident->reg_lock);
- voice->memblk = snd_trident_alloc_pages(trident, runtime->dma_area,
runtime->dma_addr, runtime->dma_bytes);
- spin_unlock_irq(&trident->reg_lock);
- if (voice->memblk == NULL)
- return -ENOMEM;
+ if (trident->tlb.entries) {
+ if ((err = snd_pcm_sgbuf_alloc(substream,
+params_buffer_bytes(hw_params))) < 0)
+ return err;
+ if (err > 0) { /* change */
+ if (voice->memblk)
+ snd_trident_free_pages(trident, voice->memblk);
+ voice->memblk = snd_trident_alloc_pages(trident, substream);
+ if (voice->memblk == NULL)
+ return -ENOMEM;
+ }
+ } else {
+ if ((err = snd_pcm_lib_malloc_pages(substream,
+params_buffer_bytes(hw_params))) < 0)
+ return err;
}
return 0;
}
@@ -792,7 +796,7 @@
/* voice management */
- if (params_buffer_size(hw_params) / 2 != params_buffer_size(hw_params)) {
+ if (params_buffer_size(hw_params) / 2 != params_period_size(hw_params)) {
if (evoice == NULL) {
evoice = snd_trident_alloc_voice(trident,
SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (evoice == NULL)
@@ -851,11 +855,14 @@
snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
snd_trident_voice_t *evoice = voice ? voice->extra : NULL;
- if (trident->tlb.entries && voice && voice->memblk) {
- snd_trident_free_pages(trident, voice->memblk);
- voice->memblk = NULL;
- }
- snd_pcm_lib_free_pages(substream);
+ if (trident->tlb.entries) {
+ if (voice && voice->memblk) {
+ snd_trident_free_pages(trident, voice->memblk);
+ voice->memblk = NULL;
+ }
+ snd_pcm_sgbuf_free(substream);
+ } else
+ snd_pcm_lib_free_pages(substream);
if (evoice != NULL) {
snd_trident_free_voice(trident, evoice);
voice->extra = NULL;
@@ -990,10 +997,12 @@
outb(0x54, TRID_REG(trident, LEGACY_DMAR11));
// Set channel buffer Address
- voice->LBA = runtime->dma_addr;
- outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));
+ /* FIXME: LEGACY_DMAR0 correctly set? */
if (voice->memblk)
voice->LBA = voice->memblk->offset;
+ else
+ voice->LBA = runtime->dma_addr;
+ outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));
// set ESO
ESO_bytes = snd_pcm_lib_buffer_bytes(substream) - 1;
@@ -1343,6 +1352,7 @@
voice->spurious_threshold =
snd_trident_spurious_threshold(runtime->rate, runtime->period_size);
/* set Loop Back Address */
+ /* FIXME: LBAO?? */
LBAO = runtime->dma_addr;
if (voice->memblk)
voice->LBA = voice->memblk->offset;
@@ -1755,17 +1765,27 @@
.fifo_size = 0,
};
+static int snd_trident_sgbuf_init(trident_t *trident, snd_pcm_substream_t *substream)
+{
+ if (trident->tlb.entries)
+ return snd_pcm_sgbuf_init(substream, trident->pci, 32);
+ return 0;
+}
+
+static void snd_trident_sgbuf_delete(trident_t *trident, snd_pcm_substream_t
+*substream)
+{
+ if (trident->tlb.entries)
+ snd_pcm_sgbuf_delete(substream);
+}
+
static void snd_trident_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- unsigned long flags;
snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
trident_t *trident;
if (voice) {
trident = voice->trident;
- spin_lock_irqsave(&trident->reg_lock, flags);
snd_trident_free_voice(trident, voice);
- spin_unlock_irqrestore(&trident->reg_lock, flags);
}
}
@@ -1774,14 +1794,15 @@
trident_t *trident = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
snd_trident_voice_t *voice;
+ int err;
- spin_lock_irq(&trident->reg_lock);
+ if ((err = snd_trident_sgbuf_init(trident, substream)) < 0)
+ return err;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL) {
- spin_unlock_irq(&trident->reg_lock);
+ snd_trident_sgbuf_delete(trident, substream);
return -EAGAIN;
}
- spin_unlock_irq(&trident->reg_lock);
snd_trident_pcm_mixer_build(trident, voice, substream);
voice->substream = substream;
runtime->private_data = voice;
@@ -1808,6 +1829,7 @@
snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
snd_trident_pcm_mixer_free(trident, voice, substream);
+ snd_trident_sgbuf_delete(trident, substream);
return 0;
}
@@ -1827,11 +1849,13 @@
trident_t *trident = snd_pcm_substream_chip(substream);
snd_trident_voice_t *voice;
snd_pcm_runtime_t *runtime = substream->runtime;
+ int err;
- spin_lock_irq(&trident->reg_lock);
+ if ((err = snd_trident_sgbuf_init(trident, substream)) < 0)
+ return err;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL) {
- spin_unlock_irq(&trident->reg_lock);
+ snd_trident_sgbuf_delete(trident, substream);
return -EAGAIN;
}
voice->spdif = 1;
@@ -1889,6 +1913,7 @@
trident->spdif_pcm_ctl->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(trident->card, SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO, &trident->spdif_pcm_ctl->id);
+ snd_trident_sgbuf_delete(trident, substream);
return 0;
}
@@ -1908,15 +1933,16 @@
trident_t *trident = snd_pcm_substream_chip(substream);
snd_trident_voice_t *voice;
snd_pcm_runtime_t *runtime = substream->runtime;
+ int err;
- spin_lock_irq(&trident->reg_lock);
+ if ((err = snd_trident_sgbuf_init(trident, substream)) < 0)
+ return err;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL) {
- spin_unlock_irq(&trident->reg_lock);
+ snd_trident_sgbuf_delete(trident, substream);
return -EAGAIN;
}
voice->capture = 1;
- spin_unlock_irq(&trident->reg_lock);
voice->substream = substream;
runtime->private_data = voice;
runtime->private_free = snd_trident_pcm_free_substream;
@@ -1937,6 +1963,8 @@
---------------------------------------------------------------------------*/
static int snd_trident_capture_close(snd_pcm_substream_t * substream)
{
+ trident_t *trident = snd_pcm_substream_chip(substream);
+ snd_trident_sgbuf_delete(trident, substream);
return 0;
}
@@ -1954,26 +1982,19 @@
static int snd_trident_foldback_open(snd_pcm_substream_t * substream)
{
trident_t *trident = snd_pcm_substream_chip(substream);
+ int err;
snd_trident_voice_t *voice;
snd_pcm_runtime_t *runtime = substream->runtime;
- spin_lock_irq(&trident->reg_lock);
+ if ((err = snd_trident_sgbuf_init(trident, substream)) < 0)
+ return err;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL) {
- spin_unlock_irq(&trident->reg_lock);
+ snd_trident_sgbuf_delete(trident, substream);
return -EAGAIN;
}
- if (trident->tlb.entries) {
- voice->memblk = snd_trident_alloc_pages(trident, runtime->dma_area,
runtime->dma_addr, runtime->dma_bytes);
- if (voice->memblk == NULL) {
- snd_trident_free_voice(trident, voice);
- spin_unlock_irq(&trident->reg_lock);
- return -ENOMEM;
- }
- }
- voice->substream = substream;
voice->foldback_chan = substream->number;
- spin_unlock_irq(&trident->reg_lock);
+ voice->substream = substream;
runtime->private_data = voice;
runtime->private_free = snd_trident_pcm_free_substream;
runtime->hw = snd_trident_foldback;
@@ -2001,6 +2022,7 @@
spin_lock_irq(&trident->reg_lock);
outb(0x00, TRID_REG(trident, T4D_RCI + voice->foldback_chan));
spin_unlock_irq(&trident->reg_lock);
+ snd_trident_sgbuf_delete(trident, substream);
return 0;
}
@@ -2886,7 +2908,7 @@
static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device)
{
- ac97_t _ac97, *ac97;
+ ac97_t _ac97;
snd_card_t * card = trident->card;
snd_kcontrol_t *kctl;
snd_ctl_elem_value_t uctl;
@@ -2900,7 +2922,7 @@
_ac97.private_data = trident;
trident->ac97_detect = 1;
__again:
- if ((err = snd_ac97_mixer(trident->card, &_ac97, &ac97)) < 0) {
+ if ((err = snd_ac97_mixer(trident->card, &_ac97, &trident->ac97)) < 0) {
if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
if ((err = snd_trident_sis_reset(trident)) < 0)
return err;
@@ -3077,6 +3099,21 @@
#endif /* CONFIG_GAMEPORT */
/*
+ * delay for 1 tick
+ */
+inline static void do_delay(trident_t *chip)
+{
+#ifdef CONFIG_PM
+ if (chip->in_suspend) {
+ mdelay((1000 + HZ - 1) / HZ);
+ return;
+ }
+#endif
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+}
+
+/*
* SiS reset routine
*/
@@ -3086,7 +3123,7 @@
unsigned int i;
int r;
- r = 2; /* count of retries */
+ r = trident->in_suspend ? 0 : 2; /* count of retries */
__si7018_retry:
pci_write_config_byte(trident->pci, 0x46, 0x04); /* SOFTWARE RESET */
udelay(100);
@@ -3107,15 +3144,13 @@
do {
if ((inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) &
SI_AC97_PRIMARY_READY) != 0)
goto __si7018_ok;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ do_delay(trident);
} while (time_after_eq(end_time, jiffies));
snd_printk("AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident,
SI_SERIAL_INTF_CTRL)));
if (r-- > 0) {
end_time = jiffies + HZ;
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ do_delay(trident);
} while (time_after_eq(end_time, jiffies));
goto __si7018_retry;
}
@@ -3188,6 +3223,183 @@
}
/*---------------------------------------------------------------------------
+ snd_trident_tlb_alloc
+
+ Description: Allocate and set up the TLB page table on 4D NX.
+ Each entry has 4 bytes (physical PCI address).
+
+ Paramters: trident - pointer to target device class for 4DWave.
+
+ Returns: 0 or negative error code
+
+ ---------------------------------------------------------------------------*/
+
+static int __devinit snd_trident_tlb_alloc(trident_t *trident)
+{
+ int i;
+
+ /* TLB array must be aligned to 16kB !!! so we allocate
+ 32kB region and correct offset when necessary */
+
+ trident->tlb.buffer = snd_malloc_pci_pages(trident->pci, 2 *
+SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer_dmaaddr);
+ if (trident->tlb.buffer == NULL) {
+ snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
+ return -ENOMEM;
+ }
+ trident->tlb.entries = (unsigned int*)(((unsigned long)trident->tlb.buffer +
+SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
+ trident->tlb.entries_dmaaddr = (trident->tlb.buffer_dmaaddr +
+SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
+ /* allocate shadow TLB page table (virtual addresses) */
+ trident->tlb.shadow_entries = (unsigned long
+*)vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
+ if (trident->tlb.shadow_entries == NULL) {
+ snd_printk(KERN_ERR "trident: unable to allocate shadow TLB
+entries\n");
+ return -ENOMEM;
+ }
+ /* allocate and setup silent page and initialise TLB entries */
+ trident->tlb.silent_page = snd_malloc_pci_pages(trident->pci,
+SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page_dmaaddr);
+ if (trident->tlb.silent_page == 0UL) {
+ snd_printk(KERN_ERR "trident: unable to allocate silent page\n");
+ return -ENOMEM;
+ }
+ memset(trident->tlb.silent_page, 0, SNDRV_TRIDENT_PAGE_SIZE);
+ for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) {
+ trident->tlb.entries[i] = cpu_to_le32(trident->tlb.silent_page_dmaaddr
+& ~(SNDRV_TRIDENT_PAGE_SIZE-1));
+ trident->tlb.shadow_entries[i] = (unsigned
+long)trident->tlb.silent_page;
+ }
+
+ /* use emu memory block manager code to manage tlb page allocation */
+ trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE *
+SNDRV_TRIDENT_MAX_PAGES);
+ if (trident->tlb.memhdr == NULL)
+ return -ENOMEM;
+
+ trident->tlb.memhdr->block_extra_size = sizeof(snd_trident_memblk_arg_t);
+ return 0;
+}
+
+/*
+ * initialize 4D DX chip
+ */
+
+static void snd_trident_stop_all_voices(trident_t *trident)
+{
+ outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
+ outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
+ outl(0, TRID_REG(trident, T4D_AINTEN_A));
+ outl(0, TRID_REG(trident, T4D_AINTEN_B));
+}
+
+static int snd_trident_4d_dx_init(trident_t *trident)
+{
+ struct pci_dev *pci = trident->pci;
+ signed long end_time;
+
+ /* reset the legacy configuration and whole audio/wavetable block */
+ pci_write_config_dword(pci, 0x40, 0); /* DDMA */
+ pci_write_config_byte(pci, 0x44, 0); /* ports */
+ pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */
+ pci_write_config_byte(pci, 0x46, 4); /* reset */
+ udelay(100);
+ pci_write_config_byte(pci, 0x46, 0); /* release reset */
+ udelay(100);
+
+ /* warm reset of the AC'97 codec */
+ outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
+ udelay(100);
+ outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
+ /* DAC on, disable SB IRQ and try to force ADC valid signal */
+ trident->ac97_ctrl = 0x0000004a;
+ outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
+ /* wait, until the codec is ready */
+ end_time = (jiffies + (HZ * 3) / 4) + 1;
+ do {
+ if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010) != 0)
+ goto __dx_ok;
+ do_delay(trident);
+ } while (time_after_eq(end_time, jiffies));
+ snd_printk(KERN_ERR "AC'97 codec ready error\n");
+ return -EIO;
+
+ __dx_ok:
+ snd_trident_stop_all_voices(trident);
+
+ return 0;
+}
+
+/*
+ * initialize 4D NX chip
+ */
+static int snd_trident_4d_nx_init(trident_t *trident)
+{
+ struct pci_dev *pci = trident->pci;
+ signed long end_time;
+
+ /* reset the legacy configuration and whole audio/wavetable block */
+ pci_write_config_dword(pci, 0x40, 0); /* DDMA */
+ pci_write_config_byte(pci, 0x44, 0); /* ports */
+ pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */
+
+ pci_write_config_byte(pci, 0x46, 1); /* reset */
+ udelay(100);
+ pci_write_config_byte(pci, 0x46, 0); /* release reset */
+ udelay(100);
+
+ /* warm reset of the AC'97 codec */
+ outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
+ udelay(100);
+ outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
+ /* wait, until the codec is ready */
+ end_time = (jiffies + (HZ * 3) / 4) + 1;
+ do {
+ if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008) != 0)
+ goto __nx_ok;
+ do_delay(trident);
+ } while (time_after_eq(end_time, jiffies));
+ snd_printk(KERN_ERR "AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident,
+NX_ACR0_AC97_COM_STAT)));
+ return -EIO;
+
+ __nx_ok:
+ /* DAC on */
+ trident->ac97_ctrl = 0x00000002;
+ outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
+ /* disable SB IRQ */
+ outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));
+
+ snd_trident_stop_all_voices(trident);
+
+ if (trident->tlb.entries != NULL) {
+ unsigned int i;
+ /* enable virtual addressing via TLB */
+ i = trident->tlb.entries_dmaaddr;
+ i |= 0x00000001;
+ outl(i, TRID_REG(trident, NX_TLBC));
+ } else {
+ outl(0, TRID_REG(trident, NX_TLBC));
+ }
+ /* initialize S/PDIF */
+ outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
+ outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
+
+ return 0;
+}
+
+/*
+ * initialize sis7018 chip
+ */
+static int snd_trident_sis_init(trident_t *trident)
+{
+ int err;
+
+ if ((err = snd_trident_sis_reset(trident)) < 0)
+ return err;
+
+ snd_trident_stop_all_voices(trident);
+
+ /* initialize S/PDIF */
+ outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------
snd_trident_create
Description: This routine will create the device specific class for
@@ -3211,9 +3423,7 @@
trident_t ** rtrident)
{
trident_t *trident;
- unsigned int i;
- int err;
- signed long end_time;
+ int i, err;
snd_trident_voice_t *voice;
snd_trident_pcm_mixer_t *tmix;
static snd_device_ops_t ops = {
@@ -3272,151 +3482,39 @@
trident->tlb.entries = NULL;
trident->tlb.buffer = NULL;
if (trident->device == TRIDENT_DEVICE_ID_NX) {
- /* allocate and setup TLB page table */
- /* each entry has 4 bytes (physical PCI address) */
- /* TLB array must be aligned to 16kB !!! so we allocate
- 32kB region and correct offset when necessary */
- trident->tlb.buffer = snd_malloc_pci_pages(trident->pci, 2 *
SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer_dmaaddr);
- if (trident->tlb.buffer == NULL) {
- snd_trident_free(trident);
- snd_printk("unable to allocate TLB buffer\n");
- return -ENOMEM;
- }
- trident->tlb.entries = (unsigned int*)(((unsigned
long)trident->tlb.buffer + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) &
~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
- trident->tlb.entries_dmaaddr = (trident->tlb.buffer_dmaaddr +
SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
- /* allocate shadow TLB page table (virtual addresses) */
- trident->tlb.shadow_entries = (unsigned long
*)vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
- if (trident->tlb.shadow_entries == NULL) {
- snd_trident_free(trident);
- snd_printk("unable to allocate shadow TLB entries\n");
- return -ENOMEM;
- }
- /* allocate and setup silent page and initialise TLB entries */
- trident->tlb.silent_page = snd_malloc_pci_pages(trident->pci,
SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page_dmaaddr);
- if (trident->tlb.silent_page == 0UL) {
- snd_trident_free(trident);
- snd_printk("unable to allocate silent page\n");
- return -ENOMEM;
- }
- memset(trident->tlb.silent_page, 0, SNDRV_TRIDENT_PAGE_SIZE);
- for (i = 0; i < SNDRV_TRIDENT_MAX_PAGES; i++) {
- trident->tlb.entries[i] =
cpu_to_le32(trident->tlb.silent_page_dmaaddr & ~(SNDRV_TRIDENT_PAGE_SIZE-1));
- trident->tlb.shadow_entries[i] = (unsigned
long)trident->tlb.silent_page;
- }
-
- /* use emu memory block manager code to manage tlb page allocation */
- trident->tlb.memhdr = snd_util_memhdr_new(SNDRV_TRIDENT_PAGE_SIZE *
SNDRV_TRIDENT_MAX_PAGES);
- if (trident->tlb.memhdr == NULL) {
+ if ((err = snd_trident_tlb_alloc(trident)) < 0) {
snd_trident_free(trident);
- return -ENOMEM;
+ return err;
}
- trident->tlb.memhdr->block_extra_size =
sizeof(snd_trident_memblk_arg_t);
}
- /* reset the legacy configuration and whole audio/wavetable block */
- if (trident->device == TRIDENT_DEVICE_ID_DX ||
- trident->device == TRIDENT_DEVICE_ID_NX) {
- pci_write_config_dword(pci, 0x40, 0); /* DDMA */
- pci_write_config_byte(pci, 0x44, 0); /* ports */
- pci_write_config_byte(pci, 0x45, 0); /* Legacy DMA */
- if (trident->device == TRIDENT_DEVICE_ID_DX) {
- pci_write_config_byte(pci, 0x46, 4); /* reset */
- udelay(100);
- pci_write_config_byte(pci, 0x46, 0); /* release reset */
- udelay(100);
- } else /* NX */ {
- pci_write_config_byte(pci, 0x46, 1); /* reset */
- udelay(100);
- pci_write_config_byte(pci, 0x46, 0); /* release reset */
- udelay(100);
- }
- }
-
- /* initialize chip */
+ trident->spdif_bits = trident->spdif_pcm_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
+ /* initialize chip */
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
- /* warm reset of the AC'97 codec */
- outl(0x00000001, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
- udelay(100);
- outl(0x00000000, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
- /* DAC on, disable SB IRQ and try to force ADC valid signal */
- trident->ac97_ctrl = 0x0000004a;
- outl(trident->ac97_ctrl, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
- /* wait, until the codec is ready */
- end_time = (jiffies + (HZ * 3) / 4) + 1;
- do {
- if ((inl(TRID_REG(trident, DX_ACR2_AC97_COM_STAT)) & 0x0010)
!= 0)
- goto __dx_ok;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } while (end_time - (signed long)jiffies >= 0);
- snd_printk("AC'97 codec ready error\n");
- snd_trident_free(trident);
- return -EIO;
- __dx_ok:
+ err = snd_trident_4d_dx_init(trident);
break;
case TRIDENT_DEVICE_ID_NX:
- /* warm reset of the AC'97 codec */
- outl(0x00000001, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
- udelay(100);
- outl(0x00000000, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
- /* wait, until the codec is ready */
- end_time = (jiffies + (HZ * 3) / 4) + 1;
- do {
- if ((inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT)) & 0x0008)
!= 0)
- goto __nx_ok;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- } while (end_time - (signed long)jiffies >= 0);
- snd_printk("AC'97 codec ready error [0x%x]\n", inl(TRID_REG(trident,
NX_ACR0_AC97_COM_STAT)));
- snd_trident_free(trident);
- return -EIO;
- __nx_ok:
- /* DAC on */
- trident->ac97_ctrl = 0x00000002;
- outl(trident->ac97_ctrl, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
- /* disable SB IRQ */
- outl(NX_SB_IRQ_DISABLE, TRID_REG(trident, T4D_MISCINT));
+ err = snd_trident_4d_nx_init(trident);
break;
case TRIDENT_DEVICE_ID_SI7018:
- if ((err = snd_trident_sis_reset(trident)) < 0) {
- snd_trident_free(trident);
- return err;
- }
+ err = snd_trident_sis_init(trident);
+ break;
+ default:
+ snd_BUG();
+ break;
+ }
+ if (err < 0) {
+ snd_trident_free(trident);
+ return err;
}
-
- outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
- outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
- outl(0, TRID_REG(trident, T4D_AINTEN_A));
- outl(0, TRID_REG(trident, T4D_AINTEN_B));
if ((err = snd_trident_mixer(trident, pcm_spdif_device)) < 0) {
snd_trident_free(trident);
return err;
}
- if (trident->device == TRIDENT_DEVICE_ID_NX) {
- if (trident->tlb.entries != NULL) {
- /* enable virtual addressing via TLB */
- i = trident->tlb.entries_dmaaddr;
- i |= 0x00000001;
- outl(i, TRID_REG(trident, NX_TLBC));
- } else {
- outl(0, TRID_REG(trident, NX_TLBC));
- }
- /* initialize S/PDIF */
- trident->spdif_bits = trident->spdif_pcm_bits =
SNDRV_PCM_DEFAULT_CON_SPDIF;
- outl(trident->spdif_bits, TRID_REG(trident, NX_SPCSTATUS));
- outb(trident->spdif_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
- }
-
- if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
- /* initialize S/PDIF */
- trident->spdif_bits = trident->spdif_pcm_bits =
SNDRV_PCM_DEFAULT_CON_SPDIF;
- outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
- }
-
/* initialise synth voices */
for (i = 0; i < 64; i++) {
voice = &trident->synth.voices[i];
@@ -3635,6 +3733,7 @@
pvoice->capture = 0;
pvoice->spdif = 0;
pvoice->memblk = NULL;
+ pvoice->substream = NULL;
spin_unlock_irqrestore(&trident->voice_alloc, flags);
return pvoice;
}
@@ -3715,6 +3814,7 @@
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return;
+ trident->in_suspend = 1;
snd_pcm_suspend_all(trident->pcm);
if (trident->foldback)
snd_pcm_suspend_all(trident->foldback);
@@ -3736,14 +3836,32 @@
if (card->power_state == SNDRV_CTL_POWER_D0)
return;
+
+ pci_enable_device(trident->pci);
+ pci_set_dma_mask(trident->pci, 0x3fffffff); /* to be sure */
+ pci_set_master(trident->pci); /* to be sure */
+
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
+ snd_trident_4d_dx_init(trident);
+ break;
case TRIDENT_DEVICE_ID_NX:
- break; /* TODO */
+ snd_trident_4d_nx_init(trident);
+ break;
case TRIDENT_DEVICE_ID_SI7018:
+ snd_trident_sis_init(trident);
break;
}
+
+ snd_ac97_resume(trident->ac97);
+
+ /* restore some registers */
+ outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
+
+ snd_trident_enable_eso(trident);
+
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ trident->in_suspend = 0;
}
static int snd_trident_set_power_state(snd_card_t *card, unsigned int power_state)
Index: trident_memory.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/trident/trident_memory.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- trident_memory.c 12 Aug 2002 08:43:48 -0000 1.7
+++ trident_memory.c 7 Jan 2003 10:49:12 -0000 1.8
@@ -28,6 +28,7 @@
#include <linux/time.h>
#include <sound/core.h>
#include <sound/trident.h>
+#include <sound/pcm_sgbuf.h>
/* page arguments of these two macros are Trident page (4096 bytes), not like
* aligned pages in others
@@ -166,9 +167,8 @@
/*
* check if the given pointer is valid for pages
*/
-static int is_valid_page(void *pages)
+static int is_valid_page(unsigned long ptr)
{
- unsigned long ptr = (unsigned long)virt_to_phys(pages);
if (ptr & ~0x3fffffffUL) {
snd_printk("max memory size is 1GB!!\n");
return 0;
@@ -184,33 +184,34 @@
* page allocation for DMA
*/
snd_util_memblk_t *
-snd_trident_alloc_pages(trident_t *trident, void *pages, dma_addr_t addr, unsigned
long size)
+snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
{
- unsigned long ptr;
snd_util_memhdr_t *hdr;
snd_util_memblk_t *blk;
- int page;
+ int idx, page;
+ struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t,
+_snd_pcm_substream_sgbuf(substream), return NULL);
snd_assert(trident != NULL, return NULL);
- snd_assert(size > 0 && size < SNDRV_TRIDENT_MAX_PAGES *
SNDRV_TRIDENT_PAGE_SIZE, return NULL);
+ snd_assert(sgbuf->size > 0 && sgbuf->size < SNDRV_TRIDENT_MAX_PAGES *
+SNDRV_TRIDENT_PAGE_SIZE, return NULL);
hdr = trident->tlb.memhdr;
snd_assert(hdr != NULL, return NULL);
- if (! is_valid_page(pages))
- return NULL;
-
down(&hdr->block_mutex);
- blk = search_empty(hdr, size);
+ blk = search_empty(hdr, sgbuf->size);
if (blk == NULL) {
up(&hdr->block_mutex);
return NULL;
}
/* set TLB entries */
- ptr = (unsigned long)pages;
- for (page = firstpg(blk); page <= lastpg(blk); page++) {
+ idx = 0;
+ for (page = firstpg(blk); page <= lastpg(blk); page++, idx++) {
+ dma_addr_t addr = sgbuf->table[idx].addr;
+ unsigned long ptr = (unsigned long)sgbuf->table[idx].buf;
+ if (! is_valid_page(addr)) {
+ up(&hdr->block_mutex);
+ return NULL;
+ }
set_tlb_bus(trident, page, ptr, addr);
- ptr += ALIGN_PAGE_SIZE;
- addr += ALIGN_PAGE_SIZE;
}
up(&hdr->block_mutex);
return blk;
@@ -301,7 +302,8 @@
void *ptr = page_to_ptr(trident, page);
dma_addr_t addr = page_to_addr(trident, page);
set_silent_tlb(trident, page);
- snd_free_pci_pages(trident->pci, ALIGN_PAGE_SIZE, ptr, addr);
+ if (ptr)
+ snd_free_pci_pages(trident->pci, ALIGN_PAGE_SIZE, ptr, addr);
}
/* check new allocation range */
@@ -346,7 +348,7 @@
ptr = snd_malloc_pci_pages(hw->pci, ALIGN_PAGE_SIZE, &addr);
if (ptr == NULL)
goto __fail;
- if (! is_valid_page(ptr)) {
+ if (! is_valid_page(addr)) {
snd_free_pci_pages(hw->pci, ALIGN_PAGE_SIZE, ptr, addr);
goto __fail;
}
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog