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