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