fms.c revision 1.10 1 /* $NetBSD: fms.c,v 1.10 2001/10/03 00:04:52 augustss Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Witold J. Wnuk.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Forte Media FM801 Audio Device Driver
41 */
42
43 #include "mpu.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/audioio.h>
51
52 #include <uvm/uvm_extern.h>
53
54 #include <machine/bus.h>
55 #include <machine/cpu.h>
56
57 #include <dev/pci/pcidevs.h>
58 #include <dev/pci/pcivar.h>
59
60 #include <dev/audio_if.h>
61 #include <dev/mulaw.h>
62 #include <dev/auconv.h>
63
64 #include <dev/ic/ac97var.h>
65 #include <dev/ic/mpuvar.h>
66
67 #include <dev/pci/fmsvar.h>
68
69
70 struct fms_dma {
71 struct fms_dma *next;
72 caddr_t addr;
73 size_t size;
74 bus_dmamap_t map;
75 bus_dma_segment_t seg;
76 };
77
78
79
80 int fms_match __P((struct device *, struct cfdata *, void *));
81 void fms_attach __P((struct device *, struct device *, void *));
82 int fms_intr __P((void *));
83
84 int fms_open __P((void *, int));
85 void fms_close __P((void *));
86 int fms_query_encoding __P((void *, struct audio_encoding *));
87 int fms_set_params __P((void *, int, int, struct audio_params *,
88 struct audio_params *));
89 int fms_round_blocksize __P((void *, int));
90 int fms_halt_output __P((void *));
91 int fms_halt_input __P((void *));
92 int fms_getdev __P((void *, struct audio_device *));
93 int fms_set_port __P((void *, mixer_ctrl_t *));
94 int fms_get_port __P((void *, mixer_ctrl_t *));
95 int fms_query_devinfo __P((void *, mixer_devinfo_t *));
96 void *fms_malloc __P((void *, int, size_t, int, int));
97 void fms_free __P((void *, void *, int));
98 size_t fms_round_buffersize __P((void *, int, size_t));
99 paddr_t fms_mappage __P((void *, void *, off_t, int));
100 int fms_get_props __P((void *));
101 int fms_trigger_output __P((void *, void *, void *, int, void (*)(void *),
102 void *, struct audio_params *));
103 int fms_trigger_input __P((void *, void *, void *, int, void (*)(void *),
104 void *, struct audio_params *));
105
106 struct cfattach fms_ca = {
107 sizeof (struct fms_softc), fms_match, fms_attach
108 };
109
110 struct audio_device fms_device = {
111 "Forte Media 801",
112 "1.0",
113 "fms"
114 };
115
116
117 struct audio_hw_if fms_hw_if = {
118 fms_open,
119 fms_close,
120 NULL,
121 fms_query_encoding,
122 fms_set_params,
123 fms_round_blocksize,
124 NULL,
125 NULL,
126 NULL,
127 NULL,
128 NULL,
129 fms_halt_output,
130 fms_halt_input,
131 NULL,
132 fms_getdev,
133 NULL,
134 fms_set_port,
135 fms_get_port,
136 fms_query_devinfo,
137 fms_malloc,
138 fms_free,
139 fms_round_buffersize,
140 fms_mappage,
141 fms_get_props,
142 fms_trigger_output,
143 fms_trigger_input,
144 NULL,
145 };
146
147 int fms_attach_codec __P((void *, struct ac97_codec_if *));
148 int fms_read_codec __P((void *, u_int8_t, u_int16_t *));
149 int fms_write_codec __P((void *, u_int8_t, u_int16_t));
150 void fms_reset_codec __P((void *));
151
152 int fms_allocmem __P((struct fms_softc *, size_t, size_t,
153 struct fms_dma *));
154 int fms_freemem __P((struct fms_softc *, struct fms_dma *));
155
156 #define FM_PCM_VOLUME 0x00
157 #define FM_FM_VOLUME 0x02
158 #define FM_I2S_VOLUME 0x04
159 #define FM_RECORD_SOURCE 0x06
160
161 #define FM_PLAY_CTL 0x08
162 #define FM_PLAY_RATE_MASK 0x0f00
163 #define FM_PLAY_BUF1_LAST 0x0001
164 #define FM_PLAY_BUF2_LAST 0x0002
165 #define FM_PLAY_START 0x0020
166 #define FM_PLAY_PAUSE 0x0040
167 #define FM_PLAY_STOPNOW 0x0080
168 #define FM_PLAY_16BIT 0x4000
169 #define FM_PLAY_STEREO 0x8000
170
171 #define FM_PLAY_DMALEN 0x0a
172 #define FM_PLAY_DMABUF1 0x0c
173 #define FM_PLAY_DMABUF2 0x10
174
175
176 #define FM_REC_CTL 0x14
177 #define FM_REC_RATE_MASK 0x0f00
178 #define FM_REC_BUF1_LAST 0x0001
179 #define FM_REC_BUF2_LAST 0x0002
180 #define FM_REC_START 0x0020
181 #define FM_REC_PAUSE 0x0040
182 #define FM_REC_STOPNOW 0x0080
183 #define FM_REC_16BIT 0x4000
184 #define FM_REC_STEREO 0x8000
185
186
187 #define FM_REC_DMALEN 0x16
188 #define FM_REC_DMABUF1 0x18
189 #define FM_REC_DMABUF2 0x1c
190
191 #define FM_CODEC_CTL 0x22
192 #define FM_VOLUME 0x26
193 #define FM_VOLUME_MUTE 0x8000
194
195 #define FM_CODEC_CMD 0x2a
196 #define FM_CODEC_CMD_READ 0x0080
197 #define FM_CODEC_CMD_VALID 0x0100
198 #define FM_CODEC_CMD_BUSY 0x0200
199
200 #define FM_CODEC_DATA 0x2c
201
202 #define FM_IO_CTL 0x52
203 #define FM_CARD_CTL 0x54
204
205 #define FM_INTMASK 0x56
206 #define FM_INTMASK_PLAY 0x0001
207 #define FM_INTMASK_REC 0x0002
208 #define FM_INTMASK_VOL 0x0040
209 #define FM_INTMASK_MPU 0x0080
210
211 #define FM_INTSTATUS 0x5a
212 #define FM_INTSTATUS_PLAY 0x0100
213 #define FM_INTSTATUS_REC 0x0200
214 #define FM_INTSTATUS_VOL 0x4000
215 #define FM_INTSTATUS_MPU 0x8000
216
217
218
219 int
220 fms_match(parent, match, aux)
221 struct device *parent;
222 struct cfdata *match;
223 void *aux;
224 {
225 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
226
227 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_FORTEMEDIA)
228 return 0;
229 if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_FORTEMEDIA_FM801)
230 return 0;
231
232 return 1;
233 }
234
235 void
236 fms_attach(parent, self, aux)
237 struct device *parent;
238 struct device *self;
239 void *aux;
240 {
241 struct pci_attach_args *pa = aux;
242 struct fms_softc *sc = (struct fms_softc *) self;
243 struct audio_attach_args aa;
244 const char *intrstr = NULL;
245 pci_chipset_tag_t pc = pa->pa_pc;
246 pcitag_t pt = pa->pa_tag;
247 pci_intr_handle_t ih;
248 int i;
249
250 u_int16_t k1;
251
252 printf(": Forte Media FM-801\n");
253
254 if (pci_intr_map(pa, &ih)) {
255 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
256 return;
257 }
258 intrstr = pci_intr_string(pc, ih);
259
260 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, fms_intr, sc);
261 if (sc->sc_ih == NULL) {
262 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname);
263 if (intrstr != NULL)
264 printf(" at %s", intrstr);
265 printf("\n");
266 return;
267 }
268
269 sc->sc_dmat = pa->pa_dmat;
270
271 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
272
273 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
274 &sc->sc_ioh, &sc->sc_ioaddr, &sc->sc_iosize)) {
275 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
276 return;
277 }
278
279 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2,
280 &sc->sc_mpu_ioh))
281 panic("fms_attach: can't get mpu subregion handle");
282
283 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4,
284 &sc->sc_opl_ioh))
285 panic("fms_attach: can't get opl subregion handle");
286
287 /* Disable legacy audio (SBPro compatibility) */
288 pci_conf_write(pc, pt, 0x40, 0);
289
290 /* Reset codec and AC'97 */
291 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020);
292 delay(2); /* > 1us according to AC'97 documentation */
293 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000);
294 delay(1); /* > 168.2ns according to AC'97 documentation */
295
296 /* Set up volume */
297 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808);
298 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808);
299 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808);
300
301 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000);
302
303 /* Unmask playback, record and mpu interrupts, mask the rest */
304 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK);
305 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK,
306 (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
307 FM_INTMASK_VOL);
308 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS,
309 FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
310 FM_INTSTATUS_VOL);
311
312 sc->host_if.arg = sc;
313 sc->host_if.attach = fms_attach_codec;
314 sc->host_if.read = fms_read_codec;
315 sc->host_if.write = fms_write_codec;
316 sc->host_if.reset = fms_reset_codec;
317
318 if (ac97_attach(&sc->host_if) != 0)
319 return;
320
321 /* Turn mute off */
322 for (i = 0; i < 3; i++) {
323 static struct {
324 char *class, *device;
325 } d[] = {
326 { AudioCoutputs, AudioNmaster },
327 { AudioCinputs, AudioNdac },
328 { AudioCrecord, AudioNvolume }
329 };
330 struct mixer_ctrl ctl;
331
332 ctl.type = AUDIO_MIXER_ENUM;
333 ctl.un.ord = 0;
334 ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
335 d[i].class, d[i].device, AudioNmute);
336 fms_set_port(sc, &ctl);
337 }
338
339 audio_attach_mi(&fms_hw_if, sc, &sc->sc_dev);
340
341 aa.type = AUDIODEV_TYPE_OPL;
342 aa.hwif = NULL;
343 aa.hdl = NULL;
344 config_found(&sc->sc_dev, &aa, audioprint);
345
346 aa.type = AUDIODEV_TYPE_MPU;
347 aa.hwif = NULL;
348 aa.hdl = NULL;
349 sc->sc_mpu_dev = config_found(&sc->sc_dev, &aa, audioprint);
350 }
351
352 /*
353 * Each AC-link frame takes 20.8us, data should be ready in next frame,
354 * we allow more than two.
355 */
356 #define TIMO 50
357 int
358 fms_read_codec(addr, reg, val)
359 void *addr;
360 u_int8_t reg;
361 u_int16_t *val;
362 {
363 struct fms_softc *sc = addr;
364 int i;
365
366 /* Poll until codec is ready */
367 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh,
368 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++)
369 delay(1);
370 if (i >= TIMO) {
371 printf("fms: codec busy\n");
372 return 1;
373 }
374
375 /* Write register index, read access */
376 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD,
377 reg | FM_CODEC_CMD_READ);
378
379 /* Poll until we have valid data */
380 for (i = 0; i < TIMO && !(bus_space_read_2(sc->sc_iot, sc->sc_ioh,
381 FM_CODEC_CMD) & FM_CODEC_CMD_VALID); i++)
382 delay(1);
383 if (i >= TIMO) {
384 printf("fms: no data from codec\n");
385 return 1;
386 }
387
388 /* Read data */
389 *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA);
390 return 0;
391 }
392
393 int
394 fms_write_codec(addr, reg, val)
395 void *addr;
396 u_int8_t reg;
397 u_int16_t val;
398 {
399 struct fms_softc *sc = addr;
400 int i;
401
402 /* Poll until codec is ready */
403 for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh,
404 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++)
405 delay(1);
406 if (i >= TIMO) {
407 printf("fms: codec busy\n");
408 return 1;
409 }
410
411 /* Write data */
412 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA, val);
413 /* Write index register, write access */
414 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, reg);
415 return 0;
416 }
417 #undef TIMO
418
419 int
420 fms_attach_codec(addr, cif)
421 void *addr;
422 struct ac97_codec_if *cif;
423 {
424 struct fms_softc *sc = addr;
425
426 sc->codec_if = cif;
427 return 0;
428 }
429
430 /* Cold Reset */
431 void
432 fms_reset_codec(addr)
433 void *addr;
434 {
435 struct fms_softc *sc = addr;
436 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020);
437 delay(2);
438 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000);
439 delay(1);
440 }
441
442 int
443 fms_intr(arg)
444 void *arg;
445 {
446 struct fms_softc *sc = arg;
447 u_int16_t istat;
448
449 istat = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS);
450
451 if (istat & FM_INTSTATUS_PLAY) {
452 if ((sc->sc_play_nextblk += sc->sc_play_blksize) >=
453 sc->sc_play_end)
454 sc->sc_play_nextblk = sc->sc_play_start;
455
456 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
457 sc->sc_play_flip++ & 1 ?
458 FM_PLAY_DMABUF2 : FM_PLAY_DMABUF1, sc->sc_play_nextblk);
459
460 if (sc->sc_pintr)
461 sc->sc_pintr(sc->sc_parg);
462 else
463 printf("unexpected play intr\n");
464 }
465
466 if (istat & FM_INTSTATUS_REC) {
467 if ((sc->sc_rec_nextblk += sc->sc_rec_blksize) >=
468 sc->sc_rec_end)
469 sc->sc_rec_nextblk = sc->sc_rec_start;
470
471 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
472 sc->sc_rec_flip++ & 1 ?
473 FM_REC_DMABUF2 : FM_REC_DMABUF1, sc->sc_rec_nextblk);
474
475 if (sc->sc_rintr)
476 sc->sc_rintr(sc->sc_rarg);
477 else
478 printf("unexpected rec intr\n");
479 }
480
481 #if NMPU > 0
482 if (istat & FM_INTSTATUS_MPU)
483 mpu_intr(sc->sc_mpu_dev);
484 #endif
485
486 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS,
487 istat & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC));
488
489 return 1;
490 }
491
492 int
493 fms_open(addr, flags)
494 void *addr;
495 int flags;
496 {
497 /* UNUSED struct fms_softc *sc = addr;*/
498
499 return 0;
500 }
501
502 void
503 fms_close(addr)
504 void *addr;
505 {
506 /* UNUSED struct fms_softc *sc = addr;*/
507 }
508
509 int
510 fms_query_encoding(addr, fp)
511 void *addr;
512 struct audio_encoding *fp;
513 {
514
515 switch (fp->index) {
516 case 0:
517 strcpy(fp->name, AudioEmulaw);
518 fp->encoding = AUDIO_ENCODING_ULAW;
519 fp->precision = 8;
520 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
521 return 0;
522 case 1:
523 strcpy(fp->name, AudioEslinear_le);
524 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
525 fp->precision = 16;
526 fp->flags = 0;
527 return 0;
528 case 2:
529 strcpy(fp->name, AudioEulinear);
530 fp->encoding = AUDIO_ENCODING_ULINEAR;
531 fp->precision = 8;
532 fp->flags = 0;
533 return 0;
534 case 3:
535 strcpy(fp->name, AudioEalaw);
536 fp->encoding = AUDIO_ENCODING_ALAW;
537 fp->precision = 8;
538 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
539 return 0;
540 case 4:
541 strcpy(fp->name, AudioEulinear_le);
542 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
543 fp->precision = 16;
544 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
545 return 0;
546 case 5:
547 strcpy(fp->name, AudioEslinear);
548 fp->encoding = AUDIO_ENCODING_SLINEAR;
549 fp->precision = 8;
550 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
551 return 0;
552 case 6:
553 strcpy(fp->name, AudioEulinear_be);
554 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
555 fp->precision = 16;
556 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
557 return 0;
558 case 7:
559 strcpy(fp->name, AudioEslinear_be);
560 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
561 fp->precision = 16;
562 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
563 return 0;
564 default:
565 return EINVAL;
566 }
567 }
568
569 /*
570 * Range below -limit- is set to -rate-
571 * What a pity FM801 does not have 24000
572 * 24000 -> 22050 sounds rather poor
573 */
574 struct {
575 int limit;
576 int rate;
577 } fms_rates[11] = {
578 { 6600, 5500 },
579 { 8750, 8000 },
580 { 10250, 9600 },
581 { 13200, 11025 },
582 { 17500, 16000 },
583 { 20500, 19200 },
584 { 26500, 22050 },
585 { 35000, 32000 },
586 { 41000, 38400 },
587 { 46000, 44100 },
588 { 48000, 48000 },
589 /* anything above -> 48000 */
590 };
591
592 int
593 fms_set_params(addr, setmode, usemode, play, rec)
594 void *addr;
595 int setmode, usemode;
596 struct audio_params *play, *rec;
597 {
598 struct fms_softc *sc = addr;
599 int i;
600
601 if (setmode & AUMODE_PLAY) {
602 play->factor = 1;
603 play->sw_code = 0;
604 switch(play->encoding) {
605 case AUDIO_ENCODING_ULAW:
606 play->factor = 2;
607 play->sw_code = mulaw_to_slinear16_le;
608 break;
609 case AUDIO_ENCODING_SLINEAR_LE:
610 if (play->precision == 8)
611 play->sw_code = change_sign8;
612 break;
613 case AUDIO_ENCODING_ULINEAR_LE:
614 if (play->precision == 16)
615 play->sw_code = change_sign16_le;
616 break;
617 case AUDIO_ENCODING_ALAW:
618 play->factor = 2;
619 play->sw_code = alaw_to_slinear16_le;
620 break;
621 case AUDIO_ENCODING_SLINEAR_BE:
622 if (play->precision == 16)
623 play->sw_code = swap_bytes;
624 else
625 play->sw_code = change_sign8;
626 break;
627 case AUDIO_ENCODING_ULINEAR_BE:
628 if (play->precision == 16)
629 play->sw_code = change_sign16_swap_bytes_le;
630 break;
631 default:
632 return EINVAL;
633 }
634 for (i = 0; i < 10 && play->sample_rate > fms_rates[i].limit;
635 i++)
636 ;
637 play->sample_rate = fms_rates[i].rate;
638 sc->sc_play_reg = (play->channels == 2 ? FM_PLAY_STEREO : 0) |
639 (play->precision * play->factor == 16 ? FM_PLAY_16BIT : 0) |
640 (i << 8);
641 }
642
643 if (setmode & AUMODE_RECORD) {
644
645 rec->factor = 1;
646 rec->sw_code = 0;
647 switch(rec->encoding) {
648 case AUDIO_ENCODING_ULAW:
649 rec->sw_code = ulinear8_to_mulaw;
650 break;
651 case AUDIO_ENCODING_SLINEAR_LE:
652 if (rec->precision == 8)
653 rec->sw_code = change_sign8;
654 break;
655 case AUDIO_ENCODING_ULINEAR_LE:
656 if (rec->precision == 16)
657 rec->sw_code = change_sign16_le;
658 break;
659 case AUDIO_ENCODING_ALAW:
660 rec->sw_code = ulinear8_to_alaw;
661 break;
662 case AUDIO_ENCODING_SLINEAR_BE:
663 if (play->precision == 16)
664 play->sw_code = swap_bytes;
665 else
666 play->sw_code = change_sign8;
667 break;
668 case AUDIO_ENCODING_ULINEAR_BE:
669 if (play->precision == 16)
670 play->sw_code = swap_bytes_change_sign16_le;
671 break;
672 default:
673 return EINVAL;
674 }
675 for (i = 0; i < 10 && rec->sample_rate > fms_rates[i].limit;
676 i++)
677 ;
678 rec->sample_rate = fms_rates[i].rate;
679 sc->sc_rec_reg =
680 (rec->channels == 2 ? FM_REC_STEREO : 0) |
681 (rec->precision * rec->factor == 16 ? FM_REC_16BIT : 0) |
682 (i << 8);
683 }
684
685 return 0;
686 }
687
688 int
689 fms_round_blocksize(addr, blk)
690 void *addr;
691 int blk;
692 {
693 return blk & ~0xf;
694 }
695
696 int
697 fms_halt_output(addr)
698 void *addr;
699 {
700 struct fms_softc *sc = addr;
701 u_int16_t k1;
702
703 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL);
704 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL,
705 (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) |
706 FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST);
707
708 return 0;
709 }
710
711 int
712 fms_halt_input(addr)
713 void *addr;
714 {
715 struct fms_softc *sc = addr;
716 u_int16_t k1;
717
718 k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL);
719 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL,
720 (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) |
721 FM_REC_BUF1_LAST | FM_REC_BUF2_LAST);
722
723 return 0;
724 }
725
726 int
727 fms_getdev(addr, retp)
728 void *addr;
729 struct audio_device *retp;
730 {
731 *retp = fms_device;
732 return 0;
733 }
734
735 int
736 fms_set_port(addr, cp)
737 void *addr;
738 mixer_ctrl_t *cp;
739 {
740 struct fms_softc *sc = addr;
741
742 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
743 }
744
745 int
746 fms_get_port(addr, cp)
747 void *addr;
748 mixer_ctrl_t *cp;
749 {
750 struct fms_softc *sc = addr;
751
752 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
753 }
754
755 void *
756 fms_malloc(addr, direction, size, pool, flags)
757 void *addr;
758 int direction;
759 size_t size;
760 int pool, flags;
761 {
762 struct fms_softc *sc = addr;
763 struct fms_dma *p;
764 int error;
765 int rseg;
766
767 p = malloc(sizeof(*p), pool, flags);
768 if (!p)
769 return 0;
770
771 p->size = size;
772 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &p->seg,
773 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
774 printf("%s: unable to allocate dma, error = %d\n",
775 sc->sc_dev.dv_xname, error);
776 goto fail_alloc;
777 }
778
779 if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr,
780 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
781 printf("%s: unable to map dma, error = %d\n",
782 sc->sc_dev.dv_xname, error);
783 goto fail_map;
784 }
785
786 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
787 BUS_DMA_NOWAIT, &p->map)) != 0) {
788 printf("%s: unable to create dma map, error = %d\n",
789 sc->sc_dev.dv_xname, error);
790 goto fail_create;
791 }
792
793 if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL,
794 BUS_DMA_NOWAIT)) != 0) {
795 printf("%s: unable to load dma map, error = %d\n",
796 sc->sc_dev.dv_xname, error);
797 goto fail_load;
798 }
799
800 p->next = sc->sc_dmas;
801 sc->sc_dmas = p;
802
803 return p->addr;
804
805
806 fail_load:
807 bus_dmamap_destroy(sc->sc_dmat, p->map);
808 fail_create:
809 bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
810 fail_map:
811 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
812 fail_alloc:
813 free(p, pool);
814 return 0;
815 }
816
817 void
818 fms_free(addr, ptr, pool)
819 void *addr;
820 void *ptr;
821 int pool;
822 {
823 struct fms_softc *sc = addr;
824 struct fms_dma **pp, *p;
825
826 for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next)
827 if (p->addr == ptr) {
828 bus_dmamap_unload(sc->sc_dmat, p->map);
829 bus_dmamap_destroy(sc->sc_dmat, p->map);
830 bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
831 bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
832
833 *pp = p->next;
834 free(p, pool);
835 return;
836 }
837
838 panic("fms_free: trying to free unallocated memory");
839 }
840
841 size_t
842 fms_round_buffersize(addr, direction, size)
843 void *addr;
844 int direction;
845 size_t size;
846 {
847 return size;
848 }
849
850 paddr_t
851 fms_mappage(addr, mem, off, prot)
852 void *addr;
853 void *mem;
854 off_t off;
855 int prot;
856 {
857 struct fms_softc *sc = addr;
858 struct fms_dma *p;
859
860 if (off < 0)
861 return -1;
862
863 for (p = sc->sc_dmas; p && p->addr != mem; p = p->next)
864 ;
865 if (!p)
866 return -1;
867
868 return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot,
869 BUS_DMA_WAITOK);
870 }
871
872 int
873 fms_get_props(addr)
874 void *addr;
875 {
876 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
877 AUDIO_PROP_FULLDUPLEX;
878 }
879
880 int
881 fms_query_devinfo(addr, dip)
882 void *addr;
883 mixer_devinfo_t *dip;
884 {
885 struct fms_softc *sc = addr;
886
887 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
888 }
889
890 int
891 fms_trigger_output(addr, start, end, blksize, intr, arg, param)
892 void *addr;
893 void *start, *end;
894 int blksize;
895 void (*intr) __P((void *));
896 void *arg;
897 struct audio_params *param;
898 {
899 struct fms_softc *sc = addr;
900 struct fms_dma *p;
901
902 sc->sc_pintr = intr;
903 sc->sc_parg = arg;
904
905 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
906 ;
907
908 if (!p)
909 panic("fms_trigger_output: request with bad start "
910 "address (%p)\n", start);
911
912 sc->sc_play_start = p->map->dm_segs[0].ds_addr;
913 sc->sc_play_end = sc->sc_play_start + ((char *)end - (char *)start);
914 sc->sc_play_blksize = blksize;
915 sc->sc_play_nextblk = sc->sc_play_start + sc->sc_play_blksize;
916 sc->sc_play_flip = 0;
917 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMALEN, blksize - 1);
918 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF1,
919 sc->sc_play_start);
920 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF2,
921 sc->sc_play_nextblk);
922 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL,
923 FM_PLAY_START | FM_PLAY_STOPNOW | sc->sc_play_reg);
924 return 0;
925 }
926
927
928 int
929 fms_trigger_input(addr, start, end, blksize, intr, arg, param)
930 void *addr;
931 void *start, *end;
932 int blksize;
933 void (*intr) __P((void *));
934 void *arg;
935 struct audio_params *param;
936 {
937 struct fms_softc *sc = addr;
938 struct fms_dma *p;
939
940 sc->sc_rintr = intr;
941 sc->sc_rarg = arg;
942
943 for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
944 ;
945
946 if (!p)
947 panic("fms_trigger_input: request with bad start "
948 "address (%p)\n", start);
949
950 sc->sc_rec_start = p->map->dm_segs[0].ds_addr;
951 sc->sc_rec_end = sc->sc_rec_start + ((char *)end - (char *)start);
952 sc->sc_rec_blksize = blksize;
953 sc->sc_rec_nextblk = sc->sc_rec_start + sc->sc_rec_blksize;
954 sc->sc_rec_flip = 0;
955 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_DMALEN, blksize - 1);
956 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF1,
957 sc->sc_rec_start);
958 bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF2,
959 sc->sc_rec_nextblk);
960 bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL,
961 FM_REC_START | FM_REC_STOPNOW | sc->sc_rec_reg);
962 return 0;
963 }
964
965
966