interwave.c revision 1.22 1 /* $NetBSD: interwave.c,v 1.22 2004/07/09 02:05:09 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Author: Kari Mettinen
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: interwave.c,v 1.22 2004/07/09 02:05:09 mycroft Exp $");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/errno.h>
44 #include <sys/ioctl.h>
45 #include <sys/syslog.h>
46 #include <sys/device.h>
47 #include <sys/proc.h>
48 #include <sys/buf.h>
49 #include <sys/fcntl.h>
50 #include <sys/malloc.h>
51 #include <sys/kernel.h>
52
53 #include <machine/cpu.h>
54 #include <machine/intr.h>
55 #include <machine/pio.h>
56 #include <sys/audioio.h>
57 #include <dev/audio_if.h>
58 #include <dev/mulaw.h>
59
60 #include <dev/isa/isavar.h>
61 #include <dev/isa/isadmavar.h>
62
63 #include <dev/ic/interwavereg.h>
64 #include <dev/ic/interwavevar.h>
65
66
67 static void iwreset __P((struct iw_softc *, int));
68
69 static int iw_set_speed __P((struct iw_softc *, u_long, char));
70 static u_long iw_set_format __P((struct iw_softc *, u_long, int));
71 static void iw_mixer_line_level __P((struct iw_softc *, int, int, int));
72 static void iw_trigger_dma __P((struct iw_softc *, u_char));
73 static void iw_stop_dma __P((struct iw_softc *, u_char, u_char));
74 static void iw_dma_count __P((struct iw_softc *, u_short, int));
75 static int iwintr __P((void *));
76 static void iw_meminit __P((struct iw_softc *));
77 static void iw_mempoke __P((struct iw_softc *, u_long, u_char));
78 static u_char iw_mempeek __P((struct iw_softc *, u_long));
79
80 #ifdef USE_WAVETABLE
81 static void iw_set_voice_place __P((struct iw_softc *, u_char, u_long));
82 static void iw_voice_pan __P((struct iw_softc *, u_char, u_short, u_short));
83 static void iw_voice_freq __P((struct iw_softc *, u_char, u_long));
84 static void iw_set_loopmode __P((struct iw_softc *, u_char, u_char, u_char));
85 static void iw_set_voice_pos __P((struct iw_softc *, u_short, u_long, u_long));
86 static void iw_start_voice __P((struct iw_softc *, u_char));
87 static void iw_play_voice __P((struct iw_softc *, u_long, u_long, u_short));
88 static void iw_stop_voice __P((struct iw_softc *, u_char));
89 static void iw_move_voice_end __P((struct iw_softc *, u_short, u_long));
90 static void iw_initvoices __P((struct iw_softc *));
91 #endif
92
93 struct audio_device iw_device = {
94 "Am78C201",
95 "0.1",
96 "guspnp"
97 };
98
99 #ifdef AUDIO_DEBUG
100 int iw_debug;
101 #define DPRINTF(p) if (iw_debug) printf p
102 #else
103 #define DPRINTF(p)
104 #endif
105
106 static int iw_cc = 1;
107 #ifdef DIAGNOSTIC
108 static int outputs = 0;
109 static int iw_ints = 0;
110 static int inputs = 0;
111 static int iw_inints = 0;
112 #endif
113
114 int
115 iwintr(arg)
116 void *arg;
117 {
118 struct iw_softc *sc = arg;
119 int val = 0;
120 u_char intrs = 0;
121
122 IW_READ_DIRECT_1(6, sc->p2xr_h, intrs); /* UISR */
123
124 /* codec ints */
125
126 /*
127 * The proper order to do this seems to be to read CSR3 to get the
128 * int cause and fifo over underrrun status, then deal with the ints
129 * (new DMA set up), and to clear ints by writing the respective bit
130 * to 0.
131 */
132
133 /* read what ints happened */
134
135 IW_READ_CODEC_1(CSR3I, intrs);
136
137 /* clear them */
138
139 IW_WRITE_DIRECT_1(2, sc->codec_index_h, 0x00);
140
141 /* and process them */
142
143 if (intrs & 0x20) {
144 #ifdef DIAGNOSTIC
145 iw_inints++;
146 #endif
147 if (sc->sc_recintr != 0)
148 sc->sc_recintr(sc->sc_recarg);
149 val = 1;
150 }
151 if (intrs & 0x10) {
152 #ifdef DIAGNOSTIC
153 iw_ints++;
154 #endif
155 if (sc->sc_playintr != 0)
156 sc->sc_playintr(sc->sc_playarg);
157 val = 1;
158 }
159 return val;
160
161 }
162
163 void
164 iwattach(sc)
165 struct iw_softc *sc;
166 {
167 int got_irq = 0;
168
169 DPRINTF(("iwattach sc %p\n", sc));
170
171 sc->cdatap = 1; /* relative offsets in region */
172 sc->csr1r = 2;
173 sc->cxdr = 3; /* CPDR or CRDR */
174
175 sc->gmxr = 0; /* sc->p3xr */
176 sc->gmxdr = 1; /* GMTDR or GMRDR */
177 sc->svsr = 2;
178 sc->igidxr = 3;
179 sc->i16dp = 4;
180 sc->i8dp = 5;
181 sc->lmbdr = 7;
182
183 sc->rec_precision = sc->play_precision = 8;
184 sc->rec_channels = sc->play_channels = 1;
185 sc->rec_encoding = sc->play_encoding = AUDIO_ENCODING_ULAW;
186 sc->sc_irate = 8000;
187 sc->sc_orate = 8000;
188
189 sc->sc_fullduplex = 1;
190
191 sc->sc_dma_flags = 0;
192
193 /*
194 * We can only use a few selected irqs, see if we got one from pnp
195 * code that suits us.
196 */
197
198 if (sc->sc_irq > 0) {
199 sc->sc_ih = isa_intr_establish(sc->sc_p2xr_ic,
200 sc->sc_irq,
201 IST_EDGE, IPL_AUDIO, iwintr, sc);
202 got_irq = 1;
203 }
204 if (!got_irq) {
205 printf("\niwattach: couldn't get a suitable irq\n");
206 return;
207 }
208 printf("\n");
209 iwreset(sc, 0);
210 iw_set_format(sc, AUDIO_ENCODING_ULAW, 0);
211 iw_set_format(sc, AUDIO_ENCODING_ULAW, 1);
212 printf("%s: interwave version %s\n",
213 sc->sc_dev.dv_xname, iw_device.version);
214 audio_attach_mi(sc->iw_hw_if, sc, &sc->sc_dev);
215 }
216
217 int
218 iwopen(sc, flags)
219 struct iw_softc *sc;
220 int flags;
221 {
222
223 DPRINTF(("iwopen: sc %p\n", sc));
224
225 #ifdef DIAGNOSTIC
226 outputs = 0;
227 iw_ints = 0;
228 inputs = 0;
229 iw_inints = 0;
230 #endif
231
232 iwreset(sc, 1);
233
234 return 0;
235 }
236
237
238
239 void
240 iwclose(addr)
241 void *addr;
242 {
243 struct iw_softc *sc = addr;
244
245 DPRINTF(("iwclose sc %p\n", sc));
246
247 #ifdef DIAGNOSTIC
248 DPRINTF(("iwclose: outputs %d ints %d inputs %d in_ints %d\n",
249 outputs, iw_ints, inputs, iw_inints));
250 #endif
251 }
252
253 #define RAM_STEP 64*1024
254
255 static void
256 iw_mempoke(sc, addy, val)
257 struct iw_softc *sc;
258 u_long addy;
259 u_char val;
260 {
261 IW_WRITE_GENERAL_2(LMALI, (u_short) addy);
262 IW_WRITE_GENERAL_1(LMAHI, (u_char) (addy >> 16));
263
264 /* Write byte to LMBDR */
265 IW_WRITE_DIRECT_1(sc->p3xr + 7, sc->p3xr_h, val);
266 }
267
268 static u_char
269 iw_mempeek(sc, addy)
270 struct iw_softc *sc;
271 u_long addy;
272 {
273 u_char ret;
274
275 IW_WRITE_GENERAL_2(LMALI, (u_short) addy);
276 IW_WRITE_GENERAL_1(LMAHI, (u_char) (addy >> 16));
277
278 IW_READ_DIRECT_1(sc->p3xr + 7, sc->p3xr_h, ret);
279 return ret; /* return byte from LMBDR */
280 }
281
282 static void
283 iw_meminit(sc)
284 struct iw_softc *sc;
285 {
286 u_long bank[4] = {0L, 0L, 0L, 0L};
287 u_long addr = 0L, base = 0L, cnt = 0L;
288 u_char i, ram = 0 /* ,memval=0 */ ;
289 u_short lmcfi;
290 u_long temppi;
291 u_long *lpbanks = &temppi;
292
293 IW_WRITE_GENERAL_1(LDMACI, 0x00);
294
295 IW_READ_GENERAL_2(LMCFI, lmcfi); /* 0x52 */
296 lmcfi |= 0x0A0C;
297 IW_WRITE_GENERAL_2(LMCFI, lmcfi); /* max addr span */
298 IW_WRITE_GENERAL_1(LMCI, 0x00);
299
300 /* fifo addresses */
301
302 IW_WRITE_GENERAL_2(LMRFAI, ((4 * 1024 * 1024) >> 8));
303 IW_WRITE_GENERAL_2(LMPFAI, ((4 * 1024 * 1024 + 16 * 1024) >> 8));
304
305 IW_WRITE_GENERAL_2(LMFSI, 0x000);
306
307 IW_WRITE_GENERAL_2(LDICI, 0x0000);
308
309 while (addr < (16 * 1024 * 1024)) {
310 iw_mempoke(sc, addr, 0x00);
311 addr += RAM_STEP;
312 }
313
314 printf("%s:", sc->sc_dev.dv_xname);
315
316 for (i = 0; i < 4; i++) {
317 iw_mempoke(sc, base, 0xAA); /* mark start of bank */
318 iw_mempoke(sc, base + 1L, 0x55);
319 if (iw_mempeek(sc, base) == 0xAA &&
320 iw_mempeek(sc, base + 1L) == 0x55)
321 ram = 1;
322 if (ram) {
323 while (cnt < (4 * 1024 * 1024)) {
324 bank[i] += RAM_STEP;
325 cnt += RAM_STEP;
326 addr = base + cnt;
327 if (iw_mempeek(sc, addr) == 0xAA)
328 break;
329 }
330 }
331 if (lpbanks != NULL) {
332 *lpbanks = bank[i];
333 lpbanks++;
334 }
335 bank[i] = bank[i] >> 10;
336 printf("%s bank[%d]: %ldK", i ? "," : "", i, bank[i]);
337 base += 4 * 1024 * 1024;
338 cnt = 0L;
339 ram = 0;
340 }
341
342 printf("\n");
343
344 /*
345 * this is not really useful since GUS PnP supports memory
346 * configurations that aren't really supported by Interwave...beware
347 * of holes! Also, we don't use the memory for anything in this
348 * version of the driver.
349 *
350 * we've configured for 4M-4M-4M-4M
351 */
352 }
353
354
355 static
356 void
357 iwreset(sc, warm)
358 struct iw_softc *sc;
359 int warm;
360 {
361 u_char reg, cmode, val = 0, mixer_image = 0;
362
363 reg = 0; /* XXX gcc -Wall */
364
365 cmode = 0x6c; /* enhanced codec mode (full duplex) */
366
367 /* reset */
368
369 IW_WRITE_GENERAL_1(URSTI, 0x00);
370 delay(10);
371 IW_WRITE_GENERAL_1(URSTI, 0x07);
372 IW_WRITE_GENERAL_1(ICMPTI, 0x1f); /* disable DSP and uici and
373 * udci writes */
374 IW_WRITE_GENERAL_1(IDECI, 0x7f); /* enable ints to ISA and
375 * codec access */
376 IW_READ_GENERAL_1(IVERI, reg);
377 IW_WRITE_GENERAL_1(IVERI, reg | 0x01); /* hidden reg lock disable */
378 IW_WRITE_GENERAL_1(UASBCI, 0x00);
379
380 /* synth enhanced mode (default), 0 active voices, disable ints */
381
382 IW_WRITE_GENERAL_1(SGMI_WR, 0x01); /* enhanced mode, LFOs
383 * disabled */
384 for (val = 0; val < 32; val++) {
385 /* set each synth sound volume to 0 */
386 IW_WRITE_DIRECT_1(sc->p3xr + 2, sc->p3xr_h, val);
387 IW_WRITE_GENERAL_1(SVSI_WR, 0x00);
388 IW_WRITE_GENERAL_2(SASLI_WR, 0x0000);
389 IW_WRITE_GENERAL_2(SASHI_WR, 0x0000);
390 IW_WRITE_GENERAL_2(SAELI_WR, 0x0000);
391 IW_WRITE_GENERAL_2(SAEHI_WR, 0x0000);
392 IW_WRITE_GENERAL_2(SFCI_WR, 0x0000);
393 IW_WRITE_GENERAL_1(SACI_WR, 0x02);
394 IW_WRITE_GENERAL_1(SVSI_WR, 0x00);
395 IW_WRITE_GENERAL_1(SVEI_WR, 0x00);
396 IW_WRITE_GENERAL_2(SVLI_WR, 0x0000);
397 IW_WRITE_GENERAL_1(SVCI_WR, 0x02);
398 IW_WRITE_GENERAL_1(SMSI_WR, 0x02);
399 }
400
401 IW_WRITE_GENERAL_1(SAVI_WR, 0x00);
402
403 /* codec mode/init */
404
405 /* first change mode to 1 */
406
407 IW_WRITE_CODEC_1(CMODEI, 0x00);
408
409 /* and mode 3 */
410
411 IW_WRITE_CODEC_1(CMODEI, cmode);
412
413 IW_READ_CODEC_1(CMODEI, reg);
414
415 DPRINTF(("cmode %x\n", reg));
416
417 sc->revision = ((reg & 0x80) >> 3) | (reg & 0x0f);
418
419 IW_WRITE_DIRECT_1(sc->codec_index + 2, sc->p2xr_h, 0x00);
420
421 IW_WRITE_CODEC_1(CFIG1I | IW_MCE, 0x00); /* DMA 2 chan access */
422 IW_WRITE_CODEC_1(CEXTI, 0x00); /* disable ints for now */
423
424
425 IW_WRITE_CODEC_1(CLPCTI, 0x00); /* reset playback sample counters */
426 IW_WRITE_CODEC_1(CUPCTI, 0x00); /* always upper byte last */
427 IW_WRITE_CODEC_1(CFIG2I, 0x80); /* full voltage range, enable record
428 * and playback sample counters, and
429 * don't center output in case or
430 * FIFO underrun */
431 IW_WRITE_CODEC_1(CFIG3I, 0xc0); /* enable record/playback irq (still
432 * turned off from CEXTI), max DMA
433 * rate */
434 IW_WRITE_CODEC_1(CSR3I, 0x00); /* clear status 3 reg */
435
436
437 IW_WRITE_CODEC_1(CLRCTI, 0x00); /* reset record sample counters */
438 IW_WRITE_CODEC_1(CURCTI, 0x00); /* always upper byte last */
439
440
441 IW_READ_GENERAL_1(IVERI, reg);
442
443 sc->vers = reg >> 4;
444 if (!warm)
445 snprintf(iw_device.version, sizeof(iw_device.version), "%d.%d",
446 sc->vers, sc->revision);
447
448 IW_WRITE_GENERAL_1(IDECI, 0x7f); /* irqs and codec decode
449 * enable */
450
451
452 /* ports */
453
454 if (!warm) {
455 iw_mixer_line_level(sc, IW_LINE_OUT, 255, 255);
456 iw_mixer_line_level(sc, IW_LINE_IN, 0, 0);
457 iw_mixer_line_level(sc, IW_AUX1, 0, 0);
458 iw_mixer_line_level(sc, IW_AUX2, 200, 200); /* CD */
459 sc->sc_dac.off = 0;
460 iw_mixer_line_level(sc, IW_DAC, 200, 200);
461
462 iw_mixer_line_level(sc, IW_MIC_IN, 0, 0);
463 iw_mixer_line_level(sc, IW_REC, 0, 0);
464 iw_mixer_line_level(sc, IW_LOOPBACK, 0, 0);
465 iw_mixer_line_level(sc, IW_MONO_IN, 0, 0);
466
467 /* mem stuff */
468 iw_meminit(sc);
469
470 }
471 IW_WRITE_CODEC_1(CEXTI, 0x02); /* codec int enable */
472
473 /* clear _LDMACI */
474
475 IW_WRITE_GENERAL_1(LDMACI, 0x00);
476
477 /* enable mixer paths */
478 mixer_image = 0x0c;
479 IW_WRITE_DIRECT_1(sc->p2xr, sc->p2xr_h, mixer_image);
480 /*
481 * enable output, line in. disable mic in bit 0 = 0 -> line in on
482 * (from codec?) bit 1 = 0 -> output on bit 2 = 1 -> mic in on bit 3
483 * = 1 -> irq&drq pin enable bit 4 = 1 -> channel interrupts to chan
484 * 1 bit 5 = 1 -> enable midi loop back bit 6 = 0 -> irq latches
485 * URCR[2:0] bit 6 = 1 -> DMA latches URCR[2:0]
486 */
487
488
489 IW_READ_DIRECT_1(sc->p2xr, sc->p2xr_h, mixer_image);
490 #ifdef AUDIO_DEBUG
491 if (!warm)
492 DPRINTF(("mix image %x \n", mixer_image));
493 #endif
494 }
495
496 struct iw_codec_freq {
497 u_long freq;
498 u_char bits;
499 };
500
501 int
502 iw_set_speed(sc, freq, in)
503 struct iw_softc *sc;
504 u_long freq;
505 char in;
506 {
507 u_char var, cfig3, reg;
508
509 static struct iw_codec_freq iw_cf[17] = {
510 #define FREQ_1 24576000
511 #define FREQ_2 16934400
512 #define XTAL1 0
513 #define XTAL2 1
514 {5510, 0x00 | XTAL2}, {6620, 0x0E | XTAL2},
515 {8000, 0x00 | XTAL1}, {9600, 0x0E | XTAL1},
516 {11025, 0x02 | XTAL2}, {16000, 0x02 | XTAL1},
517 {18900, 0x04 | XTAL2}, {22050, 0x06 | XTAL2},
518 {27420, 0x04 | XTAL1}, {32000, 0x06 | XTAL1},
519 {33075, 0x0C | XTAL2}, {37800, 0x08 | XTAL2},
520 {38400, 0x0A | XTAL1}, {44100, 0x0A | XTAL2},
521 {44800, 0x08 | XTAL1}, {48000, 0x0C | XTAL1},
522 {48000, 0x0C | XTAL1} /* really a dummy for indexing later */
523 #undef XTAL1
524 #undef XTAL2
525 };
526
527 cfig3 = 0; /* XXX gcc -Wall */
528
529 /*
530 * if the frequency is between 3493Hz and 32KHz we can use a more
531 * accurate frequency than the ones listed above base on the formula
532 * FREQ/((16*(48+x))) where FREQ is either FREQ_1 (24576000Hz) or
533 * FREQ_2 (16934400Hz) and x is the value to be written to either
534 * CPVFI or CRVFI. To enable this option, bit 2 in CFIG3 needs to be
535 * set high
536 *
537 * NOT IMPLEMENTED!
538 *
539 * Note that if you have a 'bad' XTAL_1 (higher than 18.5 MHz), 44.8KHz
540 * and 38.4KHz modes will provide wrong frequencies to output.
541 */
542
543
544 if (freq > 48000)
545 freq = 48000;
546 if (freq < 5510)
547 freq = 5510;
548
549 /* reset CFIG3[2] */
550
551 IW_READ_CODEC_1(CFIG3I, cfig3);
552
553 cfig3 |= 0xc0; /* not full fifo treshhold */
554
555 DPRINTF(("cfig3i = %x -> ", cfig3));
556
557 cfig3 &= ~0x04;
558 IW_WRITE_CODEC_1(CFIG3I, cfig3);
559 IW_READ_CODEC_1(CFIG3I, cfig3);
560
561 DPRINTF(("%x\n", cfig3));
562
563 for (var = 0; var < 16; var++) /* select closest frequency */
564 if (freq <= iw_cf[var].freq)
565 break;
566 if (var != 16)
567 if (abs(freq - iw_cf[var].freq) > abs(iw_cf[var + 1].freq - freq))
568 var++;
569
570 if (in)
571 IW_WRITE_CODEC_1(CRDFI | IW_MCE, sc->recfmtbits | iw_cf[var].bits);
572 else
573 IW_WRITE_CODEC_1(CPDFI | IW_MCE, sc->playfmtbits | iw_cf[var].bits);
574 freq = iw_cf[var].freq;
575 DPRINTF(("setting %s frequency to %d bits %x \n",
576 in ? "in" : "out", (int) freq, iw_cf[var].bits));
577
578 IW_READ_CODEC_1(CPDFI, reg);
579
580 DPRINTF((" CPDFI %x ", reg));
581
582 IW_READ_CODEC_1(CRDFI, reg);
583
584 DPRINTF((" CRDFI %x ", reg));
585
586 return freq;
587 }
588
589 /* Encoding. */
590 int
591 iw_query_encoding(addr, fp)
592 void *addr;
593 struct audio_encoding *fp;
594 {
595 /*
596 * LINEAR, ALAW, ULAW, ADPCM in HW, we'll use linear unsigned
597 * hardware mode for all 8-bit modes due to buggy (?) codec.
598 */
599
600 /*
601 * except in wavetable synth. there we have only mu-law and 8 and 16
602 * bit linear data
603 */
604
605 switch (fp->index) {
606 case 0:
607 strcpy(fp->name, AudioEulinear);
608 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
609 fp->precision = 8;
610 fp->flags = 0;
611 break;
612 case 1:
613 strcpy(fp->name, AudioEmulaw);
614 fp->encoding = AUDIO_ENCODING_ULAW;
615 fp->precision = 8;
616 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
617 break;
618 case 2:
619 strcpy(fp->name, AudioEalaw);
620 fp->encoding = AUDIO_ENCODING_ALAW;
621 fp->precision = 8;
622 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
623 break;
624 case 3:
625 strcpy(fp->name, AudioEadpcm);
626 fp->encoding = AUDIO_ENCODING_ADPCM;
627 fp->precision = 8; /* really 4 bit */
628 fp->flags = 0;
629 break;
630 case 4:
631 strcpy(fp->name, AudioEslinear_le);
632 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
633 fp->precision = 16;
634 fp->flags = 0;
635 break;
636 case 5:
637 strcpy(fp->name, AudioEslinear_be);
638 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
639 fp->precision = 16;
640 fp->flags = 0;
641 break;
642 default:
643 return (EINVAL);
644 /* NOTREACHED */
645 }
646 return (0);
647 }
648
649
650
651 u_long
652 iw_set_format(sc, precision, in)
653 struct iw_softc *sc;
654 u_long precision;
655 int in;
656 {
657 u_char data;
658 int encoding, channels;
659
660 encoding = in ? sc->rec_encoding : sc->play_encoding;
661 channels = in ? sc->rec_channels : sc->play_channels;
662
663 DPRINTF(("iw_set_format\n"));
664
665 switch (encoding) {
666 case AUDIO_ENCODING_ULAW:
667 data = 0x00;
668 break;
669
670 case AUDIO_ENCODING_ALAW:
671 data = 0x00;
672 break;
673
674 case AUDIO_ENCODING_SLINEAR_LE:
675 if (precision == 16)
676 data = 0x40; /* little endian. 0xc0 is big endian */
677 else
678 data = 0x00;
679 break;
680
681 case AUDIO_ENCODING_SLINEAR_BE:
682 if (precision == 16)
683 data = 0xc0;
684 else
685 data = 0x00;
686 break;
687
688 case AUDIO_ENCODING_ADPCM:
689 data = 0xa0;
690 break;
691
692 default:
693 return -1;
694 }
695
696 if (channels == 2)
697 data |= 0x10; /* stereo */
698
699 if (in) {
700 /* in */
701 sc->recfmtbits = data;
702 /* This will zero the normal codec frequency,
703 * iw_set_speed should always be called afterwards.
704 */
705 IW_WRITE_CODEC_1(CRDFI | IW_MCE, data);
706 } else {
707 /* out */
708 sc->playfmtbits = data;
709 IW_WRITE_CODEC_1(CPDFI | IW_MCE, data);
710 }
711
712 DPRINTF(("formatbits %s %x", in ? "in" : "out", data));
713
714 return encoding;
715 }
716
717
718
719 int
720 iw_set_params(addr, setmode, usemode, p, q)
721 void *addr;
722 int setmode;
723 int usemode;
724 struct audio_params *p;
725 struct audio_params *q;
726 {
727 struct iw_softc *sc = addr;
728 void (*swcode)__P((void *, u_char * buf, int cnt)) = NULL;
729 int factor = 1;
730 DPRINTF(("iw_setparams: code %d, prec %d, rate %d, chan %d\n",
731 (int) p->encoding, (int) p->precision, (int) p->sample_rate,
732 (int) p->channels));
733
734
735 switch (p->encoding) {
736 case AUDIO_ENCODING_ULAW:
737 if (p->precision != 8)
738 return EINVAL;
739 swcode = setmode & AUMODE_PLAY ? mulaw_to_ulinear8 : ulinear8_to_mulaw;
740 factor = 1;
741 break;
742 case AUDIO_ENCODING_ALAW:
743 if (p->precision != 8)
744 return EINVAL;
745 swcode = setmode & AUMODE_PLAY ? alaw_to_ulinear8 : ulinear8_to_alaw;
746 factor = 1;
747 break;
748 case AUDIO_ENCODING_ADPCM:
749 if (p->precision != 8)
750 return EINVAL;
751 else
752 break;
753
754 case AUDIO_ENCODING_SLINEAR_LE:
755 case AUDIO_ENCODING_SLINEAR_BE:
756 if (p->precision != 8 && p->precision != 16)
757 return EINVAL;
758 else
759 break;
760
761 default:
762 return EINVAL;
763
764 }
765
766 if (setmode & AUMODE_PLAY) {
767 sc->play_channels = p->channels;
768 sc->play_encoding = p->encoding;
769 sc->play_precision = p->precision;
770 p->factor = factor;
771 p->sw_code = swcode;
772 iw_set_format(sc, p->precision, 0);
773 q->sample_rate = p->sample_rate = sc->sc_orate =
774 iw_set_speed(sc, p->sample_rate, 0);
775 } else {
776 #if 0
777 q->channels = sc->rec_channels = p->channels;
778 q->encoding = sc->rec_encoding = p->encoding;
779 q->precision = sc->rec_precision = p->precision;
780 #endif
781 sc->rec_channels = q->channels;
782 sc->rec_encoding = q->encoding;
783 sc->rec_precision = q->precision;
784 q->factor = factor;
785 q->sw_code = swcode;
786
787 iw_set_format(sc, p->precision, 1);
788 q->sample_rate = sc->sc_irate =
789 iw_set_speed(sc, q->sample_rate, 1);
790 }
791 return 0;
792 }
793
794
795 int
796 iw_round_blocksize(addr, blk)
797 void *addr;
798 int blk;
799 {
800 /* Round to a multiple of the biggest sample size. */
801 return blk &= -4;
802 }
803
804 void
805 iw_mixer_line_level(sc, line, levl, levr)
806 struct iw_softc *sc;
807 int line;
808 int levl, levr;
809 {
810 u_char gainl, gainr, attenl, attenr;
811
812 switch (line) {
813 case IW_REC:
814 gainl = sc->sc_recsrcbits | (levl >> 4);
815 gainr = sc->sc_recsrcbits | (levr >> 4);
816 DPRINTF(("recording with %x", gainl));
817 IW_WRITE_CODEC_1(CLICI, gainl);
818 IW_WRITE_CODEC_1(CRICI, gainr);
819 sc->sc_rec.voll = levl & 0xf0;
820 sc->sc_rec.volr = levr & 0xf0;
821 break;
822
823 case IW_AUX1:
824
825 gainl = (255 - levl) >> 3;
826 gainr = (255 - levr) >> 3;
827
828 /* mute if 0 level */
829 if (levl == 0)
830 gainl |= 0x80;
831 if (levr == 0)
832 gainr |= 0x80;
833
834 IW_WRITE_CODEC_1(IW_LEFT_AUX1_PORT, gainl);
835 IW_WRITE_CODEC_1(IW_RIGHT_AUX1_PORT, gainr);
836 sc->sc_aux1.voll = levl & 0xf8;
837 sc->sc_aux1.volr = levr & 0xf8;
838
839 break;
840
841 case IW_AUX2:
842
843 gainl = (255 - levl) >> 3;
844 gainr = (255 - levr) >> 3;
845
846 /* mute if 0 level */
847 if (levl == 0)
848 gainl |= 0x80;
849 if (levr == 0)
850 gainr |= 0x80;
851
852 IW_WRITE_CODEC_1(IW_LEFT_AUX2_PORT, gainl);
853 IW_WRITE_CODEC_1(IW_RIGHT_AUX2_PORT, gainr);
854 sc->sc_aux2.voll = levl & 0xf8;
855 sc->sc_aux2.volr = levr & 0xf8;
856 break;
857 case IW_DAC:
858 attenl = ((255 - levl) >> 2) | ((levl && !sc->sc_dac.off) ? 0 : 0x80);
859 attenr = ((255 - levr) >> 2) | ((levr && !sc->sc_dac.off) ? 0 : 0x80);
860 IW_WRITE_CODEC_1(CLDACI, attenl);
861 IW_WRITE_CODEC_1(CRDACI, attenr);
862 sc->sc_dac.voll = levl & 0xfc;
863 sc->sc_dac.volr = levr & 0xfc;
864 break;
865 case IW_LOOPBACK:
866 attenl = ((255 - levl) & 0xfc) | (levl ? 0x01 : 0);
867 IW_WRITE_CODEC_1(CLCI, attenl);
868 sc->sc_loopback.voll = levl & 0xfc;
869 break;
870 case IW_LINE_IN:
871 gainl = (levl >> 3) | (levl ? 0 : 0x80);
872 gainr = (levr >> 3) | (levr ? 0 : 0x80);
873 IW_WRITE_CODEC_1(CLLICI, gainl);
874 IW_WRITE_CODEC_1(CRLICI, gainr);
875 sc->sc_linein.voll = levl & 0xf8;
876 sc->sc_linein.volr = levr & 0xf8;
877 break;
878 case IW_MIC_IN:
879 gainl = ((255 - levl) >> 3) | (levl ? 0 : 0x80);
880 gainr = ((255 - levr) >> 3) | (levr ? 0 : 0x80);
881 IW_WRITE_CODEC_1(CLMICI, gainl);
882 IW_WRITE_CODEC_1(CRMICI, gainr);
883 sc->sc_mic.voll = levl & 0xf8;
884 sc->sc_mic.volr = levr & 0xf8;
885 break;
886 case IW_LINE_OUT:
887 attenl = ((255 - levl) >> 3) | (levl ? 0 : 0x80);
888 attenr = ((255 - levr) >> 3) | (levr ? 0 : 0x80);
889 IW_WRITE_CODEC_1(CLOAI, attenl);
890 IW_WRITE_CODEC_1(CROAI, attenr);
891 sc->sc_lineout.voll = levl & 0xf8;
892 sc->sc_lineout.volr = levr & 0xf8;
893 break;
894 case IW_MONO_IN:
895 attenl = ((255 - levl) >> 4) | (levl ? 0 : 0xc0); /* in/out mute */
896 IW_WRITE_CODEC_1(CMONOI, attenl);
897 sc->sc_monoin.voll = levl & 0xf0;
898 break;
899 }
900 }
901
902 int
903 iw_commit_settings(addr)
904 void *addr;
905 {
906 return 0;
907 }
908
909
910 void
911 iw_trigger_dma(sc, io)
912 struct iw_softc *sc;
913 u_char io;
914 {
915 u_char reg;
916 int s;
917
918 s = splaudio();
919
920 IW_READ_CODEC_1(CSR3I, reg);
921 IW_WRITE_CODEC_1(CSR3I, reg & ~(io == IW_DMA_PLAYBACK ? 0x10 : 0x20));
922
923 IW_READ_CODEC_1(CFIG1I, reg);
924
925 IW_WRITE_CODEC_1(CFIG1I, reg | io);
926
927 /* let the counter run */
928 IW_READ_CODEC_1(CFIG2I, reg);
929 IW_WRITE_CODEC_1(CFIG2I, reg & ~(io << 4));
930
931 splx(s);
932 }
933
934 void
935 iw_stop_dma(sc, io, hard)
936 struct iw_softc *sc;
937 u_char io, hard;
938 {
939 u_char reg;
940
941 /* just stop the counter, no need to flush the fifo */
942 IW_READ_CODEC_1(CFIG2I, reg);
943 IW_WRITE_CODEC_1(CFIG2I, (reg | (io << 4)));
944
945 if (hard) {
946 /* unless we're closing the device */
947 IW_READ_CODEC_1(CFIG1I, reg);
948 IW_WRITE_CODEC_1(CFIG1I, reg & ~io);
949 }
950 }
951
952 void
953 iw_dma_count(sc, count, io)
954 struct iw_softc *sc;
955 u_short count;
956 int io;
957 {
958 if (io == IW_DMA_PLAYBACK) {
959 IW_WRITE_CODEC_1(CLPCTI, (u_char) (count & 0x00ff));
960 IW_WRITE_CODEC_1(CUPCTI, (u_char) ((count >> 8) & 0x00ff));
961 } else {
962 IW_WRITE_CODEC_1(CLRCTI, (u_char) (count & 0x00ff));
963 IW_WRITE_CODEC_1(CURCTI, (u_char) ((count >> 8) & 0x00ff));
964 }
965 }
966
967 int
968 iw_init_output(addr, buf, cc)
969 void *addr;
970 void *buf;
971 int cc;
972 {
973 struct iw_softc *sc = (struct iw_softc *) addr;
974
975 DPRINTF(("iw_init_output\n"));
976
977 isa_dmastart(sc->sc_ic, sc->sc_playdrq, buf,
978 cc, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
979 return 0;
980 }
981
982 int
983 iw_init_input(addr, buf, cc)
984 void *addr;
985 void *buf;
986 int cc;
987 {
988 struct iw_softc *sc = (struct iw_softc *) addr;
989
990 DPRINTF(("iw_init_input\n"));
991
992 isa_dmastart(sc->sc_ic, sc->sc_recdrq, buf,
993 cc, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
994 return 0;
995 }
996
997
998 int
999 iw_start_output(addr, p, cc, intr, arg)
1000 void *addr;
1001 void *p;
1002 int cc;
1003 void (*intr)__P((void *));
1004 void *arg;
1005 {
1006 struct iw_softc *sc = addr;
1007
1008 #ifdef DIAGNOSTIC
1009 if (!intr) {
1010 printf("iw_start_output: no callback!\n");
1011 return 1;
1012 }
1013 #endif
1014
1015 sc->sc_playintr = intr;
1016 sc->sc_playarg = arg;
1017 sc->sc_dma_flags |= DMAMODE_WRITE;
1018 sc->sc_playdma_bp = p;
1019
1020 isa_dmastart(sc->sc_ic, sc->sc_playdrq, sc->sc_playdma_bp,
1021 cc, NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
1022
1023
1024 if (sc->play_encoding == AUDIO_ENCODING_ADPCM)
1025 cc >>= 2;
1026 if (sc->play_precision == 16)
1027 cc >>= 1;
1028
1029 if (sc->play_channels == 2 && sc->play_encoding != AUDIO_ENCODING_ADPCM)
1030 cc >>= 1;
1031
1032 cc -= iw_cc;
1033
1034 /* iw_dma_access(sc,1); */
1035 if (cc != sc->sc_playdma_cnt) {
1036 iw_dma_count(sc, (u_short) cc, IW_DMA_PLAYBACK);
1037 sc->sc_playdma_cnt = cc;
1038
1039 iw_trigger_dma(sc, IW_DMA_PLAYBACK);
1040 }
1041
1042 #ifdef DIAGNOSTIC
1043 if (outputs != iw_ints)
1044 printf("iw_start_output: out %d, int %d\n", outputs, iw_ints);
1045 outputs++;
1046 #endif
1047
1048 return 0;
1049 }
1050
1051
1052 int
1053 iw_start_input(addr, p, cc, intr, arg)
1054 void *addr;
1055 void *p;
1056 int cc;
1057 void (*intr)__P((void *));
1058 void *arg;
1059 {
1060 struct iw_softc *sc = addr;
1061
1062 #ifdef DIAGNOSTIC
1063 if (!intr) {
1064 printf("iw_start_input: no callback!\n");
1065 return 1;
1066 }
1067 #endif
1068
1069 sc->sc_recintr = intr;
1070 sc->sc_recarg = arg;
1071 sc->sc_dma_flags |= DMAMODE_READ;
1072 sc->sc_recdma_bp = p;
1073
1074 isa_dmastart(sc->sc_ic, sc->sc_recdrq, sc->sc_recdma_bp,
1075 cc, NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
1076
1077
1078 if (sc->rec_encoding == AUDIO_ENCODING_ADPCM)
1079 cc >>= 2;
1080 if (sc->rec_precision == 16)
1081 cc >>= 1;
1082
1083 if (sc->rec_channels == 2 && sc->rec_encoding != AUDIO_ENCODING_ADPCM)
1084 cc >>= 1;
1085
1086 cc -= iw_cc;
1087
1088 /* iw_dma_access(sc,0); */
1089 if (sc->sc_recdma_cnt != cc) {
1090 iw_dma_count(sc, (u_short) cc, IW_DMA_RECORD);
1091 sc->sc_recdma_cnt = cc;
1092 /* iw_dma_ctrl(sc, IW_DMA_RECORD); */
1093 iw_trigger_dma(sc, IW_DMA_RECORD);
1094 }
1095
1096 #ifdef DIAGNOSTIC
1097 if ((inputs != iw_inints))
1098 printf("iw_start_input: in %d, inints %d\n", inputs, iw_inints);
1099 inputs++;
1100 #endif
1101
1102 return 0;
1103 }
1104
1105
1106 int
1107 iw_halt_output(addr)
1108 void *addr;
1109 {
1110 struct iw_softc *sc = addr;
1111
1112 iw_stop_dma(sc, IW_DMA_PLAYBACK, 0);
1113 return 0;
1114 }
1115
1116
1117 int
1118 iw_halt_input(addr)
1119 void *addr;
1120 {
1121 struct iw_softc *sc = addr;
1122
1123 iw_stop_dma(sc, IW_DMA_RECORD, 0);
1124 return 0;
1125 }
1126
1127
1128 int
1129 iw_speaker_ctl(addr, newstate)
1130 void *addr;
1131 int newstate;
1132 {
1133 struct iw_softc *sc = addr;
1134 u_char reg;
1135 if (newstate == SPKR_ON) {
1136 sc->sc_dac.off = 0;
1137 IW_READ_CODEC_1(CLDACI, reg);
1138 IW_WRITE_CODEC_1(CLDACI, reg & 0x7f);
1139 IW_READ_CODEC_1(CRDACI, reg);
1140 IW_WRITE_CODEC_1(CRDACI, reg & 0x7f);
1141 } else {
1142 /* SPKR_OFF */
1143 sc->sc_dac.off = 1;
1144 IW_READ_CODEC_1(CLDACI, reg);
1145 IW_WRITE_CODEC_1(CLDACI, reg | 0x80);
1146 IW_READ_CODEC_1(CRDACI, reg);
1147 IW_WRITE_CODEC_1(CRDACI, reg | 0x80);
1148 }
1149 return 0;
1150 }
1151
1152
1153 int
1154 iw_getdev(addr, retp)
1155 void *addr;
1156 struct audio_device *retp;
1157 {
1158 *retp = iw_device;
1159 return 0;
1160 }
1161
1162
1163 int
1164 iw_setfd(addr, flag)
1165 void *addr;
1166 int flag;
1167 {
1168 return 0;
1169 }
1170
1171
1172 /* Mixer (in/out ports) */
1173 int
1174 iw_set_port(addr, cp)
1175 void *addr;
1176 mixer_ctrl_t *cp;
1177 {
1178 struct iw_softc *sc = addr;
1179 u_char vall = 0, valr = 0;
1180 int error = EINVAL;
1181
1182 switch (cp->dev) {
1183 case IW_MIC_IN_LVL:
1184 if (cp->type == AUDIO_MIXER_VALUE) {
1185 error = 0;
1186 if (cp->un.value.num_channels == 1) {
1187 vall = valr = cp->un.value.level[0];
1188 } else {
1189 vall = cp->un.value.level[0];
1190 valr = cp->un.value.level[1];
1191 }
1192 sc->sc_mic.voll = vall;
1193 sc->sc_mic.volr = valr;
1194 iw_mixer_line_level(sc, IW_MIC_IN, vall, valr);
1195 }
1196 break;
1197 case IW_AUX1_LVL:
1198 if (cp->type == AUDIO_MIXER_VALUE) {
1199 error = 0;
1200 if (cp->un.value.num_channels == 1) {
1201 vall = valr = cp->un.value.level[0];
1202 } else {
1203 vall = cp->un.value.level[0];
1204 valr = cp->un.value.level[1];
1205 }
1206 sc->sc_aux1.voll = vall;
1207 sc->sc_aux1.volr = valr;
1208 iw_mixer_line_level(sc, IW_AUX1, vall, valr);
1209 }
1210 break;
1211 case IW_AUX2_LVL:
1212 if (cp->type == AUDIO_MIXER_VALUE) {
1213 error = 0;
1214 if (cp->un.value.num_channels == 1) {
1215 vall = valr = cp->un.value.level[0];
1216 } else {
1217 vall = cp->un.value.level[0];
1218 valr = cp->un.value.level[1];
1219 }
1220 sc->sc_aux2.voll = vall;
1221 sc->sc_aux2.volr = valr;
1222 iw_mixer_line_level(sc, IW_AUX2, vall, valr);
1223 }
1224 break;
1225 case IW_LINE_IN_LVL:
1226 if (cp->type == AUDIO_MIXER_VALUE) {
1227 error = 0;
1228 if (cp->un.value.num_channels == 1) {
1229 vall = valr = cp->un.value.level[0];
1230 } else {
1231 vall = cp->un.value.level[0];
1232 valr = cp->un.value.level[1];
1233 }
1234 sc->sc_linein.voll = vall;
1235 sc->sc_linein.volr = valr;
1236 iw_mixer_line_level(sc, IW_LINE_IN, vall, valr);
1237 }
1238 break;
1239 case IW_LINE_OUT_LVL:
1240 if (cp->type == AUDIO_MIXER_VALUE) {
1241 error = 0;
1242 if (cp->un.value.num_channels == 1) {
1243 vall = valr = cp->un.value.level[0];
1244 } else {
1245 vall = cp->un.value.level[0];
1246 valr = cp->un.value.level[1];
1247 }
1248 sc->sc_lineout.voll = vall;
1249 sc->sc_lineout.volr = valr;
1250 iw_mixer_line_level(sc, IW_LINE_OUT, vall, valr);
1251 }
1252 break;
1253 case IW_REC_LVL:
1254 if (cp->type == AUDIO_MIXER_VALUE) {
1255 error = 0;
1256 if (cp->un.value.num_channels == 1) {
1257 vall = valr = cp->un.value.level[0];
1258 } else {
1259 vall = cp->un.value.level[0];
1260 valr = cp->un.value.level[1];
1261 }
1262 sc->sc_rec.voll = vall;
1263 sc->sc_rec.volr = valr;
1264 iw_mixer_line_level(sc, IW_REC, vall, valr);
1265 }
1266 break;
1267
1268 case IW_DAC_LVL:
1269 if (cp->type == AUDIO_MIXER_VALUE) {
1270 error = 0;
1271 if (cp->un.value.num_channels == 1) {
1272 vall = valr = cp->un.value.level[0];
1273 } else {
1274 vall = cp->un.value.level[0];
1275 valr = cp->un.value.level[1];
1276 }
1277 sc->sc_dac.voll = vall;
1278 sc->sc_dac.volr = valr;
1279 iw_mixer_line_level(sc, IW_DAC, vall, valr);
1280 }
1281 break;
1282
1283 case IW_LOOPBACK_LVL:
1284 if (cp->type == AUDIO_MIXER_VALUE) {
1285 error = 0;
1286 if (cp->un.value.num_channels != 1) {
1287 return EINVAL;
1288 } else {
1289 valr = vall = cp->un.value.level[0];
1290 }
1291 sc->sc_loopback.voll = vall;
1292 sc->sc_loopback.volr = valr;
1293 iw_mixer_line_level(sc, IW_LOOPBACK, vall, valr);
1294 }
1295 break;
1296
1297 case IW_MONO_IN_LVL:
1298 if (cp->type == AUDIO_MIXER_VALUE) {
1299 error = 0;
1300 if (cp->un.value.num_channels != 1) {
1301 return EINVAL;
1302 } else {
1303 valr = vall = cp->un.value.level[0];
1304 }
1305 sc->sc_monoin.voll = vall;
1306 sc->sc_monoin.volr = valr;
1307 iw_mixer_line_level(sc, IW_MONO_IN, vall, valr);
1308 }
1309 break;
1310 case IW_RECORD_SOURCE:
1311 error = 0;
1312 sc->sc_recsrcbits = cp->un.ord << 6;
1313 DPRINTF(("record source %d bits %x\n", cp->un.ord, sc->sc_recsrcbits));
1314 iw_mixer_line_level(sc, IW_REC, sc->sc_rec.voll, sc->sc_rec.volr);
1315 break;
1316 }
1317
1318 return error;
1319 }
1320
1321
1322 int
1323 iw_get_port(addr, cp)
1324 void *addr;
1325 mixer_ctrl_t *cp;
1326 {
1327 struct iw_softc *sc = addr;
1328
1329 int error = EINVAL;
1330
1331 switch (cp->dev) {
1332 case IW_MIC_IN_LVL:
1333 if (cp->type == AUDIO_MIXER_VALUE) {
1334 cp->un.value.num_channels = 2;
1335 cp->un.value.level[0] = sc->sc_mic.voll;
1336 cp->un.value.level[1] = sc->sc_mic.volr;
1337 error = 0;
1338 }
1339 break;
1340 case IW_AUX1_LVL:
1341 if (cp->type == AUDIO_MIXER_VALUE) {
1342 cp->un.value.num_channels = 2;
1343 cp->un.value.level[0] = sc->sc_aux1.voll;
1344 cp->un.value.level[1] = sc->sc_aux1.volr;
1345 error = 0;
1346 }
1347 break;
1348 case IW_AUX2_LVL:
1349 if (cp->type == AUDIO_MIXER_VALUE) {
1350 cp->un.value.num_channels = 2;
1351 cp->un.value.level[0] = sc->sc_aux2.voll;
1352 cp->un.value.level[1] = sc->sc_aux2.volr;
1353 error = 0;
1354 }
1355 break;
1356 case IW_LINE_OUT_LVL:
1357 if (cp->type == AUDIO_MIXER_VALUE) {
1358 cp->un.value.num_channels = 2;
1359 cp->un.value.level[0] = sc->sc_lineout.voll;
1360 cp->un.value.level[1] = sc->sc_lineout.volr;
1361 error = 0;
1362 }
1363 break;
1364 case IW_LINE_IN_LVL:
1365 if (cp->type == AUDIO_MIXER_VALUE) {
1366 cp->un.value.num_channels = 2;
1367 cp->un.value.level[0] = sc->sc_linein.voll;
1368 cp->un.value.level[1] = sc->sc_linein.volr;
1369 error = 0;
1370 }
1371 case IW_REC_LVL:
1372 if (cp->type == AUDIO_MIXER_VALUE) {
1373 cp->un.value.num_channels = 2;
1374 cp->un.value.level[0] = sc->sc_rec.voll;
1375 cp->un.value.level[1] = sc->sc_rec.volr;
1376 error = 0;
1377 }
1378 break;
1379
1380 case IW_DAC_LVL:
1381 if (cp->type == AUDIO_MIXER_VALUE) {
1382 cp->un.value.num_channels = 2;
1383 cp->un.value.level[0] = sc->sc_dac.voll;
1384 cp->un.value.level[1] = sc->sc_dac.volr;
1385 error = 0;
1386 }
1387 break;
1388
1389 case IW_LOOPBACK_LVL:
1390 if (cp->type == AUDIO_MIXER_VALUE) {
1391 cp->un.value.num_channels = 1;
1392 cp->un.value.level[0] = sc->sc_loopback.voll;
1393 error = 0;
1394 }
1395 break;
1396
1397 case IW_MONO_IN_LVL:
1398 if (cp->type == AUDIO_MIXER_VALUE) {
1399 cp->un.value.num_channels = 1;
1400 cp->un.value.level[0] = sc->sc_monoin.voll;
1401 error = 0;
1402 }
1403 break;
1404 case IW_RECORD_SOURCE:
1405 cp->un.ord = sc->sc_recsrcbits >> 6;
1406 error = 0;
1407 break;
1408 }
1409
1410 return error;
1411 }
1412
1413
1414
1415 int
1416 iw_query_devinfo(addr, dip)
1417 void *addr;
1418 mixer_devinfo_t *dip;
1419 {
1420
1421 switch (dip->index) {
1422 case IW_MIC_IN_LVL: /* Microphone */
1423 dip->type = AUDIO_MIXER_VALUE;
1424 dip->mixer_class = IW_INPUT_CLASS;
1425 dip->prev = AUDIO_MIXER_LAST;
1426 dip->next = AUDIO_MIXER_LAST;
1427 strcpy(dip->label.name, AudioNmicrophone);
1428 dip->un.v.num_channels = 2;
1429 strcpy(dip->un.v.units.name, AudioNvolume);
1430 break;
1431 case IW_AUX1_LVL:
1432 dip->type = AUDIO_MIXER_VALUE;
1433 dip->mixer_class = IW_INPUT_CLASS;
1434 dip->prev = AUDIO_MIXER_LAST;
1435 dip->next = AUDIO_MIXER_LAST;
1436 strcpy(dip->label.name, AudioNline);
1437 dip->un.v.num_channels = 2;
1438 strcpy(dip->un.v.units.name, AudioNvolume);
1439 break;
1440 case IW_AUX2_LVL:
1441 dip->type = AUDIO_MIXER_VALUE;
1442 dip->mixer_class = IW_INPUT_CLASS;
1443 dip->prev = AUDIO_MIXER_LAST;
1444 dip->next = AUDIO_MIXER_LAST;
1445 strcpy(dip->label.name, AudioNcd);
1446 dip->un.v.num_channels = 2;
1447 strcpy(dip->un.v.units.name, AudioNvolume);
1448 break;
1449 case IW_LINE_OUT_LVL:
1450 dip->type = AUDIO_MIXER_VALUE;
1451 dip->mixer_class = IW_OUTPUT_CLASS;
1452 dip->prev = AUDIO_MIXER_LAST;
1453 dip->next = AUDIO_MIXER_LAST;
1454 strcpy(dip->label.name, AudioNline);
1455 dip->un.v.num_channels = 2;
1456 strcpy(dip->un.v.units.name, AudioNvolume);
1457 break;
1458 case IW_DAC_LVL:
1459 dip->type = AUDIO_MIXER_VALUE;
1460 dip->mixer_class = IW_OUTPUT_CLASS;
1461 dip->prev = AUDIO_MIXER_LAST;
1462 dip->next = AUDIO_MIXER_LAST;
1463 strcpy(dip->label.name, AudioNdac);
1464 dip->un.v.num_channels = 2;
1465 strcpy(dip->un.v.units.name, AudioNvolume);
1466 break;
1467 case IW_LINE_IN_LVL:
1468 dip->type = AUDIO_MIXER_VALUE;
1469 dip->mixer_class = IW_INPUT_CLASS;
1470 dip->prev = AUDIO_MIXER_LAST;
1471 dip->next = AUDIO_MIXER_LAST;
1472 strcpy(dip->label.name, AudioNinput);
1473 dip->un.v.num_channels = 2;
1474 strcpy(dip->un.v.units.name, AudioNvolume);
1475 break;
1476 case IW_MONO_IN_LVL:
1477 dip->type = AUDIO_MIXER_VALUE;
1478 dip->mixer_class = IW_INPUT_CLASS;
1479 dip->prev = AUDIO_MIXER_LAST;
1480 dip->next = AUDIO_MIXER_LAST;
1481 strcpy(dip->label.name, AudioNmono);
1482 dip->un.v.num_channels = 1;
1483 strcpy(dip->un.v.units.name, AudioNvolume);
1484 break;
1485
1486 case IW_REC_LVL: /* record level */
1487 dip->type = AUDIO_MIXER_VALUE;
1488 dip->mixer_class = IW_RECORD_CLASS;
1489 dip->prev = AUDIO_MIXER_LAST;
1490 dip->next = AUDIO_MIXER_LAST;
1491 strcpy(dip->label.name, AudioNrecord);
1492 dip->un.v.num_channels = 2;
1493 strcpy(dip->un.v.units.name, AudioNvolume);
1494 break;
1495
1496 case IW_LOOPBACK_LVL:
1497 dip->type = AUDIO_MIXER_VALUE;
1498 dip->mixer_class = IW_RECORD_CLASS;
1499 dip->prev = AUDIO_MIXER_LAST;
1500 dip->next = AUDIO_MIXER_LAST;
1501 strcpy(dip->label.name, "filter");
1502 dip->un.v.num_channels = 1;
1503 strcpy(dip->un.v.units.name, AudioNvolume);
1504 break;
1505
1506 case IW_RECORD_SOURCE:
1507 dip->mixer_class = IW_RECORD_CLASS;
1508 dip->type = AUDIO_MIXER_ENUM;
1509 dip->prev = AUDIO_MIXER_LAST;
1510 dip->next = AUDIO_MIXER_LAST;
1511 strcpy(dip->label.name, AudioNsource);
1512 dip->un.e.num_mem = 4;
1513 strcpy(dip->un.e.member[0].label.name, AudioNline);
1514 dip->un.e.member[0].ord = IW_LINE_IN_SRC;
1515 strcpy(dip->un.e.member[1].label.name, "aux1");
1516 dip->un.e.member[1].ord = IW_AUX1_SRC;
1517 strcpy(dip->un.e.member[2].label.name, AudioNmicrophone);
1518 dip->un.e.member[2].ord = IW_MIC_IN_SRC;
1519 strcpy(dip->un.e.member[3].label.name, AudioNmixerout);
1520 dip->un.e.member[3].ord = IW_MIX_OUT_SRC;
1521 break;
1522 case IW_INPUT_CLASS:
1523 dip->type = AUDIO_MIXER_CLASS;
1524 dip->mixer_class = IW_INPUT_CLASS;
1525 dip->next = dip->prev = AUDIO_MIXER_LAST;
1526 strcpy(dip->label.name, AudioCinputs);
1527 break;
1528 case IW_OUTPUT_CLASS:
1529 dip->type = AUDIO_MIXER_CLASS;
1530 dip->mixer_class = IW_OUTPUT_CLASS;
1531 dip->next = dip->prev = AUDIO_MIXER_LAST;
1532 strcpy(dip->label.name, AudioCoutputs);
1533 break;
1534 case IW_RECORD_CLASS: /* record source class */
1535 dip->type = AUDIO_MIXER_CLASS;
1536 dip->mixer_class = IW_RECORD_CLASS;
1537 dip->next = dip->prev = AUDIO_MIXER_LAST;
1538 strcpy(dip->label.name, AudioCrecord);
1539 return 0;
1540 default:
1541 return ENXIO;
1542 }
1543 return 0;
1544 }
1545
1546
1547 void *
1548 iw_malloc(addr, direction, size, pool, flags)
1549 void *addr;
1550 int direction;
1551 size_t size;
1552 struct malloc_type *pool;
1553 int flags;
1554 {
1555 struct iw_softc *sc = addr;
1556 int drq;
1557
1558 if (direction == AUMODE_PLAY)
1559 drq = sc->sc_playdrq;
1560 else
1561 drq = sc->sc_recdrq;
1562 return (isa_malloc(sc->sc_ic, drq, size, pool, flags));
1563 }
1564
1565 void
1566 iw_free(addr, ptr, pool)
1567 void *addr;
1568 void *ptr;
1569 struct malloc_type *pool;
1570 {
1571 isa_free(ptr, pool);
1572 }
1573
1574 size_t
1575 iw_round_buffersize(addr, direction, size)
1576 void *addr;
1577 int direction;
1578 size_t size;
1579 {
1580 struct iw_softc *sc = addr;
1581 bus_size_t maxsize;
1582
1583 if (direction == AUMODE_PLAY)
1584 maxsize = sc->sc_play_maxsize;
1585 else
1586 maxsize = sc->sc_rec_maxsize;
1587
1588 if (size > maxsize)
1589 size = maxsize;
1590 return (size);
1591 }
1592
1593 paddr_t
1594 iw_mappage(addr, mem, off, prot)
1595 void *addr;
1596 void *mem;
1597 off_t off;
1598 int prot;
1599 {
1600 return isa_mappage(mem, off, prot);
1601 }
1602
1603 int
1604 iw_get_props(addr)
1605 void *addr;
1606 {
1607 struct iw_softc *sc = addr;
1608 return AUDIO_PROP_MMAP |
1609 (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
1610 }
1611