xref: /openbsd/sys/dev/tc/bba.c (revision cc5bdd41)
1 /*	$OpenBSD: bba.c,v 1.12 2022/10/26 20:19:09 kn Exp $	*/
2 /* $NetBSD: bba.c,v 1.38 2011/06/04 01:27:57 tsutsui Exp $ */
3 /*
4  * Copyright (c) 2011 Miodrag Vallat.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * Copyright (c) 2000 The NetBSD Foundation, Inc.
20  * All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the above copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
32  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
33  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
35  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGE.
42  */
43 
44 /* maxine/alpha baseboard audio (bba) */
45 
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/device.h>
50 #include <sys/malloc.h>
51 
52 #include <machine/autoconf.h>
53 #include <machine/bus.h>
54 #include <machine/cpu.h>
55 
56 #include <sys/audioio.h>
57 #include <dev/audio_if.h>
58 
59 #include <dev/ic/am7930reg.h>
60 #include <dev/ic/am7930var.h>
61 
62 #include <dev/tc/tcvar.h>
63 #include <dev/tc/ioasicreg.h>
64 #include <dev/tc/ioasicvar.h>
65 
66 #ifdef AUDIO_DEBUG
67 #define DPRINTF(x)	if (am7930debug) printf x
68 #else
69 #define DPRINTF(x)
70 #endif  /* AUDIO_DEBUG */
71 
72 #define BBA_MAX_DMA_SEGMENTS	16
73 #define BBA_DMABUF_SIZE		(BBA_MAX_DMA_SEGMENTS*IOASIC_DMA_BLOCKSIZE)
74 #define BBA_DMABUF_ALIGN	IOASIC_DMA_BLOCKSIZE
75 #define BBA_DMABUF_BOUNDARY	0
76 
77 struct bba_mem {
78 	struct bba_mem *next;
79 	bus_addr_t addr;
80 	bus_size_t size;
81 	void *kva;
82 };
83 
84 struct bba_dma_state {
85 	bus_dmamap_t dmam;		/* DMA map */
86 	size_t size;
87 	int active;
88 	int curseg;			/* current segment in DMA buffer */
89 	void (*intr)(void *);		/* higher-level audio handler */
90 	void *intr_arg;
91 };
92 
93 struct bba_softc {
94 	struct am7930_softc sc_am7930;		/* glue to MI code */
95 
96 	bus_space_tag_t sc_bst;			/* IOASIC bus tag/handle */
97 	bus_space_handle_t sc_bsh;
98 	bus_dma_tag_t sc_dmat;
99 	bus_space_handle_t sc_codec_bsh;	/* codec bus space handle */
100 
101 	struct bba_mem *sc_mem_head;		/* list of buffers */
102 
103 	struct bba_dma_state sc_tx_dma_state;
104 	struct bba_dma_state sc_rx_dma_state;
105 };
106 
107 int	bba_match(struct device *, void *, void *);
108 void	bba_attach(struct device *, struct device *, void *);
109 
110 struct cfdriver bba_cd = {
111 	NULL, "bba", DV_DULL
112 };
113 
114 const struct cfattach bba_ca = {
115 	sizeof(struct bba_softc), bba_match, bba_attach
116 };
117 
118 /*
119  * Define our interface into the am7930 MI driver.
120  */
121 
122 uint8_t	 bba_codec_iread(struct am7930_softc *, int);
123 uint16_t bba_codec_iread16(struct am7930_softc *, int);
124 void	 bba_codec_iwrite(struct am7930_softc *, int, uint8_t);
125 void	 bba_codec_iwrite16(struct am7930_softc *, int, uint16_t);
126 void	 bba_onopen(struct am7930_softc *);
127 void	 bba_onclose(struct am7930_softc *);
128 
129 struct am7930_glue bba_glue = {
130 	bba_codec_iread,
131 	bba_codec_iwrite,
132 	bba_codec_iread16,
133 	bba_codec_iwrite16,
134 	bba_onopen,
135 	bba_onclose,
136 	24
137 };
138 
139 /*
140  * Define our interface to the higher level audio driver.
141  */
142 
143 int	bba_round_blocksize(void *, int);
144 int	bba_halt_output(void *);
145 int	bba_halt_input(void *);
146 void	*bba_allocm(void *, int, size_t, int, int);
147 void	bba_freem(void *, void *, int);
148 size_t	bba_round_buffersize(void *, int, size_t);
149 int	bba_trigger_output(void *, void *, void *, int,
150 	    void (*)(void *), void *, struct audio_params *);
151 int	bba_trigger_input(void *, void *, void *, int,
152 	    void (*)(void *), void *, struct audio_params *);
153 
154 const struct audio_hw_if bba_hw_if = {
155 	.open = am7930_open,
156 	.close = am7930_close,
157 	.set_params = am7930_set_params,
158 	.round_blocksize = bba_round_blocksize,
159 	.commit_settings = am7930_commit_settings,
160 	.halt_output = bba_halt_output,
161 	.halt_input = bba_halt_input,
162 	.set_port = am7930_set_port,
163 	.get_port = am7930_get_port,
164 	.query_devinfo = am7930_query_devinfo,
165 	.allocm = bba_allocm,
166 	.freem = bba_freem,
167 	.round_buffersize = bba_round_buffersize,
168 	.trigger_output = bba_trigger_output,
169 	.trigger_input = bba_trigger_input,
170 };
171 
172 int	bba_intr(void *);
173 void	bba_reset(struct bba_softc *, int);
174 void	bba_codec_dwrite(struct am7930_softc *, int, uint8_t);
175 uint8_t	bba_codec_dread(struct am7930_softc *, int);
176 
177 int
bba_match(struct device * parent,void * vcf,void * aux)178 bba_match(struct device *parent, void *vcf, void *aux)
179 {
180 	struct ioasicdev_attach_args *ia = aux;
181 
182 	if (strcmp(ia->iada_modname, "isdn") != 0 &&
183 	    strcmp(ia->iada_modname, "AMD79c30") != 0)
184 		return 0;
185 
186 	return 1;
187 }
188 
189 void
bba_attach(struct device * parent,struct device * self,void * aux)190 bba_attach(struct device *parent, struct device *self, void *aux)
191 {
192 	struct ioasicdev_attach_args *ia = aux;
193 	struct bba_softc *sc = (struct bba_softc *)self;
194 	struct ioasic_softc *iosc = (struct ioasic_softc *)parent;
195 
196 	sc->sc_bst = iosc->sc_bst;
197 	sc->sc_bsh = iosc->sc_bsh;
198 	sc->sc_dmat = iosc->sc_dmat;
199 
200 	/* get the bus space handle for codec */
201 	if (bus_space_subregion(sc->sc_bst, sc->sc_bsh,
202 	    ia->iada_offset, 0, &sc->sc_codec_bsh)) {
203 		printf(": unable to map device\n");
204 		return;
205 	}
206 
207 	printf("\n");
208 
209 	bba_reset(sc,1);
210 
211 	/*
212 	 * Set up glue for MI code early; we use some of it here.
213 	 */
214 	sc->sc_am7930.sc_glue = &bba_glue;
215 
216 	/*
217 	 *  MI initialisation.  We will be doing DMA.
218 	 */
219 	am7930_init(&sc->sc_am7930, AUDIOAMD_DMA_MODE);
220 
221 	ioasic_intr_establish(parent, ia->iada_cookie, IPL_AUDIO,
222 	    bba_intr, sc, self->dv_xname);
223 
224 	audio_attach_mi(&bba_hw_if, sc, NULL, self);
225 }
226 
227 void
bba_onopen(struct am7930_softc * sc)228 bba_onopen(struct am7930_softc *sc)
229 {
230 }
231 
232 void
bba_onclose(struct am7930_softc * sc)233 bba_onclose(struct am7930_softc *sc)
234 {
235 }
236 
237 void
bba_reset(struct bba_softc * sc,int reset)238 bba_reset(struct bba_softc *sc, int reset)
239 {
240 	uint32_t ssr;
241 
242 	/* disable any DMA and reset the codec */
243 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
244 	ssr &= ~(IOASIC_CSR_DMAEN_ISDN_T | IOASIC_CSR_DMAEN_ISDN_R);
245 	if (reset)
246 		ssr &= ~IOASIC_CSR_ISDN_ENABLE;
247 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
248 	DELAY(10);	/* 400ns required for codec to reset */
249 
250 	/* initialise DMA pointers */
251 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, 0);
252 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, 0);
253 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, 0);
254 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, 0);
255 
256 	/* take out of reset state */
257 	if (reset) {
258 		ssr |= IOASIC_CSR_ISDN_ENABLE;
259 		bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
260 	}
261 
262 }
263 
264 void *
bba_allocm(void * v,int direction,size_t size,int mtype,int flags)265 bba_allocm(void *v, int direction, size_t size, int mtype, int flags)
266 {
267 	struct bba_softc *sc = v;
268 	bus_dma_segment_t seg;
269 	int rseg;
270 	caddr_t kva;
271 	struct bba_mem *m;
272 	int w;
273 	int state;
274 
275 	DPRINTF(("bba_allocm: size = %zu\n", size));
276 	state = 0;
277 	w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
278 
279 	if (bus_dmamem_alloc(sc->sc_dmat, size, BBA_DMABUF_ALIGN,
280 	    BBA_DMABUF_BOUNDARY, &seg, 1, &rseg, w)) {
281 		printf("%s: can't allocate DMA buffer\n",
282 		    sc->sc_am7930.sc_dev.dv_xname);
283 		goto bad;
284 	}
285 	state |= 1;
286 
287 	if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
288 	    &kva, w | BUS_DMA_COHERENT)) {
289 		printf("%s: can't map DMA buffer\n",
290 		    sc->sc_am7930.sc_dev.dv_xname);
291 		goto bad;
292 	}
293 	state |= 2;
294 
295 	m = malloc(sizeof(struct bba_mem), mtype, flags | M_CANFAIL);
296 	if (m == NULL)
297 		goto bad;
298 	m->addr = seg.ds_addr;
299 	m->size = seg.ds_len;
300 	m->kva = kva;
301 	m->next = sc->sc_mem_head;
302 	sc->sc_mem_head = m;
303 
304 	return (void *)kva;
305 
306 bad:
307 	if (state & 2)
308 		bus_dmamem_unmap(sc->sc_dmat, kva, size);
309 	if (state & 1)
310 		bus_dmamem_free(sc->sc_dmat, &seg, 1);
311 	return NULL;
312 }
313 
314 void
bba_freem(void * v,void * ptr,int mtype)315 bba_freem(void *v, void *ptr, int mtype)
316 {
317 	struct bba_softc *sc = v;
318 	struct bba_mem **mp, *m;
319 	bus_dma_segment_t seg;
320 	void *kva;
321 
322 	kva = (void *)ptr;
323 	for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva; mp = &(*mp)->next)
324 		continue;
325 	m = *mp;
326 	if (m == NULL) {
327 		printf("bba_freem: freeing unallocated memory\n");
328 		return;
329 	}
330 	*mp = m->next;
331 	bus_dmamem_unmap(sc->sc_dmat, kva, m->size);
332 
333 	seg.ds_addr = m->addr;
334 	seg.ds_len = m->size;
335 	bus_dmamem_free(sc->sc_dmat, &seg, 1);
336 	free(m, mtype, 0);
337 }
338 
339 size_t
bba_round_buffersize(void * v,int direction,size_t size)340 bba_round_buffersize(void *v, int direction, size_t size)
341 {
342 
343 	DPRINTF(("bba_round_buffersize: size=%zu\n", size));
344 	return size > BBA_DMABUF_SIZE ? BBA_DMABUF_SIZE :
345 	    roundup(size, IOASIC_DMA_BLOCKSIZE);
346 }
347 
348 int
bba_halt_output(void * v)349 bba_halt_output(void *v)
350 {
351 	struct bba_softc *sc = v;
352 	struct bba_dma_state *d;
353 	uint32_t ssr;
354 
355 	mtx_enter(&audio_lock);
356 	d = &sc->sc_tx_dma_state;
357 	/* disable any DMA */
358 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
359 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
360 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
361 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, 0);
362 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, 0);
363 	mtx_leave(&audio_lock);
364 
365 	if (d->active) {
366 		bus_dmamap_sync(sc->sc_dmat, d->dmam, 0, d->size,
367 		    BUS_DMASYNC_POSTWRITE);
368 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
369 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
370 		d->active = 0;
371 	}
372 
373 	return 0;
374 }
375 
376 int
bba_halt_input(void * v)377 bba_halt_input(void *v)
378 {
379 	struct bba_softc *sc = v;
380 	struct bba_dma_state *d;
381 	uint32_t ssr;
382 
383 	mtx_enter(&audio_lock);
384 	d = &sc->sc_rx_dma_state;
385 	/* disable any DMA */
386 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
387 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
388 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
389 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, 0);
390 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, 0);
391 	mtx_leave(&audio_lock);
392 
393 	if (d->active) {
394 		bus_dmamap_sync(sc->sc_dmat, d->dmam, 0, d->size,
395 		    BUS_DMASYNC_POSTREAD);
396 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
397 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
398 		d->active = 0;
399 	}
400 
401 	return 0;
402 }
403 
404 int
bba_trigger_output(void * v,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)405 bba_trigger_output(void *v, void *start, void *end, int blksize,
406     void (*intr)(void *), void *arg, struct audio_params *param)
407 {
408 	struct bba_softc *sc = v;
409 	struct bba_dma_state *d;
410 	uint32_t ssr;
411 	tc_addr_t phys, nphys;
412 	int state;
413 
414 	DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
415 	    sc, start, end, blksize, intr, arg));
416 	d = &sc->sc_tx_dma_state;
417 	state = 0;
418 
419 	/* disable any DMA */
420 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
421 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
422 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
423 
424 	d->size = (vaddr_t)end - (vaddr_t)start;
425 	if (bus_dmamap_create(sc->sc_dmat, d->size,
426 	    BBA_MAX_DMA_SEGMENTS, IOASIC_DMA_BLOCKSIZE,
427 	    BBA_DMABUF_BOUNDARY, BUS_DMA_NOWAIT, &d->dmam)) {
428 		printf("bba_trigger_output: can't create DMA map\n");
429 		goto bad;
430 	}
431 	state |= 1;
432 
433 	if (bus_dmamap_load(sc->sc_dmat, d->dmam, start, d->size, NULL,
434 	    BUS_DMA_WRITE | BUS_DMA_NOWAIT)) {
435 		printf("bba_trigger_output: can't load DMA map\n");
436 		goto bad;
437 	}
438 	bus_dmamap_sync(sc->sc_dmat, d->dmam, 0, d->size, BUS_DMASYNC_PREWRITE);
439 	state |= 2;
440 
441 	d->intr = intr;
442 	d->intr_arg = arg;
443 	d->curseg = 1;
444 
445 	/* get physical address of buffer start */
446 	phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr;
447 	nphys = (tc_addr_t)d->dmam->dm_segs[1 % d->dmam->dm_nsegs].ds_addr;
448 
449 	/* setup DMA pointer */
450 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR,
451 	    IOASIC_DMA_ADDR(phys));
452 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR,
453 	    IOASIC_DMA_ADDR(nphys));
454 
455 	/* kick off DMA */
456 	mtx_enter(&audio_lock);
457 	ssr |= IOASIC_CSR_DMAEN_ISDN_T;
458 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
459 
460 	d->active = 1;
461 	mtx_leave(&audio_lock);
462 	return 0;
463 
464 bad:
465 	if (state & 2)
466 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
467 	if (state & 1)
468 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
469 	return 1;
470 }
471 
472 int
bba_trigger_input(void * v,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)473 bba_trigger_input(void *v, void *start, void *end, int blksize,
474     void (*intr)(void *), void *arg, struct audio_params *param)
475 {
476 	struct bba_softc *sc = v;
477 	struct bba_dma_state *d;
478 	uint32_t ssr;
479 	tc_addr_t phys, nphys;
480 	int state;
481 
482 	DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
483 	    sc, start, end, blksize, intr, arg));
484 	d = &sc->sc_rx_dma_state;
485 	state = 0;
486 
487 	/* disable any DMA */
488 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
489 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
490 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
491 
492 	d->size = (vaddr_t)end - (vaddr_t)start;
493 	if (bus_dmamap_create(sc->sc_dmat, d->size,
494 	    BBA_MAX_DMA_SEGMENTS, IOASIC_DMA_BLOCKSIZE,
495 	    BBA_DMABUF_BOUNDARY, BUS_DMA_NOWAIT, &d->dmam)) {
496 		printf("bba_trigger_input: can't create DMA map\n");
497 		goto bad;
498 	}
499 	state |= 1;
500 
501 	if (bus_dmamap_load(sc->sc_dmat, d->dmam, start, d->size, NULL,
502 	    BUS_DMA_READ | BUS_DMA_NOWAIT)) {
503 		printf("bba_trigger_input: can't load DMA map\n");
504 		goto bad;
505 	}
506 	bus_dmamap_sync(sc->sc_dmat, d->dmam, 0, d->size, BUS_DMASYNC_PREREAD);
507 	state |= 2;
508 
509 	d->intr = intr;
510 	d->intr_arg = arg;
511 	d->curseg = 1;
512 
513 	/* get physical address of buffer start */
514 	phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr;
515 	nphys = (tc_addr_t)d->dmam->dm_segs[1 % d->dmam->dm_nsegs].ds_addr;
516 
517 	/* setup DMA pointer */
518 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR,
519 	    IOASIC_DMA_ADDR(phys));
520 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR,
521 	    IOASIC_DMA_ADDR(nphys));
522 
523 	/* kick off DMA */
524 	mtx_enter(&audio_lock);
525 	ssr |= IOASIC_CSR_DMAEN_ISDN_R;
526 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
527 
528 	d->active = 1;
529 	mtx_leave(&audio_lock);
530 	return 0;
531 
532 bad:
533 	if (state & 2)
534 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
535 	if (state & 1)
536 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
537 	return 1;
538 }
539 
540 int
bba_intr(void * v)541 bba_intr(void *v)
542 {
543 	struct bba_softc *sc = v;
544 	struct bba_dma_state *d;
545 	tc_addr_t nphys;
546 	int mask;
547 
548 	mtx_enter(&audio_lock);
549 
550 	mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
551 
552 	if (mask & IOASIC_INTR_ISDN_TXLOAD) {
553 		d = &sc->sc_tx_dma_state;
554 		d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
555 		nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
556 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
557 		    IOASIC_ISDN_X_NEXTPTR, IOASIC_DMA_ADDR(nphys));
558 		if (d->intr != NULL)
559 			(*d->intr)(d->intr_arg);
560 	}
561 	if (mask & IOASIC_INTR_ISDN_RXLOAD) {
562 		d = &sc->sc_rx_dma_state;
563 		d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
564 		nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
565 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
566 		    IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys));
567 		if (d->intr != NULL)
568 			(*d->intr)(d->intr_arg);
569 	}
570 
571 	mtx_leave(&audio_lock);
572 
573 	return 0;
574 }
575 
576 int
bba_round_blocksize(void * v,int blk)577 bba_round_blocksize(void *v, int blk)
578 {
579 	return IOASIC_DMA_BLOCKSIZE;
580 }
581 
582 
583 /* indirect write */
584 void
bba_codec_iwrite(struct am7930_softc * sc,int reg,uint8_t val)585 bba_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val)
586 {
587 	DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%02x, val=%02x\n", sc, reg, val));
588 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
589 	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
590 }
591 
592 
593 void
bba_codec_iwrite16(struct am7930_softc * sc,int reg,uint16_t val)594 bba_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val)
595 {
596 	DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%02x, val=%04x\n", sc, reg, val));
597 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
598 	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
599 	bba_codec_dwrite(sc, AM7930_DREG_DR, val >> 8);
600 }
601 
602 
603 /* indirect read */
604 uint8_t
bba_codec_iread(struct am7930_softc * sc,int reg)605 bba_codec_iread(struct am7930_softc *sc, int reg)
606 {
607 	uint8_t val;
608 
609 	DPRINTF(("bba_codec_iread(): sc=%p, reg=%02x\n", sc, reg));
610 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
611 	val = bba_codec_dread(sc, AM7930_DREG_DR);
612 
613 	DPRINTF(("read 0x%02x (%d)\n", val, val));
614 
615 	return val;
616 }
617 
618 uint16_t
bba_codec_iread16(struct am7930_softc * sc,int reg)619 bba_codec_iread16(struct am7930_softc *sc, int reg)
620 {
621 	uint16_t val;
622 
623 	DPRINTF(("bba_codec_iread16(): sc=%p, reg=%02x\n", sc, reg));
624 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
625 	val = bba_codec_dread(sc, AM7930_DREG_DR);
626 	val |= bba_codec_dread(sc, AM7930_DREG_DR) << 8;
627 
628 	return val;
629 }
630 
631 
632 /* direct write */
633 void
bba_codec_dwrite(struct am7930_softc * asc,int reg,uint8_t val)634 bba_codec_dwrite(struct am7930_softc *asc, int reg, uint8_t val)
635 {
636 	struct bba_softc *sc = (struct bba_softc *)asc;
637 
638 #if defined(__alpha__)
639 	bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, reg << 2, val << 8);
640 #else
641 	bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, reg << 6, val);
642 #endif
643 }
644 
645 /* direct read */
646 uint8_t
bba_codec_dread(struct am7930_softc * asc,int reg)647 bba_codec_dread(struct am7930_softc *asc, int reg)
648 {
649 	struct bba_softc *sc = (struct bba_softc *)asc;
650 
651 #if defined(__alpha__)
652 	return (bus_space_read_4(sc->sc_bst, sc->sc_codec_bsh, reg << 2) >> 8) &
653 	    0xff;
654 #else
655 	return bus_space_read_4(sc->sc_bst, sc->sc_codec_bsh, reg << 6) & 0xff;
656 #endif
657 }
658