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