Subject: kern/18375: Added support for VIA VT8233 AC'97 to the auvia driver
To: None <gnats-bugs@gnats.netbsd.org>
From: None <ola@mreriksson.net>
List: netbsd-bugs
Date: 09/22/2002 20:31:30
>Number:         18375
>Category:       kern
>Synopsis:       Added needed changes to use VIA VT8233 AC'97 with the auvia driver.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Sep 22 11:33:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Ola Eriksson
>Release:        NetBSD 1.6D
>Organization:
	
>Environment:
	
	
System: NetBSD herbert 1.6D NetBSD 1.6D (VT8233TEST) #5: Sun Sep 22 13:18:37 CEST 2002 root@herbert:/usr/src/sys/arch/i386/compile/VT8233TEST i386
Architecture: i386
Machine: i386
>Description:
The VIATECH VT8233 AC'97 audio chipset did not run out-of-the-box with the
auvia(4) driver by just adding it's product id to the driver. Needed changes
where imported from OpenBSD to solve this.
>How-To-Repeat:
N/A
>Fix:

Apply the two patches below:

--- /sys/dev/pci/auvia.c.orig	Sun Sep 22 00:55:50 2002
+++ /sys/dev/pci/auvia.c	Sun Sep 22 11:51:23 2002
@@ -37,7 +37,7 @@
  */
 
 /*
- * VIA Technologies VT82C686A Southbridge Audio Driver
+ * VIA Technologies VT82C686A / VT8233 Southbridge Audio Driver
  *
  * Documentation links:
  *
@@ -131,22 +131,35 @@
 #define		AUVIA_PCICONF_ACFM	 0x00000200	/* FM enab */
 #define		AUVIA_PCICONF_ACSB	 0x00000100	/* SB enab */
 
-#define AUVIA_PLAY_STAT			0x00
-#define AUVIA_RECORD_STAT		0x10
+#define		AUVIA_PLAY_BASE						0x00
+#define		AUVIA_RECORD_BASE					0x10
+
+#define		AUVIA_RP_STAT							0x00
 #define		AUVIA_RPSTAT_INTR		0x03
-#define AUVIA_PLAY_CONTROL		0x01
-#define AUVIA_RECORD_CONTROL		0x11
+#define		AUVIA_RP_CONTROL					0x01
 #define		AUVIA_RPCTRL_START		0x80
 #define		AUVIA_RPCTRL_TERMINATE		0x40
-#define AUVIA_PLAY_MODE			0x02
-#define AUVIA_RECORD_MODE		0x12
+#define		AUVIA_RPCTRL_AUTOSTART		0x20
+/* The following are 8233 specific */
+#define		AUVIA_RPCTRL_STOP					0x04
+#define		AUVIA_RPCTRL_EOL					0x02
+#define		AUVIA_RPCTRL_FLAG					0x01
+#define		AUVIA_RP_MODE							0x02
 #define		AUVIA_RPMODE_INTR_FLAG		0x01
 #define		AUVIA_RPMODE_INTR_EOL		0x02
 #define		AUVIA_RPMODE_STEREO		0x10
 #define		AUVIA_RPMODE_16BIT		0x20
 #define		AUVIA_RPMODE_AUTOSTART		0x80
-#define	AUVIA_PLAY_DMAOPS_BASE		0x04
-#define	AUVIA_RECORD_DMAOPS_BASE	0x14
+#define		AUVIA_RP_DMAOPS_BASE			0x04
+
+#define		VIA8233_RP_DXS_LVOL				0x02
+#define		VIA8233_RP_DXS_RVOL				0x03
+#define		VIA8233_RP_RATEFMT				0x08
+#define		VIA8233_RATEFMT_48K				0xfffff
+#define		VIA8233_RATEFMT_STEREO		0x00100000
+#define		VIA8233_RATEFMT_16BIT			0x00200000
+
+#define		VIA_RP_DMAOPS_COUNT				0x0c
 
 #define	AUVIA_CODEC_CTL			0x80
 #define		AUVIA_CODEC_READ		0x00800000
