1 /* $NetBSD: snapper.c,v 1.5 2005/01/25 19:05:22 briggs Exp $ */ 2 /* Id: snapper.c,v 1.11 2002/10/31 17:42:13 tsubai Exp */ 3 4 /*- 5 * Copyright (c) 2002 Tsubai Masanari. 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 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Datasheet is available from 32 * http://www.ti.com/sc/docs/products/analog/tas3004.html 33 */ 34 35 #include <sys/param.h> 36 #include <sys/audioio.h> 37 #include <sys/device.h> 38 #include <sys/systm.h> 39 40 #include <dev/auconv.h> 41 #include <dev/audio_if.h> 42 #include <dev/mulaw.h> 43 #include <dev/ofw/openfirm.h> 44 #include <macppc/dev/dbdma.h> 45 46 #include <uvm/uvm_extern.h> 47 48 #include <machine/autoconf.h> 49 #include <machine/pio.h> 50 51 #ifdef SNAPPER_DEBUG 52 # define DPRINTF printf 53 #else 54 # define DPRINTF while (0) printf 55 #endif 56 57 struct snapper_softc { 58 struct device sc_dev; 59 int sc_flags; 60 int sc_node; 61 62 void (*sc_ointr)(void *); /* dma completion intr handler */ 63 void *sc_oarg; /* arg for sc_ointr() */ 64 int sc_opages; /* # of output pages */ 65 66 void (*sc_iintr)(void *); /* dma completion intr handler */ 67 void *sc_iarg; /* arg for sc_iintr() */ 68 69 u_int sc_record_source; /* recording source mask */ 70 u_int sc_output_mask; /* output source mask */ 71 72 u_char *sc_reg; 73 struct device *sc_i2c; 74 75 u_int sc_vol_l; 76 u_int sc_vol_r; 77 78 dbdma_regmap_t *sc_odma; 79 dbdma_regmap_t *sc_idma; 80 unsigned char dbdma_cmdspace[sizeof(struct dbdma_command) * 40 + 15]; 81 struct dbdma_command *sc_odmacmd; 82 struct dbdma_command *sc_idmacmd; 83 }; 84 85 int snapper_match(struct device *, struct cfdata *, void *); 86 void snapper_attach(struct device *, struct device *, void *); 87 void snapper_defer(struct device *); 88 int snapper_intr(void *); 89 void snapper_close(void *); 90 int snapper_query_encoding(void *, struct audio_encoding *); 91 int snapper_set_params(void *, int, int, audio_params_t *, 92 audio_params_t *, stream_filter_list_t *, stream_filter_list_t *); 93 int snapper_round_blocksize(void *, int, int, const audio_params_t *); 94 int snapper_halt_output(void *); 95 int snapper_halt_input(void *); 96 int snapper_getdev(void *, struct audio_device *); 97 int snapper_set_port(void *, mixer_ctrl_t *); 98 int snapper_get_port(void *, mixer_ctrl_t *); 99 int snapper_query_devinfo(void *, mixer_devinfo_t *); 100 size_t snapper_round_buffersize(void *, int, size_t); 101 paddr_t snapper_mappage(void *, void *, off_t, int); 102 int snapper_get_props(void *); 103 int snapper_trigger_output(void *, void *, void *, int, void (*)(void *), 104 void *, const audio_params_t *); 105 int snapper_trigger_input(void *, void *, void *, int, void (*)(void *), 106 void *, const audio_params_t *); 107 void snapper_set_volume(struct snapper_softc *, int, int); 108 int snapper_set_rate(struct snapper_softc *, u_int); 109 110 int tas3004_write(struct snapper_softc *, u_int, const void *); 111 static int gpio_read(char *); 112 static void gpio_write(char *, int); 113 void snapper_mute_speaker(struct snapper_softc *, int); 114 void snapper_mute_headphone(struct snapper_softc *, int); 115 int snapper_cint(void *); 116 int tas3004_init(struct snapper_softc *); 117 void snapper_init(struct snapper_softc *, int); 118 119 /* XXX */ 120 int ki2c_setmode(struct device *, int); 121 int ki2c_write(struct device *, int, int, const void *, int); 122 void ki2c_writereg(struct device *, int, u_int); 123 124 125 struct cfattach snapper_ca = { 126 "snapper", {}, sizeof(struct snapper_softc), 127 snapper_match, snapper_attach 128 }; 129 130 const struct audio_hw_if snapper_hw_if = { 131 NULL, /* open */ 132 snapper_close, 133 NULL, 134 snapper_query_encoding, 135 snapper_set_params, 136 snapper_round_blocksize, 137 NULL, 138 NULL, 139 NULL, 140 NULL, 141 NULL, 142 snapper_halt_output, 143 snapper_halt_input, 144 NULL, 145 snapper_getdev, 146 NULL, 147 snapper_set_port, 148 snapper_get_port, 149 snapper_query_devinfo, 150 NULL, 151 NULL, 152 snapper_round_buffersize, 153 snapper_mappage, 154 snapper_get_props, 155 snapper_trigger_output, 156 snapper_trigger_input, 157 NULL 158 }; 159 160 struct audio_device snapper_device = { 161 "SNAPPER", 162 "", 163 "snapper" 164 }; 165 166 #define SNAPPER_NFORMATS 1 167 static const struct audio_format snapper_formats[SNAPPER_NFORMATS] = { 168 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_BE, 16, 16, 169 2, AUFMT_STEREO, 3, {8000, 44100, 48000}}, 170 }; 171 172 static u_char *amp_mute; 173 static u_char *headphone_mute; 174 static u_char *audio_hw_reset; 175 static u_char *headphone_detect; 176 static int headphone_detect_active; 177 178 179 /* I2S registers */ 180 #define I2S_INT 0x00 181 #define I2S_FORMAT 0x10 182 #define I2S_FRAMECOUNT 0x40 183 #define I2S_FRAMEMATCH 0x50 184 #define I2S_WORDSIZE 0x60 185 186 /* TAS3004 registers */ 187 #define DEQ_MCR1 0x01 /* Main control register 1 (1byte) */ 188 #define DEQ_DRC 0x02 /* Dynamic range compression (6bytes?) */ 189 #define DEQ_VOLUME 0x04 /* Volume (6bytes) */ 190 #define DEQ_TREBLE 0x05 /* Treble control (1byte) */ 191 #define DEQ_BASS 0x06 /* Bass control (1byte) */ 192 #define DEQ_MIXER_L 0x07 /* Mixer left gain (9bytes) */ 193 #define DEQ_MIXER_R 0x08 /* Mixer right gain (9bytes) */ 194 #define DEQ_LB0 0x0a /* Left biquad 0 (15bytes) */ 195 #define DEQ_LB1 0x0b /* Left biquad 1 (15bytes) */ 196 #define DEQ_LB2 0x0c /* Left biquad 2 (15bytes) */ 197 #define DEQ_LB3 0x0d /* Left biquad 3 (15bytes) */ 198 #define DEQ_LB4 0x0e /* Left biquad 4 (15bytes) */ 199 #define DEQ_LB5 0x0f /* Left biquad 5 (15bytes) */ 200 #define DEQ_LB6 0x10 /* Left biquad 6 (15bytes) */ 201 #define DEQ_RB0 0x13 /* Right biquad 0 (15bytes) */ 202 #define DEQ_RB1 0x14 /* Right biquad 1 (15bytes) */ 203 #define DEQ_RB2 0x15 /* Right biquad 2 (15bytes) */ 204 #define DEQ_RB3 0x16 /* Right biquad 3 (15bytes) */ 205 #define DEQ_RB4 0x17 /* Right biquad 4 (15bytes) */ 206 #define DEQ_RB5 0x18 /* Right biquad 5 (15bytes) */ 207 #define DEQ_RB6 0x19 /* Right biquad 6 (15bytes) */ 208 #define DEQ_LLB 0x21 /* Left loudness biquad (15bytes) */ 209 #define DEQ_RLB 0x22 /* Right loudness biquad (15bytes) */ 210 #define DEQ_LLB_GAIN 0x23 /* Left loudness biquad gain (3bytes) */ 211 #define DEQ_RLB_GAIN 0x24 /* Right loudness biquad gain (3bytes) */ 212 #define DEQ_ACR 0x40 /* Analog control register (1byte) */ 213 #define DEQ_MCR2 0x43 /* Main control register 2 (1byte) */ 214 215 #define DEQ_MCR1_FL 0x80 /* Fast load */ 216 #define DEQ_MCR1_SC 0x40 /* SCLK frequency */ 217 #define DEQ_MCR1_SC_32 0x00 /* 32fs */ 218 #define DEQ_MCR1_SC_64 0x40 /* 64fs */ 219 #define DEQ_MCR1_SM 0x30 /* Output serial port mode */ 220 #define DEQ_MCR1_SM_L 0x00 /* Left justified */ 221 #define DEQ_MCR1_SM_R 0x10 /* Right justified */ 222 #define DEQ_MCR1_SM_I2S 0x20 /* I2S */ 223 #define DEQ_MCR1_W 0x03 /* Serial port word length */ 224 #define DEQ_MCR1_W_16 0x00 /* 16 bit */ 225 #define DEQ_MCR1_W_18 0x01 /* 18 bit */ 226 #define DEQ_MCR1_W_20 0x02 /* 20 bit */ 227 228 #define DEQ_MCR2_DL 0x80 /* Download */ 229 #define DEQ_MCR2_AP 0x02 /* All pass mode */ 230 231 #define DEQ_ACR_ADM 0x80 /* ADC output mode */ 232 #define DEQ_ACR_LRB 0x40 /* Select B input */ 233 #define DEQ_ACR_DM 0x0c /* De-emphasis control */ 234 #define DEQ_ACR_DM_OFF 0x00 /* off */ 235 #define DEQ_ACR_DM_48 0x04 /* fs = 48kHz */ 236 #define DEQ_ACR_DM_44 0x08 /* fs = 44.1kHz */ 237 #define DEQ_ACR_INP 0x02 /* Analog input select */ 238 #define DEQ_ACR_INP_A 0x00 /* A */ 239 #define DEQ_ACR_INP_B 0x02 /* B */ 240 #define DEQ_ACR_APD 0x01 /* Analog power down */ 241 242 struct tas3004_reg { 243 u_char MCR1[1]; 244 u_char DRC[6]; 245 u_char VOLUME[6]; 246 u_char TREBLE[1]; 247 u_char BASS[1]; 248 u_char MIXER_L[9]; 249 u_char MIXER_R[9]; 250 u_char LB0[15]; 251 u_char LB1[15]; 252 u_char LB2[15]; 253 u_char LB3[15]; 254 u_char LB4[15]; 255 u_char LB5[15]; 256 u_char LB6[15]; 257 u_char RB0[15]; 258 u_char RB1[15]; 259 u_char RB2[15]; 260 u_char RB3[15]; 261 u_char RB4[15]; 262 u_char RB5[15]; 263 u_char RB6[15]; 264 u_char LLB[15]; 265 u_char RLB[15]; 266 u_char LLB_GAIN[3]; 267 u_char RLB_GAIN[3]; 268 u_char ACR[1]; 269 u_char MCR2[1]; 270 }; 271 272 #define GPIO_OUTSEL 0xf0 /* Output select */ 273 /* 0x00 GPIO bit0 is output 274 0x10 media-bay power 275 0x20 reserved 276 0x30 MPIC */ 277 278 #define GPIO_ALTOE 0x08 /* Alternate output enable */ 279 /* 0x00 Use DDR 280 0x08 Use output select */ 281 282 #define GPIO_DDR 0x04 /* Data direction */ 283 #define GPIO_DDR_OUTPUT 0x04 /* Output */ 284 #define GPIO_DDR_INPUT 0x00 /* Input */ 285 286 #define GPIO_LEVEL 0x02 /* Pin level (RO) */ 287 288 #define GPIO_DATA 0x01 /* Data */ 289 290 int 291 snapper_match(struct device *parent, struct cfdata *match, void *aux) 292 { 293 struct confargs *ca; 294 int soundbus, soundchip; 295 char compat[32]; 296 297 ca = aux; 298 if (strcmp(ca->ca_name, "i2s") != 0) 299 return 0; 300 301 if ((soundbus = OF_child(ca->ca_node)) == 0 || 302 (soundchip = OF_child(soundbus)) == 0) 303 return 0; 304 305 bzero(compat, sizeof compat); 306 OF_getprop(soundchip, "compatible", compat, sizeof compat); 307 308 if (strcmp(compat, "snapper") != 0) 309 return 0; 310 311 return 1; 312 } 313 314 void 315 snapper_attach(struct device *parent, struct device *self, void *aux) 316 { 317 struct snapper_softc *sc; 318 struct confargs *ca; 319 unsigned long v; 320 int cirq, oirq, iirq, cirq_type, oirq_type, iirq_type; 321 int soundbus, intr[6]; 322 323 sc = (struct snapper_softc *)self; 324 ca = aux; 325 326 v = (((unsigned long) &sc->dbdma_cmdspace[0]) + 0xf) & ~0xf; 327 sc->sc_odmacmd = (struct dbdma_command *) v; 328 sc->sc_idmacmd = sc->sc_odmacmd + 20; 329 330 #ifdef DIAGNOSTIC 331 if ((vaddr_t)sc->sc_odmacmd & 0x0f) { 332 printf(": bad dbdma alignment\n"); 333 return; 334 } 335 #endif 336 337 ca->ca_reg[0] += ca->ca_baseaddr; 338 ca->ca_reg[2] += ca->ca_baseaddr; 339 ca->ca_reg[4] += ca->ca_baseaddr; 340 341 sc->sc_node = ca->ca_node; 342 sc->sc_reg = (void *)ca->ca_reg[0]; 343 sc->sc_odma = (void *)ca->ca_reg[2]; 344 sc->sc_idma = (void *)ca->ca_reg[4]; 345 346 soundbus = OF_child(ca->ca_node); 347 OF_getprop(soundbus, "interrupts", intr, sizeof intr); 348 cirq = intr[0]; 349 oirq = intr[2]; 350 iirq = intr[4]; 351 cirq_type = intr[1] ? IST_LEVEL : IST_EDGE; 352 oirq_type = intr[3] ? IST_LEVEL : IST_EDGE; 353 iirq_type = intr[5] ? IST_LEVEL : IST_EDGE; 354 355 /* intr_establish(cirq, cirq_type, IPL_AUDIO, snapper_intr, sc); */ 356 intr_establish(oirq, oirq_type, IPL_AUDIO, snapper_intr, sc); 357 /* intr_establish(iirq, iirq_type, IPL_AUDIO, snapper_intr, sc); */ 358 359 printf(": irq %d,%d,%d\n", cirq, oirq, iirq); 360 361 config_interrupts(self, snapper_defer); 362 } 363 364 void 365 snapper_defer(struct device *dev) 366 { 367 struct snapper_softc *sc; 368 struct device *dv; 369 370 sc = (struct snapper_softc *)dev; 371 for (dv = alldevs.tqh_first; dv; dv=dv->dv_list.tqe_next) 372 if (strncmp(dv->dv_xname, "ki2c", 4) == 0 && 373 strncmp(dv->dv_parent->dv_xname, "obio", 4) == 0) 374 sc->sc_i2c = dv; 375 if (sc->sc_i2c == NULL) { 376 printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname); 377 return; 378 } 379 380 /* XXX If i2c was failed to attach, what should we do? */ 381 382 audio_attach_mi(&snapper_hw_if, sc, &sc->sc_dev); 383 384 /* ki2c_setmode(sc->sc_i2c, I2C_STDSUBMODE); */ 385 snapper_init(sc, sc->sc_node); 386 } 387 388 int 389 snapper_intr(void *v) 390 { 391 struct snapper_softc *sc; 392 struct dbdma_command *cmd; 393 int count; 394 int status; 395 396 sc = v; 397 cmd = sc->sc_odmacmd; 398 count = sc->sc_opages; 399 /* Fill used buffer(s). */ 400 while (count-- > 0) { 401 if ((dbdma_ld16(&cmd->d_command) & 0x30) == 0x30) { 402 status = dbdma_ld16(&cmd->d_status); 403 cmd->d_status = 0; 404 if (status) /* status == 0x8400 */ 405 if (sc->sc_ointr) 406 (*sc->sc_ointr)(sc->sc_oarg); 407 } 408 cmd++; 409 } 410 411 return 1; 412 } 413 414 /* 415 * Close function is called at splaudio(). 416 */ 417 void 418 snapper_close(void *h) 419 { 420 struct snapper_softc *sc; 421 422 sc = h; 423 snapper_halt_output(sc); 424 snapper_halt_input(sc); 425 426 sc->sc_ointr = 0; 427 sc->sc_iintr = 0; 428 } 429 430 int 431 snapper_query_encoding(void *h, struct audio_encoding *ae) 432 { 433 434 ae->flags = AUDIO_ENCODINGFLAG_EMULATED; 435 switch (ae->index) { 436 case 0: 437 strcpy(ae->name, AudioEslinear); 438 ae->encoding = AUDIO_ENCODING_SLINEAR; 439 ae->precision = 16; 440 ae->flags = 0; 441 return 0; 442 case 1: 443 strcpy(ae->name, AudioEslinear_be); 444 ae->encoding = AUDIO_ENCODING_SLINEAR_BE; 445 ae->precision = 16; 446 ae->flags = 0; 447 return 0; 448 case 2: 449 strcpy(ae->name, AudioEslinear_le); 450 ae->encoding = AUDIO_ENCODING_SLINEAR_LE; 451 ae->precision = 16; 452 return 0; 453 case 3: 454 strcpy(ae->name, AudioEulinear_be); 455 ae->encoding = AUDIO_ENCODING_ULINEAR_BE; 456 ae->precision = 16; 457 return 0; 458 case 4: 459 strcpy(ae->name, AudioEulinear_le); 460 ae->encoding = AUDIO_ENCODING_ULINEAR_LE; 461 ae->precision = 16; 462 return 0; 463 case 5: 464 strcpy(ae->name, AudioEmulaw); 465 ae->encoding = AUDIO_ENCODING_ULAW; 466 ae->precision = 8; 467 return 0; 468 case 6: 469 strcpy(ae->name, AudioEalaw); 470 ae->encoding = AUDIO_ENCODING_ALAW; 471 ae->precision = 8; 472 return 0; 473 default: 474 return EINVAL; 475 } 476 } 477 478 int 479 snapper_set_params(void *h, int setmode, int usemode, 480 audio_params_t *play, audio_params_t *rec, 481 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 482 { 483 struct snapper_softc *sc; 484 audio_params_t *p; 485 stream_filter_list_t *fil; 486 int mode; 487 488 sc = h; 489 p = NULL; 490 491 /* 492 * This device only has one clock, so make the sample rates match. 493 */ 494 if (play->sample_rate != rec->sample_rate && 495 usemode == (AUMODE_PLAY | AUMODE_RECORD)) { 496 if (setmode == AUMODE_PLAY) { 497 rec->sample_rate = play->sample_rate; 498 setmode |= AUMODE_RECORD; 499 } else if (setmode == AUMODE_RECORD) { 500 play->sample_rate = rec->sample_rate; 501 setmode |= AUMODE_PLAY; 502 } else 503 return EINVAL; 504 } 505 506 for (mode = AUMODE_RECORD; mode != -1; 507 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 508 if ((setmode & mode) == 0) 509 continue; 510 511 p = mode == AUMODE_PLAY ? play : rec; 512 if (p->sample_rate < 4000 || p->sample_rate > 50000) 513 return EINVAL; 514 515 fil = mode == AUMODE_PLAY ? pfil : rfil; 516 if (auconv_set_converter(snapper_formats, SNAPPER_NFORMATS, 517 mode, p, TRUE, fil) < 0) 518 return EINVAL; 519 if (fil->req_size > 0) 520 p = &fil->filters[0].param; 521 } 522 523 /* Set the speed. p points HW encoding. */ 524 if (snapper_set_rate(sc, p->sample_rate)) 525 return EINVAL; 526 527 return 0; 528 } 529 530 int 531 snapper_round_blocksize(void *h, int size, int mode, 532 const audio_params_t *param) 533 { 534 535 if (size < NBPG) 536 size = NBPG; 537 return size & ~PGOFSET; 538 } 539 540 int 541 snapper_halt_output(void *h) 542 { 543 struct snapper_softc *sc; 544 545 sc = h; 546 dbdma_stop(sc->sc_odma); 547 dbdma_reset(sc->sc_odma); 548 return 0; 549 } 550 551 int 552 snapper_halt_input(void *h) 553 { 554 struct snapper_softc *sc; 555 556 sc = h; 557 dbdma_stop(sc->sc_idma); 558 dbdma_reset(sc->sc_idma); 559 return 0; 560 } 561 562 int 563 snapper_getdev(void *h, struct audio_device *retp) 564 { 565 566 *retp = snapper_device; 567 return 0; 568 } 569 570 enum { 571 SNAPPER_MONITOR_CLASS, 572 SNAPPER_OUTPUT_CLASS, 573 SNAPPER_RECORD_CLASS, 574 SNAPPER_OUTPUT_SELECT, 575 SNAPPER_VOL_OUTPUT, 576 SNAPPER_INPUT_SELECT, 577 SNAPPER_VOL_INPUT, 578 SNAPPER_ENUM_LAST 579 }; 580 581 int 582 snapper_set_port(void *h, mixer_ctrl_t *mc) 583 { 584 struct snapper_softc *sc; 585 int l, r; 586 587 DPRINTF("snapper_set_port dev = %d, type = %d\n", mc->dev, mc->type); 588 sc = h; 589 l = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 590 r = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 591 592 switch (mc->dev) { 593 case SNAPPER_OUTPUT_SELECT: 594 /* No change necessary? */ 595 if (mc->un.mask == sc->sc_output_mask) 596 return 0; 597 598 snapper_mute_speaker(sc, 1); 599 snapper_mute_headphone(sc, 1); 600 if (mc->un.mask & 1 << 0) 601 snapper_mute_speaker(sc, 0); 602 if (mc->un.mask & 1 << 1) 603 snapper_mute_headphone(sc, 0); 604 605 sc->sc_output_mask = mc->un.mask; 606 return 0; 607 608 case SNAPPER_VOL_OUTPUT: 609 snapper_set_volume(sc, l, r); 610 return 0; 611 612 case SNAPPER_INPUT_SELECT: 613 /* no change necessary? */ 614 if (mc->un.mask == sc->sc_record_source) 615 return 0; 616 switch (mc->un.mask) { 617 case 1 << 0: /* CD */ 618 case 1 << 1: /* microphone */ 619 case 1 << 2: /* line in */ 620 /* XXX TO BE DONE */ 621 break; 622 default: /* invalid argument */ 623 return EINVAL; 624 } 625 sc->sc_record_source = mc->un.mask; 626 return 0; 627 628 case SNAPPER_VOL_INPUT: 629 /* XXX TO BE DONE */ 630 return 0; 631 } 632 633 return ENXIO; 634 } 635 636 int 637 snapper_get_port(void *h, mixer_ctrl_t *mc) 638 { 639 struct snapper_softc *sc; 640 641 DPRINTF("snapper_get_port dev = %d, type = %d\n", mc->dev, mc->type); 642 sc = h; 643 switch (mc->dev) { 644 case SNAPPER_OUTPUT_SELECT: 645 mc->un.mask = sc->sc_output_mask; 646 return 0; 647 648 case SNAPPER_VOL_OUTPUT: 649 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_vol_l; 650 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_vol_r; 651 return 0; 652 653 case SNAPPER_INPUT_SELECT: 654 mc->un.mask = sc->sc_record_source; 655 return 0; 656 657 case SNAPPER_VOL_INPUT: 658 /* XXX TO BE DONE */ 659 mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 0; 660 mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 0; 661 return 0; 662 663 default: 664 return ENXIO; 665 } 666 667 return 0; 668 } 669 670 int 671 snapper_query_devinfo(void *h, mixer_devinfo_t *dip) 672 { 673 switch (dip->index) { 674 675 case SNAPPER_OUTPUT_SELECT: 676 dip->mixer_class = SNAPPER_MONITOR_CLASS; 677 strcpy(dip->label.name, AudioNoutput); 678 dip->type = AUDIO_MIXER_SET; 679 dip->prev = dip->next = AUDIO_MIXER_LAST; 680 dip->un.s.num_mem = 2; 681 strcpy(dip->un.s.member[0].label.name, AudioNspeaker); 682 dip->un.s.member[0].mask = 1 << 0; 683 strcpy(dip->un.s.member[1].label.name, AudioNheadphone); 684 dip->un.s.member[1].mask = 1 << 1; 685 return 0; 686 687 case SNAPPER_VOL_OUTPUT: 688 dip->mixer_class = SNAPPER_MONITOR_CLASS; 689 strcpy(dip->label.name, AudioNmaster); 690 dip->type = AUDIO_MIXER_VALUE; 691 dip->prev = dip->next = AUDIO_MIXER_LAST; 692 dip->un.v.num_channels = 2; 693 strcpy(dip->un.v.units.name, AudioNvolume); 694 return 0; 695 696 case SNAPPER_INPUT_SELECT: 697 dip->mixer_class = SNAPPER_RECORD_CLASS; 698 strcpy(dip->label.name, AudioNsource); 699 dip->type = AUDIO_MIXER_SET; 700 dip->prev = dip->next = AUDIO_MIXER_LAST; 701 dip->un.s.num_mem = 3; 702 strcpy(dip->un.s.member[0].label.name, AudioNcd); 703 dip->un.s.member[0].mask = 1 << 0; 704 strcpy(dip->un.s.member[1].label.name, AudioNmicrophone); 705 dip->un.s.member[1].mask = 1 << 1; 706 strcpy(dip->un.s.member[2].label.name, AudioNline); 707 dip->un.s.member[2].mask = 1 << 2; 708 return 0; 709 710 case SNAPPER_VOL_INPUT: 711 dip->mixer_class = SNAPPER_RECORD_CLASS; 712 strcpy(dip->label.name, AudioNrecord); 713 dip->type = AUDIO_MIXER_VALUE; 714 dip->prev = dip->next = AUDIO_MIXER_LAST; 715 dip->un.v.num_channels = 2; 716 strcpy(dip->un.v.units.name, AudioNvolume); 717 return 0; 718 719 case SNAPPER_MONITOR_CLASS: 720 dip->mixer_class = SNAPPER_MONITOR_CLASS; 721 strcpy(dip->label.name, AudioCmonitor); 722 dip->type = AUDIO_MIXER_CLASS; 723 dip->next = dip->prev = AUDIO_MIXER_LAST; 724 return 0; 725 726 case SNAPPER_OUTPUT_CLASS: 727 dip->mixer_class = SNAPPER_OUTPUT_CLASS; 728 strcpy(dip->label.name, AudioCoutputs); 729 dip->type = AUDIO_MIXER_CLASS; 730 dip->next = dip->prev = AUDIO_MIXER_LAST; 731 return 0; 732 733 case SNAPPER_RECORD_CLASS: 734 dip->mixer_class = SNAPPER_RECORD_CLASS; 735 strcpy(dip->label.name, AudioCrecord); 736 dip->type = AUDIO_MIXER_CLASS; 737 dip->next = dip->prev = AUDIO_MIXER_LAST; 738 return 0; 739 } 740 741 return ENXIO; 742 } 743 744 size_t 745 snapper_round_buffersize(void *h, int dir, size_t size) 746 { 747 748 if (size > 65536) 749 size = 65536; 750 return size; 751 } 752 753 paddr_t 754 snapper_mappage(void *h, void *mem, off_t off, int prot) 755 { 756 757 if (off < 0) 758 return -1; 759 return -1; /* XXX */ 760 } 761 762 int 763 snapper_get_props(void *h) 764 { 765 return AUDIO_PROP_FULLDUPLEX /* | AUDIO_PROP_MMAP */; 766 } 767 768 int 769 snapper_trigger_output(void *h, void *start, void *end, int bsize, 770 void (*intr)(void *), void *arg, 771 const audio_params_t *param) 772 { 773 struct snapper_softc *sc; 774 struct dbdma_command *cmd; 775 vaddr_t va; 776 int i, len, intmode; 777 778 DPRINTF("trigger_output %p %p 0x%x\n", start, end, bsize); 779 sc = h; 780 cmd = sc->sc_odmacmd; 781 sc->sc_ointr = intr; 782 sc->sc_oarg = arg; 783 sc->sc_opages = ((char *)end - (char *)start) / NBPG; 784 785 #ifdef DIAGNOSTIC 786 if (sc->sc_opages > 16) 787 panic("snapper_trigger_output"); 788 #endif 789 790 va = (vaddr_t)start; 791 len = 0; 792 for (i = sc->sc_opages; i > 0; i--) { 793 len += NBPG; 794 if (len < bsize) 795 intmode = 0; 796 else { 797 len = 0; 798 intmode = DBDMA_INT_ALWAYS; 799 } 800 801 DBDMA_BUILD(cmd, DBDMA_CMD_OUT_MORE, 0, NBPG, vtophys(va), 802 intmode, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); 803 cmd++; 804 va += NBPG; 805 } 806 807 DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 808 0/*vtophys((vaddr_t)sc->sc_odmacmd)*/, 0, DBDMA_WAIT_NEVER, 809 DBDMA_BRANCH_ALWAYS); 810 811 dbdma_st32(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_odmacmd)); 812 813 dbdma_start(sc->sc_odma, sc->sc_odmacmd); 814 815 return 0; 816 } 817 818 int 819 snapper_trigger_input(void *h, void *start, void *end, int bsize, 820 void (*intr)(void *), void *arg, 821 const audio_params_t *param) 822 { 823 824 printf("snapper_trigger_input called\n"); 825 return 1; 826 } 827 828 void 829 snapper_set_volume(struct snapper_softc *sc, int left, int right) 830 { 831 u_char vol[6]; 832 833 sc->sc_vol_l = left; 834 sc->sc_vol_r = right; 835 836 left <<= 8; /* XXX for now */ 837 right <<= 8; 838 839 vol[0] = left >> 16; 840 vol[1] = left >> 8; 841 vol[2] = left; 842 vol[3] = right >> 16; 843 vol[4] = right >> 8; 844 vol[5] = right; 845 846 tas3004_write(sc, DEQ_VOLUME, vol); 847 } 848 849 #define CLKSRC_49MHz 0x80000000 /* Use 49152000Hz Osc. */ 850 #define CLKSRC_45MHz 0x40000000 /* Use 45158400Hz Osc. */ 851 #define CLKSRC_18MHz 0x00000000 /* Use 18432000Hz Osc. */ 852 #define MCLK_DIV 0x1f000000 /* MCLK = SRC / DIV */ 853 #define MCLK_DIV1 0x14000000 /* MCLK = SRC */ 854 #define MCLK_DIV3 0x13000000 /* MCLK = SRC / 3 */ 855 #define MCLK_DIV5 0x12000000 /* MCLK = SRC / 5 */ 856 #define SCLK_DIV 0x00f00000 /* SCLK = MCLK / DIV */ 857 #define SCLK_DIV1 0x00800000 858 #define SCLK_DIV3 0x00900000 859 #define SCLK_MASTER 0x00080000 /* Master mode */ 860 #define SCLK_SLAVE 0x00000000 /* Slave mode */ 861 #define SERIAL_FORMAT 0x00070000 862 #define SERIAL_SONY 0x00000000 863 #define SERIAL_64x 0x00010000 864 #define SERIAL_32x 0x00020000 865 #define SERIAL_DAV 0x00040000 866 #define SERIAL_SILICON 0x00050000 867 868 // rate = fs = LRCLK 869 // SCLK = 64*LRCLK (I2S) 870 // MCLK = 256fs (typ. -- changeable) 871 872 // MCLK = clksrc / mdiv 873 // SCLK = MCLK / sdiv 874 // rate = SCLK / 64 ( = LRCLK = fs) 875 876 int 877 snapper_set_rate(struct snapper_softc *sc, u_int rate) 878 { 879 u_int reg; 880 int MCLK; 881 int clksrc, mdiv, sdiv; 882 int mclk_fs; 883 884 reg = 0; 885 switch (rate) { 886 case 8000: 887 clksrc = 18432000; /* 18MHz */ 888 reg = CLKSRC_18MHz; 889 mclk_fs = 256; 890 break; 891 892 case 44100: 893 clksrc = 45158400; /* 45MHz */ 894 reg = CLKSRC_45MHz; 895 mclk_fs = 256; 896 break; 897 898 case 48000: 899 clksrc = 49152000; /* 49MHz */ 900 reg = CLKSRC_49MHz; 901 mclk_fs = 256; 902 break; 903 904 default: 905 return EINVAL; 906 } 907 908 MCLK = rate * mclk_fs; 909 mdiv = clksrc / MCLK; // 4 910 sdiv = mclk_fs / 64; // 4 911 912 switch (mdiv) { 913 case 1: 914 reg |= MCLK_DIV1; 915 break; 916 case 3: 917 reg |= MCLK_DIV3; 918 break; 919 case 5: 920 reg |= MCLK_DIV5; 921 break; 922 default: 923 reg |= ((mdiv / 2 - 1) << 24) & 0x1f000000; 924 break; 925 } 926 927 switch (sdiv) { 928 case 1: 929 reg |= SCLK_DIV1; 930 break; 931 case 3: 932 reg |= SCLK_DIV3; 933 break; 934 default: 935 reg |= ((sdiv / 2 - 1) << 20) & 0x00f00000; 936 break; 937 } 938 939 reg |= SCLK_MASTER; /* XXX master mode */ 940 941 reg |= SERIAL_64x; 942 943 /* stereo input and output */ 944 DPRINTF("I2SSetDataWordSizeReg 0x%08x -> 0x%08x\n", 945 in32rb(sc->sc_reg + I2S_WORDSIZE), 0x02000200); 946 out32rb(sc->sc_reg + I2S_WORDSIZE, 0x02000200); 947 948 DPRINTF("I2SSetSerialFormatReg 0x%x -> 0x%x\n", 949 in32rb(sc->sc_reg + I2S_FORMAT), reg); 950 out32rb(sc->sc_reg + I2S_FORMAT, reg); 951 952 return 0; 953 } 954 955 #define DEQaddr 0x6a 956 957 const struct tas3004_reg tas3004_initdata = { 958 { DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_20 }, /* MCR1 */ 959 { 1, 0, 0, 0, 0, 0 }, /* DRC */ 960 { 0, 0, 0, 0, 0, 0 }, /* VOLUME */ 961 { 0x72 }, /* TREBLE */ 962 { 0x72 }, /* BASS */ 963 { 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 }, /* MIXER_L */ 964 { 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 }, /* MIXER_R */ 965 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 966 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 967 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 968 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 969 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 970 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 971 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 972 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 973 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 974 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 975 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 976 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 977 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 978 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 979 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 980 { 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* BIQUAD */ 981 { 0, 0, 0 }, /* LLB_GAIN */ 982 { 0, 0, 0 }, /* RLB_GAIN */ 983 { 0 }, /* ACR */ 984 { 0 } /* MCR2 */ 985 }; 986 987 const char tas3004_regsize[] = { 988 0, /* 0x00 */ 989 sizeof tas3004_initdata.MCR1, /* 0x01 */ 990 sizeof tas3004_initdata.DRC, /* 0x02 */ 991 0, /* 0x03 */ 992 sizeof tas3004_initdata.VOLUME, /* 0x04 */ 993 sizeof tas3004_initdata.TREBLE, /* 0x05 */ 994 sizeof tas3004_initdata.BASS, /* 0x06 */ 995 sizeof tas3004_initdata.MIXER_L, /* 0x07 */ 996 sizeof tas3004_initdata.MIXER_R, /* 0x08 */ 997 0, /* 0x09 */ 998 sizeof tas3004_initdata.LB0, /* 0x0a */ 999 sizeof tas3004_initdata.LB1, /* 0x0b */ 1000 sizeof tas3004_initdata.LB2, /* 0x0c */ 1001 sizeof tas3004_initdata.LB3, /* 0x0d */ 1002 sizeof tas3004_initdata.LB4, /* 0x0e */ 1003 sizeof tas3004_initdata.LB5, /* 0x0f */ 1004 sizeof tas3004_initdata.LB6, /* 0x10 */ 1005 0, /* 0x11 */ 1006 0, /* 0x12 */ 1007 sizeof tas3004_initdata.RB0, /* 0x13 */ 1008 sizeof tas3004_initdata.RB1, /* 0x14 */ 1009 sizeof tas3004_initdata.RB2, /* 0x15 */ 1010 sizeof tas3004_initdata.RB3, /* 0x16 */ 1011 sizeof tas3004_initdata.RB4, /* 0x17 */ 1012 sizeof tas3004_initdata.RB5, /* 0x18 */ 1013 sizeof tas3004_initdata.RB6, /* 0x19 */ 1014 0,0,0,0, 0,0, 1015 0, /* 0x20 */ 1016 sizeof tas3004_initdata.LLB, /* 0x21 */ 1017 sizeof tas3004_initdata.RLB, /* 0x22 */ 1018 sizeof tas3004_initdata.LLB_GAIN, /* 0x23 */ 1019 sizeof tas3004_initdata.RLB_GAIN, /* 0x24 */ 1020 0,0,0,0, 0,0,0,0, 0,0,0, 1021 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1022 sizeof tas3004_initdata.ACR, /* 0x40 */ 1023 0, /* 0x41 */ 1024 0, /* 0x42 */ 1025 sizeof tas3004_initdata.MCR2 /* 0x43 */ 1026 }; 1027 1028 int 1029 tas3004_write(struct snapper_softc *sc, u_int reg, const void *data) 1030 { 1031 int size; 1032 1033 KASSERT(reg < sizeof tas3004_regsize); 1034 size = tas3004_regsize[reg]; 1035 KASSERT(size > 0); 1036 1037 if (ki2c_write(sc->sc_i2c, DEQaddr, reg, data, size)) 1038 return -1; 1039 1040 return 0; 1041 } 1042 1043 int 1044 gpio_read(char *addr) 1045 { 1046 1047 if (*addr & GPIO_DATA) 1048 return 1; 1049 return 0; 1050 } 1051 1052 void 1053 gpio_write(char *addr, int val) 1054 { 1055 u_int data; 1056 1057 data = GPIO_DDR_OUTPUT; 1058 if (val) 1059 data |= GPIO_DATA; 1060 *addr = data; 1061 asm volatile ("eieio"); 1062 } 1063 1064 #define headphone_active 0 /* XXX OF */ 1065 #define amp_active 0 /* XXX OF */ 1066 1067 void 1068 snapper_mute_speaker(struct snapper_softc *sc, int mute) 1069 { 1070 u_int x; 1071 1072 DPRINTF("ampmute %d --> ", gpio_read(amp_mute)); 1073 1074 if (mute) 1075 x = amp_active; /* mute */ 1076 else 1077 x = !amp_active; /* unmute */ 1078 if (x != gpio_read(amp_mute)) 1079 gpio_write(amp_mute, x); 1080 1081 DPRINTF("%d\n", gpio_read(amp_mute)); 1082 } 1083 1084 void 1085 snapper_mute_headphone(struct snapper_softc *sc, int mute) 1086 { 1087 u_int x; 1088 1089 DPRINTF("headphonemute %d --> ", gpio_read(headphone_mute)); 1090 1091 if (mute) 1092 x = headphone_active; /* mute */ 1093 else 1094 x = !headphone_active; /* unmute */ 1095 if (x != gpio_read(headphone_mute)) 1096 gpio_write(headphone_mute, x); 1097 1098 DPRINTF("%d\n", gpio_read(headphone_mute)); 1099 } 1100 1101 int 1102 snapper_cint(void *v) 1103 { 1104 struct snapper_softc *sc; 1105 u_int sense; 1106 1107 sc = v; 1108 sense = *headphone_detect; 1109 DPRINTF("headphone detect = 0x%x\n", sense); 1110 1111 if (((sense & 0x02) >> 1) == headphone_detect_active) { 1112 DPRINTF("headphone is inserted\n"); 1113 snapper_mute_speaker(sc, 1); 1114 snapper_mute_headphone(sc, 0); 1115 sc->sc_output_mask = 1 << 1; 1116 } else { 1117 DPRINTF("headphone is NOT inserted\n"); 1118 snapper_mute_speaker(sc, 0); 1119 snapper_mute_headphone(sc, 1); 1120 sc->sc_output_mask = 1 << 0; 1121 } 1122 1123 return 1; 1124 } 1125 1126 #define reset_active 0 /* XXX OF */ 1127 1128 #define DEQ_WRITE(sc, reg, addr) \ 1129 if (tas3004_write(sc, reg, addr)) goto err 1130 1131 int 1132 tas3004_init(struct snapper_softc *sc) 1133 { 1134 1135 /* No reset port. Nothing to do. */ 1136 if (audio_hw_reset == NULL) 1137 goto noreset; 1138 1139 /* Reset TAS3004. */ 1140 gpio_write(audio_hw_reset, !reset_active); /* Negate RESET */ 1141 delay(100000); /* XXX Really needed? */ 1142 1143 gpio_write(audio_hw_reset, reset_active); /* Assert RESET */ 1144 delay(1); 1145 1146 gpio_write(audio_hw_reset, !reset_active); /* Negate RESET */ 1147 delay(10000); 1148 1149 noreset: 1150 DEQ_WRITE(sc, DEQ_LB0, tas3004_initdata.LB0); 1151 DEQ_WRITE(sc, DEQ_LB1, tas3004_initdata.LB1); 1152 DEQ_WRITE(sc, DEQ_LB2, tas3004_initdata.LB2); 1153 DEQ_WRITE(sc, DEQ_LB3, tas3004_initdata.LB3); 1154 DEQ_WRITE(sc, DEQ_LB4, tas3004_initdata.LB4); 1155 DEQ_WRITE(sc, DEQ_LB5, tas3004_initdata.LB5); 1156 DEQ_WRITE(sc, DEQ_LB6, tas3004_initdata.LB6); 1157 DEQ_WRITE(sc, DEQ_RB0, tas3004_initdata.RB0); 1158 DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1); 1159 DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1); 1160 DEQ_WRITE(sc, DEQ_RB2, tas3004_initdata.RB2); 1161 DEQ_WRITE(sc, DEQ_RB3, tas3004_initdata.RB3); 1162 DEQ_WRITE(sc, DEQ_RB4, tas3004_initdata.RB4); 1163 DEQ_WRITE(sc, DEQ_RB5, tas3004_initdata.RB5); 1164 DEQ_WRITE(sc, DEQ_MCR1, tas3004_initdata.MCR1); 1165 DEQ_WRITE(sc, DEQ_MCR2, tas3004_initdata.MCR2); 1166 DEQ_WRITE(sc, DEQ_DRC, tas3004_initdata.DRC); 1167 DEQ_WRITE(sc, DEQ_VOLUME, tas3004_initdata.VOLUME); 1168 DEQ_WRITE(sc, DEQ_TREBLE, tas3004_initdata.TREBLE); 1169 DEQ_WRITE(sc, DEQ_BASS, tas3004_initdata.BASS); 1170 DEQ_WRITE(sc, DEQ_MIXER_L, tas3004_initdata.MIXER_L); 1171 DEQ_WRITE(sc, DEQ_MIXER_R, tas3004_initdata.MIXER_R); 1172 DEQ_WRITE(sc, DEQ_LLB, tas3004_initdata.LLB); 1173 DEQ_WRITE(sc, DEQ_RLB, tas3004_initdata.RLB); 1174 DEQ_WRITE(sc, DEQ_LLB_GAIN, tas3004_initdata.LLB_GAIN); 1175 DEQ_WRITE(sc, DEQ_RLB_GAIN, tas3004_initdata.RLB_GAIN); 1176 DEQ_WRITE(sc, DEQ_ACR, tas3004_initdata.ACR); 1177 1178 return 0; 1179 err: 1180 printf("tas3004_init: error\n"); 1181 return -1; 1182 } 1183 1184 /* FCR(0x3c) bits */ 1185 #define I2S0CLKEN 0x1000 1186 #define I2S0EN 0x2000 1187 #define I2S1CLKEN 0x080000 1188 #define I2S1EN 0x100000 1189 1190 #define FCR3C_BITMASK "\020\25I2S1EN\24I2S1CLKEN\16I2S0EN\15I2S0CLKEN" 1191 1192 void 1193 snapper_init(struct snapper_softc *sc, int node) 1194 { 1195 int gpio; 1196 int headphone_detect_intr, headphone_detect_intrtype; 1197 #ifdef SNAPPER_DEBUG 1198 char fcr[32]; 1199 1200 bitmask_snprintf(in32rb(0x8000003c), FCR3C_BITMASK, fcr, sizeof fcr); 1201 printf("FCR(0x3c) 0x%s\n", fcr); 1202 #endif 1203 headphone_detect_intr = -1; 1204 1205 gpio = getnodebyname(OF_parent(node), "gpio"); 1206 DPRINTF(" /gpio 0x%x\n", gpio); 1207 gpio = OF_child(gpio); 1208 while (gpio) { 1209 char name[64], audio_gpio[64]; 1210 int intr[2]; 1211 char *addr; 1212 1213 bzero(name, sizeof name); 1214 bzero(audio_gpio, sizeof audio_gpio); 1215 addr = 0; 1216 OF_getprop(gpio, "name", name, sizeof name); 1217 OF_getprop(gpio, "audio-gpio", audio_gpio, sizeof audio_gpio); 1218 OF_getprop(gpio, "AAPL,address", &addr, sizeof addr); 1219 /* printf("0x%x %s %s\n", gpio, name, audio_gpio); */ 1220 1221 /* gpio5 */ 1222 if (strcmp(audio_gpio, "headphone-mute") == 0) 1223 headphone_mute = addr; 1224 /* gpio6 */ 1225 if (strcmp(audio_gpio, "amp-mute") == 0) 1226 amp_mute = addr; 1227 /* extint-gpio15 */ 1228 if (strcmp(audio_gpio, "headphone-detect") == 0) { 1229 headphone_detect = addr; 1230 OF_getprop(gpio, "audio-gpio-active-state", 1231 &headphone_detect_active, 4); 1232 OF_getprop(gpio, "interrupts", intr, 8); 1233 headphone_detect_intr = intr[0]; 1234 headphone_detect_intrtype = intr[1]; 1235 } 1236 /* gpio11 (keywest-11) */ 1237 if (strcmp(audio_gpio, "audio-hw-reset") == 0) 1238 audio_hw_reset = addr; 1239 gpio = OF_peer(gpio); 1240 } 1241 DPRINTF(" headphone-mute %p\n", headphone_mute); 1242 DPRINTF(" amp-mute %p\n", amp_mute); 1243 DPRINTF(" headphone-detect %p\n", headphone_detect); 1244 DPRINTF(" headphone-detect active %x\n", headphone_detect_active); 1245 DPRINTF(" headphone-detect intr %x\n", headphone_detect_intr); 1246 DPRINTF(" audio-hw-reset %p\n", audio_hw_reset); 1247 1248 if (headphone_detect_intr != -1) 1249 intr_establish(headphone_detect_intr, IST_EDGE, IPL_AUDIO, 1250 snapper_cint, sc); 1251 1252 /* "sample-rates" (44100, 48000) */ 1253 snapper_set_rate(sc, 44100); 1254 1255 /* Enable headphone interrupt? */ 1256 *headphone_detect |= 0x80; 1257 asm volatile ("eieio"); 1258 1259 /* i2c_set_port(port); */ 1260 1261 #if 1 1262 /* Enable I2C interrupts. */ 1263 #define IER 4 1264 #define I2C_INT_DATA 0x01 1265 #define I2C_INT_ADDR 0x02 1266 #define I2C_INT_STOP 0x04 1267 ki2c_writereg(sc->sc_i2c, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP); 1268 #endif 1269 1270 if (tas3004_init(sc)) 1271 return; 1272 1273 /* Update headphone status. */ 1274 snapper_cint(sc); 1275 1276 snapper_set_volume(sc, 80, 80); 1277 } 1278