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