@@ -203,6 +216,7 @@
 		return 0;
 	switch (PCI_PRODUCT(pa->pa_id)) {
 	case PCI_PRODUCT_VIATECH_VT82C686A_AC97:
+	case PCI_PRODUCT_VIATECH_VT8233_AC97:
 		break;
 	default:
 		return 0;
@@ -222,10 +236,24 @@
 	pci_chipset_tag_t pc = pa->pa_pc;
         pcitag_t pt = pa->pa_tag;
         pci_intr_handle_t ih;
+				bus_size_t iosize;
 	pcireg_t pr;
 	u_int16_t v;
         int r, i;
 
+	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT8233_AC97)
+		sc->sc_flags |= AUVIA_FLAGS_VT8233;
+
+	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
+		&sc->sc_ioh, NULL, &iosize)) {
+			printf(": can't map i/o space\n");
+			return;
+	}
+
+	sc->sc_dmat = pa->pa_dmat;
+	sc->sc_pc = pc;
+	sc->sc_pt = pt;
+
 	r = PCI_REVISION(pa->pa_class);
 	sc->sc_revision[1] = '\0';
 	if (r == 0x20) {
@@ -236,11 +264,17 @@
 		sprintf(sc->sc_revision, "0x%02X", r);
 	}
 
+	if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
+		printf(": VIA VT8233 AC'97 Audio (rev %s)\n",
+			sc->sc_revision);
+	} else {
 	printf(": VIA VT82C686A AC'97 Audio (rev %s)\n",
 		sc->sc_revision);
+	}
 
 	if (pci_intr_map(pa, &ih)) {
-		printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+		printf(": couldn't map interrupt\n");
+		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
 		return;
 	}
 	intrstr = pci_intr_string(pc, ih);
@@ -251,21 +285,12 @@
 		if (intrstr != NULL)
 			printf(" at %s", intrstr);
 		printf("\n");
+		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
 		return;
 	}
 
-	sc->sc_dmat = pa->pa_dmat;
-	sc->sc_pc = pc;
-	sc->sc_pt = pt;
-
 	printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
 
-	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
-                           &sc->sc_ioh, &sc->sc_ioaddr, &sc->sc_iosize)) {
-		printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
-		return;
-	}
-
 	/* disable SBPro compat & others */
 	pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK);
 
@@ -288,6 +313,8 @@
 	if ((r = ac97_attach(&sc->host_if)) != 0) {
 		printf("%s: can't attach codec (error 0x%X)\n",
 			sc->sc_dev.dv_xname, r);
+		pci_intr_disestablish(pc, sc->sc_ih);
+		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
 		return;
 	}
 
@@ -536,7 +563,7 @@
 	struct auvia_softc *sc = addr;
 	struct audio_params *p;
 	u_int16_t regval;
-	int reg, mode;
+	int reg, mode, base;
 
 	/* for mode in (RECORD, PLAY) */
 	for (mode = AUMODE_RECORD; mode != -1; 
@@ -544,7 +571,30 @@
 		if ((setmode & mode) == 0)
 			continue;
 
-		p = mode == AUMODE_PLAY ? play : rec;
+		if (mode == AUMODE_PLAY ) {
+			p = play;
+			base = AUVIA_PLAY_BASE;
+		} else {
+			p = rec;
+			base = AUVIA_RECORD_BASE;
+		}
+
+		if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
+			u_int32_t v = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+				base + VIA8233_RP_RATEFMT) & ~(VIA8233_RATEFMT_48K
+				| VIA8233_RATEFMT_STEREO | VIA8233_RATEFMT_16BIT);
+
+			v |= VIA8233_RATEFMT_48K *
+				(p->sample_rate / 20) / (48000 / 20);
+
+			if (p->channels == 2)
+				v |= VIA8233_RATEFMT_STEREO;
+			if( p->precision == 16)
+				v |= VIA8233_RATEFMT_16BIT;
+
+			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+				base + VIA8233_RP_RATEFMT, v);
+		}
 
 		if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
 		    (p->precision != 8 && p->precision != 16) ||
@@ -633,8 +683,8 @@
 {
         struct auvia_softc *sc = addr;
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_CONTROL,
-		AUVIA_RPCTRL_TERMINATE);
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+		AUVIA_PLAY_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
 
 	return 0;
 }
@@ -645,8 +695,8 @@
 {
         struct auvia_softc *sc = addr;
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_CONTROL,
-		AUVIA_RPCTRL_TERMINATE);
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+		AUVIA_PLAY_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
 
 	return 0;
 }
@@ -896,14 +946,25 @@
 	ch->sc_intr = intr;
 	ch->sc_arg = arg;
 
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_DMAOPS_BASE,
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+			AUVIA_PLAY_BASE + AUVIA_RP_DMAOPS_BASE,
 		ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_MODE,
-		ch->sc_reg);
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+		AUVIA_PLAY_BASE + AUVIA_RP_CONTROL, ch->sc_reg);
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_CONTROL,
-		AUVIA_RPCTRL_START);
+	if (sc->sc_flags & AUVIA_FLAGS_VT8233) {
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_PLAY_BASE + VIA8233_RP_DXS_LVOL, 0);
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_PLAY_BASE + VIA8233_RP_DXS_RVOL, 0);
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_PLAY_BASE + AUVIA_RP_CONTROL,
+			AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
+			AUVIA_RPCTRL_STOP  | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
+	} else
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_PLAY_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
 
 	return 0;
 }
@@ -932,14 +993,25 @@
 	ch->sc_intr = intr;
 	ch->sc_arg = arg;
 
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_DMAOPS_BASE,
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+		AUVIA_RECORD_BASE + AUVIA_RP_DMAOPS_BASE,
 		ch->sc_dma_ops_dma->map->dm_segs[0].ds_addr);
-
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_MODE,
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+		AUVIA_RECORD_BASE + AUVIA_RP_MODE,
 		ch->sc_reg);
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_CONTROL,
-		AUVIA_RPCTRL_START);
+	if(sc->sc_flags & AUVIA_FLAGS_VT8233) {
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_RECORD_BASE + VIA8233_RP_DXS_LVOL, 0);
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_RECORD_BASE + VIA8233_RP_DXS_RVOL, 0);
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_RECORD_BASE + AUVIA_RP_CONTROL,
+			AUVIA_RPCTRL_START | AUVIA_RPCTRL_AUTOSTART |
+			AUVIA_RPCTRL_STOP  | AUVIA_RPCTRL_EOL | AUVIA_RPCTRL_FLAG);
+	} else
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_RECORD_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_START);
 
 	return 0;
 }
@@ -954,24 +1026,27 @@
 
 	rval = 0;
 
-	r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_STAT);
+	r = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
+		AUVIA_RECORD_BASE + AUVIA_RP_STAT);
 	if (r & AUVIA_RPSTAT_INTR) {
 		if (sc->sc_record.sc_intr)
 			sc->sc_record.sc_intr(sc->sc_record.sc_arg);
 
 		/* clear interrupts */
-		bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_STAT,
-			AUVIA_RPSTAT_INTR);
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_RECORD_BASE + AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
 		rval = 1;
 	}
-	r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_STAT);
+
+	r = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
+		AUVIA_PLAY_BASE + AUVIA_RP_STAT);
 	if (r & AUVIA_RPSTAT_INTR) {
 		if (sc->sc_play.sc_intr)
 			sc->sc_play.sc_intr(sc->sc_play.sc_arg);
 
 		/* clear interrupts */
-		bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_STAT,
-			AUVIA_RPSTAT_INTR);
+		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+			AUVIA_PLAY_BASE + AUVIA_RP_STAT, AUVIA_RPSTAT_INTR);
 		rval = 1;
 	}




--- /sys/dev/pci/auviavar.h.orig	Sun Sep 22 01:04:24 2002
+++ /sys/dev/pci/auviavar.h	Sun Sep 22 01:05:27 2002
@@ -54,6 +54,9 @@
 	struct device sc_dev;
 
 	char sc_revision[8];
+	u_int	sc_flags;
+#define	AUVIA_FLAGS_VT8233		0x0001
+
 	u_long sc_fixed_rate;		/* if codec doesn't support variable
 					 * rate audio, set to the fixed rate
 					 * it uses */
>Release-Note:
>Audit-Trail:
>Unformatted: