1 /*- 2 * Copyright 2008 by Marco Trillo. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 20 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 /* 29 * Apple DAVbus audio controller. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/kernel.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/module.h> 39 #include <sys/mutex.h> 40 #include <sys/rman.h> 41 42 #include <dev/ofw/ofw_bus.h> 43 44 #ifdef HAVE_KERNEL_OPTION_HEADERS 45 #include "opt_snd.h" 46 #endif 47 48 #include <dev/sound/pcm/sound.h> 49 50 #include <dev/sound/macio/aoa.h> 51 #include <dev/sound/macio/davbusreg.h> 52 53 #include <machine/intr_machdep.h> 54 #include <machine/resource.h> 55 #include <machine/bus.h> 56 57 #include "mixer_if.h" 58 59 struct davbus_softc { 60 struct aoa_softc aoa; 61 phandle_t node; 62 phandle_t soundnode; 63 struct resource *reg; 64 struct mtx mutex; 65 int device_id; 66 u_int output_mask; 67 u_int (*read_status)(struct davbus_softc *, u_int); 68 void (*set_outputs)(struct davbus_softc *, u_int); 69 }; 70 71 static int davbus_probe(device_t); 72 static int davbus_attach(device_t); 73 static void davbus_cint(void *); 74 75 static device_method_t pcm_davbus_methods[] = { 76 /* Device interface. */ 77 DEVMETHOD(device_probe, davbus_probe), 78 DEVMETHOD(device_attach, davbus_attach), 79 80 { 0, 0 } 81 }; 82 83 static driver_t pcm_davbus_driver = { 84 "pcm", 85 pcm_davbus_methods, 86 PCM_SOFTC_SIZE 87 }; 88 89 DRIVER_MODULE(pcm_davbus, macio, pcm_davbus_driver, pcm_devclass, 0, 0); 90 MODULE_DEPEND(pcm_davbus, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 91 92 /***************************************************************************** 93 Probe and attachment routines. 94 *****************************************************************************/ 95 static int 96 davbus_probe(device_t self) 97 { 98 const char *name; 99 100 name = ofw_bus_get_name(self); 101 if (!name) 102 return (ENXIO); 103 104 if (strcmp(name, "davbus") != 0) 105 return (ENXIO); 106 107 device_set_desc(self, "Apple DAVBus Audio Controller"); 108 109 return (0); 110 } 111 112 /* 113 * Burgundy codec control 114 */ 115 116 static int burgundy_init(struct snd_mixer *m); 117 static int burgundy_uninit(struct snd_mixer *m); 118 static int burgundy_reinit(struct snd_mixer *m); 119 static void burgundy_write_locked(struct davbus_softc *, u_int, u_int); 120 static void burgundy_set_outputs(struct davbus_softc *d, u_int mask); 121 static u_int burgundy_read_status(struct davbus_softc *d, u_int status); 122 static int burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left, 123 unsigned right); 124 static u_int32_t burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src); 125 126 static kobj_method_t burgundy_mixer_methods[] = { 127 KOBJMETHOD(mixer_init, burgundy_init), 128 KOBJMETHOD(mixer_uninit, burgundy_uninit), 129 KOBJMETHOD(mixer_reinit, burgundy_reinit), 130 KOBJMETHOD(mixer_set, burgundy_set), 131 KOBJMETHOD(mixer_setrecsrc, burgundy_setrecsrc), 132 KOBJMETHOD_END 133 }; 134 135 MIXER_DECLARE(burgundy_mixer); 136 137 static int 138 burgundy_init(struct snd_mixer *m) 139 { 140 struct davbus_softc *d; 141 142 d = mix_getdevinfo(m); 143 144 d->read_status = burgundy_read_status; 145 d->set_outputs = burgundy_set_outputs; 146 147 /* 148 * We configure the Burgundy codec as follows: 149 * 150 * o Input subframe 0 is connected to input digital 151 * stream A (ISA). 152 * o Stream A (ISA) is mixed in mixer 2 (MIX2). 153 * o Output of mixer 2 (MIX2) is routed to output sources 154 * OS0 and OS1 which can be converted to analog. 155 * 156 */ 157 mtx_lock(&d->mutex); 158 159 burgundy_write_locked(d, 0x16700, 0x40); 160 161 burgundy_write_locked(d, BURGUNDY_MIX0_REG, 0); 162 burgundy_write_locked(d, BURGUNDY_MIX1_REG, 0); 163 burgundy_write_locked(d, BURGUNDY_MIX2_REG, BURGUNDY_MIX_ISA); 164 burgundy_write_locked(d, BURGUNDY_MIX3_REG, 0); 165 166 burgundy_write_locked(d, BURGUNDY_OS_REG, BURGUNDY_OS0_MIX2 | 167 BURGUNDY_OS1_MIX2); 168 169 burgundy_write_locked(d, BURGUNDY_SDIN_REG, BURGUNDY_ISA_SF0); 170 171 /* Set several digital scalers to unity gain. */ 172 burgundy_write_locked(d, BURGUNDY_MXS2L_REG, BURGUNDY_MXS_UNITY); 173 burgundy_write_locked(d, BURGUNDY_MXS2R_REG, BURGUNDY_MXS_UNITY); 174 burgundy_write_locked(d, BURGUNDY_OSS0L_REG, BURGUNDY_OSS_UNITY); 175 burgundy_write_locked(d, BURGUNDY_OSS0R_REG, BURGUNDY_OSS_UNITY); 176 burgundy_write_locked(d, BURGUNDY_OSS1L_REG, BURGUNDY_OSS_UNITY); 177 burgundy_write_locked(d, BURGUNDY_OSS1R_REG, BURGUNDY_OSS_UNITY); 178 burgundy_write_locked(d, BURGUNDY_ISSAL_REG, BURGUNDY_ISS_UNITY); 179 burgundy_write_locked(d, BURGUNDY_ISSAR_REG, BURGUNDY_ISS_UNITY); 180 181 burgundy_set_outputs(d, burgundy_read_status(d, 182 bus_read_4(d->reg, DAVBUS_CODEC_STATUS))); 183 184 mtx_unlock(&d->mutex); 185 186 mix_setdevs(m, SOUND_MASK_VOLUME); 187 188 return (0); 189 } 190 191 static int 192 burgundy_uninit(struct snd_mixer *m) 193 { 194 return (0); 195 } 196 197 static int 198 burgundy_reinit(struct snd_mixer *m) 199 { 200 return (0); 201 } 202 203 static void 204 burgundy_write_locked(struct davbus_softc *d, u_int reg, u_int val) 205 { 206 u_int size, addr, offset, data, i; 207 208 size = (reg & 0x00FF0000) >> 16; 209 addr = (reg & 0x0000FF00) >> 8; 210 offset = reg & 0xFF; 211 212 for (i = offset; i < offset + size; ++i) { 213 data = BURGUNDY_CTRL_WRITE | (addr << 12) | 214 ((size + offset - 1) << 10) | (i << 8) | (val & 0xFF); 215 if (i == offset) 216 data |= BURGUNDY_CTRL_RESET; 217 218 bus_write_4(d->reg, DAVBUS_CODEC_CTRL, data); 219 220 while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & 221 DAVBUS_CODEC_BUSY) 222 DELAY(1); 223 224 val >>= 8; /* next byte. */ 225 } 226 } 227 228 /* Must be called with d->mutex held. */ 229 static void 230 burgundy_set_outputs(struct davbus_softc *d, u_int mask) 231 { 232 u_int x = 0; 233 234 if (mask == d->output_mask) 235 return; 236 237 /* 238 * Bordeaux card wirings: 239 * Port 15: RCA out 240 * Port 16: Minijack out 241 * Port 17: Internal speaker 242 * 243 * B&W G3 wirings: 244 * Port 14: Minijack out 245 * Port 17: Internal speaker 246 */ 247 248 DPRINTF(("Enabled outputs:")); 249 if (mask & (1 << 0)) { 250 DPRINTF((" SPEAKER")); 251 x |= BURGUNDY_P17M_EN; 252 } 253 if (mask & (1 << 1)) { 254 DPRINTF((" HEADPHONES")); 255 x |= BURGUNDY_P14L_EN | BURGUNDY_P14R_EN; 256 } 257 DPRINTF(("\n")); 258 259 burgundy_write_locked(d, BURGUNDY_MUTE_REG, x); 260 d->output_mask = mask; 261 } 262 263 static u_int 264 burgundy_read_status(struct davbus_softc *d, u_int status) 265 { 266 if (status & 0x4) 267 return (1 << 1); 268 else 269 return (1 << 0); 270 } 271 272 static int 273 burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 274 { 275 struct davbus_softc *d; 276 int lval, rval; 277 278 lval = ((100 - left) * 15 / 100) & 0xf; 279 rval = ((100 - right) * 15 / 100) & 0xf; 280 DPRINTF(("volume %d %d\n", lval, rval)); 281 282 d = mix_getdevinfo(m); 283 284 switch (dev) { 285 case SOUND_MIXER_VOLUME: 286 mtx_lock(&d->mutex); 287 288 burgundy_write_locked(d, BURGUNDY_OL13_REG, lval); 289 burgundy_write_locked(d, BURGUNDY_OL14_REG, (rval << 4) | lval); 290 burgundy_write_locked(d, BURGUNDY_OL15_REG, (rval << 4) | lval); 291 burgundy_write_locked(d, BURGUNDY_OL16_REG, (rval << 4) | lval); 292 burgundy_write_locked(d, BURGUNDY_OL17_REG, lval); 293 294 mtx_unlock(&d->mutex); 295 296 return (left | (right << 8)); 297 } 298 299 return (0); 300 } 301 302 static u_int32_t 303 burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src) 304 { 305 return (0); 306 } 307 308 /* 309 * Screamer Codec Control 310 */ 311 312 static int screamer_init(struct snd_mixer *m); 313 static int screamer_uninit(struct snd_mixer *m); 314 static int screamer_reinit(struct snd_mixer *m); 315 static void screamer_write_locked(struct davbus_softc *, u_int, u_int); 316 static void screamer_set_outputs(struct davbus_softc *d, u_int mask); 317 static u_int screamer_read_status(struct davbus_softc *d, u_int status); 318 static int screamer_set(struct snd_mixer *m, unsigned dev, unsigned left, 319 unsigned right); 320 static u_int32_t screamer_setrecsrc(struct snd_mixer *m, u_int32_t src); 321 322 static kobj_method_t screamer_mixer_methods[] = { 323 KOBJMETHOD(mixer_init, screamer_init), 324 KOBJMETHOD(mixer_uninit, screamer_uninit), 325 KOBJMETHOD(mixer_reinit, screamer_reinit), 326 KOBJMETHOD(mixer_set, screamer_set), 327 KOBJMETHOD(mixer_setrecsrc, screamer_setrecsrc), 328 KOBJMETHOD_END 329 }; 330 331 MIXER_DECLARE(screamer_mixer); 332 333 static int 334 screamer_init(struct snd_mixer *m) 335 { 336 struct davbus_softc *d; 337 338 d = mix_getdevinfo(m); 339 340 d->read_status = screamer_read_status; 341 d->set_outputs = screamer_set_outputs; 342 343 mtx_lock(&d->mutex); 344 345 screamer_write_locked(d, SCREAMER_CODEC_ADDR0, SCREAMER_INPUT_CD | 346 SCREAMER_DEFAULT_CD_GAIN); 347 348 screamer_set_outputs(d, screamer_read_status(d, 349 bus_read_4(d->reg, DAVBUS_CODEC_STATUS))); 350 351 screamer_write_locked(d, SCREAMER_CODEC_ADDR2, 0); 352 screamer_write_locked(d, SCREAMER_CODEC_ADDR4, 0); 353 screamer_write_locked(d, SCREAMER_CODEC_ADDR5, 0); 354 screamer_write_locked(d, SCREAMER_CODEC_ADDR6, 0); 355 356 mtx_unlock(&d->mutex); 357 358 mix_setdevs(m, SOUND_MASK_VOLUME); 359 360 return (0); 361 } 362 363 static int 364 screamer_uninit(struct snd_mixer *m) 365 { 366 return (0); 367 } 368 369 static int 370 screamer_reinit(struct snd_mixer *m) 371 { 372 return (0); 373 } 374 375 376 static void 377 screamer_write_locked(struct davbus_softc *d, u_int reg, u_int val) 378 { 379 u_int x; 380 381 KASSERT(val == (val & 0xfff), ("bad val")); 382 383 while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & DAVBUS_CODEC_BUSY) 384 DELAY(100); 385 386 x = reg; 387 x |= SCREAMER_CODEC_EMSEL0; 388 x |= val; 389 bus_write_4(d->reg, DAVBUS_CODEC_CTRL, x); 390 391 while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & DAVBUS_CODEC_BUSY) 392 DELAY(100); 393 } 394 395 /* Must be called with d->mutex held. */ 396 static void 397 screamer_set_outputs(struct davbus_softc *d, u_int mask) 398 { 399 u_int x; 400 401 if (mask == d->output_mask) { 402 return; 403 } 404 405 x = SCREAMER_MUTE_SPEAKER | SCREAMER_MUTE_HEADPHONES; 406 407 DPRINTF(("Enabled outputs: ")); 408 409 if (mask & (1 << 0)) { 410 DPRINTF(("SPEAKER ")); 411 x &= ~SCREAMER_MUTE_SPEAKER; 412 } 413 if (mask & (1 << 1)) { 414 DPRINTF(("HEADPHONES ")); 415 x &= ~SCREAMER_MUTE_HEADPHONES; 416 } 417 418 DPRINTF(("\n")); 419 420 if (d->device_id == 5 || d->device_id == 11) { 421 DPRINTF(("Enabling programmable output.\n")); 422 x |= SCREAMER_PROG_OUTPUT0; 423 } 424 if (d->device_id == 8 || d->device_id == 11) { 425 x &= ~SCREAMER_MUTE_SPEAKER; 426 427 if (mask & (1 << 0)) 428 x |= SCREAMER_PROG_OUTPUT1; /* enable speaker. */ 429 } 430 431 screamer_write_locked(d, SCREAMER_CODEC_ADDR1, x); 432 d->output_mask = mask; 433 } 434 435 static u_int 436 screamer_read_status(struct davbus_softc *d, u_int status) 437 { 438 int headphones; 439 440 switch (d->device_id) { 441 case 5: /* Sawtooth */ 442 headphones = (status & 0x4); 443 break; 444 445 case 8: 446 case 11: /* iMac DV */ 447 /* The iMac DV has 2 headphone outputs. */ 448 headphones = (status & 0x7); 449 break; 450 451 default: 452 headphones = (status & 0x8); 453 } 454 455 if (headphones) 456 return (1 << 1); 457 else 458 return (1 << 0); 459 } 460 461 static int 462 screamer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right) 463 { 464 struct davbus_softc *d; 465 int lval, rval; 466 467 lval = ((100 - left) * 15 / 100) & 0xf; 468 rval = ((100 - right) * 15 / 100) & 0xf; 469 DPRINTF(("volume %d %d\n", lval, rval)); 470 471 d = mix_getdevinfo(m); 472 473 switch (dev) { 474 case SOUND_MIXER_VOLUME: 475 mtx_lock(&d->mutex); 476 screamer_write_locked(d, SCREAMER_CODEC_ADDR2, (lval << 6) | 477 rval); 478 screamer_write_locked(d, SCREAMER_CODEC_ADDR4, (lval << 6) | 479 rval); 480 mtx_unlock(&d->mutex); 481 482 return (left | (right << 8)); 483 } 484 485 return (0); 486 } 487 488 static u_int32_t 489 screamer_setrecsrc(struct snd_mixer *m, u_int32_t src) 490 { 491 return (0); 492 } 493 494 static int 495 davbus_attach(device_t self) 496 { 497 struct davbus_softc *sc; 498 struct resource *dbdma_irq, *cintr; 499 void *cookie; 500 char compat[64]; 501 int rid, oirq, err; 502 503 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 504 505 sc->aoa.sc_dev = self; 506 sc->node = ofw_bus_get_node(self); 507 sc->soundnode = OF_child(sc->node); 508 509 /* Map the controller register space. */ 510 rid = 0; 511 sc->reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 512 if (sc->reg == NULL) 513 return (ENXIO); 514 515 /* Map the DBDMA channel register space. */ 516 rid = 1; 517 sc->aoa.sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY, 518 &rid, RF_ACTIVE); 519 if (sc->aoa.sc_odma == NULL) 520 return (ENXIO); 521 522 /* Establish the DBDMA channel edge-triggered interrupt. */ 523 rid = 1; 524 dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, 525 &rid, RF_SHAREABLE | RF_ACTIVE); 526 if (dbdma_irq == NULL) 527 return (ENXIO); 528 529 oirq = rman_get_start(dbdma_irq); 530 531 DPRINTF(("interrupting at irq %d\n", oirq)); 532 533 err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); 534 if (err != 0) 535 return (err); 536 537 snd_setup_intr(self, dbdma_irq, INTR_MPSAFE, aoa_interrupt, 538 sc, &cookie); 539 540 /* Now initialize the controller. */ 541 542 bzero(compat, sizeof(compat)); 543 OF_getprop(sc->soundnode, "compatible", compat, sizeof(compat)); 544 OF_getprop(sc->soundnode, "device-id", &sc->device_id, sizeof(u_int)); 545 546 mtx_init(&sc->mutex, "DAVbus", NULL, MTX_DEF); 547 548 device_printf(self, "codec: <%s>\n", compat); 549 550 /* Setup the control interrupt. */ 551 rid = 0; 552 cintr = bus_alloc_resource_any(self, SYS_RES_IRQ, 553 &rid, RF_SHAREABLE | RF_ACTIVE); 554 if (cintr != NULL) 555 bus_setup_intr(self, cintr, INTR_TYPE_MISC | INTR_MPSAFE, 556 NULL, davbus_cint, sc, &cookie); 557 558 /* Initialize controller registers. */ 559 bus_write_4(sc->reg, DAVBUS_SOUND_CTRL, DAVBUS_INPUT_SUBFRAME0 | 560 DAVBUS_OUTPUT_SUBFRAME0 | DAVBUS_RATE_44100 | DAVBUS_INTR_PORTCHG); 561 562 /* Attach DBDMA engine and PCM layer */ 563 err = aoa_attach(sc); 564 if (err) 565 return (err); 566 567 /* Install codec module */ 568 if (strcmp(compat, "screamer") == 0) 569 mixer_init(self, &screamer_mixer_class, sc); 570 else if (strcmp(compat, "burgundy") == 0) 571 mixer_init(self, &burgundy_mixer_class, sc); 572 573 return (0); 574 } 575 576 static void 577 davbus_cint(void *ptr) 578 { 579 struct davbus_softc *d = ptr; 580 u_int reg, status, mask; 581 582 mtx_lock(&d->mutex); 583 584 reg = bus_read_4(d->reg, DAVBUS_SOUND_CTRL); 585 if (reg & DAVBUS_PORTCHG) { 586 587 status = bus_read_4(d->reg, DAVBUS_CODEC_STATUS); 588 589 if (d->read_status && d->set_outputs) { 590 591 mask = (*d->read_status)(d, status); 592 (*d->set_outputs)(d, mask); 593 } 594 595 /* Clear the interrupt. */ 596 bus_write_4(d->reg, DAVBUS_SOUND_CTRL, reg); 597 } 598 599 mtx_unlock(&d->mutex); 600 } 601 602