1 /* $NetBSD: cs4231_ebus.c,v 1.33 2009/05/12 14:20:45 cegger Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Valeriy E. Ushakov 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: cs4231_ebus.c,v 1.33 2009/05/12 14:20:45 cegger Exp $"); 32 33 #ifdef _KERNEL_OPT 34 #include "opt_sparc_arch.h" 35 #endif 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/errno.h> 40 #include <sys/device.h> 41 #include <sys/malloc.h> 42 #include <sys/cpu.h> 43 44 #include <machine/autoconf.h> 45 46 #include <dev/ebus/ebusreg.h> 47 #include <dev/ebus/ebusvar.h> 48 49 #include <sys/audioio.h> 50 #include <dev/audio_if.h> 51 52 #include <dev/ic/ad1848reg.h> 53 #include <dev/ic/cs4231reg.h> 54 #include <dev/ic/ad1848var.h> 55 #include <dev/ic/cs4231var.h> 56 57 #ifdef AUDIO_DEBUG 58 int cs4231_ebus_debug = 0; 59 #define DPRINTF(x) if (cs4231_ebus_debug) printf x 60 #else 61 #define DPRINTF(x) 62 #endif 63 64 65 struct cs4231_ebus_softc { 66 struct cs4231_softc sc_cs4231; 67 68 void *sc_pint; 69 void *sc_rint; 70 bus_space_tag_t sc_bt; 71 bus_space_handle_t sc_pdmareg; /* playback DMA */ 72 bus_space_handle_t sc_cdmareg; /* record DMA */ 73 }; 74 75 76 void cs4231_ebus_attach(device_t, device_t, void *); 77 int cs4231_ebus_match(device_t, cfdata_t, void *); 78 79 static int cs4231_ebus_pint(void *); 80 static int cs4231_ebus_rint(void *); 81 82 CFATTACH_DECL(audiocs_ebus, sizeof(struct cs4231_ebus_softc), 83 cs4231_ebus_match, cs4231_ebus_attach, NULL, NULL); 84 85 /* audio_hw_if methods specific to ebus DMA */ 86 static int cs4231_ebus_round_blocksize(void *, int, int, 87 const audio_params_t *); 88 static int cs4231_ebus_trigger_output(void *, void *, void *, int, 89 void (*)(void *), void *, 90 const audio_params_t *); 91 static int cs4231_ebus_trigger_input(void *, void *, void *, int, 92 void (*)(void *), void *, 93 const audio_params_t *); 94 static int cs4231_ebus_halt_output(void *); 95 static int cs4231_ebus_halt_input(void *); 96 97 const struct audio_hw_if audiocs_ebus_hw_if = { 98 cs4231_open, 99 cs4231_close, 100 NULL, /* drain */ 101 ad1848_query_encoding, 102 ad1848_set_params, 103 cs4231_ebus_round_blocksize, 104 ad1848_commit_settings, 105 NULL, /* init_output */ 106 NULL, /* init_input */ 107 NULL, /* start_output */ 108 NULL, /* start_input */ 109 cs4231_ebus_halt_output, 110 cs4231_ebus_halt_input, 111 NULL, /* speaker_ctl */ 112 cs4231_getdev, 113 NULL, /* setfd */ 114 cs4231_set_port, 115 cs4231_get_port, 116 cs4231_query_devinfo, 117 cs4231_malloc, 118 cs4231_free, 119 NULL, /* round_buffersize */ 120 NULL, /* mappage */ 121 cs4231_get_props, 122 cs4231_ebus_trigger_output, 123 cs4231_ebus_trigger_input, 124 NULL, /* dev_ioctl */ 125 NULL, /* powerstate */ 126 }; 127 128 #ifdef AUDIO_DEBUG 129 static void cs4231_ebus_regdump(char *, struct cs4231_ebus_softc *); 130 #endif 131 132 static int cs4231_ebus_dma_reset(bus_space_tag_t, bus_space_handle_t); 133 static int cs4231_ebus_trigger_transfer(struct cs4231_softc *, 134 struct cs_transfer *, 135 bus_space_tag_t, bus_space_handle_t, 136 int, void *, void *, int, void (*)(void *), void *, 137 const audio_params_t *); 138 static void cs4231_ebus_dma_advance(struct cs_transfer *, 139 bus_space_tag_t, bus_space_handle_t); 140 static int cs4231_ebus_dma_intr(struct cs_transfer *, 141 bus_space_tag_t, bus_space_handle_t, 142 void *); 143 static int cs4231_ebus_intr(void *); 144 145 146 int 147 cs4231_ebus_match(device_t parent, cfdata_t cf, void *aux) 148 { 149 struct ebus_attach_args *ea; 150 char *compat; 151 int len, total_size; 152 153 ea = aux; 154 if (strcmp(ea->ea_name, AUDIOCS_PROM_NAME) == 0) 155 return 1; 156 157 compat = NULL; 158 if (prom_getprop(ea->ea_node, "compatible", 1, &total_size, &compat) == 0) { 159 do { 160 if (strcmp(compat, AUDIOCS_PROM_NAME) == 0) 161 return 1; 162 #ifdef __sparc__ 163 /* on KRUPS compatible lists: "cs4231", "ad1848", 164 * "mwave", and "pnpPNP,b007" */ 165 if (strcmp(compat, "cs4231") == 0) 166 return 1; 167 #endif 168 len = strlen(compat) + 1; 169 total_size -= len; 170 compat += len; 171 } while (total_size > 0); 172 } 173 174 return 0; 175 } 176 177 178 void 179 cs4231_ebus_attach(device_t parent, device_t self, void *aux) 180 { 181 struct cs4231_ebus_softc *ebsc; 182 struct cs4231_softc *sc; 183 struct ebus_attach_args *ea; 184 bus_space_handle_t bh; 185 int i; 186 187 ebsc = device_private(self); 188 sc = &ebsc->sc_cs4231; 189 ea = aux; 190 sc->sc_bustag = ebsc->sc_bt = ea->ea_bustag; 191 sc->sc_dmatag = ea->ea_dmatag; 192 193 ebsc->sc_pint = sparc_softintr_establish(IPL_VM, 194 (void *)cs4231_ebus_pint, sc); 195 ebsc->sc_rint = sparc_softintr_establish(IPL_VM, 196 (void *)cs4231_ebus_rint, sc); 197 198 /* 199 * These are the register we get from the prom: 200 * - CS4231 registers 201 * - Playback EBus DMA controller 202 * - Capture EBus DMA controller 203 * - AUXIO audio register (codec powerdown) 204 * 205 * Map my registers in, if they aren't already in virtual 206 * address space. 207 */ 208 if (bus_space_map(ea->ea_bustag, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 209 ea->ea_reg[0].size, 0, &bh) != 0) { 210 printf(": unable to map registers\n"); 211 return; 212 } 213 214 if (bus_space_map(ea->ea_bustag, 215 #ifdef MSIIEP /* XXX: Krups */ 216 /* 217 * XXX: map playback DMA registers 218 * (we just know where they are) 219 */ 220 BUS_ADDR(0x14, 0x702000), /* XXX: magic num */ 221 EBUS_DMAC_SIZE, 222 #else 223 EBUS_ADDR_FROM_REG(&ea->ea_reg[1]), 224 ea->ea_reg[1].size, 225 #endif 226 0, &ebsc->sc_pdmareg) != 0) 227 { 228 printf(": unable to map playback DMA registers\n"); 229 return; 230 } 231 232 if (bus_space_map(ea->ea_bustag, 233 #ifdef MSIIEP /* XXX: Krups */ 234 /* 235 * XXX: map capture DMA registers 236 * (we just know where they are) 237 */ 238 BUS_ADDR(0x14, 0x704000), /* XXX: magic num */ 239 EBUS_DMAC_SIZE, 240 #else 241 EBUS_ADDR_FROM_REG(&ea->ea_reg[2]), 242 ea->ea_reg[2].size, 243 #endif 244 0, &ebsc->sc_cdmareg) != 0) 245 { 246 printf(": unable to map capture DMA registers\n"); 247 return; 248 } 249 250 /* establish interrupt channels */ 251 for (i = 0; i < ea->ea_nintr; ++i) 252 bus_intr_establish(ea->ea_bustag, 253 ea->ea_intr[i], IPL_SCHED, 254 cs4231_ebus_intr, ebsc); 255 256 cs4231_common_attach(sc, bh); 257 printf("\n"); 258 259 /* XXX: todo: move to cs4231_common_attach, pass hw_if as arg? */ 260 audio_attach_mi(&audiocs_ebus_hw_if, sc, &sc->sc_ad1848.sc_dev); 261 } 262 263 264 static int 265 cs4231_ebus_round_blocksize(void *addr, int blk, int mode, 266 const audio_params_t *param) 267 { 268 269 /* we want to use DMA burst size of 16 words */ 270 return blk & -64; 271 } 272 273 274 #ifdef AUDIO_DEBUG 275 static void 276 cs4231_ebus_regdump(char *label, struct cs4231_ebus_softc *ebsc) 277 { 278 /* char bits[128]; */ 279 280 printf("cs4231regdump(%s): regs:", label); 281 /* XXX: dump ebus DMA and aux registers */ 282 ad1848_dump_regs(&ebsc->sc_cs4231.sc_ad1848); 283 } 284 #endif /* AUDIO_DEBUG */ 285 286 287 /* XXX: nothing CS4231-specific in this code... */ 288 static int 289 cs4231_ebus_dma_reset(bus_space_tag_t dt, bus_space_handle_t dh) 290 { 291 u_int32_t csr; 292 int timo; 293 294 /* reset, also clear TC, just in case */ 295 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, EBDMA_RESET | EBDMA_TC); 296 297 for (timo = 50000; timo != 0; --timo) { 298 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 299 if ((csr & (EBDMA_CYC_PEND | EBDMA_DRAIN)) == 0) 300 break; 301 } 302 303 if (timo == 0) { 304 char bits[128]; 305 snprintb(bits, sizeof(bits), EBUS_DCSR_BITS, csr); 306 printf("cs4231_ebus_dma_reset: timed out: csr=%s\n", bits); 307 return ETIMEDOUT; 308 } 309 310 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr & ~EBDMA_RESET); 311 return 0; 312 } 313 314 315 static void 316 cs4231_ebus_dma_advance(struct cs_transfer *t, bus_space_tag_t dt, 317 bus_space_handle_t dh) 318 { 319 bus_addr_t dmaaddr; 320 bus_size_t dmasize; 321 322 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 323 324 bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (u_int32_t)dmasize); 325 bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (u_int32_t)dmaaddr); 326 } 327 328 329 /* 330 * Trigger transfer "t" using DMA controller at "dt"/"dh". 331 * "iswrite" defines direction of the transfer. 332 */ 333 static int 334 cs4231_ebus_trigger_transfer( 335 struct cs4231_softc *sc, 336 struct cs_transfer *t, 337 bus_space_tag_t dt, 338 bus_space_handle_t dh, 339 int iswrite, 340 void *start, void *end, 341 int blksize, 342 void (*intr)(void *), 343 void *arg, 344 const audio_params_t *param) 345 { 346 uint32_t csr; 347 bus_addr_t dmaaddr; 348 bus_size_t dmasize; 349 int ret; 350 351 ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize, 352 start, end, blksize, intr, arg); 353 if (ret != 0) 354 return ret; 355 356 ret = cs4231_ebus_dma_reset(dt, dh); 357 if (ret != 0) 358 return ret; 359 360 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 361 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, 362 csr | EBDMA_EN_NEXT | (iswrite ? EBDMA_WRITE : 0) 363 | EBDMA_EN_DMA | EBDMA_EN_CNT | EBDMA_INT_EN 364 | EBDMA_BURST_SIZE_16); 365 366 /* first load: propagated to DACR/DBCR */ 367 bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (uint32_t)dmasize); 368 bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (uint32_t)dmaaddr); 369 370 /* next load: goes to DNAR/DNBR */ 371 cs4231_ebus_dma_advance(t, dt, dh); 372 373 return 0; 374 } 375 376 377 static int 378 cs4231_ebus_trigger_output(void *addr, void *start, void *end, int blksize, 379 void (*intr)(void *), void *arg, 380 const audio_params_t *param) 381 { 382 struct cs4231_ebus_softc *ebsc; 383 struct cs4231_softc *sc; 384 int cfg, ret; 385 386 ebsc = addr; 387 sc = &ebsc->sc_cs4231; 388 ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_playback, 389 ebsc->sc_bt, ebsc->sc_pdmareg, 390 0, /* iswrite */ 391 start, end, blksize, 392 intr, arg, param); 393 if (ret != 0) 394 return ret; 395 396 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 397 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 398 399 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 400 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | PLAYBACK_ENABLE); 401 402 return 0; 403 } 404 405 406 static int 407 cs4231_ebus_trigger_input(void *addr, void *start, void *end, int blksize, 408 void (*intr)(void *), void *arg, 409 const audio_params_t *param) 410 { 411 struct cs4231_ebus_softc *ebsc; 412 struct cs4231_softc *sc; 413 int cfg, ret; 414 415 ebsc = addr; 416 sc = &ebsc->sc_cs4231; 417 ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_capture, 418 ebsc->sc_bt, ebsc->sc_cdmareg, 419 1, /* iswrite */ 420 start, end, blksize, 421 intr, arg, param); 422 if (ret != 0) 423 return ret; 424 425 ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff); 426 ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff); 427 428 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 429 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | CAPTURE_ENABLE); 430 431 return 0; 432 } 433 434 435 static int 436 cs4231_ebus_halt_output(void *addr) 437 { 438 struct cs4231_ebus_softc *ebsc; 439 struct cs4231_softc *sc; 440 u_int32_t csr; 441 int cfg; 442 443 ebsc = addr; 444 sc = &ebsc->sc_cs4231; 445 sc->sc_playback.t_active = 0; 446 447 csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR); 448 bus_space_write_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR, 449 csr & ~EBDMA_EN_DMA); 450 451 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 452 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 453 cfg & ~PLAYBACK_ENABLE); 454 455 return 0; 456 } 457 458 459 static int 460 cs4231_ebus_halt_input(void *addr) 461 { 462 struct cs4231_ebus_softc *ebsc; 463 struct cs4231_softc *sc; 464 uint32_t csr; 465 int cfg; 466 467 ebsc = addr; 468 sc = &ebsc->sc_cs4231; 469 sc->sc_capture.t_active = 0; 470 471 csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR); 472 bus_space_write_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR, 473 csr & ~EBDMA_EN_DMA); 474 475 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 476 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 477 cfg & ~CAPTURE_ENABLE); 478 479 return 0; 480 } 481 482 483 static int 484 cs4231_ebus_dma_intr(struct cs_transfer *t, bus_space_tag_t dt, 485 bus_space_handle_t dh, void *sih) 486 { 487 uint32_t csr; 488 #ifdef AUDIO_DEBUG 489 char bits[128]; 490 #endif 491 492 /* read DMA status, clear TC bit by writing it back */ 493 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 494 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr); 495 #ifdef AUDIO_DEBUG 496 snprintb(bits, sizeof(bits), EBUS_DCSR_BITS, csr); 497 DPRINTF(("audiocs: %s dcsr=%s\n", t->t_name, bits)); 498 #endif 499 500 if (csr & EBDMA_ERR_PEND) { 501 ++t->t_ierrcnt.ev_count; 502 printf("audiocs: %s DMA error, resetting\n", t->t_name); 503 cs4231_ebus_dma_reset(dt, dh); 504 /* how to notify audio(9)??? */ 505 return 1; 506 } 507 508 if ((csr & EBDMA_INT_PEND) == 0) 509 return 0; 510 511 ++t->t_intrcnt.ev_count; 512 513 if ((csr & EBDMA_TC) == 0) { /* can this happen? */ 514 printf("audiocs: %s INT_PEND but !TC\n", t->t_name); 515 return 1; 516 } 517 518 if (!t->t_active) 519 return 1; 520 521 cs4231_ebus_dma_advance(t, dt, dh); 522 523 /* call audio(9) framework while DMA is chugging along */ 524 if (t->t_intr != NULL) 525 sparc_softintr_schedule(sih); 526 return 1; 527 } 528 529 530 static int 531 cs4231_ebus_intr(void *arg) 532 { 533 struct cs4231_ebus_softc *ebsc; 534 struct cs4231_softc *sc; 535 int status; 536 int ret; 537 #ifdef AUDIO_DEBUG 538 char bits[128]; 539 #endif 540 541 ebsc = arg; 542 sc = &ebsc->sc_cs4231; 543 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS); 544 545 #ifdef AUDIO_DEBUG 546 if (cs4231_ebus_debug > 1) 547 cs4231_ebus_regdump("audiointr", ebsc); 548 549 snprintb(bits, sizeof(bits), AD_R2_BITS, status); 550 DPRINTF(("%s: status: %s\n", device_xname(&sc->sc_ad1848.sc_dev), 551 bits)); 552 #endif 553 554 if (status & INTERRUPT_STATUS) { 555 #ifdef AUDIO_DEBUG 556 int reason; 557 558 reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS); 559 snprintb(bits, sizeof(bits), CS_I24_BITS, reason); 560 DPRINTF(("%s: i24: %s\n", device_xname(&sc->sc_ad1848.sc_dev), 561 bits)); 562 #endif 563 /* clear interrupt from ad1848 */ 564 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0); 565 } 566 567 ret = 0; 568 569 if (cs4231_ebus_dma_intr(&sc->sc_capture, ebsc->sc_bt, 570 ebsc->sc_cdmareg, ebsc->sc_rint) != 0) 571 { 572 ++sc->sc_intrcnt.ev_count; 573 ret = 1; 574 } 575 576 if (cs4231_ebus_dma_intr(&sc->sc_playback, ebsc->sc_bt, 577 ebsc->sc_pdmareg, ebsc->sc_pint) != 0) 578 { 579 ++sc->sc_intrcnt.ev_count; 580 ret = 1; 581 } 582 583 584 return ret; 585 } 586 587 static int 588 cs4231_ebus_pint(void *cookie) 589 { 590 struct cs4231_softc *sc = cookie; 591 struct cs_transfer *t = &sc->sc_playback; 592 593 KERNEL_LOCK(1, NULL); 594 if (t->t_intr != NULL) 595 (*t->t_intr)(t->t_arg); 596 KERNEL_UNLOCK_ONE(NULL); 597 return 0; 598 } 599 600 static int 601 cs4231_ebus_rint(void *cookie) 602 { 603 struct cs4231_softc *sc = cookie; 604 struct cs_transfer *t = &sc->sc_capture; 605 606 KERNEL_LOCK(1, NULL); 607 if (t->t_intr != NULL) 608 (*t->t_intr)(t->t_arg); 609 KERNEL_UNLOCK_ONE(NULL); 610 return 0; 611 } 612