dbri.c revision 1.11 1 /* $NetBSD: dbri.c,v 1.11 2007/03/11 00:36:57 macallan Exp $ */
2
3 /*
4 * Copyright (C) 1997 Rudolf Koenig (rfkoenig (at) immd4.informatik.uni-erlangen.de)
5 * Copyright (c) 1998, 1999 Brent Baccala (baccala (at) freesoft.org)
6 * Copyright (c) 2001, 2002 Jared D. McNeill <jmcneill (at) netbsd.org>
7 * Copyright (c) 2005 Michael Lorenz <macallan (at) netbsd.org>
8 * All rights reserved.
9 *
10 * This driver is losely based on a Linux driver written by Rudolf Koenig and
11 * Brent Baccala who kindly gave their permission to use their code in a
12 * BSD-licensed driver.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Rudolf Koenig, Brent
25 * Baccala, Jared D. McNeill.
26 * 4. Neither the name of the author nor the names of any contributors may
27 * be used to endorse or promote products derived from this software
28 * without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: dbri.c,v 1.11 2007/03/11 00:36:57 macallan Exp $");
46
47 #include "audio.h"
48 #if NAUDIO > 0
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/errno.h>
53 #include <sys/device.h>
54 #include <sys/malloc.h>
55 #include <sys/proc.h>
56
57 #include <machine/bus.h>
58 #include <machine/intr.h>
59
60 #include <dev/sbus/sbusvar.h>
61 #include <sparc/sparc/auxreg.h>
62 #include <machine/autoconf.h>
63
64 #include <sys/audioio.h>
65 #include <dev/audio_if.h>
66 #include <dev/auconv.h>
67
68 #include <dev/ic/cs4215reg.h>
69 #include <dev/ic/cs4215var.h>
70 #include <dev/sbus/dbrireg.h>
71 #include <dev/sbus/dbrivar.h>
72
73 #include "opt_sbus_dbri.h"
74
75 #define DBRI_ROM_NAME_PREFIX "SUNW,DBRI"
76
77 #ifdef DBRI_DEBUG
78 # define DPRINTF aprint_normal
79 #else
80 # define DPRINTF while (0) printf
81 #endif
82
83 static const char *dbri_supported[] = {
84 "e",
85 "s3",
86 ""
87 };
88
89 enum ms {
90 CHImaster,
91 CHIslave
92 };
93
94 enum io {
95 PIPEinput,
96 PIPEoutput
97 };
98
99 /*
100 * Function prototypes
101 */
102
103 /* softc stuff */
104 static void dbri_attach_sbus(struct device *, struct device *, void *);
105 static int dbri_match_sbus(struct device *, struct cfdata *, void *);
106
107 static void dbri_config_interrupts(struct device *);
108
109 /* interrupt handler */
110 static int dbri_intr(void *);
111
112 /* supporting subroutines */
113 static int dbri_init(struct dbri_softc *);
114 static int dbri_reset(struct dbri_softc *);
115 static volatile u_int32_t *dbri_command_lock(struct dbri_softc *);
116 static void dbri_command_send(struct dbri_softc *, volatile u_int32_t *);
117 static void dbri_process_interrupt_buffer(struct dbri_softc *);
118 static void dbri_process_interrupt(struct dbri_softc *, int32_t);
119
120 /* mmcodec subroutines */
121 static int mmcodec_init(struct dbri_softc *);
122 static void mmcodec_init_data(struct dbri_softc *);
123 static void mmcodec_pipe_init(struct dbri_softc *);
124 static void mmcodec_default(struct dbri_softc *);
125 static void mmcodec_setgain(struct dbri_softc *, int);
126 static int mmcodec_setcontrol(struct dbri_softc *);
127
128 /* chi subroutines */
129 static void chi_reset(struct dbri_softc *, enum ms, int);
130
131 /* pipe subroutines */
132 static void pipe_setup(struct dbri_softc *, int, int);
133 static void pipe_reset(struct dbri_softc *, int);
134 static void pipe_receive_fixed(struct dbri_softc *, int,
135 volatile u_int32_t *);
136 static void pipe_transmit_fixed(struct dbri_softc *, int, u_int32_t);
137
138 static void pipe_ts_link(struct dbri_softc *, int, enum io, int, int, int);
139 static int pipe_active(struct dbri_softc *, int);
140
141 /* audio(9) stuff */
142 static int dbri_query_encoding(void *, struct audio_encoding *);
143 static int dbri_set_params(void *, int, int, struct audio_params *,
144 struct audio_params *,stream_filter_list_t *, stream_filter_list_t *);
145 static int dbri_round_blocksize(void *, int, int, const audio_params_t *);
146 static int dbri_halt_output(void *);
147 static int dbri_getdev(void *, struct audio_device *);
148 static int dbri_set_port(void *, mixer_ctrl_t *);
149 static int dbri_get_port(void *, mixer_ctrl_t *);
150 static int dbri_query_devinfo(void *, mixer_devinfo_t *);
151 static size_t dbri_round_buffersize(void *, int, size_t);
152 static int dbri_get_props(void *);
153 static int dbri_open(void *, int);
154 static void dbri_close(void *);
155
156 static void setup_ring(struct dbri_softc *, int, int, int, int,
157 void (*)(void *), void *);
158
159 static int dbri_trigger_output(void *, void *, void *, int,
160 void (*)(void *), void *, const struct audio_params *);
161
162 static void *dbri_malloc(void *, int, size_t, struct malloc_type *, int);
163 static void dbri_free(void *, void *, struct malloc_type *);
164 static paddr_t dbri_mappage(void *, void *, off_t, int);
165 static void dbri_set_power(struct dbri_softc *, int);
166 static void dbri_bring_up(struct dbri_softc *);
167 static void dbri_powerhook(int, void *);
168
169 /* stupid support routines */
170 static u_int32_t reverse_bytes(u_int32_t, int);
171
172 struct audio_device dbri_device = {
173 "CS4215",
174 "",
175 "dbri"
176 };
177
178 struct audio_hw_if dbri_hw_if = {
179 dbri_open,
180 dbri_close,
181 NULL, /* drain */
182 dbri_query_encoding,
183 dbri_set_params,
184 dbri_round_blocksize,
185 NULL, /* commit_settings */
186 NULL, /* init_output */
187 NULL, /* init_input */
188 NULL, /* start_output */
189 NULL, /* start_input */
190 dbri_halt_output,
191 NULL, /* halt_input */
192 NULL, /* speaker_ctl */
193 dbri_getdev,
194 NULL, /* setfd */
195 dbri_set_port,
196 dbri_get_port,
197 dbri_query_devinfo,
198 dbri_malloc,
199 dbri_free,
200 dbri_round_buffersize,
201 dbri_mappage,
202 dbri_get_props,
203 dbri_trigger_output,
204 NULL /* trigger_input */
205 };
206
207 CFATTACH_DECL(dbri, sizeof(struct dbri_softc),
208 dbri_match_sbus, dbri_attach_sbus, NULL, NULL);
209
210 #define DBRI_NFORMATS 7
211 static const struct audio_format dbri_formats[DBRI_NFORMATS] = {
212 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_BE, 16, 16,
213 2, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
214 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULAW, 8, 8,
215 2, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
216 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ALAW, 8, 8,
217 2, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
218 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR, 8, 8,
219 2, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
220 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULAW, 8, 8,
221 1, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
222 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ALAW, 8, 8,
223 1, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
224 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_ULINEAR, 8, 8,
225 1, AUFMT_STEREO, 8, {8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000}},
226 };
227
228 enum {
229 DBRI_MONITOR_CLASS,
230 DBRI_VOL_OUTPUT,
231 DBRI_ENABLE_MONO,
232 DBRI_ENABLE_HEADPHONE,
233 DBRI_ENABLE_LINE
234 /*
235 DBRI_INPUT_CLASS,
236 DBRI_RECORD_CLASS,
237 DBRI_INPUT_GAIN,
238 DBRI_INPUT_SELECT,
239 DBRI_ENUM_LAST
240 */
241 };
242
243 /*
244 * Autoconfig routines
245 */
246 static int
247 dbri_match_sbus(struct device *parent, struct cfdata *match, void *aux)
248 {
249 struct sbus_attach_args *sa = aux;
250 char *ver;
251 int i;
252
253 if (strncmp(DBRI_ROM_NAME_PREFIX, sa->sa_name, 9))
254 return (0);
255
256 ver = &sa->sa_name[9];
257
258 for (i = 0; dbri_supported[i][0] != '\0'; i++)
259 if (strcmp(dbri_supported[i], ver) == 0)
260 return (1);
261
262 return (0);
263 }
264
265 static void
266 dbri_attach_sbus(struct device *parent, struct device *self, void *aux)
267 {
268 struct dbri_softc *sc = (struct dbri_softc *)self;
269 struct sbus_attach_args *sa = aux;
270 bus_space_handle_t ioh;
271 bus_size_t size;
272 int error, rseg, pwr;
273 char *ver = &sa->sa_name[9];
274
275 sc->sc_iot = sa->sa_bustag;
276 sc->sc_dmat = sa->sa_dmatag;
277 sc->sc_powerstate = PWR_RESUME;
278
279 pwr = prom_getpropint(sa->sa_node,"pwr-on-auxio",0);
280 printf(": rev %s\n", ver);
281
282 if(pwr) {
283 /*
284 * we can control DBRI power via auxio and we're initially
285 * powered down
286 */
287
288 sc->sc_have_powerctl = 1;
289 sc->sc_powerstate = 0;
290 dbri_set_power(sc, 1);
291 powerhook_establish(self->dv_xname, dbri_powerhook, sc);
292 } else {
293 /* we can't control power so we're always up */
294 sc->sc_have_powerctl = 0;
295 sc->sc_powerstate = 1;
296 }
297
298 if (sa->sa_npromvaddrs)
299 ioh = (bus_space_handle_t)sa->sa_promvaddrs[0];
300 else {
301 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
302 sa->sa_offset, sa->sa_size,
303 BUS_SPACE_MAP_LINEAR, /*0,*/ &ioh) != 0) {
304 aprint_error("%s @ sbus: cannot map registers\n",
305 self->dv_xname);
306 return;
307 }
308 }
309
310 sc->sc_ioh = ioh;
311
312 size = sizeof(struct dbri_dma);
313
314 /* get a DMA handle */
315 if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
316 BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
317 aprint_error("%s: DMA map create error %d\n", self->dv_xname, error);
318 return;
319 }
320
321 /* allocate DMA buffer */
322 if ((error = bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_dmaseg,
323 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
324 aprint_error("%s: DMA buffer alloc error %d\n",
325 self->dv_xname, error);
326 return;
327 }
328
329 /* map DMA buffer into CPU addressable space */
330 if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dmaseg, rseg, size,
331 &sc->sc_membase,
332 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
333 aprint_error("%s: DMA buffer map error %d\n",
334 self->dv_xname, error);
335 return;
336 }
337
338 /* load the buffer */
339 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
340 sc->sc_membase, size, NULL,
341 BUS_DMA_NOWAIT)) != 0) {
342 aprint_error("%s: DMA buffer map load error %d\n",
343 self->dv_xname, error);
344 bus_dmamem_unmap(sc->sc_dmat, sc->sc_membase, size);
345 bus_dmamem_free(sc->sc_dmat, &sc->sc_dmaseg, rseg);
346 return;
347 }
348
349 /* map the registers into memory */
350
351 /* kernel virtual address of DMA buffer */
352 sc->sc_dma = (struct dbri_dma *)sc->sc_membase;
353 /* physical address of DMA buffer */
354 sc->sc_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;
355 sc->sc_bufsiz = size;
356
357 sbus_establish(&sc->sc_sd, &sc->sc_dev);
358
359 bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, /*0,*/
360 dbri_intr, sc);
361
362 sc->sc_locked = 0;
363 sc->sc_desc_used = 0;
364
365 config_interrupts(self, &dbri_config_interrupts);
366
367 return;
368 }
369
370 /*
371 * lowlevel routine to switch power for the DBRI chip
372 */
373 static void
374 dbri_set_power(struct dbri_softc *sc, int state)
375 {
376 int s;
377
378 if (sc->sc_have_powerctl == 0)
379 return;
380 if (sc->sc_powerstate == state)
381 return;
382
383 if (state) {
384 DPRINTF("%s: waiting to power up... ", sc->sc_dev.dv_xname);
385 s = splhigh();
386 *AUXIO4M_REG |= (AUXIO4M_MMX);
387 splx(s);
388 delay(10000);
389 DPRINTF("done (%02x})\n", *AUXIO4M_REG);
390 } else {
391 DPRINTF("%s: powering down\n", sc->sc_dev.dv_xname);
392 s = splhigh();
393 *AUXIO4M_REG &= ~AUXIO4M_MMX;
394 splx(s);
395 DPRINTF("done (%02x})\n", *AUXIO4M_REG);
396 }
397 sc->sc_powerstate = state;
398 }
399
400 /*
401 * power up and re-initialize the chip
402 */
403 static void
404 dbri_bring_up(struct dbri_softc *sc)
405 {
406
407 if (sc->sc_have_powerctl == 0)
408 return;
409 if (sc->sc_powerstate == 1)
410 return;
411
412 /* ok, we really need to do something */
413 dbri_set_power(sc, 1);
414
415 /*
416 * re-initialize the chip but skip all the probing, don't overwrite
417 * any other settings either
418 */
419 dbri_init(sc);
420 mmcodec_setgain(sc, 1);
421 mmcodec_pipe_init(sc);
422 mmcodec_init_data(sc);
423 mmcodec_setgain(sc, 0);
424 }
425
426 static void
427 dbri_config_interrupts(struct device *dev)
428 {
429 struct dbri_softc *sc = (struct dbri_softc *)dev;
430
431 dbri_init(sc);
432 mmcodec_init(sc);
433
434 /* Attach ourselves to the high level audio interface */
435 audio_attach_mi(&dbri_hw_if, sc, &sc->sc_dev);
436
437 /* power down until open() */
438 dbri_set_power(sc, 0);
439 return;
440 }
441
442 static int
443 dbri_intr(void *hdl)
444 {
445 struct dbri_softc *sc = hdl;
446 bus_space_tag_t iot = sc->sc_iot;
447 bus_space_handle_t ioh = sc->sc_ioh;
448 int x;
449
450 /* clear interrupt */
451 x = bus_space_read_4(iot, ioh, DBRI_REG1);
452 if (x & (DBRI_MRR | DBRI_MLE | DBRI_LBG | DBRI_MBE)) {
453 u_int32_t tmp;
454
455 if (x & DBRI_MRR)
456 aprint_debug("%s: multiple ack error on sbus\n",
457 sc->sc_dev.dv_xname);
458 if (x & DBRI_MLE)
459 aprint_debug("%s: multiple late error on sbus\n",
460 sc->sc_dev.dv_xname);
461 if (x & DBRI_LBG)
462 aprint_debug("%s: lost bus grant on sbus\n",
463 sc->sc_dev.dv_xname);
464 if (x & DBRI_MBE)
465 aprint_debug("%s: burst error on sbus\n",
466 sc->sc_dev.dv_xname);
467
468 /*
469 * Some of these errors disable the chip's circuitry.
470 * Re-enable the circuitry and keep on going.
471 */
472
473 tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
474 tmp &= ~(DBRI_DISABLE_MASTER);
475 bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
476 }
477
478 #if 0
479 if (!x & 1) /* XXX: DBRI_INTR_REQ */
480 return (1);
481 #endif
482
483 dbri_process_interrupt_buffer(sc);
484
485 return (1);
486 }
487
488 static int
489 dbri_init(struct dbri_softc *sc)
490 {
491 bus_space_tag_t iot = sc->sc_iot;
492 bus_space_handle_t ioh = sc->sc_ioh;
493 u_int32_t reg;
494 volatile u_int32_t *cmd;
495 bus_addr_t dmaaddr;
496 int n;
497
498 dbri_reset(sc);
499
500 cmd = dbri_command_lock(sc);
501
502 /* XXX: Initialize interrupt ring buffer */
503 sc->sc_dma->intr[0] = (u_int32_t)sc->sc_dmabase + dbri_dma_off(intr, 0);
504 sc->sc_irqp = 1;
505
506 /* Initialize pipes */
507 for (n = 0; n < DBRI_PIPE_MAX; n++)
508 sc->sc_pipe[n].desc = sc->sc_pipe[n].next = -1;
509
510 for(n=1;n<DBRI_INT_BLOCKS;n++) {
511 sc->sc_dma->intr[n]=0;
512 }
513
514 /* Disable all SBus bursts */
515 /* XXX 16 byte bursts cause errors, the rest works */
516 reg = bus_space_read_4(iot, ioh, DBRI_REG0);
517
518 /*reg &= ~(DBRI_BURST_4 | DBRI_BURST_8 | DBRI_BURST_16);*/
519 reg |= (DBRI_BURST_4 | DBRI_BURST_8);
520 bus_space_write_4(iot, ioh, DBRI_REG0, reg);
521
522 /* setup interrupt queue */
523 dmaaddr = (u_int32_t)sc->sc_dmabase + dbri_dma_off(intr, 0);
524 *(cmd++) = DBRI_CMD(DBRI_COMMAND_IIQ, 0, 0);
525 *(cmd++) = dmaaddr;
526
527 dbri_command_send(sc, cmd);
528 return (0);
529 }
530
531 static int
532 dbri_reset(struct dbri_softc *sc)
533 {
534 int bail=0;
535 bus_space_tag_t iot = sc->sc_iot;
536 bus_space_handle_t ioh = sc->sc_ioh;
537
538 bus_space_write_4(iot, ioh, DBRI_REG0, DBRI_SOFT_RESET);
539 while ((bus_space_read_4(iot, ioh, DBRI_REG0) & DBRI_SOFT_RESET) &&
540 (bail < 100000)) {
541 bail++;
542 delay(10);
543 }
544 if (bail == 100000) aprint_error("%s: reset timed out\n",
545 sc->sc_dev.dv_xname);
546 return (0);
547 }
548
549 static volatile u_int32_t *
550 dbri_command_lock(struct dbri_softc *sc)
551 {
552
553 if (sc->sc_locked)
554 aprint_debug("%s: command buffer locked\n", sc->sc_dev.dv_xname);
555
556 sc->sc_locked++;
557
558 return (&sc->sc_dma->command[0]);
559 }
560
561 static void
562 dbri_command_send(struct dbri_softc *sc, volatile u_int32_t *cmd)
563 {
564 bus_space_handle_t ioh = sc->sc_ioh;
565 bus_space_tag_t iot = sc->sc_iot;
566 int maxloops = 1000000;
567 int x;
568
569 x = splaudio();
570 //x = splhigh();
571
572 sc->sc_locked--;
573
574 if (sc->sc_locked != 0) {
575 aprint_error("%s: command buffer improperly locked\n",
576 sc->sc_dev.dv_xname);
577 } else if ((cmd - &sc->sc_dma->command[0]) >= DBRI_NUM_COMMANDS - 1) {
578 aprint_error("%s: command buffer overflow\n", sc->sc_dev.dv_xname);
579 } else {
580 *(cmd++) = DBRI_CMD(DBRI_COMMAND_PAUSE, 0, 0);
581 *(cmd++) = DBRI_CMD(DBRI_COMMAND_WAIT, 1, 0);
582 sc->sc_waitseen = 0;
583 bus_space_write_4(iot, ioh, DBRI_REG8, sc->sc_dmabase);
584 while ((--maxloops) > 0 &&
585 (bus_space_read_4(iot, ioh, DBRI_REG0)
586 & DBRI_COMMAND_VALID)) {
587 bus_space_barrier(iot, ioh, DBRI_REG0, 4,
588 BUS_SPACE_BARRIER_READ);
589 delay(1000);
590 }
591
592 if (maxloops == 0) {
593 aprint_error("%s: chip never completed command buffer\n",
594 sc->sc_dev.dv_xname);
595 } else {
596
597 DPRINTF("%s: command completed\n",
598 sc->sc_dev.dv_xname);
599
600 while ((--maxloops) > 0 && (!sc->sc_waitseen))
601 dbri_process_interrupt_buffer(sc);
602 if (maxloops == 0) {
603 aprint_error("%s: chip never acked WAIT\n",
604 sc->sc_dev.dv_xname);
605 }
606 }
607 }
608
609 splx(x);
610
611 return;
612 }
613
614 static void
615 dbri_process_interrupt_buffer(struct dbri_softc *sc)
616 {
617 int32_t i;
618
619 while ((i = sc->sc_dma->intr[sc->sc_irqp]) != 0) {
620 sc->sc_dma->intr[sc->sc_irqp] = 0;
621 sc->sc_irqp++;
622
623 if (sc->sc_irqp == DBRI_INT_BLOCKS)
624 sc->sc_irqp = 1;
625 else if ((sc->sc_irqp & (DBRI_INT_BLOCKS - 1)) == 0)
626 sc->sc_irqp++;
627
628 dbri_process_interrupt(sc, i);
629 }
630
631 return;
632 }
633
634 static void
635 dbri_process_interrupt(struct dbri_softc *sc, int32_t i)
636 {
637 #if 0
638 const int liu_states[] = { 1, 0, 8, 3, 4, 5, 6, 7 };
639 #endif
640 int val = DBRI_INTR_GETVAL(i);
641 int channel = DBRI_INTR_GETCHAN(i);
642 int command = DBRI_INTR_GETCMD(i);
643 int code = DBRI_INTR_GETCODE(i);
644 #if 0
645 int rval = DBRI_INTR_GETRVAL(i);
646 #endif
647 if (channel == DBRI_INTR_CMD && command == DBRI_COMMAND_WAIT)
648 sc->sc_waitseen++;
649
650 switch (code) {
651 case DBRI_INTR_XCMP: /* transmission complete */
652 {
653 int td;
654 struct dbri_desc *dd;
655
656 td = sc->sc_pipe[channel].desc;
657 dd = &sc->sc_desc[td];
658
659 if (dd->callback != NULL)
660 dd->callback(dd->callback_args);
661 break;
662 }
663 case DBRI_INTR_FXDT: /* fixed data change */
664 DPRINTF("dbri_intr: Fixed data change (%d: %x)\n", channel,
665 val);
666
667 if (sc->sc_pipe[channel].sdp & DBRI_SDP_MSB)
668 val = reverse_bytes(val, sc->sc_pipe[channel].length);
669 if (sc->sc_pipe[channel].prec)
670 *(sc->sc_pipe[channel].prec) = val;
671 DPRINTF("%s: wakeup %p\n", sc->sc_dev.dv_xname, sc);
672 #if 0
673 wakeup(sc);
674 #endif
675 break;
676 case DBRI_INTR_SBRI:
677 DPRINTF("dbri_intr: SBRI\n");
678 break;
679 case DBRI_INTR_BRDY:
680 {
681 /* XXX no input (yet) */
682 #if 0
683 int rd = sc->sc_pipe[channel].desc;
684 u_int32_t status;
685
686 DPRINTF("dbri_intr: BRDY\n");
687 if (rd < 0 || rd >= DBRI_NUM_DESCRIPTORS) {
688 printf("%s: invalid rd on pipe\n", sc->sc_dev.dv_xname);
689 break;
690 }
691
692 sc->sc_desc[rd].busy = 0;
693 sc->sc_pipe[channel].desc = sc->sc_desc[rd].next;
694 status = sc->sc_dma->desc[rd].word1;
695 #endif
696 /* XXX: callback ??? */
697
698 break;
699 }
700 case DBRI_INTR_UNDR:
701 {
702 volatile u_int32_t *cmd;
703 int td = sc->sc_pipe[channel].desc;
704
705 DPRINTF("%s: DBRI_INTR_UNDR\n", sc->sc_dev.dv_xname);
706
707 sc->sc_dma->desc[td].status = 0;
708
709 cmd = dbri_command_lock(sc);
710 *(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
711 sc->sc_pipe[channel].sdp |
712 DBRI_SDP_VALID_POINTER |
713 DBRI_SDP_CLEAR |
714 DBRI_SDP_2SAME);
715 *(cmd++) = sc->sc_dmabase + dbri_dma_off(desc, td);
716 dbri_command_send(sc, cmd);
717 break;
718 }
719 case DBRI_INTR_CMDI:
720 break;
721 default:
722
723 DPRINTF("%s: unknown interrupt code %d\n",
724 sc->sc_dev.dv_xname, code);
725 break;
726 }
727
728 return;
729 }
730
731 /*
732 * mmcodec stuff
733 */
734
735 static int
736 mmcodec_init(struct dbri_softc *sc)
737 {
738 bus_space_handle_t ioh = sc->sc_ioh;
739 bus_space_tag_t iot = sc->sc_iot;
740 u_int32_t reg2;
741 int bail;
742
743 reg2 = bus_space_read_4(iot, ioh, DBRI_REG2);
744 DPRINTF("mmcodec_init: PIO reads %x\n", reg2);
745
746 if (reg2 & DBRI_PIO2) {
747 aprint_normal("%s: onboard CS4215 detected\n",
748 sc->sc_dev.dv_xname);
749 sc->sc_mm.onboard = 1;
750 }
751
752 if (reg2 & DBRI_PIO0) {
753 aprint_normal("%s: speakerbox detected\n",
754 sc->sc_dev.dv_xname);
755 sc->sc_mm.onboard = 0;
756 }
757
758 if ((reg2 & DBRI_PIO2) && (reg2 & DBRI_PIO0)) {
759 aprint_normal("%s: using speakerbox\n",
760 sc->sc_dev.dv_xname);
761 bus_space_write_4(iot, ioh, DBRI_REG2, DBRI_PIO2_ENABLE);
762 sc->sc_mm.onboard = 0;
763 }
764
765 if (!(reg2 & (DBRI_PIO0|DBRI_PIO2))) {
766 aprint_normal("%s: no mmcodec found\n", sc->sc_dev.dv_xname);
767 return -1;
768 }
769
770 sc->sc_version = 0xff;
771
772 mmcodec_pipe_init(sc);
773 mmcodec_default(sc);
774
775 sc->sc_mm.offset = sc->sc_mm.onboard ? 0 : 8;
776
777 /*
778 * mmcodec_setcontrol() sometimes fails right after powerup
779 * so we just try again until we either get a useful response or run
780 * out of time
781 */
782 bail = 0;
783 while (mmcodec_setcontrol(sc) == -1 || sc->sc_version == 0xff) {
784
785 bail++;
786 if (bail > 100) {
787 DPRINTF("%s: cs4215 probe failed at offset %d\n",
788 sc->sc_dev.dv_xname, sc->sc_mm.offset);
789 return (-1);
790 }
791 delay(10000);
792 }
793
794 aprint_normal("%s: cs4215 ver %d found at offset %d\n",
795 sc->sc_dev.dv_xname, sc->sc_version & 0xf, sc->sc_mm.offset);
796
797 /* set some sane defaults for mmcodec_init_data */
798 sc->sc_params.channels = 2;
799 sc->sc_params.precision = 16;
800
801 mmcodec_init_data(sc);
802
803 sc->sc_open = 0;
804
805 return (0);
806 }
807
808 static void
809 mmcodec_init_data(struct dbri_softc *sc)
810 {
811 bus_space_tag_t iot = sc->sc_iot;
812 bus_space_handle_t ioh = sc->sc_ioh;
813 u_int32_t tmp;
814 int data_width;
815
816 tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
817 tmp &= ~(DBRI_CHI_ACTIVATE); /* disable CHI */
818 bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
819
820 /* switch CS4215 to data mode - set PIO3 to 1 */
821 tmp = DBRI_PIO_ENABLE_ALL | DBRI_PIO1 | DBRI_PIO3;
822 /* XXX */
823 tmp |= (sc->sc_mm.onboard ? DBRI_PIO0 : DBRI_PIO2);
824
825 bus_space_write_4(iot, ioh, DBRI_REG2, tmp);
826 chi_reset(sc, CHIslave, 128);
827
828 data_width = sc->sc_params.channels
829 * sc->sc_params.precision;
830 pipe_ts_link(sc, 20, PIPEoutput, 16, 32, sc->sc_mm.offset + 32);
831 pipe_ts_link(sc, 4, PIPEoutput, 16, data_width, sc->sc_mm.offset);
832 pipe_ts_link(sc, 6, PIPEinput, 16, data_width, sc->sc_mm.offset);
833 pipe_ts_link(sc, 21, PIPEinput, 16, 16, sc->sc_mm.offset + 40);
834
835 mmcodec_setgain(sc, 0);
836
837 tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
838 tmp |= DBRI_CHI_ACTIVATE;
839 bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
840
841 return;
842 }
843
844 static void
845 mmcodec_pipe_init(struct dbri_softc *sc)
846 {
847
848 pipe_setup(sc, 4, DBRI_SDP_MEM | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
849 pipe_setup(sc, 20, DBRI_SDP_FIXED | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
850 pipe_setup(sc, 6, DBRI_SDP_MEM | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
851 pipe_setup(sc, 21, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
852
853 pipe_setup(sc, 17, DBRI_SDP_FIXED | DBRI_SDP_TO_SER | DBRI_SDP_MSB);
854 pipe_setup(sc, 18, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
855 pipe_setup(sc, 19, DBRI_SDP_FIXED | DBRI_SDP_FROM_SER | DBRI_SDP_MSB);
856
857 sc->sc_mm.status = 0;
858
859 pipe_receive_fixed(sc, 18, &sc->sc_mm.status);
860 pipe_receive_fixed(sc, 19, &sc->sc_mm.version);
861
862 return;
863 }
864
865 static void
866 mmcodec_default(struct dbri_softc *sc)
867 {
868 struct cs4215_state *mm = &sc->sc_mm;
869
870 /*
871 * no action, memory resetting only
872 *
873 * data time slots 5-8
874 * speaker, line and headphone enable. set gain to half.
875 * input is mic
876 */
877 mm->d.bdata[0] = sc->sc_latt = 0x20 | CS4215_HE | CS4215_LE;
878 mm->d.bdata[1] = sc->sc_ratt = 0x20 | CS4215_SE;
879 mm->d.bdata[2] = CS4215_LG(0x08) | CS4215_IS | CS4215_PIO0 | CS4215_PIO1;
880 mm->d.bdata[3] = CS4215_RG(0x08) | CS4215_MA(0x0f);
881
882 /*
883 * control time slots 1-4
884 *
885 * 0: default I/O voltage scale
886 * 1: 8 bit ulaw, 8kHz, mono, high pass filter disabled
887 * 2: serial enable, CHI master, 128 bits per frame, clock 1
888 * 3: tests disabled
889 */
890 mm->c.bcontrol[0] = CS4215_RSRVD_1 | CS4215_MLB;
891 mm->c.bcontrol[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval;
892 mm->c.bcontrol[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal;
893 mm->c.bcontrol[3] = 0;
894
895 return;
896 }
897
898 static void
899 mmcodec_setgain(struct dbri_softc *sc, int mute)
900 {
901 if (mute) {
902 /* disable all outputs, max. attenuation */
903 sc->sc_mm.d.bdata[0] = sc->sc_latt | 63;
904 sc->sc_mm.d.bdata[1] = sc->sc_ratt | 63;
905 } else {
906 /*
907 * We should be setting the proper output here.. for now,
908 * use the speaker. Possible outputs:
909 * Headphones:
910 * data[0] |= CS4215_HE;
911 * Line out:
912 * data[0] |= CS4215_LE;
913 * Speaker:
914 * data[1] |= CS4215_SE;
915 */
916 sc->sc_mm.d.bdata[0] = sc->sc_latt;
917 sc->sc_mm.d.bdata[1] = sc->sc_ratt;
918 }
919
920 if (sc->sc_powerstate == 0)
921 return;
922 pipe_transmit_fixed(sc, 20, sc->sc_mm.d.ldata);
923
924 /* give the chip some time to execure the command */
925 delay(250);
926
927 return;
928 }
929
930 static int
931 mmcodec_setcontrol(struct dbri_softc *sc)
932 {
933 bus_space_tag_t iot = sc->sc_iot;
934 bus_space_handle_t ioh = sc->sc_ioh;
935 u_int32_t val;
936 u_int32_t tmp;
937 #if 1
938 int i;
939 #endif
940
941 /*
942 * Temporarily mute outputs and wait 125 us to make sure that it
943 * happens. This avoids clicking noises.
944 */
945 mmcodec_setgain(sc, 1);
946 delay(125);
947
948 /* enable control mode */
949 val = DBRI_PIO_ENABLE_ALL | DBRI_PIO1; /* was PIO1 */
950
951 /* XXX */
952 val |= (sc->sc_mm.onboard ? DBRI_PIO0 : DBRI_PIO2);
953
954 bus_space_write_4(iot, ioh, DBRI_REG2, val);
955
956 delay(34);
957
958 /*
959 * in control mode, the cs4215 is the slave device, so the
960 * DBRI must act as the CHI master.
961 *
962 * in data mode, the cs4215 must be the CHI master to insure
963 * that the data stream is in sync with its codec
964 */
965 tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
966 tmp &= ~DBRI_COMMAND_CHI;
967 bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
968
969 chi_reset(sc, CHImaster, 128);
970
971 /* control mode */
972 pipe_ts_link(sc, 17, PIPEoutput, 16, 32, sc->sc_mm.offset);
973 pipe_ts_link(sc, 18, PIPEinput, 16, 8, sc->sc_mm.offset);
974 pipe_ts_link(sc, 19, PIPEinput, 16, 8, sc->sc_mm.offset + 48);
975
976 /* wait for the chip to echo back CLB as zero */
977 sc->sc_mm.c.bcontrol[0] &= ~CS4215_CLB;
978 pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
979
980 tmp = bus_space_read_4(iot, ioh, DBRI_REG0);
981 tmp |= DBRI_CHI_ACTIVATE;
982 bus_space_write_4(iot, ioh, DBRI_REG0, tmp);
983
984 #if 1
985 i = 1024;
986 while (((sc->sc_mm.status & 0xe4) != 0x20) && --i) {
987 delay(125);
988 }
989
990 if (i == 0) {
991 DPRINTF("%s: cs4215 didn't respond to CLB (0x%02x)\n",
992 sc->sc_dev.dv_xname, sc->sc_mm.status);
993 return (-1);
994 }
995 #else
996 while ((sc->sc_mm.status & 0xe4) != 0x20) {
997 DPRINTF("%s: tsleep %p\n", sc->sc_dev.dv_xname, sc);
998 tsleep(sc, PCATCH | PZERO, "dbrifxdt", 0);
999 }
1000 #endif
1001
1002 /* copy the version information before it becomes unreadable again */
1003 sc->sc_version = sc->sc_mm.version;
1004
1005 /* terminate cs4215 control mode */
1006 sc->sc_mm.c.bcontrol[0] |= CS4215_CLB;
1007 pipe_transmit_fixed(sc, 17, sc->sc_mm.c.lcontrol);
1008
1009 /* two frames of control info @ 8kHz frame rate = 250us delay */
1010 delay(250);
1011
1012 mmcodec_setgain(sc, 0);
1013
1014 return (0);
1015
1016 }
1017
1018 /*
1019 * CHI combo
1020 */
1021 static void
1022 chi_reset(struct dbri_softc *sc, enum ms ms, int bpf)
1023 {
1024 volatile u_int32_t *cmd;
1025 int val;
1026 int clockrate, divisor;
1027
1028 cmd = dbri_command_lock(sc);
1029
1030 /* set CHI anchor: pipe 16 */
1031 val = DBRI_DTS_VI | DBRI_DTS_INS | DBRI_DTS_PRVIN(16) | DBRI_PIPE(16);
1032 *(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
1033 *(cmd++) = DBRI_TS_ANCHOR | DBRI_TS_NEXT(16);
1034 *(cmd++) = 0;
1035
1036 val = DBRI_DTS_VO | DBRI_DTS_INS | DBRI_DTS_PRVOUT(16) | DBRI_PIPE(16);
1037 *(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
1038 *(cmd++) = 0;
1039 *(cmd++) = DBRI_TS_ANCHOR | DBRI_TS_NEXT(16);
1040
1041 sc->sc_pipe[16].sdp = 1;
1042 sc->sc_pipe[16].next = 16;
1043 sc->sc_chi_pipe_in = 16;
1044 sc->sc_chi_pipe_out = 16;
1045
1046 switch (ms) {
1047 case CHIslave:
1048 *(cmd++) = DBRI_CMD(DBRI_COMMAND_CHI, 0, DBRI_CHI_CHICM(0));
1049 break;
1050 case CHImaster:
1051 clockrate = bpf * 8;
1052 divisor = 12288 / clockrate;
1053
1054 if (divisor > 255 || divisor * clockrate != 12288)
1055 aprint_error("%s: illegal bits-per-frame %d\n",
1056 sc->sc_dev.dv_xname, bpf);
1057
1058 *(cmd++) = DBRI_CMD(DBRI_COMMAND_CHI, 0,
1059 DBRI_CHI_CHICM(divisor) | DBRI_CHI_FD | DBRI_CHI_BPF(bpf));
1060 break;
1061 default:
1062 aprint_error("%s: unknown value for ms!\n", sc->sc_dev.dv_xname);
1063 break;
1064 }
1065
1066 sc->sc_chi_bpf = bpf;
1067
1068 /* CHI data mode */
1069 *(cmd++) = DBRI_CMD(DBRI_COMMAND_PAUSE, 0, 0);
1070 *(cmd++) = DBRI_CMD(DBRI_COMMAND_CDM, 0,
1071 DBRI_CDM_XCE | DBRI_CDM_XEN | DBRI_CDM_REN);
1072
1073 dbri_command_send(sc, cmd);
1074
1075 return;
1076 }
1077
1078 /*
1079 * pipe stuff
1080 */
1081 static void
1082 pipe_setup(struct dbri_softc *sc, int pipe, int sdp)
1083 {
1084 DPRINTF("pipe setup: %d\n", pipe);
1085 if (pipe < 0 || pipe >= DBRI_PIPE_MAX) {
1086 aprint_error("%s: illegal pipe number %d\n", sc->sc_dev.dv_xname,
1087 pipe);
1088 return;
1089 }
1090
1091 if ((sdp & 0xf800) != sdp)
1092 aprint_error("%s: strange SDP value %d\n", sc->sc_dev.dv_xname, sdp);
1093
1094 if (DBRI_SDP_MODE(sdp) == DBRI_SDP_FIXED &&
1095 !(sdp & DBRI_SDP_TO_SER))
1096 sdp |= DBRI_SDP_CHANGE;
1097
1098 sdp |= DBRI_PIPE(pipe);
1099
1100 sc->sc_pipe[pipe].sdp = sdp;
1101 sc->sc_pipe[pipe].desc = -1;
1102
1103 pipe_reset(sc, pipe);
1104
1105 return;
1106 }
1107
1108 static void
1109 pipe_reset(struct dbri_softc *sc, int pipe)
1110 {
1111 struct dbri_desc *dd;
1112 int sdp;
1113 int desc;
1114 volatile u_int32_t *cmd;
1115
1116 if (pipe < 0 || pipe >= DBRI_PIPE_MAX) {
1117 aprint_error("%s: illegal pipe number %d\n", sc->sc_dev.dv_xname,
1118 pipe);
1119 return;
1120 }
1121
1122 sdp = sc->sc_pipe[pipe].sdp;
1123 if (sdp == 0) {
1124 aprint_error("%s: can not reset uninitialized pipe %d\n",
1125 sc->sc_dev.dv_xname, pipe);
1126 return;
1127 }
1128
1129 cmd = dbri_command_lock(sc);
1130 *(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
1131 sdp | DBRI_SDP_CLEAR | DBRI_SDP_VALID_POINTER);
1132 *(cmd++) = 0;
1133 dbri_command_send(sc, cmd);
1134
1135 desc = sc->sc_pipe[pipe].desc;
1136
1137 dd = &sc->sc_desc[desc];
1138
1139 dd->busy = 0;
1140
1141 #if 0
1142 if (dd->callback)
1143 (*dd->callback)(dd->callback_args);
1144 #endif
1145
1146 sc->sc_pipe[pipe].desc = -1;
1147
1148 return;
1149 }
1150
1151 static void
1152 pipe_receive_fixed(struct dbri_softc *sc, int pipe, volatile u_int32_t *prec)
1153 {
1154
1155 if (pipe < DBRI_PIPE_MAX / 2 || pipe >= DBRI_PIPE_MAX) {
1156 aprint_error("%s: illegal pipe number %d\n", sc->sc_dev.dv_xname,
1157 pipe);
1158 return;
1159 }
1160
1161 if (DBRI_SDP_MODE(sc->sc_pipe[pipe].sdp) != DBRI_SDP_FIXED) {
1162 aprint_error("%s: non-fixed pipe %d\n", sc->sc_dev.dv_xname,
1163 pipe);
1164 return;
1165 }
1166
1167 if (sc->sc_pipe[pipe].sdp & DBRI_SDP_TO_SER) {
1168 aprint_error("%s: can not receive on transmit pipe %d\b",
1169 sc->sc_dev.dv_xname, pipe);
1170 return;
1171 }
1172
1173 sc->sc_pipe[pipe].prec = prec;
1174
1175 return;
1176 }
1177
1178 static void
1179 pipe_transmit_fixed(struct dbri_softc *sc, int pipe, u_int32_t data)
1180 {
1181 volatile u_int32_t *cmd;
1182
1183 if (pipe < DBRI_PIPE_MAX / 2 || pipe >= DBRI_PIPE_MAX) {
1184 aprint_error("%s: illegal pipe number %d\n", sc->sc_dev.dv_xname,
1185 pipe);
1186 return;
1187 }
1188
1189 if (DBRI_SDP_MODE(sc->sc_pipe[pipe].sdp) == 0) {
1190 aprint_error("%s: uninitialized pipe %d\n", sc->sc_dev.dv_xname,
1191 pipe);
1192 return;
1193 }
1194
1195 if (DBRI_SDP_MODE(sc->sc_pipe[pipe].sdp) != DBRI_SDP_FIXED) {
1196 aprint_error("%s: non-fixed pipe %d\n", sc->sc_dev.dv_xname, pipe);
1197 return;
1198 }
1199
1200 if (!(sc->sc_pipe[pipe].sdp & DBRI_SDP_TO_SER)) {
1201 aprint_error("%s: called on receive pipe %d\n", sc->sc_dev.dv_xname,
1202 pipe);
1203 return;
1204 }
1205
1206 if (sc->sc_pipe[pipe].sdp & DBRI_SDP_MSB)
1207 data = reverse_bytes(data, sc->sc_pipe[pipe].length);
1208
1209 cmd = dbri_command_lock(sc);
1210 *(cmd++) = DBRI_CMD(DBRI_COMMAND_SSP, 0, pipe);
1211 *(cmd++) = data;
1212
1213 dbri_command_send(sc, cmd);
1214
1215 return;
1216 }
1217
1218 static void
1219 setup_ring(struct dbri_softc *sc, int pipe, int which, int num, int blksz,
1220 void (*callback)(void *), void *callback_args)
1221 {
1222 volatile u_int32_t *cmd;
1223 int x, i;
1224 int td;
1225 int td_first, td_last;
1226 bus_addr_t dmabuf, dmabase;
1227 struct dbri_desc *dd = &sc->sc_desc[which];
1228
1229 td = 0;
1230 td_first = td_last = -1;
1231
1232 if (pipe < 0 || pipe >= DBRI_PIPE_MAX / 2) {
1233 aprint_error("%s: illegal pipe number %d\n", sc->sc_dev.dv_xname,
1234 pipe);
1235 return;
1236 }
1237
1238 if (sc->sc_pipe[pipe].sdp == 0) {
1239 aprint_error("%s: uninitialized pipe %d\n", sc->sc_dev.dv_xname,
1240 pipe);
1241 return;
1242 }
1243
1244 if (!(sc->sc_pipe[pipe].sdp & DBRI_SDP_TO_SER)) {
1245 aprint_error("%s: called on receive pipe %d\n",
1246 sc->sc_dev.dv_xname, pipe);
1247 return;
1248 }
1249
1250
1251 dmabuf = dd->dmabase;
1252 dmabase = sc->sc_dmabase;
1253 td = 0;
1254
1255 for (i = 0; i < (num-1); i++) {
1256
1257 sc->sc_dma->desc[i].flags = TX_BCNT(blksz)
1258 | TX_EOF | TX_BINT;
1259 sc->sc_dma->desc[i].ba = dmabuf;
1260 sc->sc_dma->desc[i].nda = dmabase + dbri_dma_off(desc, i + 1);
1261 sc->sc_dma->desc[i].status = 0;
1262
1263 td_last = td;
1264 dmabuf += blksz;
1265 }
1266
1267 sc->sc_dma->desc[i].flags = TX_BCNT(blksz) | TX_EOF | TX_BINT;
1268 sc->sc_dma->desc[i].ba = dmabuf;
1269 sc->sc_dma->desc[i].nda = dmabase + dbri_dma_off(desc, 0);
1270 sc->sc_dma->desc[i].status = 0;
1271
1272 dd->callback = callback; //sc->intr;
1273 dd->callback_args = callback_args; //sc->intrarg;
1274
1275 x = splaudio();
1276
1277 /* the pipe shouldn't be active */
1278 if (pipe_active(sc, pipe)) {
1279 aprint_error("pipe active (CDP)\n");
1280 /* pipe is already active */
1281 #if 0
1282 td_last = sc->sc_pipe[pipe].desc;
1283 while (sc->sc_desc[td_last].next != -1)
1284 td_last = sc->sc_desc[td_last].next;
1285
1286 sc->sc_desc[td_last].next = td_first;
1287 sc->sc_dma->desc[td_last].nda =
1288 sc->sc_dmabase + dbri_dma_off(desc, td_first);
1289
1290 cmd = dbri_command_lock(sc);
1291 *(cmd++) = DBRI_CMD(DBRI_COMMAND_CDP, 0, pipe);
1292 dbri_command_send(sc, cmd);
1293 #endif
1294 } else {
1295 /*
1296 * pipe isn't active - issue an SDP command to start our
1297 * chain of TDs running
1298 */
1299 sc->sc_pipe[pipe].desc = which;
1300 cmd = dbri_command_lock(sc);
1301 *(cmd++) = DBRI_CMD(DBRI_COMMAND_SDP, 0,
1302 sc->sc_pipe[pipe].sdp |
1303 DBRI_SDP_VALID_POINTER |
1304 DBRI_SDP_EVERY |
1305 DBRI_SDP_CLEAR);
1306 *(cmd++) = sc->sc_dmabase + dbri_dma_off(desc, 0);
1307 dbri_command_send(sc, cmd);
1308 }
1309
1310 splx(x);
1311
1312 return;
1313 }
1314
1315 static void
1316 pipe_ts_link(struct dbri_softc *sc, int pipe, enum io dir, int basepipe,
1317 int len, int cycle)
1318 {
1319 volatile u_int32_t *cmd;
1320 int prevpipe, nextpipe;
1321 int val;
1322
1323 if (pipe < 0 || pipe >= DBRI_PIPE_MAX ||
1324 basepipe < 0 || basepipe >= DBRI_PIPE_MAX) {
1325 aprint_error("%s: illegal pipe numbers (%d, %d)\n",
1326 sc->sc_dev.dv_xname, pipe, basepipe);
1327 return;
1328 }
1329
1330 if (sc->sc_pipe[pipe].sdp == 0 || sc->sc_pipe[basepipe].sdp == 0) {
1331 aprint_error("%s: uninitialized pipe (%d, %d)\n",
1332 sc->sc_dev.dv_xname, pipe, basepipe);
1333 return;
1334 }
1335
1336 if (basepipe == 16 && dir == PIPEoutput && cycle == 0)
1337 cycle = sc->sc_chi_bpf;
1338
1339 if (basepipe == pipe)
1340 prevpipe = nextpipe = pipe;
1341 else {
1342 if (basepipe == 16) {
1343 if (dir == PIPEinput) {
1344 prevpipe = sc->sc_chi_pipe_in;
1345 } else {
1346 prevpipe = sc->sc_chi_pipe_out;
1347 }
1348 } else
1349 prevpipe = basepipe;
1350
1351 nextpipe = sc->sc_pipe[prevpipe].next;
1352
1353 while (sc->sc_pipe[nextpipe].cycle < cycle &&
1354 sc->sc_pipe[nextpipe].next != basepipe) {
1355 prevpipe = nextpipe;
1356 nextpipe = sc->sc_pipe[nextpipe].next;
1357 }
1358 }
1359
1360 if (prevpipe == 16) {
1361 if (dir == PIPEinput) {
1362 sc->sc_chi_pipe_in = pipe;
1363 } else {
1364 sc->sc_chi_pipe_out = pipe;
1365 }
1366 } else
1367 sc->sc_pipe[prevpipe].next = pipe;
1368
1369 sc->sc_pipe[pipe].next = nextpipe;
1370 sc->sc_pipe[pipe].cycle = cycle;
1371 sc->sc_pipe[pipe].length = len;
1372
1373 cmd = dbri_command_lock(sc);
1374
1375 switch (dir) {
1376 case PIPEinput:
1377 val = DBRI_DTS_VI | DBRI_DTS_INS | DBRI_DTS_PRVIN(prevpipe);
1378 val |= pipe;
1379 *(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
1380 *(cmd++) = DBRI_TS_LEN(len) | DBRI_TS_CYCLE(cycle) |
1381 DBRI_TS_NEXT(nextpipe);
1382 *(cmd++) = 0;
1383 break;
1384 case PIPEoutput:
1385 val = DBRI_DTS_VO | DBRI_DTS_INS | DBRI_DTS_PRVOUT(prevpipe);
1386 val |= pipe;
1387 *(cmd++) = DBRI_CMD(DBRI_COMMAND_DTS, 0, val);
1388 *(cmd++) = 0;
1389 *(cmd++) = DBRI_TS_LEN(len) | DBRI_TS_CYCLE(cycle) |
1390 DBRI_TS_NEXT(nextpipe);
1391 break;
1392 default:
1393 DPRINTF("%s: should not have happened!\n",
1394 sc->sc_dev.dv_xname);
1395 break;
1396 }
1397
1398 dbri_command_send(sc, cmd);
1399
1400 return;
1401 }
1402
1403 static int
1404 pipe_active(struct dbri_softc *sc, int pipe)
1405 {
1406
1407 return (sc->sc_pipe[pipe].desc != -1);
1408 }
1409
1410 /*
1411 * subroutines required to interface with audio(9)
1412 */
1413
1414 static int
1415 dbri_query_encoding(void *hdl, struct audio_encoding *ae)
1416 {
1417
1418 switch (ae->index) {
1419 case 0:
1420 strcpy(ae->name, AudioEulinear);
1421 ae->encoding = AUDIO_ENCODING_ULINEAR;
1422 ae->precision = 8;
1423 ae->flags = 0;
1424 break;
1425 case 1:
1426 strcpy(ae->name, AudioEmulaw);
1427 ae->encoding = AUDIO_ENCODING_ULAW;
1428 ae->precision = 8;
1429 ae->flags = 0;
1430 break;
1431 case 2:
1432 strcpy(ae->name, AudioEalaw);
1433 ae->encoding = AUDIO_ENCODING_ALAW;
1434 ae->precision = 8;
1435 ae->flags = 0;
1436 break;
1437 case 3:
1438 strcpy(ae->name, AudioEslinear);
1439 ae->encoding = AUDIO_ENCODING_SLINEAR;
1440 ae->precision = 8;
1441 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
1442 break;
1443 case 4:
1444 strcpy(ae->name, AudioEslinear_le);
1445 ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
1446 ae->precision = 16;
1447 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
1448 break;
1449 case 5:
1450 strcpy(ae->name, AudioEulinear_le);
1451 ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
1452 ae->precision = 16;
1453 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
1454 break;
1455 case 6:
1456 strcpy(ae->name, AudioEslinear_be);
1457 ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
1458 ae->precision = 16;
1459 ae->flags = 0;
1460 break;
1461 case 7:
1462 strcpy(ae->name, AudioEulinear_be);
1463 ae->encoding = AUDIO_ENCODING_ULINEAR_BE;
1464 ae->precision = 16;
1465 ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
1466 break;
1467 case 8:
1468 strcpy(ae->name, AudioEslinear);
1469 ae->encoding = AUDIO_ENCODING_SLINEAR;
1470 ae->precision = 16;
1471 ae->flags = 0;
1472 break;
1473 default:
1474 return (EINVAL);
1475 }
1476
1477 return (0);
1478 }
1479
1480 /*
1481 * XXX: recording isn't supported - jmcneill
1482 */
1483 static int
1484 dbri_set_params(void *hdl, int setmode, int usemode,
1485 struct audio_params *play, struct audio_params *rec,
1486 stream_filter_list_t *pfil, stream_filter_list_t *rfil)
1487 {
1488 struct dbri_softc *sc = hdl;
1489 int rate;
1490 audio_params_t *p = NULL;
1491 stream_filter_list_t *fil;
1492 int mode;
1493
1494 /*
1495 * This device only has one clock, so make the sample rates match.
1496 */
1497 if (play->sample_rate != rec->sample_rate &&
1498 usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
1499 if (setmode == AUMODE_PLAY) {
1500 rec->sample_rate = play->sample_rate;
1501 setmode |= AUMODE_RECORD;
1502 } else if (setmode == AUMODE_RECORD) {
1503 play->sample_rate = rec->sample_rate;
1504 setmode |= AUMODE_PLAY;
1505 } else
1506 return EINVAL;
1507 }
1508
1509 for (mode = AUMODE_RECORD; mode != -1;
1510 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
1511 if ((setmode & mode) == 0)
1512 continue;
1513
1514 p = mode == AUMODE_PLAY ? play : rec;
1515 if (p->sample_rate < 4000 || p->sample_rate > 50000) {
1516 DPRINTF("dbri_set_params: invalid rate %d\n",
1517 p->sample_rate);
1518 return EINVAL;
1519 }
1520
1521 fil = mode == AUMODE_PLAY ? pfil : rfil;
1522 DPRINTF("enc: %d rate: %d prec: %d chan: %d\n", p->encoding,
1523 p->sample_rate, p->precision, p->channels);
1524 if (auconv_set_converter(dbri_formats, DBRI_NFORMATS,
1525 mode, p, true, fil) < 0) {
1526 DPRINTF("dbri_set_params: auconv_set_converter failed\n");
1527 return EINVAL;
1528 }
1529 if (fil->req_size > 0)
1530 p = &fil->filters[0].param;
1531 }
1532
1533 if (p == NULL) {
1534 DPRINTF("dbri_set_params: no parameters to set\n");
1535 return 0;
1536 }
1537
1538 DPRINTF("enc: %d rate: %d prec: %d chan: %d\n", p->encoding,
1539 p->sample_rate, p->precision, p->channels);
1540
1541 for (rate = 0; CS4215_FREQ[rate].freq; rate++)
1542 if (CS4215_FREQ[rate].freq == p->sample_rate)
1543 break;
1544
1545 if (CS4215_FREQ[rate].freq == 0)
1546 return (EINVAL);
1547
1548 /* set frequency */
1549 sc->sc_mm.c.bcontrol[1] &= ~0x38;
1550 sc->sc_mm.c.bcontrol[1] |= CS4215_FREQ[rate].csval;
1551 sc->sc_mm.c.bcontrol[2] &= ~0x70;
1552 sc->sc_mm.c.bcontrol[2] |= CS4215_FREQ[rate].xtal;
1553
1554 switch (p->encoding) {
1555 case AUDIO_ENCODING_ULAW:
1556 sc->sc_mm.c.bcontrol[1] &= ~3;
1557 sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_ULAW;
1558 break;
1559 case AUDIO_ENCODING_ALAW:
1560 sc->sc_mm.c.bcontrol[1] &= ~3;
1561 sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_ALAW;
1562 break;
1563 case AUDIO_ENCODING_ULINEAR:
1564 sc->sc_mm.c.bcontrol[1] &= ~3;
1565 if (p->precision == 8) {
1566 sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_LINEAR8;
1567 } else {
1568 sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_LINEAR16;
1569 }
1570 break;
1571 case AUDIO_ENCODING_SLINEAR_BE:
1572 case AUDIO_ENCODING_SLINEAR:
1573 sc->sc_mm.c.bcontrol[1] &= ~3;
1574 sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_LINEAR16;
1575 break;
1576 }
1577
1578 switch (p->channels) {
1579 case 1:
1580 sc->sc_mm.c.bcontrol[1] &= ~CS4215_DFR_STEREO;
1581 break;
1582 case 2:
1583 sc->sc_mm.c.bcontrol[1] |= CS4215_DFR_STEREO;
1584 break;
1585 }
1586
1587 return (0);
1588 }
1589
1590 static int
1591 dbri_round_blocksize(void *hdl, int bs, int mode,
1592 const audio_params_t *param)
1593 {
1594
1595 /* DBRI DMA segment size, rounded town to 32bit alignment */
1596 return 0x1ffc;
1597 }
1598
1599 static int
1600 dbri_halt_output(void *hdl)
1601 {
1602 struct dbri_softc *sc = hdl;
1603
1604 pipe_reset(sc, 4);
1605
1606 return (0);
1607 }
1608
1609 static int
1610 dbri_getdev(void *hdl, struct audio_device *ret)
1611 {
1612
1613 *ret = dbri_device;
1614 return (0);
1615 }
1616
1617 static int
1618 dbri_set_port(void *hdl, mixer_ctrl_t *mc)
1619 {
1620 struct dbri_softc *sc = hdl;
1621 int latt = sc->sc_latt, ratt = sc->sc_ratt;
1622
1623 switch (mc->dev) {
1624 case DBRI_VOL_OUTPUT: /* master volume */
1625 latt = (latt & 0xc0) | (63 -
1626 min(mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] >> 2, 63));
1627 ratt = (ratt & 0xc0) | (63 -
1628 min(mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] >> 2, 63));
1629 break;
1630 case DBRI_ENABLE_MONO: /* built-in speaker */
1631 if (mc->un.ord == 1) {
1632 ratt |= CS4215_SE;
1633 } else
1634 ratt &= ~CS4215_SE;
1635 break;
1636 case DBRI_ENABLE_HEADPHONE: /* headphones output */
1637 if (mc->un.ord == 1) {
1638 latt |= CS4215_HE;
1639 } else
1640 latt &= ~CS4215_HE;
1641 break;
1642 case DBRI_ENABLE_LINE: /* line out */
1643 if (mc->un.ord == 1) {
1644 latt |= CS4215_LE;
1645 } else
1646 latt &= ~CS4215_LE;
1647 break;
1648 }
1649
1650 sc->sc_latt = latt;
1651 sc->sc_ratt = ratt;
1652
1653 mmcodec_setgain(sc, 0);
1654
1655 return (0);
1656 }
1657
1658 static int
1659 dbri_get_port(void *hdl, mixer_ctrl_t *mc)
1660 {
1661 struct dbri_softc *sc = hdl;
1662
1663 switch (mc->dev) {
1664 case DBRI_VOL_OUTPUT: /* master volume */
1665 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1666 (63 - (sc->sc_latt & 0x3f)) << 2;
1667 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1668 (63 - (sc->sc_ratt & 0x3f)) << 2;
1669 return (0);
1670 case DBRI_ENABLE_MONO: /* built-in speaker */
1671 mc->un.ord = (sc->sc_ratt & CS4215_SE) ? 1 : 0;
1672 return 0;
1673 case DBRI_ENABLE_HEADPHONE: /* headphones output */
1674 mc->un.ord = (sc->sc_latt & CS4215_HE) ? 1 : 0;
1675 return 0;
1676 case DBRI_ENABLE_LINE: /* line out */
1677 mc->un.ord = (sc->sc_latt & CS4215_LE) ? 1 : 0;
1678 return 0;
1679 }
1680 return (EINVAL);
1681 }
1682
1683 static int
1684 dbri_query_devinfo(void *hdl, mixer_devinfo_t *di)
1685 {
1686
1687 switch (di->index) {
1688 case DBRI_MONITOR_CLASS:
1689 di->mixer_class = DBRI_MONITOR_CLASS;
1690 strcpy(di->label.name, AudioCmonitor);
1691 di->type = AUDIO_MIXER_CLASS;
1692 di->next = di->prev = AUDIO_MIXER_LAST;
1693 return 0;
1694 case DBRI_VOL_OUTPUT: /* master volume */
1695 di->mixer_class = DBRI_MONITOR_CLASS;
1696 di->next = di->prev = AUDIO_MIXER_LAST;
1697 strcpy(di->label.name, AudioNmaster);
1698 di->type = AUDIO_MIXER_VALUE;
1699 di->un.v.num_channels = 2;
1700 strcpy(di->un.v.units.name, AudioNvolume);
1701 return (0);
1702 case DBRI_ENABLE_MONO: /* built-in speaker */
1703 di->mixer_class = DBRI_MONITOR_CLASS;
1704 di->next = di->prev = AUDIO_MIXER_LAST;
1705 strcpy(di->label.name, AudioNmono);
1706 di->type = AUDIO_MIXER_ENUM;
1707 di->un.e.num_mem = 2;
1708 strcpy(di->un.e.member[0].label.name, AudioNoff);
1709 di->un.e.member[0].ord = 0;
1710 strcpy(di->un.e.member[1].label.name, AudioNon);
1711 di->un.e.member[1].ord = 1;
1712 return (0);
1713 case DBRI_ENABLE_HEADPHONE: /* headphones output */
1714 di->mixer_class = DBRI_MONITOR_CLASS;
1715 di->next = di->prev = AUDIO_MIXER_LAST;
1716 strcpy(di->label.name, AudioNheadphone);
1717 di->type = AUDIO_MIXER_ENUM;
1718 di->un.e.num_mem = 2;
1719 strcpy(di->un.e.member[0].label.name, AudioNoff);
1720 di->un.e.member[0].ord = 0;
1721 strcpy(di->un.e.member[1].label.name, AudioNon);
1722 di->un.e.member[1].ord = 1;
1723 return (0);
1724 case DBRI_ENABLE_LINE: /* line out */
1725 di->mixer_class = DBRI_MONITOR_CLASS;
1726 di->next = di->prev = AUDIO_MIXER_LAST;
1727 strcpy(di->label.name, AudioNline);
1728 di->type = AUDIO_MIXER_ENUM;
1729 di->un.e.num_mem = 2;
1730 strcpy(di->un.e.member[0].label.name, AudioNoff);
1731 di->un.e.member[0].ord = 0;
1732 strcpy(di->un.e.member[1].label.name, AudioNon);
1733 di->un.e.member[1].ord = 1;
1734 return (0);
1735 }
1736
1737 return (ENXIO);
1738 }
1739
1740 static size_t
1741 dbri_round_buffersize(void *hdl, int dir, size_t bufsize)
1742 {
1743 #ifdef DBRI_BIG_BUFFER
1744 return 16*0x1ffc; /* use ~128KB buffer */
1745 #else
1746 return bufsize;
1747 #endif
1748 }
1749
1750 static int
1751 dbri_get_props(void *hdl)
1752 {
1753
1754 return (AUDIO_PROP_MMAP/* | AUDIO_PROP_INDEPENDENT*/);
1755 //return (0);
1756 }
1757
1758 static int
1759 dbri_trigger_output(void *hdl, void *start, void *end, int blksize,
1760 void (*intr)(void *), void *intrarg,
1761 const struct audio_params *param)
1762 {
1763 struct dbri_softc *sc = hdl;
1764 unsigned long count, current, num;
1765
1766 count = (unsigned long)(((char *)end - (char *)start));
1767 num = count / blksize;
1768
1769 DPRINTF("trigger_output(%lx %lx) : %d %ld %ld\n",
1770 (unsigned long)intr,
1771 (unsigned long)intrarg, blksize, count, num);
1772
1773 sc->sc_params = *param;
1774
1775 mmcodec_setcontrol(sc);
1776 mmcodec_init_data(sc);
1777 current = 0;
1778 while ((current < sc->sc_desc_used) &&
1779 (sc->sc_desc[current].buf != start))
1780 current++;
1781
1782 if (current < sc->sc_desc_used) {
1783 setup_ring(sc, 4, current, num, blksize, intr, intrarg);
1784 return 0;
1785 }
1786 return EINVAL;
1787 }
1788
1789 static u_int32_t
1790 reverse_bytes(u_int32_t b, int len)
1791 {
1792 switch (len) {
1793 case 32:
1794 b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16);
1795 case 16:
1796 b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8);
1797 case 8:
1798 b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4);
1799 case 4:
1800 b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2);
1801 case 2:
1802 b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1);
1803 case 1:
1804 case 0:
1805 break;
1806 default:
1807 DPRINTF("reverse_bytes: unsupported length\n");
1808 };
1809
1810 return (b);
1811 }
1812
1813 static void
1814 *dbri_malloc(void *v, int dir, size_t s, struct malloc_type *mt, int flags)
1815 {
1816 struct dbri_softc *sc = v;
1817 struct dbri_desc *dd = &sc->sc_desc[sc->sc_desc_used];
1818 int rseg;
1819
1820 if (bus_dmamap_create(sc->sc_dmat, s, 1, s, 0, BUS_DMA_NOWAIT,
1821 &dd->dmamap) == 0) {
1822 if (bus_dmamem_alloc(sc->sc_dmat, s, 0, 0, &dd->dmaseg,
1823 1, &rseg, BUS_DMA_NOWAIT) == 0) {
1824 if (bus_dmamem_map(sc->sc_dmat, &dd->dmaseg, rseg, s,
1825 &dd->buf, BUS_DMA_NOWAIT|BUS_DMA_COHERENT) == 0) {
1826 if (dd->buf!=NULL) {
1827 if (bus_dmamap_load(sc->sc_dmat,
1828 dd->dmamap, dd->buf, s, NULL,
1829 BUS_DMA_NOWAIT) == 0) {
1830 dd->len = s;
1831 dd->busy = 0;
1832 dd->callback = NULL;
1833 dd->dmabase =
1834 dd->dmamap->dm_segs[0].ds_addr;
1835 DPRINTF("dbri_malloc: using buffer %d\n",
1836 sc->sc_desc_used);
1837 sc->sc_desc_used++;
1838 return dd->buf;
1839 } else
1840 aprint_error("dbri_malloc: load failed\n");
1841 } else
1842 aprint_error("dbri_malloc: map returned NULL\n");
1843 } else
1844 aprint_error("dbri_malloc: map failed\n");
1845 bus_dmamem_free(sc->sc_dmat, &dd->dmaseg, rseg);
1846 } else
1847 aprint_error("dbri_malloc: malloc() failed\n");
1848 bus_dmamap_destroy(sc->sc_dmat, dd->dmamap);
1849 } else
1850 aprint_error("dbri_malloc: bus_dmamap_create() failed\n");
1851 return NULL;
1852 }
1853
1854 static void
1855 dbri_free(void *v, void *p, struct malloc_type *mt)
1856 {
1857 free(p, mt);
1858 }
1859
1860 static paddr_t
1861 dbri_mappage(void *v, void *mem, off_t off, int prot)
1862 {
1863 struct dbri_softc *sc = v;;
1864 int current;
1865
1866 if (off < 0)
1867 return -1;
1868
1869 current = 0;
1870 while ((current < sc->sc_desc_used) &&
1871 (sc->sc_desc[current].buf != mem))
1872 current++;
1873
1874 if (current < sc->sc_desc_used) {
1875 return bus_dmamem_mmap(sc->sc_dmat,
1876 &sc->sc_desc[current].dmaseg, 1, off, prot, BUS_DMA_WAITOK);
1877 }
1878
1879 return -1;
1880 }
1881
1882 static int
1883 dbri_open(void *cookie, int flags)
1884 {
1885 struct dbri_softc *sc = cookie;
1886
1887 dbri_bring_up(sc);
1888 return 0;
1889 }
1890
1891 static void
1892 dbri_close(void *cookie)
1893 {
1894 struct dbri_softc *sc = cookie;
1895
1896 dbri_set_power(sc, 0);
1897 }
1898
1899 static void
1900 dbri_powerhook(int why, void *cookie)
1901 {
1902 struct dbri_softc *sc = cookie;
1903
1904 switch(why)
1905 {
1906 case PWR_SUSPEND:
1907 case PWR_STANDBY:
1908 dbri_set_power(sc, 0);
1909 break;
1910 case PWR_RESUME:
1911 dbri_bring_up(sc);
1912 break;
1913 }
1914 }
1915
1916 #endif /* NAUDIO > 0 */
1917