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