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

Reply via email to