1 /* $NetBSD: cmpci.c,v 1.41 2009/05/12 08:23:00 cegger Exp $ */
4 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Takuya SHIOZAKI <tshiozak@NetBSD.org> .
10 * This code is derived from software contributed to The NetBSD Foundation
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * C-Media CMI8x38 Audio Chip Support.
40 * - 4ch / 6ch support.
45 #include <sys/cdefs.h>
46 __KERNEL_RCSID(0, "$NetBSD: cmpci.c,v 1.41 2009/05/12 08:23:00 cegger Exp $");
48 #if defined(AUDIO_DEBUG) || defined(DEBUG)
49 #define DPRINTF(x) if (cmpcidebug) printf x
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
60 #include <sys/malloc.h>
61 #include <sys/device.h>
64 #include <dev/pci/pcidevs.h>
65 #include <dev/pci/pcivar.h>
67 #include <sys/audioio.h>
68 #include <dev/audio_if.h>
69 #include <dev/midi_if.h>
71 #include <dev/mulaw.h>
72 #include <dev/auconv.h>
73 #include <dev/pci/cmpcireg.h>
74 #include <dev/pci/cmpcivar.h>
76 #include <dev/ic/mpuvar.h>
81 * Low-level HW interface
83 static inline uint8_t cmpci_mixerreg_read(struct cmpci_softc
*, uint8_t);
84 static inline void cmpci_mixerreg_write(struct cmpci_softc
*,
86 static inline void cmpci_reg_partial_write_1(struct cmpci_softc
*, int, int,
88 static inline void cmpci_reg_partial_write_4(struct cmpci_softc
*, int, int,
90 static inline void cmpci_reg_set_1(struct cmpci_softc
*, int, uint8_t);
91 static inline void cmpci_reg_clear_1(struct cmpci_softc
*, int, uint8_t);
92 static inline void cmpci_reg_set_4(struct cmpci_softc
*, int, uint32_t);
93 static inline void cmpci_reg_clear_4(struct cmpci_softc
*, int, uint32_t);
94 static inline void cmpci_reg_set_reg_misc(struct cmpci_softc
*, uint32_t);
95 static inline void cmpci_reg_clear_reg_misc(struct cmpci_softc
*, uint32_t);
96 static int cmpci_rate_to_index(int);
97 static inline int cmpci_index_to_rate(int);
98 static inline int cmpci_index_to_divider(int);
100 static int cmpci_adjust(int, int);
101 static void cmpci_set_mixer_gain(struct cmpci_softc
*, int);
102 static void cmpci_set_out_ports(struct cmpci_softc
*);
103 static int cmpci_set_in_ports(struct cmpci_softc
*);
109 static int cmpci_match(device_t
, cfdata_t
, void *);
110 static void cmpci_attach(device_t
, device_t
, void *);
112 CFATTACH_DECL(cmpci
, sizeof (struct cmpci_softc
),
113 cmpci_match
, cmpci_attach
, NULL
, NULL
);
116 static int cmpci_intr(void *);
122 static int cmpci_alloc_dmamem(struct cmpci_softc
*, size_t,
123 struct malloc_type
*, int, void **);
124 static int cmpci_free_dmamem(struct cmpci_softc
*, void *,
125 struct malloc_type
*);
126 static struct cmpci_dmanode
* cmpci_find_dmamem(struct cmpci_softc
*,
131 * interface to machine independent layer
133 static int cmpci_query_encoding(void *, struct audio_encoding
*);
134 static int cmpci_set_params(void *, int, int, audio_params_t
*,
135 audio_params_t
*, stream_filter_list_t
*, stream_filter_list_t
*);
136 static int cmpci_round_blocksize(void *, int, int, const audio_params_t
*);
137 static int cmpci_halt_output(void *);
138 static int cmpci_halt_input(void *);
139 static int cmpci_getdev(void *, struct audio_device
*);
140 static int cmpci_set_port(void *, mixer_ctrl_t
*);
141 static int cmpci_get_port(void *, mixer_ctrl_t
*);
142 static int cmpci_query_devinfo(void *, mixer_devinfo_t
*);
143 static void *cmpci_allocm(void *, int, size_t, struct malloc_type
*, int);
144 static void cmpci_freem(void *, void *, struct malloc_type
*);
145 static size_t cmpci_round_buffersize(void *, int, size_t);
146 static paddr_t
cmpci_mappage(void *, void *, off_t
, int);
147 static int cmpci_get_props(void *);
148 static int cmpci_trigger_output(void *, void *, void *, int,
149 void (*)(void *), void *, const audio_params_t
*);
150 static int cmpci_trigger_input(void *, void *, void *, int,
151 void (*)(void *), void *, const audio_params_t
*);
153 static const struct audio_hw_if cmpci_hw_if
= {
157 cmpci_query_encoding
, /* query_encoding */
158 cmpci_set_params
, /* set_params */
159 cmpci_round_blocksize
, /* round_blocksize */
160 NULL
, /* commit_settings */
161 NULL
, /* init_output */
162 NULL
, /* init_input */
163 NULL
, /* start_output */
164 NULL
, /* start_input */
165 cmpci_halt_output
, /* halt_output */
166 cmpci_halt_input
, /* halt_input */
167 NULL
, /* speaker_ctl */
168 cmpci_getdev
, /* getdev */
170 cmpci_set_port
, /* set_port */
171 cmpci_get_port
, /* get_port */
172 cmpci_query_devinfo
, /* query_devinfo */
173 cmpci_allocm
, /* allocm */
174 cmpci_freem
, /* freem */
175 cmpci_round_buffersize
,/* round_buffersize */
176 cmpci_mappage
, /* mappage */
177 cmpci_get_props
, /* get_props */
178 cmpci_trigger_output
, /* trigger_output */
179 cmpci_trigger_input
, /* trigger_input */
180 NULL
, /* dev_ioctl */
181 NULL
, /* powerstate */
184 #define CMPCI_NFORMATS 4
185 static const struct audio_format cmpci_formats
[CMPCI_NFORMATS
] = {
186 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
187 2, AUFMT_STEREO
, 0, {5512, 48000}},
188 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
189 1, AUFMT_MONAURAL
, 0, {5512, 48000}},
190 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
191 2, AUFMT_STEREO
, 0, {5512, 48000}},
192 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
193 1, AUFMT_MONAURAL
, 0, {5512, 48000}},
198 * Low-level HW interface
201 /* mixer register read/write */
202 static inline uint8_t
203 cmpci_mixerreg_read(struct cmpci_softc
*sc
, uint8_t no
)
207 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_SBADDR
, no
);
209 ret
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_SBDATA
);
215 cmpci_mixerreg_write(struct cmpci_softc
*sc
, uint8_t no
, uint8_t val
)
218 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_SBADDR
, no
);
220 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_SBDATA
, val
);
225 /* register partial write */
227 cmpci_reg_partial_write_1(struct cmpci_softc
*sc
, int no
, int shift
,
228 unsigned mask
, unsigned val
)
231 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, no
,
233 (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, no
) & ~(mask
<<shift
)));
238 cmpci_reg_partial_write_4(struct cmpci_softc
*sc
, int no
, int shift
,
239 uint32_t mask
, uint32_t val
)
242 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, no
,
244 (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, no
) & ~(mask
<<shift
)));
248 /* register set/clear bit */
250 cmpci_reg_set_1(struct cmpci_softc
*sc
, int no
, uint8_t mask
)
253 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, no
,
254 (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, no
) | mask
));
259 cmpci_reg_clear_1(struct cmpci_softc
*sc
, int no
, uint8_t mask
)
262 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, no
,
263 (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, no
) & ~mask
));
268 cmpci_reg_set_4(struct cmpci_softc
*sc
, int no
, uint32_t mask
)
271 /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */
272 KDASSERT(no
!= CMPCI_REG_MISC
);
274 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, no
,
275 (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, no
) | mask
));
280 cmpci_reg_clear_4(struct cmpci_softc
*sc
, int no
, uint32_t mask
)
283 /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */
284 KDASSERT(no
!= CMPCI_REG_MISC
);
286 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, no
,
287 (bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, no
) & ~mask
));
292 * The CMPCI_REG_MISC register needs special handling, since one of
293 * its bits has different read/write values.
296 cmpci_reg_set_reg_misc(struct cmpci_softc
*sc
, uint32_t mask
)
299 sc
->sc_reg_misc
|= mask
;
300 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_MISC
,
306 cmpci_reg_clear_reg_misc(struct cmpci_softc
*sc
, uint32_t mask
)
309 sc
->sc_reg_misc
&= ~mask
;
310 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_MISC
,
316 static const struct {
319 } cmpci_rate_table
[CMPCI_REG_NUMRATE
] = {
320 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
333 cmpci_rate_to_index(int rate
)
337 for (i
= 0; i
< CMPCI_REG_NUMRATE
- 1; i
++)
339 (cmpci_rate_table
[i
].rate
+cmpci_rate_table
[i
+1].rate
) / 2)
341 return i
; /* 48000 */
345 cmpci_index_to_rate(int index
)
348 return cmpci_rate_table
[index
].rate
;
352 cmpci_index_to_divider(int index
)
355 return cmpci_rate_table
[index
].divider
;
359 * interface to configure the device.
362 cmpci_match(device_t parent
, cfdata_t match
, void *aux
)
364 struct pci_attach_args
*pa
;
366 pa
= (struct pci_attach_args
*)aux
;
367 if ( PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_CMEDIA
&&
368 (PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_CMEDIA_CMI8338A
||
369 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_CMEDIA_CMI8338B
||
370 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_CMEDIA_CMI8738
||
371 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_CMEDIA_CMI8738B
) )
378 cmpci_attach(device_t parent
, device_t self
, void *aux
)
380 struct cmpci_softc
*sc
;
381 struct pci_attach_args
*pa
;
382 struct audio_attach_args aa
;
383 pci_intr_handle_t ih
;
388 sc
= device_private(self
);
389 pa
= (struct pci_attach_args
*)aux
;
390 aprint_naive(": Audio controller\n");
392 sc
->sc_id
= pa
->pa_id
;
393 sc
->sc_class
= pa
->pa_class
;
394 pci_devinfo(pa
->pa_id
, pa
->pa_class
, 0, devinfo
, sizeof(devinfo
));
395 aprint_normal(": %s (rev. 0x%02x)\n", devinfo
,
396 PCI_REVISION(sc
->sc_class
));
397 switch (PCI_PRODUCT(sc
->sc_id
)) {
398 case PCI_PRODUCT_CMEDIA_CMI8338A
:
400 case PCI_PRODUCT_CMEDIA_CMI8338B
:
401 sc
->sc_capable
= CMPCI_CAP_CMI8338
;
403 case PCI_PRODUCT_CMEDIA_CMI8738
:
405 case PCI_PRODUCT_CMEDIA_CMI8738B
:
406 sc
->sc_capable
= CMPCI_CAP_CMI8738
;
411 if (pci_mapreg_map(pa
, CMPCI_PCI_IOBASEREG
, PCI_MAPREG_TYPE_IO
, 0,
412 &sc
->sc_iot
, &sc
->sc_ioh
, NULL
, NULL
)) {
413 aprint_error_dev(&sc
->sc_dev
, "failed to map I/O space\n");
418 if (pci_intr_map(pa
, &ih
)) {
419 aprint_error_dev(&sc
->sc_dev
, "failed to map interrupt\n");
422 strintr
= pci_intr_string(pa
->pa_pc
, ih
);
423 sc
->sc_ih
=pci_intr_establish(pa
->pa_pc
, ih
, IPL_AUDIO
, cmpci_intr
, sc
);
424 if (sc
->sc_ih
== NULL
) {
425 aprint_error_dev(&sc
->sc_dev
, "failed to establish interrupt");
427 aprint_error(" at %s", strintr
);
431 aprint_normal_dev(&sc
->sc_dev
, "interrupting at %s\n", strintr
);
433 sc
->sc_dmat
= pa
->pa_dmat
;
435 audio_attach_mi(&cmpci_hw_if
, sc
, &sc
->sc_dev
);
437 /* attach OPL device */
438 aa
.type
= AUDIODEV_TYPE_OPL
;
441 (void)config_found(&sc
->sc_dev
, &aa
, audioprint
);
443 /* attach MPU-401 device */
444 aa
.type
= AUDIODEV_TYPE_MPU
;
447 if (bus_space_subregion(sc
->sc_iot
, sc
->sc_ioh
,
448 CMPCI_REG_MPU_BASE
, CMPCI_REG_MPU_SIZE
, &sc
->sc_mpu_ioh
) == 0)
449 sc
->sc_mpudev
= config_found(&sc
->sc_dev
, &aa
, audioprint
);
451 /* get initial value (this is 0 and may be omitted but just in case) */
452 sc
->sc_reg_misc
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
453 CMPCI_REG_MISC
) & ~CMPCI_REG_SPDIF48K
;
455 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_RESET
, 0);
456 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_ADCMIX_L
, 0);
457 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_ADCMIX_R
, 0);
458 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_OUTMIX
,
459 CMPCI_SB16_SW_CD
|CMPCI_SB16_SW_MIC
| CMPCI_SB16_SW_LINE
);
460 for (i
= 0; i
< CMPCI_NDEVS
; i
++) {
463 * CMI8738 defaults are
464 * master: 0xe0 (0x00 - 0xf8)
465 * FM, DAC: 0xc0 (0x00 - 0xf8)
466 * PC speaker: 0x80 (0x00 - 0xc0)
470 case CMPCI_MASTER_VOL
:
477 case CMPCI_PCSPEAKER
:
481 /* booleans, set to true */
484 case CMPCI_LINE_IN_MUTE
:
485 case CMPCI_AUX_IN_MUTE
:
489 /* volume with inital value 0 */
491 case CMPCI_LINE_IN_VOL
:
492 case CMPCI_AUX_IN_VOL
:
494 case CMPCI_MIC_RECVOL
:
497 /* others are cleared */
498 case CMPCI_MIC_PREAMP
:
499 case CMPCI_RECORD_SOURCE
:
500 case CMPCI_PLAYBACK_MODE
:
501 case CMPCI_SPDIF_IN_SELECT
:
502 case CMPCI_SPDIF_IN_PHASE
:
503 case CMPCI_SPDIF_LOOP
:
504 case CMPCI_SPDIF_OUT_PLAYBACK
:
505 case CMPCI_SPDIF_OUT_VOLTAGE
:
506 case CMPCI_MONITOR_DAC
:
508 case CMPCI_INDIVIDUAL
:
515 sc
->sc_gain
[i
][CMPCI_LEFT
] = sc
->sc_gain
[i
][CMPCI_RIGHT
] = v
;
516 cmpci_set_mixer_gain(sc
, i
);
521 cmpci_intr(void *handle
)
523 struct cmpci_softc
*sc
= handle
;
525 struct mpu_softc
*sc_mpu
= device_private(sc
->sc_mpudev
);
529 intrstat
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
,
530 CMPCI_REG_INTR_STATUS
);
532 if (!(intrstat
& CMPCI_REG_ANY_INTR
))
537 /* disable and reset intr */
538 if (intrstat
& CMPCI_REG_CH0_INTR
)
539 cmpci_reg_clear_4(sc
, CMPCI_REG_INTR_CTRL
,
540 CMPCI_REG_CH0_INTR_ENABLE
);
541 if (intrstat
& CMPCI_REG_CH1_INTR
)
542 cmpci_reg_clear_4(sc
, CMPCI_REG_INTR_CTRL
,
543 CMPCI_REG_CH1_INTR_ENABLE
);
545 if (intrstat
& CMPCI_REG_CH0_INTR
) {
546 if (sc
->sc_play
.intr
!= NULL
)
547 (*sc
->sc_play
.intr
)(sc
->sc_play
.intr_arg
);
549 if (intrstat
& CMPCI_REG_CH1_INTR
) {
550 if (sc
->sc_rec
.intr
!= NULL
)
551 (*sc
->sc_rec
.intr
)(sc
->sc_rec
.intr_arg
);
555 if (intrstat
& CMPCI_REG_CH0_INTR
)
556 cmpci_reg_set_4(sc
, CMPCI_REG_INTR_CTRL
,
557 CMPCI_REG_CH0_INTR_ENABLE
);
558 if (intrstat
& CMPCI_REG_CH1_INTR
)
559 cmpci_reg_set_4(sc
, CMPCI_REG_INTR_CTRL
,
560 CMPCI_REG_CH1_INTR_ENABLE
);
563 if (intrstat
& CMPCI_REG_UART_INTR
&& sc_mpu
!= NULL
)
571 cmpci_query_encoding(void *handle
, struct audio_encoding
*fp
)
576 strcpy(fp
->name
, AudioEulinear
);
577 fp
->encoding
= AUDIO_ENCODING_ULINEAR
;
579 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
582 strcpy(fp
->name
, AudioEmulaw
);
583 fp
->encoding
= AUDIO_ENCODING_ULAW
;
585 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
588 strcpy(fp
->name
, AudioEalaw
);
589 fp
->encoding
= AUDIO_ENCODING_ALAW
;
591 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
594 strcpy(fp
->name
, AudioEslinear
);
595 fp
->encoding
= AUDIO_ENCODING_SLINEAR
;
600 strcpy(fp
->name
, AudioEslinear_le
);
601 fp
->encoding
= AUDIO_ENCODING_SLINEAR_LE
;
606 strcpy(fp
->name
, AudioEulinear_le
);
607 fp
->encoding
= AUDIO_ENCODING_ULINEAR_LE
;
609 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
612 strcpy(fp
->name
, AudioEslinear_be
);
613 fp
->encoding
= AUDIO_ENCODING_SLINEAR_BE
;
615 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
618 strcpy(fp
->name
, AudioEulinear_be
);
619 fp
->encoding
= AUDIO_ENCODING_ULINEAR_BE
;
621 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
631 cmpci_set_params(void *handle
, int setmode
, int usemode
,
632 audio_params_t
*play
, audio_params_t
*rec
, stream_filter_list_t
*pfil
,
633 stream_filter_list_t
*rfil
)
636 struct cmpci_softc
*sc
;
639 for (i
= 0; i
< 2; i
++) {
645 stream_filter_list_t
*fil
;
655 mode
= AUMODE_RECORD
;
663 if (!(setmode
& mode
))
666 md_index
= cmpci_rate_to_index(p
->sample_rate
);
667 md_divide
= cmpci_index_to_divider(md_index
);
668 p
->sample_rate
= cmpci_index_to_rate(md_index
);
669 DPRINTF(("%s: sample:%u, divider=%d\n",
670 device_xname(&sc
->sc_dev
), p
->sample_rate
, md_divide
));
672 ind
= auconv_set_converter(cmpci_formats
, CMPCI_NFORMATS
,
673 mode
, p
, FALSE
, fil
);
676 if (fil
->req_size
> 0)
677 p
= &fil
->filters
[0].param
;
680 md_format
= p
->channels
== 1
681 ? CMPCI_REG_FORMAT_MONO
: CMPCI_REG_FORMAT_STEREO
;
682 md_format
|= p
->precision
== 16
683 ? CMPCI_REG_FORMAT_16BIT
: CMPCI_REG_FORMAT_8BIT
;
684 if (mode
& AUMODE_PLAY
) {
685 cmpci_reg_partial_write_4(sc
,
686 CMPCI_REG_CHANNEL_FORMAT
,
687 CMPCI_REG_CH0_FORMAT_SHIFT
,
688 CMPCI_REG_CH0_FORMAT_MASK
, md_format
);
689 cmpci_reg_partial_write_4(sc
,
690 CMPCI_REG_FUNC_1
, CMPCI_REG_DAC_FS_SHIFT
,
691 CMPCI_REG_DAC_FS_MASK
, md_divide
);
692 sc
->sc_play
.md_divide
= md_divide
;
694 cmpci_reg_partial_write_4(sc
,
695 CMPCI_REG_CHANNEL_FORMAT
,
696 CMPCI_REG_CH1_FORMAT_SHIFT
,
697 CMPCI_REG_CH1_FORMAT_MASK
, md_format
);
698 cmpci_reg_partial_write_4(sc
,
699 CMPCI_REG_FUNC_1
, CMPCI_REG_ADC_FS_SHIFT
,
700 CMPCI_REG_ADC_FS_MASK
, md_divide
);
701 sc
->sc_rec
.md_divide
= md_divide
;
703 cmpci_set_out_ports(sc
);
704 cmpci_set_in_ports(sc
);
711 cmpci_round_blocksize(void *handle
, int block
,
712 int mode
, const audio_params_t
*param
)
719 cmpci_halt_output(void *handle
)
721 struct cmpci_softc
*sc
;
726 sc
->sc_play
.intr
= NULL
;
727 cmpci_reg_clear_4(sc
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH0_INTR_ENABLE
);
728 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_ENABLE
);
729 /* wait for reset DMA */
730 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_RESET
);
732 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_RESET
);
739 cmpci_halt_input(void *handle
)
741 struct cmpci_softc
*sc
;
746 sc
->sc_rec
.intr
= NULL
;
747 cmpci_reg_clear_4(sc
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH1_INTR_ENABLE
);
748 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_ENABLE
);
749 /* wait for reset DMA */
750 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_RESET
);
752 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_RESET
);
758 /* get audio device information */
760 cmpci_getdev(void *handle
, struct audio_device
*ad
)
762 struct cmpci_softc
*sc
;
765 strncpy(ad
->name
, "CMI PCI Audio", sizeof(ad
->name
));
766 snprintf(ad
->version
, sizeof(ad
->version
), "0x%02x",
767 PCI_REVISION(sc
->sc_class
));
768 switch (PCI_PRODUCT(sc
->sc_id
)) {
769 case PCI_PRODUCT_CMEDIA_CMI8338A
:
770 strncpy(ad
->config
, "CMI8338A", sizeof(ad
->config
));
772 case PCI_PRODUCT_CMEDIA_CMI8338B
:
773 strncpy(ad
->config
, "CMI8338B", sizeof(ad
->config
));
775 case PCI_PRODUCT_CMEDIA_CMI8738
:
776 strncpy(ad
->config
, "CMI8738", sizeof(ad
->config
));
778 case PCI_PRODUCT_CMEDIA_CMI8738B
:
779 strncpy(ad
->config
, "CMI8738B", sizeof(ad
->config
));
782 strncpy(ad
->config
, "unknown", sizeof(ad
->config
));
788 /* mixer device information */
790 cmpci_query_devinfo(void *handle
, mixer_devinfo_t
*dip
)
792 static const char *const mixer_port_names
[] = {
793 AudioNdac
, AudioNfmsynth
, AudioNcd
, AudioNline
, AudioNaux
,
796 static const char *const mixer_classes
[] = {
797 AudioCinputs
, AudioCoutputs
, AudioCrecord
, CmpciCplayback
,
800 struct cmpci_softc
*sc
;
804 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
806 switch (dip
->index
) {
807 case CMPCI_INPUT_CLASS
:
808 case CMPCI_OUTPUT_CLASS
:
809 case CMPCI_RECORD_CLASS
:
810 case CMPCI_PLAYBACK_CLASS
:
811 case CMPCI_SPDIF_CLASS
:
812 dip
->type
= AUDIO_MIXER_CLASS
;
813 dip
->mixer_class
= dip
->index
;
814 strcpy(dip
->label
.name
,
815 mixer_classes
[dip
->index
- CMPCI_INPUT_CLASS
]);
818 case CMPCI_AUX_IN_VOL
:
819 dip
->un
.v
.delta
= 1 << (8 - CMPCI_REG_AUX_VALBITS
);
824 case CMPCI_LINE_IN_VOL
:
826 dip
->un
.v
.delta
= 1 << (8 - CMPCI_SB16_MIXER_VALBITS
);
827 vol1
: dip
->mixer_class
= CMPCI_INPUT_CLASS
;
828 dip
->next
= dip
->index
+ 6; /* CMPCI_xxx_MUTE */
829 strcpy(dip
->label
.name
, mixer_port_names
[dip
->index
]);
830 dip
->un
.v
.num_channels
= (dip
->index
== CMPCI_MIC_VOL
? 1 : 2);
832 dip
->type
= AUDIO_MIXER_VALUE
;
833 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
837 dip
->next
= CMPCI_MIC_PREAMP
;
842 case CMPCI_LINE_IN_MUTE
:
843 case CMPCI_AUX_IN_MUTE
:
844 dip
->prev
= dip
->index
- 6; /* CMPCI_xxx_VOL */
845 dip
->mixer_class
= CMPCI_INPUT_CLASS
;
846 strcpy(dip
->label
.name
, AudioNmute
);
849 dip
->type
= AUDIO_MIXER_ENUM
;
850 dip
->un
.e
.num_mem
= 2;
851 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
852 dip
->un
.e
.member
[0].ord
= 0;
853 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
854 dip
->un
.e
.member
[1].ord
= 1;
857 case CMPCI_MIC_PREAMP
:
858 dip
->mixer_class
= CMPCI_INPUT_CLASS
;
859 dip
->prev
= CMPCI_MIC_MUTE
;
860 strcpy(dip
->label
.name
, AudioNpreamp
);
862 case CMPCI_PCSPEAKER
:
863 dip
->mixer_class
= CMPCI_INPUT_CLASS
;
864 strcpy(dip
->label
.name
, AudioNspeaker
);
865 dip
->un
.v
.num_channels
= 1;
866 dip
->un
.v
.delta
= 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS
);
868 case CMPCI_RECORD_SOURCE
:
869 dip
->mixer_class
= CMPCI_RECORD_CLASS
;
870 strcpy(dip
->label
.name
, AudioNsource
);
871 dip
->type
= AUDIO_MIXER_SET
;
872 dip
->un
.s
.num_mem
= 7;
873 strcpy(dip
->un
.s
.member
[0].label
.name
, AudioNmicrophone
);
874 dip
->un
.s
.member
[0].mask
= CMPCI_RECORD_SOURCE_MIC
;
875 strcpy(dip
->un
.s
.member
[1].label
.name
, AudioNcd
);
876 dip
->un
.s
.member
[1].mask
= CMPCI_RECORD_SOURCE_CD
;
877 strcpy(dip
->un
.s
.member
[2].label
.name
, AudioNline
);
878 dip
->un
.s
.member
[2].mask
= CMPCI_RECORD_SOURCE_LINE_IN
;
879 strcpy(dip
->un
.s
.member
[3].label
.name
, AudioNaux
);
880 dip
->un
.s
.member
[3].mask
= CMPCI_RECORD_SOURCE_AUX_IN
;
881 strcpy(dip
->un
.s
.member
[4].label
.name
, AudioNwave
);
882 dip
->un
.s
.member
[4].mask
= CMPCI_RECORD_SOURCE_WAVE
;
883 strcpy(dip
->un
.s
.member
[5].label
.name
, AudioNfmsynth
);
884 dip
->un
.s
.member
[5].mask
= CMPCI_RECORD_SOURCE_FM
;
885 strcpy(dip
->un
.s
.member
[6].label
.name
, CmpciNspdif
);
886 dip
->un
.s
.member
[6].mask
= CMPCI_RECORD_SOURCE_SPDIF
;
888 case CMPCI_MIC_RECVOL
:
889 dip
->mixer_class
= CMPCI_RECORD_CLASS
;
890 strcpy(dip
->label
.name
, AudioNmicrophone
);
891 dip
->un
.v
.num_channels
= 1;
892 dip
->un
.v
.delta
= 1 << (8 - CMPCI_REG_ADMIC_VALBITS
);
895 case CMPCI_PLAYBACK_MODE
:
896 dip
->mixer_class
= CMPCI_PLAYBACK_CLASS
;
897 dip
->type
= AUDIO_MIXER_ENUM
;
898 strcpy(dip
->label
.name
, AudioNmode
);
899 dip
->un
.e
.num_mem
= 2;
900 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNdac
);
901 dip
->un
.e
.member
[0].ord
= CMPCI_PLAYBACK_MODE_WAVE
;
902 strcpy(dip
->un
.e
.member
[1].label
.name
, CmpciNspdif
);
903 dip
->un
.e
.member
[1].ord
= CMPCI_PLAYBACK_MODE_SPDIF
;
905 case CMPCI_SPDIF_IN_SELECT
:
906 dip
->mixer_class
= CMPCI_SPDIF_CLASS
;
907 dip
->type
= AUDIO_MIXER_ENUM
;
908 dip
->next
= CMPCI_SPDIF_IN_PHASE
;
909 strcpy(dip
->label
.name
, AudioNinput
);
911 strcpy(dip
->un
.e
.member
[i
].label
.name
, CmpciNspdin1
);
912 dip
->un
.e
.member
[i
++].ord
= CMPCI_SPDIF_IN_SPDIN1
;
913 if (CMPCI_ISCAP(sc
, 2ND_SPDIN
)) {
914 strcpy(dip
->un
.e
.member
[i
].label
.name
, CmpciNspdin2
);
915 dip
->un
.e
.member
[i
++].ord
= CMPCI_SPDIF_IN_SPDIN2
;
917 strcpy(dip
->un
.e
.member
[i
].label
.name
, CmpciNspdout
);
918 dip
->un
.e
.member
[i
++].ord
= CMPCI_SPDIF_IN_SPDOUT
;
919 dip
->un
.e
.num_mem
= i
;
921 case CMPCI_SPDIF_IN_PHASE
:
922 dip
->mixer_class
= CMPCI_SPDIF_CLASS
;
923 dip
->prev
= CMPCI_SPDIF_IN_SELECT
;
924 strcpy(dip
->label
.name
, CmpciNphase
);
925 dip
->type
= AUDIO_MIXER_ENUM
;
926 dip
->un
.e
.num_mem
= 2;
927 strcpy(dip
->un
.e
.member
[0].label
.name
, CmpciNpositive
);
928 dip
->un
.e
.member
[0].ord
= CMPCI_SPDIF_IN_PHASE_POSITIVE
;
929 strcpy(dip
->un
.e
.member
[1].label
.name
, CmpciNnegative
);
930 dip
->un
.e
.member
[1].ord
= CMPCI_SPDIF_IN_PHASE_NEGATIVE
;
932 case CMPCI_SPDIF_LOOP
:
933 dip
->mixer_class
= CMPCI_SPDIF_CLASS
;
934 dip
->next
= CMPCI_SPDIF_OUT_PLAYBACK
;
935 strcpy(dip
->label
.name
, AudioNoutput
);
936 dip
->type
= AUDIO_MIXER_ENUM
;
937 dip
->un
.e
.num_mem
= 2;
938 strcpy(dip
->un
.e
.member
[0].label
.name
, CmpciNplayback
);
939 dip
->un
.e
.member
[0].ord
= CMPCI_SPDIF_LOOP_OFF
;
940 strcpy(dip
->un
.e
.member
[1].label
.name
, CmpciNspdin
);
941 dip
->un
.e
.member
[1].ord
= CMPCI_SPDIF_LOOP_ON
;
943 case CMPCI_SPDIF_OUT_PLAYBACK
:
944 dip
->mixer_class
= CMPCI_SPDIF_CLASS
;
945 dip
->prev
= CMPCI_SPDIF_LOOP
;
946 dip
->next
= CMPCI_SPDIF_OUT_VOLTAGE
;
947 strcpy(dip
->label
.name
, CmpciNplayback
);
948 dip
->type
= AUDIO_MIXER_ENUM
;
949 dip
->un
.e
.num_mem
= 2;
950 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNwave
);
951 dip
->un
.e
.member
[0].ord
= CMPCI_SPDIF_OUT_PLAYBACK_WAVE
;
952 strcpy(dip
->un
.e
.member
[1].label
.name
, CmpciNlegacy
);
953 dip
->un
.e
.member
[1].ord
= CMPCI_SPDIF_OUT_PLAYBACK_LEGACY
;
955 case CMPCI_SPDIF_OUT_VOLTAGE
:
956 dip
->mixer_class
= CMPCI_SPDIF_CLASS
;
957 dip
->prev
= CMPCI_SPDIF_OUT_PLAYBACK
;
958 strcpy(dip
->label
.name
, CmpciNvoltage
);
959 dip
->type
= AUDIO_MIXER_ENUM
;
960 dip
->un
.e
.num_mem
= 2;
961 strcpy(dip
->un
.e
.member
[0].label
.name
, CmpciNhigh_v
);
962 dip
->un
.e
.member
[0].ord
= CMPCI_SPDIF_OUT_VOLTAGE_HIGH
;
963 strcpy(dip
->un
.e
.member
[1].label
.name
, CmpciNlow_v
);
964 dip
->un
.e
.member
[1].ord
= CMPCI_SPDIF_OUT_VOLTAGE_LOW
;
966 case CMPCI_MONITOR_DAC
:
967 dip
->mixer_class
= CMPCI_SPDIF_CLASS
;
968 strcpy(dip
->label
.name
, AudioNmonitor
);
969 dip
->type
= AUDIO_MIXER_ENUM
;
970 dip
->un
.e
.num_mem
= 3;
971 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
972 dip
->un
.e
.member
[0].ord
= CMPCI_MONITOR_DAC_OFF
;
973 strcpy(dip
->un
.e
.member
[1].label
.name
, CmpciNspdin
);
974 dip
->un
.e
.member
[1].ord
= CMPCI_MONITOR_DAC_SPDIN
;
975 strcpy(dip
->un
.e
.member
[2].label
.name
, CmpciNspdout
);
976 dip
->un
.e
.member
[2].ord
= CMPCI_MONITOR_DAC_SPDOUT
;
979 case CMPCI_MASTER_VOL
:
980 dip
->mixer_class
= CMPCI_OUTPUT_CLASS
;
981 strcpy(dip
->label
.name
, AudioNmaster
);
982 dip
->un
.v
.num_channels
= 2;
983 dip
->un
.v
.delta
= 1 << (8 - CMPCI_SB16_MIXER_VALBITS
);
986 dip
->mixer_class
= CMPCI_OUTPUT_CLASS
;
987 dip
->next
= CMPCI_INDIVIDUAL
;
988 strcpy(dip
->label
.name
, CmpciNrear
);
990 case CMPCI_INDIVIDUAL
:
991 dip
->mixer_class
= CMPCI_OUTPUT_CLASS
;
992 dip
->prev
= CMPCI_REAR
;
993 dip
->next
= CMPCI_REVERSE
;
994 strcpy(dip
->label
.name
, CmpciNindividual
);
997 dip
->mixer_class
= CMPCI_OUTPUT_CLASS
;
998 dip
->prev
= CMPCI_INDIVIDUAL
;
999 strcpy(dip
->label
.name
, CmpciNreverse
);
1001 case CMPCI_SURROUND
:
1002 dip
->mixer_class
= CMPCI_OUTPUT_CLASS
;
1003 strcpy(dip
->label
.name
, CmpciNsurround
);
1011 cmpci_alloc_dmamem(struct cmpci_softc
*sc
, size_t size
, struct malloc_type
*type
,
1012 int flags
, void **r_addr
)
1015 struct cmpci_dmanode
*n
;
1019 n
= malloc(sizeof(struct cmpci_dmanode
), type
, flags
);
1025 w
= (flags
& M_NOWAIT
) ? BUS_DMA_NOWAIT
: BUS_DMA_WAITOK
;
1026 #define CMPCI_DMABUF_ALIGN 0x4
1027 #define CMPCI_DMABUF_BOUNDARY 0x0
1028 n
->cd_tag
= sc
->sc_dmat
;
1030 error
= bus_dmamem_alloc(n
->cd_tag
, n
->cd_size
,
1031 CMPCI_DMABUF_ALIGN
, CMPCI_DMABUF_BOUNDARY
, n
->cd_segs
,
1032 sizeof(n
->cd_segs
)/sizeof(n
->cd_segs
[0]), &n
->cd_nsegs
, w
);
1035 error
= bus_dmamem_map(n
->cd_tag
, n
->cd_segs
, n
->cd_nsegs
, n
->cd_size
,
1036 &n
->cd_addr
, w
| BUS_DMA_COHERENT
);
1039 error
= bus_dmamap_create(n
->cd_tag
, n
->cd_size
, 1, n
->cd_size
, 0,
1043 error
= bus_dmamap_load(n
->cd_tag
, n
->cd_map
, n
->cd_addr
, n
->cd_size
,
1048 n
->cd_next
= sc
->sc_dmap
;
1050 *r_addr
= KVADDR(n
);
1054 bus_dmamap_destroy(n
->cd_tag
, n
->cd_map
);
1056 bus_dmamem_unmap(n
->cd_tag
, n
->cd_addr
, n
->cd_size
);
1058 bus_dmamem_free(n
->cd_tag
,
1059 n
->cd_segs
, sizeof(n
->cd_segs
)/sizeof(n
->cd_segs
[0]));
1067 cmpci_free_dmamem(struct cmpci_softc
*sc
, void *addr
, struct malloc_type
*type
)
1069 struct cmpci_dmanode
**nnp
;
1071 for (nnp
= &sc
->sc_dmap
; *nnp
; nnp
= &(*nnp
)->cd_next
) {
1072 if ((*nnp
)->cd_addr
== addr
) {
1073 struct cmpci_dmanode
*n
= *nnp
;
1074 bus_dmamap_unload(n
->cd_tag
, n
->cd_map
);
1075 bus_dmamap_destroy(n
->cd_tag
, n
->cd_map
);
1076 bus_dmamem_unmap(n
->cd_tag
, n
->cd_addr
, n
->cd_size
);
1077 bus_dmamem_free(n
->cd_tag
, n
->cd_segs
,
1078 sizeof(n
->cd_segs
)/sizeof(n
->cd_segs
[0]));
1086 static struct cmpci_dmanode
*
1087 cmpci_find_dmamem(struct cmpci_softc
*sc
, void *addr
)
1089 struct cmpci_dmanode
*p
;
1091 for (p
= sc
->sc_dmap
; p
; p
= p
->cd_next
)
1092 if (KVADDR(p
) == (void *)addr
)
1099 cmpci_print_dmamem(struct cmpci_dmanode
*);
1101 cmpci_print_dmamem(struct cmpci_dmanode
*p
)
1104 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1105 (void *)p
->cd_addr
, (void *)p
->cd_segs
[0].ds_addr
,
1106 (void *)DMAADDR(p
), (void *)p
->cd_size
));
1111 cmpci_allocm(void *handle
, int direction
, size_t size
,
1112 struct malloc_type
*type
, int flags
)
1116 addr
= NULL
; /* XXX gcc */
1118 if (cmpci_alloc_dmamem(handle
, size
, type
, flags
, &addr
))
1124 cmpci_freem(void *handle
, void *addr
, struct malloc_type
*type
)
1127 cmpci_free_dmamem(handle
, addr
, type
);
1132 cmpci_adjust(int val
, int mask
)
1135 val
+= (MAXVAL
- mask
) >> 1;
1142 cmpci_set_mixer_gain(struct cmpci_softc
*sc
, int port
)
1149 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_MIC
,
1150 CMPCI_ADJUST_MIC_GAIN(sc
, sc
->sc_gain
[port
][CMPCI_LR
]));
1152 case CMPCI_MASTER_VOL
:
1153 src
= CMPCI_SB16_MIXER_MASTER_L
;
1155 case CMPCI_LINE_IN_VOL
:
1156 src
= CMPCI_SB16_MIXER_LINE_L
;
1158 case CMPCI_AUX_IN_VOL
:
1159 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_MIXER_AUX
,
1160 CMPCI_ADJUST_AUX_GAIN(sc
, sc
->sc_gain
[port
][CMPCI_LEFT
],
1161 sc
->sc_gain
[port
][CMPCI_RIGHT
]));
1163 case CMPCI_MIC_RECVOL
:
1164 cmpci_reg_partial_write_1(sc
, CMPCI_REG_MIXER25
,
1165 CMPCI_REG_ADMIC_SHIFT
, CMPCI_REG_ADMIC_MASK
,
1166 CMPCI_ADJUST_ADMIC_GAIN(sc
, sc
->sc_gain
[port
][CMPCI_LR
]));
1169 src
= CMPCI_SB16_MIXER_VOICE_L
;
1172 src
= CMPCI_SB16_MIXER_FM_L
;
1175 src
= CMPCI_SB16_MIXER_CDDA_L
;
1177 case CMPCI_PCSPEAKER
:
1178 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_SPEAKER
,
1179 CMPCI_ADJUST_2_GAIN(sc
, sc
->sc_gain
[port
][CMPCI_LR
]));
1181 case CMPCI_MIC_PREAMP
:
1182 if (sc
->sc_gain
[port
][CMPCI_LR
])
1183 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER25
,
1184 CMPCI_REG_MICGAINZ
);
1186 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER25
,
1187 CMPCI_REG_MICGAINZ
);
1190 case CMPCI_DAC_MUTE
:
1191 if (sc
->sc_gain
[port
][CMPCI_LR
])
1192 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1195 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1199 if (sc
->sc_gain
[port
][CMPCI_LR
])
1200 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1203 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1206 case CMPCI_AUX_IN_MUTE
:
1207 if (sc
->sc_gain
[port
][CMPCI_LR
])
1208 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER25
,
1209 CMPCI_REG_VAUXRM
|CMPCI_REG_VAUXLM
);
1211 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER25
,
1212 CMPCI_REG_VAUXRM
|CMPCI_REG_VAUXLM
);
1215 mask
= CMPCI_SB16_SW_CD
;
1217 case CMPCI_MIC_MUTE
:
1218 mask
= CMPCI_SB16_SW_MIC
;
1220 case CMPCI_LINE_IN_MUTE
:
1221 mask
= CMPCI_SB16_SW_LINE
;
1223 bits
= cmpci_mixerreg_read(sc
, CMPCI_SB16_MIXER_OUTMIX
);
1224 if (sc
->sc_gain
[port
][CMPCI_LR
])
1225 bits
= bits
& ~mask
;
1228 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_OUTMIX
, bits
);
1231 case CMPCI_SPDIF_IN_SELECT
:
1232 case CMPCI_MONITOR_DAC
:
1233 case CMPCI_PLAYBACK_MODE
:
1234 case CMPCI_SPDIF_LOOP
:
1235 case CMPCI_SPDIF_OUT_PLAYBACK
:
1236 cmpci_set_out_ports(sc
);
1238 case CMPCI_SPDIF_OUT_VOLTAGE
:
1239 if (CMPCI_ISCAP(sc
, SPDOUT_VOLTAGE
)) {
1240 if (sc
->sc_gain
[CMPCI_SPDIF_OUT_VOLTAGE
][CMPCI_LR
]
1241 == CMPCI_SPDIF_OUT_VOLTAGE_HIGH
)
1242 cmpci_reg_clear_reg_misc(sc
, CMPCI_REG_5V
);
1244 cmpci_reg_set_reg_misc(sc
, CMPCI_REG_5V
);
1247 case CMPCI_SURROUND
:
1248 if (CMPCI_ISCAP(sc
, SURROUND
)) {
1249 if (sc
->sc_gain
[CMPCI_SURROUND
][CMPCI_LR
])
1250 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1251 CMPCI_REG_SURROUND
);
1253 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1254 CMPCI_REG_SURROUND
);
1258 if (CMPCI_ISCAP(sc
, REAR
)) {
1259 if (sc
->sc_gain
[CMPCI_REAR
][CMPCI_LR
])
1260 cmpci_reg_set_reg_misc(sc
, CMPCI_REG_N4SPK3D
);
1262 cmpci_reg_clear_reg_misc(sc
, CMPCI_REG_N4SPK3D
);
1265 case CMPCI_INDIVIDUAL
:
1266 if (CMPCI_ISCAP(sc
, INDIVIDUAL_REAR
)) {
1267 if (sc
->sc_gain
[CMPCI_REAR
][CMPCI_LR
])
1268 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1269 CMPCI_REG_INDIVIDUAL
);
1271 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1272 CMPCI_REG_INDIVIDUAL
);
1276 if (CMPCI_ISCAP(sc
, REVERSE_FR
)) {
1277 if (sc
->sc_gain
[CMPCI_REVERSE
][CMPCI_LR
])
1278 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1279 CMPCI_REG_REVERSE_FR
);
1281 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1282 CMPCI_REG_REVERSE_FR
);
1285 case CMPCI_SPDIF_IN_PHASE
:
1286 if (CMPCI_ISCAP(sc
, SPDIN_PHASE
)) {
1287 if (sc
->sc_gain
[CMPCI_SPDIF_IN_PHASE
][CMPCI_LR
]
1288 == CMPCI_SPDIF_IN_PHASE_POSITIVE
)
1289 cmpci_reg_clear_1(sc
, CMPCI_REG_CHANNEL_FORMAT
,
1290 CMPCI_REG_SPDIN_PHASE
);
1292 cmpci_reg_set_1(sc
, CMPCI_REG_CHANNEL_FORMAT
,
1293 CMPCI_REG_SPDIN_PHASE
);
1300 cmpci_mixerreg_write(sc
, src
,
1301 CMPCI_ADJUST_GAIN(sc
, sc
->sc_gain
[port
][CMPCI_LEFT
]));
1302 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_L_TO_R(src
),
1303 CMPCI_ADJUST_GAIN(sc
, sc
->sc_gain
[port
][CMPCI_RIGHT
]));
1307 cmpci_set_out_ports(struct cmpci_softc
*sc
)
1312 if (!CMPCI_ISCAP(sc
, SPDLOOP
))
1315 /* SPDIF/out select */
1316 if (sc
->sc_gain
[CMPCI_SPDIF_LOOP
][CMPCI_LR
] == CMPCI_SPDIF_LOOP_OFF
) {
1318 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_1
, CMPCI_REG_SPDIF_LOOP
);
1320 /* monitor SPDIF/in */
1321 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_1
, CMPCI_REG_SPDIF_LOOP
);
1324 /* SPDIF in select */
1325 v
= sc
->sc_gain
[CMPCI_SPDIF_IN_SELECT
][CMPCI_LR
];
1326 if (v
& CMPCI_SPDIFIN_SPDIFIN2
)
1327 cmpci_reg_set_reg_misc(sc
, CMPCI_REG_2ND_SPDIFIN
);
1329 cmpci_reg_clear_reg_misc(sc
, CMPCI_REG_2ND_SPDIFIN
);
1330 if (v
& CMPCI_SPDIFIN_SPDIFOUT
)
1331 cmpci_reg_set_reg_misc(sc
, CMPCI_REG_SPDFLOOPI
);
1333 cmpci_reg_clear_reg_misc(sc
, CMPCI_REG_SPDFLOOPI
);
1336 /* playback to ... */
1337 if (CMPCI_ISCAP(sc
, SPDOUT
) &&
1338 sc
->sc_gain
[CMPCI_PLAYBACK_MODE
][CMPCI_LR
]
1339 == CMPCI_PLAYBACK_MODE_SPDIF
&&
1340 (sc
->sc_play
.md_divide
== CMPCI_REG_RATE_44100
||
1341 (CMPCI_ISCAP(sc
, SPDOUT_48K
) &&
1342 sc
->sc_play
.md_divide
==CMPCI_REG_RATE_48000
))) {
1343 /* playback to SPDIF */
1344 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_1
, CMPCI_REG_SPDIF0_ENABLE
);
1346 if (sc
->sc_play
.md_divide
==CMPCI_REG_RATE_48000
)
1347 cmpci_reg_set_reg_misc(sc
,
1348 CMPCI_REG_SPDIFOUT_48K
| CMPCI_REG_SPDIF48K
);
1350 cmpci_reg_clear_reg_misc(sc
,
1351 CMPCI_REG_SPDIFOUT_48K
| CMPCI_REG_SPDIF48K
);
1353 /* playback to DAC */
1354 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_1
,
1355 CMPCI_REG_SPDIF0_ENABLE
);
1356 if (CMPCI_ISCAP(sc
, SPDOUT_48K
))
1357 cmpci_reg_clear_reg_misc(sc
,
1358 CMPCI_REG_SPDIFOUT_48K
| CMPCI_REG_SPDIF48K
);
1361 /* legacy to SPDIF/out or not */
1362 if (CMPCI_ISCAP(sc
, SPDLEGACY
)) {
1363 if (sc
->sc_gain
[CMPCI_SPDIF_OUT_PLAYBACK
][CMPCI_LR
]
1364 == CMPCI_SPDIF_OUT_PLAYBACK_WAVE
)
1365 cmpci_reg_clear_4(sc
, CMPCI_REG_LEGACY_CTRL
,
1366 CMPCI_REG_LEGACY_SPDIF_ENABLE
);
1368 cmpci_reg_set_4(sc
, CMPCI_REG_LEGACY_CTRL
,
1369 CMPCI_REG_LEGACY_SPDIF_ENABLE
);
1374 /* enable/disable SPDIF/out */
1375 if (CMPCI_ISCAP(sc
, XSPDOUT
) && enspdout
)
1376 cmpci_reg_set_4(sc
, CMPCI_REG_LEGACY_CTRL
,
1377 CMPCI_REG_XSPDIF_ENABLE
);
1379 cmpci_reg_clear_4(sc
, CMPCI_REG_LEGACY_CTRL
,
1380 CMPCI_REG_XSPDIF_ENABLE
);
1382 /* SPDIF monitor (digital to analog output) */
1383 if (CMPCI_ISCAP(sc
, SPDIN_MONITOR
)) {
1384 v
= sc
->sc_gain
[CMPCI_MONITOR_DAC
][CMPCI_LR
];
1385 if (!(v
& CMPCI_MONDAC_ENABLE
))
1386 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1387 CMPCI_REG_SPDIN_MONITOR
);
1388 if (v
& CMPCI_MONDAC_SPDOUT
)
1389 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_1
,
1390 CMPCI_REG_SPDIFOUT_DAC
);
1392 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_1
,
1393 CMPCI_REG_SPDIFOUT_DAC
);
1394 if (v
& CMPCI_MONDAC_ENABLE
)
1395 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1396 CMPCI_REG_SPDIN_MONITOR
);
1401 cmpci_set_in_ports(struct cmpci_softc
*sc
)
1406 mask
= sc
->sc_in_mask
;
1409 * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and
1410 * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit
1411 * of the mixer register.
1413 bitsr
= mask
& (CMPCI_RECORD_SOURCE_CD
| CMPCI_RECORD_SOURCE_LINE_IN
|
1414 CMPCI_RECORD_SOURCE_FM
);
1416 bitsl
= CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr
);
1417 if (mask
& CMPCI_RECORD_SOURCE_MIC
) {
1418 bitsl
|= CMPCI_SB16_MIXER_MIC_SRC
;
1419 bitsr
|= CMPCI_SB16_MIXER_MIC_SRC
;
1421 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_ADCMIX_L
, bitsl
);
1422 cmpci_mixerreg_write(sc
, CMPCI_SB16_MIXER_ADCMIX_R
, bitsr
);
1424 if (mask
& CMPCI_RECORD_SOURCE_AUX_IN
)
1425 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER25
,
1426 CMPCI_REG_RAUXREN
| CMPCI_REG_RAUXLEN
);
1428 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER25
,
1429 CMPCI_REG_RAUXREN
| CMPCI_REG_RAUXLEN
);
1431 if (mask
& CMPCI_RECORD_SOURCE_WAVE
)
1432 cmpci_reg_set_1(sc
, CMPCI_REG_MIXER24
,
1433 CMPCI_REG_WAVEINL
| CMPCI_REG_WAVEINR
);
1435 cmpci_reg_clear_1(sc
, CMPCI_REG_MIXER24
,
1436 CMPCI_REG_WAVEINL
| CMPCI_REG_WAVEINR
);
1438 if (CMPCI_ISCAP(sc
, SPDIN
) &&
1439 (sc
->sc_rec
.md_divide
== CMPCI_REG_RATE_44100
||
1440 (CMPCI_ISCAP(sc
, SPDOUT_48K
) &&
1441 sc
->sc_rec
.md_divide
== CMPCI_REG_RATE_48000
/* XXX? */))) {
1442 if (mask
& CMPCI_RECORD_SOURCE_SPDIF
) {
1443 /* enable SPDIF/in */
1446 CMPCI_REG_SPDIF1_ENABLE
);
1448 cmpci_reg_clear_4(sc
,
1450 CMPCI_REG_SPDIF1_ENABLE
);
1458 cmpci_set_port(void *handle
, mixer_ctrl_t
*cp
)
1460 struct cmpci_softc
*sc
;
1466 case CMPCI_PCSPEAKER
:
1467 case CMPCI_MIC_RECVOL
:
1468 if (cp
->un
.value
.num_channels
!= 1)
1474 case CMPCI_LINE_IN_VOL
:
1475 case CMPCI_AUX_IN_VOL
:
1476 case CMPCI_MASTER_VOL
:
1477 if (cp
->type
!= AUDIO_MIXER_VALUE
)
1479 switch (cp
->un
.value
.num_channels
) {
1482 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
];
1485 lgain
= cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
];
1486 rgain
= cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
];
1491 sc
->sc_gain
[cp
->dev
][CMPCI_LEFT
] = lgain
;
1492 sc
->sc_gain
[cp
->dev
][CMPCI_RIGHT
] = rgain
;
1494 cmpci_set_mixer_gain(sc
, cp
->dev
);
1497 case CMPCI_RECORD_SOURCE
:
1498 if (cp
->type
!= AUDIO_MIXER_SET
)
1501 if (cp
->un
.mask
& ~(CMPCI_RECORD_SOURCE_MIC
|
1502 CMPCI_RECORD_SOURCE_CD
| CMPCI_RECORD_SOURCE_LINE_IN
|
1503 CMPCI_RECORD_SOURCE_AUX_IN
| CMPCI_RECORD_SOURCE_WAVE
|
1504 CMPCI_RECORD_SOURCE_FM
| CMPCI_RECORD_SOURCE_SPDIF
))
1507 if (cp
->un
.mask
& CMPCI_RECORD_SOURCE_SPDIF
)
1508 cp
->un
.mask
= CMPCI_RECORD_SOURCE_SPDIF
;
1510 sc
->sc_in_mask
= cp
->un
.mask
;
1511 return cmpci_set_in_ports(sc
);
1514 case CMPCI_DAC_MUTE
:
1517 case CMPCI_LINE_IN_MUTE
:
1518 case CMPCI_AUX_IN_MUTE
:
1519 case CMPCI_MIC_MUTE
:
1520 case CMPCI_MIC_PREAMP
:
1521 case CMPCI_PLAYBACK_MODE
:
1522 case CMPCI_SPDIF_IN_PHASE
:
1523 case CMPCI_SPDIF_LOOP
:
1524 case CMPCI_SPDIF_OUT_PLAYBACK
:
1525 case CMPCI_SPDIF_OUT_VOLTAGE
:
1527 case CMPCI_INDIVIDUAL
:
1529 case CMPCI_SURROUND
:
1530 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1532 sc
->sc_gain
[cp
->dev
][CMPCI_LR
] = cp
->un
.ord
!= 0;
1533 cmpci_set_mixer_gain(sc
, cp
->dev
);
1536 case CMPCI_SPDIF_IN_SELECT
:
1537 switch (cp
->un
.ord
) {
1538 case CMPCI_SPDIF_IN_SPDIN1
:
1539 case CMPCI_SPDIF_IN_SPDIN2
:
1540 case CMPCI_SPDIF_IN_SPDOUT
:
1546 case CMPCI_MONITOR_DAC
:
1547 switch (cp
->un
.ord
) {
1548 case CMPCI_MONITOR_DAC_OFF
:
1549 case CMPCI_MONITOR_DAC_SPDIN
:
1550 case CMPCI_MONITOR_DAC_SPDOUT
:
1556 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1558 sc
->sc_gain
[cp
->dev
][CMPCI_LR
] = cp
->un
.ord
;
1559 cmpci_set_mixer_gain(sc
, cp
->dev
);
1570 cmpci_get_port(void *handle
, mixer_ctrl_t
*cp
)
1572 struct cmpci_softc
*sc
;
1577 case CMPCI_PCSPEAKER
:
1578 case CMPCI_MIC_RECVOL
:
1579 if (cp
->un
.value
.num_channels
!= 1)
1585 case CMPCI_LINE_IN_VOL
:
1586 case CMPCI_AUX_IN_VOL
:
1587 case CMPCI_MASTER_VOL
:
1588 switch (cp
->un
.value
.num_channels
) {
1590 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] =
1591 sc
->sc_gain
[cp
->dev
][CMPCI_LEFT
];
1594 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] =
1595 sc
->sc_gain
[cp
->dev
][CMPCI_LEFT
];
1596 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] =
1597 sc
->sc_gain
[cp
->dev
][CMPCI_RIGHT
];
1604 case CMPCI_RECORD_SOURCE
:
1605 cp
->un
.mask
= sc
->sc_in_mask
;
1608 case CMPCI_DAC_MUTE
:
1611 case CMPCI_LINE_IN_MUTE
:
1612 case CMPCI_AUX_IN_MUTE
:
1613 case CMPCI_MIC_MUTE
:
1614 case CMPCI_MIC_PREAMP
:
1615 case CMPCI_PLAYBACK_MODE
:
1616 case CMPCI_SPDIF_IN_SELECT
:
1617 case CMPCI_SPDIF_IN_PHASE
:
1618 case CMPCI_SPDIF_LOOP
:
1619 case CMPCI_SPDIF_OUT_PLAYBACK
:
1620 case CMPCI_SPDIF_OUT_VOLTAGE
:
1621 case CMPCI_MONITOR_DAC
:
1623 case CMPCI_INDIVIDUAL
:
1625 case CMPCI_SURROUND
:
1626 cp
->un
.ord
= sc
->sc_gain
[cp
->dev
][CMPCI_LR
];
1638 cmpci_round_buffersize(void *handle
, int direction
,
1642 if (bufsize
> 0x10000)
1649 cmpci_mappage(void *handle
, void *addr
, off_t offset
, int prot
)
1651 struct cmpci_dmanode
*p
;
1653 if (offset
< 0 || NULL
== (p
= cmpci_find_dmamem(handle
, addr
)))
1656 return bus_dmamem_mmap(p
->cd_tag
, p
->cd_segs
,
1657 sizeof(p
->cd_segs
)/sizeof(p
->cd_segs
[0]),
1658 offset
, prot
, BUS_DMA_WAITOK
);
1663 cmpci_get_props(void *handle
)
1666 return AUDIO_PROP_MMAP
| AUDIO_PROP_INDEPENDENT
| AUDIO_PROP_FULLDUPLEX
;
1670 cmpci_trigger_output(void *handle
, void *start
, void *end
, int blksize
,
1671 void (*intr
)(void *), void *arg
,
1672 const audio_params_t
*param
)
1674 struct cmpci_softc
*sc
;
1675 struct cmpci_dmanode
*p
;
1679 sc
->sc_play
.intr
= intr
;
1680 sc
->sc_play
.intr_arg
= arg
;
1681 bps
= param
->channels
* param
->precision
/ 8;
1686 if (!(p
= cmpci_find_dmamem(sc
, start
)))
1688 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_DMA0_BASE
,
1691 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_DMA0_BYTES
,
1692 ((char *)end
- (char *)start
+ 1) / bps
- 1);
1695 /* set interrupt count */
1696 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_DMA0_SAMPLES
,
1697 (blksize
+ bps
- 1) / bps
- 1);
1701 cmpci_reg_clear_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_DIR
); /* PLAY */
1702 cmpci_reg_set_4(sc
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH0_INTR_ENABLE
);
1703 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH0_ENABLE
);
1709 cmpci_trigger_input(void *handle
, void *start
, void *end
, int blksize
,
1710 void (*intr
)(void *), void *arg
,
1711 const audio_params_t
*param
)
1713 struct cmpci_softc
*sc
;
1714 struct cmpci_dmanode
*p
;
1718 sc
->sc_rec
.intr
= intr
;
1719 sc
->sc_rec
.intr_arg
= arg
;
1720 bps
= param
->channels
* param
->precision
/ 8;
1725 if (!(p
=cmpci_find_dmamem(sc
, start
)))
1727 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_DMA1_BASE
,
1730 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_DMA1_BYTES
,
1731 ((char *)end
- (char *)start
+ 1) / bps
- 1);
1734 /* set interrupt count */
1735 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, CMPCI_REG_DMA1_SAMPLES
,
1736 (blksize
+ bps
- 1) / bps
- 1);
1740 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_DIR
); /* REC */
1741 cmpci_reg_set_4(sc
, CMPCI_REG_INTR_CTRL
, CMPCI_REG_CH1_INTR_ENABLE
);
1742 cmpci_reg_set_4(sc
, CMPCI_REG_FUNC_0
, CMPCI_REG_CH1_ENABLE
);