Update of /cvsroot/alsa/alsa-kernel/pci In directory sc8-pr-cvs1:/tmp/cvs-serv8139
Modified Files: via82xx.c Log Message: Fix in build_via_table, clenaups and improvements for the current ring pointer routines Index: via82xx.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/via82xx.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- via82xx.c 28 Nov 2002 15:21:43 -0000 1.12 +++ via82xx.c 23 Dec 2002 10:34:20 -0000 1.13 @@ -40,6 +40,10 @@ #define SNDRV_GET_ID #include <sound/initval.h> +#if 0 +#define POINTER_DEBUG +#endif + MODULE_AUTHOR("Jaroslav Kysela <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION("VIA VT82xx audio"); MODULE_LICENSE("GPL"); @@ -198,6 +202,9 @@ u32 *table; /* physical address + flag */ dma_addr_t table_addr; struct snd_via_sg_table *idx_table; + unsigned int lastpos; + unsigned int bufsize; + unsigned int bufsize2; } viadev_t; @@ -208,9 +215,9 @@ */ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream, struct pci_dev *pci, - int periods, int fragsize) + unsigned int periods, unsigned int fragsize) { - int i, idx, ofs, rest; + unsigned int i, idx, ofs, rest; struct snd_sg_buf *sgbuf = snd_magic_cast(snd_pcm_sgbuf_t, substream->dma_private, return -EINVAL); if (! dev->table) { @@ -237,8 +244,13 @@ * over page boundary. */ do { - int r; + unsigned int r; unsigned int flag; + + if (idx >= VIA_TABLE_SIZE) { + snd_printk(KERN_ERR "via82xx: too much table size!\n"); + return -EINVAL; + } dev->table[idx << 1] = cpu_to_le32((u32)snd_pcm_sgbuf_get_addr(sgbuf, ofs)); r = PAGE_SIZE - (ofs % PAGE_SIZE); if (rest < r) @@ -257,13 +269,11 @@ dev->idx_table[idx].size = r; ofs += r; idx++; - if (idx >= VIA_TABLE_SIZE) { - snd_printk(KERN_ERR "via82xx: too much table size!\n"); - return -EINVAL; - } } while (rest > 0); } dev->tbl_entries = idx; + dev->bufsize = periods * fragsize; + dev->bufsize2 = dev->bufsize / 2; return 0; } @@ -439,6 +449,7 @@ outb(0x03, port + VIA_REG_OFFSET_STATUS); outb(0x00, port + VIA_REG_OFFSET_TYPE); /* for via686 */ outl(0, port + VIA_REG_OFFSET_CURR_PTR); + viadev->lastpos = 0; } static int snd_via82xx_trigger(via82xx_t *chip, viadev_t *viadev, int cmd) @@ -641,19 +652,22 @@ static inline unsigned int snd_via82xx_cur_ptr(via82xx_t *chip, viadev_t *viadev) { - unsigned int val, ptr, count; - + unsigned int val, ptr, count, res; + snd_assert(viadev->tbl_entries, return 0); if (!(inb(VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset) & VIA_REG_STAT_ACTIVE)) return 0; - count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset) & 0xffffff; + spin_lock(&chip->reg_lock); + switch (chip->chip_type) { case TYPE_VIA686: + count &= 0xffffff; /* The via686a does not have the current index register, * so we need to calculate the index from CURR_PTR. */ ptr = inl(VIAREG(chip, OFFSET_CURR_PTR) + viadev->reg_offset); + count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset) & +0xffffff; if (ptr <= (unsigned int)viadev->table_addr) val = 0; else /* CURR_PTR holds the address + 8 */ @@ -662,14 +676,37 @@ case TYPE_VIA8233: default: - /* ah, this register makes life easier for us here. */ - val = inb(VIAREG(chip, OFFSET_CURR_INDEX) + viadev->reg_offset) % viadev->tbl_entries; + count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset); + val = count >> 24; + count &= 0xffffff; break; } /* convert to the linear position */ - return viadev->idx_table[val].offset + - viadev->idx_table[val].size - count; + ptr = viadev->idx_table[val].size; + res = viadev->idx_table[val].offset + ptr - count; + + if (ptr < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || +viadev->lastpos < viadev->bufsize2))) { +#ifdef POINTER_DEBUG + printk("fail: val = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = +0x%x, size = 0x%x, count = 0x%x\n", val, viadev->tbl_entries, viadev->lastpos, +viadev->bufsize2, viadev->idx_table[val].offset, viadev->idx_table[val].size, count); +#endif + /* VIA8233 count register returns full size when end of buffer is +reached */ + if (ptr != count) { + snd_printk("invalid via82xx_cur_ptr, using last valid +pointer\n"); + res = viadev->lastpos; + } else { + res = viadev->idx_table[val].offset + ptr; + if (res < viadev->lastpos && (res >= viadev->bufsize2 || +viadev->lastpos < viadev->bufsize2)) { + snd_printk("invalid via82xx_cur_ptr (2), using last +valid pointer\n"); + res = viadev->lastpos; + } + } + } + + viadev->lastpos = res; + spin_unlock(&chip->reg_lock); + + return res; } static snd_pcm_uframes_t snd_via82xx_playback_pointer(snd_pcm_substream_t * substream) @@ -1223,7 +1260,6 @@ snd_card_free(card); return err; } - if (snd_via82xx_mixer(chip) < 0) { snd_card_free(card); ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Alsa-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-cvslog