audioamd.c revision 1.6.2.2 1 1.6.2.2 bouyer /* $NetBSD: audioamd.c,v 1.6.2.2 2000/11/20 20:25:30 bouyer Exp $ */
2 1.6.2.2 bouyer /* NetBSD: am7930_sparc.c,v 1.44 1999/03/14 22:29:00 jonathan Exp */
3 1.6.2.2 bouyer
4 1.6.2.2 bouyer /*
5 1.6.2.2 bouyer * Copyright (c) 1995 Rolf Grossmann
6 1.6.2.2 bouyer * All rights reserved.
7 1.6.2.2 bouyer *
8 1.6.2.2 bouyer * Redistribution and use in source and binary forms, with or without
9 1.6.2.2 bouyer * modification, are permitted provided that the following conditions
10 1.6.2.2 bouyer * are met:
11 1.6.2.2 bouyer * 1. Redistributions of source code must retain the above copyright
12 1.6.2.2 bouyer * notice, this list of conditions and the following disclaimer.
13 1.6.2.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
14 1.6.2.2 bouyer * notice, this list of conditions and the following disclaimer in the
15 1.6.2.2 bouyer * documentation and/or other materials provided with the distribution.
16 1.6.2.2 bouyer * 3. All advertising materials mentioning features or use of this software
17 1.6.2.2 bouyer * must display the following acknowledgement:
18 1.6.2.2 bouyer * This product includes software developed by Rolf Grossmann.
19 1.6.2.2 bouyer * 4. The name of the author may not be used to endorse or promote products
20 1.6.2.2 bouyer * derived from this software without specific prior written permission
21 1.6.2.2 bouyer *
22 1.6.2.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.6.2.2 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.6.2.2 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.6.2.2 bouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.6.2.2 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.6.2.2 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.6.2.2 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.6.2.2 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.6.2.2 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.6.2.2 bouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.6.2.2 bouyer */
33 1.6.2.2 bouyer
34 1.6.2.2 bouyer #include "audio.h"
35 1.6.2.2 bouyer #if NAUDIO > 0
36 1.6.2.2 bouyer
37 1.6.2.2 bouyer #include <sys/param.h>
38 1.6.2.2 bouyer #include <sys/systm.h>
39 1.6.2.2 bouyer #include <sys/errno.h>
40 1.6.2.2 bouyer #include <sys/device.h>
41 1.6.2.2 bouyer
42 1.6.2.2 bouyer #include <machine/bus.h>
43 1.6.2.2 bouyer #include <machine/intr.h>
44 1.6.2.2 bouyer #include <machine/autoconf.h>
45 1.6.2.2 bouyer
46 1.6.2.2 bouyer #include <sys/audioio.h>
47 1.6.2.2 bouyer #include <dev/audio_if.h>
48 1.6.2.2 bouyer
49 1.6.2.2 bouyer #include <dev/ic/am7930reg.h>
50 1.6.2.2 bouyer #include <dev/ic/am7930var.h>
51 1.6.2.2 bouyer #include <sparc/dev/audioamdvar.h>
52 1.6.2.2 bouyer
53 1.6.2.2 bouyer #define AUDIO_ROM_NAME "audio"
54 1.6.2.2 bouyer
55 1.6.2.2 bouyer #ifdef AUDIO_DEBUG
56 1.6.2.2 bouyer #define DPRINTF(x) if (am7930debug) printf x
57 1.6.2.2 bouyer #define DPRINTFN(n,x) if (am7930debug>(n)) printf x
58 1.6.2.2 bouyer #else
59 1.6.2.2 bouyer #define DPRINTF(x)
60 1.6.2.2 bouyer #define DPRINTFN(n,x)
61 1.6.2.2 bouyer #endif /* AUDIO_DEBUG */
62 1.6.2.2 bouyer
63 1.6.2.2 bouyer
64 1.6.2.2 bouyer /* interrupt interfaces */
65 1.6.2.2 bouyer #ifdef AUDIO_C_HANDLER
66 1.6.2.2 bouyer int am7930hwintr __P((void *));
67 1.6.2.2 bouyer #if defined(SUN4M)
68 1.6.2.2 bouyer #define AUDIO_SET_SWINTR do { \
69 1.6.2.2 bouyer if (CPU_ISSUN4M) \
70 1.6.2.2 bouyer raise(0, 4); \
71 1.6.2.2 bouyer else \
72 1.6.2.2 bouyer ienab_bis(IE_L4); \
73 1.6.2.2 bouyer } while(0);
74 1.6.2.2 bouyer #else
75 1.6.2.2 bouyer #define AUDIO_SET_SWINTR ienab_bis(IE_L4)
76 1.6.2.2 bouyer #endif /* defined(SUN4M) */
77 1.6.2.2 bouyer #else
78 1.6.2.2 bouyer struct auio *auiop;
79 1.6.2.2 bouyer #endif /* AUDIO_C_HANDLER */
80 1.6.2.2 bouyer int am7930swintr __P((void *));
81 1.6.2.2 bouyer
82 1.6.2.2 bouyer /*
83 1.6.2.2 bouyer * interrupt-handler status
84 1.6.2.2 bouyer */
85 1.6.2.2 bouyer struct am7930_intrhand {
86 1.6.2.2 bouyer int (*ih_fun) __P((void *));
87 1.6.2.2 bouyer void *ih_arg;
88 1.6.2.2 bouyer };
89 1.6.2.2 bouyer
90 1.6.2.2 bouyer struct audioamd_softc {
91 1.6.2.2 bouyer struct am7930_softc sc_am7930; /* glue to MI code */
92 1.6.2.2 bouyer
93 1.6.2.2 bouyer bus_space_tag_t sc_bt; /* bus cookie */
94 1.6.2.2 bouyer bus_space_handle_t sc_bh; /* device registers */
95 1.6.2.2 bouyer
96 1.6.2.2 bouyer struct am7930_intrhand sc_ih; /* interrupt vector (hw or sw) */
97 1.6.2.2 bouyer void (*sc_rintr)(void*); /* input completion intr handler */
98 1.6.2.2 bouyer void *sc_rarg; /* arg for sc_rintr() */
99 1.6.2.2 bouyer void (*sc_pintr)(void*); /* output completion intr handler */
100 1.6.2.2 bouyer void *sc_parg; /* arg for sc_pintr() */
101 1.6.2.2 bouyer
102 1.6.2.2 bouyer /* sc_au is special in that the hardware interrupt handler uses it */
103 1.6.2.2 bouyer struct auio sc_au; /* recv and xmit buffers, etc */
104 1.6.2.2 bouyer #define sc_intrcnt sc_au.au_intrcnt /* statistics */
105 1.6.2.2 bouyer };
106 1.6.2.2 bouyer
107 1.6.2.2 bouyer void audioamd_mainbus_attach __P((struct device *,
108 1.6.2.2 bouyer struct device *, void *));
109 1.6.2.2 bouyer int audioamd_mainbus_match __P((struct device *, struct cfdata *, void *));
110 1.6.2.2 bouyer void audioamd_sbus_attach __P((struct device *, struct device *, void *));
111 1.6.2.2 bouyer int audioamd_sbus_match __P((struct device *, struct cfdata *, void *));
112 1.6.2.2 bouyer void audioamd_attach(struct audioamd_softc *sc, int);
113 1.6.2.2 bouyer
114 1.6.2.2 bouyer struct cfattach audioamd_mainbus_ca = {
115 1.6.2.2 bouyer sizeof(struct audioamd_softc),
116 1.6.2.2 bouyer audioamd_mainbus_match,
117 1.6.2.2 bouyer audioamd_mainbus_attach
118 1.6.2.2 bouyer };
119 1.6.2.2 bouyer
120 1.6.2.2 bouyer struct cfattach audioamd_sbus_ca = {
121 1.6.2.2 bouyer sizeof(struct audioamd_softc),
122 1.6.2.2 bouyer audioamd_sbus_match,
123 1.6.2.2 bouyer audioamd_sbus_attach
124 1.6.2.2 bouyer };
125 1.6.2.2 bouyer
126 1.6.2.2 bouyer /*
127 1.6.2.2 bouyer * Define our interface into the am7930 MI driver.
128 1.6.2.2 bouyer */
129 1.6.2.2 bouyer
130 1.6.2.2 bouyer u_int8_t audioamd_codec_iread __P((struct am7930_softc *, int));
131 1.6.2.2 bouyer u_int16_t audioamd_codec_iread16 __P((struct am7930_softc *, int));
132 1.6.2.2 bouyer u_int8_t audioamd_codec_dread __P((struct audioamd_softc *, int));
133 1.6.2.2 bouyer void audioamd_codec_iwrite __P((struct am7930_softc *, int, u_int8_t));
134 1.6.2.2 bouyer void audioamd_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t));
135 1.6.2.2 bouyer void audioamd_codec_dwrite __P((struct audioamd_softc *, int, u_int8_t));
136 1.6.2.2 bouyer void audioamd_onopen __P((struct am7930_softc *sc));
137 1.6.2.2 bouyer void audioamd_onclose __P((struct am7930_softc *sc));
138 1.6.2.2 bouyer
139 1.6.2.2 bouyer struct am7930_glue audioamd_glue = {
140 1.6.2.2 bouyer audioamd_codec_iread,
141 1.6.2.2 bouyer audioamd_codec_iwrite,
142 1.6.2.2 bouyer audioamd_codec_iread16,
143 1.6.2.2 bouyer audioamd_codec_iwrite16,
144 1.6.2.2 bouyer audioamd_onopen,
145 1.6.2.2 bouyer audioamd_onclose,
146 1.6.2.2 bouyer 0,
147 1.6.2.2 bouyer 0,
148 1.6.2.2 bouyer 0,
149 1.6.2.2 bouyer };
150 1.6.2.2 bouyer
151 1.6.2.2 bouyer /*
152 1.6.2.2 bouyer * Define our interface to the higher level audio driver.
153 1.6.2.2 bouyer */
154 1.6.2.2 bouyer int audioamd_start_output __P((void *, void *, int, void (*)(void *),
155 1.6.2.2 bouyer void *));
156 1.6.2.2 bouyer int audioamd_start_input __P((void *, void *, int, void (*)(void *),
157 1.6.2.2 bouyer void *));
158 1.6.2.2 bouyer int audioamd_getdev __P((void *, struct audio_device *));
159 1.6.2.2 bouyer
160 1.6.2.2 bouyer struct audio_hw_if sa_hw_if = {
161 1.6.2.2 bouyer am7930_open,
162 1.6.2.2 bouyer am7930_close,
163 1.6.2.2 bouyer 0,
164 1.6.2.2 bouyer am7930_query_encoding,
165 1.6.2.2 bouyer am7930_set_params,
166 1.6.2.2 bouyer am7930_round_blocksize,
167 1.6.2.2 bouyer am7930_commit_settings,
168 1.6.2.2 bouyer 0,
169 1.6.2.2 bouyer 0,
170 1.6.2.2 bouyer audioamd_start_output, /* md */
171 1.6.2.2 bouyer audioamd_start_input, /* md */
172 1.6.2.2 bouyer am7930_halt_output,
173 1.6.2.2 bouyer am7930_halt_input,
174 1.6.2.2 bouyer 0,
175 1.6.2.2 bouyer audioamd_getdev,
176 1.6.2.2 bouyer 0,
177 1.6.2.2 bouyer am7930_set_port,
178 1.6.2.2 bouyer am7930_get_port,
179 1.6.2.2 bouyer am7930_query_devinfo,
180 1.6.2.2 bouyer 0,
181 1.6.2.2 bouyer 0,
182 1.6.2.2 bouyer 0,
183 1.6.2.2 bouyer 0,
184 1.6.2.2 bouyer am7930_get_props,
185 1.6.2.2 bouyer };
186 1.6.2.2 bouyer
187 1.6.2.2 bouyer struct audio_device audioamd_device = {
188 1.6.2.2 bouyer "am7930",
189 1.6.2.2 bouyer "x",
190 1.6.2.2 bouyer "audioamd"
191 1.6.2.2 bouyer };
192 1.6.2.2 bouyer
193 1.6.2.2 bouyer
194 1.6.2.2 bouyer int
195 1.6.2.2 bouyer audioamd_mainbus_match(parent, cf, aux)
196 1.6.2.2 bouyer struct device *parent;
197 1.6.2.2 bouyer struct cfdata *cf;
198 1.6.2.2 bouyer void *aux;
199 1.6.2.2 bouyer {
200 1.6.2.2 bouyer struct mainbus_attach_args *ma = aux;
201 1.6.2.2 bouyer
202 1.6.2.2 bouyer if (CPU_ISSUN4)
203 1.6.2.2 bouyer return (0);
204 1.6.2.2 bouyer return (strcmp(AUDIO_ROM_NAME, ma->ma_name) == 0);
205 1.6.2.2 bouyer }
206 1.6.2.2 bouyer
207 1.6.2.2 bouyer int
208 1.6.2.2 bouyer audioamd_sbus_match(parent, cf, aux)
209 1.6.2.2 bouyer struct device *parent;
210 1.6.2.2 bouyer struct cfdata *cf;
211 1.6.2.2 bouyer void *aux;
212 1.6.2.2 bouyer {
213 1.6.2.2 bouyer struct sbus_attach_args *sa = aux;
214 1.6.2.2 bouyer
215 1.6.2.2 bouyer return (strcmp(AUDIO_ROM_NAME, sa->sa_name) == 0);
216 1.6.2.2 bouyer }
217 1.6.2.2 bouyer
218 1.6.2.2 bouyer void
219 1.6.2.2 bouyer audioamd_mainbus_attach(parent, self, aux)
220 1.6.2.2 bouyer struct device *parent, *self;
221 1.6.2.2 bouyer void *aux;
222 1.6.2.2 bouyer {
223 1.6.2.2 bouyer struct mainbus_attach_args *ma = aux;
224 1.6.2.2 bouyer struct audioamd_softc *sc = (struct audioamd_softc *)self;
225 1.6.2.2 bouyer bus_space_handle_t bh;
226 1.6.2.2 bouyer
227 1.6.2.2 bouyer sc->sc_bt = ma->ma_bustag;
228 1.6.2.2 bouyer
229 1.6.2.2 bouyer if (bus_space_map2(
230 1.6.2.2 bouyer ma->ma_bustag,
231 1.6.2.2 bouyer ma->ma_iospace,
232 1.6.2.2 bouyer ma->ma_paddr,
233 1.6.2.2 bouyer AM7930_DREG_SIZE,
234 1.6.2.2 bouyer BUS_SPACE_MAP_LINEAR,
235 1.6.2.2 bouyer 0,
236 1.6.2.2 bouyer &bh) != 0) {
237 1.6.2.2 bouyer printf("%s: cannot map registers\n", self->dv_xname);
238 1.6.2.2 bouyer return;
239 1.6.2.2 bouyer }
240 1.6.2.2 bouyer sc->sc_bh = bh;
241 1.6.2.2 bouyer audioamd_attach(sc, ma->ma_pri);
242 1.6.2.2 bouyer }
243 1.6.2.2 bouyer
244 1.6.2.2 bouyer
245 1.6.2.2 bouyer void
246 1.6.2.2 bouyer audioamd_sbus_attach(parent, self, aux)
247 1.6.2.2 bouyer struct device *parent, *self;
248 1.6.2.2 bouyer void *aux;
249 1.6.2.2 bouyer {
250 1.6.2.2 bouyer struct sbus_attach_args *sa = aux;
251 1.6.2.2 bouyer struct audioamd_softc *sc = (struct audioamd_softc *)self;
252 1.6.2.2 bouyer bus_space_handle_t bh;
253 1.6.2.2 bouyer
254 1.6.2.2 bouyer sc->sc_bt = sa->sa_bustag;
255 1.6.2.2 bouyer
256 1.6.2.2 bouyer if (sbus_bus_map(
257 1.6.2.2 bouyer sa->sa_bustag,
258 1.6.2.2 bouyer sa->sa_slot,
259 1.6.2.2 bouyer sa->sa_offset,
260 1.6.2.2 bouyer AM7930_DREG_SIZE,
261 1.6.2.2 bouyer 0, 0,
262 1.6.2.2 bouyer &bh) != 0) {
263 1.6.2.2 bouyer printf("%s: cannot map registers\n", self->dv_xname);
264 1.6.2.2 bouyer return;
265 1.6.2.2 bouyer }
266 1.6.2.2 bouyer sc->sc_bh = bh;
267 1.6.2.2 bouyer audioamd_attach(sc, sa->sa_pri);
268 1.6.2.2 bouyer }
269 1.6.2.2 bouyer
270 1.6.2.2 bouyer void
271 1.6.2.2 bouyer audioamd_attach(sc, pri)
272 1.6.2.2 bouyer struct audioamd_softc *sc;
273 1.6.2.2 bouyer int pri;
274 1.6.2.2 bouyer {
275 1.6.2.2 bouyer
276 1.6.2.2 bouyer printf(" softpri %d\n", PIL_AUSOFT);
277 1.6.2.2 bouyer
278 1.6.2.2 bouyer /*
279 1.6.2.2 bouyer * Set up glue for MI code early; we use some of it here.
280 1.6.2.2 bouyer */
281 1.6.2.2 bouyer sc->sc_am7930.sc_glue = &audioamd_glue;
282 1.6.2.2 bouyer
283 1.6.2.2 bouyer am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE);
284 1.6.2.2 bouyer
285 1.6.2.2 bouyer #ifndef AUDIO_C_HANDLER
286 1.6.2.2 bouyer auiop = &sc->sc_au;
287 1.6.2.2 bouyer (void)bus_intr_establish(sc->sc_bt, pri, IPL_AUDIO,
288 1.6.2.2 bouyer BUS_INTR_ESTABLISH_FASTTRAP,
289 1.6.2.2 bouyer (int (*) __P((void *)))amd7930_trap, NULL);
290 1.6.2.2 bouyer #else
291 1.6.2.2 bouyer (void)bus_intr_establish(sc->sc_bt, pri, IPL_AUDIO, 0,
292 1.6.2.2 bouyer am7930hwintr, sc);
293 1.6.2.2 bouyer #endif
294 1.6.2.2 bouyer (void)bus_intr_establish(sc->sc_bt, PIL_AUSOFT, IPL_AUDIO,
295 1.6.2.2 bouyer BUS_INTR_ESTABLISH_SOFTINTR,
296 1.6.2.2 bouyer am7930swintr, sc);
297 1.6.2.2 bouyer
298 1.6.2.2 bouyer evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
299 1.6.2.2 bouyer sc->sc_am7930.sc_dev.dv_xname, "intr");
300 1.6.2.2 bouyer
301 1.6.2.2 bouyer audio_attach_mi(&sa_hw_if, sc, &sc->sc_am7930.sc_dev);
302 1.6.2.2 bouyer }
303 1.6.2.2 bouyer
304 1.6.2.2 bouyer
305 1.6.2.2 bouyer void
306 1.6.2.2 bouyer audioamd_onopen(sc)
307 1.6.2.2 bouyer struct am7930_softc *sc;
308 1.6.2.2 bouyer {
309 1.6.2.2 bouyer struct audioamd_softc *mdsc = (struct audioamd_softc *)sc;
310 1.6.2.2 bouyer
311 1.6.2.2 bouyer /* reset pdma state */
312 1.6.2.2 bouyer mdsc->sc_rintr = 0;
313 1.6.2.2 bouyer mdsc->sc_rarg = 0;
314 1.6.2.2 bouyer mdsc->sc_pintr = 0;
315 1.6.2.2 bouyer mdsc->sc_parg = 0;
316 1.6.2.2 bouyer
317 1.6.2.2 bouyer mdsc->sc_au.au_rdata = 0;
318 1.6.2.2 bouyer mdsc->sc_au.au_pdata = 0;
319 1.6.2.2 bouyer }
320 1.6.2.2 bouyer
321 1.6.2.2 bouyer
322 1.6.2.2 bouyer void
323 1.6.2.2 bouyer audioamd_onclose(sc)
324 1.6.2.2 bouyer struct am7930_softc *sc;
325 1.6.2.2 bouyer {
326 1.6.2.2 bouyer /* On sparc, just do the chipset-level halt. */
327 1.6.2.2 bouyer am7930_halt_input(sc);
328 1.6.2.2 bouyer am7930_halt_output(sc);
329 1.6.2.2 bouyer }
330 1.6.2.2 bouyer
331 1.6.2.2 bouyer int
332 1.6.2.2 bouyer audioamd_start_output(addr, p, cc, intr, arg)
333 1.6.2.2 bouyer void *addr;
334 1.6.2.2 bouyer void *p;
335 1.6.2.2 bouyer int cc;
336 1.6.2.2 bouyer void (*intr) __P((void *));
337 1.6.2.2 bouyer void *arg;
338 1.6.2.2 bouyer {
339 1.6.2.2 bouyer struct audioamd_softc *sc = addr;
340 1.6.2.2 bouyer
341 1.6.2.2 bouyer DPRINTFN(1, ("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
342 1.6.2.2 bouyer
343 1.6.2.2 bouyer if (!sc->sc_am7930.sc_locked) {
344 1.6.2.2 bouyer audioamd_codec_iwrite(&sc->sc_am7930,
345 1.6.2.2 bouyer AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
346 1.6.2.2 bouyer sc->sc_am7930.sc_locked = 1;
347 1.6.2.2 bouyer DPRINTF(("sa_start_output: started intrs.\n"));
348 1.6.2.2 bouyer }
349 1.6.2.2 bouyer sc->sc_pintr = intr;
350 1.6.2.2 bouyer sc->sc_parg = arg;
351 1.6.2.2 bouyer #ifndef AUDIO_C_HANDLER
352 1.6.2.2 bouyer sc->sc_au.au_bt = sc->sc_bt;
353 1.6.2.2 bouyer sc->sc_au.au_bh = sc->sc_bh;
354 1.6.2.2 bouyer #endif
355 1.6.2.2 bouyer sc->sc_au.au_pdata = p;
356 1.6.2.2 bouyer sc->sc_au.au_pend = (char *)p + cc - 1;
357 1.6.2.2 bouyer return(0);
358 1.6.2.2 bouyer }
359 1.6.2.2 bouyer
360 1.6.2.2 bouyer int
361 1.6.2.2 bouyer audioamd_start_input(addr, p, cc, intr, arg)
362 1.6.2.2 bouyer void *addr;
363 1.6.2.2 bouyer void *p;
364 1.6.2.2 bouyer int cc;
365 1.6.2.2 bouyer void (*intr) __P((void *));
366 1.6.2.2 bouyer void *arg;
367 1.6.2.2 bouyer {
368 1.6.2.2 bouyer struct audioamd_softc *sc = addr;
369 1.6.2.2 bouyer
370 1.6.2.2 bouyer DPRINTFN(1, ("sa_start_input: cc=%d %p (%p)\n", cc, intr, arg));
371 1.6.2.2 bouyer
372 1.6.2.2 bouyer if (!sc->sc_am7930.sc_locked) {
373 1.6.2.2 bouyer audioamd_codec_iwrite(&sc->sc_am7930,
374 1.6.2.2 bouyer AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
375 1.6.2.2 bouyer sc->sc_am7930.sc_locked = 1;
376 1.6.2.2 bouyer DPRINTF(("sa_start_input: started intrs.\n"));
377 1.6.2.2 bouyer }
378 1.6.2.2 bouyer sc->sc_rintr = intr;
379 1.6.2.2 bouyer sc->sc_rarg = arg;
380 1.6.2.2 bouyer #ifndef AUDIO_C_HANDLER
381 1.6.2.2 bouyer sc->sc_au.au_bt = sc->sc_bt;
382 1.6.2.2 bouyer sc->sc_au.au_bh = sc->sc_bh;
383 1.6.2.2 bouyer #endif
384 1.6.2.2 bouyer sc->sc_au.au_rdata = p;
385 1.6.2.2 bouyer sc->sc_au.au_rend = (char *)p + cc -1;
386 1.6.2.2 bouyer return(0);
387 1.6.2.2 bouyer }
388 1.6.2.2 bouyer
389 1.6.2.2 bouyer
390 1.6.2.2 bouyer /*
391 1.6.2.2 bouyer * Pseudo-DMA support: either C or locore assember.
392 1.6.2.2 bouyer */
393 1.6.2.2 bouyer
394 1.6.2.2 bouyer #ifdef AUDIO_C_HANDLER
395 1.6.2.2 bouyer int
396 1.6.2.2 bouyer am7930hwintr(sc)
397 1.6.2.2 bouyer struct audioamd_softc *au0;
398 1.6.2.2 bouyer {
399 1.6.2.2 bouyer struct auio *au = &sc->sc_au;
400 1.6.2.2 bouyer u_int8_t *d, *e;
401 1.6.2.2 bouyer int k;
402 1.6.2.2 bouyer
403 1.6.2.2 bouyer /* clear interrupt */
404 1.6.2.2 bouyer k = audioamd_codec_dread(sc, AM7930_DREG_IR);
405 1.6.2.2 bouyer
406 1.6.2.2 bouyer /* receive incoming data */
407 1.6.2.2 bouyer d = au->au_rdata;
408 1.6.2.2 bouyer e = au->au_rend;
409 1.6.2.2 bouyer if (d && d <= e) {
410 1.6.2.2 bouyer *d = audioamd_codec_dread(sc, AM7930_DREG_BBRB);
411 1.6.2.2 bouyer au->au_rdata++;
412 1.6.2.2 bouyer if (d == e) {
413 1.6.2.2 bouyer DPRINTFN(1, ("am7930hwintr: swintr(r) requested"));
414 1.6.2.2 bouyer AUDIO_SET_SWINTR;
415 1.6.2.2 bouyer }
416 1.6.2.2 bouyer }
417 1.6.2.2 bouyer
418 1.6.2.2 bouyer /* send outgoing data */
419 1.6.2.2 bouyer d = au->au_pdata;
420 1.6.2.2 bouyer e = au->au_pend;
421 1.6.2.2 bouyer if (d && d <= e) {
422 1.6.2.2 bouyer audioamd_codec_dwrite(sc, AM7930_DREG_BBTB, *d);
423 1.6.2.2 bouyer au->au_pdata++;
424 1.6.2.2 bouyer if (d == e) {
425 1.6.2.2 bouyer DPRINTFN(1, ("am7930hwintr: swintr(p) requested"));
426 1.6.2.2 bouyer AUDIO_SET_SWINTR;
427 1.6.2.2 bouyer }
428 1.6.2.2 bouyer }
429 1.6.2.2 bouyer
430 1.6.2.2 bouyer *(au->au_intrcnt)++;
431 1.6.2.2 bouyer return (1);
432 1.6.2.2 bouyer }
433 1.6.2.2 bouyer #endif /* AUDIO_C_HANDLER */
434 1.6.2.2 bouyer
435 1.6.2.2 bouyer int
436 1.6.2.2 bouyer am7930swintr(sc0)
437 1.6.2.2 bouyer void *sc0;
438 1.6.2.2 bouyer {
439 1.6.2.2 bouyer struct audioamd_softc *sc = sc0;
440 1.6.2.2 bouyer struct auio *au;
441 1.6.2.2 bouyer int s, ret = 0;
442 1.6.2.2 bouyer
443 1.6.2.2 bouyer DPRINTFN(1, ("audiointr: sc=%p\n", sc););
444 1.6.2.2 bouyer
445 1.6.2.2 bouyer au = &sc->sc_au;
446 1.6.2.2 bouyer s = splaudio();
447 1.6.2.2 bouyer if (au->au_rdata > au->au_rend && sc->sc_rintr != NULL) {
448 1.6.2.2 bouyer splx(s);
449 1.6.2.2 bouyer ret = 1;
450 1.6.2.2 bouyer (*sc->sc_rintr)(sc->sc_rarg);
451 1.6.2.2 bouyer s = splaudio();
452 1.6.2.2 bouyer }
453 1.6.2.2 bouyer if (au->au_pdata > au->au_pend && sc->sc_pintr != NULL) {
454 1.6.2.2 bouyer splx(s);
455 1.6.2.2 bouyer ret = 1;
456 1.6.2.2 bouyer (*sc->sc_pintr)(sc->sc_parg);
457 1.6.2.2 bouyer } else
458 1.6.2.2 bouyer splx(s);
459 1.6.2.2 bouyer return (ret);
460 1.6.2.2 bouyer }
461 1.6.2.2 bouyer
462 1.6.2.2 bouyer
463 1.6.2.2 bouyer /* indirect write */
464 1.6.2.2 bouyer void
465 1.6.2.2 bouyer audioamd_codec_iwrite(sc, reg, val)
466 1.6.2.2 bouyer struct am7930_softc *sc;
467 1.6.2.2 bouyer int reg;
468 1.6.2.2 bouyer u_int8_t val;
469 1.6.2.2 bouyer {
470 1.6.2.2 bouyer struct audioamd_softc *mdsc = (struct audioamd_softc *)sc;
471 1.6.2.2 bouyer
472 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
473 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val);
474 1.6.2.2 bouyer }
475 1.6.2.2 bouyer
476 1.6.2.2 bouyer void
477 1.6.2.2 bouyer audioamd_codec_iwrite16(sc, reg, val)
478 1.6.2.2 bouyer struct am7930_softc *sc;
479 1.6.2.2 bouyer int reg;
480 1.6.2.2 bouyer u_int16_t val;
481 1.6.2.2 bouyer {
482 1.6.2.2 bouyer struct audioamd_softc *mdsc = (struct audioamd_softc *)sc;
483 1.6.2.2 bouyer
484 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
485 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val);
486 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val>>8);
487 1.6.2.2 bouyer }
488 1.6.2.2 bouyer
489 1.6.2.2 bouyer
490 1.6.2.2 bouyer /* indirect read */
491 1.6.2.2 bouyer u_int8_t
492 1.6.2.2 bouyer audioamd_codec_iread(sc, reg)
493 1.6.2.2 bouyer struct am7930_softc *sc;
494 1.6.2.2 bouyer int reg;
495 1.6.2.2 bouyer {
496 1.6.2.2 bouyer struct audioamd_softc *mdsc = (struct audioamd_softc *)sc;
497 1.6.2.2 bouyer
498 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
499 1.6.2.2 bouyer return (audioamd_codec_dread(mdsc, AM7930_DREG_DR));
500 1.6.2.2 bouyer }
501 1.6.2.2 bouyer
502 1.6.2.2 bouyer u_int16_t
503 1.6.2.2 bouyer audioamd_codec_iread16(sc, reg)
504 1.6.2.2 bouyer struct am7930_softc *sc;
505 1.6.2.2 bouyer int reg;
506 1.6.2.2 bouyer {
507 1.6.2.2 bouyer struct audioamd_softc *mdsc = (struct audioamd_softc *)sc;
508 1.6.2.2 bouyer u_int8_t lo, hi;
509 1.6.2.2 bouyer
510 1.6.2.2 bouyer audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg);
511 1.6.2.2 bouyer lo = audioamd_codec_dread(mdsc, AM7930_DREG_DR);
512 1.6.2.2 bouyer hi = audioamd_codec_dread(mdsc, AM7930_DREG_DR);
513 1.6.2.2 bouyer return ((hi << 8) | lo);
514 1.6.2.2 bouyer }
515 1.6.2.2 bouyer
516 1.6.2.2 bouyer /* direct read */
517 1.6.2.2 bouyer u_int8_t
518 1.6.2.2 bouyer audioamd_codec_dread(sc, reg)
519 1.6.2.2 bouyer struct audioamd_softc *sc;
520 1.6.2.2 bouyer int reg;
521 1.6.2.2 bouyer {
522 1.6.2.2 bouyer return (bus_space_read_1(sc->sc_bt, sc->sc_bh, reg));
523 1.6.2.2 bouyer }
524 1.6.2.2 bouyer
525 1.6.2.2 bouyer /* direct write */
526 1.6.2.2 bouyer void
527 1.6.2.2 bouyer audioamd_codec_dwrite(sc, reg, val)
528 1.6.2.2 bouyer struct audioamd_softc *sc;
529 1.6.2.2 bouyer int reg;
530 1.6.2.2 bouyer u_int8_t val;
531 1.6.2.2 bouyer {
532 1.6.2.2 bouyer bus_space_write_1(sc->sc_bt, sc->sc_bh, reg, val);
533 1.6.2.2 bouyer }
534 1.6.2.2 bouyer
535 1.6.2.2 bouyer int
536 1.6.2.2 bouyer audioamd_getdev(addr, retp)
537 1.6.2.2 bouyer void *addr;
538 1.6.2.2 bouyer struct audio_device *retp;
539 1.6.2.2 bouyer {
540 1.6.2.2 bouyer
541 1.6.2.2 bouyer *retp = audioamd_device;
542 1.6.2.2 bouyer return (0);
543 1.6.2.2 bouyer }
544 1.6.2.2 bouyer
545 1.6.2.2 bouyer #endif /* NAUDIO > 0 */
546