1/* $NetBSD$ */ 2 3/*- 4 * Copyright (c) 1998, 1999, 2002, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Kranenburg. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD$"); 34 35#include "audio.h" 36#if NAUDIO > 0 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/errno.h> 41#include <sys/device.h> 42#include <sys/malloc.h> 43#include <sys/bus.h> 44#include <sys/intr.h> 45 46#include <dev/sbus/sbusvar.h> 47 48#include <sys/audioio.h> 49#include <dev/audio_if.h> 50 51#include <dev/ic/ad1848reg.h> 52#include <dev/ic/cs4231reg.h> 53#include <dev/ic/ad1848var.h> 54#include <dev/ic/cs4231var.h> 55 56#include <dev/ic/apcdmareg.h> 57 58#ifdef AUDIO_DEBUG 59int cs4231_sbus_debug = 0; 60#define DPRINTF(x) if (cs4231_sbus_debug) printf x 61#else 62#define DPRINTF(x) 63#endif 64 65/* where APC DMA registers are located */ 66#define CS4231_APCDMA_OFFSET 16 67 68/* interrupt enable bits except those specific for playback/capture */ 69#define APC_ENABLE (APC_EI | APC_IE | APC_EIE) 70 71struct cs4231_sbus_softc { 72 struct cs4231_softc sc_cs4231; 73 74 void *sc_pint; 75 void *sc_rint; 76 bus_space_tag_t sc_bt; /* DMA controller tag */ 77 bus_space_handle_t sc_bh; /* DMA controller registers */ 78}; 79 80 81static int cs4231_sbus_match(device_t, cfdata_t, void *); 82static void cs4231_sbus_attach(device_t, device_t, void *); 83static int cs4231_sbus_pint(void *); 84static int cs4231_sbus_rint(void *); 85 86CFATTACH_DECL_NEW(audiocs_sbus, sizeof(struct cs4231_sbus_softc), 87 cs4231_sbus_match, cs4231_sbus_attach, NULL, NULL); 88 89/* audio_hw_if methods specific to apc DMA */ 90static int cs4231_sbus_trigger_output(void *, void *, void *, int, 91 void (*)(void *), void *, 92 const audio_params_t *); 93static int cs4231_sbus_trigger_input(void *, void *, void *, int, 94 void (*)(void *), void *, 95 const audio_params_t *); 96static int cs4231_sbus_halt_output(void *); 97static int cs4231_sbus_halt_input(void *); 98 99const struct audio_hw_if audiocs_sbus_hw_if = { 100 cs4231_open, 101 cs4231_close, 102 NULL, /* drain */ 103 ad1848_query_encoding, 104 ad1848_set_params, 105 NULL, /* round_blocksize */ 106 ad1848_commit_settings, 107 NULL, /* init_output */ 108 NULL, /* init_input */ 109 NULL, /* start_output */ 110 NULL, /* start_input */ 111 cs4231_sbus_halt_output, 112 cs4231_sbus_halt_input, 113 NULL, /* speaker_ctl */ 114 cs4231_getdev, 115 NULL, /* setfd */ 116 cs4231_set_port, 117 cs4231_get_port, 118 cs4231_query_devinfo, 119 cs4231_malloc, 120 cs4231_free, 121 NULL, /* round_buffersize */ 122 NULL, /* mappage */ 123 cs4231_get_props, 124 cs4231_sbus_trigger_output, 125 cs4231_sbus_trigger_input, 126 NULL, /* dev_ioctl */ 127 ad1848_get_locks, 128}; 129 130 131#ifdef AUDIO_DEBUG 132static void cs4231_sbus_regdump(char *, struct cs4231_sbus_softc *); 133#endif 134 135static int cs4231_sbus_intr(void *); 136 137 138 139static int 140cs4231_sbus_match(device_t parent, cfdata_t cf, void *aux) 141{ 142 struct sbus_attach_args *sa; 143 144 sa = aux; 145 return strcmp(sa->sa_name, AUDIOCS_PROM_NAME) == 0; 146} 147 148 149static void 150cs4231_sbus_attach(device_t parent, device_t self, void *aux) 151{ 152 struct cs4231_sbus_softc *sbsc; 153 struct cs4231_softc *sc; 154 struct sbus_attach_args *sa; 155 bus_space_handle_t bh; 156 157 sbsc = device_private(self); 158 sc = &sbsc->sc_cs4231; 159 sa = aux; 160 sbsc->sc_bt = sc->sc_bustag = sa->sa_bustag; 161 sc->sc_dmatag = sa->sa_dmatag; 162 163 sbsc->sc_pint = sparc_softintr_establish(IPL_SCHED, 164 (void *)cs4231_sbus_pint, sc); 165 sbsc->sc_rint = sparc_softintr_establish(IPL_SCHED, 166 (void *)cs4231_sbus_rint, sc); 167 168 /* 169 * Map my registers in, if they aren't already in virtual 170 * address space. 171 */ 172 if (sa->sa_npromvaddrs) { 173 sbus_promaddr_to_handle(sa->sa_bustag, 174 sa->sa_promvaddrs[0], &bh); 175 } else { 176 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 177 sa->sa_offset, sa->sa_size, 0, &bh) != 0) { 178 aprint_error("%s @ sbus: cannot map registers\n", 179 device_xname(self)); 180 return; 181 } 182 } 183 184 bus_space_subregion(sa->sa_bustag, bh, CS4231_APCDMA_OFFSET, 185 APC_DMA_SIZE, &sbsc->sc_bh); 186 187 cs4231_common_attach(sc, self, bh); 188 printf("\n"); 189 190 ad1848_init_locks(&sc->sc_ad1848, IPL_SCHED); 191 /* Establish interrupt channel */ 192 if (sa->sa_nintr) 193 bus_intr_establish(sa->sa_bustag, 194 sa->sa_pri, IPL_SCHED, 195 cs4231_sbus_intr, sbsc); 196 197 audio_attach_mi(&audiocs_sbus_hw_if, sbsc, self); 198} 199 200 201#ifdef AUDIO_DEBUG 202static void 203cs4231_sbus_regdump(char *label, struct cs4231_sbus_softc *sc) 204{ 205 char bits[128]; 206 207 printf("cs4231regdump(%s): regs:", label); 208 printf("dmapva: 0x%x; ", 209 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PVA)); 210 printf("dmapc: 0x%x; ", 211 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PC)); 212 printf("dmapnva: 0x%x; ", 213 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PNVA)); 214 printf("dmapnc: 0x%x\n", 215 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_PNC)); 216 printf("dmacva: 0x%x; ", 217 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CVA)); 218 printf("dmacc: 0x%x; ", 219 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CC)); 220 printf("dmacnva: 0x%x; ", 221 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CNVA)); 222 printf("dmacnc: 0x%x\n", 223 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CNC)); 224 225 snprintb(bits, sizeof(bits), APC_BITS, 226 bus_space_read_4(sc->sc_bh, sc->sc_bh, APC_DMA_CSR)); 227 printf("apc_dmacsr=%s\n", bits); 228 229 ad1848_dump_regs(&sc->sc_cs4231.sc_ad1848); 230} 231#endif /* AUDIO_DEBUG */ 232 233 234static int 235cs4231_sbus_trigger_output(void *addr, void *start, void *end, int blksize, 236 void (*intr)(void *), void *arg, 237 const audio_params_t *param) 238{ 239 struct cs4231_sbus_softc *sbsc; 240 struct cs4231_softc *sc; 241 struct cs_transfer *t; 242 uint32_t csr; 243 bus_addr_t dmaaddr; 244 bus_size_t dmasize; 245 int ret; 246#ifdef AUDIO_DEBUG 247 char bits[128]; 248#endif 249 250 sbsc = addr; 251 sc = &sbsc->sc_cs4231; 252 t = &sc->sc_playback; 253 ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize, 254 start, end, blksize, intr, arg); 255 if (ret != 0) 256 return ret; 257 258 DPRINTF(("trigger_output: was: %x %d, %x %d\n", 259 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA), 260 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC), 261 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA), 262 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC))); 263 264 /* load first block */ 265 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr); 266 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize); 267 268 DPRINTF(("trigger_output: 1st: %x %d, %x %d\n", 269 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA), 270 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC), 271 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA), 272 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC))); 273 274 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 275#ifdef AUDIO_DEBUG 276 snprintb(bits, sizeof(bits), APC_BITS, csr); 277#endif 278 DPRINTF(("trigger_output: csr=%s\n", bits)); 279 if ((csr & PDMA_GO) == 0 || (csr & APC_PPAUSE) != 0) { 280 int cfg; 281 282 csr &= ~(APC_PPAUSE | APC_PMIE | APC_INTR_MASK); 283 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 284 285 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 286 csr &= ~APC_INTR_MASK; 287 csr |= APC_ENABLE | APC_PIE | APC_PMIE | PDMA_GO; 288 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 289 290 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 291 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 292 293 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 294 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 295 (cfg | PLAYBACK_ENABLE)); 296 } else { 297#ifdef AUDIO_DEBUG 298 snprintb(bits, sizeof(bits), APC_BITS, csr); 299#endif 300 DPRINTF(("trigger_output: already: csr=%s\n", bits)); 301 302 } 303 304 /* load next block if we can */ 305 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 306 if (csr & APC_PD) { 307 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 308 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA, dmaaddr); 309 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC, dmasize); 310 311 DPRINTF(("trigger_output: 2nd: %x %d, %x %d\n", 312 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PVA), 313 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PC), 314 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNVA), 315 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_PNC))); 316 } 317 318 return 0; 319} 320 321 322static int 323cs4231_sbus_halt_output(void *addr) 324{ 325 struct cs4231_sbus_softc *sbsc; 326 struct cs4231_softc *sc; 327 uint32_t csr; 328 int cfg; 329#ifdef AUDIO_DEBUG 330 char bits[128]; 331#endif 332 333 sbsc = addr; 334 sc = &sbsc->sc_cs4231; 335 sc->sc_playback.t_active = 0; 336 337 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 338#ifdef AUDIO_DEBUG 339 snprintb(bits, sizeof(bits), APC_BITS, csr); 340#endif 341 DPRINTF(("halt_output: csr=%s\n", bits)); 342 343 csr &= ~APC_INTR_MASK; /* do not clear interrupts accidentally */ 344 csr |= APC_PPAUSE; /* pause playback (let current complete) */ 345 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 346 347 /* let the curernt transfer complete */ 348 if (csr & PDMA_GO) 349 do { 350 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, 351 APC_DMA_CSR); 352#ifdef AUDIO_DEBUG 353 snprintb(bits, sizeof(bits), APC_BITS, csr); 354#endif 355 DPRINTF(("halt_output: csr=%s\n", bits)); 356 } while ((csr & APC_PM) == 0); 357 358 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 359 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG,(cfg & ~PLAYBACK_ENABLE)); 360 361 return 0; 362} 363 364 365/* NB: we don't enable APC_CMIE and won't use APC_CM */ 366static int 367cs4231_sbus_trigger_input(void *addr, void *start, void *end, int blksize, 368 void (*intr)(void *), void *arg, 369 const audio_params_t *param) 370{ 371 struct cs4231_sbus_softc *sbsc; 372 struct cs4231_softc *sc; 373 struct cs_transfer *t; 374 uint32_t csr; 375 bus_addr_t dmaaddr; 376 bus_size_t dmasize; 377 int ret; 378#ifdef AUDIO_DEBUG 379 char bits[128]; 380#endif 381 382 sbsc = addr; 383 sc = &sbsc->sc_cs4231; 384 t = &sc->sc_capture; 385 ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize, 386 start, end, blksize, intr, arg); 387 if (ret != 0) 388 return ret; 389 390 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 391#ifdef AUDIO_DEBUG 392 snprintb(bits, sizeof(bits), APC_BITS, csr); 393#endif 394 DPRINTF(("trigger_input: csr=%s\n", bits)); 395 DPRINTF(("trigger_input: was: %x %d, %x %d\n", 396 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA), 397 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC), 398 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA), 399 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC))); 400 401 /* supply first block */ 402 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr); 403 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize); 404 405 DPRINTF(("trigger_input: 1st: %x %d, %x %d\n", 406 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA), 407 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC), 408 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA), 409 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC))); 410 411 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 412 if ((csr & CDMA_GO) == 0 || (csr & APC_CPAUSE) != 0) { 413 int cfg; 414 415 csr &= ~(APC_CPAUSE | APC_CMIE | APC_INTR_MASK); 416 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 417 418 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 419 csr &= ~APC_INTR_MASK; 420 csr |= APC_ENABLE | APC_CIE | CDMA_GO; 421 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 422 423 ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff); 424 ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff); 425 426 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 427 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 428 (cfg | CAPTURE_ENABLE)); 429 } else { 430#ifdef AUDIO_DEBUG 431 snprintb(bits, sizeof(bits), APC_BITS, csr); 432#endif 433 DPRINTF(("trigger_input: already: csr=%s\n", bits)); 434 } 435 436 /* supply next block if we can */ 437 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 438 if (csr & APC_CD) { 439 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 440 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA, dmaaddr); 441 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC, dmasize); 442 DPRINTF(("trigger_input: 2nd: %x %d, %x %d\n", 443 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CVA), 444 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CC), 445 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNVA), 446 bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CNC))); 447 } 448 449 return 0; 450} 451 452 453static int 454cs4231_sbus_halt_input(void *addr) 455{ 456 struct cs4231_sbus_softc *sbsc; 457 struct cs4231_softc *sc; 458 uint32_t csr; 459 int cfg; 460#ifdef AUDIO_DEBUG 461 char bits[128]; 462#endif 463 464 sbsc = addr; 465 sc = &sbsc->sc_cs4231; 466 sc->sc_capture.t_active = 0; 467 468 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 469#ifdef AUDIO_DEBUG 470 snprintb(bits, sizeof(bits), APC_BITS, csr); 471#endif 472 DPRINTF(("halt_input: csr=%s\n", bits)); 473 474 475 csr &= ~APC_INTR_MASK; /* do not clear interrupts accidentally */ 476 csr |= APC_CPAUSE; 477 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 478 479 /* let the curernt transfer complete */ 480 if (csr & CDMA_GO) 481 do { 482 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, 483 APC_DMA_CSR); 484#ifdef AUDIO_DEBUG 485 snprintb(bits, sizeof(bits), APC_BITS, csr); 486#endif 487 DPRINTF(("halt_input: csr=%s\n", bits)); 488 489 490 } while ((csr & APC_CM) == 0); 491 492 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 493 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, (cfg & ~CAPTURE_ENABLE)); 494 495 return 0; 496} 497 498 499static int 500cs4231_sbus_intr(void *arg) 501{ 502 struct cs4231_sbus_softc *sbsc; 503 struct cs4231_softc *sc; 504 uint32_t csr; 505 int status; 506 bus_addr_t dmaaddr; 507 bus_size_t dmasize; 508 int served; 509#if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC) 510 char bits[128]; 511#endif 512 513 sbsc = arg; 514 sc = &sbsc->sc_cs4231; 515 csr = bus_space_read_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR); 516 if ((csr & APC_INTR_MASK) == 0) /* any interrupt pedning? */ 517 return 0; 518 519 mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock); 520 521 /* write back DMA status to clear interrupt */ 522 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, APC_DMA_CSR, csr); 523 ++sc->sc_intrcnt.ev_count; 524 served = 0; 525 526#ifdef AUDIO_DEBUG 527 if (cs4231_sbus_debug > 1) 528 cs4231_sbus_regdump("audiointr", sbsc); 529#endif 530 531 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS); 532#ifdef AUDIO_DEBUG 533 snprintb(bits, sizeof(bits), AD_R2_BITS, status); 534#endif 535 DPRINTF(("%s: status: %s\n", device_xname(sc->sc_ad1848.sc_dev), 536 bits)); 537 if (status & INTERRUPT_STATUS) { 538#ifdef AUDIO_DEBUG 539 int reason; 540 541 reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS); 542 snprintb(bits, sizeof(bits), CS_I24_BITS, reason); 543 DPRINTF(("%s: i24: %s\n", device_xname(sc->sc_ad1848.sc_dev), 544 bits)); 545#endif 546 /* clear ad1848 interrupt */ 547 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0); 548 } 549 550 if (csr & APC_CI) { 551 if (csr & APC_CD) { /* can supply new block */ 552 struct cs_transfer *t = &sc->sc_capture; 553 554 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 555 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, 556 APC_DMA_CNVA, dmaaddr); 557 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, 558 APC_DMA_CNC, dmasize); 559 560 if (t->t_intr != NULL) 561 sparc_softintr_schedule(sbsc->sc_rint); 562 ++t->t_intrcnt.ev_count; 563 served = 1; 564 } 565 } 566 567 if (csr & APC_PMI) { 568 if (!sc->sc_playback.t_active) 569 served = 1; /* draining in halt_output() */ 570 } 571 572 if (csr & APC_PI) { 573 if (csr & APC_PD) { /* can load new block */ 574 struct cs_transfer *t = &sc->sc_playback; 575 576 if (t->t_active) { 577 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 578 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, 579 APC_DMA_PNVA, dmaaddr); 580 bus_space_write_4(sbsc->sc_bt, sbsc->sc_bh, 581 APC_DMA_PNC, dmasize); 582 } 583 584 if (t->t_intr != NULL) 585 sparc_softintr_schedule(sbsc->sc_pint); 586 ++t->t_intrcnt.ev_count; 587 served = 1; 588 } 589 } 590 591 /* got an interrupt we don't know how to handle */ 592 if (!served) { 593#ifdef DIAGNOSTIC 594 snprintb(bits, sizeof(bits), APC_BITS, csr); 595 printf("%s: unhandled csr=%s\n", 596 device_xname(sc->sc_ad1848.sc_dev), bits); 597#endif 598 /* evcnt? */ 599 } 600 601 mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock); 602 603 return 1; 604} 605 606static int 607cs4231_sbus_pint(void *cookie) 608{ 609 struct cs4231_softc *sc = cookie; 610 struct cs_transfer *t; 611 612 mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock); 613 t = &sc->sc_playback; 614 if (t->t_intr != NULL) 615 (*t->t_intr)(t->t_arg); 616 mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock); 617 return 0; 618} 619 620static int 621cs4231_sbus_rint(void *cookie) 622{ 623 struct cs4231_softc *sc = cookie; 624 struct cs_transfer *t; 625 626 mutex_spin_enter(&sc->sc_ad1848.sc_intr_lock); 627 t = &sc->sc_capture; 628 if (t->t_intr != NULL) 629 (*t->t_intr)(t->t_arg); 630 mutex_spin_exit(&sc->sc_ad1848.sc_intr_lock); 631 return 0; 632} 633 634#endif /* NAUDIO > 0 */ 635