cmpci.c revision 1.7.2.2 1 /* $NetBSD: cmpci.c,v 1.7.2.2 2001/10/08 20:11:10 nathanw Exp $ */
2
3 /*
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Takuya SHIOZAKI <tshiozak (at) netbsd.org> .
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
33 /*
34 * C-Media CMI8x38 Audio Chip Support.
35 *
36 * TODO:
37 * - Legacy MPU, OPL and Joystick support.
38 *
39 */
40
41 #if defined(AUDIO_DEBUG) || defined(DEBUG)
42 #define DPRINTF(x) if (cmpcidebug) printf x
43 int cmpcidebug = 0;
44 #else
45 #define DPRINTF(x)
46 #endif
47
48 #include "mpu.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/malloc.h>
54 #include <sys/device.h>
55 #include <sys/proc.h>
56
57 #include <dev/pci/pcidevs.h>
58 #include <dev/pci/pcivar.h>
59
60 #include <sys/audioio.h>
61 #include <dev/audio_if.h>
62 #include <dev/midi_if.h>
63
64 #include <dev/mulaw.h>
65 #include <dev/auconv.h>
66 #include <dev/pci/cmpcireg.h>
67 #include <dev/pci/cmpcivar.h>
68
69 #include <dev/ic/mpuvar.h>
70 #include <machine/bus.h>
71 #include <machine/intr.h>
72
73 /*
74 * Low-level HW interface
75 */
76 static __inline uint8_t cmpci_mixerreg_read __P((struct cmpci_softc *,
77 uint8_t));
78 static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *,
79 uint8_t, uint8_t));
80 static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *,
81 int, int,
82 uint32_t, uint32_t));
83 static __inline void cmpci_reg_set_1 __P((struct cmpci_softc *,
84 int, uint8_t));
85 static __inline void cmpci_reg_clear_1 __P((struct cmpci_softc *,
86 int, uint8_t));
87 static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *,
88 int, uint32_t));
89 static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *,
90 int, uint32_t));
91 static int cmpci_rate_to_index __P((int));
92 static __inline int cmpci_index_to_rate __P((int));
93 static __inline int cmpci_index_to_divider __P((int));
94
95 static int cmpci_adjust __P((int, int));
96 static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int));
97 static void cmpci_set_out_ports __P((struct cmpci_softc *));
98 static int cmpci_set_in_ports __P((struct cmpci_softc *, int));
99
100
101 /*
102 * autoconf interface
103 */
104 static int cmpci_match __P((struct device *, struct cfdata *, void *));
105 static void cmpci_attach __P((struct device *, struct device *, void *));
106
107 struct cfattach cmpci_ca = {
108 sizeof (struct cmpci_softc), cmpci_match, cmpci_attach
109 };
110
111 /* interrupt */
112 static int cmpci_intr __P((void *));
113
114
115 /*
116 * DMA stuffs
117 */
118 static int cmpci_alloc_dmamem __P((struct cmpci_softc *,
119 size_t, int, int, caddr_t *));
120 static int cmpci_free_dmamem __P((struct cmpci_softc *, caddr_t, int));
121 static struct cmpci_dmanode * cmpci_find_dmamem __P((struct cmpci_softc *,
122 caddr_t));
123
124
125 /*
126 * interface to machine independent layer
127 */
128 static int cmpci_open __P((void *, int));
129 static void cmpci_close __P((void *));
130 static int cmpci_query_encoding __P((void *, struct audio_encoding *));
131 static int cmpci_set_params __P((void *, int, int,
132 struct audio_params *,
133 struct audio_params *));
134 static int cmpci_round_blocksize __P((void *, int));
135 static int cmpci_halt_output __P((void *));
136 static int cmpci_halt_input __P((void *));
137 static int cmpci_getdev __P((void *, struct audio_device *));
138 static int cmpci_set_port __P((void *, mixer_ctrl_t *));
139 static int cmpci_get_port __P((void *, mixer_ctrl_t *));
140 static int cmpci_query_devinfo __P((void *, mixer_devinfo_t *));
141 static void *cmpci_allocm __P((void *, int, size_t, int, int));
142 static void cmpci_freem __P((void *, void *, int));
143 static size_t cmpci_round_buffersize __P((void *, int, size_t));
144 static paddr_t cmpci_mappage __P((void *, void *, off_t, int));
145 static int cmpci_get_props __P((void *));
146 static int cmpci_trigger_output __P((void *, void *, void *, int,
147 void (*)(void *), void *,
148 struct audio_params *));
149 static int cmpci_trigger_input __P((void *, void *, void *, int,
150 void (*)(void *), void *,
151 struct audio_params *));
152
153 static struct audio_hw_if cmpci_hw_if = {
154 cmpci_open, /* open */
155 cmpci_close, /* close */
156 NULL, /* drain */
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 */
169 NULL, /* setfd */
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 };
182
183
184 /*
185 * Low-level HW interface
186 */
187
188 /* mixer register read/write */
189 static __inline uint8_t
190 cmpci_mixerreg_read(sc, no)
191 struct cmpci_softc *sc;
192 uint8_t no;
193 {
194 uint8_t ret;
195
196 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
197 delay(10);
198 ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
199 delay(10);
200 return ret;
201 }
202
203 static __inline void
204 cmpci_mixerreg_write(sc, no, val)
205 struct cmpci_softc *sc;
206 uint8_t no, val;
207 {
208 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
209 delay(10);
210 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
211 delay(10);
212 }
213
214
215 /* register partial write */
216 static __inline void
217 cmpci_reg_partial_write_4(sc, no, shift, mask, val)
218 struct cmpci_softc *sc;
219 int no, shift;
220 uint32_t mask, val;
221 {
222 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
223 (val<<shift) |
224 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
225 delay(10);
226 }
227
228 /* register set/clear bit */
229 static __inline void
230 cmpci_reg_set_1(sc, no, mask)
231 struct cmpci_softc *sc;
232 int no;
233 uint8_t mask;
234 {
235 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
236 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
237 delay(10);
238 }
239
240 static __inline void
241 cmpci_reg_clear_1(sc, no, mask)
242 struct cmpci_softc *sc;
243 int no;
244 uint8_t mask;
245 {
246 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
247 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
248 delay(10);
249 }
250
251
252 static __inline void
253 cmpci_reg_set_4(sc, no, mask)
254 struct cmpci_softc *sc;
255 int no;
256 uint32_t mask;
257 {
258 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
259 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
260 delay(10);
261 }
262
263 static __inline void
264 cmpci_reg_clear_4(sc, no, mask)
265 struct cmpci_softc *sc;
266 int no;
267 uint32_t mask;
268 {
269 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
270 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
271 delay(10);
272 }
273
274
275 /* rate */
276 static const struct {
277 int rate;
278 int divider;
279 } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
280 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
281 _RATE(5512),
282 _RATE(8000),
283 _RATE(11025),
284 _RATE(16000),
285 _RATE(22050),
286 _RATE(32000),
287 _RATE(44100),
288 _RATE(48000)
289 #undef _RATE
290 };
291
292 static int
293 cmpci_rate_to_index(rate)
294 int rate;
295 {
296 int i;
297
298 for (i = 0; i < CMPCI_REG_NUMRATE - 2; i++)
299 if (rate <=
300 (cmpci_rate_table[i].rate+cmpci_rate_table[i+1].rate) / 2)
301 return i;
302 return i; /* 48000 */
303 }
304
305 static __inline int
306 cmpci_index_to_rate(index)
307 int index;
308 {
309 return cmpci_rate_table[index].rate;
310 }
311
312 static __inline int
313 cmpci_index_to_divider(index)
314 int index;
315 {
316 return cmpci_rate_table[index].divider;
317 }
318
319
320 /*
321 * interface to configure the device.
322 */
323
324 static int
325 cmpci_match(parent, match, aux)
326 struct device *parent;
327 struct cfdata *match;
328 void *aux;
329 {
330 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
331
332 if ( PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMEDIA &&
333 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338A ||
334 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338B ||
335 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738 ||
336 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738B) )
337 return 1;
338
339 return 0;
340 }
341
342 static void
343 cmpci_attach(parent, self, aux)
344 struct device *parent, *self;
345 void *aux;
346 {
347 struct cmpci_softc *sc = (struct cmpci_softc *)self;
348 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
349 struct audio_attach_args aa;
350 pci_intr_handle_t ih;
351 char const *strintr;
352 char devinfo[256];
353 int i, v;
354
355 sc->sc_id = pa->pa_id;
356 sc->sc_class = pa->pa_class;
357 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
358 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(sc->sc_class));
359 switch (PCI_PRODUCT(sc->sc_id)) {
360 case PCI_PRODUCT_CMEDIA_CMI8338A:
361 /*FALLTHROUGH*/
362 case PCI_PRODUCT_CMEDIA_CMI8338B:
363 sc->sc_capable = CMPCI_CAP_CMI8338;
364 break;
365 case PCI_PRODUCT_CMEDIA_CMI8738:
366 /*FALLTHROUGH*/
367 case PCI_PRODUCT_CMEDIA_CMI8738B:
368 sc->sc_capable = CMPCI_CAP_CMI8738;
369 break;
370 }
371
372 /* map I/O space */
373 if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
374 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
375 printf("%s: failed to map I/O space\n", sc->sc_dev.dv_xname);
376 return;
377 }
378
379 /* interrupt */
380 if (pci_intr_map(pa, &ih)) {
381 printf("%s: failed to map interrupt\n", sc->sc_dev.dv_xname);
382 return;
383 }
384 strintr = pci_intr_string(pa->pa_pc, ih);
385 sc->sc_ih=pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr, sc);
386 if (sc->sc_ih == NULL) {
387 printf("%s: failed to establish interrupt",
388 sc->sc_dev.dv_xname);
389 if (strintr != NULL)
390 printf(" at %s", strintr);
391 printf("\n");
392 return;
393 }
394 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, strintr);
395
396 sc->sc_dmat = pa->pa_dmat;
397
398 audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
399
400 /* attach OPL device */
401 aa.type = AUDIODEV_TYPE_OPL;
402 aa.hwif = NULL;
403 aa.hdl = NULL;
404 (void)config_found(&sc->sc_dev, &aa, audioprint);
405
406 /* attach MPU-401 device */
407 aa.type = AUDIODEV_TYPE_MPU;
408 aa.hwif = NULL;
409 aa.hdl = NULL;
410 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
411 CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0)
412 sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
413
414 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
415 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
416 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
417 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
418 CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE);
419 for (i = 0; i < CMPCI_NDEVS; i++) {
420 switch(i) {
421 /* volumes */
422 case CMPCI_MASTER_VOL:
423 case CMPCI_FM_VOL:
424 case CMPCI_CD_VOL:
425 case CMPCI_VOICE_VOL:
426 case CMPCI_BASS:
427 case CMPCI_TREBLE:
428 case CMPCI_PCSPEAKER:
429 case CMPCI_INPUT_GAIN:
430 case CMPCI_OUTPUT_GAIN:
431 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
432 break;
433 case CMPCI_MIC_VOL:
434 case CMPCI_LINE_IN_VOL:
435 v = 0;
436 break;
437
438 /* booleans, set to true */
439 case CMPCI_CD_OUT_MUTE:
440 case CMPCI_MIC_OUT_MUTE:
441 case CMPCI_LINE_OUT_MUTE:
442 case CMPCI_SPDIF_IN_MUTE:
443 v = 1;
444 break;
445 /* others are cleared */
446 case CMPCI_RECORD_SOURCE:
447 case CMPCI_CD_IN_MUTE:
448 case CMPCI_MIC_IN_MUTE:
449 case CMPCI_LINE_IN_MUTE:
450 case CMPCI_FM_IN_MUTE:
451 case CMPCI_CD_SWAP:
452 case CMPCI_MIC_SWAP:
453 case CMPCI_LINE_SWAP:
454 case CMPCI_FM_SWAP:
455 case CMPCI_SPDIF_LOOP:
456 case CMPCI_SPDIF_LEGACY:
457 case CMPCI_SPDIF_OUT_VOLTAGE:
458 case CMPCI_SPDIF_IN_PHASE:
459 case CMPCI_REAR:
460 case CMPCI_INDIVIDUAL:
461 case CMPCI_REVERSE:
462 case CMPCI_SURROUND:
463 default:
464 v = 0;
465 break;
466 }
467 sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
468 cmpci_set_mixer_gain(sc, i);
469 }
470 }
471
472
473 static int
474 cmpci_intr(handle)
475 void *handle;
476 {
477 struct cmpci_softc *sc = handle;
478 uint32_t intrstat;
479
480 intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
481 CMPCI_REG_INTR_STATUS);
482
483 if (!(intrstat & CMPCI_REG_ANY_INTR))
484 return 0;
485
486 delay(10);
487
488 /* disable and reset intr */
489 if (intrstat & CMPCI_REG_CH0_INTR)
490 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
491 CMPCI_REG_CH0_INTR_ENABLE);
492 if (intrstat & CMPCI_REG_CH1_INTR)
493 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
494 CMPCI_REG_CH1_INTR_ENABLE);
495
496 if (intrstat & CMPCI_REG_CH0_INTR) {
497 if (sc->sc_play.intr != NULL)
498 (*sc->sc_play.intr)(sc->sc_play.intr_arg);
499 }
500 if (intrstat & CMPCI_REG_CH1_INTR) {
501 if (sc->sc_rec.intr != NULL)
502 (*sc->sc_rec.intr)(sc->sc_rec.intr_arg);
503 }
504
505 /* enable intr */
506 if (intrstat & CMPCI_REG_CH0_INTR)
507 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
508 CMPCI_REG_CH0_INTR_ENABLE);
509 if (intrstat & CMPCI_REG_CH1_INTR)
510 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
511 CMPCI_REG_CH1_INTR_ENABLE);
512
513 #if NMPU > 0
514 if (intrstat & CMPCI_REG_UART_INTR && sc->sc_mpudev != NULL)
515 mpu_intr(sc->sc_mpudev);
516 #endif
517
518 return 1;
519 }
520
521
522 /* open/close */
523 static int
524 cmpci_open(handle, flags)
525 void *handle;
526 int flags;
527 {
528 return 0;
529 }
530
531 static void
532 cmpci_close(handle)
533 void *handle;
534 {
535 }
536
537 static int
538 cmpci_query_encoding(handle, fp)
539 void *handle;
540 struct audio_encoding *fp;
541 {
542 switch (fp->index) {
543 case 0:
544 strcpy(fp->name, AudioEulinear);
545 fp->encoding = AUDIO_ENCODING_ULINEAR;
546 fp->precision = 8;
547 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
548 break;
549 case 1:
550 strcpy(fp->name, AudioEmulaw);
551 fp->encoding = AUDIO_ENCODING_ULAW;
552 fp->precision = 8;
553 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
554 break;
555 case 2:
556 strcpy(fp->name, AudioEalaw);
557 fp->encoding = AUDIO_ENCODING_ALAW;
558 fp->precision = 8;
559 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
560 break;
561 case 3:
562 strcpy(fp->name, AudioEslinear);
563 fp->encoding = AUDIO_ENCODING_SLINEAR;
564 fp->precision = 8;
565 fp->flags = 0;
566 break;
567 case 4:
568 strcpy(fp->name, AudioEslinear_le);
569 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
570 fp->precision = 16;
571 fp->flags = 0;
572 break;
573 case 5:
574 strcpy(fp->name, AudioEulinear_le);
575 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
576 fp->precision = 16;
577 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
578 break;
579 case 6:
580 strcpy(fp->name, AudioEslinear_be);
581 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
582 fp->precision = 16;
583 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
584 break;
585 case 7:
586 strcpy(fp->name, AudioEulinear_be);
587 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
588 fp->precision = 16;
589 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
590 break;
591 default:
592 return EINVAL;
593 }
594 return 0;
595 }
596
597
598 static int
599 cmpci_set_params(handle, setmode, usemode, play, rec)
600 void *handle;
601 int setmode, usemode;
602 struct audio_params *play, *rec;
603 {
604 int i;
605 struct cmpci_softc *sc = handle;
606
607 for (i = 0; i < 2; i++) {
608 int md_format;
609 int md_divide;
610 int md_index;
611 int mode;
612 struct audio_params *p;
613
614 switch (i) {
615 case 0:
616 mode = AUMODE_PLAY;
617 p = play;
618 break;
619 case 1:
620 mode = AUMODE_RECORD;
621 p = rec;
622 break;
623 }
624
625 if (!(setmode & mode))
626 continue;
627
628
629 /* format */
630 p->sw_code = NULL;
631 switch ( p->channels ) {
632 case 1:
633 md_format = CMPCI_REG_FORMAT_MONO;
634 break;
635 case 2:
636 md_format = CMPCI_REG_FORMAT_STEREO;
637 break;
638 default:
639 return (EINVAL);
640 }
641 switch (p->encoding) {
642 case AUDIO_ENCODING_ULAW:
643 if (p->precision != 8)
644 return (EINVAL);
645 if (mode & AUMODE_PLAY) {
646 p->factor = 2;
647 p->sw_code = mulaw_to_slinear16_le;
648 md_format |= CMPCI_REG_FORMAT_16BIT;
649 } else {
650 p->sw_code = ulinear8_to_mulaw;
651 md_format |= CMPCI_REG_FORMAT_8BIT;
652 }
653 break;
654 case AUDIO_ENCODING_ALAW:
655 if (p->precision != 8)
656 return (EINVAL);
657 if (mode & AUMODE_PLAY) {
658 p->factor = 2;
659 p->sw_code = alaw_to_slinear16_le;
660 md_format |= CMPCI_REG_FORMAT_16BIT;
661 } else {
662 p->sw_code = ulinear8_to_alaw;
663 md_format |= CMPCI_REG_FORMAT_8BIT;
664 }
665 break;
666 case AUDIO_ENCODING_SLINEAR_LE:
667 switch (p->precision) {
668 case 8:
669 p->sw_code = change_sign8;
670 md_format |= CMPCI_REG_FORMAT_8BIT;
671 break;
672 case 16:
673 md_format |= CMPCI_REG_FORMAT_16BIT;
674 break;
675 default:
676 return (EINVAL);
677 }
678 break;
679 case AUDIO_ENCODING_SLINEAR_BE:
680 switch (p->precision) {
681 case 8:
682 md_format |= CMPCI_REG_FORMAT_8BIT;
683 p->sw_code = change_sign8;
684 break;
685 case 16:
686 md_format |= CMPCI_REG_FORMAT_16BIT;
687 p->sw_code = swap_bytes;
688 break;
689 default:
690 return (EINVAL);
691 }
692 break;
693 case AUDIO_ENCODING_ULINEAR_LE:
694 switch (p->precision) {
695 case 8:
696 md_format |= CMPCI_REG_FORMAT_8BIT;
697 break;
698 case 16:
699 md_format |= CMPCI_REG_FORMAT_16BIT;
700 p->sw_code = change_sign16_le;
701 break;
702 default:
703 return (EINVAL);
704 }
705 break;
706 case AUDIO_ENCODING_ULINEAR_BE:
707 switch (p->precision) {
708 case 8:
709 md_format |= CMPCI_REG_FORMAT_8BIT;
710 break;
711 case 16:
712 md_format |= CMPCI_REG_FORMAT_16BIT;
713 if (mode & AUMODE_PLAY)
714 p->sw_code =
715 swap_bytes_change_sign16_le;
716 else
717 p->sw_code =
718 change_sign16_swap_bytes_le;
719 break;
720 default:
721 return (EINVAL);
722 }
723 break;
724 default:
725 return (EINVAL);
726 }
727 if (mode & AUMODE_PLAY)
728 cmpci_reg_partial_write_4(sc,
729 CMPCI_REG_CHANNEL_FORMAT,
730 CMPCI_REG_CH0_FORMAT_SHIFT,
731 CMPCI_REG_CH0_FORMAT_MASK, md_format);
732 else
733 cmpci_reg_partial_write_4(sc,
734 CMPCI_REG_CHANNEL_FORMAT,
735 CMPCI_REG_CH1_FORMAT_SHIFT,
736 CMPCI_REG_CH1_FORMAT_MASK, md_format);
737 /* sample rate */
738 md_index = cmpci_rate_to_index(p->sample_rate);
739 md_divide = cmpci_index_to_divider(md_index);
740 p->sample_rate = cmpci_index_to_rate(md_index);
741 DPRINTF(("%s: sample:%d, divider=%d\n",
742 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
743 if (mode & AUMODE_PLAY) {
744 cmpci_reg_partial_write_4(sc,
745 CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
746 CMPCI_REG_DAC_FS_MASK, md_divide);
747 sc->sc_play.md_divide = md_divide;
748 } else {
749 cmpci_reg_partial_write_4(sc,
750 CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
751 CMPCI_REG_ADC_FS_MASK, md_divide);
752 sc->sc_rec.md_divide = md_divide;
753 }
754 cmpci_set_mixer_gain(sc, CMPCI_SPDIF_LOOP);
755 }
756 return 0;
757 }
758
759 /* ARGSUSED */
760 static int
761 cmpci_round_blocksize(handle, block)
762 void *handle;
763 int block;
764 {
765 return (block & -4);
766 }
767
768 static int
769 cmpci_halt_output(handle)
770 void *handle;
771 {
772 struct cmpci_softc *sc = handle;
773 int s;
774
775 s = splaudio();
776 sc->sc_play.intr = NULL;
777 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
778 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
779 /* wait for reset DMA */
780 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
781 delay(10);
782 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
783 splx(s);
784
785 return 0;
786 }
787
788 static int
789 cmpci_halt_input(handle)
790 void *handle;
791 {
792 struct cmpci_softc *sc = handle;
793 int s;
794
795 s = splaudio();
796 sc->sc_rec.intr = NULL;
797 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
798 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
799 /* wait for reset DMA */
800 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
801 delay(10);
802 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
803 splx(s);
804
805 return 0;
806 }
807
808
809 /* get audio device information */
810 static int
811 cmpci_getdev(handle, ad)
812 void *handle;
813 struct audio_device *ad;
814 {
815 struct cmpci_softc *sc = handle;
816
817 strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name));
818 snprintf(ad->version, sizeof(ad->version), "0x%02x",
819 PCI_REVISION(sc->sc_class));
820 switch (PCI_PRODUCT(sc->sc_id)) {
821 case PCI_PRODUCT_CMEDIA_CMI8338A:
822 strncpy(ad->config, "CMI8338A", sizeof(ad->config));
823 break;
824 case PCI_PRODUCT_CMEDIA_CMI8338B:
825 strncpy(ad->config, "CMI8338B", sizeof(ad->config));
826 break;
827 case PCI_PRODUCT_CMEDIA_CMI8738:
828 strncpy(ad->config, "CMI8738", sizeof(ad->config));
829 break;
830 case PCI_PRODUCT_CMEDIA_CMI8738B:
831 strncpy(ad->config, "CMI8738B", sizeof(ad->config));
832 break;
833 default:
834 strncpy(ad->config, "unknown", sizeof(ad->config));
835 }
836
837 return 0;
838 }
839
840
841 /* mixer device information */
842 int
843 cmpci_query_devinfo(handle, dip)
844 void *handle;
845 mixer_devinfo_t *dip;
846 {
847 switch (dip->index) {
848 case CMPCI_MASTER_VOL:
849 dip->type = AUDIO_MIXER_VALUE;
850 dip->mixer_class = CMPCI_OUTPUT_CLASS;
851 dip->prev = dip->next = AUDIO_MIXER_LAST;
852 strcpy(dip->label.name, AudioNmaster);
853 dip->un.v.num_channels = 2;
854 strcpy(dip->un.v.units.name, AudioNvolume);
855 return 0;
856 case CMPCI_FM_VOL:
857 dip->type = AUDIO_MIXER_VALUE;
858 dip->mixer_class = CMPCI_INPUT_CLASS;
859 dip->prev = AUDIO_MIXER_LAST;
860 dip->next = CMPCI_FM_IN_MUTE;
861 strcpy(dip->label.name, AudioNfmsynth);
862 dip->un.v.num_channels = 2;
863 strcpy(dip->un.v.units.name, AudioNvolume);
864 return 0;
865 case CMPCI_CD_VOL:
866 dip->type = AUDIO_MIXER_VALUE;
867 dip->mixer_class = CMPCI_INPUT_CLASS;
868 dip->prev = AUDIO_MIXER_LAST;
869 dip->next = CMPCI_CD_IN_MUTE;
870 strcpy(dip->label.name, AudioNcd);
871 dip->un.v.num_channels = 2;
872 strcpy(dip->un.v.units.name, AudioNvolume);
873 return 0;
874 case CMPCI_VOICE_VOL:
875 dip->type = AUDIO_MIXER_VALUE;
876 dip->mixer_class = CMPCI_OUTPUT_CLASS;
877 dip->prev = AUDIO_MIXER_LAST;
878 dip->next = AUDIO_MIXER_LAST;
879 strcpy(dip->label.name, AudioNdac);
880 dip->un.v.num_channels = 2;
881 strcpy(dip->un.v.units.name, AudioNvolume);
882 return 0;
883 case CMPCI_OUTPUT_CLASS:
884 dip->type = AUDIO_MIXER_CLASS;
885 dip->mixer_class = CMPCI_INPUT_CLASS;
886 dip->next = dip->prev = AUDIO_MIXER_LAST;
887 strcpy(dip->label.name, AudioCoutputs);
888 return 0;
889 case CMPCI_MIC_VOL:
890 dip->type = AUDIO_MIXER_VALUE;
891 dip->mixer_class = CMPCI_INPUT_CLASS;
892 dip->prev = AUDIO_MIXER_LAST;
893 dip->next = CMPCI_MIC_IN_MUTE;
894 strcpy(dip->label.name, AudioNmicrophone);
895 dip->un.v.num_channels = 1;
896 strcpy(dip->un.v.units.name, AudioNvolume);
897 return 0;
898 case CMPCI_LINE_IN_VOL:
899 dip->type = AUDIO_MIXER_VALUE;
900 dip->mixer_class = CMPCI_INPUT_CLASS;
901 dip->prev = AUDIO_MIXER_LAST;
902 dip->next = CMPCI_LINE_IN_MUTE;
903 strcpy(dip->label.name, AudioNline);
904 dip->un.v.num_channels = 2;
905 strcpy(dip->un.v.units.name, AudioNvolume);
906 return 0;
907 case CMPCI_RECORD_SOURCE:
908 dip->mixer_class = CMPCI_RECORD_CLASS;
909 dip->prev = dip->next = AUDIO_MIXER_LAST;
910 strcpy(dip->label.name, AudioNsource);
911 dip->type = AUDIO_MIXER_SET;
912 dip->un.s.num_mem = 5;
913 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
914 dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC;
915 strcpy(dip->un.s.member[1].label.name, AudioNcd);
916 dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD;
917 strcpy(dip->un.s.member[2].label.name, AudioNline);
918 dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN;
919 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
920 dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_FM;
921 strcpy(dip->un.s.member[4].label.name, CmpciNspdif);
922 dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_SPDIF;
923 return 0;
924 case CMPCI_BASS:
925 dip->prev = dip->next = AUDIO_MIXER_LAST;
926 strcpy(dip->label.name, AudioNbass);
927 dip->type = AUDIO_MIXER_VALUE;
928 dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
929 dip->un.v.num_channels = 2;
930 strcpy(dip->un.v.units.name, AudioNbass);
931 return 0;
932 case CMPCI_TREBLE:
933 dip->prev = dip->next = AUDIO_MIXER_LAST;
934 strcpy(dip->label.name, AudioNtreble);
935 dip->type = AUDIO_MIXER_VALUE;
936 dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
937 dip->un.v.num_channels = 2;
938 strcpy(dip->un.v.units.name, AudioNtreble);
939 return 0;
940 case CMPCI_RECORD_CLASS:
941 dip->type = AUDIO_MIXER_CLASS;
942 dip->mixer_class = CMPCI_RECORD_CLASS;
943 dip->next = dip->prev = AUDIO_MIXER_LAST;
944 strcpy(dip->label.name, AudioCrecord);
945 return 0;
946 case CMPCI_INPUT_CLASS:
947 dip->type = AUDIO_MIXER_CLASS;
948 dip->mixer_class = CMPCI_INPUT_CLASS;
949 dip->next = dip->prev = AUDIO_MIXER_LAST;
950 strcpy(dip->label.name, AudioCinputs);
951 return 0;
952 case CMPCI_PCSPEAKER:
953 dip->type = AUDIO_MIXER_VALUE;
954 dip->mixer_class = CMPCI_INPUT_CLASS;
955 dip->prev = dip->next = AUDIO_MIXER_LAST;
956 strcpy(dip->label.name, "pc_speaker");
957 dip->un.v.num_channels = 1;
958 strcpy(dip->un.v.units.name, AudioNvolume);
959 return 0;
960 case CMPCI_INPUT_GAIN:
961 dip->type = AUDIO_MIXER_VALUE;
962 dip->mixer_class = CMPCI_INPUT_CLASS;
963 dip->prev = dip->next = AUDIO_MIXER_LAST;
964 strcpy(dip->label.name, AudioNinput);
965 dip->un.v.num_channels = 2;
966 strcpy(dip->un.v.units.name, AudioNvolume);
967 return 0;
968 case CMPCI_OUTPUT_GAIN:
969 dip->type = AUDIO_MIXER_VALUE;
970 dip->mixer_class = CMPCI_OUTPUT_CLASS;
971 dip->prev = dip->next = AUDIO_MIXER_LAST;
972 strcpy(dip->label.name, AudioNoutput);
973 dip->un.v.num_channels = 2;
974 strcpy(dip->un.v.units.name, AudioNvolume);
975 return 0;
976 case CMPCI_AGC:
977 dip->type = AUDIO_MIXER_ENUM;
978 dip->mixer_class = CMPCI_INPUT_CLASS;
979 dip->prev = dip->next = AUDIO_MIXER_LAST;
980 strcpy(dip->label.name, "agc");
981 goto on_off;
982 case CMPCI_EQUALIZATION_CLASS:
983 dip->type = AUDIO_MIXER_CLASS;
984 dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
985 dip->next = dip->prev = AUDIO_MIXER_LAST;
986 strcpy(dip->label.name, AudioCequalization);
987 return 0;
988 case CMPCI_SPDIF_IN_MUTE:
989 dip->type = AUDIO_MIXER_CLASS;
990 dip->mixer_class = CMPCI_INPUT_CLASS;
991 dip->next = dip->prev = AUDIO_MIXER_LAST;
992 strcpy(dip->label.name, CmpciNspdif);
993 return 0;
994 case CMPCI_SPDIF_CLASS:
995 dip->type = AUDIO_MIXER_CLASS;
996 dip->mixer_class = CMPCI_SPDIF_CLASS;
997 dip->next = dip->prev = AUDIO_MIXER_LAST;
998 strcpy(dip->label.name, CmpciCspdif);
999 return 0;
1000 case CMPCI_SPDIF_LOOP:
1001 dip->mixer_class = CMPCI_SPDIF_CLASS;
1002 dip->prev = dip->next = AUDIO_MIXER_LAST;
1003 strcpy(dip->label.name, CmpciNloop);
1004 goto on_off;
1005 case CMPCI_SPDIF_LEGACY:
1006 dip->mixer_class = CMPCI_SPDIF_CLASS;
1007 dip->prev = dip->next = AUDIO_MIXER_LAST;
1008 strcpy(dip->label.name, CmpciNlegacy);
1009 goto on_off;
1010 case CMPCI_SPDIF_OUT_VOLTAGE:
1011 dip->mixer_class = CMPCI_SPDIF_CLASS;
1012 dip->prev = dip->next = AUDIO_MIXER_LAST;
1013 strcpy(dip->label.name, CmpciNout_voltage);
1014 dip->type = AUDIO_MIXER_ENUM;
1015 dip->un.e.num_mem = 2;
1016 strcpy(dip->un.e.member[0].label.name, CmpciNlow_v);
1017 dip->un.e.member[0].ord = 0;
1018 strcpy(dip->un.e.member[1].label.name, CmpciNhigh_v);
1019 dip->un.e.member[1].ord = 1;
1020 return 0;
1021 case CMPCI_SPDIF_IN_PHASE:
1022 dip->mixer_class = CMPCI_SPDIF_CLASS;
1023 dip->prev = dip->next = AUDIO_MIXER_LAST;
1024 strcpy(dip->label.name, CmpciNin_phase);
1025 goto on_off;
1026 case CMPCI_REAR:
1027 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1028 dip->prev = AUDIO_MIXER_LAST;
1029 dip->next = CMPCI_INDIVIDUAL;
1030 strcpy(dip->label.name, CmpciNrear);
1031 goto on_off;
1032 case CMPCI_INDIVIDUAL:
1033 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1034 dip->prev = CMPCI_REAR;
1035 dip->next = CMPCI_REVERSE;
1036 strcpy(dip->label.name, CmpciNindividual);
1037 goto on_off;
1038 case CMPCI_REVERSE:
1039 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1040 dip->prev = CMPCI_INDIVIDUAL;
1041 dip->next = AUDIO_MIXER_LAST;
1042 strcpy(dip->label.name, CmpciNreverse);
1043 dip->type = AUDIO_MIXER_ENUM;
1044 dip->un.e.num_mem = 2;
1045 strcpy(dip->un.e.member[0].label.name, CmpciNpositive);
1046 dip->un.e.member[0].ord = 0;
1047 strcpy(dip->un.e.member[1].label.name, CmpciNnegative);
1048 dip->un.e.member[1].ord = 1;
1049 return 0;
1050 case CMPCI_SURROUND:
1051 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1052 dip->prev = dip->next = AUDIO_MIXER_LAST;
1053 strcpy(dip->label.name, CmpciNsurround);
1054 goto on_off;
1055
1056 case CMPCI_CD_IN_MUTE:
1057 dip->prev = CMPCI_CD_VOL;
1058 dip->next = CMPCI_CD_SWAP;
1059 dip->mixer_class = CMPCI_INPUT_CLASS;
1060 goto mute;
1061 case CMPCI_MIC_IN_MUTE:
1062 dip->prev = CMPCI_MIC_VOL;
1063 dip->next = CMPCI_MIC_SWAP;
1064 dip->mixer_class = CMPCI_INPUT_CLASS;
1065 goto mute;
1066 case CMPCI_LINE_IN_MUTE:
1067 dip->prev = CMPCI_LINE_IN_VOL;
1068 dip->next = CMPCI_LINE_SWAP;
1069 dip->mixer_class = CMPCI_INPUT_CLASS;
1070 goto mute;
1071 case CMPCI_FM_IN_MUTE:
1072 dip->prev = CMPCI_FM_VOL;
1073 dip->next = CMPCI_FM_SWAP;
1074 dip->mixer_class = CMPCI_INPUT_CLASS;
1075 goto mute;
1076 case CMPCI_CD_SWAP:
1077 dip->prev = CMPCI_CD_IN_MUTE;
1078 dip->next = CMPCI_CD_OUT_MUTE;
1079 goto swap;
1080 case CMPCI_MIC_SWAP:
1081 dip->prev = CMPCI_MIC_IN_MUTE;
1082 dip->next = CMPCI_MIC_OUT_MUTE;
1083 goto swap;
1084 case CMPCI_LINE_SWAP:
1085 dip->prev = CMPCI_LINE_IN_MUTE;
1086 dip->next = CMPCI_LINE_OUT_MUTE;
1087 goto swap;
1088 case CMPCI_FM_SWAP:
1089 dip->prev = CMPCI_FM_IN_MUTE;
1090 dip->next = AUDIO_MIXER_LAST;
1091 swap:
1092 dip->mixer_class = CMPCI_INPUT_CLASS;
1093 strcpy(dip->label.name, AudioNswap);
1094 goto on_off;
1095
1096 case CMPCI_CD_OUT_MUTE:
1097 dip->prev = CMPCI_CD_SWAP;
1098 dip->next = AUDIO_MIXER_LAST;
1099 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1100 goto mute;
1101 case CMPCI_MIC_OUT_MUTE:
1102 dip->prev = CMPCI_MIC_SWAP;
1103 dip->next = AUDIO_MIXER_LAST;
1104 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1105 goto mute;
1106 case CMPCI_LINE_OUT_MUTE:
1107 dip->prev = CMPCI_LINE_SWAP;
1108 dip->next = AUDIO_MIXER_LAST;
1109 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1110 mute:
1111 strcpy(dip->label.name, AudioNmute);
1112 on_off:
1113 dip->type = AUDIO_MIXER_ENUM;
1114 dip->un.e.num_mem = 2;
1115 strcpy(dip->un.e.member[0].label.name, AudioNoff);
1116 dip->un.e.member[0].ord = 0;
1117 strcpy(dip->un.e.member[1].label.name, AudioNon);
1118 dip->un.e.member[1].ord = 1;
1119 return 0;
1120 }
1121
1122 return ENXIO;
1123 }
1124
1125 static int
1126 cmpci_alloc_dmamem(sc, size, type, flags, r_addr)
1127 struct cmpci_softc *sc;
1128 size_t size;
1129 int type, flags;
1130 caddr_t *r_addr;
1131 {
1132 int error = 0;
1133 struct cmpci_dmanode *n;
1134 int w;
1135
1136 n = malloc(sizeof(struct cmpci_dmanode), type, flags);
1137 if (n == NULL) {
1138 error = ENOMEM;
1139 goto quit;
1140 }
1141
1142 w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1143 #define CMPCI_DMABUF_ALIGN 0x4
1144 #define CMPCI_DMABUF_BOUNDARY 0x0
1145 n->cd_tag = sc->sc_dmat;
1146 n->cd_size = size;
1147 error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
1148 CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
1149 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w);
1150 if (error)
1151 goto mfree;
1152 error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
1153 &n->cd_addr, w | BUS_DMA_COHERENT);
1154 if (error)
1155 goto dmafree;
1156 error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
1157 w, &n->cd_map);
1158 if (error)
1159 goto unmap;
1160 error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
1161 NULL, w);
1162 if (error)
1163 goto destroy;
1164
1165 n->cd_next = sc->sc_dmap;
1166 sc->sc_dmap = n;
1167 *r_addr = KVADDR(n);
1168 return 0;
1169
1170 destroy:
1171 bus_dmamap_destroy(n->cd_tag, n->cd_map);
1172 unmap:
1173 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1174 dmafree:
1175 bus_dmamem_free(n->cd_tag,
1176 n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1177 mfree:
1178 free(n, type);
1179 quit:
1180 return error;
1181 }
1182
1183 static int
1184 cmpci_free_dmamem(sc, addr, type)
1185 struct cmpci_softc *sc;
1186 caddr_t addr;
1187 int type;
1188 {
1189 struct cmpci_dmanode **nnp;
1190
1191 for (nnp = &sc->sc_dmap; *nnp; nnp= &(*nnp)->cd_next) {
1192 if ((*nnp)->cd_addr == addr) {
1193 struct cmpci_dmanode *n = *nnp;
1194 bus_dmamap_unload(n->cd_tag, n->cd_map);
1195 bus_dmamap_destroy(n->cd_tag, n->cd_map);
1196 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1197 bus_dmamem_free(n->cd_tag, n->cd_segs,
1198 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1199 free(n, type);
1200 return 0;
1201 }
1202 }
1203 return -1;
1204 }
1205
1206 static struct cmpci_dmanode *
1207 cmpci_find_dmamem(sc, addr)
1208 struct cmpci_softc *sc;
1209 caddr_t addr;
1210 {
1211 struct cmpci_dmanode *p;
1212 for (p=sc->sc_dmap; p; p=p->cd_next)
1213 if ( KVADDR(p) == (void *)addr )
1214 break;
1215 return p;
1216 }
1217
1218
1219 #if 0
1220 static void
1221 cmpci_print_dmamem __P((struct cmpci_dmanode *p));
1222 static void
1223 cmpci_print_dmamem(p)
1224 struct cmpci_dmanode *p;
1225 {
1226 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1227 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
1228 (void *)DMAADDR(p), (void *)p->cd_size));
1229 }
1230 #endif /* DEBUG */
1231
1232
1233 static void *
1234 cmpci_allocm(handle, direction, size, type, flags)
1235 void *handle;
1236 int direction;
1237 size_t size;
1238 int type, flags;
1239 {
1240 struct cmpci_softc *sc = handle;
1241 caddr_t addr;
1242
1243 if (cmpci_alloc_dmamem(sc, size, type, flags, &addr))
1244 return NULL;
1245 return addr;
1246 }
1247
1248 static void
1249 cmpci_freem(handle, addr, type)
1250 void *handle;
1251 void *addr;
1252 int type;
1253 {
1254 struct cmpci_softc *sc = handle;
1255
1256 cmpci_free_dmamem(sc, addr, type);
1257 }
1258
1259
1260 #define MAXVAL 256
1261 static int
1262 cmpci_adjust(val, mask)
1263 int val, mask;
1264 {
1265 val += (MAXVAL - mask) >> 1;
1266 if (val >= MAXVAL)
1267 val = MAXVAL-1;
1268 return val & mask;
1269 }
1270
1271 static void
1272 cmpci_set_mixer_gain(sc, port)
1273 struct cmpci_softc *sc;
1274 int port;
1275 {
1276 int src;
1277
1278 switch (port) {
1279 case CMPCI_MIC_VOL:
1280 src = CMPCI_SB16_MIXER_MIC;
1281 break;
1282 case CMPCI_MASTER_VOL:
1283 src = CMPCI_SB16_MIXER_MASTER_L;
1284 break;
1285 case CMPCI_LINE_IN_VOL:
1286 src = CMPCI_SB16_MIXER_LINE_L;
1287 break;
1288 case CMPCI_VOICE_VOL:
1289 src = CMPCI_SB16_MIXER_VOICE_L;
1290 break;
1291 case CMPCI_FM_VOL:
1292 src = CMPCI_SB16_MIXER_FM_L;
1293 break;
1294 case CMPCI_CD_VOL:
1295 src = CMPCI_SB16_MIXER_CDDA_L;
1296 break;
1297 case CMPCI_INPUT_GAIN:
1298 src = CMPCI_SB16_MIXER_INGAIN_L;
1299 break;
1300 case CMPCI_OUTPUT_GAIN:
1301 src = CMPCI_SB16_MIXER_OUTGAIN_L;
1302 break;
1303 case CMPCI_TREBLE:
1304 src = CMPCI_SB16_MIXER_TREBLE_L;
1305 break;
1306 case CMPCI_BASS:
1307 src = CMPCI_SB16_MIXER_BASS_L;
1308 break;
1309 case CMPCI_PCSPEAKER:
1310 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
1311 sc->sc_gain[port][CMPCI_LEFT]);
1312 return;
1313 case CMPCI_SPDIF_IN_MUTE:
1314 if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
1315 if (sc->sc_gain[CMPCI_SPDIF_IN_MUTE][CMPCI_LR])
1316 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1317 CMPCI_REG_SPDIN_MONITOR);
1318 else
1319 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1320 CMPCI_REG_SPDIN_MONITOR);
1321 }
1322 return;
1323 case CMPCI_SPDIF_LOOP:
1324 /*FALLTHROUGH*/
1325 case CMPCI_SPDIF_LEGACY:
1326 cmpci_set_out_ports(sc);
1327 return;
1328 case CMPCI_SPDIF_OUT_VOLTAGE:
1329 if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
1330 if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR])
1331 cmpci_reg_set_4(sc, CMPCI_REG_MISC,
1332 CMPCI_REG_5V);
1333 else
1334 cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
1335 CMPCI_REG_5V);
1336 }
1337 return;
1338 case CMPCI_SURROUND:
1339 if (CMPCI_ISCAP(sc, SURROUND)) {
1340 if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
1341 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1342 CMPCI_REG_SURROUND);
1343 else
1344 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1345 CMPCI_REG_SURROUND);
1346 }
1347 return;
1348 case CMPCI_REAR:
1349 if (CMPCI_ISCAP(sc, REAR)) {
1350 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
1351 cmpci_reg_set_4(sc, CMPCI_REG_MISC,
1352 CMPCI_REG_N4SPK3D);
1353 else
1354 cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
1355 CMPCI_REG_N4SPK3D);
1356 }
1357 return;
1358 case CMPCI_INDIVIDUAL:
1359 if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
1360 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
1361 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1362 CMPCI_REG_INDIVIDUAL);
1363 else
1364 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1365 CMPCI_REG_INDIVIDUAL);
1366 }
1367 return;
1368 case CMPCI_REVERSE:
1369 if (CMPCI_ISCAP(sc, REVERSE_FR)) {
1370 if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
1371 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1372 CMPCI_REG_REVERSE_FR);
1373 else
1374 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1375 CMPCI_REG_REVERSE_FR);
1376 }
1377 return;
1378 case CMPCI_SPDIF_IN_PHASE:
1379 if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
1380 if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR])
1381 cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT,
1382 CMPCI_REG_SPDIN_PHASE);
1383 else
1384 cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT,
1385 CMPCI_REG_SPDIN_PHASE);
1386 }
1387 return;
1388 default:
1389 return;
1390 }
1391 cmpci_mixerreg_write(sc, src, sc->sc_gain[port][CMPCI_LEFT]);
1392 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
1393 sc->sc_gain[port][CMPCI_RIGHT]);
1394 }
1395
1396 static void
1397 cmpci_set_out_ports(sc)
1398 struct cmpci_softc *sc;
1399 {
1400 if (!CMPCI_ISCAP(sc, SPDLOOP))
1401 return;
1402 if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR]) {
1403 /* loop on */
1404 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1405 CMPCI_REG_SPDIF0_ENABLE |
1406 CMPCI_REG_SPDIF1_ENABLE);
1407 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
1408 CMPCI_REG_LEGACY_SPDIF_ENABLE);
1409 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1410 CMPCI_REG_SPDIF_LOOP);
1411 } else {
1412 /* loop off */
1413 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1414 CMPCI_REG_SPDIF_LOOP);
1415 cmpci_set_in_ports(sc, sc->sc_in_mask);
1416 if (CMPCI_ISCAP(sc, SPDOUT) &&
1417 (sc->sc_play.md_divide==CMPCI_REG_RATE_44100 ||
1418 (CMPCI_ISCAP(sc, SPDOUT_48K) &&
1419 sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) {
1420 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1421 CMPCI_REG_SPDIF0_ENABLE);
1422 if (CMPCI_ISCAP(sc, XSPDOUT))
1423 cmpci_reg_set_4(sc,
1424 CMPCI_REG_LEGACY_CTRL,
1425 CMPCI_REG_XSPDIF_ENABLE);
1426 if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000)
1427 cmpci_reg_set_4(sc,
1428 CMPCI_REG_MISC,
1429 CMPCI_REG_SPDIF_48K);
1430 else
1431 cmpci_reg_clear_4(sc,
1432 CMPCI_REG_MISC,
1433 CMPCI_REG_SPDIF_48K);
1434 } else {
1435 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1436 CMPCI_REG_SPDIF0_ENABLE);
1437 if (CMPCI_ISCAP(sc, XSPDOUT))
1438 cmpci_reg_clear_4(sc,
1439 CMPCI_REG_LEGACY_CTRL,
1440 CMPCI_REG_XSPDIF_ENABLE);
1441 if (CMPCI_ISCAP(sc, SPDOUT_48K))
1442 cmpci_reg_clear_4(sc,
1443 CMPCI_REG_MISC,
1444 CMPCI_REG_SPDIF_48K);
1445 }
1446 if (CMPCI_ISCAP(sc, SPDLEGACY)) {
1447 if (sc->sc_gain[CMPCI_SPDIF_LEGACY][CMPCI_LR])
1448 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
1449 CMPCI_REG_LEGACY_SPDIF_ENABLE);
1450 else
1451 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
1452 CMPCI_REG_LEGACY_SPDIF_ENABLE);
1453 }
1454 }
1455 }
1456
1457 static int
1458 cmpci_set_in_ports(sc, mask)
1459 struct cmpci_softc *sc;
1460 int mask;
1461 {
1462 int bitsl, bitsr;
1463
1464 if (mask & ~(CMPCI_RECORD_SOURCE_MIC | CMPCI_RECORD_SOURCE_CD |
1465 CMPCI_RECORD_SOURCE_LINE_IN | CMPCI_RECORD_SOURCE_FM |
1466 CMPCI_RECORD_SOURCE_SPDIF))
1467 return EINVAL;
1468 bitsr = 0;
1469 if (mask & CMPCI_RECORD_SOURCE_FM)
1470 bitsr |= CMPCI_SB16_MIXER_FM_SRC_R;
1471 if (mask & CMPCI_RECORD_SOURCE_LINE_IN)
1472 bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R;
1473 if (mask & CMPCI_RECORD_SOURCE_CD)
1474 bitsr |= CMPCI_SB16_MIXER_CD_SRC_R;
1475 bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
1476 if (mask & CMPCI_RECORD_SOURCE_MIC) {
1477 bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
1478 bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
1479 }
1480 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
1481 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
1482 if (CMPCI_ISCAP(sc, SPDIN) &&
1483 sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 &&
1484 !sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR]) {
1485 if (mask & CMPCI_RECORD_SOURCE_SPDIF) {
1486 /* enable SPDIF/in */
1487 cmpci_reg_set_4(sc,
1488 CMPCI_REG_FUNC_1,
1489 CMPCI_REG_SPDIF1_ENABLE);
1490 } else {
1491 cmpci_reg_clear_4(sc,
1492 CMPCI_REG_FUNC_1,
1493 CMPCI_REG_SPDIF1_ENABLE);
1494 }
1495 }
1496
1497 sc->sc_in_mask = mask;
1498
1499 return 0;
1500 }
1501
1502 static int
1503 cmpci_set_port(handle, cp)
1504 void *handle;
1505 mixer_ctrl_t *cp;
1506 {
1507 struct cmpci_softc *sc = handle;
1508 int lgain, rgain;
1509 int mask, bits;
1510 int lmask, rmask, lbits, rbits;
1511 int mute, swap;
1512
1513 switch (cp->dev) {
1514 case CMPCI_TREBLE:
1515 case CMPCI_BASS:
1516 case CMPCI_PCSPEAKER:
1517 case CMPCI_INPUT_GAIN:
1518 case CMPCI_OUTPUT_GAIN:
1519 case CMPCI_MIC_VOL:
1520 case CMPCI_LINE_IN_VOL:
1521 case CMPCI_VOICE_VOL:
1522 case CMPCI_FM_VOL:
1523 case CMPCI_CD_VOL:
1524 case CMPCI_MASTER_VOL:
1525 if (cp->type != AUDIO_MIXER_VALUE)
1526 return EINVAL;
1527 switch (cp->dev) {
1528 case CMPCI_MIC_VOL:
1529 if (cp->un.value.num_channels != 1)
1530 return EINVAL;
1531
1532 lgain = rgain =
1533 CMPCI_ADJUST_MIC_GAIN(sc,
1534 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1535 break;
1536 case CMPCI_PCSPEAKER:
1537 if (cp->un.value.num_channels != 1)
1538 return EINVAL;
1539 /* fall into */
1540 case CMPCI_INPUT_GAIN:
1541 case CMPCI_OUTPUT_GAIN:
1542 lgain = rgain = CMPCI_ADJUST_2_GAIN(sc,
1543 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1544 break;
1545 default:
1546 switch (cp->un.value.num_channels) {
1547 case 1:
1548 lgain = rgain = CMPCI_ADJUST_GAIN(sc,
1549 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]
1550 );
1551 break;
1552 case 2:
1553 lgain = CMPCI_ADJUST_GAIN(sc,
1554 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]
1555 );
1556 rgain = CMPCI_ADJUST_GAIN(sc,
1557 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]
1558 );
1559 break;
1560 default:
1561 return EINVAL;
1562 }
1563 break;
1564 }
1565 sc->sc_gain[cp->dev][CMPCI_LEFT] = lgain;
1566 sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
1567
1568 cmpci_set_mixer_gain(sc, cp->dev);
1569 break;
1570
1571 case CMPCI_RECORD_SOURCE:
1572 if (cp->type != AUDIO_MIXER_SET)
1573 return EINVAL;
1574
1575 if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF)
1576 cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF;
1577
1578 return cmpci_set_in_ports(sc, cp->un.mask);
1579
1580 case CMPCI_AGC:
1581 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_AGC, cp->un.ord & 1);
1582 break;
1583
1584 case CMPCI_CD_OUT_MUTE:
1585 mask = CMPCI_SB16_SW_CD;
1586 goto omute;
1587 case CMPCI_MIC_OUT_MUTE:
1588 mask = CMPCI_SB16_SW_MIC;
1589 goto omute;
1590 case CMPCI_LINE_OUT_MUTE:
1591 mask = CMPCI_SB16_SW_LINE;
1592 omute:
1593 if (cp->type != AUDIO_MIXER_ENUM)
1594 return EINVAL;
1595 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
1596 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1597 if (cp->un.ord)
1598 bits = bits & ~mask;
1599 else
1600 bits = bits | mask;
1601 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
1602 break;
1603
1604 case CMPCI_MIC_IN_MUTE:
1605 case CMPCI_MIC_SWAP:
1606 lmask = rmask = CMPCI_SB16_SW_MIC;
1607 goto imute;
1608 case CMPCI_CD_IN_MUTE:
1609 case CMPCI_CD_SWAP:
1610 lmask = CMPCI_SB16_SW_CD_L;
1611 rmask = CMPCI_SB16_SW_CD_R;
1612 goto imute;
1613 case CMPCI_LINE_IN_MUTE:
1614 case CMPCI_LINE_SWAP:
1615 lmask = CMPCI_SB16_SW_LINE_L;
1616 rmask = CMPCI_SB16_SW_LINE_R;
1617 goto imute;
1618 case CMPCI_FM_IN_MUTE:
1619 case CMPCI_FM_SWAP:
1620 lmask = CMPCI_SB16_SW_FM_L;
1621 rmask = CMPCI_SB16_SW_FM_R;
1622 imute:
1623 if (cp->type != AUDIO_MIXER_ENUM)
1624 return EINVAL;
1625 mask = lmask | rmask;
1626 lbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_L)
1627 & ~mask;
1628 rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R)
1629 & ~mask;
1630 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1631 if (CMPCI_IS_IN_MUTE(cp->dev)) {
1632 mute = cp->dev;
1633 swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP;
1634 } else {
1635 swap = cp->dev;
1636 mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP;
1637 }
1638 if (sc->sc_gain[swap][CMPCI_LR]) {
1639 mask = lmask;
1640 lmask = rmask;
1641 rmask = mask;
1642 }
1643 if (!sc->sc_gain[mute][CMPCI_LR]) {
1644 lbits = lbits | lmask;
1645 rbits = rbits | rmask;
1646 }
1647 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits);
1648 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits);
1649 break;
1650 case CMPCI_SPDIF_LOOP:
1651 case CMPCI_SPDIF_LEGACY:
1652 case CMPCI_SPDIF_OUT_VOLTAGE:
1653 case CMPCI_SPDIF_IN_PHASE:
1654 case CMPCI_REAR:
1655 case CMPCI_INDIVIDUAL:
1656 case CMPCI_REVERSE:
1657 case CMPCI_SURROUND:
1658 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
1659 break;
1660
1661 default:
1662 return EINVAL;
1663 }
1664
1665 return 0;
1666 }
1667
1668 static int
1669 cmpci_get_port(handle, cp)
1670 void *handle;
1671 mixer_ctrl_t *cp;
1672 {
1673 struct cmpci_softc *sc = handle;
1674
1675 switch (cp->dev) {
1676 case CMPCI_MIC_VOL:
1677 case CMPCI_LINE_IN_VOL:
1678 if (cp->un.value.num_channels != 1)
1679 return EINVAL;
1680 /* fall into */
1681 case CMPCI_TREBLE:
1682 case CMPCI_BASS:
1683 case CMPCI_PCSPEAKER:
1684 case CMPCI_INPUT_GAIN:
1685 case CMPCI_OUTPUT_GAIN:
1686 case CMPCI_VOICE_VOL:
1687 case CMPCI_FM_VOL:
1688 case CMPCI_CD_VOL:
1689 case CMPCI_MASTER_VOL:
1690 switch (cp->un.value.num_channels) {
1691 case 1:
1692 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1693 sc->sc_gain[cp->dev][CMPCI_LEFT];
1694 break;
1695 case 2:
1696 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1697 sc->sc_gain[cp->dev][CMPCI_LEFT];
1698 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1699 sc->sc_gain[cp->dev][CMPCI_RIGHT];
1700 break;
1701 default:
1702 return EINVAL;
1703 }
1704 break;
1705
1706 case CMPCI_RECORD_SOURCE:
1707 cp->un.mask = sc->sc_in_mask;
1708 break;
1709
1710 case CMPCI_AGC:
1711 cp->un.ord = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_AGC);
1712 break;
1713
1714 case CMPCI_CD_IN_MUTE:
1715 case CMPCI_MIC_IN_MUTE:
1716 case CMPCI_LINE_IN_MUTE:
1717 case CMPCI_FM_IN_MUTE:
1718 case CMPCI_CD_SWAP:
1719 case CMPCI_MIC_SWAP:
1720 case CMPCI_LINE_SWAP:
1721 case CMPCI_FM_SWAP:
1722 case CMPCI_CD_OUT_MUTE:
1723 case CMPCI_MIC_OUT_MUTE:
1724 case CMPCI_LINE_OUT_MUTE:
1725 case CMPCI_SPDIF_IN_MUTE:
1726 case CMPCI_SPDIF_LOOP:
1727 case CMPCI_SPDIF_LEGACY:
1728 case CMPCI_SPDIF_OUT_VOLTAGE:
1729 case CMPCI_SPDIF_IN_PHASE:
1730 case CMPCI_REAR:
1731 case CMPCI_INDIVIDUAL:
1732 case CMPCI_REVERSE:
1733 case CMPCI_SURROUND:
1734 cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
1735 break;
1736
1737 default:
1738 return EINVAL;
1739 }
1740
1741 return 0;
1742 }
1743
1744 /* ARGSUSED */
1745 static size_t
1746 cmpci_round_buffersize(handle, direction, bufsize)
1747 void *handle;
1748 int direction;
1749 size_t bufsize;
1750 {
1751 if (bufsize > 0x10000)
1752 bufsize = 0x10000;
1753
1754 return bufsize;
1755 }
1756
1757
1758 static paddr_t
1759 cmpci_mappage(handle, addr, offset, prot)
1760 void *handle;
1761 void *addr;
1762 off_t offset;
1763 int prot;
1764 {
1765 struct cmpci_softc *sc = handle;
1766 struct cmpci_dmanode *p;
1767
1768 if (offset < 0 || NULL == (p = cmpci_find_dmamem(sc, addr)))
1769 return -1;
1770
1771 return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
1772 sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
1773 offset, prot, BUS_DMA_WAITOK);
1774 }
1775
1776
1777 /* ARGSUSED */
1778 static int
1779 cmpci_get_props(handle)
1780 void *handle;
1781 {
1782 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1783 }
1784
1785
1786 static int
1787 cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
1788 void *handle;
1789 void *start, *end;
1790 int blksize;
1791 void (*intr) __P((void *));
1792 void *arg;
1793 struct audio_params *param;
1794 {
1795 struct cmpci_softc *sc = handle;
1796 struct cmpci_dmanode *p;
1797 int bps;
1798
1799 sc->sc_play.intr = intr;
1800 sc->sc_play.intr_arg = arg;
1801 bps = param->channels*param->precision*param->factor / 8;
1802 if (!bps)
1803 return EINVAL;
1804
1805 /* set DMA frame */
1806 if (!(p = cmpci_find_dmamem(sc, start)))
1807 return EINVAL;
1808 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE,
1809 DMAADDR(p));
1810 delay(10);
1811 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
1812 ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
1813 delay(10);
1814
1815 /* set interrupt count */
1816 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES,
1817 (blksize + bps - 1) / bps - 1);
1818 delay(10);
1819
1820 /* start DMA */
1821 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */
1822 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
1823 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
1824
1825 return 0;
1826 }
1827
1828 static int
1829 cmpci_trigger_input(handle, start, end, blksize, intr, arg, param)
1830 void *handle;
1831 void *start, *end;
1832 int blksize;
1833 void (*intr) __P((void *));
1834 void *arg;
1835 struct audio_params *param;
1836 {
1837 struct cmpci_softc *sc = handle;
1838 struct cmpci_dmanode *p;
1839 int bps;
1840
1841 sc->sc_rec.intr = intr;
1842 sc->sc_rec.intr_arg = arg;
1843 bps = param->channels*param->precision*param->factor/8;
1844 if (!bps)
1845 return EINVAL;
1846
1847 /* set DMA frame */
1848 if (!(p=cmpci_find_dmamem(sc, start)))
1849 return EINVAL;
1850 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
1851 DMAADDR(p));
1852 delay(10);
1853 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
1854 ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
1855 delay(10);
1856
1857 /* set interrupt count */
1858 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
1859 (blksize + bps - 1) / bps - 1);
1860 delay(10);
1861
1862 /* start DMA */
1863 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
1864 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
1865 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
1866
1867 return 0;
1868 }
1869
1870
1871 /* end of file */
1872