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