summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2002-05-30 15:13:21 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2002-05-30 15:13:21 +0000
commit4f5535f8f919f3fc2748c8597f3112b9b4a78909 (patch)
tree0f2db97b3a120a71673830afa2b6d346af2edeeb
parent44e84fa8e11719f94458e3ff1ce6d93fec7ad8b7 (diff)
proper support for vt8233; from freebsd; tested by Jolan Luff <jolan@encryptedemail.net>
-rw-r--r--sys/dev/pci/auvia.c164
-rw-r--r--sys/dev/pci/auviavar.h6
2 files changed, 119 insertions, 51 deletions
diff --git a/sys/dev/pci/auvia.c b/sys/dev/pci/auvia.c
index 85b4faf7fa6..c2551d6064e 100644
--- a/sys/dev/pci/auvia.c
+++ b/sys/dev/pci/auvia.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auvia.c,v 1.16 2002/05/08 18:33:53 mickey Exp $ */
+/* $OpenBSD: auvia.c,v 1.17 2002/05/30 15:13:20 mickey Exp $ */
/* $NetBSD: auvia.c,v 1.7 2000/11/15 21:06:33 jdolecek Exp $ */
/*-
@@ -132,22 +132,35 @@ struct cfattach auvia_ca = {
#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
@@ -223,11 +236,26 @@ auvia_attach(struct device *parent, struct device *self, void *aux)
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;
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, 0)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ sc->sc_dmat = pa->pa_dmat;
+ sc->sc_pc = pc;
+ sc->sc_pt = pt;
+
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);
@@ -239,21 +267,12 @@ auvia_attach(struct device *parent, struct device *self, void *aux)
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\n", intrstr);
- if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
- &sc->sc_ioh, &sc->sc_ioaddr, &sc->sc_iosize, 0)) {
- 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);
@@ -276,6 +295,8 @@ auvia_attach(struct device *parent, struct device *self, void *aux)
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;
}
@@ -507,7 +528,7 @@ auvia_set_params(void *addr, int setmode, int usemode,
struct auvia_softc *sc = addr;
struct audio_params *p;
u_int16_t regval;
- int mode;
+ int mode, base;
/* for mode in (RECORD, PLAY) */
for (mode = AUMODE_RECORD; mode != -1;
@@ -515,7 +536,30 @@ auvia_set_params(void *addr, int setmode, int usemode,
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 (ac97_set_rate(sc->codec_if, p, mode))
return (EINVAL);
@@ -596,8 +640,8 @@ auvia_halt_output(void *addr)
{
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;
}
@@ -608,8 +652,8 @@ auvia_halt_input(void *addr)
{
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_RECORD_BASE + AUVIA_RP_CONTROL, AUVIA_RPCTRL_TERMINATE);
return 0;
}
@@ -854,14 +898,25 @@ auvia_trigger_output(void *addr, void *start, void *end,
ch->sc_intr = intr;
ch->sc_arg = arg;
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_PLAY_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_CONTROL,
- AUVIA_RPCTRL_START);
+ 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_BASE + AUVIA_RP_CONTROL, ch->sc_reg);
+
+ 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;
}
@@ -890,14 +945,25 @@ auvia_trigger_input(void *addr, void *start, void *end,
ch->sc_intr = intr;
ch->sc_arg = arg;
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_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,
- ch->sc_reg);
-
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, AUVIA_RECORD_CONTROL,
- AUVIA_RPCTRL_START);
+ 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_BASE + AUVIA_RP_MODE,
+ ch->sc_reg);
+
+ 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;
}
@@ -910,25 +976,27 @@ auvia_intr(void *arg)
u_int8_t r;
int i = 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);
i++;
}
- 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);
i++;
}
diff --git a/sys/dev/pci/auviavar.h b/sys/dev/pci/auviavar.h
index b6042b2a79d..9dee15abd6e 100644
--- a/sys/dev/pci/auviavar.h
+++ b/sys/dev/pci/auviavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auviavar.h,v 1.4 2001/11/19 17:47:37 mickey Exp $ */
+/* $OpenBSD: auviavar.h,v 1.5 2002/05/30 15:13:20 mickey Exp $ */
/* $NetBSD: auviavar.h,v 1.1 2000/03/31 04:45:29 tsarna Exp $ */
/*-
@@ -56,14 +56,14 @@ struct auvia_softc {
void *sc_ih; /* interrupt handle */
char sc_revision[8];
+ u_int sc_flags;
+#define AUVIA_FLAGS_VT8233 0x0001
pci_chipset_tag_t sc_pc;
pcitag_t sc_pt;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
- bus_addr_t sc_ioaddr;
- bus_size_t sc_iosize;
bus_dma_tag_t sc_dmat;
struct ac97_host_if host_if;