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