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