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