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