1 /* $NetBSD: cs4231_ebus.c,v 1.39 2019/05/08 13:40:17 isaki 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.39 2019/05/08 13:40:17 isaki 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/cpu.h> 42 #include <sys/kmem.h> 43 #include <sys/malloc.h> 44 45 #include <machine/autoconf.h> 46 47 #include <dev/ebus/ebusreg.h> 48 #include <dev/ebus/ebusvar.h> 49 50 #include <sys/audioio.h> 51 #include <dev/audio/audio_if.h> 52 53 #include <dev/ic/ad1848reg.h> 54 #include <dev/ic/cs4231reg.h> 55 #include <dev/ic/ad1848var.h> 56 #include <dev/ic/cs4231var.h> 57 58 #ifdef AUDIO_DEBUG 59 int cs4231_ebus_debug = 0; 60 #define DPRINTF(x) if (cs4231_ebus_debug) printf x 61 #else 62 #define DPRINTF(x) 63 #endif 64 65 66 struct cs4231_ebus_softc { 67 struct cs4231_softc sc_cs4231; 68 69 void *sc_pint; 70 void *sc_rint; 71 bus_space_tag_t sc_bt; 72 bus_space_handle_t sc_pdmareg; /* playback DMA */ 73 bus_space_handle_t sc_cdmareg; /* record DMA */ 74 }; 75 76 77 void cs4231_ebus_attach(device_t, device_t, void *); 78 int cs4231_ebus_match(device_t, cfdata_t, void *); 79 80 static int cs4231_ebus_pint(void *); 81 static int cs4231_ebus_rint(void *); 82 83 CFATTACH_DECL_NEW(audiocs_ebus, sizeof(struct cs4231_ebus_softc), 84 cs4231_ebus_match, cs4231_ebus_attach, NULL, NULL); 85 86 /* audio_hw_if methods specific to ebus DMA */ 87 static int cs4231_ebus_round_blocksize(void *, int, int, 88 const audio_params_t *); 89 static int cs4231_ebus_trigger_output(void *, void *, void *, int, 90 void (*)(void *), void *, 91 const audio_params_t *); 92 static int cs4231_ebus_trigger_input(void *, void *, void *, int, 93 void (*)(void *), void *, 94 const audio_params_t *); 95 static int cs4231_ebus_halt_output(void *); 96 static int cs4231_ebus_halt_input(void *); 97 98 const struct audio_hw_if audiocs_ebus_hw_if = { 99 .open = cs4231_open, 100 .close = cs4231_close, 101 .query_format = ad1848_query_format, 102 .set_format = ad1848_set_format, 103 .round_blocksize = cs4231_ebus_round_blocksize, 104 .commit_settings = ad1848_commit_settings, 105 .halt_output = cs4231_ebus_halt_output, 106 .halt_input = cs4231_ebus_halt_input, 107 .getdev = cs4231_getdev, 108 .set_port = cs4231_set_port, 109 .get_port = cs4231_get_port, 110 .query_devinfo = cs4231_query_devinfo, 111 .allocm = cs4231_malloc, 112 .freem = cs4231_free, 113 .get_props = cs4231_get_props, 114 .trigger_output = cs4231_ebus_trigger_output, 115 .trigger_input = cs4231_ebus_trigger_input, 116 .get_locks = ad1848_get_locks, 117 }; 118 119 #ifdef AUDIO_DEBUG 120 static void cs4231_ebus_regdump(const char *, struct cs4231_ebus_softc *); 121 #endif 122 123 static int cs4231_ebus_dma_reset(bus_space_tag_t, bus_space_handle_t); 124 static int cs4231_ebus_trigger_transfer(struct cs4231_softc *, 125 struct cs_transfer *, 126 bus_space_tag_t, bus_space_handle_t, 127 int, void *, void *, int, void (*)(void *), void *, 128 const audio_params_t *); 129 static void cs4231_ebus_dma_advance(struct cs_transfer *, 130 bus_space_tag_t, bus_space_handle_t); 131 static int cs4231_ebus_dma_intr(struct cs_transfer *, 132 bus_space_tag_t, bus_space_handle_t, 133 void *); 134 static int cs4231_ebus_intr(void *); 135 136 137 int 138 cs4231_ebus_match(device_t parent, cfdata_t cf, void *aux) 139 { 140 struct ebus_attach_args *ea; 141 char *compat; 142 int len, total_size; 143 144 ea = aux; 145 if (strcmp(ea->ea_name, AUDIOCS_PROM_NAME) == 0) 146 return 1; 147 148 compat = NULL; 149 if (prom_getprop(ea->ea_node, "compatible", 1, &total_size, &compat) == 0) { 150 do { 151 if (strcmp(compat, AUDIOCS_PROM_NAME) == 0) 152 return 1; 153 #ifdef __sparc__ 154 /* on KRUPS compatible lists: "cs4231", "ad1848", 155 * "mwave", and "pnpPNP,b007" */ 156 if (strcmp(compat, "cs4231") == 0) 157 return 1; 158 #endif 159 len = strlen(compat) + 1; 160 total_size -= len; 161 compat += len; 162 } while (total_size > 0); 163 } 164 165 return 0; 166 } 167 168 169 void 170 cs4231_ebus_attach(device_t parent, device_t self, void *aux) 171 { 172 struct cs4231_ebus_softc *ebsc; 173 struct cs4231_softc *sc; 174 struct ebus_attach_args *ea; 175 bus_space_handle_t bh; 176 int i; 177 178 ebsc = device_private(self); 179 sc = &ebsc->sc_cs4231; 180 ea = aux; 181 sc->sc_bustag = ebsc->sc_bt = ea->ea_bustag; 182 sc->sc_dmatag = ea->ea_dmatag; 183 184 ebsc->sc_pint = sparc_softintr_establish(IPL_VM, 185 (void *)cs4231_ebus_pint, sc); 186 ebsc->sc_rint = sparc_softintr_establish(IPL_VM, 187 (void *)cs4231_ebus_rint, sc); 188 189 /* 190 * These are the register we get from the prom: 191 * - CS4231 registers 192 * - Playback EBus DMA controller 193 * - Capture EBus DMA controller 194 * - AUXIO audio register (codec powerdown) 195 * 196 * Map my registers in, if they aren't already in virtual 197 * address space. 198 */ 199 if (bus_space_map(ea->ea_bustag, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 200 ea->ea_reg[0].size, 0, &bh) != 0) { 201 printf(": unable to map registers\n"); 202 return; 203 } 204 205 if (bus_space_map(ea->ea_bustag, 206 #ifdef MSIIEP /* XXX: Krups */ 207 /* 208 * XXX: map playback DMA registers 209 * (we just know where they are) 210 */ 211 BUS_ADDR(0x14, 0x702000), /* XXX: magic num */ 212 EBUS_DMAC_SIZE, 213 #else 214 EBUS_ADDR_FROM_REG(&ea->ea_reg[1]), 215 ea->ea_reg[1].size, 216 #endif 217 0, &ebsc->sc_pdmareg) != 0) 218 { 219 printf(": unable to map playback DMA registers\n"); 220 return; 221 } 222 223 if (bus_space_map(ea->ea_bustag, 224 #ifdef MSIIEP /* XXX: Krups */ 225 /* 226 * XXX: map capture DMA registers 227 * (we just know where they are) 228 */ 229 BUS_ADDR(0x14, 0x704000), /* XXX: magic num */ 230 EBUS_DMAC_SIZE, 231 #else 232 EBUS_ADDR_FROM_REG(&ea->ea_reg[2]), 233 ea->ea_reg[2].size, 234 #endif 235 0, &ebsc->sc_cdmareg) != 0) 236 { 237 printf(": unable to map capture DMA registers\n"); 238 return; 239 } 240 241 ad1848_init_locks(&sc->sc_ad1848, IPL_SCHED); 242 243 /* establish interrupt channels */ 244 for (i = 0; i < ea->ea_nintr; ++i) 245 bus_intr_establish(ea->ea_bustag, 246 ea->ea_intr[i], IPL_SCHED, 247 cs4231_ebus_intr, ebsc); 248 249 cs4231_common_attach(sc, self, bh); 250 printf("\n"); 251 252 /* XXX: todo: move to cs4231_common_attach, pass hw_if as arg? */ 253 audio_attach_mi(&audiocs_ebus_hw_if, sc, sc->sc_ad1848.sc_dev); 254 } 255 256 257 static int 258 cs4231_ebus_round_blocksize(void *addr, int blk, int mode, 259 const audio_params_t *param) 260 { 261 int sz; 262 263 /* we want to use DMA burst size of 16 words */ 264 sz = blk & -64; 265 if (sz == 0) 266 sz = 64; /* zero is not a good blocksize */ 267 return sz; 268 } 269 270 271 #ifdef AUDIO_DEBUG 272 static void 273 cs4231_ebus_regdump(const char *label, struct cs4231_ebus_softc *ebsc) 274 { 275 /* char bits[128]; */ 276 277 printf("cs4231regdump(%s): regs:", label); 278 /* XXX: dump ebus DMA and aux registers */ 279 ad1848_dump_regs(&ebsc->sc_cs4231.sc_ad1848); 280 } 281 #endif /* AUDIO_DEBUG */ 282 283 284 /* XXX: nothing CS4231-specific in this code... */ 285 static int 286 cs4231_ebus_dma_reset(bus_space_tag_t dt, bus_space_handle_t dh) 287 { 288 u_int32_t csr; 289 int timo; 290 291 /* reset, also clear TC, just in case */ 292 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, EBDMA_RESET | EBDMA_TC); 293 294 for (timo = 50000; timo != 0; --timo) { 295 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 296 if ((csr & (EBDMA_CYC_PEND | EBDMA_DRAIN)) == 0) 297 break; 298 } 299 300 if (timo == 0) { 301 char bits[128]; 302 snprintb(bits, sizeof(bits), EBUS_DCSR_BITS, csr); 303 printf("cs4231_ebus_dma_reset: timed out: csr=%s\n", bits); 304 return ETIMEDOUT; 305 } 306 307 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr & ~EBDMA_RESET); 308 return 0; 309 } 310 311 312 static void 313 cs4231_ebus_dma_advance(struct cs_transfer *t, bus_space_tag_t dt, 314 bus_space_handle_t dh) 315 { 316 bus_addr_t dmaaddr; 317 bus_size_t dmasize; 318 319 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 320 321 bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (u_int32_t)dmasize); 322 bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (u_int32_t)dmaaddr); 323 } 324 325 326 /* 327 * Trigger transfer "t" using DMA controller at "dt"/"dh". 328 * "iswrite" defines direction of the transfer. 329 */ 330 static int 331 cs4231_ebus_trigger_transfer( 332 struct cs4231_softc *sc, 333 struct cs_transfer *t, 334 bus_space_tag_t dt, 335 bus_space_handle_t dh, 336 int iswrite, 337 void *start, void *end, 338 int blksize, 339 void (*intr)(void *), 340 void *arg, 341 const audio_params_t *param) 342 { 343 uint32_t csr; 344 bus_addr_t dmaaddr; 345 bus_size_t dmasize; 346 int ret; 347 348 ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize, 349 start, end, blksize, intr, arg); 350 if (ret != 0) 351 return ret; 352 353 ret = cs4231_ebus_dma_reset(dt, dh); 354 if (ret != 0) 355 return ret; 356 357 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 358 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, 359 csr | EBDMA_EN_NEXT | (iswrite ? EBDMA_WRITE : 0) 360 | EBDMA_EN_DMA | EBDMA_EN_CNT | EBDMA_INT_EN 361 | EBDMA_BURST_SIZE_16); 362 363 /* first load: propagated to DACR/DBCR */ 364 bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (uint32_t)dmasize); 365 bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (uint32_t)dmaaddr); 366 367 /* next load: goes to DNAR/DNBR */ 368 cs4231_ebus_dma_advance(t, dt, dh); 369 370 return 0; 371 } 372 373 374 static int 375 cs4231_ebus_trigger_output(void *addr, void *start, void *end, int blksize, 376 void (*intr)(void *), void *arg, 377 const audio_params_t *param) 378 { 379 struct cs4231_ebus_softc *ebsc; 380 struct cs4231_softc *sc; 381 int cfg, ret; 382 383 ebsc = addr; 384 sc = &ebsc->sc_cs4231; 385 ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_playback, 386 ebsc->sc_bt, ebsc->sc_pdmareg, 387 0, /* iswrite */ 388 start, end, blksize, 389 intr, arg, param); 390 if (ret != 0) 391 return ret; 392 393 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 394 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 395 396 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 397 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | PLAYBACK_ENABLE); 398 399 return 0; 400 } 401 402 403 static int 404 cs4231_ebus_trigger_input(void *addr, void *start, void *end, int blksize, 405 void (*intr)(void *), void *arg, 406 const audio_params_t *param) 407 { 408 struct cs4231_ebus_softc *ebsc; 409 struct cs4231_softc *sc; 410 int cfg, ret; 411 412 ebsc = addr; 413 sc = &ebsc->sc_cs4231; 414 ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_capture, 415 ebsc->sc_bt, ebsc->sc_cdmareg, 416 1, /* iswrite */ 417 start, end, blksize, 418 intr, arg, param); 419 if (ret != 0) 420 return ret; 421 422 ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff); 423 ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff); 424 425 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 426 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | CAPTURE_ENABLE); 427 428 return 0; 429 } 430 431 432 static int 433 cs4231_ebus_halt_output(void *addr) 434 { 435 struct cs4231_ebus_softc *ebsc; 436 struct cs4231_softc *sc; 437 u_int32_t csr; 438 int cfg; 439 440 ebsc = addr; 441 sc = &ebsc->sc_cs4231; 442 sc->sc_playback.t_active = 0; 443 444 csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR); 445 bus_space_write_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR, 446 csr & ~EBDMA_EN_DMA); 447 448 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 449 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 450 cfg & ~PLAYBACK_ENABLE); 451 452 return 0; 453 } 454 455 456 static int 457 cs4231_ebus_halt_input(void *addr) 458 { 459 struct cs4231_ebus_softc *ebsc; 460 struct cs4231_softc *sc; 461 uint32_t csr; 462 int cfg; 463 464 ebsc = addr; 465 sc = &ebsc->sc_cs4231; 466 sc->sc_capture.t_active = 0; 467 468 csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR); 469 bus_space_write_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR, 470 csr & ~EBDMA_EN_DMA); 471 472 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 473 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 474 cfg & ~CAPTURE_ENABLE); 475 476 return 0; 477 } 478 479 480 static int 481 cs4231_ebus_dma_intr(struct cs_transfer *t, bus_space_tag_t dt, 482 bus_space_handle_t dh, void *sih) 483 { 484 uint32_t csr; 485 #ifdef AUDIO_DEBUG 486 char bits[128]; 487 #endif 488 489 /* read DMA status, clear TC bit by writing it back */ 490 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 491 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr); 492 #ifdef AUDIO_DEBUG 493 snprintb(bits, sizeof(bits), EBUS_DCSR_BITS, csr); 494 DPRINTF(("audiocs: %s dcsr=%s\n", t->t_name, bits)); 495 #endif 496 497 if (csr & EBDMA_ERR_PEND) { 498 ++t->t_ierrcnt.ev_count; 499 printf("audiocs: %s DMA error, resetting\n", t->t_name); 500 cs4231_ebus_dma_reset(dt, dh); 501 /* how to notify audio(9)??? */ 502 return 1; 503 } 504 505 if ((csr & EBDMA_INT_PEND) == 0) 506 return 0; 507 508 ++t->t_intrcnt.ev_count; 509 510 if ((csr & EBDMA_TC) == 0) { /* can this happen? */ 511 printf("audiocs: %s INT_PEND but !TC\n", t->t_name); 512 return 1; 513 } 514 515 if (!t->t_active) 516 return 1; 517 518 cs4231_ebus_dma_advance(t, dt, dh); 519 520 /* call audio(9) framework while DMA is chugging along */ 521 if (t->t_intr != NULL) 522 sparc_softintr_schedule(sih); 523 return 1; 524 } 525 526 527 static int 528 cs4231_ebus_intr(void *arg) 529 { 530 struct cs4231_ebus_softc *ebsc; 531 struct cs4231_softc *sc; 532 int status; 533 int ret; 534 #ifdef AUDIO_DEBUG 535 char bits[128]; 536 #endif 537 538 ebsc = arg; 539 sc = &ebsc->sc_cs4231; 540 mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock); 541 542 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS); 543 544 #ifdef AUDIO_DEBUG 545 if (cs4231_ebus_debug > 1) 546 cs4231_ebus_regdump("audiointr", ebsc); 547 548 snprintb(bits, sizeof(bits), AD_R2_BITS, status); 549 DPRINTF(("%s: status: %s\n", device_xname(sc->sc_ad1848.sc_dev), 550 bits)); 551 #endif 552 553 if (status & INTERRUPT_STATUS) { 554 #ifdef AUDIO_DEBUG 555 int reason; 556 557 reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS); 558 snprintb(bits, sizeof(bits), CS_I24_BITS, reason); 559 DPRINTF(("%s: i24: %s\n", device_xname(sc->sc_ad1848.sc_dev), 560 bits)); 561 #endif 562 /* clear interrupt from ad1848 */ 563 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0); 564 } 565 566 ret = 0; 567 568 if (cs4231_ebus_dma_intr(&sc->sc_capture, ebsc->sc_bt, 569 ebsc->sc_cdmareg, ebsc->sc_rint) != 0) 570 { 571 ++sc->sc_intrcnt.ev_count; 572 ret = 1; 573 } 574 575 if (cs4231_ebus_dma_intr(&sc->sc_playback, ebsc->sc_bt, 576 ebsc->sc_pdmareg, ebsc->sc_pint) != 0) 577 { 578 ++sc->sc_intrcnt.ev_count; 579 ret = 1; 580 } 581 582 mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock); 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 mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock); 594 if (t->t_intr != NULL) 595 (*t->t_intr)(t->t_arg); 596 mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock); 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 mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock); 607 if (t->t_intr != NULL) 608 (*t->t_intr)(t->t_arg); 609 mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock); 610 return 0; 611 } 612