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 | |
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')
-rw-r--r-- | sys/dev/ic/ac97.c | 76 | ||||
-rw-r--r-- | sys/dev/ic/ac97.h | 30 | ||||
-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 |
5 files changed, 269 insertions, 121 deletions
diff --git a/sys/dev/ic/ac97.c b/sys/dev/ic/ac97.c index 536c1bcf2f0..cef9a9b88f8 100644 --- a/sys/dev/ic/ac97.c +++ b/sys/dev/ic/ac97.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ac97.c,v 1.69 2008/10/23 20:52:50 jakemsr Exp $ */ +/* $OpenBSD: ac97.c,v 1.70 2008/10/23 21:50:01 jakemsr Exp $ */ /* * Copyright (c) 1999, 2000 Constantine Sapuntzakis @@ -126,6 +126,8 @@ const struct audio_mixer_value ac97_volume_mono = { 1 }; +#define AudioNspdif "spdif" + #define WRAP(a) &a, sizeof(a) const struct ac97_source_info { @@ -152,7 +154,8 @@ const struct ac97_source_info { CHECK_TONE, CHECK_MIC, CHECK_LOUDNESS, - CHECK_3D + CHECK_3D, + CHECK_SPDIF } req_feature; int16_t prev; @@ -293,10 +296,16 @@ const struct ac97_source_info { AUDIO_MIXER_VALUE, WRAP(ac97_volume_mono), AC97_REG_3D_CONTROL, 0x0000, 4, 0, 0, 1, CHECK_3D }, + /* External Amp */ { AudioCoutputs, AudioNextamp, NULL, AUDIO_MIXER_ENUM, WRAP(ac97_on_off), AC97_REG_POWER, 0x0000, 1, 15, 0, 0 }, + /* S/PDIF output enable */ + { AudioCoutputs, AudioNspdif, NULL, + AUDIO_MIXER_ENUM, WRAP(ac97_on_off), + AC97_REG_EXT_AUDIO_CTRL, 0x0000, 1, 2, 0, 0, CHECK_SPDIF + } /* Missing features: Simulated Stereo, POP, Loopback mode */ }; @@ -321,10 +330,13 @@ struct ac97_softc { u_int16_t caps; /* -> AC97_REG_RESET */ u_int16_t ext_id; /* -> AC97_REG_EXT_AUDIO_ID */ u_int16_t shadow_reg[128]; + int lock_counter; }; int ac97_mixer_get_port(struct ac97_codec_if *, mixer_ctrl_t *); int ac97_mixer_set_port(struct ac97_codec_if *, mixer_ctrl_t *); +void ac97_lock(struct ac97_codec_if *); +void ac97_unlock(struct ac97_codec_if *); int ac97_query_devinfo(struct ac97_codec_if *, mixer_devinfo_t *); int ac97_get_portnum_by_name(struct ac97_codec_if *, char *, char *, char *); @@ -348,7 +360,9 @@ struct ac97_codec_if_vtbl ac97civ = { ac97_restore_shadow, ac97_get_extcaps, ac97_set_rate, - ac97_set_clock + ac97_set_clock, + ac97_lock, + ac97_unlock }; const struct ac97_codecid { @@ -670,6 +684,8 @@ ac97_check_capability(struct ac97_softc *as, int check) return as->ext_id & AC97_EXT_AUDIO_CDAC; case CHECK_LFE: return as->ext_id & AC97_EXT_AUDIO_LDAC; + case CHECK_SPDIF: + return as->ext_id & AC97_EXT_AUDIO_SPDIF; case CHECK_HEADPHONES: return as->caps & AC97_CAPS_HEADPHONES; case CHECK_TONE: @@ -783,7 +799,7 @@ int ac97_attach(struct ac97_host_if *host_if) { struct ac97_softc *as; - u_int16_t id1, id2; + u_int16_t id1, id2, val; u_int32_t id; u_int16_t extstat, rate; mixer_ctrl_t ctl; @@ -868,17 +884,31 @@ ac97_attach(struct ac97_host_if *host_if) | AC97_EXT_AUDIO_LDAC)) { ac97_read(as, AC97_REG_EXT_AUDIO_CTRL, &extstat); - if (as->ext_id & AC97_EXT_AUDIO_VRA) - extstat |= AC97_EXT_AUDIO_VRA; extstat &= ~AC97_EXT_AUDIO_DRA; + if (as->ext_id & AC97_EXT_AUDIO_VRM) extstat |= AC97_EXT_AUDIO_VRM; - if (as->ext_id & AC97_EXT_AUDIO_CDAC) - extstat |= AC97_EXT_AUDIO_CDAC; - if (as->ext_id & AC97_EXT_AUDIO_SDAC) - extstat |= AC97_EXT_AUDIO_SDAC; + if (as->ext_id & AC97_EXT_AUDIO_LDAC) extstat |= AC97_EXT_AUDIO_LDAC; + if (as->ext_id & AC97_EXT_AUDIO_SDAC) + extstat |= AC97_EXT_AUDIO_SDAC; + if (as->ext_id & AC97_EXT_AUDIO_CDAC) + extstat |= AC97_EXT_AUDIO_CDAC; + if (as->ext_id & AC97_EXT_AUDIO_SPDIF) { + /* XXX S/PDIF gets same data as DAC? + * maybe this should be settable? + * default is SPSAAB (10/11) on AD1980 and ALC codecs. + */ + extstat &= ~AC97_EXT_AUDIO_SPSA_MASK; + extstat |= AC97_EXT_AUDIO_SPSA34; + ac97_read(as, AC97_REG_SPDIF_CTRL, &val); + val = (val & ~AC97_SPDIF_SPSR_MASK) | + AC97_SPDIF_SPSR_48K; + ac97_write(as, AC97_REG_SPDIF_CTRL, val); + } + if (as->ext_id & AC97_EXT_AUDIO_VRA) + extstat |= AC97_EXT_AUDIO_VRA; ac97_write(as, AC97_REG_EXT_AUDIO_CTRL, extstat); if (as->ext_id & AC97_EXT_AUDIO_VRA) { /* VRA should be enabled. */ @@ -929,6 +959,20 @@ ac97_attach(struct ac97_host_if *host_if) return (0); } +void +ac97_lock(struct ac97_codec_if *codec_if) +{ + struct ac97_softc *as = (struct ac97_softc *)codec_if; + as->lock_counter++; +} + +void +ac97_unlock(struct ac97_codec_if *codec_if) +{ + struct ac97_softc *as = (struct ac97_softc *)codec_if; + as->lock_counter--; +} + int ac97_query_devinfo(struct ac97_codec_if *codec_if, mixer_devinfo_t *dip) { @@ -974,12 +1018,17 @@ ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) struct ac97_source_info *si = &as->source_info[cp->dev]; u_int16_t mask; u_int16_t val, newval; - int error; + int error, spdif; if (cp->dev < 0 || cp->dev >= as->num_source_info || - cp->type != si->type) + cp->type == AUDIO_MIXER_CLASS || cp->type != si->type) return (EINVAL); + spdif = si->req_feature == CHECK_SPDIF && + si->reg == AC97_REG_EXT_AUDIO_CTRL; + if (spdif && as->lock_counter >= 0) + return EBUSY; + ac97_read(as, si->reg, &val); DPRINTFN(5, ("read(%x) = %x\n", si->reg, val)); @@ -1053,6 +1102,9 @@ ac97_mixer_set_port(struct ac97_codec_if *codec_if, mixer_ctrl_t *cp) if (error) return (error); + if (spdif && as->host_if->spdif_event != NULL) + as->host_if->spdif_event(as->host_if->arg, cp->un.ord); + return (0); } diff --git a/sys/dev/ic/ac97.h b/sys/dev/ic/ac97.h index 3439aa64058..453cc626fe4 100644 --- a/sys/dev/ic/ac97.h +++ b/sys/dev/ic/ac97.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ac97.h,v 1.22 2008/05/25 23:52:30 jakemsr Exp $ */ +/* $OpenBSD: ac97.h,v 1.23 2008/10/23 21:50:01 jakemsr Exp $ */ /* * Copyright (c) 1999 Constantine Sapuntzakis @@ -48,6 +48,7 @@ struct ac97_host_if { void (*reset)(void *arg); enum ac97_host_flags (*flags)(void *arg); + void (*spdif_event)(void *arg, int); }; /* @@ -73,6 +74,8 @@ struct ac97_codec_if_vtbl { u_long *rate); void (*set_clock)(struct ac97_codec_if *codec_if, unsigned int clock); + void (*lock)(struct ac97_codec_if *codec_if); + void (*unlock)(struct ac97_codec_if *codec_if); }; struct ac97_codec_if { @@ -134,12 +137,21 @@ void ac97_get_default_params(struct audio_params *); #define AC97_EXT_AUDIO_DRA 0x0002 #define AC97_EXT_AUDIO_SPDIF 0x0004 #define AC97_EXT_AUDIO_VRM 0x0008 -#define AC97_EXT_AUDIO_DSA0 0x0010 -#define AC97_EXT_AUDIO_DSA1 0x0020 +#define AC97_EXT_AUDIO_DSA_MASK 0x0030 +#define AC97_EXT_AUDIO_DSA00 0x0000 +#define AC97_EXT_AUDIO_DSA01 0x0010 +#define AC97_EXT_AUDIO_DSA10 0x0020 +#define AC97_EXT_AUDIO_DSA11 0x0030 +#define AC97_EXT_AUDIO_SPSA_MASK 0x0030 +#define AC97_EXT_AUDIO_SPSA34 0x0000 +#define AC97_EXT_AUDIO_SPSA78 0x0010 +#define AC97_EXT_AUDIO_SPSA69 0x0020 +#define AC97_EXT_AUDIO_SPSAAB 0x0030 #define AC97_EXT_AUDIO_CDAC 0x0040 #define AC97_EXT_AUDIO_SDAC 0x0080 #define AC97_EXT_AUDIO_LDAC 0x0100 #define AC97_EXT_AUDIO_AMAP 0x0200 +#define AC97_EXT_AUDIO_SPCV 0x0400 #define AC97_EXT_AUDIO_REV_11 0x0000 #define AC97_EXT_AUDIO_REV_22 0x0400 #define AC97_EXT_AUDIO_REV_23 0x0800 @@ -156,6 +168,18 @@ void ac97_get_default_params(struct audio_params *); #define AC97_REG_SURR_MASTER 0x38 #define AC97_REG_SPDIF_CTRL 0x3a #define AC97_REG_SPDIF_CTRL_BITS "\02\01pro\02/audio\03copy\04pre\014l\017drs\020valid" +#define AC97_SPDIF_V 0x8000 +#define AC97_SPDIF_DRS 0x4000 +#define AC97_SPDIF_SPSR_MASK 0x3000 +#define AC97_SPDIF_SPSR_44K 0x0000 +#define AC97_SPDIF_SPSR_48K 0x2000 +#define AC97_SPDIF_SPSR_32K 0x1000 +#define AC97_SPDIF_L 0x0800 +#define AC97_SPDIF_CC_MASK 0x07f0 +#define AC97_SPDIF_PRE 0x0008 +#define AC97_SPDIF_COPY 0x0004 +#define AC97_SPDIF_NOAUDIO 0x0002 +#define AC97_SPDIF_PRO 0x0001 #define AC97_REG_VENDOR_ID1 0x7c #define AC97_REG_VENDOR_ID2 0x7e 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; |