From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Re: [Alsa-user] Upgrade problems -addendum Date: Mon, 27 Jan 2003 16:15:45 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: <200301221234.33054.tais.hansen@osd.dk> <200301242224.47436.tais.hansen@osd.dk> <200301271542.48663.tais.hansen@osd.dk> Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Mon_Jan_27_16:15:45_2003-1" Return-path: In-Reply-To: <200301271542.48663.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_Mon_Jan_27_16:15:45_2003-1 Content-Type: text/plain; charset=US-ASCII At Mon, 27 Jan 2003 15:42:43 +0100, Tais M. Hansen wrote: > > [1 ] > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On Monday 27 January 2003 11:42, Takashi Iwai wrote: > > > I just gave it another try with aplay. Bad idea; froze the system. > > > Something's really wrong with the test8-patch. > > ok. now, i rewrote the patch completely again. > > the module options was removed again. > > here we go... > > Ok. Hope you had a great weekend. :) > > - - Fresh cvs update. Recompiled & installed alsa-lib and alsa-util. > - - POINTER_DEBUG enabled. > > No sound from aplay but it had a lot of complaints for me. Two files attached. ok, the patch was buggy. but any sounds must come out. please check your mixer configuration. the fixed patch below: same as test9 but more verbose with POINTER_DEBUG. Takashi --Multipart_Mon_Jan_27_16:15:45_2003-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="via-pointer-test10.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 27 Jan 2003 15:12:46 -0000 @@ -88,7 +88,7 @@ MODULE_PARM(mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); MODULE_PARM_DESC(mpu_port, "MPU-401 port."); MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT_DESC); -MODULE_PARM(ac97_clock, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); +MODULE_PARM(ac97_clock, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:48000"); @@ -230,10 +230,13 @@ 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 lastidx; 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 @@ -302,7 +311,7 @@ } dev->tbl_entries = idx; dev->bufsize = periods * fragsize; - dev->bufsize2 = dev->bufsize / 2; + dev->periods = periods; return 0; } @@ -318,13 +327,18 @@ kfree(dev->idx_table); dev->idx_table = NULL; } + if (dev->period_idx) { + kfree(dev->period_idx); + dev->period_idx = NULL; + } } /* */ -enum { TYPE_VIA686 = 1, TYPE_VIA8233 }; +enum { TYPE_CARD_VIA686 = 1, TYPE_CARD_VIA8233 }; +enum { TYPE_VIA686, TYPE_VIA8233, TYPE_VIA8233A }; #define VIA_MAX_DEVS 7 /* 4 playback, 1 multi, 2 capture */ @@ -365,8 +379,8 @@ }; static struct pci_device_id snd_via82xx_ids[] __devinitdata = { - { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_VIA686, }, /* 686A */ - { 0x1106, 0x3059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_VIA8233, }, /* VT8233 */ + { 0x1106, 0x3058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */ + { 0x1106, 0x3059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, }, /* VT8233 */ { 0, } }; @@ -481,10 +495,13 @@ /* 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->lastidx = 0; + viadev->intr_cnt = 0; } @@ -512,10 +529,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); } @@ -538,7 +565,7 @@ unsigned char val; unsigned long port = chip->port + viadev->reg_offset; - if (chip->chip_type == TYPE_VIA8233) + if (chip->chip_type != TYPE_VIA686) val = VIA_REG_CTRL_INT; else val = 0; @@ -573,35 +600,76 @@ */ /* + * check whether the given index is within the current area + */ +static inline int out_of_intr_idx(viadev_t *viadev, unsigned int idx) +{ + unsigned int cnt; + + if (idx < viadev->period_idx[viadev->intr_cnt]) + return 1; + cnt = viadev->intr_cnt + 1; + if (cnt != viadev->periods && idx >= viadev->period_idx[cnt]) + return 1; + return 0; +} + +/* * calculate the linear position at the given sg-buffer index and the rest count */ -static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count) +static unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count) { unsigned int size, res; size = viadev->idx_table[idx].size; res = viadev->idx_table[idx].offset + size - count; - - /* 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("calc_linear_pos: idx = %i/%i, ptr = 0x%x, lastpos = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, res, viadev->lastpos, 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; - } else { - 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; + if (count == 0) { + /* fully processed, increase the index */ + if (++idx >= viadev->tbl_entries) + idx = 0; + } + + if (out_of_intr_idx(viadev, idx)) { + if (size == count) { + /* count register returns full size when end of buffer is reached */ + if (++idx >= viadev->tbl_entries) + idx = 0; + if (! out_of_intr_idx(viadev, idx)) { + res = viadev->idx_table[idx].offset; + goto _ok; } } + if (! out_of_intr_idx(viadev, viadev->lastidx)) { +#ifdef POINTER_DEBUG + snd_printd("recover from last\n"); +#endif + return viadev->lastpos; + } + /* recover from the interrupt pointer */ + idx = viadev->period_idx[viadev->intr_cnt]; + res = viadev->idx_table[idx].offset; +#ifdef POINTER_DEBUG + snd_printd("recover from intr: idx = %i, ptr = 0x%x\n", idx, res); +#endif + } else if (res < viadev->lastpos) { + if (! out_of_intr_idx(viadev, viadev->lastidx)) { +#ifdef POINTER_DEBUG + snd_printd("recover from last #2\n"); +#endif + return viadev->lastpos; + } } - viadev->lastpos = res; /* remember the last positiion */ + _ok: if (res >= viadev->bufsize) res -= viadev->bufsize; + viadev->lastidx = idx; + viadev->lastpos = res; +#ifdef POINTER_DEBUG + snd_printd("get position: 0x%x, idx = %d\n", res, idx); +#endif return res; } @@ -648,7 +716,7 @@ 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; res = calc_linear_pos(viadev, idx, count); spin_unlock(&chip->reg_lock); @@ -950,7 +1018,7 @@ if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0) return err; substream->runtime->hw.channels_max = 6; - if (chip->revision == VIA_REV_8233A) + if (chip->chip_type == TYPE_VIA8233A) snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels); return 0; } @@ -1365,7 +1433,7 @@ int i, err, caps; unsigned char val; - caps = chip->revision == VIA_REV_8233A ? 1 : 2; + caps = chip->chip_type == TYPE_VIA8233A ? 1 : 2; for (i = 0; i < caps; i++) { snd_via8233_capture_source.index = i; err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_capture_source, chip)); @@ -1651,6 +1719,19 @@ return 0; } +struct via823x_info { + int revision; + char *name; + int type; +}; +static struct via823x_info via823x_cards[] __devinitdata = { + { VIA_REV_PRE_8233, "VIA 8233-Pre", TYPE_VIA8233 }, + { VIA_REV_8233C, "VIA 8233C", TYPE_VIA8233 }, + { VIA_REV_8233, "VIA 8233", TYPE_VIA8233 }, + { VIA_REV_8233A, "VIA 8233A", TYPE_VIA8233A }, + { VIA_REV_8233, "VIA 8235", TYPE_VIA8233 }, +}; + static int __devinit snd_via82xx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -1658,7 +1739,7 @@ snd_card_t *card; via82xx_t *chip; unsigned char revision; - int chip_type; + int chip_type = 0, card_type; int i, err; if (dev >= SNDRV_CARDS) @@ -1672,24 +1753,31 @@ if (card == NULL) return -ENOMEM; - chip_type = pci_id->driver_data; + card_type = pci_id->driver_data; pci_read_config_byte(pci, PCI_REVISION_ID, &revision); - switch (chip_type) { - case TYPE_VIA686: + switch (card_type) { + case TYPE_CARD_VIA686: strcpy(card->driver, "VIA686A"); strcpy(card->shortname, "VIA 82C686A/B"); + chip_type = TYPE_VIA686; break; - case TYPE_VIA8233: - if (revision == VIA_REV_8233A) { + case TYPE_CARD_VIA8233: + chip_type = TYPE_VIA8233; + sprintf(card->shortname, "VIA 823x rev%d", revision); + for (i = 0; i < ARRAY_SIZE(via823x_cards); i++) { + if (revision == via823x_cards[i].revision) { + chip_type = via823x_cards[i].type; + strcpy(card->shortname, via823x_cards[i].name); + break; + } + } + if (chip_type == VIA_REV_8233A) strcpy(card->driver, "VIA8233A"); - strcpy(card->shortname, "VIA 8233A"); - } else { + else strcpy(card->driver, "VIA8233"); - strcpy(card->shortname, "VIA 8233/C"); - } break; default: - snd_printk(KERN_ERR "invalid chip type %d\n", chip_type); + snd_printk(KERN_ERR "invalid card type %d\n", card_type); err = -EINVAL; goto __error; } @@ -1705,7 +1793,7 @@ (err = snd_via686_init_misc(chip, dev)) < 0) goto __error; } else { - if (revision == VIA_REV_8233A) { + if (chip_type == VIA_REV_8233A) { if ((err = snd_via8233a_pcm_new(chip)) < 0) goto __error; } else { @@ -1792,4 +1880,3 @@ __setup("snd-via82xx=", alsa_card_via82xx_setup); #endif /* ifndef MODULE */ - --Multipart_Mon_Jan_27_16:15:45_2003-1-- ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com