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 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 .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 120static void cs4231_ebus_regdump(const char *, struct cs4231_ebus_softc *); 121#endif 122 123static int cs4231_ebus_dma_reset(bus_space_tag_t, bus_space_handle_t); 124static 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 *); 129static void cs4231_ebus_dma_advance(struct cs_transfer *, 130 bus_space_tag_t, bus_space_handle_t); 131static int cs4231_ebus_dma_intr(struct cs_transfer *, 132 bus_space_tag_t, bus_space_handle_t, 133 void *); 134static int cs4231_ebus_intr(void *); 135 136 137int 138cs4231_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 169void 170cs4231_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 257static int 258cs4231_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 272static void 273cs4231_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... */ 285static int 286cs4231_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 312static void 313cs4231_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 */ 330static int 331cs4231_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 374static int 375cs4231_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 403static int 404cs4231_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 432static int 433cs4231_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 456static int 457cs4231_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 480static int 481cs4231_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 527static int 528cs4231_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 587static int 588cs4231_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 600static int 601cs4231_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