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