diff options
Diffstat (limited to 'sys/dev/pci/auvia.c')
-rw-r--r-- | sys/dev/pci/auvia.c | 139 |
1 files changed, 91 insertions, 48 deletions
diff --git a/sys/dev/pci/auvia.c b/sys/dev/pci/auvia.c index 8d7b02468b1..6e38f7bad23 100644 --- a/sys/dev/pci/auvia.c +++ b/sys/dev/pci/auvia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auvia.c,v 1.21 2002/11/19 18:40:17 jason Exp $ */ +/* $OpenBSD: auvia.c,v 1.22 2003/02/28 15:14:08 mickey Exp $ */ /* $NetBSD: auvia.c,v 1.7 2000/11/15 21:06:33 jdolecek Exp $ */ /*- @@ -132,41 +132,49 @@ struct cfattach auvia_ca = { #define AUVIA_PCICONF_ACFM 0x00000200 /* FM enab */ #define AUVIA_PCICONF_ACSB 0x00000100 /* SB enab */ -#define AUVIA_PLAY_BASE 0x00 -#define AUVIA_RECORD_BASE 0x10 +#define AUVIA_PLAY_BASE 0x00 +#define AUVIA_RECORD_BASE 0x10 -#define AUVIA_RP_STAT 0x00 -#define AUVIA_RPSTAT_INTR 0x03 -#define AUVIA_RP_CONTROL 0x01 -#define AUVIA_RPCTRL_START 0x80 -#define AUVIA_RPCTRL_TERMINATE 0x40 -#define AUVIA_RPCTRL_AUTOSTART 0x20 +#define AUVIA_RP_STAT 0x00 +#define AUVIA_RPSTAT_INTR 0x03 +#define AUVIA_RP_CONTROL 0x01 +#define AUVIA_RPCTRL_START 0x80 +#define AUVIA_RPCTRL_TERMINATE 0x40 +#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_RP_DMAOPS_BASE 0x04 - -#define VIA8233_RP_DXS_LVOL 0x02 -#define VIA8233_RP_DXS_RVOL 0x03 -#define VIA8233_RP_RATEFMT 0x08 +#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_RP_DMAOPS_BASE 0x04 +#define AUVIA_RPDMAOP_PTR 0x00 +#define AUVIA_RPDMAOP_IDX 0x04 +#define AUVIA_RPDMAOP_CNT 0x08 +#define AUVIA_RPDMAOP_CHIDX 0x0f + +#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_MPB_BASE 0x40 +#define AUVIA_MPBMODE_16BIT 0x80 +#define AUVIA_MPBMODE_CHMASK 0x70 -#define AUVIA_CODEC_CTL 0x80 -#define AUVIA_CODEC_READ 0x00800000 -#define AUVIA_CODEC_BUSY 0x01000000 -#define AUVIA_CODEC_PRIVALID 0x02000000 -#define AUVIA_CODEC_INDEX(x) ((x)<<16) +#define AUVIA_CAPTURE_BASE 0x60 + +#define AUVIA_CODEC_CTL 0x80 +#define AUVIA_CODEC_READ 0x00800000 +#define AUVIA_CODEC_BUSY 0x01000000 +#define AUVIA_CODEC_PRIVALID 0x02000000 +#define AUVIA_CODEC_INDEX(x) ((x)<<16) #define TIMEOUT 50 @@ -230,6 +238,7 @@ auvia_attach(struct device *parent, struct device *self, void *aux) pcitag_t pt = pa->pa_tag; pci_intr_handle_t ih; bus_size_t iosize; + const char *p; pcireg_t pr; int r, i; @@ -266,6 +275,21 @@ auvia_attach(struct device *parent, struct device *self, void *aux) printf(": %s\n", intrstr); + switch (PCI_REVISION(pa->pa_class) & 0xf0) { + case 0x10: p = "pre-8233"; break; + case 0x20: p = "8233C"; break; + case 0x30: p = "8233"; break; + case 0x50: p = "8235"; break; + case 0x40: p = "8233A"; + sc->sc_flags |= AUVIA_FLAGS_MPB; + break; + } + + sprintf(sc->sc_audev.name, "%s AC97", p); + sprintf(sc->sc_audev.version, "0x%x", + PCI_REVISION(pa->pa_class) & 0xf); + strcpy(sc->sc_audev.config, sc->sc_dev.dv_xname); + /* disable SBPro compat & others */ pr = pci_conf_read(pc, pt, AUVIA_PCICONF_JUNK); @@ -547,10 +571,33 @@ auvia_set_params(void *addr, int setmode, int usemode, 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; + if (mode == AUMODE_PLAY && + sc->sc_flags & AUVIA_FLAGS_MPB) { + static const u_int32_t nch2sl[] = { + 0, 1, 0x21, 0, + 0x4321, 0, 0x436521 + }; + int slots; + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, + AUVIA_MPB_BASE + AUVIA_RP_MODE, + (p->precision == 16? AUVIA_MPBMODE_16BIT:0) + | (p->channels << 4)); + + if (p->channels < + sizeof(nch2sl) / sizeof(*nch2sl)) + slots = 0; + else + slots = nch2sl[p->channels]; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + AUVIA_RP_DMAOPS_BASE + AUVIA_RPDMAOP_IDX, + slots | 0xff000000); + } else { + 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); @@ -652,18 +699,10 @@ auvia_halt_input(void *addr) int -auvia_getdev(void *addr, struct audio_device *retp) +auvia_getdev(void *v, struct audio_device *adp) { - struct auvia_softc *sc = addr; - - if (retp) { - strncpy(retp->name, - sc->sc_flags & AUVIA_FLAGS_VT8233? "VIA VT8233" : - "VIA VT82C686A", sizeof(retp->name)); - strncpy(retp->version, sc->sc_revision, sizeof(retp->version)); - strncpy(retp->config, "auvia", sizeof(retp->config)); - } - + struct auvia_softc *sc = v; + *adp = sc->sc_audev; return 0; } @@ -958,7 +997,7 @@ auvia_intr(void *arg) { struct auvia_softc *sc = arg; u_int8_t r; - int i = 0; + int base, i = 0; r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_BASE + AUVIA_RP_STAT); @@ -972,15 +1011,19 @@ auvia_intr(void *arg) i++; } - r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, - AUVIA_PLAY_BASE + AUVIA_RP_STAT); + + if (sc->sc_flags & AUVIA_FLAGS_MPB) + base = AUVIA_MPB_BASE; + else + base = AUVIA_PLAY_BASE; + r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 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_BASE + AUVIA_RP_STAT, AUVIA_RPSTAT_INTR); + base + AUVIA_RP_STAT, AUVIA_RPSTAT_INTR); i++; } |