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