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