diff options
-rw-r--r-- | share/man/man4/cmpci.4 | 30 | ||||
-rw-r--r-- | sys/dev/pci/cmpci.c | 263 | ||||
-rw-r--r-- | sys/dev/pci/cmpcireg.h | 19 | ||||
-rw-r--r-- | sys/dev/pci/cmpcivar.h | 25 |
4 files changed, 279 insertions, 58 deletions
diff --git a/share/man/man4/cmpci.4 b/share/man/man4/cmpci.4 index 5f9fc06de64..b6539eb6737 100644 --- a/share/man/man4/cmpci.4 +++ b/share/man/man4/cmpci.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: cmpci.4,v 1.10 2007/05/31 19:19:49 jmc Exp $ +.\" $OpenBSD: cmpci.4,v 1.11 2008/01/09 02:17:52 jakemsr Exp $ .\" .\" Copyright (c) 2000 Takuya SHIOZAKI .\" All rights reserved. @@ -24,21 +24,39 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: May 31 2007 $ +.Dd $Mdocdate: January 9 2008 $ .Dt CMPCI 4 .Os .Sh NAME .Nm cmpci -.Nd C-Media CMI8x38 PCI audio device +.Nd C-Media CMI8338, CMI8738, CMI8768 PCI audio devices .Sh SYNOPSIS .Cd "cmpci* at pci?" .Cd "audio* at cmpci?" .Sh DESCRIPTION The .Nm -driver supports the C-Media CMI8338A, CMI8338B, CMI8738 and CMI8738B -sound chips present in some PCI sound cards and some integrated -PC motherboard chipsets (such as the SiS 530). +driver supports the C-Media CMI8338A, CMI8338B, CMI8738, CMI8738B +and CMI8768 sound chips present in some PCI sound cards and some +integrated PC motherboard chipsets (such as the SiS 530). +.Pp +Hardware features: +.Bl -bullet -offset indent +.It +Supports 8 common sample rates from 5512 Hz to 48000 Hz +.It +Hardware full-duplex support enables simultaneous record and playback +.It +Some CMI8738 versions support 4 and 6 channel playback +.It +CMI8768 chips support 4, 6, and 8 channel playback +.It +CMI8768 chips can only record sample rates of 44100 Hz or 48000 Hz +.It +Hardware copying of front to rear for playing stereo input on 4 speakers +.It +S/PDIF input and output +.El .Sh SEE ALSO .Xr audio 4 , .Xr intro 4 , diff --git a/sys/dev/pci/cmpci.c b/sys/dev/pci/cmpci.c index d8e9622e42f..708ddb594d0 100644 --- a/sys/dev/pci/cmpci.c +++ b/sys/dev/pci/cmpci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmpci.c,v 1.16 2007/09/13 16:51:19 brad Exp $ */ +/* $OpenBSD: cmpci.c,v 1.17 2008/01/09 02:17:52 jakemsr Exp $ */ /* $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $ */ /* @@ -35,10 +35,9 @@ */ /* - * C-Media CMI8x38 Audio Chip Support. + * C-Media CMI8x38, CMI8768 Audio Chip Support. * * TODO: - * - 4ch / 6ch support. * - Joystick support. * */ @@ -362,7 +361,7 @@ cmpci_attach(struct device *parent, struct device *self, void *aux) struct audio_attach_args aa; pci_intr_handle_t ih; char const *intrstr; - int i, v; + int i, v, d; sc->sc_id = pa->pa_id; sc->sc_class = pa->pa_class; @@ -425,6 +424,34 @@ cmpci_attach(struct device *parent, struct device *self, void *aux) sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K; + /* extra capabilitites check */ + d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_INTR_CTRL) & + CMPCI_REG_CHIP_MASK2; + if (d) { + if (d & CMPCI_REG_CHIP_8768) { + sc->sc_version = 68; + sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH | + CMPCI_CAP_8CH; + } else if (d & CMPCI_REG_CHIP_055) { + sc->sc_version = 55; + sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH; + } else if (d & CMPCI_REG_CHIP_039) { + sc->sc_version = 39; + sc->sc_capable |= CMPCI_CAP_4CH | + ((d & CMPCI_REG_CHIP_039_6CH) ? CMPCI_CAP_6CH : 0); + } else { + /* unknown version */ + sc->sc_version = 0; + } + } else { + d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + CMPCI_REG_CHANNEL_FORMAT) & CMPCI_REG_CHIP_MASK1; + if (d) + sc->sc_version = 37; + else + sc->sc_version = 33; + } + 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); @@ -488,6 +515,8 @@ cmpci_attach(struct device *parent, struct device *self, void *aux) sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v; cmpci_set_mixer_gain(sc, i); } + + sc->sc_play_channel = 0; } int @@ -513,12 +542,12 @@ cmpci_intr(void *handle) CMPCI_REG_CH1_INTR_ENABLE); if (intrstat & CMPCI_REG_CH0_INTR) { - if (sc->sc_play.intr != NULL) - (*sc->sc_play.intr)(sc->sc_play.intr_arg); + if (sc->sc_ch0.intr != NULL) + (*sc->sc_ch0.intr)(sc->sc_ch0.intr_arg); } if (intrstat & CMPCI_REG_CH1_INTR) { - if (sc->sc_rec.intr != NULL) - (*sc->sc_rec.intr)(sc->sc_rec.intr_arg); + if (sc->sc_ch1.intr != NULL) + (*sc->sc_ch1.intr)(sc->sc_ch1.intr_arg); } /* enable intr */ @@ -637,6 +666,34 @@ cmpci_set_params(void *handle, int setmode, int usemode, if (!(setmode & mode)) continue; + if (setmode & AUMODE_RECORD) { + if (p->channels > 2) + return (EINVAL); + sc->sc_play_channel = 0; + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENDBDAC); + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_XCHGDAC); + } else { + sc->sc_play_channel = 1; + cmpci_reg_set_reg_misc(sc, CMPCI_REG_ENDBDAC); + cmpci_reg_set_reg_misc(sc, CMPCI_REG_XCHGDAC); + } + + cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_NXCHG); + if (sc->sc_capable & CMPCI_CAP_4CH) + cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, + CMPCI_REG_CHB3D); + if (sc->sc_capable & CMPCI_CAP_6CH) { + cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, + CMPCI_REG_CHB3D5C); + cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_CHB3D6C); + cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENCENTER); + } + if (sc->sc_capable & CMPCI_CAP_8CH) + cmpci_reg_clear_4(sc, CMPCI_REG_8768_MISC, + CMPCI_REG_CHB3D8C); + /* format */ p->sw_code = NULL; switch (p->channels) { @@ -646,6 +703,67 @@ cmpci_set_params(void *handle, int setmode, int usemode, case 2: md_format = CMPCI_REG_FORMAT_STEREO; break; + case 4: + if (mode & AUMODE_PLAY) { + if (sc->sc_capable & CMPCI_CAP_4CH) { + cmpci_reg_clear_reg_misc(sc, + CMPCI_REG_N4SPK3D); + cmpci_reg_set_4(sc, + CMPCI_REG_CHANNEL_FORMAT, + CMPCI_REG_CHB3D); + cmpci_reg_set_4(sc, + CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_NXCHG); + } else + return (EINVAL); + } + md_format = CMPCI_REG_FORMAT_STEREO; + break; + case 6: + if (mode & AUMODE_PLAY) { + if (sc->sc_capable & CMPCI_CAP_6CH) { + cmpci_reg_clear_reg_misc(sc, + CMPCI_REG_N4SPK3D); + cmpci_reg_set_4(sc, + CMPCI_REG_CHANNEL_FORMAT, + CMPCI_REG_CHB3D5C); + cmpci_reg_set_4(sc, + CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_CHB3D6C); + cmpci_reg_set_reg_misc(sc, + CMPCI_REG_ENCENTER); + cmpci_reg_set_4(sc, + CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_NXCHG); + } else + return (EINVAL); + } + md_format = CMPCI_REG_FORMAT_STEREO; + break; + case 8: + if (mode & AUMODE_PLAY) { + if (sc->sc_capable & CMPCI_CAP_8CH) { + cmpci_reg_clear_reg_misc(sc, + CMPCI_REG_N4SPK3D); + cmpci_reg_set_4(sc, + CMPCI_REG_CHANNEL_FORMAT, + CMPCI_REG_CHB3D5C); + cmpci_reg_set_4(sc, + CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_CHB3D6C); + cmpci_reg_set_reg_misc(sc, + CMPCI_REG_ENCENTER); + cmpci_reg_set_4(sc, + CMPCI_REG_8768_MISC, + CMPCI_REG_CHB3D8C); + cmpci_reg_set_4(sc, + CMPCI_REG_LEGACY_CTRL, + CMPCI_REG_NXCHG); + } else + return (EINVAL); + } + md_format = CMPCI_REG_FORMAT_STEREO; + break; default: return (EINVAL); } @@ -735,16 +853,24 @@ cmpci_set_params(void *handle, int setmode, int usemode, default: return (EINVAL); } - 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); - else + if (mode & AUMODE_PLAY) { + if (sc->sc_play_channel == 1) { + cmpci_reg_partial_write_4(sc, + CMPCI_REG_CHANNEL_FORMAT, + CMPCI_REG_CH1_FORMAT_SHIFT, + CMPCI_REG_CH1_FORMAT_MASK, md_format); + } else { + cmpci_reg_partial_write_4(sc, + 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_CH1_FORMAT_MASK, md_format); + } /* sample rate */ md_index = cmpci_rate_to_index(p->sample_rate); md_divide = cmpci_index_to_divider(md_index); @@ -752,15 +878,22 @@ cmpci_set_params(void *handle, int setmode, int usemode, DPRINTF(("%s: sample:%d, divider=%d\n", sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide)); 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); - sc->sc_play.md_divide = md_divide; + if (sc->sc_play_channel == 1) { + cmpci_reg_partial_write_4(sc, + CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT, + CMPCI_REG_ADC_FS_MASK, md_divide); + sc->sc_ch1.md_divide = md_divide; + } else { + cmpci_reg_partial_write_4(sc, + CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT, + CMPCI_REG_DAC_FS_MASK, md_divide); + sc->sc_ch0.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); - sc->sc_rec.md_divide = md_divide; + sc->sc_ch1.md_divide = md_divide; } cmpci_set_out_ports(sc); cmpci_set_in_ports(sc); @@ -779,16 +912,27 @@ int cmpci_halt_output(void *handle) { struct cmpci_softc *sc = handle; + uint32_t reg_intr, reg_enable, reg_reset; int s; s = splaudio(); - sc->sc_play.intr = NULL; - cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); - cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); + if (sc->sc_play_channel == 1) { + sc->sc_ch1.intr = NULL; + reg_intr = CMPCI_REG_CH1_INTR_ENABLE; + reg_enable = CMPCI_REG_CH1_ENABLE; + reg_reset = CMPCI_REG_CH1_RESET; + } else { + sc->sc_ch0.intr = NULL; + reg_intr = CMPCI_REG_CH0_INTR_ENABLE; + reg_enable = CMPCI_REG_CH0_ENABLE; + reg_reset = CMPCI_REG_CH0_RESET; + } + cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, reg_intr); + cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_enable); /* wait for reset DMA */ - cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); + cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_reset); delay(10); - cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); + cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_reset); splx(s); return 0; @@ -801,7 +945,7 @@ cmpci_halt_input(void *handle) int s; s = splaudio(); - sc->sc_rec.intr = NULL; + sc->sc_ch1.intr = NULL; cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); /* wait for reset DMA */ @@ -820,8 +964,8 @@ cmpci_getdev(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", - PCI_REVISION(sc->sc_class)); + snprintf(ad->version, sizeof(ad->version), "0x%02x (%d)", + PCI_REVISION(sc->sc_class), sc->sc_version); switch (PCI_PRODUCT(sc->sc_id)) { case PCI_PRODUCT_CMI_CMI8338A: strncpy(ad->config, "CMI8338A", sizeof(ad->config)); @@ -1385,6 +1529,7 @@ cmpci_set_mixer_gain(struct cmpci_softc *sc, int port) void cmpci_set_out_ports(struct cmpci_softc *sc) { + struct cmpci_channel *chan; u_int8_t v; int enspdout = 0; @@ -1411,17 +1556,22 @@ cmpci_set_out_ports(struct cmpci_softc *sc) else cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI); + if (sc->sc_play_channel == 1) + chan = &sc->sc_ch1; + else + chan = &sc->sc_ch0; + /* playback to ... */ if (CMPCI_ISCAP(sc, SPDOUT) && sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR] == CMPCI_PLAYBACK_MODE_SPDIF && - (sc->sc_play.md_divide == CMPCI_REG_RATE_44100 || + (chan->md_divide == CMPCI_REG_RATE_44100 || (CMPCI_ISCAP(sc, SPDOUT_48K) && - sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) { + chan->md_divide==CMPCI_REG_RATE_48000))) { /* playback to SPDIF */ 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) + if (chan->md_divide==CMPCI_REG_RATE_48000) cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); else @@ -1514,9 +1664,9 @@ cmpci_set_in_ports(struct cmpci_softc *sc) CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR); if (CMPCI_ISCAP(sc, SPDIN) && - (sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 || + (sc->sc_ch1.md_divide == CMPCI_REG_RATE_44100 || (CMPCI_ISCAP(sc, SPDOUT_48K) && - sc->sc_rec.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) { + sc->sc_ch1.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) { if (mask & CMPCI_RECORD_SOURCE_SPDIF) { /* enable SPDIF/in */ cmpci_reg_set_4(sc, @@ -1746,33 +1896,56 @@ cmpci_trigger_output(void *handle, void *start, void *end, int blksize, { struct cmpci_softc *sc = handle; struct cmpci_dmanode *p; + struct cmpci_channel *chan; + uint32_t reg_dma_base, reg_dma_bytes, reg_dma_samples, reg_dir, + reg_intr_enable, reg_enable; + uint32_t length; int bps; - sc->sc_play.intr = intr; - sc->sc_play.intr_arg = arg; - bps = param->channels * param->precision * param->factor / 8; + if (sc->sc_play_channel == 1) { + chan = &sc->sc_ch1; + reg_dma_base = CMPCI_REG_DMA1_BASE; + reg_dma_bytes = CMPCI_REG_DMA1_BYTES; + reg_dma_samples = CMPCI_REG_DMA1_SAMPLES; + reg_dir = CMPCI_REG_CH1_DIR; + reg_intr_enable = CMPCI_REG_CH1_INTR_ENABLE; + reg_enable = CMPCI_REG_CH1_ENABLE; + } else { + chan = &sc->sc_ch0; + reg_dma_base = CMPCI_REG_DMA0_BASE; + reg_dma_bytes = CMPCI_REG_DMA0_BYTES; + reg_dma_samples = CMPCI_REG_DMA0_SAMPLES; + reg_dir = CMPCI_REG_CH0_DIR; + reg_intr_enable = CMPCI_REG_CH0_INTR_ENABLE; + reg_enable = CMPCI_REG_CH0_ENABLE; + } + + chan->intr = intr; + chan->intr_arg = arg; + bps = (param->channels > 1 ? 2 : 1) * param->precision * + param->factor / 8; if (!bps) return EINVAL; /* set DMA frame */ if (!(p = cmpci_find_dmamem(sc, start))) return EINVAL; - bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE, + bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg_dma_base, 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); + length = ((caddr_t)end - (caddr_t)start + 1) / bps - 1; + bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_bytes, length); delay(10); /* set interrupt count */ - bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES, - (blksize + bps - 1) / bps - 1); + length = (blksize + bps - 1) / bps - 1; + bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_samples, length); delay(10); /* start DMA */ - cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */ - cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); - cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); + cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_dir); /* PLAY */ + cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, reg_intr_enable); + cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_enable); return 0; } @@ -1785,8 +1958,8 @@ cmpci_trigger_input(void *handle, void *start, void *end, int blksize, struct cmpci_dmanode *p; int bps; - sc->sc_rec.intr = intr; - sc->sc_rec.intr_arg = arg; + sc->sc_ch1.intr = intr; + sc->sc_ch1.intr_arg = arg; bps = param->channels*param->precision*param->factor/8; if (!bps) return EINVAL; diff --git a/sys/dev/pci/cmpcireg.h b/sys/dev/pci/cmpcireg.h index 9ef92c206f0..341107127af 100644 --- a/sys/dev/pci/cmpcireg.h +++ b/sys/dev/pci/cmpcireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cmpcireg.h,v 1.2 2006/07/27 00:45:59 brad Exp $ */ +/* $OpenBSD: cmpcireg.h,v 1.3 2008/01/09 02:17:52 jakemsr Exp $ */ /* $NetBSD: cmpcireg.h,v 1.7 2005/12/11 12:22:48 christos Exp $ */ /* @@ -85,11 +85,20 @@ # define CMPCI_REG_FORMAT_STEREO 0x00000001 # define CMPCI_REG_FORMAT_8BIT 0x00000000 # define CMPCI_REG_FORMAT_16BIT 0x00000002 +# define CMPCI_REG_CHIP_MASK1 0x1f000000 +# define CMCPI_REG_CHIP_037 0x01000000 +# define CMPCI_REG_CHB3D 0x20000000 +# define CMPCI_REG_CHB3D5C 0x80000000 #define CMPCI_REG_INTR_CTRL 0x0c # define CMPCI_REG_CH0_INTR_ENABLE 0x00010000 # define CMPCI_REG_CH1_INTR_ENABLE 0x00020000 # define CMPCI_REG_TDMA_INTR_ENABLE 0x00040000 +# define CMPCI_REG_CHIP_MASK2 0xff000000 +# define CMPCI_REG_CHIP_039 0x04000000 +# define CMPCI_REG_CHIP_039_6CH 0x01000000 +# define CMPCI_REG_CHIP_055 0x08000000 +# define CMPCI_REG_CHIP_8768 0x20000000 #define CMPCI_REG_INTR_STATUS 0x10 # define CMPCI_REG_CH0_INTR 0x00000001 @@ -117,12 +126,18 @@ # define CMPCI_REG_VSBSEL_MASK 0x00000003 # define CMPCI_REG_VMPUSEL_SHIFT 29 # define CMPCI_REG_VMPUSEL_MASK 0x00000003 +# define CMPCI_REG_CHB3D6C 0x00008000 +# define CMPCI_REG_NXCHG 0x80000000 #define CMPCI_REG_MISC 0x18 +# define CMPCI_REG_ENCENTER 0x00000080 # define CMPCI_REG_2ND_SPDIFIN 0x00000100 # define CMPCI_REG_SPDIFOUT_48K 0x00008000 # define CMPCI_REG_FM_ENABLE 0x00080000 # define CMPCI_REG_SPDFLOOPI 0x00100000 +# define CMPCI_REG_SPD32SEL 0x00200000 +# define CMPCI_REG_XCHGDAC 0x00400000 +# define CMPCI_REG_ENDBDAC 0x00800000 # define CMPCI_REG_SPDIF48K 0x01000000 # define CMPCI_REG_5V 0x02000000 # define CMPCI_REG_N4SPK3D 0x04000000 @@ -211,6 +226,8 @@ #define CMPCI_REG_DMA1_BYTES 0x8C #define CMPCI_REG_DMA1_SAMPLES 0x8E +#define CMPCI_REG_8768_MISC 0x92 +#define CMPCI_REG_CHB3D8C 0x20 /* sample rate */ #define CMPCI_REG_RATE_5512 0 diff --git a/sys/dev/pci/cmpcivar.h b/sys/dev/pci/cmpcivar.h index 7e1eb6e0400..93b35e49edb 100644 --- a/sys/dev/pci/cmpcivar.h +++ b/sys/dev/pci/cmpcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cmpcivar.h,v 1.5 2007/10/28 18:29:13 fgsch Exp $ */ +/* $OpenBSD: cmpcivar.h,v 1.6 2008/01/09 02:17:52 jakemsr Exp $ */ /* $NetBSD: cmpcivar.h,v 1.9 2005/12/11 12:22:48 christos Exp $ */ /* @@ -173,6 +173,14 @@ typedef struct cmpci_dmanode *cmpci_dmapool_t; /* * softc */ + + /* each channel */ +struct cmpci_channel { + void (*intr)(void *); + void *intr_arg; + int md_divide; +}; + struct cmpci_softc { struct device sc_dev; @@ -194,6 +202,9 @@ struct cmpci_softc { #define CMPCI_CAP_REVERSE_FR 0x00000800 #define CMPCI_CAP_SPDIN_PHASE 0x00001000 #define CMPCI_CAP_2ND_SPDIN 0x00002000 +#define CMPCI_CAP_4CH 0x00004000 +#define CMPCI_CAP_6CH 0x00008000 +#define CMPCI_CAP_8CH 0x00010000 #define CMPCI_CAP_CMI8338 (CMPCI_CAP_SPDIN | CMPCI_CAP_SPDOUT | \ CMPCI_CAP_SPDLOOP | CMPCI_CAP_SPDLEGACY) @@ -225,15 +236,17 @@ struct cmpci_softc { cmpci_dmapool_t sc_dmap; /* each channel */ - struct { - void (*intr)(void *); - void *intr_arg; - int md_divide; - } sc_play, sc_rec; + struct cmpci_channel sc_ch0, sc_ch1; + + /* which channel is used for playback */ + uint32_t sc_play_channel; /* value of CMPCI_REG_MISC register */ uint32_t sc_reg_misc; + /* chip version */ + uint32_t sc_version; + /* mixer */ uint8_t sc_gain[CMPCI_NDEVS][2]; #define CMPCI_LEFT 0 |