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: