summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/cmpci.430
-rw-r--r--sys/dev/pci/cmpci.c263
-rw-r--r--sys/dev/pci/cmpcireg.h19
-rw-r--r--sys/dev/pci/cmpcivar.h25
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