All of lore.kernel.org
 help / color / mirror / Atom feed
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: Fri, 24 Jan 2003 16:45:13 +0100	[thread overview]
Message-ID: <s5h8yxapn5i.wl@alsa2.suse.de> (raw)
In-Reply-To: <200301241512.17848.tais.hansen@osd.dk>

[-- Attachment #1: Type: text/plain, Size: 1490 bytes --]

At Fri, 24 Jan 2003 15:12:13 +0100,
Tais M. Hansen <tais.hansen@osd.dk> wrote:
> 
> On Friday 24 January 2003 14:30, Takashi Iwai wrote:
> > > Same deal as before, another 3 files filled with debug output. Good luck.
> > > :)
> > it seems that we need to use CURRPTR always on your chip.
> > i guess this depends on the board, how reliable IDX register is.
> 
> Need any specific info about the board? Chip? I saw some talks about the 
> ALC650 chip in another thread on this list and alsamixer claims I've got such 
> a chip.
 
most likely it has nothing to do with ALC650.
but lspci -v and lspci -n (for the chip) might be helpful for the
later development.

> 
> > if the attached new patch works, i'll add a module option to enable
> > this behavior.
> > good luck for you, too :)
> 
> Thanks. Maybe we should exchange good luck more often. Seems like you worked 
> some magic here. :)

now comes the patch of the week:

now you'll have possibility to change the behavior of the driver via a
module option idx_detect.

idx_detect=0 : the default, won't work for you.
idx_detect=1 : like test7.  perhaps not perfect.
idx_detect=2 : use the interrupt pointer only.  the resolution will be
               in the size of periods.  this should work.
idx_detect=3 : like test7 but don't evaluate the counter.
               might be be finer than idx_detect=2 but might be
               inaccurate in some cases.

if the debug output is only 'elapsed only', it's ok.


have fun :)


Takashi

[-- Attachment #2: via-pointer-test8.dif --]
[-- Type: application/octet-stream, Size: 10846 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	24 Jan 2003 15:36:52 -0000
@@ -75,6 +75,7 @@
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
+static int idx_detect[SNDRV_CARDS];
 
 MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
 MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge.");
@@ -88,9 +89,12 @@
 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");
+MODULE_PARM(idx_detect, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(idx_detect, "Index update method for VIA823x chips (0 = default).");
+MODULE_PARM_SYNTAX(idx_detect, SNDRV_ENABLED);
 
 
 /* pci ids */
@@ -203,6 +207,14 @@
 #define VIA_TBL_BIT_FLAG	0x40000000
 #define VIA_TBL_BIT_EOL		0x80000000
 
+/* idx_detection */
+enum {
+	VIA_IDX_USE_IDX_REG,
+	VIA_IDX_USE_CURRPTR,
+	VIA_IDX_USE_PERIODS,
+	VIA_IDX_USE_CPTR_IDX
+};
+
 /*
  */
 
@@ -230,7 +242,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 +277,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 +324,7 @@
 	dev->tbl_entries = idx;
 	dev->bufsize = periods * fragsize;
 	dev->bufsize2 = dev->bufsize / 2;
+	dev->periods = periods;
 	return 0;
 }
 
@@ -318,13 +340,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 */
 
@@ -344,6 +371,7 @@
 
 	unsigned char old_legacy;
 	unsigned char old_legacy_cfg;
+	int idx_detection;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -365,8 +393,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 +509,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 +542,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 +578,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;
@@ -585,17 +625,17 @@
 	/* 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;
+			snd_printd("invalid via82xx_cur_ptr, using last valid pointer\n");
+			return 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;
+				snd_printd("invalid via82xx_cur_ptr (2), using last valid pointer\n");
+				return viadev->lastpos;
 			}
 		}
 	}
@@ -646,11 +686,35 @@
 	snd_assert(viadev->tbl_entries, return 0);
 	if (!(inb(VIAREG(chip, OFFSET_STATUS) + viadev->reg_offset) & VIA_REG_STAT_ACTIVE))
 		return 0;
+
+	if (chip->idx_detection == VIA_IDX_USE_PERIODS) {
+		idx = viadev->period_idx[viadev->intr_cnt];
+		res = viadev->idx_table[idx].offset;
+		return bytes_to_frames(substream->runtime, res);
+	}
+
 	spin_lock(&chip->reg_lock);
 	count = inl(VIAREG(chip, OFFSET_CURR_COUNT) + viadev->reg_offset);
-	idx = count >> 24;
-	count &= 0xffffff;
-	res = calc_linear_pos(viadev, idx, count);
+	switch (chip->idx_detection) {
+	case VIA_IDX_USE_CURRPTR:
+	case VIA_IDX_USE_CPTR_IDX:
+		/* detect the index from CURRPTR register */
+		idx = inl(VIAREG(chip, OFFSET_CURR_PTR) + viadev->reg_offset);
+		if (idx <= (unsigned int)viadev->table_addr)
+			idx = 0;
+		else
+			idx = (idx - (unsigned int)viadev->table_addr - 4) / 8;
+		break;
+	default:
+		idx = (count >> 24) & viadev->tbl_entries;
+		break;
+	}
+	if (chip->idx_detection != VIA_IDX_USE_CPTR_IDX) {
+		count &= 0xffffff;
+		res = calc_linear_pos(viadev, idx, count);
+	} else {
+		res = viadev->idx_table[idx].offset;
+	}
 	spin_unlock(&chip->reg_lock);
 
 	return bytes_to_frames(substream->runtime, res);
@@ -950,7 +1014,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 +1429,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 +1715,19 @@
 	return 0;
 }
 
+struct via823x_info {
+	int revision;
+	char *name;
+	int type;
+};
+static struct via823x_info via823x_cards[] = {
+	{ 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 +1735,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 +1749,30 @@
 	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);
+			}
+		}
+		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;
 	}
@@ -1697,6 +1780,8 @@
 	if ((err = snd_via82xx_create(card, pci, chip_type, ac97_clock[dev], &chip)) < 0)
 		goto __error;
 
+	chip->idx_detection = idx_detect[dev];
+
 	if ((err = snd_via82xx_mixer_new(chip)) < 0)
 		goto __error;
 
@@ -1705,7 +1790,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 +1877,3 @@
 __setup("snd-via82xx=", alsa_card_via82xx_setup);
 
 #endif /* ifndef MODULE */
- 

  reply	other threads:[~2003-01-24 15:45 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 [this message]
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
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=s5h8yxapn5i.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.