From: Takashi Iwai <tiwai@suse.de>
To: "Tais M. Hansen" <tais.hansen@osd.dk>
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: Re: [Alsa-user] Upgrade problems -addendum
Date: Mon, 27 Jan 2003 18:27:19 +0100 [thread overview]
Message-ID: <s5hvg0amrk8.wl@alsa2.suse.de> (raw)
In-Reply-To: <200301271801.46689.tais.hansen@osd.dk>
[-- Attachment #1: Type: text/plain, Size: 960 bytes --]
At Mon, 27 Jan 2003 18:01:42 +0100,
Tais M. Hansen <tais.hansen@osd.dk> wrote:
>
> [1 <text/plain; iso-8859-1 (quoted-printable)>]
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Monday 27 January 2003 16:15, Takashi Iwai wrote:
> > > 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.
>
> It seems okay. Just to make sure I reverted the patch and recompiled. Aplay
> played several minutes without any errors at all. I also let ogg123 play for
> about 10 minutes. Had a few pops and an equal amount of fails in syslog.
> Pretty much the same as what I started out with after your initial via-fix.
> I've attached the ogg123 logoutput anyway.
>
>
> > the fixed patch below: same as test9 but more verbose with POINTER_DEBUG.
>
> Attached 2 files from testing with aplay.
how about this one?
Takashi
[-- Attachment #2: via-pointer-test11.dif --]
[-- Type: application/octet-stream, Size: 11281 bytes --]
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 17:24:08 -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,85 @@
*/
/*
+ * 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;
+ int recover = 0;
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, 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;
+ if (count == 0) {
+ /* fully processed, increase the index */
+ if (++idx >= viadev->tbl_entries)
+ idx = 0;
+ res = viadev->idx_table[idx].offset;
+ } else if (count > size) {
+ /* totally corrupted? get the position from interrupt ptr */
+ recover = 2;
+ res = 0; /* shut up warning */
+ goto _check;
+ } else {
+ res = viadev->idx_table[idx].offset + size - count;
+ }
+
+ 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 _check;
}
}
+ recover = 2;
+ } else if (res < viadev->lastpos)
+ recover = 1;
+
+ _check:
+ if (recover > 0) {
+ if (! out_of_intr_idx(viadev, viadev->lastidx)) {
+#ifdef POINTER_DEBUG
+ snd_printd("recover from last\n");
+#endif
+ return viadev->lastpos;
+ }
+ if (recover > 1) {
+ /* 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
+ }
}
- viadev->lastpos = res; /* remember the last positiion */
+
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;
}
@@ -642,13 +719,23 @@
via82xx_t *chip = snd_pcm_substream_chip(substream);
viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
unsigned int idx, count, res;
+ int timeout = 50;
snd_assert(viadev->tbl_entries, return 0);
if (!(inb(VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset) & VIA_REG_STAT_ACTIVE))
return 0;
+ while (timeout-- > 0) {
+ count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset);
+ if (count != (unsigned int)-1)
+ goto _got_count;
+ }
+#ifdef POINTER_DEBUG
+ snd_printd("invalid CURR_COUNT reg\n");
+#endif
+ count = 0;
+ _got_count:
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 +1037,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 +1452,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 +1738,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 +1758,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 +1772,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 +1812,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 +1899,3 @@
__setup("snd-via82xx=", alsa_card_via82xx_setup);
#endif /* ifndef MODULE */
-
next prev parent reply other threads:[~2003-01-27 17:27 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200301221234.33054.tais.hansen@osd.dk>
[not found] ` <200301221543.52285.tais.hansen@osd.dk>
[not found] ` <s5hznpt1bn2.wl@alsa2.suse.de>
[not found] ` <200301221647.05780.tais.hansen@osd.dk>
2003-01-22 16:23 ` [Alsa-user] Upgrade problems -addendum Takashi Iwai
2003-01-23 0:35 ` Tais M. Hansen
2003-01-23 10:03 ` Takashi Iwai
2003-01-23 11:15 ` Tais M. Hansen
2003-01-23 11:46 ` Takashi Iwai
2003-01-23 12:36 ` Tais M. Hansen
2003-01-23 15:08 ` Takashi Iwai
2003-01-23 17:50 ` Tais M. Hansen
2003-01-23 18:07 ` Takashi Iwai
2003-01-23 18:43 ` Tais M. Hansen
2003-01-24 9:12 ` Takashi Iwai
2003-01-24 12:41 ` Tais M. Hansen
2003-01-24 13:30 ` Takashi Iwai
2003-01-24 14:12 ` Tais M. Hansen
2003-01-24 15:45 ` Takashi Iwai
2003-01-24 16:40 ` Tais M. Hansen
2003-01-24 17:08 ` Takashi Iwai
2003-01-24 21:24 ` Tais M. Hansen
2003-01-27 10:42 ` Takashi Iwai
2003-01-27 14:42 ` Tais M. Hansen
2003-01-27 15:15 ` Takashi Iwai
2003-01-27 17:01 ` Tais M. Hansen
2003-01-27 17:27 ` Takashi Iwai [this message]
2003-01-28 0:43 ` VIA823x testing Tais M. Hansen
2003-01-28 9:31 ` Takashi Iwai
2003-01-28 13:25 ` Tais M. Hansen
2003-01-28 16:21 ` Takashi Iwai
2003-01-28 23:19 ` Tais M. Hansen
2003-01-24 16:42 ` Re: [Alsa-user] Upgrade problems -addendum Tais M. Hansen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=s5hvg0amrk8.wl@alsa2.suse.de \
--to=tiwai@suse.de \
--cc=alsa-devel@lists.sourceforge.net \
--cc=tais.hansen@osd.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.