summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2008-10-23 21:50:02 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2008-10-23 21:50:02 +0000
commit6f459ae12d184272e7ef7b3f547537bbf501f31a (patch)
tree33f295d20f143e6eaf9ae5cb909524d945af7e16 /sys/dev
parent403c943deb4dc1db75d2ecc26efa828ba93697cf (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.c76
-rw-r--r--sys/dev/ic/ac97.h30
-rw-r--r--sys/dev/pci/auich.c142
-rw-r--r--sys/dev/pci/auvia.c139
-rw-r--r--sys/dev/pci/auviavar.h3
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;