Update of /cvsroot/alsa/alsa-kernel/pci/trident
In directory sc8-pr-cvs1:/tmp/cvs-serv5849/pci/trident
Modified Files:
trident_main.c trident_memory.c
Log Message:
Fixed trident NX memory allocation for capture.
Improved capture workaround (IRQ ack).
Index: trident_main.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/trident/trident_main.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -r1.34 -r1.35
--- trident_main.c 7 Mar 2003 15:12:38 -0000 1.34
+++ trident_main.c 9 Mar 2003 23:16:11 -0000 1.35
@@ -489,6 +489,7 @@
#endif
}
+#if 0
/*---------------------------------------------------------------------------
snd_trident_write_cso_reg
@@ -511,6 +512,30 @@
outl((voice->Delta << 24) | (voice->CSO & 0x00ffffff),
TRID_REG(trident, CH_NX_DELTA_CSO));
}
}
+#endif
+
+/*---------------------------------------------------------------------------
+ snd_trident_write_eso_reg
+
+ Description: This routine will write the new ESO offset
+ register to hardware.
+
+ Paramters: trident - pointer to target device class for 4DWave.
+ voice - synthesizer voice structure
+ ESO - new ESO value
+
+ ---------------------------------------------------------------------------*/
+
+static void snd_trident_write_eso_reg(trident_t * trident, snd_trident_voice_t *
voice, unsigned int ESO)
+{
+ voice->ESO = ESO;
+ outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
+ if (trident->device != TRIDENT_DEVICE_ID_NX) {
+ outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);
+ } else {
+ outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff),
TRID_REG(trident, CH_NX_DELTA_ESO));
+ }
+}
/*---------------------------------------------------------------------------
snd_trident_write_vol_reg
@@ -983,6 +1008,8 @@
snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
unsigned int val, ESO_bytes;
+ snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI, return -EIO);
+
spin_lock(&trident->reg_lock);
// Initilize the channel and set channel Mode
@@ -991,13 +1018,11 @@
// Set DMA channel operation mode register
outb(0x54, TRID_REG(trident, LEGACY_DMAR11));
- // Set channel buffer Address
- /* FIXME: LEGACY_DMAR0 correctly set? */
+ // Set channel buffer Address, DMAR0 expects contiguous PCI memory area
+ voice->LBA = runtime->dma_addr;
+ outl(voice->LBA, TRID_REG(trident, LEGACY_DMAR0));
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;
@@ -1006,7 +1031,7 @@
ESO_bytes++;
// Set channel sample rate, 4.12 format
- val = ((unsigned int) 48000L << 12) / runtime->rate;
+ val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate;
outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));
// Set channel interrupt blk length
@@ -1033,15 +1058,13 @@
voice->Delta = snd_trident_convert_rate(runtime->rate);
voice->spurious_threshold = snd_trident_spurious_threshold(runtime->rate,
runtime->period_size);
+ voice->isync = 1;
+ voice->isync_mark = runtime->period_size;
+ voice->isync_max = runtime->buffer_size;
// Set voice parameters
voice->CSO = 0;
- /* the +2 is a correction for a h/w problem. if not
- used, the ESO interrupt is received before the capture pointer
- has actually reached the ESO point. this causes errors in
- the mid-level code.
- */
- voice->ESO = (runtime->period_size * 2) + 2 - 1;
+ voice->ESO = voice->isync_ESO = (runtime->period_size * 2) + 8 - 1;
voice->CTRL = snd_trident_control_mode(substream);
voice->FMC = 3;
voice->RVol = 0x7f;
@@ -1498,6 +1521,8 @@
} else {
what |= 1 << (evoice->number & 0x1f);
whati |= 1 << (evoice->number & 0x1f);
+ if (go)
+ evoice->stimer = val;
}
if (go) {
voice->running = 1;
@@ -1611,8 +1636,6 @@
if (result > 0)
result = runtime->buffer_size - result;
- // printk("capture result = 0x%x, cso = 0x%x\n", result, cso);
-
return result;
}
@@ -2173,10 +2196,14 @@
strcpy(pcm->name, "Trident 4DWave");
trident->pcm = pcm;
- if (trident->tlb.entries)
- snd_pcm_lib_preallocate_sg_pages_for_all(trident->pci, pcm, 64*1024,
128*1024);
- else
+ if (trident->tlb.entries) {
+ snd_pcm_substream_t *substream;
+ for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream; substream = substream->next)
+ snd_pcm_lib_preallocate_sg_pages(trident->pci, substream,
64*1024, 128*1024);
+ snd_pcm_lib_preallocate_pci_pages(trident->pci,
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, 64*1024, 128*1024);
+ } else {
snd_pcm_lib_preallocate_pci_pages_for_all(trident->pci, pcm, 64*1024,
128*1024);
+ }
if (rpcm)
*rpcm = pcm;
@@ -3676,7 +3703,7 @@
static void snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
trident_t *trident = snd_magic_cast(trident_t, dev_id, return);
- unsigned int audio_int, chn_int, stimer, channel, mask;
+ unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
int delta;
snd_trident_voice_t *voice;
@@ -3715,16 +3742,31 @@
continue;
}
voice->stimer = stimer;
+ if (voice->isync) {
+ tmp = inw(TRID_REG(trident, T4D_SBBL_SBCL));
+ if (trident->bDMAStart & 0x40)
+ tmp >>= 1;
+ if (tmp > 0)
+ tmp = voice->isync_max - tmp;
+ if (tmp < voice->isync_mark) {
+ if (tmp > 0x20)
+ tmp = voice->isync_ESO - 9;
+ else
+ tmp = voice->isync_ESO + 2;
+ /* update ESO for IRQ voice to preserve sync */
+ snd_trident_stop_voice(trident, voice->number);
+ snd_trident_write_eso_reg(trident, voice, tmp);
+ snd_trident_start_voice(trident,
voice->number);
+ }
+ }
+#if 0
if (voice->extra) {
/* update CSO for extra voice to preserve sync */
snd_trident_stop_voice(trident, voice->extra->number);
snd_trident_write_cso_reg(trident, voice->extra, 0);
snd_trident_start_voice(trident, voice->extra->number);
- } else if (voice->spdif) {
- snd_trident_stop_voice(trident, voice->number);
- snd_trident_write_cso_reg(trident, voice, 0);
- snd_trident_start_voice(trident, voice->number);
}
+#endif
spin_unlock(&trident->reg_lock);
snd_pcm_period_elapsed(voice->substream);
spin_lock(&trident->reg_lock);
Index: trident_memory.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/trident/trident_memory.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- trident_memory.c 28 Feb 2003 14:29:27 -0000 1.10
+++ trident_memory.c 9 Mar 2003 23:16:12 -0000 1.11
@@ -180,23 +180,26 @@
}
/*
- * page allocation for DMA
+ * page allocation for DMA (Scatter-Gather version)
*/
-snd_util_memblk_t *
-snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
+static snd_util_memblk_t *
+snd_trident_alloc_sg_pages(trident_t *trident, snd_pcm_substream_t *substream)
{
snd_util_memhdr_t *hdr;
snd_util_memblk_t *blk;
+ snd_pcm_runtime_t *runtime = substream->runtime;
int idx, page;
- struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+ struct snd_sg_buf *sgbuf = runtime->dma_private;
- snd_assert(trident != NULL, return NULL);
- snd_assert(sgbuf->size > 0 && sgbuf->size < SNDRV_TRIDENT_MAX_PAGES *
SNDRV_TRIDENT_PAGE_SIZE, return NULL);
+ snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI_SG, return NULL);
+ snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <=
SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
hdr = trident->tlb.memhdr;
snd_assert(hdr != NULL, return NULL);
+
+
down(&hdr->block_mutex);
- blk = search_empty(hdr, sgbuf->size);
+ blk = search_empty(hdr, runtime->dma_bytes);
if (blk == NULL) {
up(&hdr->block_mutex);
return NULL;
@@ -222,6 +225,61 @@
}
up(&hdr->block_mutex);
return blk;
+}
+
+/*
+ * page allocation for DMA (contiguous version)
+ */
+static snd_util_memblk_t *
+snd_trident_alloc_cont_pages(trident_t *trident, snd_pcm_substream_t *substream)
+{
+ snd_util_memhdr_t *hdr;
+ snd_util_memblk_t *blk;
+ int page;
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ dma_addr_t addr;
+ unsigned long ptr;
+
+ snd_assert(substream->dma_device.type == SNDRV_DMA_TYPE_PCI, return NULL);
+ snd_assert(runtime->dma_bytes> 0 && runtime->dma_bytes <=
SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
+ hdr = trident->tlb.memhdr;
+ snd_assert(hdr != NULL, return NULL);
+
+ down(&hdr->block_mutex);
+ blk = search_empty(hdr, runtime->dma_bytes);
+ if (blk == NULL) {
+ up(&hdr->block_mutex);
+ return NULL;
+ }
+
+ /* set TLB entries */
+ addr = runtime->dma_addr;
+ ptr = (unsigned long)runtime->dma_area;
+ for (page = firstpg(blk); page <= lastpg(blk); page++,
+ ptr += SNDRV_TRIDENT_PAGE_SIZE, addr += SNDRV_TRIDENT_PAGE_SIZE) {
+ if (! is_valid_page(addr)) {
+ __snd_util_mem_free(hdr, blk);
+ up(&hdr->block_mutex);
+ return NULL;
+ }
+ set_tlb_bus(trident, page, ptr, addr);
+ }
+ up(&hdr->block_mutex);
+ return blk;
+}
+
+/*
+ * page allocation for DMA
+ */
+snd_util_memblk_t *
+snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
+{
+ snd_assert(trident != NULL, return NULL);
+ snd_assert(substream != NULL, return NULL);
+ if (substream->dma_device.type == SNDRV_DMA_TYPE_PCI_SG)
+ return snd_trident_alloc_sg_pages(trident, substream);
+ else
+ return snd_trident_alloc_cont_pages(trident, substream);
}
-------------------------------------------------------
This SF.net email is sponsored by: Etnus, makers of TotalView, The debugger
for complex code. Debugging C/C++ programs can leave you feeling lost and
disoriented. TotalView can help you find your way. Available on major UNIX
and Linux platforms. Try it free. www.etnus.com
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog