- Correctly handle bit 24 of miscellaneous control register, which has
different meanings for read and write. This fixes 48kHz playback to SPDIF. - Fix the problem where the SPDIF output voltage setting (0.5V, 5V) was swapped. The default value is changed from 0.5V to 5V, which correctly selects 5V (so the default physical behavior is unchanged). Should fix PRs kern/16047 and kern/16817 (but not tested since I don't have other SPDIF hardware to test with). Approved by tshiozak.
This commit is contained in:
parent
20d207b125
commit
1b7b873248
@ -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 <sys/cdefs.h>
|
||||
__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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user