cmpci.c revision 1.1 1 /* $NetBSD: cmpci.c,v 1.1 2000/04/30 21:59:58 augustss 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 <AoiMoe (at) imou.to> .
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 (but, I have no interest...)
38 * - SPDIF support.
39 *
40 * ACKNOWLEDGEMENT:
41 * - Lennart Augustsson : He touched up this code.
42 *
43 */
44
45 #undef CMPCI_SPDIF_SUPPORT /* XXX: not working */
46
47 #if defined(AUDIO_DEBUG) || defined(DEBUG)
48 #define DPRINTF(x) printf x
49 #else
50 #define DPRINTF(x)
51 #endif
52
53 #include "mpu.h"
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kernel.h>
58 #include <sys/malloc.h>
59 #include <sys/device.h>
60 #include <sys/proc.h>
61
62 #include <dev/pci/pcidevs.h>
63 #include <dev/pci/pcivar.h>
64
65 #include <sys/audioio.h>
66 #include <dev/audio_if.h>
67 #include <dev/midi_if.h>
68
69 #include <dev/mulaw.h>
70 #include <dev/auconv.h>
71 #include <dev/pci/cmpcireg.h>
72 #include <dev/pci/cmpcivar.h>
73
74 #include <dev/ic/mpuvar.h>
75 #include <machine/bus.h>
76 #include <machine/intr.h>
77
78 /*
79 * Low-level HW interface
80 */
81 static __inline uint8_t cmpci_mixerreg_read __P((struct cmpci_softc *,
82 uint8_t));
83 static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *,
84 uint8_t, uint8_t));
85 static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *,
86 int, int,
87 uint32_t, uint32_t));
88 static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *,
89 int, uint32_t));
90 static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *,
91 int, uint32_t));
92 static int cmpci_rate_to_index __P((int));
93 static __inline int cmpci_index_to_rate __P((int));
94 static __inline int cmpci_index_to_divider __P((int));
95
96 static int cmpci_adjust __P((int, int));
97 static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int));
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 int cmpci_mappage __P((void *, void *, int, 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 };
181
182
183 /*
184 * Low-level HW interface
185 */
186
187 /* mixer register read/write */
188 static __inline uint8_t
189 cmpci_mixerreg_read(sc, no)
190 struct cmpci_softc *sc;
191 uint8_t no;
192 {
193 uint8_t ret;
194
195 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
196 delay(10);
197 ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
198 delay(10);
199 return ret;
200 }
201
202 static __inline void
203 cmpci_mixerreg_write(sc, no, val)
204 struct cmpci_softc *sc;
205 uint8_t no, val;
206 {
207 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
208 delay(10);
209 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
210 delay(10);
211 }
212
213
214 /* register partial write */
215 static __inline void
216 cmpci_reg_partial_write_4(sc, no, shift, mask, val)
217 struct cmpci_softc *sc;
218 int no, shift;
219 uint32_t mask, val;
220 {
221 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
222 (val<<shift) |
223 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
224 delay(10);
225 }
226
227 /* register set/clear bit */
228 static __inline void
229 cmpci_reg_set_4(sc, no, mask)
230 struct cmpci_softc *sc;
231 int no;
232 uint32_t mask;
233 {
234 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
235 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
236 delay(10);
237 }
238
239 static __inline void
240 cmpci_reg_clear_4(sc, no, mask)
241 struct cmpci_softc *sc;
242 int no;
243 uint32_t mask;
244 {
245 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
246 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
247 delay(10);
248 }
249
250
251 /* rate */
252 static struct {
253 int rate;
254 int divider;
255 } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
256 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
257 _RATE(5512),
258 _RATE(8000),
259 _RATE(11025),
260 _RATE(16000),
261 _RATE(22050),
262 _RATE(32000),
263 _RATE(44100),
264 _RATE(48000)
265 #undef _RATE
266 };
267
268 static int
269 cmpci_rate_to_index(rate)
270 int rate;
271 {
272 int i;
273
274 for (i = 0; i < CMPCI_REG_NUMRATE - 2; i++)
275 if (rate <=
276 (cmpci_rate_table[i].rate+cmpci_rate_table[i+1].rate) / 2)
277 return i;
278 return i; /* 48000 */
279 }
280
281 static __inline int
282 cmpci_index_to_rate(index)
283 int index;
284 {
285 return cmpci_rate_table[index].rate;
286 }
287
288 static __inline int
289 cmpci_index_to_divider(index)
290 int index;
291 {
292 return cmpci_rate_table[index].divider;
293 }
294
295
296 /*
297 * interface to configure the device.
298 */
299
300 static int
301 cmpci_match(parent, match, aux)
302 struct device *parent;
303 struct cfdata *match;
304 void *aux;
305 {
306 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
307
308 if ( PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMEDIA &&
309 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338A ||
310 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338B ||
311 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738) )
312 return 1;
313
314 return 0;
315 }
316
317 static void
318 cmpci_attach(parent, self, aux)
319 struct device *parent, *self;
320 void *aux;
321 {
322 struct cmpci_softc *sc = (struct cmpci_softc *)self;
323 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
324 pci_intr_handle_t ih;
325 char const *strintr;
326 int i, v;
327
328 sc->sc_revision = PCI_REVISION(pa->pa_class);
329 sc->sc_model = PCI_PRODUCT(pa->pa_id);
330 switch (sc->sc_model) {
331 case PCI_PRODUCT_CMEDIA_CMI8338A:
332 printf(": CMI8338A PCI Audio Device\n");
333 break;
334 case PCI_PRODUCT_CMEDIA_CMI8338B:
335 printf(": CMI8338B PCI Audio Device\n");
336 break;
337 case PCI_PRODUCT_CMEDIA_CMI8738:
338 printf(": CMI8738 PCI Audio Device\n");
339 break;
340 }
341
342 /* map I/O space */
343 if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
344 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
345 printf("%s: failed to map I/O space\n", sc->sc_dev.dv_xname);
346 return;
347 }
348
349 /* interrupt */
350 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
351 pa->pa_intrline, &ih)) {
352 printf("%s: failed to map interrupt\n", sc->sc_dev.dv_xname);
353 return;
354 }
355 strintr = pci_intr_string(pa->pa_pc, ih);
356 sc->sc_ih=pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr, sc);
357 if (sc->sc_ih == NULL) {
358 printf("%s: failed to establish interrupt",
359 sc->sc_dev.dv_xname);
360 if (strintr != NULL)
361 printf(" at %s", strintr);
362 printf("\n");
363 return;
364 }
365 printf("%s: intr at %s\n", sc->sc_dev.dv_xname, strintr);
366
367 sc->sc_dmat = pa->pa_dmat;
368
369 audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
370
371 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
372 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
373 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
374 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
375 CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE);
376 for (i = 0; i < CMPCI_NDEVS; i++) {
377 switch(i) {
378 case CMPCI_MIC_VOL:
379 case CMPCI_LINE_IN_VOL:
380 v = 0;
381 break;
382 case CMPCI_BASS:
383 case CMPCI_TREBLE:
384 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
385 break;
386 case CMPCI_CD_IN_MUTE:
387 case CMPCI_MIC_IN_MUTE:
388 case CMPCI_LINE_IN_MUTE:
389 case CMPCI_FM_IN_MUTE:
390 case CMPCI_CD_SWAP:
391 case CMPCI_MIC_SWAP:
392 case CMPCI_LINE_SWAP:
393 case CMPCI_FM_SWAP:
394 v = 0;
395 break;
396 case CMPCI_CD_OUT_MUTE:
397 case CMPCI_MIC_OUT_MUTE:
398 case CMPCI_LINE_OUT_MUTE:
399 v = 1;
400 break;
401 default:
402 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
403 }
404 sc->gain[i][CMPCI_LEFT] = sc->gain[i][CMPCI_RIGHT] = v;
405 cmpci_set_mixer_gain(sc, i);
406 }
407 }
408
409
410 static int
411 cmpci_intr(handle)
412 void *handle;
413 {
414 struct cmpci_softc *sc = handle;
415 uint32_t intrstat;
416
417 intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
418 CMPCI_REG_INTR_STATUS);
419 delay(10);
420
421 if (!(intrstat & CMPCI_REG_ANY_INTR))
422 return 0;
423
424 /* disable and reset intr */
425 if (intrstat & CMPCI_REG_CH0_INTR)
426 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
427 CMPCI_REG_CH0_INTR_ENABLE);
428 if (intrstat & CMPCI_REG_CH1_INTR)
429 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
430 CMPCI_REG_CH1_INTR_ENABLE);
431
432 if (intrstat & CMPCI_REG_CH0_INTR) {
433 if (sc->sc_play.intr != NULL)
434 (*sc->sc_play.intr)(sc->sc_play.intr_arg);
435 }
436 if (intrstat & CMPCI_REG_CH1_INTR) {
437 if (sc->sc_rec.intr != NULL)
438 (*sc->sc_rec.intr)(sc->sc_rec.intr_arg);
439 }
440
441 /* enable intr */
442 if (intrstat & CMPCI_REG_CH0_INTR)
443 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
444 CMPCI_REG_CH0_INTR_ENABLE);
445 if (intrstat & CMPCI_REG_CH1_INTR)
446 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
447 CMPCI_REG_CH1_INTR_ENABLE);
448
449 return 0;
450 }
451
452
453 /* open/close */
454 static int
455 cmpci_open(handle, flags)
456 void *handle;
457 int flags;
458 {
459 #if 0
460 struct cmpci_softc *sc = handle;
461 #endif
462
463 return 0;
464 }
465
466 static void
467 cmpci_close(handle)
468 void *handle;
469 {
470 }
471
472 static int
473 cmpci_query_encoding(handle, fp)
474 void *handle;
475 struct audio_encoding *fp;
476 {
477 #if 0
478 struct cmpci_softc *sc = handle;
479 #endif
480
481 switch (fp->index) {
482 case 0:
483 strcpy(fp->name, AudioEulinear);
484 fp->encoding = AUDIO_ENCODING_ULINEAR;
485 fp->precision = 8;
486 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
487 break;
488 case 1:
489 strcpy(fp->name, AudioEmulaw);
490 fp->encoding = AUDIO_ENCODING_ULAW;
491 fp->precision = 8;
492 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
493 break;
494 case 2:
495 strcpy(fp->name, AudioEalaw);
496 fp->encoding = AUDIO_ENCODING_ALAW;
497 fp->precision = 8;
498 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
499 break;
500 case 3:
501 strcpy(fp->name, AudioEslinear);
502 fp->encoding = AUDIO_ENCODING_SLINEAR;
503 fp->precision = 8;
504 fp->flags = 0;
505 break;
506 case 4:
507 strcpy(fp->name, AudioEslinear_le);
508 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
509 fp->precision = 16;
510 fp->flags = 0;
511 break;
512 case 5:
513 strcpy(fp->name, AudioEulinear_le);
514 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
515 fp->precision = 16;
516 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
517 break;
518 case 6:
519 strcpy(fp->name, AudioEslinear_be);
520 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
521 fp->precision = 16;
522 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
523 break;
524 case 7:
525 strcpy(fp->name, AudioEulinear_be);
526 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
527 fp->precision = 16;
528 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
529 break;
530 default:
531 return EINVAL;
532 }
533 return 0;
534 }
535
536
537 static int
538 cmpci_set_params(handle, setmode, usemode, play, rec)
539 void *handle;
540 int setmode, usemode;
541 struct audio_params *play, *rec;
542 {
543 int i;
544 struct cmpci_softc *sc = handle;
545
546 for (i = 0; i < 2; i++) {
547 int md_format;
548 int md_divide;
549 int md_index;
550 int mode;
551 struct audio_params *p;
552
553 switch (i) {
554 case 0:
555 mode = AUMODE_PLAY;
556 p = play;
557 break;
558 case 1:
559 mode = AUMODE_RECORD;
560 p = rec;
561 break;
562 }
563
564 if (!(setmode & mode))
565 continue;
566
567
568 /* format */
569 p->sw_code = NULL;
570 switch ( p->channels ) {
571 case 1:
572 md_format = CMPCI_REG_FORMAT_MONO;
573 break;
574 case 2:
575 md_format = CMPCI_REG_FORMAT_STEREO;
576 break;
577 default:
578 return (EINVAL);
579 }
580 switch (p->encoding) {
581 case AUDIO_ENCODING_ULAW:
582 if (p->precision != 8)
583 return (EINVAL);
584 if (mode & AUMODE_PLAY) {
585 p->factor = 2;
586 p->sw_code = mulaw_to_slinear16_le;
587 md_format |= CMPCI_REG_FORMAT_16BIT;
588 } else {
589 p->sw_code = ulinear8_to_mulaw;
590 md_format |= CMPCI_REG_FORMAT_8BIT;
591 }
592 break;
593 case AUDIO_ENCODING_ALAW:
594 if (p->precision != 8)
595 return (EINVAL);
596 if (mode & AUMODE_PLAY) {
597 p->factor = 2;
598 p->sw_code = alaw_to_slinear16_le;
599 md_format |= CMPCI_REG_FORMAT_16BIT;
600 } else {
601 p->sw_code = ulinear8_to_alaw;
602 md_format |= CMPCI_REG_FORMAT_8BIT;
603 }
604 break;
605 case AUDIO_ENCODING_SLINEAR_LE:
606 switch (p->precision) {
607 case 8:
608 p->sw_code = change_sign8;
609 md_format |= CMPCI_REG_FORMAT_8BIT;
610 break;
611 case 16:
612 md_format |= CMPCI_REG_FORMAT_16BIT;
613 break;
614 default:
615 return (EINVAL);
616 }
617 break;
618 case AUDIO_ENCODING_SLINEAR_BE:
619 switch (p->precision) {
620 case 8:
621 md_format |= CMPCI_REG_FORMAT_8BIT;
622 p->sw_code = change_sign8;
623 break;
624 case 16:
625 md_format |= CMPCI_REG_FORMAT_16BIT;
626 p->sw_code = swap_bytes;
627 break;
628 default:
629 return (EINVAL);
630 }
631 break;
632 case AUDIO_ENCODING_ULINEAR_LE:
633 switch (p->precision) {
634 case 8:
635 md_format |= CMPCI_REG_FORMAT_8BIT;
636 break;
637 case 16:
638 md_format |= CMPCI_REG_FORMAT_16BIT;
639 p->sw_code = change_sign16_le;
640 break;
641 default:
642 return (EINVAL);
643 }
644 break;
645 case AUDIO_ENCODING_ULINEAR_BE:
646 switch (p->precision) {
647 case 8:
648 md_format |= CMPCI_REG_FORMAT_8BIT;
649 break;
650 case 16:
651 md_format |= CMPCI_REG_FORMAT_16BIT;
652 if (mode & AUMODE_PLAY)
653 p->sw_code =swap_bytes_change_sign16_le;
654 else
655 p->sw_code =change_sign16_swap_bytes_le;
656 break;
657 default:
658 return (EINVAL);
659 }
660 break;
661 default:
662 return (EINVAL);
663 }
664 if (mode & AUMODE_PLAY)
665 cmpci_reg_partial_write_4(sc,
666 CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH0_FORMAT_SHIFT,
667 CMPCI_REG_CH0_FORMAT_MASK, md_format);
668 else
669 cmpci_reg_partial_write_4(sc,
670 CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_CH1_FORMAT_SHIFT,
671 CMPCI_REG_CH1_FORMAT_MASK, md_format);
672 /* sample rate */
673 md_index = cmpci_rate_to_index(p->sample_rate);
674 md_divide = cmpci_index_to_divider(md_index);
675 p->sample_rate = cmpci_index_to_rate(md_index);
676 #if 0
677 DPRINTF(("%s: sample:%d, divider=%d\n",
678 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
679 #endif
680 if (mode & AUMODE_PLAY) {
681 cmpci_reg_partial_write_4(sc,
682 CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
683 CMPCI_REG_DAC_FS_MASK, md_divide);
684 #ifdef CMPCI_SPDIF_SUPPORT
685 switch (md_divide) {
686 case CMPCI_REG_RATE_44100:
687 cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
688 CMPCI_REG_SPDIF_48K);
689 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
690 CMPCI_REG_SPDIF_LOOP);
691 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
692 CMPCI_REG_SPDIF0_ENABLE);
693 break;
694 case CMPCI_REG_RATE_48000:
695 cmpci_reg_set_4(sc, CMPCI_REG_MISC,
696 CMPCI_REG_SPDIF_48K);
697 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
698 CMPCI_REG_SPDIF_LOOP);
699 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
700 CMPCI_REG_SPDIF0_ENABLE);
701 break;
702 default:
703 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
704 CMPCI_REG_SPDIF0_ENABLE);
705 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
706 CMPCI_REG_SPDIF_LOOP);
707 }
708 #endif
709 } else {
710 cmpci_reg_partial_write_4(sc,
711 CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
712 CMPCI_REG_ADC_FS_MASK, md_divide);
713 #ifdef CMPCI_SPDIF_SUPPORT
714 if (sc->in_mask & CMPCI_SPDIF_IN) {
715 switch (md_divide) {
716 case CMPCI_REG_RATE_44100:
717 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
718 CMPCI_REG_SPDIF1_ENABLE);
719 break;
720 default:
721 return EINVAL;
722 }
723 } else
724 cmpci_reg_clear_4(sc,
725 CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF1_ENABLE);
726 #endif
727 }
728 }
729 return 0;
730 }
731
732 /* ARGSUSED */
733 static int
734 cmpci_round_blocksize(handle, block)
735 void *handle;
736 int block;
737 {
738 return (block & -4);
739 }
740
741 static int
742 cmpci_halt_output(handle)
743 void *handle;
744 {
745 struct cmpci_softc *sc = handle;
746 int s;
747
748 s = splaudio();
749 sc->sc_play.intr = NULL;
750 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
751 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
752 /* wait for reset DMA */
753 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
754 delay(10);
755 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
756 splx(s);
757
758 return 0;
759 }
760
761 static int
762 cmpci_halt_input(handle)
763 void *handle;
764 {
765 struct cmpci_softc *sc = handle;
766 int s;
767
768 s = splaudio();
769 sc->sc_rec.intr = NULL;
770 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
771 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
772 /* wait for reset DMA */
773 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
774 delay(10);
775 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
776 splx(s);
777
778 return 0;
779 }
780
781
782 /* get audio device information */
783 static int
784 cmpci_getdev(handle, ad)
785 void *handle;
786 struct audio_device *ad;
787 {
788 struct cmpci_softc *sc = handle;
789
790 strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name));
791 snprintf(ad->version, sizeof(ad->version), "0x%02x", sc->sc_revision);
792 switch (sc->sc_model) {
793 case PCI_PRODUCT_CMEDIA_CMI8338A:
794 strncpy(ad->config, "CMI8338A", sizeof(ad->config));
795 break;
796 case PCI_PRODUCT_CMEDIA_CMI8338B:
797 strncpy(ad->config, "CMI8338B", sizeof(ad->config));
798 break;
799 case PCI_PRODUCT_CMEDIA_CMI8738:
800 strncpy(ad->config, "CMI8738", sizeof(ad->config));
801 break;
802 default:
803 strncpy(ad->config, "unknown", sizeof(ad->config));
804 }
805
806 return 0;
807 }
808
809
810 /* mixer device information */
811 int
812 cmpci_query_devinfo(handle, dip)
813 void *handle;
814 mixer_devinfo_t *dip;
815 {
816 #if 0
817 struct cmpci_softc *sc = handle;
818 #endif
819
820 switch (dip->index) {
821 case CMPCI_MASTER_VOL:
822 dip->type = AUDIO_MIXER_VALUE;
823 dip->mixer_class = CMPCI_OUTPUT_CLASS;
824 dip->prev = dip->next = AUDIO_MIXER_LAST;
825 strcpy(dip->label.name, AudioNmaster);
826 dip->un.v.num_channels = 2;
827 strcpy(dip->un.v.units.name, AudioNvolume);
828 return 0;
829 case CMPCI_FM_VOL:
830 dip->type = AUDIO_MIXER_VALUE;
831 dip->mixer_class = CMPCI_INPUT_CLASS;
832 dip->prev = AUDIO_MIXER_LAST;
833 dip->next = CMPCI_FM_IN_MUTE;
834 strcpy(dip->label.name, AudioNfmsynth);
835 dip->un.v.num_channels = 2;
836 strcpy(dip->un.v.units.name, AudioNvolume);
837 return 0;
838 case CMPCI_CD_VOL:
839 dip->type = AUDIO_MIXER_VALUE;
840 dip->mixer_class = CMPCI_INPUT_CLASS;
841 dip->prev = AUDIO_MIXER_LAST;
842 dip->next = CMPCI_CD_IN_MUTE;
843 strcpy(dip->label.name, AudioNcd);
844 dip->un.v.num_channels = 2;
845 strcpy(dip->un.v.units.name, AudioNvolume);
846 return 0;
847 case CMPCI_VOICE_VOL:
848 dip->type = AUDIO_MIXER_VALUE;
849 dip->mixer_class = CMPCI_OUTPUT_CLASS;
850 dip->prev = AUDIO_MIXER_LAST;
851 dip->next = AUDIO_MIXER_LAST;
852 strcpy(dip->label.name, AudioNdac);
853 dip->un.v.num_channels = 2;
854 strcpy(dip->un.v.units.name, AudioNvolume);
855 return 0;
856 case CMPCI_OUTPUT_CLASS:
857 dip->type = AUDIO_MIXER_CLASS;
858 dip->mixer_class = CMPCI_INPUT_CLASS;
859 dip->next = dip->prev = AUDIO_MIXER_LAST;
860 strcpy(dip->label.name, AudioCoutputs);
861 return 0;
862 case CMPCI_MIC_VOL:
863 dip->type = AUDIO_MIXER_VALUE;
864 dip->mixer_class = CMPCI_INPUT_CLASS;
865 dip->prev = AUDIO_MIXER_LAST;
866 dip->next = CMPCI_MIC_IN_MUTE;
867 strcpy(dip->label.name, AudioNmicrophone);
868 dip->un.v.num_channels = 1;
869 strcpy(dip->un.v.units.name, AudioNvolume);
870 return 0;
871 case CMPCI_LINE_IN_VOL:
872 dip->type = AUDIO_MIXER_VALUE;
873 dip->mixer_class = CMPCI_INPUT_CLASS;
874 dip->prev = AUDIO_MIXER_LAST;
875 dip->next = CMPCI_LINE_IN_MUTE;
876 strcpy(dip->label.name, AudioNline);
877 dip->un.v.num_channels = 2;
878 strcpy(dip->un.v.units.name, AudioNvolume);
879 return 0;
880 case CMPCI_RECORD_SOURCE:
881 dip->mixer_class = CMPCI_RECORD_CLASS;
882 dip->prev = dip->next = AUDIO_MIXER_LAST;
883 strcpy(dip->label.name, AudioNsource);
884 dip->type = AUDIO_MIXER_SET;
885 #ifdef CMPCI_SPDIF_SUPPORT
886 dip->un.s.num_mem = 5;
887 #else
888 dip->un.s.num_mem = 4;
889 #endif
890 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
891 dip->un.s.member[0].mask = 1 << CMPCI_MIC_VOL;
892 strcpy(dip->un.s.member[1].label.name, AudioNcd);
893 dip->un.s.member[1].mask = 1 << CMPCI_CD_VOL;
894 strcpy(dip->un.s.member[2].label.name, AudioNline);
895 dip->un.s.member[2].mask = 1 << CMPCI_LINE_IN_VOL;
896 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
897 dip->un.s.member[3].mask = 1 << CMPCI_FM_VOL;
898 #ifdef CMPCI_SPDIF_SUPPORT
899 strcpy(dip->un.s.member[4].label.name, CmpciNspdif);
900 dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_IN;
901 #endif
902 return 0;
903 case CMPCI_BASS:
904 dip->prev = dip->next = AUDIO_MIXER_LAST;
905 strcpy(dip->label.name, AudioNbass);
906 dip->type = AUDIO_MIXER_VALUE;
907 dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
908 dip->un.v.num_channels = 2;
909 strcpy(dip->un.v.units.name, AudioNbass);
910 return 0;
911 case CMPCI_TREBLE:
912 dip->prev = dip->next = AUDIO_MIXER_LAST;
913 strcpy(dip->label.name, AudioNtreble);
914 dip->type = AUDIO_MIXER_VALUE;
915 dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
916 dip->un.v.num_channels = 2;
917 strcpy(dip->un.v.units.name, AudioNtreble);
918 return 0;
919 case CMPCI_RECORD_CLASS:
920 dip->type = AUDIO_MIXER_CLASS;
921 dip->mixer_class = CMPCI_RECORD_CLASS;
922 dip->next = dip->prev = AUDIO_MIXER_LAST;
923 strcpy(dip->label.name, AudioCrecord);
924 return 0;
925 case CMPCI_INPUT_CLASS:
926 dip->type = AUDIO_MIXER_CLASS;
927 dip->mixer_class = CMPCI_INPUT_CLASS;
928 dip->next = dip->prev = AUDIO_MIXER_LAST;
929 strcpy(dip->label.name, AudioCinputs);
930 return 0;
931 case CMPCI_PCSPEAKER:
932 dip->type = AUDIO_MIXER_VALUE;
933 dip->mixer_class = CMPCI_INPUT_CLASS;
934 dip->prev = dip->next = AUDIO_MIXER_LAST;
935 strcpy(dip->label.name, "pc_speaker");
936 dip->un.v.num_channels = 1;
937 strcpy(dip->un.v.units.name, AudioNvolume);
938 return 0;
939 case CMPCI_INPUT_GAIN:
940 dip->type = AUDIO_MIXER_VALUE;
941 dip->mixer_class = CMPCI_INPUT_CLASS;
942 dip->prev = dip->next = AUDIO_MIXER_LAST;
943 strcpy(dip->label.name, AudioNinput);
944 dip->un.v.num_channels = 2;
945 strcpy(dip->un.v.units.name, AudioNvolume);
946 return 0;
947 case CMPCI_OUTPUT_GAIN:
948 dip->type = AUDIO_MIXER_VALUE;
949 dip->mixer_class = CMPCI_OUTPUT_CLASS;
950 dip->prev = dip->next = AUDIO_MIXER_LAST;
951 strcpy(dip->label.name, AudioNoutput);
952 dip->un.v.num_channels = 2;
953 strcpy(dip->un.v.units.name, AudioNvolume);
954 return 0;
955 case CMPCI_AGC:
956 dip->type = AUDIO_MIXER_ENUM;
957 dip->mixer_class = CMPCI_INPUT_CLASS;
958 dip->prev = dip->next = AUDIO_MIXER_LAST;
959 strcpy(dip->label.name, "agc");
960 dip->un.e.num_mem = 2;
961 strcpy(dip->un.e.member[0].label.name, AudioNoff);
962 dip->un.e.member[0].ord = 0;
963 strcpy(dip->un.e.member[1].label.name, AudioNon);
964 dip->un.e.member[1].ord = 1;
965 return 0;
966 case CMPCI_EQUALIZATION_CLASS:
967 dip->type = AUDIO_MIXER_CLASS;
968 dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
969 dip->next = dip->prev = AUDIO_MIXER_LAST;
970 strcpy(dip->label.name, AudioCequalization);
971 return 0;
972
973 case CMPCI_CD_IN_MUTE:
974 dip->prev = CMPCI_CD_VOL;
975 dip->next = CMPCI_CD_SWAP;
976 dip->mixer_class = CMPCI_INPUT_CLASS;
977 goto mute;
978 case CMPCI_MIC_IN_MUTE:
979 dip->prev = CMPCI_MIC_VOL;
980 dip->next = CMPCI_MIC_SWAP;
981 dip->mixer_class = CMPCI_INPUT_CLASS;
982 goto mute;
983 case CMPCI_LINE_IN_MUTE:
984 dip->prev = CMPCI_LINE_IN_VOL;
985 dip->next = CMPCI_LINE_SWAP;
986 dip->mixer_class = CMPCI_INPUT_CLASS;
987 goto mute;
988 case CMPCI_FM_IN_MUTE:
989 dip->prev = CMPCI_FM_VOL;
990 dip->next = CMPCI_FM_SWAP;
991 dip->mixer_class = CMPCI_INPUT_CLASS;
992 goto mute;
993 case CMPCI_CD_SWAP:
994 dip->prev = CMPCI_CD_IN_MUTE;
995 dip->next = CMPCI_CD_OUT_MUTE;
996 goto swap;
997 case CMPCI_MIC_SWAP:
998 dip->prev = CMPCI_MIC_IN_MUTE;
999 dip->next = CMPCI_MIC_OUT_MUTE;
1000 goto swap;
1001 case CMPCI_LINE_SWAP:
1002 dip->prev = CMPCI_LINE_IN_MUTE;
1003 dip->next = CMPCI_LINE_OUT_MUTE;
1004 goto swap;
1005 case CMPCI_FM_SWAP:
1006 dip->prev = CMPCI_FM_IN_MUTE;
1007 dip->next = AUDIO_MIXER_LAST;
1008 swap:
1009 dip->mixer_class = CMPCI_INPUT_CLASS;
1010 strcpy(dip->label.name, AudioNswap);
1011 goto mute1;
1012
1013 case CMPCI_CD_OUT_MUTE:
1014 dip->prev = CMPCI_CD_SWAP;
1015 dip->next = AUDIO_MIXER_LAST;
1016 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1017 goto mute;
1018 case CMPCI_MIC_OUT_MUTE:
1019 dip->prev = CMPCI_MIC_SWAP;
1020 dip->next = AUDIO_MIXER_LAST;
1021 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1022 goto mute;
1023 case CMPCI_LINE_OUT_MUTE:
1024 dip->prev = CMPCI_LINE_SWAP;
1025 dip->next = AUDIO_MIXER_LAST;
1026 dip->mixer_class = CMPCI_OUTPUT_CLASS;
1027 mute:
1028 strcpy(dip->label.name, AudioNmute);
1029 mute1:
1030 dip->type = AUDIO_MIXER_ENUM;
1031 dip->un.e.num_mem = 2;
1032 strcpy(dip->un.e.member[0].label.name, AudioNoff);
1033 dip->un.e.member[0].ord = 0;
1034 strcpy(dip->un.e.member[1].label.name, AudioNon);
1035 dip->un.e.member[1].ord = 1;
1036 return 0;
1037 }
1038
1039 return ENXIO;
1040 }
1041
1042 static int
1043 cmpci_alloc_dmamem(sc, size, type, flags, r_addr)
1044 struct cmpci_softc *sc;
1045 size_t size;
1046 int type, flags;
1047 caddr_t *r_addr;
1048 {
1049 int error = 0;
1050 struct cmpci_dmanode *n;
1051 int w;
1052
1053 n = malloc(sizeof(struct cmpci_dmanode), type, flags);
1054 if (n == NULL) {
1055 error = ENOMEM;
1056 goto quit;
1057 }
1058
1059 w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1060 #define CMPCI_DMABUF_ALIGN 0x4
1061 #define CMPCI_DMABUF_BOUNDARY 0x0
1062 n->cd_tag = sc->sc_dmat;
1063 n->cd_size = size;
1064 error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
1065 CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
1066 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w);
1067 if (error)
1068 goto mfree;
1069 error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
1070 &n->cd_addr, w | BUS_DMA_COHERENT);
1071 if (error)
1072 goto dmafree;
1073 error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
1074 w, &n->cd_map);
1075 if (error)
1076 goto unmap;
1077 error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
1078 NULL, w);
1079 if (error)
1080 goto destroy;
1081
1082 n->cd_next = sc->sc_dmap;
1083 sc->sc_dmap = n;
1084 *r_addr = KVADDR(n);
1085 return 0;
1086
1087 destroy:
1088 bus_dmamap_destroy(n->cd_tag, n->cd_map);
1089 unmap:
1090 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1091 dmafree:
1092 bus_dmamem_free(n->cd_tag,
1093 n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1094 mfree:
1095 free(n, type);
1096 quit:
1097 return error;
1098 }
1099
1100 static int
1101 cmpci_free_dmamem(sc, addr, type)
1102 struct cmpci_softc *sc;
1103 caddr_t addr;
1104 int type;
1105 {
1106 struct cmpci_dmanode **nnp;
1107
1108 for (nnp = &sc->sc_dmap; *nnp; nnp= &(*nnp)->cd_next) {
1109 if ((*nnp)->cd_addr == addr) {
1110 struct cmpci_dmanode *n = *nnp;
1111 bus_dmamap_unload(n->cd_tag, n->cd_map);
1112 bus_dmamap_destroy(n->cd_tag, n->cd_map);
1113 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1114 bus_dmamem_free(n->cd_tag, n->cd_segs,
1115 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1116 free(n, type);
1117 return 0;
1118 }
1119 }
1120 return -1;
1121 }
1122
1123 static struct cmpci_dmanode *
1124 cmpci_find_dmamem(sc, addr)
1125 struct cmpci_softc *sc;
1126 caddr_t addr;
1127 {
1128 struct cmpci_dmanode *p;
1129 for (p=sc->sc_dmap; p; p=p->cd_next)
1130 if ( KVADDR(p) == (void *)addr )
1131 break;
1132 return p;
1133 }
1134
1135
1136 #if 0
1137 static void
1138 cmpci_print_dmamem __P((struct cmpci_dmanode *p));
1139 static void
1140 cmpci_print_dmamem(p)
1141 struct cmpci_dmanode *p;
1142 {
1143 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1144 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
1145 (void *)DMAADDR(p), (void *)p->cd_size));
1146 }
1147 #endif /* DEBUG */
1148
1149
1150 static void *
1151 cmpci_allocm(handle, direction, size, type, flags)
1152 void *handle;
1153 int direction;
1154 size_t size;
1155 int type, flags;
1156 {
1157 struct cmpci_softc *sc = handle;
1158 caddr_t addr;
1159
1160 if (cmpci_alloc_dmamem(sc, size, type, flags, &addr))
1161 return NULL;
1162 return addr;
1163 }
1164
1165 static void
1166 cmpci_freem(handle, addr, type)
1167 void *handle;
1168 void *addr;
1169 int type;
1170 {
1171 struct cmpci_softc *sc = handle;
1172
1173 cmpci_free_dmamem(sc, addr, type);
1174 }
1175
1176
1177 #define MAXVAL 256
1178 static int
1179 cmpci_adjust(val, mask)
1180 int val, mask;
1181 {
1182 val += (MAXVAL - mask) >> 1;
1183 if (val >= MAXVAL)
1184 val = MAXVAL-1;
1185 return val & mask;
1186 }
1187
1188 static void
1189 cmpci_set_mixer_gain(sc, port)
1190 struct cmpci_softc *sc;
1191 int port;
1192 {
1193 int src;
1194
1195 switch (port) {
1196 case CMPCI_MIC_VOL:
1197 src = CMPCI_SB16_MIXER_MIC;
1198 break;
1199 case CMPCI_MASTER_VOL:
1200 src = CMPCI_SB16_MIXER_MASTER_L;
1201 break;
1202 case CMPCI_LINE_IN_VOL:
1203 src = CMPCI_SB16_MIXER_LINE_L;
1204 break;
1205 case CMPCI_VOICE_VOL:
1206 src = CMPCI_SB16_MIXER_VOICE_L;
1207 break;
1208 case CMPCI_FM_VOL:
1209 src = CMPCI_SB16_MIXER_FM_L;
1210 break;
1211 case CMPCI_CD_VOL:
1212 src = CMPCI_SB16_MIXER_CDDA_L;
1213 break;
1214 case CMPCI_INPUT_GAIN:
1215 src = CMPCI_SB16_MIXER_INGAIN_L;
1216 break;
1217 case CMPCI_OUTPUT_GAIN:
1218 src = CMPCI_SB16_MIXER_OUTGAIN_L;
1219 break;
1220 case CMPCI_TREBLE:
1221 src = CMPCI_SB16_MIXER_TREBLE_L;
1222 break;
1223 case CMPCI_BASS:
1224 src = CMPCI_SB16_MIXER_BASS_L;
1225 break;
1226 case CMPCI_PCSPEAKER:
1227 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
1228 sc->gain[port][CMPCI_LEFT]);
1229 return;
1230 default:
1231 return;
1232 }
1233 cmpci_mixerreg_write(sc, src, sc->gain[port][CMPCI_LEFT]);
1234 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
1235 sc->gain[port][CMPCI_RIGHT]);
1236 }
1237
1238 static int
1239 cmpci_set_in_ports(sc, mask)
1240 struct cmpci_softc *sc;
1241 int mask;
1242 {
1243 int bitsl, bitsr;
1244
1245 if (mask & ~((1<<CMPCI_FM_VOL) | (1<<CMPCI_LINE_IN_VOL) |
1246 (1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL)
1247 #ifdef CMPCI_SPDIF_SUPPORT
1248 | (1<<CMPCI_SPDIF_IN)
1249 #endif
1250 ))
1251 return EINVAL;
1252 bitsr = 0;
1253 if (mask & (1<<CMPCI_FM_VOL)) bitsr |= CMPCI_SB16_MIXER_FM_SRC_R;
1254 if (mask & (1<<CMPCI_LINE_IN_VOL)) bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R;
1255 if (mask & (1<<CMPCI_CD_VOL)) bitsr |= CMPCI_SB16_MIXER_CD_SRC_R;
1256 bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
1257 if (mask & (1<<CMPCI_MIC_VOL)) {
1258 bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
1259 bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
1260 }
1261 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
1262 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
1263
1264 sc->in_mask = mask;
1265
1266 return 0;
1267 }
1268
1269 static int
1270 cmpci_set_port(handle, cp)
1271 void *handle;
1272 mixer_ctrl_t *cp;
1273 {
1274 struct cmpci_softc *sc = handle;
1275 int lgain, rgain;
1276 int mask, bits;
1277 int lmask, rmask, lbits, rbits;
1278 int mute, swap;
1279
1280 switch (cp->dev) {
1281 case CMPCI_TREBLE:
1282 case CMPCI_BASS:
1283 case CMPCI_PCSPEAKER:
1284 case CMPCI_INPUT_GAIN:
1285 case CMPCI_OUTPUT_GAIN:
1286 case CMPCI_MIC_VOL:
1287 case CMPCI_LINE_IN_VOL:
1288 case CMPCI_VOICE_VOL:
1289 case CMPCI_FM_VOL:
1290 case CMPCI_CD_VOL:
1291 case CMPCI_MASTER_VOL:
1292 if (cp->type != AUDIO_MIXER_VALUE)
1293 return EINVAL;
1294 switch (cp->dev) {
1295 case CMPCI_MIC_VOL:
1296 if (cp->un.value.num_channels != 1)
1297 return EINVAL;
1298
1299 lgain = rgain =
1300 CMPCI_ADJUST_MIC_GAIN(sc,
1301 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1302 break;
1303 case CMPCI_PCSPEAKER:
1304 if (cp->un.value.num_channels != 1)
1305 return EINVAL;
1306 /* fall into */
1307 case CMPCI_INPUT_GAIN:
1308 case CMPCI_OUTPUT_GAIN:
1309 lgain = rgain = CMPCI_ADJUST_2_GAIN(sc,
1310 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1311 break;
1312 default:
1313 switch (cp->un.value.num_channels) {
1314 case 1:
1315 lgain = rgain = CMPCI_ADJUST_GAIN(sc,
1316 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1317 break;
1318 case 2:
1319 lgain = CMPCI_ADJUST_GAIN(sc,
1320 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1321 rgain = CMPCI_ADJUST_GAIN(sc,
1322 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1323 break;
1324 default:
1325 return EINVAL;
1326 }
1327 break;
1328 }
1329 sc->gain[cp->dev][CMPCI_LEFT] = lgain;
1330 sc->gain[cp->dev][CMPCI_RIGHT] = rgain;
1331
1332 cmpci_set_mixer_gain(sc, cp->dev);
1333 break;
1334
1335 case CMPCI_RECORD_SOURCE:
1336 if (cp->type != AUDIO_MIXER_SET)
1337 return EINVAL;
1338 #ifdef CMPCI_SPDIF_SUPPORT
1339 if (cp->un.mask & (1<<CMPCI_SPDIF_IN))
1340 cp->un.mask = 1<<CMPCI_SPDIF_IN;
1341 #endif
1342 return cmpci_set_in_ports(sc, cp->un.mask);
1343
1344 case CMPCI_AGC:
1345 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_AGC, cp->un.ord & 1);
1346 break;
1347
1348 case CMPCI_CD_OUT_MUTE:
1349 mask = CMPCI_SB16_SW_CD;
1350 goto omute;
1351 case CMPCI_MIC_OUT_MUTE:
1352 mask = CMPCI_SB16_SW_MIC;
1353 goto omute;
1354 case CMPCI_LINE_OUT_MUTE:
1355 mask = CMPCI_SB16_SW_LINE;
1356 omute:
1357 if (cp->type != AUDIO_MIXER_ENUM)
1358 return EINVAL;
1359 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
1360 sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1361 if (cp->un.ord)
1362 bits = bits & ~mask;
1363 else
1364 bits = bits | mask;
1365 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
1366 break;
1367
1368 case CMPCI_MIC_IN_MUTE:
1369 case CMPCI_MIC_SWAP:
1370 lmask = rmask = CMPCI_SB16_SW_MIC;
1371 goto imute;
1372 case CMPCI_CD_IN_MUTE:
1373 case CMPCI_CD_SWAP:
1374 lmask = CMPCI_SB16_SW_CD_L;
1375 rmask = CMPCI_SB16_SW_CD_R;
1376 goto imute;
1377 case CMPCI_LINE_IN_MUTE:
1378 case CMPCI_LINE_SWAP:
1379 lmask = CMPCI_SB16_SW_LINE_L;
1380 rmask = CMPCI_SB16_SW_LINE_R;
1381 goto imute;
1382 case CMPCI_FM_IN_MUTE:
1383 case CMPCI_FM_SWAP:
1384 lmask = CMPCI_SB16_SW_FM_L;
1385 rmask = CMPCI_SB16_SW_FM_R;
1386 imute:
1387 if (cp->type != AUDIO_MIXER_ENUM)
1388 return EINVAL;
1389 mask = lmask | rmask;
1390 lbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_L)
1391 & ~mask;
1392 rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R)
1393 & ~mask;
1394 sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1395 if (CMPCI_IS_IN_MUTE(cp->dev)) {
1396 mute = cp->dev;
1397 swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP;
1398 } else {
1399 swap = cp->dev;
1400 mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP;
1401 }
1402 if (sc->gain[swap][CMPCI_LR]) {
1403 mask = lmask;
1404 lmask = rmask;
1405 rmask = mask;
1406 }
1407 if (!sc->gain[mute][CMPCI_LR]) {
1408 lbits = lbits | lmask;
1409 rbits = rbits | rmask;
1410 }
1411 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits);
1412 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits);
1413 break;
1414
1415 default:
1416 return EINVAL;
1417 }
1418
1419 return 0;
1420 }
1421
1422 static int
1423 cmpci_get_port(handle, cp)
1424 void *handle;
1425 mixer_ctrl_t *cp;
1426 {
1427 struct cmpci_softc *sc = handle;
1428
1429 switch (cp->dev) {
1430 case CMPCI_MIC_VOL:
1431 case CMPCI_LINE_IN_VOL:
1432 if (cp->un.value.num_channels != 1)
1433 return EINVAL;
1434 /* fall into */
1435 case CMPCI_TREBLE:
1436 case CMPCI_BASS:
1437 case CMPCI_PCSPEAKER:
1438 case CMPCI_INPUT_GAIN:
1439 case CMPCI_OUTPUT_GAIN:
1440 case CMPCI_VOICE_VOL:
1441 case CMPCI_FM_VOL:
1442 case CMPCI_CD_VOL:
1443 case CMPCI_MASTER_VOL:
1444 switch (cp->un.value.num_channels) {
1445 case 1:
1446 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1447 sc->gain[cp->dev][CMPCI_LEFT];
1448 break;
1449 case 2:
1450 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1451 sc->gain[cp->dev][CMPCI_LEFT];
1452 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1453 sc->gain[cp->dev][CMPCI_RIGHT];
1454 break;
1455 default:
1456 return EINVAL;
1457 }
1458 break;
1459
1460 case CMPCI_RECORD_SOURCE:
1461 cp->un.mask = sc->in_mask;
1462 break;
1463
1464 case CMPCI_AGC:
1465 cp->un.ord = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_AGC);
1466 break;
1467
1468 case CMPCI_CD_IN_MUTE:
1469 case CMPCI_MIC_IN_MUTE:
1470 case CMPCI_LINE_IN_MUTE:
1471 case CMPCI_FM_IN_MUTE:
1472 case CMPCI_CD_SWAP:
1473 case CMPCI_MIC_SWAP:
1474 case CMPCI_LINE_SWAP:
1475 case CMPCI_FM_SWAP:
1476 case CMPCI_CD_OUT_MUTE:
1477 case CMPCI_MIC_OUT_MUTE:
1478 case CMPCI_LINE_OUT_MUTE:
1479 cp->un.ord = sc->gain[cp->dev][CMPCI_LR];
1480 break;
1481
1482 default:
1483 return EINVAL;
1484 }
1485
1486 return 0;
1487 }
1488
1489 /* ARGSUSED */
1490 static size_t
1491 cmpci_round_buffersize(handle, direction, bufsize)
1492 void *handle;
1493 int direction;
1494 size_t bufsize;
1495 {
1496 if (bufsize > 0x10000)
1497 bufsize = 0x10000;
1498
1499 return bufsize;
1500 }
1501
1502
1503 static int
1504 cmpci_mappage(handle, addr, offset, prot)
1505 void *handle;
1506 void *addr;
1507 int offset;
1508 int prot;
1509 {
1510 struct cmpci_softc *sc = handle;
1511 struct cmpci_dmanode *p;
1512
1513 if (offset < 0 || NULL == (p = cmpci_find_dmamem(sc, addr)))
1514 return -1;
1515
1516 return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
1517 sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
1518 offset, prot, BUS_DMA_WAITOK);
1519 }
1520
1521
1522 /* ARGSUSED */
1523 static int
1524 cmpci_get_props(handle)
1525 void *handle;
1526 {
1527 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1528 }
1529
1530
1531 static int
1532 cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
1533 void *handle;
1534 void *start, *end;
1535 int blksize;
1536 void (*intr) __P((void *));
1537 void *arg;
1538 struct audio_params *param;
1539 {
1540 struct cmpci_softc *sc = handle;
1541 struct cmpci_dmanode *p;
1542 int bps;
1543
1544 sc->sc_play.intr = intr;
1545 sc->sc_play.intr_arg = arg;
1546 bps = param->channels*param->precision*param->factor / 8;
1547 if (!bps)
1548 return EINVAL;
1549
1550 /* set DMA frame */
1551 if (!(p = cmpci_find_dmamem(sc, start)))
1552 return EINVAL;
1553 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE,
1554 DMAADDR(p));
1555 delay(10);
1556 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
1557 ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
1558 delay(10);
1559
1560 /* set interrupt count */
1561 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES,
1562 (blksize + bps - 1) / bps - 1);
1563 delay(10);
1564
1565 /* start DMA */
1566 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */
1567 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
1568 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
1569
1570 return 0;
1571 }
1572
1573 static int
1574 cmpci_trigger_input(handle, start, end, blksize, intr, arg, param)
1575 void *handle;
1576 void *start, *end;
1577 int blksize;
1578 void (*intr) __P((void *));
1579 void *arg;
1580 struct audio_params *param;
1581 {
1582 struct cmpci_softc *sc = handle;
1583 struct cmpci_dmanode *p;
1584 int bps;
1585
1586 sc->sc_rec.intr = intr;
1587 sc->sc_rec.intr_arg = arg;
1588 bps = param->channels*param->precision*param->factor/8;
1589 if (!bps)
1590 return EINVAL;
1591
1592 /* set DMA frame */
1593 if (!(p=cmpci_find_dmamem(sc, start)))
1594 return EINVAL;
1595 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
1596 DMAADDR(p));
1597 delay(10);
1598 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
1599 ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
1600 delay(10);
1601
1602 /* set interrupt count */
1603 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
1604 (blksize + bps - 1) / bps - 1);
1605 delay(10);
1606
1607 /* start DMA */
1608 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
1609 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
1610 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
1611
1612 return 0;
1613 }
1614
1615
1616 /* end of file */
1617