From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Re: [Alsa-user] Upgrade problems -addendum Date: Fri, 24 Jan 2003 10:12:27 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: <200301221234.33054.tais.hansen@osd.dk> <200301231850.44138.tais.hansen@osd.dk> <200301231944.01306.tais.hansen@osd.dk> Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Fri_Jan_24_10:12:27_2003-1" Return-path: In-Reply-To: <200301231944.01306.tais.hansen@osd.dk> Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: "Tais M. Hansen" Cc: alsa-devel@lists.sourceforge.net List-Id: alsa-devel@alsa-project.org --Multipart_Fri_Jan_24_10:12:27_2003-1 Content-Type: text/plain; charset=US-ASCII At Thu, 23 Jan 2003 19:43:52 +0100, Tais M. Hansen wrote: > > [1 ] > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On Thursday 23 January 2003 19:07, Takashi Iwai wrote: > > > > thanks. > > > > it seems really the index value was not updated correctly by the > > > > chip. > > > > ok, take 4: please try the new one... > > > Same as before, log output attached. :) > > the next one is to put all logs to /var/log/debug. > > and will show more verbose. > > Ok, log output attached, 3 files with loads of gibberish ;). Same behavior > btw. thanks. sigh, this chip is really weird. perhaps in the last patch, the recoverd pointer overtook the actual pointer and got the driver confused. take 6: the calculation of recovered pointer is changed. and the register value of CURRPTR is shown as reference. if it's more acculate, we can refer to it instead... as usual, debug messages appear by enabling DEBUG_POITNER. Takashi --Multipart_Fri_Jan_24_10:12:27_2003-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="via-pointer-test6.dif" Content-Transfer-Encoding: 7bit Index: alsa-kernel/pci/via82xx.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/via82xx.c,v retrieving revision 1.21 diff -u -r1.21 via82xx.c --- alsa-kernel/pci/via82xx.c 22 Jan 2003 14:21:05 -0000 1.21 +++ alsa-kernel/pci/via82xx.c 24 Jan 2003 09:05:27 -0000 @@ -230,7 +230,10 @@ u32 *table; /* physical address + flag */ dma_addr_t table_addr; struct snd_via_sg_table *idx_table; + int *period_idx; + unsigned int periods; /* for recovery from the unexpected pointer */ + unsigned int intr_cnt; unsigned int lastpos; unsigned int bufsize; unsigned int bufsize2; @@ -262,11 +265,17 @@ if (! dev->idx_table) return -ENOMEM; } + if (! dev->period_idx) { + dev->period_idx = kmalloc(sizeof(int) * VIA_TABLE_SIZE, GFP_KERNEL); + if (! dev->period_idx) + return -ENOMEM; + } /* fill the entries */ idx = 0; ofs = 0; for (i = 0; i < periods; i++) { + dev->period_idx[i] = idx; rest = fragsize; /* fill descriptors for a period. * a period can be split to several descriptors if it's @@ -303,6 +312,7 @@ dev->tbl_entries = idx; dev->bufsize = periods * fragsize; dev->bufsize2 = dev->bufsize / 2; + dev->periods = periods; return 0; } @@ -318,6 +328,10 @@ kfree(dev->idx_table); dev->idx_table = NULL; } + if (dev->period_idx) { + kfree(dev->period_idx); + dev->period_idx = NULL; + } } @@ -481,10 +495,12 @@ /* disable interrupts */ outb(0x00, port + VIA_REG_OFFSET_CONTROL); /* clear interrupts */ - outb(0x03, port + VIA_REG_OFFSET_STATUS); - outb(0x00, port + VIA_REG_OFFSET_TYPE); /* for via686 */ + outb(0x07, port + VIA_REG_OFFSET_STATUS); + if (chip->chip_type == TYPE_VIA686) + outb(0x00, port + VIA_REG_OFFSET_TYPE); outl(0, port + VIA_REG_OFFSET_CURR_PTR); viadev->lastpos = 0; + viadev->intr_cnt = 0; } @@ -512,10 +528,20 @@ /* check status for each stream */ for (i = 0; i < chip->num_devs; i++) { viadev_t *viadev = &chip->devs[i]; - if (inb(chip->port + viadev->reg_offset) & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG)) { - outb(VIA_REG_STAT_FLAG | VIA_REG_STAT_EOL, VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset); + unsigned long port = chip->port + viadev->reg_offset; /* STATUS */ + unsigned char status = inb(port) & 0x07; + if (! status) + continue; + outb(status, port); /* ack */ + if (status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG)) { if (viadev->substream && viadev->running) { + viadev->intr_cnt++; + if (viadev->intr_cnt >= viadev->periods) + viadev->intr_cnt = 0; spin_unlock(&chip->reg_lock); +#ifdef POINTER_DEBUG + snd_printd("period elapsed\n"); +#endif snd_pcm_period_elapsed(viadev->substream); spin_lock(&chip->reg_lock); } @@ -585,17 +611,22 @@ /* check the validity of the calculated position */ if (size < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))) { #ifdef POINTER_DEBUG - printk("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); + // snd_printd("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count); #endif - /* count register returns full size when end of buffer is reached */ if (size != count) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n"); - res = viadev->lastpos; + /* recover from the interrupt position */ + idx = viadev->period_idx[viadev->intr_cnt]; + res = viadev->idx_table[idx].offset; + if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) { + snd_printd("invalid via82xx_cur_ptr, using last valid pointer\n"); + return viadev->lastpos; + } } else { + /* count register returns full size when end of buffer is reached */ res = viadev->idx_table[idx].offset + size; if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) { - snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n"); - res = viadev->lastpos; + snd_printd("invalid via82xx_cur_ptr (2), using last valid pointer\n"); + return viadev->lastpos; } } } @@ -648,8 +679,15 @@ return 0; spin_lock(&chip->reg_lock); count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset); - idx = count >> 24; + idx = (count >> 24) & viadev->tbl_entries; count &= 0xffffff; +#ifdef POINTER_DEBUG + { unsigned int ptr; + ptr = inl(VIAREG(chip, OFFSET_CURR_PTR) + viadev->reg_offset); + ptr -= (unsigned int)viadev->table_addr; + snd_printd("idx = %d, count = 0x%x, ptr = 0x%x\n", idx, count, ptr); + } +#endif res = calc_linear_pos(viadev, idx, count); spin_unlock(&chip->reg_lock); --Multipart_Fri_Jan_24_10:12:27_2003-1-- ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com