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