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