This source file includes following definitions.
- fms_match
- fms_attach
- fms_read_codec
- fms_write_codec
- fms_attach_codec
- fms_reset_codec
- fms_intr
- fms_open
- fms_close
- fms_query_encoding
- fms_set_params
- fms_round_blocksize
- fms_halt_output
- fms_halt_input
- fms_getdev
- fms_set_port
- fms_get_port
- fms_malloc
- fms_free
- fms_mappage
- fms_get_props
- fms_query_devinfo
- fms_trigger_output
- fms_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 #include "radio.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/device.h>
51 #include <sys/audioio.h>
52
53 #include <machine/bus.h>
54 #include <machine/cpu.h>
55
56 #include <dev/pci/pcidevs.h>
57 #include <dev/pci/pcivar.h>
58
59 #include <dev/audio_if.h>
60 #include <dev/mulaw.h>
61 #include <dev/auconv.h>
62
63 #include <dev/ic/ac97.h>
64 #if 0
65 #include <dev/ic/mpuvar.h>
66 #endif
67
68 #include <dev/pci/fmsreg.h>
69 #include <dev/pci/fmsvar.h>
70
71
72 struct fms_dma {
73 struct fms_dma *next;
74 caddr_t addr;
75 size_t size;
76 bus_dmamap_t map;
77 bus_dma_segment_t seg;
78 };
79
80
81
82 int fms_match(struct device *, void *, void *);
83 void fms_attach(struct device *, struct device *, void *);
84 int fms_intr(void *);
85
86 int fms_open(void *, int);
87 void fms_close(void *);
88 int fms_query_encoding(void *, struct audio_encoding *);
89 int fms_set_params(void *, int, int, struct audio_params *,
90 struct audio_params *);
91 int fms_round_blocksize(void *, int);
92 int fms_halt_output(void *);
93 int fms_halt_input(void *);
94 int fms_getdev(void *, struct audio_device *);
95 int fms_set_port(void *, mixer_ctrl_t *);
96 int fms_get_port(void *, mixer_ctrl_t *);
97 int fms_query_devinfo(void *, mixer_devinfo_t *);
98 void *fms_malloc(void *, int, size_t, int, int);
99 void fms_free(void *, void *, int);
100 paddr_t fms_mappage(void *, void *, off_t, int);
101 int fms_get_props(void *);
102 int fms_trigger_output(void *, void *, void *, int, void (*)(void *),
103 void *, struct audio_params *);
104 int fms_trigger_input(void *, void *, void *, int, void (*)(void *),
105 void *, struct audio_params *);
106
107 struct cfdriver fms_cd = {
108 NULL, "fms", DV_DULL
109 };
110
111 struct cfattach fms_ca = {
112 sizeof (struct fms_softc), fms_match, fms_attach
113 };
114
115 struct audio_device fms_device = {
116 "Forte Media 801",
117 "1.0",
118 "fms"
119 };
120
121
122 struct audio_hw_if fms_hw_if = {
123 fms_open,
124 fms_close,
125 NULL,
126 fms_query_encoding,
127 fms_set_params,
128 fms_round_blocksize,
129 NULL,
130 NULL,
131 NULL,
132 NULL,
133 NULL,
134 fms_halt_output,
135 fms_halt_input,
136 NULL,
137 fms_getdev,
138 NULL,
139 fms_set_port,
140 fms_get_port,
141 fms_query_devinfo,
142 fms_malloc,
143 fms_free,
144 NULL,
145 fms_mappage,
146 fms_get_props,
147 fms_trigger_output,
148 fms_trigger_input
149 };
150
151 int fms_attach_codec(void *, struct ac97_codec_if *);
152 int fms_read_codec(void *, u_int8_t, u_int16_t *);
153 int fms_write_codec(void *, u_int8_t, u_int16_t);
154 void fms_reset_codec(void *);
155
156 int fms_allocmem(struct fms_softc *, size_t, size_t,
157 struct fms_dma *);
158 int fms_freemem(struct fms_softc *, struct fms_dma *);
159
160 int
161 fms_match(parent, match, aux)
162 struct device *parent;
163 void *match;
164 void *aux;
165 {
166 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
167
168 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_FORTEMEDIA &&
169 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_FORTEMEDIA_FM801)
170 return (1);
171 return (0);
172 }
173
174 void
175 fms_attach(parent, self, aux)
176 struct device *parent;
177 struct device *self;
178 void *aux;
179 {
180 struct pci_attach_args *pa = aux;
181 struct fms_softc *sc = (struct fms_softc *) self;
182 struct audio_attach_args aa;
183 pci_chipset_tag_t pc = pa->pa_pc;
184 pcitag_t pt = pa->pa_tag;
185 pci_intr_handle_t ih;
186 bus_size_t iosize;
187 const char *intrstr;
188 u_int16_t k1;
189 int i;
190
191 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
192 &sc->sc_ioh, NULL, &iosize, 0)) {
193 printf(": can't map i/o space\n");
194 return;
195 }
196
197 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2,
198 &sc->sc_mpu_ioh)) {
199 printf(": can't get mpu subregion handle\n");
200 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
201 return;
202 }
203
204 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4,
205 &sc->sc_opl_ioh)) {
206 printf(": can't get opl subregion handle\n");
207 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
208 return;
209 }
210
211 if (pci_intr_map(pa, &ih)) {
212 printf(": couldn't map interrupt\n");
213 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
214 return;
215 }
216 intrstr = pci_intr_string(pc, ih);
217
218 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, fms_intr, sc,
219 sc->sc_dev.dv_xname);
220 if (sc->sc_ih == NULL) {
221 printf(": couldn't establish interrupt");
222 if (intrstr != NULL)
223 printf(" at %s", intrstr);
224 printf("\n");
225 bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
226 return;
227 }
228
229 printf(": %s\n", intrstr);
230
231 sc->sc_dmat = pa->pa_dmat;
232
233
234 pci_conf_write(pc, pt, 0x40, 0);
235
236
237 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020);
238 delay(2);
239 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000);
240 delay(1);
241
242
243 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808);
244 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808);
245 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808);
246
247 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000);
248
249
250 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK);
251 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK,
252 (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
253 FM_INTMASK_VOL);
254 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS,
255 FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
256 FM_INTSTATUS_VOL);
257
258 #if NRADIO > 0
259 fmsradio_attach(sc);
260 #endif
261
262 sc->host_if.arg = sc;
263 sc->host_if.attach = fms_attach_codec;
264 sc->host_if.read = fms_read_codec;
265 sc->host_if.write = fms_write_codec;
266 sc->host_if.reset = fms_reset_codec;
267
268 if (ac97_attach(&sc->host_if) != 0)
269 return;
270
271
272 for (i = 0; i < 3; i++) {
273 static struct {
274 char *class, *device;
275 } d[] = {
276 { AudioCoutputs, AudioNmaster },
277 { AudioCinputs, AudioNdac },
278 { AudioCrecord, AudioNvolume }
279 };
280 struct mixer_ctrl ctl;
281
282 ctl.type = AUDIO_MIXER_ENUM;
283 ctl.un.ord = 0;
284 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
285 d[i].class, d[i].device, AudioNmute);
286 fms_set_port(sc, &ctl);
287 }
288
289 audio_attach_mi(&fms_hw_if, sc, &sc->sc_dev);
290
291 aa.type = AUDIODEV_TYPE_OPL;
292 aa.hwif = NULL;
293 aa.hdl = NULL;
294 config_found(&sc->sc_dev, &aa, audioprint);
295
296 aa.type = AUDIODEV_TYPE_MPU;
297 aa.hwif = NULL;
298 aa.hdl = NULL;
299 sc->sc_mpu_dev = config_found(&sc->sc_dev, &aa, audioprint);
300 }
301
302
303
304
305
306 #define TIMO 50
307 int
308 fms_read_codec(addr, reg, val)
309 void *addr;
310 u_int8_t reg;
311 u_int16_t *val;
312 {
313 struct fms_softc *sc = addr;
314 int i;
315
316
317 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh,
318 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++)
319 delay(1);
320 if (i >= TIMO) {
321 printf("fms: codec busy\n");
322 return 1;
323 }
324
325
326 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD,
327 reg | FM_CODEC_CMD_READ);
328
329
330 for (i = 0; i < TIMO && !(bus_space_read_2(sc->sc_iot, sc->sc_ioh,
331 FM_CODEC_CMD) & FM_CODEC_CMD_VALID); i++)
332 delay(1);
333 if (i >= TIMO) {
334 printf("fms: no data from codec\n");
335 return 1;
336 }
337
338
339 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA);
340 return 0;
341 }
342
343 int
344 fms_write_codec(addr, reg, val)
345 void *addr;
346 u_int8_t reg;
347 u_int16_t val;
348 {
349 struct fms_softc *sc = addr;
350 int i;
351
352
353 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh,
354 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++)
355 delay(1);
356 if (i >= TIMO) {
357 printf("fms: codec busy\n");
358 return 1;
359 }
360
361
362 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA, val);
363
364 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, reg);
365 return 0;
366 }
367 #undef TIMO
368
369 int
370 fms_attach_codec(addr, cif)
371 void *addr;
372 struct ac97_codec_if *cif;
373 {
374 struct fms_softc *sc = addr;
375
376 sc->codec_if = cif;
377 return 0;
378 }
379
380
381 void
382 fms_reset_codec(addr)
383 void *addr;
384 {
385 struct fms_softc *sc = addr;
386 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020);
387 delay(2);
388 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000);
389 delay(1);
390 }
391
392 int
393 fms_intr(arg)
394 void *arg;
395 {
396 struct fms_softc *sc = arg;
397 u_int16_t istat;
398
399 istat = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS);
400
401 if (istat & FM_INTSTATUS_PLAY) {
402 if ((sc->sc_play_nextblk += sc->sc_play_blksize) >=
403 sc->sc_play_end)
404 sc->sc_play_nextblk = sc->sc_play_start;
405
406 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
407 sc->sc_play_flip++ & 1 ?
408 FM_PLAY_DMABUF2 : FM_PLAY_DMABUF1, sc->sc_play_nextblk);
409
410 if (sc->sc_pintr)
411 sc->sc_pintr(sc->sc_parg);
412 else
413 printf("unexpected play intr\n");
414 }
415
416 if (istat & FM_INTSTATUS_REC) {
417 if ((sc->sc_rec_nextblk += sc->sc_rec_blksize) >=
418 sc->sc_rec_end)
419 sc->sc_rec_nextblk = sc->sc_rec_start;
420
421 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
422 sc->sc_rec_flip++ & 1 ?
423 FM_REC_DMABUF2 : FM_REC_DMABUF1, sc->sc_rec_nextblk);
424
425 if (sc->sc_rintr)
426 sc->sc_rintr(sc->sc_rarg);
427 else
428 printf("unexpected rec intr\n");
429 }
430
431 #if 0
432 if (istat & FM_INTSTATUS_MPU)
433 mpu_intr(sc->sc_mpu_dev);
434 #endif
435
436 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS,
437 istat & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC));
438
439 return 1;
440 }
441
442 int
443 fms_open(addr, flags)
444 void *addr;
445 int flags;
446 {
447
448
449 return 0;
450 }
451
452 void
453 fms_close(addr)
454 void *addr;
455 {
456
457 }
458
459 int
460 fms_query_encoding(addr, fp)
461 void *addr;
462 struct audio_encoding *fp;
463 {
464
465 switch (fp->index) {
466 case 0:
467 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
468 fp->encoding = AUDIO_ENCODING_ULAW;
469 fp->precision = 8;
470 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
471 return 0;
472 case 1:
473 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
474 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
475 fp->precision = 16;
476 fp->flags = 0;
477 return 0;
478 case 2:
479 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
480 fp->encoding = AUDIO_ENCODING_ULINEAR;
481 fp->precision = 8;
482 fp->flags = 0;
483 return 0;
484 case 3:
485 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
486 fp->encoding = AUDIO_ENCODING_ALAW;
487 fp->precision = 8;
488 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
489 return 0;
490 case 4:
491 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
492 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
493 fp->precision = 16;
494 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
495 return 0;
496 case 5:
497 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
498 fp->encoding = AUDIO_ENCODING_SLINEAR;
499 fp->precision = 8;
500 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
501 return 0;
502 case 6:
503 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
504 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
505 fp->precision = 16;
506 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
507 return 0;
508 case 7:
509 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
510 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
511 fp->precision = 16;
512 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
513 return 0;
514 default:
515 return EINVAL;
516 }
517 }
518
519
520
521
522
523
524 struct {
525 int limit;
526 int rate;
527 } fms_rates[11] = {
528 { 6600, 5500 },
529 { 8750, 8000 },
530 { 10250, 9600 },
531 { 13200, 11025 },
532 { 17500, 16000 },
533 { 20500, 19200 },
534 { 26500, 22050 },
535 { 35000, 32000 },
536 { 41000, 38400 },
537 { 46000, 44100 },
538 { 48000, 48000 },
539
540 };
541
542 int
543 fms_set_params(addr, setmode, usemode, play, rec)
544 void *addr;
545 int setmode, usemode;
546 struct audio_params *play, *rec;
547 {
548 struct fms_softc *sc = addr;
549 int i;
550
551 if (setmode & AUMODE_PLAY) {
552 play->factor = 1;
553 play->sw_code = 0;
554 switch(play->encoding) {
555 case AUDIO_ENCODING_ULAW:
556 play->factor = 2;
557 play->sw_code = mulaw_to_slinear16_le;
558 break;
559 case AUDIO_ENCODING_SLINEAR_LE:
560 if (play->precision == 8)
561 play->sw_code = change_sign8;
562 break;
563 case AUDIO_ENCODING_ULINEAR_LE:
564 if (play->precision == 16)
565 play->sw_code = change_sign16_le;
566 break;
567 case AUDIO_ENCODING_ALAW:
568 play->factor = 2;
569 play->sw_code = alaw_to_slinear16_le;
570 break;
571 case AUDIO_ENCODING_SLINEAR_BE:
572 if (play->precision == 16)
573 play->sw_code = swap_bytes;
574 else
575 play->sw_code = change_sign8;
576 break;
577 case AUDIO_ENCODING_ULINEAR_BE:
578 if (play->precision == 16)
579 play->sw_code = change_sign16_swap_bytes_le;
580 break;
581 default:
582 return EINVAL;
583 }
584 for (i = 0; i < 10 && play->sample_rate > fms_rates[i].limit;
585 i++)
586 ;
587 play->sample_rate = fms_rates[i].rate;
588 sc->sc_play_reg = (play->channels == 2 ? FM_PLAY_STEREO : 0) |
589 (play->precision * play->factor == 16 ? FM_PLAY_16BIT : 0) |
590 (i << 8);
591 }
592
593 if (setmode & AUMODE_RECORD) {
594
595 rec->factor = 1;
596 rec->sw_code = 0;
597 switch(rec->encoding) {
598 case AUDIO_ENCODING_ULAW:
599 rec->sw_code = ulinear8_to_mulaw;
600 break;
601 case AUDIO_ENCODING_SLINEAR_LE:
602 if (rec->precision == 8)
603 rec->sw_code = change_sign8;
604 break;
605 case AUDIO_ENCODING_ULINEAR_LE:
606 if (rec->precision == 16)
607 rec->sw_code = change_sign16_le;
608 break;
609 case AUDIO_ENCODING_ALAW:
610 rec->sw_code = ulinear8_to_alaw;
611 break;
612 case AUDIO_ENCODING_SLINEAR_BE:
613 if (play->precision == 16)
614 play->sw_code = swap_bytes;
615 else
616 play->sw_code = change_sign8;
617 break;
618 case AUDIO_ENCODING_ULINEAR_BE:
619 if (play->precision == 16)
620 play->sw_code = swap_bytes_change_sign16_le;
621 break;
622 default:
623 return EINVAL;
624 }
625 for (i = 0; i < 10 && rec->sample_rate > fms_rates[i].limit;
626 i++)
627 ;
628 rec->sample_rate = fms_rates[i].rate;
629 sc->sc_rec_reg =
630 (rec->channels == 2 ? FM_REC_STEREO : 0) |
631 (rec->precision * rec->factor == 16 ? FM_REC_16BIT : 0) |
632 (i << 8);
633 }
634
635 return 0;
636 }
637
638 int
639 fms_round_blocksize(addr, blk)
640 void *addr;
641 int blk;
642 {
643 return (blk + 0xf) & ~0xf;
644 }
645
646 int
647 fms_halt_output(addr)
648 void *addr;
649 {
650 struct fms_softc *sc = addr;
651 u_int16_t k1;
652
653 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL);
654 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL,
655 (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) |
656 FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST);
657
658 return 0;
659 }
660
661 int
662 fms_halt_input(addr)
663 void *addr;
664 {
665 struct fms_softc *sc = addr;
666 u_int16_t k1;
667
668 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL);
669 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL,
670 (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) |
671 FM_REC_BUF1_LAST | FM_REC_BUF2_LAST);
672
673 return 0;
674 }
675
676 int
677 fms_getdev(addr, retp)
678 void *addr;
679 struct audio_device *retp;
680 {
681 *retp = fms_device;
682 return 0;
683 }
684
685 int
686 fms_set_port(addr, cp)
687 void *addr;
688 mixer_ctrl_t *cp;
689 {
690 struct fms_softc *sc = addr;
691
692 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
693 }
694
695 int
696 fms_get_port(addr, cp)
697 void *addr;
698 mixer_ctrl_t *cp;
699 {
700 struct fms_softc *sc = addr;
701
702 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
703 }
704
705 void *
706 fms_malloc(addr, direction, size, pool, flags)
707 void *addr;
708 int direction;
709 size_t size;
710 int pool, flags;
711 {
712 struct fms_softc *sc = addr;
713 struct fms_dma *p;
714 int error;
715 int rseg;
716
717 p = malloc(sizeof(*p), pool, flags);
718 if (!p)
719 return 0;
720
721 p->size = size;
722 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &p->seg, 1,
723 &rseg, BUS_DMA_NOWAIT)) != 0) {
724 printf("%s: unable to allocate dma, error = %d\n",
725 sc->sc_dev.dv_xname, error);
726 goto fail_alloc;
727 }
728
729 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr,
730 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
731 printf("%s: unable to map dma, error = %d\n",
732 sc->sc_dev.dv_xname, error);
733 goto fail_map;
734 }
735
736 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
737 BUS_DMA_NOWAIT, &p->map)) != 0) {
738 printf("%s: unable to create dma map, error = %d\n",
739 sc->sc_dev.dv_xname, error);
740 goto fail_create;
741 }
742
743 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL,
744 BUS_DMA_NOWAIT)) != 0) {
745 printf("%s: unable to load dma map, error = %d\n",
746 sc->sc_dev.dv_xname, error);
747 goto fail_load;
748 }
749
750 p->next = sc->sc_dmas;
751 sc->sc_dmas = p;
752
753 return p->addr;
754
755
756 fail_load:
757 bus_dmamap_destroy(sc->sc_dmat, p->map);
758 fail_create:
759 bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
760 fail_map:
761 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
762 fail_alloc:
763 free(p, pool);
764 return 0;
765 }
766
767 void
768 fms_free(addr, ptr, pool)
769 void *addr;
770 void *ptr;
771 int pool;
772 {
773 struct fms_softc *sc = addr;
774 struct fms_dma **pp, *p;
775
776 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next)
777 if (p->addr == ptr) {
778 bus_dmamap_unload(sc->sc_dmat, p->map);
779 bus_dmamap_destroy(sc->sc_dmat, p->map);
780 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
781 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
782
783 *pp = p->next;
784 free(p, pool);
785 return;
786 }
787
788 panic("fms_free: trying to free unallocated memory");
789 }
790
791 paddr_t
792 fms_mappage(addr, mem, off, prot)
793 void *addr;
794 void *mem;
795 off_t off;
796 int prot;
797 {
798 struct fms_softc *sc = addr;
799 struct fms_dma *p;
800
801 if (off < 0)
802 return -1;
803
804 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next)
805 ;
806 if (!p)
807 return -1;
808
809 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot,
810 BUS_DMA_WAITOK);
811 }
812
813 int
814 fms_get_props(addr)
815 void *addr;
816 {
817 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
818 AUDIO_PROP_FULLDUPLEX;
819 }
820
821 int
822 fms_query_devinfo(addr, dip)
823 void *addr;
824 mixer_devinfo_t *dip;
825 {
826 struct fms_softc *sc = addr;
827
828 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
829 }
830
831 int
832 fms_trigger_output(addr, start, end, blksize, intr, arg, param)
833 void *addr;
834 void *start, *end;
835 int blksize;
836 void (*intr)(void *);
837 void *arg;
838 struct audio_params *param;
839 {
840 struct fms_softc *sc = addr;
841 struct fms_dma *p;
842
843 sc->sc_pintr = intr;
844 sc->sc_parg = arg;
845
846 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
847 ;
848
849 if (!p)
850 panic("fms_trigger_output: request with bad start "
851 "address (%p)", start);
852
853 sc->sc_play_start = p->map->dm_segs[0].ds_addr;
854 sc->sc_play_end = sc->sc_play_start + ((char *)end - (char *)start);
855 sc->sc_play_blksize = blksize;
856 sc->sc_play_nextblk = sc->sc_play_start + sc->sc_play_blksize;
857 sc->sc_play_flip = 0;
858 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMALEN, blksize - 1);
859 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF1,
860 sc->sc_play_start);
861 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF2,
862 sc->sc_play_nextblk);
863 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL,
864 FM_PLAY_START | FM_PLAY_STOPNOW | sc->sc_play_reg);
865 return 0;
866 }
867
868
869 int
870 fms_trigger_input(addr, start, end, blksize, intr, arg, param)
871 void *addr;
872 void *start, *end;
873 int blksize;
874 void (*intr)(void *);
875 void *arg;
876 struct audio_params *param;
877 {
878 struct fms_softc *sc = addr;
879 struct fms_dma *p;
880
881 sc->sc_rintr = intr;
882 sc->sc_rarg = arg;
883
884 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
885 ;
886
887 if (!p)
888 panic("fms_trigger_input: request with bad start "
889 "address (%p)", start);
890
891 sc->sc_rec_start = p->map->dm_segs[0].ds_addr;
892 sc->sc_rec_end = sc->sc_rec_start + ((char *)end - (char *)start);
893 sc->sc_rec_blksize = blksize;
894 sc->sc_rec_nextblk = sc->sc_rec_start + sc->sc_rec_blksize;
895 sc->sc_rec_flip = 0;
896 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_DMALEN, blksize - 1);
897 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF1,
898 sc->sc_rec_start);
899 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF2,
900 sc->sc_rec_nextblk);
901 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL,
902 FM_REC_START | FM_REC_STOPNOW | sc->sc_rec_reg);
903 return 0;
904 }
905
906