i2s.c revision 187717
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: head/sys/dev/sound/macio/i2s.c 187717 2009-01-26 14:43:18Z nwhitehorn $ 26 */ 27/*- 28 * Copyright (c) 2002, 2003 Tsubai Masanari. All rights reserved. 29 * 30 * Redistribution and use in source and binary forms, with or without 31 * modification, are permitted provided that the following conditions 32 * are met: 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in the 37 * documentation and/or other materials provided with the distribution. 38 * 3. The name of the author may not be used to endorse or promote products 39 * derived from this software without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 42 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 44 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 * 52 * NetBSD: snapper.c,v 1.28 2008/05/16 03:49:54 macallan Exp 53 * Id: snapper.c,v 1.11 2002/10/31 17:42:13 tsubai Exp 54 */ 55 56/* 57 * Apple I2S audio controller. 58 */ 59 60#include <sys/param.h> 61#include <sys/systm.h> 62#include <sys/kernel.h> 63#include <sys/module.h> 64#include <sys/bus.h> 65#include <sys/malloc.h> 66#include <sys/lock.h> 67#include <sys/mutex.h> 68#include <machine/dbdma.h> 69#include <machine/intr_machdep.h> 70#include <machine/resource.h> 71#include <machine/bus.h> 72#include <machine/pio.h> 73#include <sys/rman.h> 74#include <dev/ofw/ofw_bus.h> 75#include <dev/sound/pcm/sound.h> 76#include <dev/sound/macio/aoa.h> 77#include <powerpc/powermac/macgpiovar.h> 78 79struct i2s_softc { 80 struct aoa_softc aoa; 81 device_t dev; 82 phandle_t node; 83 phandle_t soundnode; 84 struct resource *reg; 85 u_int output_mask; 86 struct mtx port_mtx; 87}; 88 89static int i2s_probe(device_t); 90static int i2s_attach(device_t); 91static void i2s_postattach(void *); 92static int i2s_setup(struct i2s_softc *, u_int, u_int, u_int); 93static void i2s_mute_headphone (struct i2s_softc *, int); 94static void i2s_mute_lineout (struct i2s_softc *, int); 95static void i2s_mute_speaker (struct i2s_softc *, int); 96static void i2s_set_outputs(void *, u_int); 97 98static struct intr_config_hook *i2s_delayed_attach = NULL; 99 100kobj_class_t i2s_mixer_class = NULL; 101device_t i2s_mixer = NULL; 102 103static device_method_t pcm_i2s_methods[] = { 104 /* Device interface. */ 105 DEVMETHOD(device_probe, i2s_probe), 106 DEVMETHOD(device_attach, i2s_attach), 107 108 { 0, 0 } 109}; 110 111static driver_t pcm_i2s_driver = { 112 "pcm", 113 pcm_i2s_methods, 114 PCM_SOFTC_SIZE 115}; 116 117DRIVER_MODULE(pcm_i2s, macio, pcm_i2s_driver, pcm_devclass, 0, 0); 118MODULE_DEPEND(pcm_i2s, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 119 120static int aoagpio_probe(device_t); 121static int aoagpio_attach(device_t); 122 123static device_method_t aoagpio_methods[] = { 124 /* Device interface. */ 125 DEVMETHOD(device_probe, aoagpio_probe), 126 DEVMETHOD(device_attach, aoagpio_attach), 127 128 { 0, 0 } 129}; 130 131struct aoagpio_softc { 132 device_t dev; 133 int ctrl; 134 int detect_active; /* for extint-gpio */ 135 int level; /* for extint-gpio */ 136 struct i2s_softc *i2s; /* for extint-gpio */ 137}; 138 139static driver_t aoagpio_driver = { 140 "aoagpio", 141 aoagpio_methods, 142 sizeof(struct aoagpio_softc) 143}; 144static devclass_t aoagpio_devclass; 145 146DRIVER_MODULE(aoagpio, macgpio, aoagpio_driver, aoagpio_devclass, 0, 0); 147 148 149/***************************************************************************** 150 Probe and attachment routines. 151 *****************************************************************************/ 152static int 153i2s_probe(device_t self) 154{ 155 const char *name; 156 157 name = ofw_bus_get_name(self); 158 if (!name) 159 return (ENXIO); 160 161 if (strcmp(name, "i2s") != 0) 162 return (ENXIO); 163 164 device_set_desc(self, "Apple I2S Audio Controller"); 165 166 return (0); 167} 168 169static phandle_t of_find_firstchild_byname(phandle_t, const char *); 170 171static int 172i2s_attach(device_t self) 173{ 174 struct i2s_softc *sc; 175 struct resource *dbdma_irq; 176 void *dbdma_ih; 177 int rid, oirq, err; 178 phandle_t port; 179 180 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 181 182 sc->dev = self; 183 sc->node = ofw_bus_get_node(self); 184 185 port = of_find_firstchild_byname(sc->node, "i2s-a"); 186 if (port == -1) 187 return (ENXIO); 188 sc->soundnode = of_find_firstchild_byname(port, "sound"); 189 if (sc->soundnode == -1) 190 return (ENXIO); 191 192 mtx_init(&sc->port_mtx, "port_mtx", NULL, MTX_DEF); 193 194 /* Map the controller register space. */ 195 rid = 0; 196 sc->reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 197 if (sc->reg == NULL) 198 return ENXIO; 199 200 /* Map the DBDMA channel register space. */ 201 rid = 1; 202 sc->aoa.sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, 203 RF_ACTIVE); 204 if (sc->aoa.sc_odma == NULL) 205 return ENXIO; 206 207 /* Establish the DBDMA channel edge-triggered interrupt. */ 208 rid = 1; 209 dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, 210 &rid, RF_SHAREABLE | RF_ACTIVE); 211 if (dbdma_irq == NULL) 212 return (ENXIO); 213 214 /* Now initialize the controller. */ 215 err = i2s_setup(sc, 44100, 16, 64); 216 if (err != 0) 217 return (err); 218 219 bus_setup_intr(self, dbdma_irq, INTR_TYPE_AV | INTR_MPSAFE, NULL, 220 aoa_interrupt, sc, &dbdma_ih); 221 222 oirq = rman_get_start(dbdma_irq); 223 err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); 224 if (err != 0) 225 return (err); 226 227 /* 228 * Register a hook for delayed attach in order to allow 229 * the I2C controller to attach. 230 */ 231 if ((i2s_delayed_attach = malloc(sizeof(struct intr_config_hook), 232 M_TEMP, M_WAITOK | M_ZERO)) == NULL) 233 return (ENOMEM); 234 235 i2s_delayed_attach->ich_func = i2s_postattach; 236 i2s_delayed_attach->ich_arg = self; 237 238 if (config_intrhook_establish(i2s_delayed_attach) != 0) 239 return (ENOMEM); 240 241 return (aoa_attach(self,sc)); 242} 243 244/***************************************************************************** 245 GPIO routines. 246 *****************************************************************************/ 247 248enum gpio_ctrl { 249 AMP_MUTE, 250 HEADPHONE_MUTE, 251 LINEOUT_MUTE, 252 AUDIO_HW_RESET, 253 HEADPHONE_DETECT, 254 LINEOUT_DETECT, 255 GPIO_CTRL_NUM 256}; 257 258#define GPIO_CTRL_EXTINT_SET \ 259 ((1 << HEADPHONE_DETECT) | \ 260 (1 << LINEOUT_DETECT)) 261 262static struct aoagpio_softc *gpio_ctrls[GPIO_CTRL_NUM] = 263 {NULL, NULL, NULL, NULL, NULL, NULL}; 264 265static struct gpio_match { 266 const char *name; 267 enum gpio_ctrl ctrl; 268} gpio_controls[] = { 269 {"headphone-mute", HEADPHONE_MUTE}, 270 {"lineout-mute", LINEOUT_MUTE}, 271 {"amp-mute", AMP_MUTE}, 272 {"headphone-detect", HEADPHONE_DETECT}, 273 {"lineout-detect", LINEOUT_DETECT}, 274 {"line-output-detect", LINEOUT_DETECT}, 275 {"audio-hw-reset", AUDIO_HW_RESET}, 276 {"hw-reset", AUDIO_HW_RESET}, 277 {NULL, GPIO_CTRL_NUM} 278}; 279 280static void i2s_cint(struct i2s_softc *); 281 282static void 283aoagpio_int(void *cookie) 284{ 285 device_t self = cookie; 286 struct aoagpio_softc *sc; 287 288 sc = device_get_softc(self); 289 290 if (macgpio_read(self) & GPIO_LEVEL_RO) 291 sc->level = sc->detect_active; 292 else 293 sc->level = !(sc->detect_active); 294 295 if (sc->i2s) 296 i2s_cint(sc->i2s); 297} 298 299static int 300aoagpio_probe(device_t gpio) 301{ 302 phandle_t node; 303 char bname[32]; 304 const char *name; 305 struct gpio_match *m; 306 struct aoagpio_softc *sc; 307 308 node = ofw_bus_get_node(gpio); 309 if (node == 0 || node == -1) 310 return (EINVAL); 311 312 bzero(bname, sizeof(bname)); 313 if (OF_getprop(node, "audio-gpio", bname, sizeof(bname)) > 2) 314 name = bname; 315 else 316 name = ofw_bus_get_name(gpio); 317 318 /* Try to find a match. */ 319 for (m = gpio_controls; m->name != NULL; m++) { 320 if (strcmp(name, m->name) == 0) { 321 sc = device_get_softc(gpio); 322 gpio_ctrls[m->ctrl] = sc; 323 sc->dev = gpio; 324 sc->ctrl = m->ctrl; 325 sc->level = 0; 326 sc->detect_active = 0; 327 sc->i2s = NULL; 328 329 OF_getprop(node, "audio-gpio-active-state", 330 &sc->detect_active, sizeof(sc->detect_active)); 331 332 if ((1 << m->ctrl) & GPIO_CTRL_EXTINT_SET) 333 aoagpio_int(gpio); 334 335 device_set_desc(gpio, m->name); 336 device_quiet(gpio); 337 return (0); 338 } 339 } 340 341 return (ENXIO); 342} 343 344static int 345aoagpio_attach(device_t gpio) 346{ 347 struct aoagpio_softc *sc; 348 struct resource *r; 349 void *cookie; 350 int irq, rid = 0; 351 352 sc = device_get_softc(gpio); 353 354 if ((1 << sc->ctrl) & GPIO_CTRL_EXTINT_SET) { 355 r = bus_alloc_resource_any(gpio, SYS_RES_IRQ, &rid, RF_ACTIVE); 356 if (r == NULL) 357 return (ENXIO); 358 359 irq = rman_get_start(r); 360 DPRINTF(("interrupting at irq %d\n", irq)); 361 362 if (powerpc_config_intr(irq, INTR_TRIGGER_EDGE, 363 INTR_POLARITY_LOW) != 0) 364 return (ENXIO); 365 366 bus_setup_intr(gpio, r, INTR_TYPE_MISC | INTR_MPSAFE | 367 INTR_ENTROPY, NULL, aoagpio_int, gpio, &cookie); 368 } 369 370 return (0); 371} 372 373/* 374 * I2S module registers 375 */ 376#define I2S_INT 0x00 377#define I2S_FORMAT 0x10 378#define I2S_FRAMECOUNT 0x40 379#define I2S_FRAMEMATCH 0x50 380#define I2S_WORDSIZE 0x60 381 382/* I2S_INT register definitions */ 383#define I2S_INT_CLKSTOPPEND 0x01000000 /* clock-stop interrupt pending */ 384 385/* I2S_FORMAT register definitions */ 386#define CLKSRC_49MHz 0x80000000 /* Use 49152000Hz Osc. */ 387#define CLKSRC_45MHz 0x40000000 /* Use 45158400Hz Osc. */ 388#define CLKSRC_18MHz 0x00000000 /* Use 18432000Hz Osc. */ 389#define MCLK_DIV_MASK 0x1f000000 /* MCLK = SRC / DIV */ 390#define SCLK_DIV_MASK 0x00f00000 /* SCLK = MCLK / DIV */ 391#define SCLK_MASTER 0x00080000 /* Master mode */ 392#define SCLK_SLAVE 0x00000000 /* Slave mode */ 393#define SERIAL_FORMAT 0x00070000 394#define SERIAL_SONY 0x00000000 395#define SERIAL_64x 0x00010000 396#define SERIAL_32x 0x00020000 397#define SERIAL_DAV 0x00040000 398#define SERIAL_SILICON 0x00050000 399 400/* I2S_WORDSIZE register definitions */ 401#define INPUT_STEREO (2 << 24) 402#define INPUT_MONO (1 << 24) 403#define INPUT_16BIT (0 << 16) 404#define INPUT_24BIT (3 << 16) 405#define OUTPUT_STEREO (2 << 8) 406#define OUTPUT_MONO (1 << 8) 407#define OUTPUT_16BIT (0 << 0) 408#define OUTPUT_24BIT (3 << 0) 409 410/* Master clock, needed by some codecs. We hardcode this 411 to 256 * fs as this is valid for most codecs. */ 412#define MCLK_FS 256 413 414/* Number of clock sources we can use. */ 415#define NCLKS 3 416static const struct i2s_clksrc { 417 u_int cs_clock; 418 u_int cs_reg; 419} clksrc[NCLKS] = { 420 {49152000, CLKSRC_49MHz}, 421 {45158400, CLKSRC_45MHz}, 422 {18432000, CLKSRC_18MHz} 423}; 424 425/* Configure the I2S controller for the required settings. 426 'rate' is the frame rate. 427 'wordsize' is the sample size (usually 16 bits). 428 'sclk_fs' is the SCLK/framerate ratio, which needs to be equal 429 or greater to the number of bits per frame. */ 430 431static int 432i2s_setup(struct i2s_softc *sc, u_int rate, u_int wordsize, u_int sclk_fs) 433{ 434 u_int mclk, mdiv, sdiv; 435 u_int reg = 0, x, wordformat; 436 u_int i; 437 438 /* Make sure the settings are consistent... */ 439 if ((wordsize * 2) > sclk_fs) 440 return (EINVAL); 441 442 if (sclk_fs != 32 && sclk_fs != 64) 443 return (EINVAL); 444 445 /* 446 * Find a clock source to derive the master clock (MCLK) 447 * and the I2S bit block (SCLK) and set the divisors as 448 * appropriate. 449 */ 450 mclk = rate * MCLK_FS; 451 sdiv = MCLK_FS / sclk_fs; 452 453 for (i = 0; i < NCLKS; ++i) { 454 if ((clksrc[i].cs_clock % mclk) == 0) { 455 reg = clksrc[i].cs_reg; 456 mdiv = clksrc[i].cs_clock / mclk; 457 break; 458 } 459 } 460 if (reg == 0) 461 return (EINVAL); 462 463 switch (mdiv) { 464 /* exception cases */ 465 case 1: 466 x = 14; 467 break; 468 case 3: 469 x = 13; 470 break; 471 case 5: 472 x = 12; 473 break; 474 default: 475 x = (mdiv / 2) - 1; 476 break; 477 } 478 reg |= (x << 24) & MCLK_DIV_MASK; 479 480 switch (sdiv) { 481 case 1: 482 x = 8; 483 break; 484 case 3: 485 x = 9; 486 break; 487 default: 488 x = (sdiv / 2) - 1; 489 break; 490 } 491 reg |= (x << 20) & SCLK_DIV_MASK; 492 493 /* 494 * XXX use master mode for now. This needs to be 495 * revisited if we want to add recording from SPDIF some day. 496 */ 497 reg |= SCLK_MASTER; 498 499 switch (sclk_fs) { 500 case 64: 501 reg |= SERIAL_64x; 502 break; 503 case 32: 504 reg |= SERIAL_32x; 505 break; 506 } 507 508 /* stereo input and output */ 509 wordformat = INPUT_STEREO | OUTPUT_STEREO; 510 511 switch (wordsize) { 512 case 16: 513 wordformat |= INPUT_16BIT | OUTPUT_16BIT; 514 break; 515 case 24: 516 wordformat |= INPUT_24BIT | OUTPUT_24BIT; 517 break; 518 default: 519 return (EINVAL); 520 } 521 522 x = bus_read_4(sc->reg, I2S_WORDSIZE); 523 if (x != wordformat) 524 bus_write_4(sc->reg, I2S_WORDSIZE, wordformat); 525 526 x = bus_read_4(sc->reg, I2S_FORMAT); 527 if (x != reg) { 528 /* 529 * XXX to change the format we need to stop the clock 530 * via the FCR registers. For now, rely on the firmware 531 * to set sane defaults (44100). 532 */ 533 printf("i2s_setup: changing format not supported yet.\n"); 534 return (EOPNOTSUPP); 535 536#ifdef notyet 537 if (obio_fcr_isset(OBIO_FCR1, I2S0CLKEN)) { 538 539 bus_space_write_4(sc->sc_tag, sc->sc_bsh, I2S_INT, 540 I2S_INT_CLKSTOPPEND); 541 542 obio_fcr_clear(OBIO_FCR1, I2S0CLKEN); 543 544 for (timo = 1000; timo > 0; timo--) { 545 if (bus_space_read_4(sc->sc_tag, sc->sc_bsh, 546 I2S_INT) & I2S_INT_CLKSTOPPEND) 547 break; 548 549 DELAY(10); 550 } 551 552 if (timo == 0) 553 printf("%s: timeout waiting for clock to stop\n", 554 sc->sc_dev.dv_xname); 555 } 556 557 bus_space_write_4(sc->sc_tag, sc->sc_bsh, I2S_FORMAT, reg); 558 559 obio_fcr_set(OBIO_FCR1, I2S0CLKEN); 560#endif 561 } 562 563 return (0); 564} 565 566 567/* XXX this does not belong here. */ 568static phandle_t 569of_find_firstchild_byname(phandle_t node, const char *req_name) 570{ 571 char name[32]; /* max name len per OF spec. */ 572 phandle_t n; 573 574 for (n = OF_child(node); n != -1; n = OF_peer(n)) { 575 bzero(name, sizeof(name)); 576 OF_getprop(n, "name", name, sizeof(name)); 577 578 if (strcmp(name, req_name) == 0) 579 return (n); 580 } 581 582 return (-1); 583} 584 585 586static u_int 587gpio_read(enum gpio_ctrl ctrl) 588{ 589 struct aoagpio_softc *sc; 590 591 if ((sc = gpio_ctrls[ctrl]) == NULL) 592 return (0); 593 594 return (macgpio_read(sc->dev) & GPIO_DATA); 595} 596 597static void 598gpio_write(enum gpio_ctrl ctrl, u_int x) 599{ 600 struct aoagpio_softc *sc; 601 u_int reg; 602 603 if ((sc = gpio_ctrls[ctrl]) == NULL) 604 return; 605 606 reg = GPIO_DDR_OUTPUT; 607 if (x) 608 reg |= GPIO_DATA; 609 610 macgpio_write(sc->dev, reg); 611} 612 613static void 614i2s_cint(struct i2s_softc *sc) 615{ 616 u_int mask = 0; 617 618 if (gpio_ctrls[HEADPHONE_DETECT] && 619 gpio_ctrls[HEADPHONE_DETECT]->level) 620 mask |= 1 << 1; 621 622 if (gpio_ctrls[LINEOUT_DETECT] && 623 gpio_ctrls[LINEOUT_DETECT]->level) 624 mask |= 1 << 2; 625 626 if (mask == 0) 627 mask = 1 << 0; /* fall back to speakers. */ 628 629 i2s_set_outputs(sc, mask); 630} 631 632#define reset_active 0 633 634/* these values are in microseconds */ 635#define RESET_SETUP_TIME 5000 636#define RESET_HOLD_TIME 20000 637#define RESET_RELEASE_TIME 10000 638 639static void 640i2s_audio_hw_reset(struct i2s_softc *sc) 641{ 642 if (gpio_ctrls[AUDIO_HW_RESET]) { 643 DPRINTF(("resetting codec\n")); 644 645 gpio_write(AUDIO_HW_RESET, !reset_active); /* Negate RESET */ 646 DELAY(RESET_SETUP_TIME); 647 648 gpio_write(AUDIO_HW_RESET, reset_active); /* Assert RESET */ 649 DELAY(RESET_HOLD_TIME); 650 651 gpio_write(AUDIO_HW_RESET, !reset_active); /* Negate RESET */ 652 DELAY(RESET_RELEASE_TIME); 653 654 } else { 655 DPRINTF(("no audio_hw_reset\n")); 656 } 657} 658 659#define AMP_ACTIVE 0 /* XXX OF */ 660#define HEADPHONE_ACTIVE 0 /* XXX OF */ 661#define LINEOUT_ACTIVE 0 /* XXX OF */ 662 663#define MUTE_CONTROL(xxx, yyy) \ 664static void \ 665i2s_mute_##xxx(struct i2s_softc *sc, int mute) \ 666{ \ 667 int x; \ 668 \ 669 if (gpio_ctrls[yyy##_MUTE] == NULL) \ 670 return; \ 671 if (mute) \ 672 x = yyy##_ACTIVE; \ 673 else \ 674 x = ! yyy##_ACTIVE; \ 675 \ 676 if (x != gpio_read(yyy##_MUTE)) \ 677 gpio_write(yyy##_MUTE, x); \ 678} 679 680MUTE_CONTROL(speaker, AMP) 681MUTE_CONTROL(headphone, HEADPHONE) 682MUTE_CONTROL(lineout, LINEOUT) 683 684static void 685i2s_set_outputs(void *ptr, u_int mask) 686{ 687 struct i2s_softc *sc = ptr; 688 689 if (mask == sc->output_mask) 690 return; 691 692 mtx_lock(&sc->port_mtx); 693 694 i2s_mute_speaker(sc, 1); 695 i2s_mute_headphone(sc, 1); 696 i2s_mute_lineout(sc, 1); 697 698 DPRINTF(("enabled outputs: ")); 699 700 if (mask & (1 << 0)) { 701 DPRINTF(("SPEAKER ")); 702 i2s_mute_speaker(sc, 0); 703 } 704 if (mask & (1 << 1)) { 705 DPRINTF(("HEADPHONE ")); 706 i2s_mute_headphone(sc, 0); 707 } 708 if (mask & (1 << 2)) { 709 DPRINTF(("LINEOUT ")); 710 i2s_mute_lineout(sc, 0); 711 } 712 713 DPRINTF(("\n")); 714 sc->output_mask = mask; 715 716 mtx_unlock(&sc->port_mtx); 717} 718 719static void 720i2s_postattach(void *arg) 721{ 722 device_t self = arg; 723 struct i2s_softc *sc; 724 int i; 725 726 KASSERT(self != NULL, ("bad arg")); 727 KASSERT(i2s_delayed_attach != NULL, ("bogus call")); 728 729 sc = pcm_getdevinfo(self); 730 731 /* Reset the codec. */ 732 i2s_audio_hw_reset(sc); 733 734 /* If we have a codec, initialize it. */ 735 if (i2s_mixer) 736 mixer_init(self, i2s_mixer_class, i2s_mixer); 737 738 /* Read initial port status. */ 739 i2s_cint(sc); 740 741 /* Enable GPIO interrupt callback. */ 742 for (i = 0; i < GPIO_CTRL_NUM; i++) 743 if (gpio_ctrls[i]) 744 gpio_ctrls[i]->i2s = sc; 745 746 config_intrhook_disestablish(i2s_delayed_attach); 747 free(i2s_delayed_attach, M_TEMP); 748} 749 750