some improvement for cmpci; SPDIF supports, etc.
This commit is contained in:
parent
85fcf16be0
commit
faec1fc4fc
|
@ -1,11 +1,11 @@
|
|||
/* $NetBSD: cmpci.c,v 1.6 2001/01/18 20:28:15 jdolecek Exp $ */
|
||||
/* $NetBSD: cmpci.c,v 1.7 2001/02/12 18:47:12 tshiozak Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Takuya SHIOZAKI <AoiMoe@imou.to> .
|
||||
* by Takuya SHIOZAKI <tshiozak@netbsd.org> .
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -34,18 +34,13 @@
|
|||
* C-Media CMI8x38 Audio Chip Support.
|
||||
*
|
||||
* TODO:
|
||||
* - Legacy MPU, OPL and Joystick support (but, I have no interest...)
|
||||
* - SPDIF support.
|
||||
*
|
||||
* ACKNOWLEDGEMENT:
|
||||
* - Lennart Augustsson : He touched up this code.
|
||||
* - Legacy MPU, OPL and Joystick support.
|
||||
*
|
||||
*/
|
||||
|
||||
#undef CMPCI_SPDIF_SUPPORT /* XXX: not working */
|
||||
|
||||
#if defined(AUDIO_DEBUG) || defined(DEBUG)
|
||||
#define DPRINTF(x) printf x
|
||||
#define DPRINTF(x) if (cmpcidebug) printf x
|
||||
int cmpcidebug = 0;
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
@ -77,22 +72,27 @@
|
|||
* Low-level HW interface
|
||||
*/
|
||||
static __inline uint8_t cmpci_mixerreg_read __P((struct cmpci_softc *,
|
||||
uint8_t));
|
||||
uint8_t));
|
||||
static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *,
|
||||
uint8_t, uint8_t));
|
||||
uint8_t, uint8_t));
|
||||
static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *,
|
||||
int, int,
|
||||
uint32_t, uint32_t));
|
||||
int, int,
|
||||
uint32_t, uint32_t));
|
||||
static __inline void cmpci_reg_set_1 __P((struct cmpci_softc *,
|
||||
int, uint8_t));
|
||||
static __inline void cmpci_reg_clear_1 __P((struct cmpci_softc *,
|
||||
int, uint8_t));
|
||||
static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *,
|
||||
int, uint32_t));
|
||||
int, uint32_t));
|
||||
static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *,
|
||||
int, uint32_t));
|
||||
int, 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));
|
||||
|
||||
static int cmpci_adjust __P((int, int));
|
||||
static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int));
|
||||
static void cmpci_set_out_ports __P((struct cmpci_softc *));
|
||||
static int cmpci_set_in_ports __P((struct cmpci_softc *, int));
|
||||
|
||||
|
||||
|
@ -114,10 +114,10 @@ static int cmpci_intr __P((void *));
|
|||
* DMA stuffs
|
||||
*/
|
||||
static int cmpci_alloc_dmamem __P((struct cmpci_softc *,
|
||||
size_t, int, int, caddr_t *));
|
||||
size_t, int, int, caddr_t *));
|
||||
static int cmpci_free_dmamem __P((struct cmpci_softc *, caddr_t, int));
|
||||
static struct cmpci_dmanode * cmpci_find_dmamem __P((struct cmpci_softc *,
|
||||
caddr_t));
|
||||
caddr_t));
|
||||
|
||||
|
||||
/*
|
||||
|
@ -127,8 +127,8 @@ static int cmpci_open __P((void *, int));
|
|||
static void cmpci_close __P((void *));
|
||||
static int cmpci_query_encoding __P((void *, struct audio_encoding *));
|
||||
static int cmpci_set_params __P((void *, int, int,
|
||||
struct audio_params *,
|
||||
struct audio_params *));
|
||||
struct audio_params *,
|
||||
struct audio_params *));
|
||||
static int cmpci_round_blocksize __P((void *, int));
|
||||
static int cmpci_halt_output __P((void *));
|
||||
static int cmpci_halt_input __P((void *));
|
||||
|
@ -142,11 +142,11 @@ static size_t cmpci_round_buffersize __P((void *, int, size_t));
|
|||
static paddr_t cmpci_mappage __P((void *, void *, off_t, int));
|
||||
static int cmpci_get_props __P((void *));
|
||||
static int cmpci_trigger_output __P((void *, void *, void *, int,
|
||||
void (*)(void *), void *,
|
||||
struct audio_params *));
|
||||
void (*)(void *), void *,
|
||||
struct audio_params *));
|
||||
static int cmpci_trigger_input __P((void *, void *, void *, int,
|
||||
void (*)(void *), void *,
|
||||
struct audio_params *));
|
||||
void (*)(void *), void *,
|
||||
struct audio_params *));
|
||||
|
||||
static struct audio_hw_if cmpci_hw_if = {
|
||||
cmpci_open, /* open */
|
||||
|
@ -223,6 +223,29 @@ cmpci_reg_partial_write_4(sc, no, shift, mask, val)
|
|||
}
|
||||
|
||||
/* register set/clear bit */
|
||||
static __inline void
|
||||
cmpci_reg_set_1(sc, no, mask)
|
||||
struct cmpci_softc *sc;
|
||||
int no;
|
||||
uint8_t mask;
|
||||
{
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
|
||||
(bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
|
||||
delay(10);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cmpci_reg_clear_1(sc, no, mask)
|
||||
struct cmpci_softc *sc;
|
||||
int no;
|
||||
uint8_t mask;
|
||||
{
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
|
||||
(bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
|
||||
delay(10);
|
||||
}
|
||||
|
||||
|
||||
static __inline void
|
||||
cmpci_reg_set_4(sc, no, mask)
|
||||
struct cmpci_softc *sc;
|
||||
|
@ -230,7 +253,7 @@ cmpci_reg_set_4(sc, no, mask)
|
|||
uint32_t mask;
|
||||
{
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
|
||||
(bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
|
||||
(bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
|
||||
delay(10);
|
||||
}
|
||||
|
||||
|
@ -241,7 +264,7 @@ cmpci_reg_clear_4(sc, no, mask)
|
|||
uint32_t mask;
|
||||
{
|
||||
bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
|
||||
(bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
|
||||
(bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
|
||||
delay(10);
|
||||
}
|
||||
|
||||
|
@ -260,7 +283,7 @@ static const struct {
|
|||
_RATE(32000),
|
||||
_RATE(44100),
|
||||
_RATE(48000)
|
||||
#undef _RATE
|
||||
#undef _RATE
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -306,7 +329,8 @@ cmpci_match(parent, match, aux)
|
|||
if ( PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMEDIA &&
|
||||
(PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338A ||
|
||||
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338B ||
|
||||
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738) )
|
||||
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738 ||
|
||||
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738B) )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -321,25 +345,29 @@ cmpci_attach(parent, self, aux)
|
|||
struct pci_attach_args *pa = (struct pci_attach_args *)aux;
|
||||
pci_intr_handle_t ih;
|
||||
char const *strintr;
|
||||
char devinfo[256];
|
||||
int i, v;
|
||||
|
||||
sc->sc_revision = PCI_REVISION(pa->pa_class);
|
||||
sc->sc_model = PCI_PRODUCT(pa->pa_id);
|
||||
switch (sc->sc_model) {
|
||||
sc->sc_id = pa->pa_id;
|
||||
sc->sc_class = pa->pa_class;
|
||||
pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
|
||||
printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(sc->sc_class));
|
||||
switch (PCI_PRODUCT(sc->sc_id)) {
|
||||
case PCI_PRODUCT_CMEDIA_CMI8338A:
|
||||
printf(": CMI8338A PCI Audio Device\n");
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
case PCI_PRODUCT_CMEDIA_CMI8338B:
|
||||
printf(": CMI8338B PCI Audio Device\n");
|
||||
sc->sc_capable = CMPCI_CAP_CMI8338;
|
||||
break;
|
||||
case PCI_PRODUCT_CMEDIA_CMI8738:
|
||||
printf(": CMI8738 PCI Audio Device\n");
|
||||
/*FALLTHROUGH*/
|
||||
case PCI_PRODUCT_CMEDIA_CMI8738B:
|
||||
sc->sc_capable = CMPCI_CAP_CMI8738;
|
||||
break;
|
||||
}
|
||||
|
||||
/* map I/O space */
|
||||
if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
|
||||
&sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
|
||||
&sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
|
||||
printf("%s: failed to map I/O space\n", sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
|
@ -388,17 +416,25 @@ cmpci_attach(parent, self, aux)
|
|||
case CMPCI_MIC_SWAP:
|
||||
case CMPCI_LINE_SWAP:
|
||||
case CMPCI_FM_SWAP:
|
||||
case CMPCI_SPDIF_LOOP:
|
||||
case CMPCI_SPDIF_OUT_VOLTAGE:
|
||||
case CMPCI_SPDIF_IN_PHASE:
|
||||
case CMPCI_REAR:
|
||||
case CMPCI_INDIVIDUAL:
|
||||
case CMPCI_REVERSE:
|
||||
case CMPCI_SURROUND:
|
||||
v = 0;
|
||||
break;
|
||||
case CMPCI_CD_OUT_MUTE:
|
||||
case CMPCI_MIC_OUT_MUTE:
|
||||
case CMPCI_LINE_OUT_MUTE:
|
||||
case CMPCI_SPDIF_IN_MUTE:
|
||||
v = 1;
|
||||
break;
|
||||
default:
|
||||
v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
|
||||
}
|
||||
sc->gain[i][CMPCI_LEFT] = sc->gain[i][CMPCI_RIGHT] = v;
|
||||
sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
|
||||
cmpci_set_mixer_gain(sc, i);
|
||||
}
|
||||
}
|
||||
|
@ -453,10 +489,6 @@ cmpci_open(handle, flags)
|
|||
void *handle;
|
||||
int flags;
|
||||
{
|
||||
#if 0
|
||||
struct cmpci_softc *sc = handle;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -471,10 +503,6 @@ cmpci_query_encoding(handle, fp)
|
|||
void *handle;
|
||||
struct audio_encoding *fp;
|
||||
{
|
||||
#if 0
|
||||
struct cmpci_softc *sc = handle;
|
||||
#endif
|
||||
|
||||
switch (fp->index) {
|
||||
case 0:
|
||||
strcpy(fp->name, AudioEulinear);
|
||||
|
@ -647,9 +675,11 @@ cmpci_set_params(handle, setmode, usemode, play, rec)
|
|||
case 16:
|
||||
md_format |= CMPCI_REG_FORMAT_16BIT;
|
||||
if (mode & AUMODE_PLAY)
|
||||
p->sw_code =swap_bytes_change_sign16_le;
|
||||
p->sw_code =
|
||||
swap_bytes_change_sign16_le;
|
||||
else
|
||||
p->sw_code =change_sign16_swap_bytes_le;
|
||||
p->sw_code =
|
||||
change_sign16_swap_bytes_le;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
|
@ -660,68 +690,32 @@ cmpci_set_params(handle, setmode, usemode, play, rec)
|
|||
}
|
||||
if (mode & AUMODE_PLAY)
|
||||
cmpci_reg_partial_write_4(sc,
|
||||
CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH0_FORMAT_SHIFT,
|
||||
CMPCI_REG_CH0_FORMAT_MASK, md_format);
|
||||
CMPCI_REG_CHANNEL_FORMAT,
|
||||
CMPCI_REG_CH0_FORMAT_SHIFT,
|
||||
CMPCI_REG_CH0_FORMAT_MASK, md_format);
|
||||
else
|
||||
cmpci_reg_partial_write_4(sc,
|
||||
CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH1_FORMAT_SHIFT,
|
||||
CMPCI_REG_CHANNEL_FORMAT,
|
||||
CMPCI_REG_CH1_FORMAT_SHIFT,
|
||||
CMPCI_REG_CH1_FORMAT_MASK, md_format);
|
||||
/* sample rate */
|
||||
md_index = cmpci_rate_to_index(p->sample_rate);
|
||||
md_divide = cmpci_index_to_divider(md_index);
|
||||
p->sample_rate = cmpci_index_to_rate(md_index);
|
||||
#if 0
|
||||
DPRINTF(("%s: sample:%d, divider=%d\n",
|
||||
sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
|
||||
#endif
|
||||
if (mode & AUMODE_PLAY) {
|
||||
cmpci_reg_partial_write_4(sc,
|
||||
CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
|
||||
CMPCI_REG_DAC_FS_MASK, md_divide);
|
||||
#ifdef CMPCI_SPDIF_SUPPORT
|
||||
switch (md_divide) {
|
||||
case CMPCI_REG_RATE_44100:
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
|
||||
CMPCI_REG_SPDIF_48K);
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF_LOOP);
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF0_ENABLE);
|
||||
break;
|
||||
case CMPCI_REG_RATE_48000:
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_MISC,
|
||||
CMPCI_REG_SPDIF_48K);
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF_LOOP);
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF0_ENABLE);
|
||||
break;
|
||||
default:
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF0_ENABLE);
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF_LOOP);
|
||||
}
|
||||
#endif
|
||||
sc->sc_play.md_divide = md_divide;
|
||||
} else {
|
||||
cmpci_reg_partial_write_4(sc,
|
||||
CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
|
||||
CMPCI_REG_ADC_FS_MASK, md_divide);
|
||||
#ifdef CMPCI_SPDIF_SUPPORT
|
||||
if (sc->in_mask & CMPCI_SPDIF_IN) {
|
||||
switch (md_divide) {
|
||||
case CMPCI_REG_RATE_44100:
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF1_ENABLE);
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
} else
|
||||
cmpci_reg_clear_4(sc,
|
||||
CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF1_ENABLE);
|
||||
#endif
|
||||
sc->sc_rec.md_divide = md_divide;
|
||||
}
|
||||
cmpci_set_mixer_gain(sc, CMPCI_SPDIF_LOOP);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -779,14 +773,15 @@ cmpci_halt_input(handle)
|
|||
/* get audio device information */
|
||||
static int
|
||||
cmpci_getdev(handle, ad)
|
||||
void *handle;
|
||||
struct audio_device *ad;
|
||||
void *handle;
|
||||
struct audio_device *ad;
|
||||
{
|
||||
struct cmpci_softc *sc = handle;
|
||||
|
||||
strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name));
|
||||
snprintf(ad->version, sizeof(ad->version), "0x%02x", sc->sc_revision);
|
||||
switch (sc->sc_model) {
|
||||
snprintf(ad->version, sizeof(ad->version), "0x%02x",
|
||||
PCI_REVISION(sc->sc_class));
|
||||
switch (PCI_PRODUCT(sc->sc_id)) {
|
||||
case PCI_PRODUCT_CMEDIA_CMI8338A:
|
||||
strncpy(ad->config, "CMI8338A", sizeof(ad->config));
|
||||
break;
|
||||
|
@ -796,6 +791,9 @@ cmpci_getdev(handle, ad)
|
|||
case PCI_PRODUCT_CMEDIA_CMI8738:
|
||||
strncpy(ad->config, "CMI8738", sizeof(ad->config));
|
||||
break;
|
||||
case PCI_PRODUCT_CMEDIA_CMI8738B:
|
||||
strncpy(ad->config, "CMI8738B", sizeof(ad->config));
|
||||
break;
|
||||
default:
|
||||
strncpy(ad->config, "unknown", sizeof(ad->config));
|
||||
}
|
||||
|
@ -810,10 +808,6 @@ cmpci_query_devinfo(handle, dip)
|
|||
void *handle;
|
||||
mixer_devinfo_t *dip;
|
||||
{
|
||||
#if 0
|
||||
struct cmpci_softc *sc = handle;
|
||||
#endif
|
||||
|
||||
switch (dip->index) {
|
||||
case CMPCI_MASTER_VOL:
|
||||
dip->type = AUDIO_MIXER_VALUE;
|
||||
|
@ -879,11 +873,7 @@ cmpci_query_devinfo(handle, dip)
|
|||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, AudioNsource);
|
||||
dip->type = AUDIO_MIXER_SET;
|
||||
#ifdef CMPCI_SPDIF_SUPPORT
|
||||
dip->un.s.num_mem = 5;
|
||||
#else
|
||||
dip->un.s.num_mem = 4;
|
||||
#endif
|
||||
strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
|
||||
dip->un.s.member[0].mask = 1 << CMPCI_MIC_VOL;
|
||||
strcpy(dip->un.s.member[1].label.name, AudioNcd);
|
||||
|
@ -892,10 +882,8 @@ cmpci_query_devinfo(handle, dip)
|
|||
dip->un.s.member[2].mask = 1 << CMPCI_LINE_IN_VOL;
|
||||
strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
|
||||
dip->un.s.member[3].mask = 1 << CMPCI_FM_VOL;
|
||||
#ifdef CMPCI_SPDIF_SUPPORT
|
||||
strcpy(dip->un.s.member[4].label.name, CmpciNspdif);
|
||||
dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_IN;
|
||||
#endif
|
||||
dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_CLASS;
|
||||
return 0;
|
||||
case CMPCI_BASS:
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
|
@ -954,19 +942,81 @@ cmpci_query_devinfo(handle, dip)
|
|||
dip->mixer_class = CMPCI_INPUT_CLASS;
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, "agc");
|
||||
dip->un.e.num_mem = 2;
|
||||
strcpy(dip->un.e.member[0].label.name, AudioNoff);
|
||||
dip->un.e.member[0].ord = 0;
|
||||
strcpy(dip->un.e.member[1].label.name, AudioNon);
|
||||
dip->un.e.member[1].ord = 1;
|
||||
return 0;
|
||||
goto on_off;
|
||||
case CMPCI_EQUALIZATION_CLASS:
|
||||
dip->type = AUDIO_MIXER_CLASS;
|
||||
dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
|
||||
dip->next = dip->prev = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, AudioCequalization);
|
||||
return 0;
|
||||
|
||||
case CMPCI_SPDIF_IN_MUTE:
|
||||
dip->type = AUDIO_MIXER_CLASS;
|
||||
dip->mixer_class = CMPCI_INPUT_CLASS;
|
||||
dip->next = dip->prev = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNspdif);
|
||||
return 0;
|
||||
case CMPCI_SPDIF_CLASS:
|
||||
dip->type = AUDIO_MIXER_CLASS;
|
||||
dip->mixer_class = CMPCI_SPDIF_CLASS;
|
||||
dip->next = dip->prev = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciCspdif);
|
||||
return 0;
|
||||
case CMPCI_SPDIF_LOOP:
|
||||
dip->mixer_class = CMPCI_SPDIF_CLASS;
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNloop);
|
||||
goto on_off;
|
||||
case CMPCI_SPDIF_LEGACY:
|
||||
dip->mixer_class = CMPCI_SPDIF_CLASS;
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNlegacy);
|
||||
goto on_off;
|
||||
case CMPCI_SPDIF_OUT_VOLTAGE:
|
||||
dip->mixer_class = CMPCI_SPDIF_CLASS;
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNout_voltage);
|
||||
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 = 0;
|
||||
strcpy(dip->un.e.member[1].label.name, CmpciNhigh_v);
|
||||
dip->un.e.member[1].ord = 1;
|
||||
return 0;
|
||||
case CMPCI_SPDIF_IN_PHASE:
|
||||
dip->mixer_class = CMPCI_SPDIF_CLASS;
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNin_phase);
|
||||
goto on_off;
|
||||
case CMPCI_REAR:
|
||||
dip->mixer_class = CMPCI_OUTPUT_CLASS;
|
||||
dip->prev = AUDIO_MIXER_LAST;
|
||||
dip->next = CMPCI_INDIVIDUAL;
|
||||
strcpy(dip->label.name, CmpciNrear);
|
||||
goto on_off;
|
||||
case CMPCI_INDIVIDUAL:
|
||||
dip->mixer_class = CMPCI_OUTPUT_CLASS;
|
||||
dip->prev = CMPCI_REAR;
|
||||
dip->next = CMPCI_REVERSE;
|
||||
strcpy(dip->label.name, CmpciNindividual);
|
||||
goto on_off;
|
||||
case CMPCI_REVERSE:
|
||||
dip->mixer_class = CMPCI_OUTPUT_CLASS;
|
||||
dip->prev = CMPCI_INDIVIDUAL;
|
||||
dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNreverse);
|
||||
dip->type = AUDIO_MIXER_ENUM;
|
||||
dip->un.e.num_mem = 2;
|
||||
strcpy(dip->un.e.member[0].label.name, CmpciNpositive);
|
||||
dip->un.e.member[0].ord = 0;
|
||||
strcpy(dip->un.e.member[1].label.name, CmpciNnegative);
|
||||
dip->un.e.member[1].ord = 1;
|
||||
return 0;
|
||||
case CMPCI_SURROUND:
|
||||
dip->mixer_class = CMPCI_OUTPUT_CLASS;
|
||||
dip->prev = dip->next = AUDIO_MIXER_LAST;
|
||||
strcpy(dip->label.name, CmpciNsurround);
|
||||
goto on_off;
|
||||
|
||||
case CMPCI_CD_IN_MUTE:
|
||||
dip->prev = CMPCI_CD_VOL;
|
||||
dip->next = CMPCI_CD_SWAP;
|
||||
|
@ -1005,7 +1055,7 @@ cmpci_query_devinfo(handle, dip)
|
|||
swap:
|
||||
dip->mixer_class = CMPCI_INPUT_CLASS;
|
||||
strcpy(dip->label.name, AudioNswap);
|
||||
goto mute1;
|
||||
goto on_off;
|
||||
|
||||
case CMPCI_CD_OUT_MUTE:
|
||||
dip->prev = CMPCI_CD_SWAP;
|
||||
|
@ -1023,7 +1073,7 @@ cmpci_query_devinfo(handle, dip)
|
|||
dip->mixer_class = CMPCI_OUTPUT_CLASS;
|
||||
mute:
|
||||
strcpy(dip->label.name, AudioNmute);
|
||||
mute1:
|
||||
on_off:
|
||||
dip->type = AUDIO_MIXER_ENUM;
|
||||
dip->un.e.num_mem = 2;
|
||||
strcpy(dip->un.e.member[0].label.name, AudioNoff);
|
||||
|
@ -1060,7 +1110,7 @@ cmpci_alloc_dmamem(sc, size, type, flags, r_addr)
|
|||
n->cd_size = size;
|
||||
error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
|
||||
CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
|
||||
sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w);
|
||||
sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w);
|
||||
if (error)
|
||||
goto mfree;
|
||||
error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
|
||||
|
@ -1161,9 +1211,9 @@ cmpci_allocm(handle, direction, size, type, flags)
|
|||
|
||||
static void
|
||||
cmpci_freem(handle, addr, type)
|
||||
void *handle;
|
||||
void *addr;
|
||||
int type;
|
||||
void *handle;
|
||||
void *addr;
|
||||
int type;
|
||||
{
|
||||
struct cmpci_softc *sc = handle;
|
||||
|
||||
|
@ -1222,14 +1272,150 @@ cmpci_set_mixer_gain(sc, port)
|
|||
break;
|
||||
case CMPCI_PCSPEAKER:
|
||||
cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
|
||||
sc->gain[port][CMPCI_LEFT]);
|
||||
sc->sc_gain[port][CMPCI_LEFT]);
|
||||
return;
|
||||
case CMPCI_SPDIF_IN_MUTE:
|
||||
if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
|
||||
if (sc->sc_gain[CMPCI_SPDIF_IN_MUTE][CMPCI_LR])
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_SPDIN_MONITOR);
|
||||
else
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_SPDIN_MONITOR);
|
||||
}
|
||||
|
||||
case CMPCI_SPDIF_LOOP:
|
||||
/*FALLTHROUGH*/
|
||||
case CMPCI_SPDIF_LEGACY:
|
||||
cmpci_set_out_ports(sc);
|
||||
return;
|
||||
case CMPCI_SPDIF_OUT_VOLTAGE:
|
||||
if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
|
||||
if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR])
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_MISC,
|
||||
CMPCI_REG_5V);
|
||||
else
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
|
||||
CMPCI_REG_5V);
|
||||
}
|
||||
return;
|
||||
case CMPCI_SURROUND:
|
||||
if (CMPCI_ISCAP(sc, SURROUND)) {
|
||||
if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
|
||||
cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_SURROUND);
|
||||
else
|
||||
cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_SURROUND);
|
||||
}
|
||||
return;
|
||||
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);
|
||||
else
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
|
||||
CMPCI_REG_N4SPK3D);
|
||||
}
|
||||
return;
|
||||
case CMPCI_INDIVIDUAL:
|
||||
if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
|
||||
if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
|
||||
cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_INDIVIDUAL);
|
||||
else
|
||||
cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_INDIVIDUAL);
|
||||
}
|
||||
return;
|
||||
case CMPCI_REVERSE:
|
||||
if (CMPCI_ISCAP(sc, REVERSE_FR)) {
|
||||
if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
|
||||
cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_REVERSE_FR);
|
||||
else
|
||||
cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
|
||||
CMPCI_REG_REVERSE_FR);
|
||||
}
|
||||
return;
|
||||
case CMPCI_SPDIF_IN_PHASE:
|
||||
if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
|
||||
if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR])
|
||||
cmpci_reg_set_1(sc, CMPCI_REG_MIXER27,
|
||||
CMPCI_REG_PHASE);
|
||||
else
|
||||
cmpci_reg_clear_1(sc, CMPCI_REG_MIXER27,
|
||||
CMPCI_REG_PHASE);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
cmpci_mixerreg_write(sc, src, sc->gain[port][CMPCI_LEFT]);
|
||||
cmpci_mixerreg_write(sc, src, sc->sc_gain[port][CMPCI_LEFT]);
|
||||
cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
|
||||
sc->gain[port][CMPCI_RIGHT]);
|
||||
sc->sc_gain[port][CMPCI_RIGHT]);
|
||||
}
|
||||
|
||||
static void
|
||||
cmpci_set_out_ports(sc)
|
||||
struct cmpci_softc *sc;
|
||||
{
|
||||
if (!CMPCI_ISCAP(sc, SPDLOOP))
|
||||
return;
|
||||
if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR]) {
|
||||
/* loop on */
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF0_ENABLE |
|
||||
CMPCI_REG_SPDIF1_ENABLE);
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
|
||||
CMPCI_REG_LEGACY_SPDIF_ENABLE);
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF_LOOP);
|
||||
} else {
|
||||
/* loop off */
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF_LOOP);
|
||||
cmpci_set_in_ports(sc, sc->sc_in_mask);
|
||||
if (CMPCI_ISCAP(sc, SPDOUT) &&
|
||||
(sc->sc_play.md_divide==CMPCI_REG_RATE_44100 ||
|
||||
(CMPCI_ISCAP(sc, SPDOUT_48K) &&
|
||||
sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) {
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF0_ENABLE);
|
||||
if (CMPCI_ISCAP(sc, XSPDOUT))
|
||||
cmpci_reg_set_4(sc,
|
||||
CMPCI_REG_LEGACY_CTRL,
|
||||
CMPCI_REG_XSPDIF_ENABLE);
|
||||
if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000)
|
||||
cmpci_reg_set_4(sc,
|
||||
CMPCI_REG_MISC,
|
||||
CMPCI_REG_SPDIF_48K);
|
||||
else
|
||||
cmpci_reg_clear_4(sc,
|
||||
CMPCI_REG_MISC,
|
||||
CMPCI_REG_SPDIF_48K);
|
||||
} else {
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF0_ENABLE);
|
||||
if (CMPCI_ISCAP(sc, XSPDOUT))
|
||||
cmpci_reg_clear_4(sc,
|
||||
CMPCI_REG_LEGACY_CTRL,
|
||||
CMPCI_REG_XSPDIF_ENABLE);
|
||||
if (CMPCI_ISCAP(sc, SPDOUT_48K))
|
||||
cmpci_reg_clear_4(sc,
|
||||
CMPCI_REG_MISC,
|
||||
CMPCI_REG_SPDIF_48K);
|
||||
}
|
||||
if (CMPCI_ISCAP(sc, SPDLEGACY)) {
|
||||
if (sc->sc_gain[CMPCI_SPDIF_LEGACY][CMPCI_LR])
|
||||
cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
|
||||
CMPCI_REG_LEGACY_SPDIF_ENABLE);
|
||||
else
|
||||
cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
|
||||
CMPCI_REG_LEGACY_SPDIF_ENABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1240,16 +1426,13 @@ cmpci_set_in_ports(sc, mask)
|
|||
int bitsl, bitsr;
|
||||
|
||||
if (mask & ~((1<<CMPCI_FM_VOL) | (1<<CMPCI_LINE_IN_VOL) |
|
||||
(1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL)
|
||||
#ifdef CMPCI_SPDIF_SUPPORT
|
||||
| (1<<CMPCI_SPDIF_IN)
|
||||
#endif
|
||||
))
|
||||
(1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL) |
|
||||
(1<<CMPCI_SPDIF_CLASS)))
|
||||
return EINVAL;
|
||||
bitsr = 0;
|
||||
if (mask & (1<<CMPCI_FM_VOL)) bitsr |= CMPCI_SB16_MIXER_FM_SRC_R;
|
||||
if (mask & (1<<CMPCI_FM_VOL)) bitsr |= CMPCI_SB16_MIXER_FM_SRC_R;
|
||||
if (mask & (1<<CMPCI_LINE_IN_VOL)) bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R;
|
||||
if (mask & (1<<CMPCI_CD_VOL)) bitsr |= CMPCI_SB16_MIXER_CD_SRC_R;
|
||||
if (mask & (1<<CMPCI_CD_VOL)) bitsr |= CMPCI_SB16_MIXER_CD_SRC_R;
|
||||
bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
|
||||
if (mask & (1<<CMPCI_MIC_VOL)) {
|
||||
bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
|
||||
|
@ -1257,8 +1440,22 @@ cmpci_set_in_ports(sc, mask)
|
|||
}
|
||||
cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
|
||||
cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
|
||||
if (CMPCI_ISCAP(sc, SPDIN) &&
|
||||
sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 &&
|
||||
!sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR]) {
|
||||
if (mask & (1<<CMPCI_SPDIF_CLASS)) {
|
||||
/* enable SPDIF/in */
|
||||
cmpci_reg_set_4(sc,
|
||||
CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF1_ENABLE);
|
||||
} else {
|
||||
cmpci_reg_clear_4(sc,
|
||||
CMPCI_REG_FUNC_1,
|
||||
CMPCI_REG_SPDIF1_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
sc->in_mask = mask;
|
||||
sc->sc_in_mask = mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1294,8 +1491,8 @@ cmpci_set_port(handle, cp)
|
|||
return EINVAL;
|
||||
|
||||
lgain = rgain =
|
||||
CMPCI_ADJUST_MIC_GAIN(sc,
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
|
||||
CMPCI_ADJUST_MIC_GAIN(sc,
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
|
||||
break;
|
||||
case CMPCI_PCSPEAKER:
|
||||
if (cp->un.value.num_channels != 1)
|
||||
|
@ -1310,21 +1507,24 @@ cmpci_set_port(handle, cp)
|
|||
switch (cp->un.value.num_channels) {
|
||||
case 1:
|
||||
lgain = rgain = CMPCI_ADJUST_GAIN(sc,
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]
|
||||
);
|
||||
break;
|
||||
case 2:
|
||||
lgain = CMPCI_ADJUST_GAIN(sc,
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]
|
||||
);
|
||||
rgain = CMPCI_ADJUST_GAIN(sc,
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sc->gain[cp->dev][CMPCI_LEFT] = lgain;
|
||||
sc->gain[cp->dev][CMPCI_RIGHT] = rgain;
|
||||
sc->sc_gain[cp->dev][CMPCI_LEFT] = lgain;
|
||||
sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
|
||||
|
||||
cmpci_set_mixer_gain(sc, cp->dev);
|
||||
break;
|
||||
|
@ -1354,7 +1554,7 @@ cmpci_set_port(handle, cp)
|
|||
if (cp->type != AUDIO_MIXER_ENUM)
|
||||
return EINVAL;
|
||||
bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
|
||||
sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
|
||||
sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
|
||||
if (cp->un.ord)
|
||||
bits = bits & ~mask;
|
||||
else
|
||||
|
@ -1388,7 +1588,7 @@ cmpci_set_port(handle, cp)
|
|||
& ~mask;
|
||||
rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R)
|
||||
& ~mask;
|
||||
sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
|
||||
sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
|
||||
if (CMPCI_IS_IN_MUTE(cp->dev)) {
|
||||
mute = cp->dev;
|
||||
swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP;
|
||||
|
@ -1396,18 +1596,27 @@ cmpci_set_port(handle, cp)
|
|||
swap = cp->dev;
|
||||
mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP;
|
||||
}
|
||||
if (sc->gain[swap][CMPCI_LR]) {
|
||||
if (sc->sc_gain[swap][CMPCI_LR]) {
|
||||
mask = lmask;
|
||||
lmask = rmask;
|
||||
rmask = mask;
|
||||
}
|
||||
if (!sc->gain[mute][CMPCI_LR]) {
|
||||
if (!sc->sc_gain[mute][CMPCI_LR]) {
|
||||
lbits = lbits | lmask;
|
||||
rbits = rbits | rmask;
|
||||
}
|
||||
cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits);
|
||||
cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits);
|
||||
break;
|
||||
case CMPCI_SPDIF_LOOP:
|
||||
case CMPCI_SPDIF_OUT_VOLTAGE:
|
||||
case CMPCI_SPDIF_IN_PHASE:
|
||||
case CMPCI_REAR:
|
||||
case CMPCI_INDIVIDUAL:
|
||||
case CMPCI_REVERSE:
|
||||
case CMPCI_SURROUND:
|
||||
sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
|
||||
break;
|
||||
|
||||
default:
|
||||
return EINVAL;
|
||||
|
@ -1441,13 +1650,13 @@ cmpci_get_port(handle, cp)
|
|||
switch (cp->un.value.num_channels) {
|
||||
case 1:
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
|
||||
sc->gain[cp->dev][CMPCI_LEFT];
|
||||
sc->sc_gain[cp->dev][CMPCI_LEFT];
|
||||
break;
|
||||
case 2:
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
|
||||
sc->gain[cp->dev][CMPCI_LEFT];
|
||||
sc->sc_gain[cp->dev][CMPCI_LEFT];
|
||||
cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
|
||||
sc->gain[cp->dev][CMPCI_RIGHT];
|
||||
sc->sc_gain[cp->dev][CMPCI_RIGHT];
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
|
@ -1455,7 +1664,7 @@ cmpci_get_port(handle, cp)
|
|||
break;
|
||||
|
||||
case CMPCI_RECORD_SOURCE:
|
||||
cp->un.mask = sc->in_mask;
|
||||
cp->un.mask = sc->sc_in_mask;
|
||||
break;
|
||||
|
||||
case CMPCI_AGC:
|
||||
|
@ -1473,7 +1682,16 @@ cmpci_get_port(handle, cp)
|
|||
case CMPCI_CD_OUT_MUTE:
|
||||
case CMPCI_MIC_OUT_MUTE:
|
||||
case CMPCI_LINE_OUT_MUTE:
|
||||
cp->un.ord = sc->gain[cp->dev][CMPCI_LR];
|
||||
case CMPCI_SPDIF_IN_MUTE:
|
||||
case CMPCI_SPDIF_LOOP:
|
||||
case CMPCI_SPDIF_LEGACY:
|
||||
case CMPCI_SPDIF_OUT_VOLTAGE:
|
||||
case CMPCI_SPDIF_IN_PHASE:
|
||||
case CMPCI_REAR:
|
||||
case CMPCI_INDIVIDUAL:
|
||||
case CMPCI_REVERSE:
|
||||
case CMPCI_SURROUND:
|
||||
cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1511,8 +1729,8 @@ cmpci_mappage(handle, addr, offset, prot)
|
|||
return -1;
|
||||
|
||||
return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
|
||||
sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
|
||||
offset, prot, BUS_DMA_WAITOK);
|
||||
sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
|
||||
offset, prot, BUS_DMA_WAITOK);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1527,12 +1745,12 @@ cmpci_get_props(handle)
|
|||
|
||||
static int
|
||||
cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
|
||||
void *handle;
|
||||
void *start, *end;
|
||||
int blksize;
|
||||
void (*intr) __P((void *));
|
||||
void *arg;
|
||||
struct audio_params *param;
|
||||
void *handle;
|
||||
void *start, *end;
|
||||
int blksize;
|
||||
void (*intr) __P((void *));
|
||||
void *arg;
|
||||
struct audio_params *param;
|
||||
{
|
||||
struct cmpci_softc *sc = handle;
|
||||
struct cmpci_dmanode *p;
|
||||
|
@ -1551,7 +1769,7 @@ cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
|
|||
DMAADDR(p));
|
||||
delay(10);
|
||||
bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
|
||||
((caddr_t)end - (caddr_t)start + 1) / bps - 1);
|
||||
((caddr_t)end - (caddr_t)start + 1) / bps - 1);
|
||||
delay(10);
|
||||
|
||||
/* set interrupt count */
|
||||
|
@ -1569,12 +1787,12 @@ cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
|
|||
|
||||
static int
|
||||
cmpci_trigger_input(handle, start, end, blksize, intr, arg, param)
|
||||
void *handle;
|
||||
void *start, *end;
|
||||
int blksize;
|
||||
void (*intr) __P((void *));
|
||||
void *arg;
|
||||
struct audio_params *param;
|
||||
void *handle;
|
||||
void *start, *end;
|
||||
int blksize;
|
||||
void (*intr) __P((void *));
|
||||
void *arg;
|
||||
struct audio_params *param;
|
||||
{
|
||||
struct cmpci_softc *sc = handle;
|
||||
struct cmpci_dmanode *p;
|
||||
|
@ -1593,12 +1811,12 @@ cmpci_trigger_input(handle, start, end, blksize, intr, arg, param)
|
|||
DMAADDR(p));
|
||||
delay(10);
|
||||
bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
|
||||
((caddr_t)end - (caddr_t)start + 1) / bps - 1);
|
||||
((caddr_t)end - (caddr_t)start + 1) / bps - 1);
|
||||
delay(10);
|
||||
|
||||
/* set interrupt count */
|
||||
bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
|
||||
(blksize + bps - 1) / bps - 1);
|
||||
(blksize + bps - 1) / bps - 1);
|
||||
delay(10);
|
||||
|
||||
/* start DMA */
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* $NetBSD: cmpcireg.h,v 1.1 2000/04/30 21:59:58 augustss Exp $ */
|
||||
/* $NetBSD: cmpcireg.h,v 1.2 2001/02/12 18:47:12 tshiozak Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Takuya SHIOZAKI <AoiMoe@imou.to> .
|
||||
* by Takuya SHIOZAKI <tshiozak@netbsd.org> .
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -116,6 +116,8 @@
|
|||
#define CMPCI_REG_MISC 0x18
|
||||
# define CMPCI_REG_SPDIF_48K 0x00008000
|
||||
# define CMPCI_REG_FM_ENABLE 0x00080000
|
||||
# define CMPCI_REG_5V 0x02000000
|
||||
# define CMPCI_REG_N4SPK3D 0x04000000
|
||||
|
||||
|
||||
#define CMPCI_REG_SBDATA 0x22
|
||||
|
@ -150,7 +152,7 @@
|
|||
# define CMPCI_SB16_MIXER_LINE_SRC_R 0x08
|
||||
# define CMPCI_SB16_MIXER_CD_SRC_R 0x02
|
||||
# define CMPCI_SB16_MIXER_MIC_SRC 0x01
|
||||
# define CMPCI_SB16_MIXER_SRC_R_TO_L(v) ((v) << 1)
|
||||
# define CMPCI_SB16_MIXER_SRC_R_TO_L(v) ((v) << 1)
|
||||
|
||||
# define CMPCI_SB16_MIXER_INGAIN_L 0x3F
|
||||
# define CMPCI_SB16_MIXER_INGAIN_R 0x40
|
||||
|
@ -163,9 +165,17 @@
|
|||
# define CMPCI_SB16_MIXER_BASS_R 0x47
|
||||
# define CMPCI_SB16_MIXER_L_TO_R(addr) ((addr)+1)
|
||||
|
||||
# define CMPCI_ADJUST_MIC_GAIN(sc, x) cmpci_adjust((x), 0xf8)
|
||||
# define CMPCI_ADJUST_GAIN(sc, x) cmpci_adjust((x), 0xf8)
|
||||
# define CMPCI_ADJUST_2_GAIN(sc, x) cmpci_adjust((x), 0xc0)
|
||||
# define CMPCI_ADJUST_MIC_GAIN(sc, x) cmpci_adjust((x), 0xf8)
|
||||
# define CMPCI_ADJUST_GAIN(sc, x) cmpci_adjust((x), 0xf8)
|
||||
# define CMPCI_ADJUST_2_GAIN(sc, x) cmpci_adjust((x), 0xc0)
|
||||
|
||||
#define CMPCI_REG_MIXER24 0x24
|
||||
# define CMPCI_REG_SPDIN_MONITOR 0x01
|
||||
# define CMPCI_REG_SURROUND 0x02
|
||||
# define CMPCI_REG_INDIVIDUAL 0x20
|
||||
# define CMPCI_REG_REVERSE_FR 0x10
|
||||
#define CMPCI_REG_MIXER27 0x27
|
||||
# define CMPCI_REG_PHASE 0x04
|
||||
|
||||
#define CMPCI_REG_MPU_BASE 0x40
|
||||
#define CMPCI_REG_MPU_SIZE 0x10
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* $NetBSD: cmpcivar.h,v 1.1 2000/04/30 21:59:58 augustss Exp $ */
|
||||
/* $NetBSD: cmpcivar.h,v 1.2 2001/02/12 18:47:12 tshiozak Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Takuya SHIOZAKI <AoiMoe@imou.to> .
|
||||
* by Takuya SHIOZAKI <tshiozak@netbsd.org> .
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -40,13 +40,13 @@
|
|||
* DMA pool
|
||||
*/
|
||||
struct cmpci_dmanode {
|
||||
bus_dma_tag_t cd_tag;
|
||||
int cd_nsegs;
|
||||
bus_dma_segment_t cd_segs[1];
|
||||
bus_dmamap_t cd_map;
|
||||
caddr_t cd_addr;
|
||||
size_t cd_size;
|
||||
struct cmpci_dmanode *cd_next;
|
||||
bus_dma_tag_t cd_tag;
|
||||
int cd_nsegs;
|
||||
bus_dma_segment_t cd_segs[1];
|
||||
bus_dmamap_t cd_map;
|
||||
caddr_t cd_addr;
|
||||
size_t cd_size;
|
||||
struct cmpci_dmanode *cd_next;
|
||||
};
|
||||
|
||||
typedef struct cmpci_dmanode *cmpci_dmapool_t;
|
||||
|
@ -91,14 +91,31 @@ typedef struct cmpci_dmanode *cmpci_dmapool_t;
|
|||
#define CMPCI_MIC_OUT_MUTE 26
|
||||
#define CMPCI_LINE_OUT_MUTE 27
|
||||
|
||||
#ifdef CMPCI_SPDIF_SUPPORT
|
||||
#define CMPCI_SPDIF_IN 28
|
||||
#define CMPCI_SPDIF_IN_MUTE 29
|
||||
#define CMPCI_SPDIF_IN_MUTE 28
|
||||
#define CMPCI_SPDIF_CLASS 29
|
||||
#define CMPCI_SPDIF_LOOP 30
|
||||
#define CMPCI_SPDIF_LEGACY 31
|
||||
#define CMPCI_SPDIF_OUT_VOLTAGE 32
|
||||
#define CMPCI_SPDIF_IN_PHASE 33
|
||||
#define CMPCI_REAR 34
|
||||
#define CMPCI_INDIVIDUAL 35
|
||||
#define CMPCI_REVERSE 36
|
||||
#define CMPCI_SURROUND 37
|
||||
#define CmpciNspdif "spdif"
|
||||
#define CMPCI_NDEVS 30
|
||||
#else
|
||||
#define CMPCI_NDEVS 28
|
||||
#endif
|
||||
#define CmpciCspdif "spdif"
|
||||
#define CmpciNloop "loop"
|
||||
#define CmpciNlegacy "legacy"
|
||||
#define CmpciNout_voltage "out_voltage"
|
||||
#define CmpciNin_phase "in_phase"
|
||||
#define CmpciNpositive "positive"
|
||||
#define CmpciNnegative "negative"
|
||||
#define CmpciNrear "rear"
|
||||
#define CmpciNindividual "individual"
|
||||
#define CmpciNreverse "reverse"
|
||||
#define CmpciNlow_v "0.5V"
|
||||
#define CmpciNhigh_v "5V"
|
||||
#define CmpciNsurround "surround"
|
||||
#define CMPCI_NDEVS 38
|
||||
|
||||
#define CMPCI_IS_IN_MUTE(x) ((x) < CMPCI_CD_SWAP)
|
||||
|
||||
|
@ -107,35 +124,64 @@ typedef struct cmpci_dmanode *cmpci_dmapool_t;
|
|||
* softc
|
||||
*/
|
||||
struct cmpci_softc {
|
||||
struct device sc_dev;
|
||||
struct device sc_dev;
|
||||
|
||||
/* model/rev */
|
||||
int sc_revision;
|
||||
int sc_model;
|
||||
uint32_t sc_id;
|
||||
uint32_t sc_class;
|
||||
uint32_t sc_capable;
|
||||
#define CMPCI_CAP_SPDIN 0x00000001
|
||||
#define CMPCI_CAP_SPDOUT 0x00000002
|
||||
#define CMPCI_CAP_SPDLOOP 0x00000004
|
||||
#define CMPCI_CAP_SPDLEGACY 0x00000008
|
||||
#define CMPCI_CAP_SPDIN_MONITOR 0x00000010
|
||||
#define CMPCI_CAP_XSPDOUT 0x00000020
|
||||
#define CMPCI_CAP_SPDOUT_VOLTAGE 0x00000040
|
||||
#define CMPCI_CAP_SPDOUT_48K 0x00000080
|
||||
#define CMPCI_CAP_SURROUND 0x00000100
|
||||
#define CMPCI_CAP_REAR 0x00000200
|
||||
#define CMPCI_CAP_INDIVIDUAL_REAR 0x00000400
|
||||
#define CMPCI_CAP_REVERSE_FR 0x00000800
|
||||
#define CMPCI_CAP_SPDIN_PHASE 0x00001000
|
||||
|
||||
#define CMPCI_CAP_CMI8338 (CMPCI_CAP_SPDIN | CMPCI_CAP_SPDOUT | \
|
||||
CMPCI_CAP_SPDLOOP | CMPCI_CAP_SPDLEGACY)
|
||||
|
||||
#define CMPCI_CAP_CMI8738 (CMPCI_CAP_CMI8338 | \
|
||||
CMPCI_CAP_SPDIN_MONITOR | \
|
||||
CMPCI_CAP_XSPDOUT | \
|
||||
CMPCI_CAP_SPDOUT_VOLTAGE | \
|
||||
CMPCI_CAP_SPDOUT_48K | CMPCI_CAP_SURROUND |\
|
||||
CMPCI_CAP_REAR | \
|
||||
CMPCI_CAP_INDIVIDUAL_REAR | \
|
||||
CMPCI_CAP_REVERSE_FR | \
|
||||
CMPCI_CAP_SPDIN_PHASE)
|
||||
#define CMPCI_ISCAP(sc, name) (sc->sc_capable & CMPCI_CAP_ ## name)
|
||||
|
||||
/* I/O Base device */
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
|
||||
/* intr handle */
|
||||
pci_intr_handle_t * sc_ih;
|
||||
pci_intr_handle_t *sc_ih;
|
||||
|
||||
/* DMA */
|
||||
bus_dma_tag_t sc_dmat;
|
||||
cmpci_dmapool_t sc_dmap;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
cmpci_dmapool_t sc_dmap;
|
||||
|
||||
/* each channel */
|
||||
struct {
|
||||
void (*intr) __P((void *));
|
||||
void *intr_arg;
|
||||
void (*intr) __P((void *));
|
||||
void *intr_arg;
|
||||
int md_divide;
|
||||
} sc_play, sc_rec;
|
||||
|
||||
/* mixer */
|
||||
uint8_t gain[CMPCI_NDEVS][2];
|
||||
#define CMPCI_LEFT 0
|
||||
#define CMPCI_RIGHT 1
|
||||
#define CMPCI_LR 0
|
||||
uint16_t in_mask;
|
||||
uint8_t sc_gain[CMPCI_NDEVS][2];
|
||||
#define CMPCI_LEFT 0
|
||||
#define CMPCI_RIGHT 1
|
||||
#define CMPCI_LR 0
|
||||
uint16_t sc_in_mask;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue