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 11:42:49 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: <200301221234.33054.tais.hansen@osd.dk> <200301241740.13498.tais.hansen@osd.dk> <200301242224.47436.tais.hansen@osd.dk> Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Mon_Jan_27_11:42:48_2003-1" Return-path: In-Reply-To: <200301242224.47436.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_11:42:48_2003-1 Content-Type: text/plain; charset=US-ASCII At Fri, 24 Jan 2003 22:24:43 +0100, Tais M. Hansen wrote: > > > > > now comes the patch of the week: > > > > idx_detect=1 : like test7. perhaps not perfect. > > > No sound, so you're right. > > hmm, it should produce some sounds. > > 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... Takashi --Multipart_Mon_Jan_27_11:42:48_2003-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="via-pointer-test9.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 10:38:59 -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; @@ -572,36 +599,70 @@ * pointer callbacks */ +static inline int out_of_intr_idx(viadev_t *viadev, unsigned int idx) +{ + unsigned int cnt; + + if (idx < viadev->period_idx[viadev->period_idx[viadev->intr_cnt]]) + return 1; + cnt = viadev->intr_cnt + 1; + if (cnt != viadev->periods && + idx >= viadev->period_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; + if (count == 0) { + if (++idx >= viadev->tbl_entries) + idx = 0; + } - /* check the validity of the calculated position */ - if (size < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))) { + 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 - 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("recover from last: idx = %i/%i, lastpos = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, 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; + return viadev->lastpos; + } +#ifdef POINTER_DEBUG + snd_printd("recover from intr: idx = %i/%i, lastpos = 0x%x, intr_idx = %i\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->period_idx[viadev->intr_cnt]); +#endif + /* recover from the interrupt pointer */ + idx = viadev->period_idx[viadev->intr_cnt]; + res = viadev->idx_table[idx].offset; + } else { + if (res < viadev->lastpos) { + if (! out_of_intr_idx(viadev, viadev->lastidx)) { +#ifdef POINTER_DEBUG + snd_printd("recover from last #2: idx = %i/%i, curpos = 0x%x, lastpos = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, res, viadev->lastpos, size, count); +#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; return res; } @@ -646,9 +707,10 @@ snd_assert(viadev->tbl_entries, return 0); if (!(inb(VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset) & VIA_REG_STAT_ACTIVE)) 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 +1012,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 +1427,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 +1713,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 +1733,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 +1747,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 +1787,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 +1874,3 @@ __setup("snd-via82xx=", alsa_card_via82xx_setup); #endif /* ifndef MODULE */ - --Multipart_Mon_Jan_27_11:42:48_2003-1-- ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com