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