diff --git a/sys/dev/pci/cmpci.c b/sys/dev/pci/cmpci.c index 8ad4acd8258c..b73f74fb171b 100644 --- a/sys/dev/pci/cmpci.c +++ b/sys/dev/pci/cmpci.c @@ -1,4 +1,4 @@ -/* $NetBSD: cmpci.c,v 1.20 2003/10/25 21:31:43 christos Exp $ */ +/* $NetBSD: cmpci.c,v 1.21 2003/11/22 16:48:14 itohy Exp $ */ /* * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -43,7 +43,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cmpci.c,v 1.20 2003/10/25 21:31:43 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cmpci.c,v 1.21 2003/11/22 16:48:14 itohy Exp $"); #if defined(AUDIO_DEBUG) || defined(DEBUG) #define DPRINTF(x) if (cmpcidebug) printf x @@ -98,6 +98,10 @@ static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *, int, uint32_t)); static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *, int, uint32_t)); +static __inline void cmpci_reg_set_reg_misc __P((struct cmpci_softc *, + uint32_t)); +static __inline void cmpci_reg_clear_reg_misc __P((struct cmpci_softc *, + uint32_t)); static int cmpci_rate_to_index __P((int)); static __inline int cmpci_index_to_rate __P((int)); static __inline int cmpci_index_to_divider __P((int)); @@ -278,6 +282,9 @@ cmpci_reg_set_4(sc, no, mask) int no; uint32_t mask; { + /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */ + KDASSERT(no != CMPCI_REG_MISC); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask)); delay(10); @@ -289,12 +296,42 @@ cmpci_reg_clear_4(sc, no, mask) int no; uint32_t mask; { + /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */ + KDASSERT(no != CMPCI_REG_MISC); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask)); delay(10); } +/* + * The CMPCI_REG_MISC register needs special handling, since one of + * its bits has different read/write values. + */ +static __inline void +cmpci_reg_set_reg_misc(sc, mask) + struct cmpci_softc *sc; + uint32_t mask; +{ + sc->sc_reg_misc |= mask; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC, + sc->sc_reg_misc); + delay(10); +} + +static __inline void +cmpci_reg_clear_reg_misc(sc, mask) + struct cmpci_softc *sc; + uint32_t mask; +{ + sc->sc_reg_misc &= ~mask; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC, + sc->sc_reg_misc); + delay(10); +} + + /* rate */ static const struct { int rate; @@ -439,6 +476,10 @@ cmpci_attach(parent, self, aux) CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0) sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint); + /* get initial value (this is 0 and may be omitted but just in case) */ + sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K; + cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0); cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0); cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0); @@ -1050,10 +1091,10 @@ cmpci_query_devinfo(handle, dip) strcpy(dip->label.name, CmpciNvoltage); dip->type = AUDIO_MIXER_ENUM; dip->un.e.num_mem = 2; - strcpy(dip->un.e.member[0].label.name, CmpciNlow_v); - dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW; - strcpy(dip->un.e.member[1].label.name, CmpciNhigh_v); - dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH; + strcpy(dip->un.e.member[0].label.name, CmpciNhigh_v); + dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH; + strcpy(dip->un.e.member[1].label.name, CmpciNlow_v); + dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW; return 0; case CMPCI_MONITOR_DAC: dip->mixer_class = CMPCI_SPDIF_CLASS; @@ -1350,12 +1391,10 @@ cmpci_set_mixer_gain(sc, port) case CMPCI_SPDIF_OUT_VOLTAGE: if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) { if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR] - == CMPCI_SPDIF_OUT_VOLTAGE_LOW) - cmpci_reg_clear_4(sc, CMPCI_REG_MISC, - CMPCI_REG_5V); + == CMPCI_SPDIF_OUT_VOLTAGE_HIGH) + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V); else - cmpci_reg_set_4(sc, CMPCI_REG_MISC, - CMPCI_REG_5V); + cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V); } return; case CMPCI_SURROUND: @@ -1371,11 +1410,9 @@ cmpci_set_mixer_gain(sc, port) case CMPCI_REAR: if (CMPCI_ISCAP(sc, REAR)) { if (sc->sc_gain[CMPCI_REAR][CMPCI_LR]) - cmpci_reg_set_4(sc, CMPCI_REG_MISC, - CMPCI_REG_N4SPK3D); + cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D); else - cmpci_reg_clear_4(sc, CMPCI_REG_MISC, - CMPCI_REG_N4SPK3D); + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D); } return; case CMPCI_INDIVIDUAL: @@ -1441,13 +1478,13 @@ cmpci_set_out_ports(sc) /* SPDIF in select */ v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR]; if (v & CMPCI_SPDIFIN_SPDIFIN2) - cmpci_reg_set_4(sc, CMPCI_REG_MISC, CMPCI_REG_2ND_SPDIFIN); + cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN); else - cmpci_reg_clear_4(sc, CMPCI_REG_MISC, CMPCI_REG_2ND_SPDIFIN); + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN); if (v & CMPCI_SPDIFIN_SPDIFOUT) - cmpci_reg_set_4(sc, CMPCI_REG_MISC, CMPCI_REG_SPDFLOOPI); + cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI); else - cmpci_reg_clear_4(sc, CMPCI_REG_MISC, CMPCI_REG_SPDFLOOPI); + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI); /* playback to ... */ if (CMPCI_ISCAP(sc, SPDOUT) && @@ -1460,18 +1497,18 @@ cmpci_set_out_ports(sc) cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF0_ENABLE); enspdout = 1; if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000) - cmpci_reg_set_4(sc, CMPCI_REG_MISC, - CMPCI_REG_SPDIF_48K); + cmpci_reg_set_reg_misc(sc, + CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); else - cmpci_reg_clear_4(sc, CMPCI_REG_MISC, - CMPCI_REG_SPDIF_48K); + cmpci_reg_clear_reg_misc(sc, + CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); } else { /* playback to DAC */ cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF0_ENABLE); if (CMPCI_ISCAP(sc, SPDOUT_48K)) - cmpci_reg_clear_4(sc, CMPCI_REG_MISC, - CMPCI_REG_SPDIF_48K); + cmpci_reg_clear_reg_misc(sc, + CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); } /* legacy to SPDIF/out or not */ diff --git a/sys/dev/pci/cmpcireg.h b/sys/dev/pci/cmpcireg.h index 7fe54030d220..611a2126f076 100644 --- a/sys/dev/pci/cmpcireg.h +++ b/sys/dev/pci/cmpcireg.h @@ -1,4 +1,4 @@ -/* $NetBSD: cmpcireg.h,v 1.4 2001/11/04 06:57:40 itohy Exp $ */ +/* $NetBSD: cmpcireg.h,v 1.5 2003/11/22 16:48:14 itohy Exp $ */ /* * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -119,9 +119,10 @@ #define CMPCI_REG_MISC 0x18 # define CMPCI_REG_2ND_SPDIFIN 0x00000100 -# define CMPCI_REG_SPDIF_48K 0x00008000 +# define CMPCI_REG_SPDIFOUT_48K 0x00008000 # define CMPCI_REG_FM_ENABLE 0x00080000 # define CMPCI_REG_SPDFLOOPI 0x00100000 +# define CMPCI_REG_SPDIF48K 0x01000000 # define CMPCI_REG_5V 0x02000000 # define CMPCI_REG_N4SPK3D 0x04000000 diff --git a/sys/dev/pci/cmpcivar.h b/sys/dev/pci/cmpcivar.h index 0496a8c7a1d2..7909c864bbb7 100644 --- a/sys/dev/pci/cmpcivar.h +++ b/sys/dev/pci/cmpcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: cmpcivar.h,v 1.4 2001/11/04 06:57:40 itohy Exp $ */ +/* $NetBSD: cmpcivar.h,v 1.5 2003/11/22 16:48:14 itohy Exp $ */ /* * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -121,8 +121,8 @@ typedef struct cmpci_dmanode *cmpci_dmapool_t; #define CmpciNrear "rear" #define CmpciNindividual "individual" #define CmpciNreverse "reverse" -#define CmpciNlow_v "0.5V" #define CmpciNhigh_v "5V" +#define CmpciNlow_v "0.5V" #define CmpciNsurround "surround" /* record.sorce bitmap (see cmpci_set_in_ports()) */ @@ -158,8 +158,8 @@ typedef struct cmpci_dmanode *cmpci_dmapool_t; #define CMPCI_SPDIF_OUT_PLAYBACK_LEGACY 1 /* legacy */ /* spdif.output.voltage */ -#define CMPCI_SPDIF_OUT_VOLTAGE_LOW 0 /* 0.5V */ -#define CMPCI_SPDIF_OUT_VOLTAGE_HIGH 1 /* 5V */ +#define CMPCI_SPDIF_OUT_VOLTAGE_HIGH 0 /* 5V */ +#define CMPCI_SPDIF_OUT_VOLTAGE_LOW 1 /* 0.5V */ /* spdif.monitor */ #define CMPCI_MONDAC_ENABLE 0x01 @@ -230,6 +230,9 @@ struct cmpci_softc { int md_divide; } sc_play, sc_rec; + /* value of CMPCI_REG_MISC register */ + uint32_t sc_reg_misc; + /* mixer */ uint8_t sc_gain[CMPCI_NDEVS][2]; #define CMPCI_LEFT 0