bba.c revision 1.1 1 /* $NetBSD: bba.c,v 1.1 2000/05/02 06:43:05 augustss Exp $ */
2
3 /*
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /* maxine/alpha baseboard audio (bba) */
37
38 #include "audio.h"
39 #if NAUDIO > 0
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46
47 #include <machine/bus.h>
48 #include <machine/autoconf.h>
49 #include <machine/cpu.h>
50
51 #include <vm/vm.h> /* for PAGE_SIZE */
52
53 #include <sys/audioio.h>
54 #include <dev/audio_if.h>
55
56 #include <dev/ic/am7930reg.h>
57 #include <dev/ic/am7930var.h>
58
59 #include <dev/tc/tcvar.h>
60 #include <dev/tc/ioasicreg.h>
61 #include <dev/tc/ioasicvar.h>
62
63 #ifdef pmax
64 #include <pmax/pmax/maxine.h>
65 #define IOASIC_CSR_ISDN_ENABLE XINE_CSR_ISDN_ENABLE
66 #define IOASIC_INTR_ISDN_TXLOAD IOASIC_INTR_ISDN_DS_TXLOAD
67 #define IOASIC_INTR_ISDN_RXLOAD IOASIC_INTR_ISDN_DS_RXLOAD
68 #ifdef IOASIC_INTR_ISDN_OVRUN
69 #undef IOASIC_INTR_ISDN_OVRUN
70 #endif
71 #define IOASIC_INTR_ISDN_OVRUN IOASIC_INTR_ISDN_DS_OVRUN
72 #endif
73
74 #ifdef AUDIO_DEBUG
75 #define DPRINTF(x) if (am7930debug) printf x
76 #else
77 #define DPRINTF(x)
78 #endif /* AUDIO_DEBUG */
79
80 #define BBA_MAX_DMA_SEGMENTS 16
81
82 struct bba_mem {
83 bus_addr_t addr;
84 bus_size_t size;
85 caddr_t kva;
86 struct bba_mem *next;
87 };
88
89 struct bba_dma_state {
90 bus_dmamap_t dmam; /* dma map */
91 int active;
92 int curseg; /* current segment in dma buffer */
93 void (*intr)__P((void *)); /* higher-level audio handler */
94 void *intr_arg;
95 };
96
97 struct bba_softc {
98 struct am7930_softc sc_am7930; /* glue to MI code */
99
100 bus_space_tag_t sc_bst; /* IOASIC bus tag/handle */
101 bus_space_handle_t sc_bsh;
102 bus_dma_tag_t sc_dmat;
103 bus_space_handle_t sc_codec_bsh; /* codec bus space handle */
104
105 struct bba_mem *sc_mem_head; /* list of buffers */
106
107 struct bba_dma_state sc_tx_dma_state;
108 struct bba_dma_state sc_rx_dma_state;
109 };
110
111 int bba_match __P((struct device *, struct cfdata *, void *));
112 void bba_attach __P((struct device *, struct device *, void *));
113
114 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 u_int8_t bba_codec_iread __P((struct am7930_softc *, int));
123 u_int16_t bba_codec_iread16 __P((struct am7930_softc *, int));
124 void bba_codec_iwrite __P((struct am7930_softc *, int, u_int8_t));
125 void bba_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t));
126 void bba_onopen __P((struct am7930_softc *sc));
127 void bba_onclose __P((struct am7930_softc *sc));
128 void bba_output_conv __P((void *, u_int8_t *, int));
129 void bba_input_conv __P((void *, u_int8_t *, int));
130
131 struct am7930_glue bba_glue = {
132 bba_codec_iread,
133 bba_codec_iwrite,
134 bba_codec_iread16,
135 bba_codec_iwrite16,
136 bba_onopen,
137 bba_onclose,
138 4,
139 bba_input_conv,
140 bba_output_conv,
141 };
142
143 /*
144 * Define our interface to the higher level audio driver.
145 */
146
147 int bba_round_blocksize __P((void *, int));
148 int bba_halt_output __P((void *));
149 int bba_halt_input __P((void *));
150 int bba_getdev __P((void *, struct audio_device *));
151 void *bba_allocm __P((void *, int, size_t, int, int));
152 void bba_freem __P((void *, void *, int));
153 size_t bba_round_buffersize __P((void *, int, size_t));
154 int bba_trigger_output __P((void *, void *, void *, int,
155 void (*)(void *), void *, struct audio_params *));
156 int bba_trigger_input __P((void *, void *, void *, int,
157 void (*)(void *), void *, struct audio_params *));
158
159 struct audio_hw_if sa_hw_if = {
160 am7930_open,
161 am7930_close,
162 0,
163 am7930_query_encoding,
164 am7930_set_params,
165 bba_round_blocksize, /* md */
166 am7930_commit_settings,
167 0,
168 0,
169 0,
170 0,
171 bba_halt_output, /* md */
172 bba_halt_input, /* md */
173 0,
174 bba_getdev,
175 0,
176 am7930_set_port,
177 am7930_get_port,
178 am7930_query_devinfo,
179 bba_allocm, /* md */
180 bba_freem, /* md */
181 bba_round_buffersize, /* md */
182 0,
183 am7930_get_props,
184 bba_trigger_output, /* md */
185 bba_trigger_input /* md */
186 };
187
188 struct audio_device bba_device = {
189 "am7930",
190 "x",
191 "bba"
192 };
193
194 int bba_intr __P((void *));
195 void bba_reset __P((struct bba_softc *, int));
196 void bba_codec_dwrite __P((struct am7930_softc *, int, u_int8_t));
197 u_int8_t bba_codec_dread __P((struct am7930_softc *, int));
198
199 int bba_match(parent, cf, aux)
200 struct device *parent;
201 struct cfdata *cf;
202 void *aux;
203 {
204 struct ioasicdev_attach_args *ia = aux;
205
206 if (strcmp(ia->iada_modname, "isdn") != 0 &&
207 strcmp(ia->iada_modname, "AMD79c30") != 0)
208 return 0;
209
210 return 1;
211 }
212
213
214 void
215 bba_attach(parent, self, aux)
216 struct device *parent;
217 struct device *self;
218 void *aux;
219 {
220 struct ioasicdev_attach_args *ia = aux;
221 struct bba_softc *sc = (struct bba_softc *)self;
222 struct am7930_softc *asc = &sc->sc_am7930;
223
224 sc->sc_bst = ((struct ioasic_softc *)parent)->sc_bst;
225 sc->sc_bsh = ((struct ioasic_softc *)parent)->sc_bsh;
226 sc->sc_dmat = ((struct ioasic_softc *)parent)->sc_dmat;
227
228 /* get the bus space handle for codec */
229 if (bus_space_subregion(sc->sc_bst, sc->sc_bsh,
230 ia->iada_offset, 0, &sc->sc_codec_bsh)) {
231 printf("%s: unable to map device\n", asc->sc_dev.dv_xname);
232 return;
233 }
234
235 printf("\n");
236
237 bba_reset(sc,1);
238
239 /*
240 * Set up glue for MI code early; we use some of it here.
241 */
242 asc->sc_glue = &bba_glue;
243
244 /*
245 * MI initialisation. We will be doing DMA.
246 */
247 am7930_init(asc, AUDIOAMD_DMA_MODE);
248
249 ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE,
250 bba_intr, sc);
251
252 audio_attach_mi(&sa_hw_if, asc, &asc->sc_dev);
253 }
254
255
256 void
257 bba_onopen(sc)
258 struct am7930_softc *sc;
259 {
260 bba_reset((struct bba_softc *)sc, 0);
261 }
262
263
264 void
265 bba_onclose(sc)
266 struct am7930_softc *sc;
267 {
268 bba_halt_input((struct bba_softc *)sc);
269 bba_halt_output((struct bba_softc *)sc);
270 }
271
272
273 void
274 bba_reset(sc, reset)
275 struct bba_softc *sc;
276 int reset;
277 {
278 u_int32_t ssr;
279
280 /* disable any DMA and reset the codec */
281 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
282 ssr &= ~(IOASIC_CSR_DMAEN_ISDN_T | IOASIC_CSR_DMAEN_ISDN_R);
283 if (reset)
284 ssr &= ~IOASIC_CSR_ISDN_ENABLE;
285 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
286 DELAY(10); /* 400ns required for codec to reset */
287
288 /* initialise DMA pointers */
289 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
290 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
291 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
292 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
293
294 /* take out of reset state */
295 if (reset) {
296 ssr |= IOASIC_CSR_ISDN_ENABLE;
297 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
298 }
299
300 }
301
302
303 void *
304 bba_allocm(addr, direction, size, pool, flags)
305 void *addr;
306 int direction;
307 size_t size;
308 int pool, flags;
309 {
310 struct am7930_softc *asc = addr;
311 struct bba_softc *sc = addr;
312 bus_dma_segment_t seg;
313 int rseg;
314 caddr_t kva;
315 struct bba_mem *m;
316 int state = 0;
317
318 DPRINTF(("bba_allocm: size = %d\n",size));
319
320 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg,
321 1, &rseg, BUS_DMA_NOWAIT)) {
322 printf("%s: can't allocate DMA buffer\n",
323 asc->sc_dev.dv_xname);
324 goto bad;
325 }
326 state |= 1;
327
328 if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
329 &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
330 printf("%s: can't map DMA buffer\n", asc->sc_dev.dv_xname);
331 goto bad;
332 }
333 state |= 2;
334
335 m = malloc(sizeof(struct bba_mem), pool, flags);
336 if (m == NULL)
337 goto bad;
338 m->addr = seg.ds_addr;
339 m->size = seg.ds_len;
340 m->kva = kva;
341 m->next = sc->sc_mem_head;
342 sc->sc_mem_head = m;
343
344 return (void *)kva;
345
346 bad:
347 if (state & 2)
348 bus_dmamem_unmap(sc->sc_dmat, kva, size);
349 if (state & 1)
350 bus_dmamem_free(sc->sc_dmat, &seg, 1);
351 return NULL;
352 }
353
354
355 void
356 bba_freem(addr, ptr, pool)
357 void *addr;
358 void *ptr;
359 int pool;
360 {
361 struct bba_softc *sc = addr;
362 struct bba_mem **mp, *m;
363 bus_dma_segment_t seg;
364 caddr_t kva = (caddr_t)addr;
365
366 for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva;
367 mp = &(*mp)->next)
368 /* nothing */ ;
369 m = *mp;
370 if (m != NULL) {
371 printf("bba_freem: freeing unallocted memory\n");
372 return;
373 }
374 *mp = m->next;
375 bus_dmamem_unmap(sc->sc_dmat, kva, m->size);
376
377 seg.ds_addr = m->addr;
378 seg.ds_len = m->size;
379 bus_dmamem_free(sc->sc_dmat, &seg, 1);
380 free(m, pool);
381 }
382
383
384 size_t
385 bba_round_buffersize(addr, direction, size)
386 void *addr;
387 int direction;
388 size_t size;
389 {
390 DPRINTF(("bba_round_buffersize: size=%d\n", size));
391
392 #define BBA_BUFFERSIZE (BBA_MAX_DMA_SEGMENTS * PAGE_SIZE)
393 return (size > BBA_BUFFERSIZE ? BBA_BUFFERSIZE : round_page(size));
394 }
395
396
397 int
398 bba_halt_output(addr)
399 void *addr;
400 {
401 struct bba_softc *sc = addr;
402 struct bba_dma_state *d = &sc->sc_tx_dma_state;
403 u_int32_t ssr;
404
405 /* disable any DMA */
406 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
407 ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
408 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
409 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
410 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
411
412 if (d->active) {
413 bus_dmamap_unload(sc->sc_dmat, d->dmam);
414 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
415 d->active = 0;
416 }
417
418 return 0;
419 }
420
421
422 int
423 bba_halt_input(addr)
424 void *addr;
425 {
426 struct bba_softc *sc = addr;
427 struct bba_dma_state *d = &sc->sc_rx_dma_state;
428 u_int32_t ssr;
429
430 /* disable any DMA */
431 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
432 ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
433 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
434 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
435 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
436
437 if (d->active) {
438 bus_dmamap_unload(sc->sc_dmat, d->dmam);
439 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
440 d->active = 0;
441 }
442
443 return 0;
444 }
445
446
447 int
448 bba_getdev(addr, retp)
449 void *addr;
450 struct audio_device *retp;
451 {
452 *retp = bba_device;
453 return 0;
454 }
455
456
457 int
458 bba_trigger_output(addr, start, end, blksize, intr, arg, param)
459 void *addr;
460 void *start, *end;
461 int blksize;
462 void (*intr) __P((void *));
463 void *arg;
464 struct audio_params *param;
465 {
466 struct bba_softc *sc = addr;
467 struct bba_dma_state *d = &sc->sc_tx_dma_state;
468 u_int32_t ssr;
469 tc_addr_t phys, nphys;
470 int state = 0;
471
472 DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
473 addr, start, end, blksize, intr, arg));
474
475 if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
476 BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &d->dmam)) {
477 printf("bba_trigger_output: can't create DMA map\n");
478 goto bad;
479 }
480 state |= 1;
481
482 if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
483 (char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) {
484 printf("bba_trigger_output: can't load DMA map\n");
485 goto bad;
486 }
487 state |= 2;
488
489 /* disable any DMA */
490 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
491 ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
492 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
493
494 d->intr = intr;
495 d->intr_arg = arg;
496 d->curseg = 1;
497
498 /* get physical address of buffer start */
499 phys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
500 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg+1].ds_addr;
501
502 /* setup DMA pointer */
503 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR,
504 IOASIC_DMA_ADDR(phys));
505 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR,
506 IOASIC_DMA_ADDR(nphys));
507
508 /* kick off DMA */
509 ssr |= IOASIC_CSR_DMAEN_ISDN_T;
510 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
511
512 wbflush();
513
514 d->active = 1;
515
516 return 0;
517
518 bad:
519 if (state & 2)
520 bus_dmamap_unload(sc->sc_dmat, d->dmam);
521 if (state & 1)
522 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
523 return 1;
524 }
525
526
527 int
528 bba_trigger_input(addr, start, end, blksize, intr, arg, param)
529 void *addr;
530 void *start, *end;
531 int blksize;
532 void (*intr) __P((void *));
533 void *arg;
534 struct audio_params *param;
535 {
536 struct bba_softc *sc = (struct bba_softc *)addr;
537 struct bba_dma_state *d = &sc->sc_rx_dma_state;
538 tc_addr_t phys, nphys;
539 u_int32_t ssr;
540 int state = 0;
541
542 DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
543 addr, start, end, blksize, intr, arg));
544
545 if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
546 BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &d->dmam)) {
547 printf("bba_trigger_input: can't create DMA map\n");
548 goto bad;
549 }
550 state |= 1;
551
552 if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
553 (char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) {
554 printf("bba_trigger_input: can't load DMA map\n");
555 goto bad;
556 }
557 state |= 2;
558
559 /* disable any DMA */
560 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
561 ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
562 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
563
564 d->intr = intr;
565 d->intr_arg = arg;
566 d->curseg = 1;
567
568 /* get physical address of buffer start */
569 phys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
570 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg+1].ds_addr;
571
572 /* setup DMA pointer */
573 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR,
574 IOASIC_DMA_ADDR(phys));
575 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR,
576 IOASIC_DMA_ADDR(nphys));
577
578 /* kick off DMA */
579 ssr |= IOASIC_CSR_DMAEN_ISDN_R;
580 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
581
582 wbflush();
583
584 d->active = 1;
585
586 return 0;
587
588 bad:
589 if (state & 2)
590 bus_dmamap_unload(sc->sc_dmat, d->dmam);
591 if (state & 1)
592 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
593 return 1;
594 }
595
596 int
597 bba_intr(addr)
598 void *addr;
599 {
600 struct bba_softc *sc = addr;
601 struct bba_dma_state *d;
602 tc_addr_t nphys;
603 int s, mask;
604
605 s = splaudio();
606
607 mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
608
609 if (mask & IOASIC_INTR_ISDN_TXLOAD) {
610 d = &sc->sc_tx_dma_state;
611 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
612 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
613 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
614 IOASIC_ISDN_X_NEXTPTR, IOASIC_DMA_ADDR(nphys));
615 if (d->intr != NULL)
616 (*d->intr)(d->intr_arg);
617 }
618 if (mask & IOASIC_INTR_ISDN_RXLOAD) {
619 d = &sc->sc_rx_dma_state;
620 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
621 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
622 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
623 IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys));
624 if (d->intr != NULL)
625 (*d->intr)(d->intr_arg);
626 }
627
628 splx(s);
629
630 return 0;
631 }
632
633
634 void
635 bba_input_conv(v, p, cc)
636 void *v;
637 u_int8_t *p;
638 int cc;
639 {
640 u_int8_t *q = p;
641
642 DPRINTF(("bba_input_conv(): v=%p p=%p cc=%d\n", v, p, cc));
643
644 /*
645 * p points start of buffer
646 * cc is the number of bytes in the destination buffer
647 */
648
649 while (--cc >= 0) {
650 *p = ((*(u_int32_t *)q)>>16)&0xff;
651 q += 4;
652 p++;
653 }
654 }
655
656
657 void
658 bba_output_conv(v, p, cc)
659 void *v;
660 u_int8_t *p;
661 int cc;
662 {
663 u_int8_t *q = p;
664
665 DPRINTF(("bba_output_conv(): v=%p p=%p cc=%d\n", v, p, cc));
666
667 /*
668 * p points start of buffer
669 * cc is the number of bytes in the source buffer
670 */
671
672 p += cc;
673 q += cc * 4;
674 while (--cc >= 0) {
675 q -= 4;
676 p -= 1;
677 *(u_int32_t *)q = (*p<<16);
678 }
679 }
680
681
682 int
683 bba_round_blocksize(addr, blk)
684 void *addr;
685 int blk;
686 {
687 return (PAGE_SIZE);
688 }
689
690
691 /* indirect write */
692 void
693 bba_codec_iwrite(sc, reg, val)
694 struct am7930_softc *sc;
695 int reg;
696 u_int8_t val;
697 {
698 DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
699
700 bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
701 bba_codec_dwrite(sc, AM7930_DREG_DR, val);
702 }
703
704
705 void
706 bba_codec_iwrite16(sc, reg, val)
707 struct am7930_softc *sc;
708 int reg;
709 u_int16_t val;
710 {
711 DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
712
713 bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
714 #if 0
715 bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
716 bba_codec_dwrite(sc, AM7930_DREG_DR, val);
717 #else
718 bba_codec_dwrite(sc, AM7930_DREG_DR, val);
719 bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
720 #endif
721 }
722
723
724 u_int16_t
725 bba_codec_iread16(sc, reg)
726 struct am7930_softc *sc;
727 int reg;
728 {
729 u_int16_t val;
730 DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n",sc,reg));
731
732 bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
733 #if 0
734 bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
735 bba_codec_dwrite(sc, AM7930_DREG_DR, val);
736 #else
737 val = bba_codec_dread(sc, AM7930_DREG_DR) << 8;
738 val |= bba_codec_dread(sc, AM7930_DREG_DR);
739 #endif
740
741 return val;
742 }
743
744
745 /* indirect read */
746 u_int8_t
747 bba_codec_iread(sc, reg)
748 struct am7930_softc *sc;
749 int reg;
750 {
751 u_int8_t val;
752
753 DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n",sc,reg));
754
755 bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
756 val = bba_codec_dread(sc, AM7930_DREG_DR);
757
758 DPRINTF(("read 0x%x (%d)\n", val, val));
759
760 return val;
761 }
762
763
764 #define TIMETOWASTE 50
765
766 /* direct write */
767 void
768 bba_codec_dwrite(asc, reg, val)
769 struct am7930_softc *asc;
770 int reg;
771 u_int8_t val;
772 {
773 struct bba_softc *sc = (struct bba_softc *)asc;
774 int i;
775
776 DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
777
778 bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, (reg<<6), val);
779
780 for (i=0; i<TIMETOWASTE; i++) {};
781 }
782
783 /* direct read */
784 u_int8_t
785 bba_codec_dread(asc, reg)
786 struct am7930_softc *asc;
787 int reg;
788 {
789 struct bba_softc *sc = (struct bba_softc *)asc;
790 u_int8_t val;
791 int i;
792
793 DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n",sc,reg));
794
795 val = bus_space_read_1(sc->sc_bst, sc->sc_codec_bsh, (reg<<6));
796
797 for (i=0; i<TIMETOWASTE; i++) {};
798
799 return val;
800 }
801
802 #endif /* NAUDIO > 0 */
803