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