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