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