1 /* $NetBSD: cs4231_ebus.c,v 1.19 2005/12/11 12:21:20 christos 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.19 2005/12/11 12:21:20 christos 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, int, 77 const audio_params_t *); 78 static int cs4231_ebus_trigger_output(void *, void *, void *, int, 79 void (*)(void *), void *, 80 const audio_params_t *); 81 static int cs4231_ebus_trigger_input(void *, void *, void *, int, 82 void (*)(void *), void *, 83 const audio_params_t *); 84 static int cs4231_ebus_halt_output(void *); 85 static int cs4231_ebus_halt_input(void *); 86 87 const struct audio_hw_if audiocs_ebus_hw_if = { 88 cs4231_open, 89 cs4231_close, 90 NULL, /* drain */ 91 ad1848_query_encoding, 92 ad1848_set_params, 93 cs4231_ebus_round_blocksize, 94 ad1848_commit_settings, 95 NULL, /* init_output */ 96 NULL, /* init_input */ 97 NULL, /* start_output */ 98 NULL, /* start_input */ 99 cs4231_ebus_halt_output, 100 cs4231_ebus_halt_input, 101 NULL, /* speaker_ctl */ 102 cs4231_getdev, 103 NULL, /* setfd */ 104 cs4231_set_port, 105 cs4231_get_port, 106 cs4231_query_devinfo, 107 cs4231_malloc, 108 cs4231_free, 109 NULL, /* round_buffersize */ 110 NULL, /* mappage */ 111 cs4231_get_props, 112 cs4231_ebus_trigger_output, 113 cs4231_ebus_trigger_input, 114 NULL, /* dev_ioctl */ 115 }; 116 117 #ifdef AUDIO_DEBUG 118 static void cs4231_ebus_regdump(char *, struct cs4231_ebus_softc *); 119 #endif 120 121 static int cs4231_ebus_dma_reset(bus_space_tag_t, bus_space_handle_t); 122 static int cs4231_ebus_trigger_transfer(struct cs4231_softc *, 123 struct cs_transfer *, 124 bus_space_tag_t, bus_space_handle_t, 125 int, void *, void *, int, void (*)(void *), void *, 126 const audio_params_t *); 127 static void cs4231_ebus_dma_advance(struct cs_transfer *, 128 bus_space_tag_t, bus_space_handle_t); 129 static int cs4231_ebus_dma_intr(struct cs_transfer *, 130 bus_space_tag_t, bus_space_handle_t); 131 static int cs4231_ebus_intr(void *); 132 133 134 int 135 cs4231_ebus_match(struct device *parent, struct cfdata *cf, void *aux) 136 { 137 struct ebus_attach_args *ea; 138 139 ea = aux; 140 if (strcmp(ea->ea_name, AUDIOCS_PROM_NAME) == 0) 141 return 1; 142 #ifdef __sparc__ /* XXX: Krups */ 143 if (strcmp(ea->ea_name, "sound") == 0) 144 return 1; 145 #endif 146 147 return 0; 148 } 149 150 151 void 152 cs4231_ebus_attach(struct device *parent, struct device *self, void *aux) 153 { 154 struct cs4231_ebus_softc *ebsc; 155 struct cs4231_softc *sc; 156 struct ebus_attach_args *ea; 157 bus_space_handle_t bh; 158 int i; 159 160 ebsc = (struct cs4231_ebus_softc *)self; 161 sc = &ebsc->sc_cs4231; 162 ea = aux; 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(void *addr, int blk, int mode, 218 const audio_params_t *param) 219 { 220 221 /* we want to use DMA burst size of 16 words */ 222 return blk & -64; 223 } 224 225 226 #ifdef AUDIO_DEBUG 227 static void 228 cs4231_ebus_regdump(char *label, struct cs4231_ebus_softc *ebsc) 229 { 230 /* char bits[128]; */ 231 232 printf("cs4231regdump(%s): regs:", label); 233 /* XXX: dump ebus DMA and aux registers */ 234 ad1848_dump_regs(&ebsc->sc_cs4231.sc_ad1848); 235 } 236 #endif /* AUDIO_DEBUG */ 237 238 239 /* XXX: nothing CS4231-specific in this code... */ 240 static int 241 cs4231_ebus_dma_reset(bus_space_tag_t dt, bus_space_handle_t dh) 242 { 243 u_int32_t csr; 244 int timo; 245 246 /* reset, also clear TC, just in case */ 247 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, EBDMA_RESET | EBDMA_TC); 248 249 for (timo = 50000; timo != 0; --timo) { 250 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 251 if ((csr & (EBDMA_CYC_PEND | EBDMA_DRAIN)) == 0) 252 break; 253 } 254 255 if (timo == 0) { 256 char bits[128]; 257 258 printf("cs4231_ebus_dma_reset: timed out: csr=%s\n", 259 bitmask_snprintf(csr, EBUS_DCSR_BITS, 260 bits, sizeof(bits))); 261 return ETIMEDOUT; 262 } 263 264 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr & ~EBDMA_RESET); 265 return 0; 266 } 267 268 269 static void 270 cs4231_ebus_dma_advance(struct cs_transfer *t, bus_space_tag_t dt, 271 bus_space_handle_t dh) 272 { 273 bus_addr_t dmaaddr; 274 bus_size_t dmasize; 275 276 cs4231_transfer_advance(t, &dmaaddr, &dmasize); 277 278 bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (u_int32_t)dmasize); 279 bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (u_int32_t)dmaaddr); 280 } 281 282 283 /* 284 * Trigger transfer "t" using DMA controller at "dt"/"dh". 285 * "iswrite" defines direction of the transfer. 286 */ 287 static int 288 cs4231_ebus_trigger_transfer( 289 struct cs4231_softc *sc, 290 struct cs_transfer *t, 291 bus_space_tag_t dt, 292 bus_space_handle_t dh, 293 int iswrite, 294 void *start, void *end, 295 int blksize, 296 void (*intr)(void *), 297 void *arg, 298 const audio_params_t *param) 299 { 300 uint32_t csr; 301 bus_addr_t dmaaddr; 302 bus_size_t dmasize; 303 int ret; 304 305 ret = cs4231_transfer_init(sc, t, &dmaaddr, &dmasize, 306 start, end, blksize, intr, arg); 307 if (ret != 0) 308 return ret; 309 310 ret = cs4231_ebus_dma_reset(dt, dh); 311 if (ret != 0) 312 return ret; 313 314 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 315 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, 316 csr | EBDMA_EN_NEXT | (iswrite ? EBDMA_WRITE : 0) 317 | EBDMA_EN_DMA | EBDMA_EN_CNT | EBDMA_INT_EN 318 | EBDMA_BURST_SIZE_16); 319 320 /* first load: propagated to DACR/DBCR */ 321 bus_space_write_4(dt, dh, EBUS_DMAC_DNBR, (uint32_t)dmasize); 322 bus_space_write_4(dt, dh, EBUS_DMAC_DNAR, (uint32_t)dmaaddr); 323 324 /* next load: goes to DNAR/DNBR */ 325 cs4231_ebus_dma_advance(t, dt, dh); 326 327 return 0; 328 } 329 330 331 static int 332 cs4231_ebus_trigger_output(void *addr, void *start, void *end, int blksize, 333 void (*intr)(void *), void *arg, 334 const audio_params_t *param) 335 { 336 struct cs4231_ebus_softc *ebsc; 337 struct cs4231_softc *sc; 338 int cfg, ret; 339 340 ebsc = addr; 341 sc = &ebsc->sc_cs4231; 342 ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_playback, 343 ebsc->sc_bt, ebsc->sc_pdmareg, 344 0, /* iswrite */ 345 start, end, blksize, 346 intr, arg, param); 347 if (ret != 0) 348 return ret; 349 350 ad_write(&sc->sc_ad1848, SP_LOWER_BASE_COUNT, 0xff); 351 ad_write(&sc->sc_ad1848, SP_UPPER_BASE_COUNT, 0xff); 352 353 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 354 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | PLAYBACK_ENABLE); 355 356 return 0; 357 } 358 359 360 static int 361 cs4231_ebus_trigger_input(void *addr, void *start, void *end, int blksize, 362 void (*intr)(void *), void *arg, 363 const audio_params_t *param) 364 { 365 struct cs4231_ebus_softc *ebsc; 366 struct cs4231_softc *sc; 367 int cfg, ret; 368 369 ebsc = addr; 370 sc = &ebsc->sc_cs4231; 371 ret = cs4231_ebus_trigger_transfer(sc, &sc->sc_capture, 372 ebsc->sc_bt, ebsc->sc_cdmareg, 373 1, /* iswrite */ 374 start, end, blksize, 375 intr, arg, param); 376 if (ret != 0) 377 return ret; 378 379 ad_write(&sc->sc_ad1848, CS_LOWER_REC_CNT, 0xff); 380 ad_write(&sc->sc_ad1848, CS_UPPER_REC_CNT, 0xff); 381 382 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 383 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, cfg | CAPTURE_ENABLE); 384 385 return 0; 386 } 387 388 389 static int 390 cs4231_ebus_halt_output(void *addr) 391 { 392 struct cs4231_ebus_softc *ebsc; 393 struct cs4231_softc *sc; 394 u_int32_t csr; 395 int cfg; 396 397 ebsc = addr; 398 sc = &ebsc->sc_cs4231; 399 sc->sc_playback.t_active = 0; 400 401 csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR); 402 bus_space_write_4(ebsc->sc_bt, ebsc->sc_pdmareg, EBUS_DMAC_DCSR, 403 csr & ~EBDMA_EN_DMA); 404 405 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 406 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 407 cfg & ~PLAYBACK_ENABLE); 408 409 return 0; 410 } 411 412 413 static int 414 cs4231_ebus_halt_input(void *addr) 415 { 416 struct cs4231_ebus_softc *ebsc; 417 struct cs4231_softc *sc; 418 uint32_t csr; 419 int cfg; 420 421 ebsc = addr; 422 sc = &ebsc->sc_cs4231; 423 sc->sc_capture.t_active = 0; 424 425 csr = bus_space_read_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR); 426 bus_space_write_4(ebsc->sc_bt, ebsc->sc_cdmareg, EBUS_DMAC_DCSR, 427 csr & ~EBDMA_EN_DMA); 428 429 cfg = ad_read(&sc->sc_ad1848, SP_INTERFACE_CONFIG); 430 ad_write(&sc->sc_ad1848, SP_INTERFACE_CONFIG, 431 cfg & ~CAPTURE_ENABLE); 432 433 return 0; 434 } 435 436 437 static int 438 cs4231_ebus_dma_intr(struct cs_transfer *t, bus_space_tag_t dt, 439 bus_space_handle_t dh) 440 { 441 uint32_t csr; 442 #ifdef AUDIO_DEBUG 443 char bits[128]; 444 #endif 445 446 /* read DMA status, clear TC bit by writing it back */ 447 csr = bus_space_read_4(dt, dh, EBUS_DMAC_DCSR); 448 bus_space_write_4(dt, dh, EBUS_DMAC_DCSR, csr); 449 DPRINTF(("audiocs: %s dcsr=%s\n", t->t_name, 450 bitmask_snprintf(csr, EBUS_DCSR_BITS, bits, sizeof(bits)))); 451 452 if (csr & EBDMA_ERR_PEND) { 453 ++t->t_ierrcnt.ev_count; 454 printf("audiocs: %s DMA error, resetting\n", t->t_name); 455 cs4231_ebus_dma_reset(dt, dh); 456 /* how to notify audio(9)??? */ 457 return 1; 458 } 459 460 if ((csr & EBDMA_INT_PEND) == 0) 461 return 0; 462 463 ++t->t_intrcnt.ev_count; 464 465 if ((csr & EBDMA_TC) == 0) { /* can this happen? */ 466 printf("audiocs: %s INT_PEND but !TC\n", t->t_name); 467 return 1; 468 } 469 470 if (!t->t_active) 471 return 1; 472 473 cs4231_ebus_dma_advance(t, dt, dh); 474 475 /* call audio(9) framework while DMA is chugging along */ 476 if (t->t_intr != NULL) 477 (*t->t_intr)(t->t_arg); 478 return 1; 479 } 480 481 482 static int 483 cs4231_ebus_intr(void *arg) 484 { 485 struct cs4231_ebus_softc *ebsc; 486 struct cs4231_softc *sc; 487 int status; 488 int ret; 489 #ifdef AUDIO_DEBUG 490 char bits[128]; 491 #endif 492 493 ebsc = arg; 494 sc = &ebsc->sc_cs4231; 495 status = ADREAD(&sc->sc_ad1848, AD1848_STATUS); 496 497 #ifdef AUDIO_DEBUG 498 if (cs4231_ebus_debug > 1) 499 cs4231_ebus_regdump("audiointr", ebsc); 500 501 DPRINTF(("%s: status: %s\n", sc->sc_ad1848.sc_dev.dv_xname, 502 bitmask_snprintf(status, AD_R2_BITS, bits, sizeof(bits)))); 503 #endif 504 505 if (status & INTERRUPT_STATUS) { 506 #ifdef AUDIO_DEBUG 507 int reason; 508 509 reason = ad_read(&sc->sc_ad1848, CS_IRQ_STATUS); 510 DPRINTF(("%s: i24: %s\n", sc->sc_ad1848.sc_dev.dv_xname, 511 bitmask_snprintf(reason, CS_I24_BITS, bits, sizeof(bits)))); 512 #endif 513 /* clear interrupt from ad1848 */ 514 ADWRITE(&sc->sc_ad1848, AD1848_STATUS, 0); 515 } 516 517 ret = 0; 518 519 if (cs4231_ebus_dma_intr(&sc->sc_capture, 520 ebsc->sc_bt, ebsc->sc_cdmareg) != 0) 521 { 522 ++sc->sc_intrcnt.ev_count; 523 ret = 1; 524 } 525 526 if (cs4231_ebus_dma_intr(&sc->sc_playback, 527 ebsc->sc_bt, ebsc->sc_pdmareg) != 0) 528 { 529 ++sc->sc_intrcnt.ev_count; 530 ret = 1; 531 } 532 533 return ret; 534 } 535