diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2008-10-23 21:50:02 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2008-10-23 21:50:02 +0000 |
commit | 6f459ae12d184272e7ef7b3f547537bbf501f31a (patch) | |
tree | 33f295d20f143e6eaf9ae5cb909524d945af7e16 /sys/dev/pci | |
parent | 403c943deb4dc1db75d2ecc26efa828ba93697cf (diff) |
S/PDIF output support in ac97(4), auich(4) and auvia(4)
from NetBSD
tested by a few with no regressions. optical works for jsg@.
ok ratchov@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/auich.c | 142 | ||||
-rw-r--r-- | sys/dev/pci/auvia.c | 139 | ||||
-rw-r--r-- | sys/dev/pci/auviavar.h | 3 |
3 files changed, 178 insertions, 106 deletions
diff --git a/sys/dev/pci/auich.c b/sys/dev/pci/auich.c index fde33499d53..97147001f97 100644 --- a/sys/dev/pci/auich.c +++ b/sys/dev/pci/auich.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auich.c,v 1.75 2008/10/23 21:28:31 jakemsr Exp $ */ +/* $OpenBSD: auich.c,v 1.76 2008/10/23 21:50:01 jakemsr Exp $ */ /* * Copyright (c) 2000,2001 Michael Shalayeff @@ -184,6 +184,7 @@ struct auich_softc { struct ac97_codec_if *codec_if; struct ac97_host_if host_if; + int sc_spdif; /* dma scatter-gather buffer lists */ @@ -344,6 +345,7 @@ int auich_write_codec(void *, u_int8_t, u_int16_t); void auich_reset_codec(void *); enum ac97_host_flags auich_flags_codec(void *); unsigned int auich_calibrate(struct auich_softc *); +void auich_spdif_event(void *, int); int auich_match(parent, match, aux) @@ -508,6 +510,7 @@ auich_attach(parent, self, aux) sc->host_if.write = auich_write_codec; sc->host_if.reset = auich_reset_codec; sc->host_if.flags = auich_flags_codec; + sc->host_if.spdif_event = auich_spdif_event; if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001) sc->flags = AC97_HOST_SWAPPED_CHANNELS; @@ -517,6 +520,7 @@ auich_attach(parent, self, aux) bus_space_unmap(sc->iot_mix, sc->mix_ioh, mix_size); return; } + sc->codec_if->vtbl->unlock(sc->codec_if); audio_attach_mi(&auich_hw_if, sc, &sc->sc_dev); @@ -618,6 +622,13 @@ auich_flags_codec(void *v) return (sc->flags); } +void +auich_spdif_event(void *v, int flag) +{ + struct auich_softc *sc = v; + sc->sc_spdif = flag; +} + int auich_open(v, flags) void *v; @@ -627,6 +638,9 @@ auich_open(v, flags) if (sc->sc_ac97rate == -1) sc->sc_ac97rate = auich_calibrate(sc); + + sc->codec_if->vtbl->lock(sc->codec_if); + return 0; } @@ -634,6 +648,9 @@ void auich_close(v) void *v; { + struct auich_softc *sc = v; + + sc->codec_if->vtbl->unlock(sc->codec_if); } void @@ -647,57 +664,71 @@ auich_query_encoding(v, aep) void *v; struct audio_encoding *aep; { - switch (aep->index) { - case 0: - strlcpy(aep->name, AudioEulinear, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULINEAR; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 1: - strlcpy(aep->name, AudioEmulaw, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULAW; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 2: - strlcpy(aep->name, AudioEalaw, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ALAW; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 3: - strlcpy(aep->name, AudioEslinear, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_SLINEAR; - aep->precision = 8; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 4: - strlcpy(aep->name, AudioEslinear_le, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_SLINEAR_LE; - aep->precision = 16; - aep->flags = 0; - return (0); - case 5: - strlcpy(aep->name, AudioEulinear_le, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULINEAR_LE; - aep->precision = 16; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 6: - strlcpy(aep->name, AudioEslinear_be, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_SLINEAR_BE; - aep->precision = 16; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 7: - strlcpy(aep->name, AudioEulinear_be, sizeof aep->name); - aep->encoding = AUDIO_ENCODING_ULINEAR_BE; - aep->precision = 16; - aep->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - default: - return (EINVAL); + struct auich_softc *sc = v; + if (sc->sc_spdif) { + switch (aep->index) { + case 0: + strlcpy(aep->name, AudioEslinear_le, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_SLINEAR_LE; + aep->precision = 16; + aep->flags = 0; + return (0); + default: + return (EINVAL); + } + } else { + switch (aep->index) { + case 0: + strlcpy(aep->name, AudioEulinear, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_ULINEAR; + aep->precision = 8; + aep->flags = 0; + return (0); + case 1: + strlcpy(aep->name, AudioEmulaw, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_ULAW; + aep->precision = 8; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 2: + strlcpy(aep->name, AudioEalaw, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_ALAW; + aep->precision = 8; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 3: + strlcpy(aep->name, AudioEslinear, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_SLINEAR; + aep->precision = 8; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 4: + strlcpy(aep->name, AudioEslinear_le, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_SLINEAR_LE; + aep->precision = 16; + aep->flags = 0; + return (0); + case 5: + strlcpy(aep->name, AudioEulinear_le, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_ULINEAR_LE; + aep->precision = 16; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 6: + strlcpy(aep->name, AudioEslinear_be, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_SLINEAR_BE; + aep->precision = 16; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 7: + strlcpy(aep->name, AudioEulinear_be, sizeof aep->name); + aep->encoding = AUDIO_ENCODING_ULINEAR_BE; + aep->precision = 16; + aep->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + default: + return (EINVAL); + } } } @@ -716,6 +747,13 @@ auich_set_params(v, setmode, usemode, play, rec) u_int16_t ext_id; if (setmode & AUMODE_PLAY) { + /* only 16-bit 48kHz slinear_le if s/pdif enabled */ + if (sc->sc_spdif && + ((play->sample_rate != 48000) || (play->precision != 16) || + (play->encoding != AUDIO_ENCODING_SLINEAR_LE))) + return (EINVAL); + } + if (setmode & AUMODE_PLAY) { play->factor = 1; play->sw_code = NULL; switch(play->encoding) { diff --git a/sys/dev/pci/auvia.c b/sys/dev/pci/auvia.c index f6307d4a960..9a6eab62cc7 100644 --- a/sys/dev/pci/auvia.c +++ b/sys/dev/pci/auvia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auvia.c,v 1.42 2008/10/02 18:29:40 jakemsr Exp $ */ +/* $OpenBSD: auvia.c,v 1.43 2008/10/23 21:50:01 jakemsr Exp $ */ /* $NetBSD: auvia.c,v 1.28 2002/11/04 16:38:49 kent Exp $ */ /*- @@ -217,6 +217,7 @@ int auvia_read_codec(void *, u_int8_t, u_int16_t *); void auvia_reset_codec(void *); int auvia_waitready_codec(struct auvia_softc *sc); int auvia_waitvalid_codec(struct auvia_softc *sc); +void auvia_spdif_event(void *, int); const struct pci_matchid auvia_devices[] = { { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_AC97 }, @@ -301,6 +302,7 @@ auvia_attach(struct device *parent, struct device *self, void *aux) sc->host_if.read = auvia_read_codec; sc->host_if.write = auvia_write_codec; sc->host_if.reset = auvia_reset_codec; + sc->host_if.spdif_event = auvia_spdif_event; if ((r = ac97_attach(&sc->host_if)) != 0) { printf("%s: can't attach codec (error 0x%X)\n", @@ -341,6 +343,7 @@ auvia_attach(struct device *parent, struct device *self, void *aux) auvia_set_port(sc, &ctl); audio_attach_mi(&auvia_hw_if, sc, &sc->sc_dev); + sc->codec_if->vtbl->unlock(sc->codec_if); } @@ -458,9 +461,18 @@ auvia_read_codec(void *addr, u_int8_t reg, u_int16_t *val) } +void +auvia_spdif_event(void *addr, int flag) +{ + struct auvia_softc *sc = addr; + sc->sc_spdif = flag; +} + int auvia_open(void *addr, int flags) { + struct auvia_softc *sc = addr; + sc->codec_if->vtbl->lock(sc->codec_if); return 0; } @@ -469,6 +481,7 @@ void auvia_close(void *addr) { struct auvia_softc *sc = addr; + sc->codec_if->vtbl->unlock(sc->codec_if); auvia_halt_output(sc); auvia_halt_input(sc); @@ -481,60 +494,74 @@ auvia_close(void *addr) int auvia_query_encoding(void *addr, struct audio_encoding *fp) { - switch (fp->index) { - case 0: - strlcpy(fp->name, AudioEulinear, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULINEAR; - fp->precision = 8; - fp->flags = 0; - return (0); - case 1: - strlcpy(fp->name, AudioEmulaw, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULAW; - fp->precision = 8; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 2: - strlcpy(fp->name, AudioEalaw, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ALAW; - fp->precision = 8; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 3: - strlcpy(fp->name, AudioEslinear, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_SLINEAR; - fp->precision = 8; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 4: - strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_SLINEAR_LE; - fp->precision = 16; - fp->flags = 0; - return (0); - case 5: - strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULINEAR_LE; - fp->precision = 16; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 6: - strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_SLINEAR_BE; - fp->precision = 16; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - case 7: - strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); - fp->encoding = AUDIO_ENCODING_ULINEAR_BE; - fp->precision = 16; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - return (0); - default: - return (EINVAL); + struct auvia_softc *sc = addr; + + if (sc->sc_spdif) { + switch (fp->index) { + case 0: + strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR_LE; + fp->precision = 16; + fp->flags = 0; + return (0); + default: + return (EINVAL); + } + } else { + switch (fp->index) { + case 0: + strlcpy(fp->name, AudioEulinear, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULINEAR; + fp->precision = 8; + fp->flags = 0; + return (0); + case 1: + strlcpy(fp->name, AudioEmulaw, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULAW; + fp->precision = 8; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 2: + strlcpy(fp->name, AudioEalaw, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ALAW; + fp->precision = 8; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 3: + strlcpy(fp->name, AudioEslinear, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR; + fp->precision = 8; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 4: + strlcpy(fp->name, AudioEslinear_le, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR_LE; + fp->precision = 16; + fp->flags = 0; + return (0); + case 5: + strlcpy(fp->name, AudioEulinear_le, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULINEAR_LE; + fp->precision = 16; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 6: + strlcpy(fp->name, AudioEslinear_be, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_SLINEAR_BE; + fp->precision = 16; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + case 7: + strlcpy(fp->name, AudioEulinear_be, sizeof fp->name); + fp->encoding = AUDIO_ENCODING_ULINEAR_BE; + fp->precision = 16; + fp->flags = AUDIO_ENCODINGFLAG_EMULATED; + return (0); + default: + return (EINVAL); + } } } - void auvia_set_params_sub(struct auvia_softc *sc, struct auvia_softc_chan *ch, struct audio_params *p) @@ -632,6 +659,12 @@ auvia_set_params(void *addr, int setmode, int usemode, (p->precision != 8 && p->precision != 16)) return (EINVAL); + /* XXX only 16-bit 48kHz slinear_le if s/pdif enabled ? */ + if (sc->sc_spdif && + ((p->sample_rate != 48000) || (p->precision != 16) || + (p->encoding != AUDIO_ENCODING_SLINEAR_LE))) + return (EINVAL); + if (AC97_IS_FIXED_RATE(codec)) { p->sample_rate = AC97_SINGLE_RATE; } else { diff --git a/sys/dev/pci/auviavar.h b/sys/dev/pci/auviavar.h index d83879ab9c4..b9a6fcbebb0 100644 --- a/sys/dev/pci/auviavar.h +++ b/sys/dev/pci/auviavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auviavar.h,v 1.10 2008/10/02 18:29:40 jakemsr Exp $ */ +/* $OpenBSD: auviavar.h,v 1.11 2008/10/23 21:50:01 jakemsr Exp $ */ /* $NetBSD: auviavar.h,v 1.1 2000/03/31 04:45:29 tsarna Exp $ */ /*- @@ -63,6 +63,7 @@ struct auvia_softc { struct ac97_host_if host_if; struct ac97_codec_if *codec_if; int bufsize; + int sc_spdif; struct auvia_dma *sc_dmas; |