1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* 3 * PMac AWACS lowlevel functions 4 * 5 * Copyright (c) by Takashi Iwai <tiwai@suse.d 6 * code based on dmasound.c. 7 */ 8 9 10 #include <linux/io.h> 11 #include <asm/nvram.h> 12 #include <linux/init.h> 13 #include <linux/delay.h> 14 #include <linux/of.h> 15 #include <linux/slab.h> 16 #include <sound/core.h> 17 #include "pmac.h" 18 19 20 #ifdef CONFIG_ADB_CUDA 21 #define PMAC_AMP_AVAIL 22 #endif 23 24 #ifdef PMAC_AMP_AVAIL 25 struct awacs_amp { 26 unsigned char amp_master; 27 unsigned char amp_vol[2][2]; 28 unsigned char amp_tone[2]; 29 }; 30 31 #define CHECK_CUDA_AMP() (sys_ctrler == SYS_CT 32 33 #endif /* PMAC_AMP_AVAIL */ 34 35 36 static void snd_pmac_screamer_wait(struct snd_ 37 { 38 long timeout = 2000; 39 while (!(in_le32(&chip->awacs->codec_s 40 mdelay(1); 41 if (! --timeout) { 42 snd_printd("snd_pmac_s 43 break; 44 } 45 } 46 } 47 48 /* 49 * write AWACS register 50 */ 51 static void 52 snd_pmac_awacs_write(struct snd_pmac *chip, in 53 { 54 long timeout = 5000000; 55 56 if (chip->model == PMAC_SCREAMER) 57 snd_pmac_screamer_wait(chip); 58 out_le32(&chip->awacs->codec_ctrl, val 59 while (in_le32(&chip->awacs->codec_ctr 60 if (! --timeout) { 61 snd_printd("snd_pmac_a 62 break; 63 } 64 } 65 } 66 67 static void 68 snd_pmac_awacs_write_reg(struct snd_pmac *chip 69 { 70 snd_pmac_awacs_write(chip, val | (reg 71 chip->awacs_reg[reg] = val; 72 } 73 74 static void 75 snd_pmac_awacs_write_noreg(struct snd_pmac *ch 76 { 77 snd_pmac_awacs_write(chip, val | (reg 78 } 79 80 #ifdef CONFIG_PM 81 /* Recalibrate chip */ 82 static void screamer_recalibrate(struct snd_pm 83 { 84 if (chip->model != PMAC_SCREAMER) 85 return; 86 87 /* Sorry for the horrible delays... I 88 * by making the whole PM process asyn 89 */ 90 snd_pmac_awacs_write_noreg(chip, 1, ch 91 if (chip->manufacturer == 0x1) 92 /* delay for broken crystal pa 93 msleep(750); 94 snd_pmac_awacs_write_noreg(chip, 1, 95 chip->awacs 96 MASK_CMUTE 97 snd_pmac_awacs_write_noreg(chip, 1, ch 98 snd_pmac_awacs_write_noreg(chip, 6, ch 99 } 100 101 #else 102 #define screamer_recalibrate(chip) /* NOP */ 103 #endif 104 105 106 /* 107 * additional callback to set the pcm format 108 */ 109 static void snd_pmac_awacs_set_format(struct s 110 { 111 chip->awacs_reg[1] &= ~MASK_SAMPLERATE 112 chip->awacs_reg[1] |= chip->rate_index 113 snd_pmac_awacs_write_reg(chip, 1, chip 114 } 115 116 117 /* 118 * AWACS volume callbacks 119 */ 120 /* 121 * volumes: 0-15 stereo 122 */ 123 static int snd_pmac_awacs_info_volume(struct s 124 struct s 125 { 126 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE 127 uinfo->count = 2; 128 uinfo->value.integer.min = 0; 129 uinfo->value.integer.max = 15; 130 return 0; 131 } 132 133 static int snd_pmac_awacs_get_volume(struct sn 134 struct sn 135 { 136 struct snd_pmac *chip = snd_kcontrol_c 137 int reg = kcontrol->private_value & 0x 138 int lshift = (kcontrol->private_value 139 int inverted = (kcontrol->private_valu 140 unsigned long flags; 141 int vol[2]; 142 143 spin_lock_irqsave(&chip->reg_lock, fla 144 vol[0] = (chip->awacs_reg[reg] >> lshi 145 vol[1] = chip->awacs_reg[reg] & 0xf; 146 spin_unlock_irqrestore(&chip->reg_lock 147 if (inverted) { 148 vol[0] = 0x0f - vol[0]; 149 vol[1] = 0x0f - vol[1]; 150 } 151 ucontrol->value.integer.value[0] = vol 152 ucontrol->value.integer.value[1] = vol 153 return 0; 154 } 155 156 static int snd_pmac_awacs_put_volume(struct sn 157 struct sn 158 { 159 struct snd_pmac *chip = snd_kcontrol_c 160 int reg = kcontrol->private_value & 0x 161 int lshift = (kcontrol->private_value 162 int inverted = (kcontrol->private_valu 163 int val, oldval; 164 unsigned long flags; 165 unsigned int vol[2]; 166 167 vol[0] = ucontrol->value.integer.value 168 vol[1] = ucontrol->value.integer.value 169 if (vol[0] > 0x0f || vol[1] > 0x0f) 170 return -EINVAL; 171 if (inverted) { 172 vol[0] = 0x0f - vol[0]; 173 vol[1] = 0x0f - vol[1]; 174 } 175 vol[0] &= 0x0f; 176 vol[1] &= 0x0f; 177 spin_lock_irqsave(&chip->reg_lock, fla 178 oldval = chip->awacs_reg[reg]; 179 val = oldval & ~(0xf | (0xf << lshift) 180 val |= vol[0] << lshift; 181 val |= vol[1]; 182 if (oldval != val) 183 snd_pmac_awacs_write_reg(chip, 184 spin_unlock_irqrestore(&chip->reg_lock 185 return oldval != reg; 186 } 187 188 189 #define AWACS_VOLUME(xname, xreg, xshift, xinv 190 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = 191 .info = snd_pmac_awacs_info_volume, \ 192 .get = snd_pmac_awacs_get_volume, \ 193 .put = snd_pmac_awacs_put_volume, \ 194 .private_value = (xreg) | ((xshift) << 8) | 195 196 /* 197 * mute master/ogain for AWACS: mono 198 */ 199 static int snd_pmac_awacs_get_switch(struct sn 200 struct sn 201 { 202 struct snd_pmac *chip = snd_kcontrol_c 203 int reg = kcontrol->private_value & 0x 204 int shift = (kcontrol->private_value > 205 int invert = (kcontrol->private_value 206 int val; 207 unsigned long flags; 208 209 spin_lock_irqsave(&chip->reg_lock, fla 210 val = (chip->awacs_reg[reg] >> shift) 211 spin_unlock_irqrestore(&chip->reg_lock 212 if (invert) 213 val = 1 - val; 214 ucontrol->value.integer.value[0] = val 215 return 0; 216 } 217 218 static int snd_pmac_awacs_put_switch(struct sn 219 struct sn 220 { 221 struct snd_pmac *chip = snd_kcontrol_c 222 int reg = kcontrol->private_value & 0x 223 int shift = (kcontrol->private_value > 224 int invert = (kcontrol->private_value 225 int mask = 1 << shift; 226 int val, changed; 227 unsigned long flags; 228 229 spin_lock_irqsave(&chip->reg_lock, fla 230 val = chip->awacs_reg[reg] & ~mask; 231 if (ucontrol->value.integer.value[0] ! 232 val |= mask; 233 changed = chip->awacs_reg[reg] != val; 234 if (changed) 235 snd_pmac_awacs_write_reg(chip, 236 spin_unlock_irqrestore(&chip->reg_lock 237 return changed; 238 } 239 240 #define AWACS_SWITCH(xname, xreg, xshift, xinv 241 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = 242 .info = snd_pmac_boolean_mono_info, \ 243 .get = snd_pmac_awacs_get_switch, \ 244 .put = snd_pmac_awacs_put_switch, \ 245 .private_value = (xreg) | ((xshift) << 8) | 246 247 248 #ifdef PMAC_AMP_AVAIL 249 /* 250 * controls for perch/whisper extension cards, 251 * 252 * TDA7433 connected via i2c address 0x45 (= 0 253 * accessed through cuda 254 */ 255 static void awacs_set_cuda(int reg, int val) 256 { 257 struct adb_request req; 258 cuda_request(&req, NULL, 5, CUDA_PACKE 259 reg, val); 260 while (! req.complete) 261 cuda_poll(); 262 } 263 264 /* 265 * level = 0 - 14, 7 = 0 dB 266 */ 267 static void awacs_amp_set_tone(struct awacs_am 268 { 269 amp->amp_tone[0] = bass; 270 amp->amp_tone[1] = treble; 271 if (bass > 7) 272 bass = (14 - bass) + 8; 273 if (treble > 7) 274 treble = (14 - treble) + 8; 275 awacs_set_cuda(2, (bass << 4) | treble 276 } 277 278 /* 279 * vol = 0 - 31 (attenuation), 32 = mute bit, 280 */ 281 static int awacs_amp_set_vol(struct awacs_amp 282 int lvol, int rvo 283 { 284 if (do_check && amp->amp_vol[index][0] 285 amp->amp_vol[index][1] 286 return 0; 287 awacs_set_cuda(3 + index, lvol); 288 awacs_set_cuda(5 + index, rvol); 289 amp->amp_vol[index][0] = lvol; 290 amp->amp_vol[index][1] = rvol; 291 return 1; 292 } 293 294 /* 295 * 0 = -79 dB, 79 = 0 dB, 99 = +20 dB 296 */ 297 static void awacs_amp_set_master(struct awacs_ 298 { 299 amp->amp_master = vol; 300 if (vol <= 79) 301 vol = 32 + (79 - vol); 302 else 303 vol = 32 - (vol - 79); 304 awacs_set_cuda(1, vol); 305 } 306 307 static void awacs_amp_free(struct snd_pmac *ch 308 { 309 struct awacs_amp *amp = chip->mixer_da 310 if (!amp) 311 return; 312 kfree(amp); 313 chip->mixer_data = NULL; 314 chip->mixer_free = NULL; 315 } 316 317 318 /* 319 * mixer controls 320 */ 321 static int snd_pmac_awacs_info_volume_amp(stru 322 stru 323 { 324 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE 325 uinfo->count = 2; 326 uinfo->value.integer.min = 0; 327 uinfo->value.integer.max = 31; 328 return 0; 329 } 330 331 static int snd_pmac_awacs_get_volume_amp(struc 332 struc 333 { 334 struct snd_pmac *chip = snd_kcontrol_c 335 int index = kcontrol->private_value; 336 struct awacs_amp *amp = chip->mixer_da 337 338 ucontrol->value.integer.value[0] = 31 339 ucontrol->value.integer.value[1] = 31 340 return 0; 341 } 342 343 static int snd_pmac_awacs_put_volume_amp(struc 344 struc 345 { 346 struct snd_pmac *chip = snd_kcontrol_c 347 int index = kcontrol->private_value; 348 int vol[2]; 349 struct awacs_amp *amp = chip->mixer_da 350 351 vol[0] = (31 - (ucontrol->value.intege 352 | (amp->amp_vol[index][0] & 32 353 vol[1] = (31 - (ucontrol->value.intege 354 | (amp->amp_vol[index][1] & 32 355 return awacs_amp_set_vol(amp, index, v 356 } 357 358 static int snd_pmac_awacs_get_switch_amp(struc 359 struc 360 { 361 struct snd_pmac *chip = snd_kcontrol_c 362 int index = kcontrol->private_value; 363 struct awacs_amp *amp = chip->mixer_da 364 365 ucontrol->value.integer.value[0] = (am 366 ? 0 : 367 ucontrol->value.integer.value[1] = (am 368 ? 0 : 369 return 0; 370 } 371 372 static int snd_pmac_awacs_put_switch_amp(struc 373 struc 374 { 375 struct snd_pmac *chip = snd_kcontrol_c 376 int index = kcontrol->private_value; 377 int vol[2]; 378 struct awacs_amp *amp = chip->mixer_da 379 380 vol[0] = (ucontrol->value.integer.valu 381 | (amp->amp_vol[index][0] & 31 382 vol[1] = (ucontrol->value.integer.valu 383 | (amp->amp_vol[index][1] & 31 384 return awacs_amp_set_vol(amp, index, v 385 } 386 387 static int snd_pmac_awacs_info_tone_amp(struct 388 struct 389 { 390 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE 391 uinfo->count = 1; 392 uinfo->value.integer.min = 0; 393 uinfo->value.integer.max = 14; 394 return 0; 395 } 396 397 static int snd_pmac_awacs_get_tone_amp(struct 398 struct 399 { 400 struct snd_pmac *chip = snd_kcontrol_c 401 int index = kcontrol->private_value; 402 struct awacs_amp *amp = chip->mixer_da 403 404 ucontrol->value.integer.value[0] = amp 405 return 0; 406 } 407 408 static int snd_pmac_awacs_put_tone_amp(struct 409 struct 410 { 411 struct snd_pmac *chip = snd_kcontrol_c 412 int index = kcontrol->private_value; 413 struct awacs_amp *amp = chip->mixer_da 414 unsigned int val; 415 416 val = ucontrol->value.integer.value[0] 417 if (val > 14) 418 return -EINVAL; 419 if (val != amp->amp_tone[index]) { 420 amp->amp_tone[index] = val; 421 awacs_amp_set_tone(amp, amp->a 422 return 1; 423 } 424 return 0; 425 } 426 427 static int snd_pmac_awacs_info_master_amp(stru 428 stru 429 { 430 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE 431 uinfo->count = 1; 432 uinfo->value.integer.min = 0; 433 uinfo->value.integer.max = 99; 434 return 0; 435 } 436 437 static int snd_pmac_awacs_get_master_amp(struc 438 struc 439 { 440 struct snd_pmac *chip = snd_kcontrol_c 441 struct awacs_amp *amp = chip->mixer_da 442 443 ucontrol->value.integer.value[0] = amp 444 return 0; 445 } 446 447 static int snd_pmac_awacs_put_master_amp(struc 448 struc 449 { 450 struct snd_pmac *chip = snd_kcontrol_c 451 struct awacs_amp *amp = chip->mixer_da 452 unsigned int val; 453 454 val = ucontrol->value.integer.value[0] 455 if (val > 99) 456 return -EINVAL; 457 if (val != amp->amp_master) { 458 amp->amp_master = val; 459 awacs_amp_set_master(amp, amp- 460 return 1; 461 } 462 return 0; 463 } 464 465 #define AMP_CH_SPK 0 466 #define AMP_CH_HD 1 467 468 static const struct snd_kcontrol_new snd_pmac_ 469 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 470 .name = "Speaker Playback Volume", 471 .info = snd_pmac_awacs_info_volume_a 472 .get = snd_pmac_awacs_get_volume_amp 473 .put = snd_pmac_awacs_put_volume_amp 474 .private_value = AMP_CH_SPK, 475 }, 476 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 477 .name = "Headphone Playback Volume", 478 .info = snd_pmac_awacs_info_volume_a 479 .get = snd_pmac_awacs_get_volume_amp 480 .put = snd_pmac_awacs_put_volume_amp 481 .private_value = AMP_CH_HD, 482 }, 483 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 484 .name = "Tone Control - Bass", 485 .info = snd_pmac_awacs_info_tone_amp 486 .get = snd_pmac_awacs_get_tone_amp, 487 .put = snd_pmac_awacs_put_tone_amp, 488 .private_value = 0, 489 }, 490 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 491 .name = "Tone Control - Treble", 492 .info = snd_pmac_awacs_info_tone_amp 493 .get = snd_pmac_awacs_get_tone_amp, 494 .put = snd_pmac_awacs_put_tone_amp, 495 .private_value = 1, 496 }, 497 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 498 .name = "Amp Master Playback Volume" 499 .info = snd_pmac_awacs_info_master_a 500 .get = snd_pmac_awacs_get_master_amp 501 .put = snd_pmac_awacs_put_master_amp 502 }, 503 }; 504 505 static const struct snd_kcontrol_new snd_pmac_ 506 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 507 .name = "Headphone Playback Switch", 508 .info = snd_pmac_boolean_stereo_info, 509 .get = snd_pmac_awacs_get_switch_amp, 510 .put = snd_pmac_awacs_put_switch_amp, 511 .private_value = AMP_CH_HD, 512 }; 513 514 static const struct snd_kcontrol_new snd_pmac_ 515 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 516 .name = "Speaker Playback Switch", 517 .info = snd_pmac_boolean_stereo_info, 518 .get = snd_pmac_awacs_get_switch_amp, 519 .put = snd_pmac_awacs_put_switch_amp, 520 .private_value = AMP_CH_SPK, 521 }; 522 523 #endif /* PMAC_AMP_AVAIL */ 524 525 526 /* 527 * mic boost for screamer 528 */ 529 static int snd_pmac_screamer_mic_boost_info(st 530 st 531 { 532 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE 533 uinfo->count = 1; 534 uinfo->value.integer.min = 0; 535 uinfo->value.integer.max = 3; 536 return 0; 537 } 538 539 static int snd_pmac_screamer_mic_boost_get(str 540 str 541 { 542 struct snd_pmac *chip = snd_kcontrol_c 543 int val = 0; 544 unsigned long flags; 545 546 spin_lock_irqsave(&chip->reg_lock, fla 547 if (chip->awacs_reg[6] & MASK_MIC_BOOS 548 val |= 2; 549 if (chip->awacs_reg[0] & MASK_GAINLINE 550 val |= 1; 551 spin_unlock_irqrestore(&chip->reg_lock 552 ucontrol->value.integer.value[0] = val 553 return 0; 554 } 555 556 static int snd_pmac_screamer_mic_boost_put(str 557 str 558 { 559 struct snd_pmac *chip = snd_kcontrol_c 560 int changed = 0; 561 int val0, val6; 562 unsigned long flags; 563 564 spin_lock_irqsave(&chip->reg_lock, fla 565 val0 = chip->awacs_reg[0] & ~MASK_GAIN 566 val6 = chip->awacs_reg[6] & ~MASK_MIC_ 567 if (ucontrol->value.integer.value[0] & 568 val0 |= MASK_GAINLINE; 569 if (ucontrol->value.integer.value[0] & 570 val6 |= MASK_MIC_BOOST; 571 if (val0 != chip->awacs_reg[0]) { 572 snd_pmac_awacs_write_reg(chip, 573 changed = 1; 574 } 575 if (val6 != chip->awacs_reg[6]) { 576 snd_pmac_awacs_write_reg(chip, 577 changed = 1; 578 } 579 spin_unlock_irqrestore(&chip->reg_lock 580 return changed; 581 } 582 583 /* 584 * lists of mixer elements 585 */ 586 static const struct snd_kcontrol_new snd_pmac_ 587 AWACS_SWITCH("Master Capture Switch", 588 AWACS_VOLUME("Master Capture Volume", 589 /* AWACS_SWITCH("Unknown Playback Switch" 590 }; 591 592 static const struct snd_kcontrol_new snd_pmac_ 593 AWACS_VOLUME("Master Playback Volume", 594 AWACS_VOLUME("Play-through Playback Vo 595 AWACS_SWITCH("Line Capture Switch", 0, 596 AWACS_SWITCH("CD Capture Switch", 0, S 597 }; 598 599 static const struct snd_kcontrol_new snd_pmac_ 600 AWACS_VOLUME("Line out Playback Volume 601 }; 602 603 static const struct snd_kcontrol_new snd_pmac_ 604 AWACS_VOLUME("Play-through Playback Vo 605 AWACS_SWITCH("CD Capture Switch", 0, S 606 }; 607 608 static const struct snd_kcontrol_new snd_pmac_ 609 AWACS_VOLUME("Line out Playback Volume 610 AWACS_VOLUME("Master Playback Volume", 611 AWACS_SWITCH("CD Capture Switch", 0, S 612 AWACS_SWITCH("Line Capture Switch", 0, 613 }; 614 615 static const struct snd_kcontrol_new snd_pmac_ 616 AWACS_VOLUME("Line out Playback Volume 617 AWACS_SWITCH("CD Capture Switch", 0, S 618 AWACS_SWITCH("Line Capture Switch", 0, 619 }; 620 621 static const struct snd_kcontrol_new snd_pmac_ 622 AWACS_VOLUME("Headphone Playback Volum 623 }; 624 625 static const struct snd_kcontrol_new snd_pmac_ 626 AWACS_VOLUME("Master Playback Volume", 627 AWACS_SWITCH("CD Capture Switch", 0, S 628 }; 629 630 /* FIXME: is this correct order? 631 * screamer (powerbook G3 pismo) seems to have 632 */ 633 static const struct snd_kcontrol_new snd_pmac_ 634 AWACS_SWITCH("Line Capture Switch", 0, 635 AWACS_SWITCH("Mic Capture Switch", 0, 636 }; 637 638 static const struct snd_kcontrol_new snd_pmac_ 639 AWACS_SWITCH("Line Capture Switch", 0, 640 AWACS_SWITCH("Mic Capture Switch", 0, 641 }; 642 643 static const struct snd_kcontrol_new snd_pmac_ 644 AWACS_SWITCH("CD Capture Switch", 0, S 645 }; 646 647 static const struct snd_kcontrol_new snd_pmac_ 648 AWACS_SWITCH("Master Playback Switch", 1, SHIF 649 650 static const struct snd_kcontrol_new snd_pmac_ 651 AWACS_SWITCH("Line out Playback Switch", 1, SH 652 653 static const struct snd_kcontrol_new snd_pmac_ 654 AWACS_SWITCH("Headphone Playback Switch", 1, S 655 656 static const struct snd_kcontrol_new snd_pmac_ 657 AWACS_SWITCH("Mic Boost Capture Switch 658 }; 659 660 static const struct snd_kcontrol_new snd_pmac_ 661 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 662 .name = "Mic Boost Capture Volume", 663 .info = snd_pmac_screamer_mic_boost_ 664 .get = snd_pmac_screamer_mic_boost_g 665 .put = snd_pmac_screamer_mic_boost_p 666 }, 667 }; 668 669 static const struct snd_kcontrol_new snd_pmac_ 670 { 671 AWACS_SWITCH("Line Boost Capture Switc 672 }; 673 674 static const struct snd_kcontrol_new snd_pmac_ 675 { 676 AWACS_SWITCH("Line Boost Capture Switc 677 AWACS_SWITCH("CD Boost Capture Switch" 678 }; 679 680 static const struct snd_kcontrol_new snd_pmac_ 681 { 682 AWACS_SWITCH("Line Boost Capture Switc 683 AWACS_SWITCH("Mic Boost Capture Switch 684 }; 685 686 static const struct snd_kcontrol_new snd_pmac_ 687 AWACS_VOLUME("Speaker Playback Volume" 688 }; 689 690 static const struct snd_kcontrol_new snd_pmac_ 691 AWACS_SWITCH("Speaker Playback Switch", 1, SHI 692 693 static const struct snd_kcontrol_new snd_pmac_ 694 AWACS_SWITCH("Speaker Playback Switch", 1, SHI 695 696 static const struct snd_kcontrol_new snd_pmac_ 697 AWACS_SWITCH("Speaker Playback Switch", 1, SHI 698 699 700 /* 701 * add new mixer elements to the card 702 */ 703 static int build_mixers(struct snd_pmac *chip, 704 const struct snd_kcont 705 { 706 int i, err; 707 708 for (i = 0; i < nums; i++) { 709 err = snd_ctl_add(chip->card, 710 if (err < 0) 711 return err; 712 } 713 return 0; 714 } 715 716 717 /* 718 * restore all registers 719 */ 720 static void awacs_restore_all_regs(struct snd_ 721 { 722 snd_pmac_awacs_write_noreg(chip, 0, ch 723 snd_pmac_awacs_write_noreg(chip, 1, ch 724 snd_pmac_awacs_write_noreg(chip, 2, ch 725 snd_pmac_awacs_write_noreg(chip, 4, ch 726 if (chip->model == PMAC_SCREAMER) { 727 snd_pmac_awacs_write_noreg(chi 728 snd_pmac_awacs_write_noreg(chi 729 snd_pmac_awacs_write_noreg(chi 730 } 731 } 732 733 #ifdef CONFIG_PM 734 static void snd_pmac_awacs_suspend(struct snd_ 735 { 736 snd_pmac_awacs_write_noreg(chip, 1, (c 737 | 738 } 739 740 static void snd_pmac_awacs_resume(struct snd_p 741 { 742 if (of_machine_is_compatible("PowerBoo 743 || of_machine_is_compatible("Power 744 msleep(100); 745 snd_pmac_awacs_write_reg(chip, 746 chip->awacs_reg[1] & ~ 747 msleep(300); 748 } 749 750 awacs_restore_all_regs(chip); 751 if (chip->model == PMAC_SCREAMER) { 752 /* reset power bits in reg 6 * 753 mdelay(5); 754 snd_pmac_awacs_write_noreg(chi 755 } 756 screamer_recalibrate(chip); 757 #ifdef PMAC_AMP_AVAIL 758 if (chip->mixer_data) { 759 struct awacs_amp *amp = chip-> 760 awacs_amp_set_vol(amp, 0, 761 amp->amp_vol 762 awacs_amp_set_vol(amp, 1, 763 amp->amp_vol 764 awacs_amp_set_tone(amp, amp->a 765 awacs_amp_set_master(amp, amp- 766 } 767 #endif 768 } 769 #endif /* CONFIG_PM */ 770 771 #define IS_PM7500 (of_machine_is_compatible("A 772 || of_machine_is_compatible("A 773 || of_machine_is_compatible("A 774 #define IS_PM5500 (of_machine_is_compatible("A 775 #define IS_BEIGE (of_machine_is_compatible("AA 776 #define IS_IMAC1 (of_machine_is_compatible("Po 777 #define IS_IMAC2 (of_machine_is_compatible("Po 778 || of_machine_is_compatible("P 779 #define IS_G4AGP (of_machine_is_compatible("Po 780 #define IS_LOMBARD (of_machine_is_compatible(" 781 782 static int imac1, imac2; 783 784 #ifdef PMAC_SUPPORT_AUTOMUTE 785 /* 786 * auto-mute stuffs 787 */ 788 static int snd_pmac_awacs_detect_headphone(str 789 { 790 return (in_le32(&chip->awacs->codec_st 791 } 792 793 #ifdef PMAC_AMP_AVAIL 794 static int toggle_amp_mute(struct awacs_amp *a 795 { 796 int vol[2]; 797 vol[0] = amp->amp_vol[index][0] & 31; 798 vol[1] = amp->amp_vol[index][1] & 31; 799 if (mute) { 800 vol[0] |= 32; 801 vol[1] |= 32; 802 } 803 return awacs_amp_set_vol(amp, index, v 804 } 805 #endif 806 807 static void snd_pmac_awacs_update_automute(str 808 { 809 if (chip->auto_mute) { 810 #ifdef PMAC_AMP_AVAIL 811 if (chip->mixer_data) { 812 struct awacs_amp *amp 813 int changed; 814 if (snd_pmac_awacs_det 815 changed = togg 816 changed |= tog 817 } else { 818 changed = togg 819 changed |= tog 820 } 821 if (do_notify && ! cha 822 return; 823 } else 824 #endif 825 { 826 int reg = chip->awacs_ 827 | (MASK_HDMUTE 828 if (imac1) { 829 reg &= ~MASK_S 830 reg |= MASK_PA 831 } else if (imac2) { 832 reg &= ~MASK_S 833 reg &= ~MASK_P 834 } 835 if (snd_pmac_awacs_det 836 reg &= ~MASK_H 837 else if (imac1) 838 reg &= ~MASK_P 839 else if (imac2) 840 reg |= MASK_PA 841 else 842 reg &= ~MASK_S 843 if (do_notify && reg = 844 return; 845 snd_pmac_awacs_write_r 846 } 847 if (do_notify) { 848 snd_ctl_notify(chip->c 849 &chip-> 850 snd_ctl_notify(chip->c 851 &chip-> 852 snd_ctl_notify(chip->c 853 &chip-> 854 } 855 } 856 } 857 #endif /* PMAC_SUPPORT_AUTOMUTE */ 858 859 860 /* 861 * initialize chip 862 */ 863 int 864 snd_pmac_awacs_init(struct snd_pmac *chip) 865 { 866 int pm7500 = IS_PM7500; 867 int pm5500 = IS_PM5500; 868 int beige = IS_BEIGE; 869 int g4agp = IS_G4AGP; 870 int lombard = IS_LOMBARD; 871 int imac; 872 int err, vol; 873 struct snd_kcontrol *vmaster_sw, *vmas 874 struct snd_kcontrol *master_vol, *spea 875 876 imac1 = IS_IMAC1; 877 imac2 = IS_IMAC2; 878 imac = imac1 || imac2; 879 /* looks like MASK_GAINLINE triggers s 880 * as start-up 881 */ 882 chip->awacs_reg[0] = MASK_MUX_CD | 0xf 883 chip->awacs_reg[1] = MASK_CMUTE | MASK 884 /* FIXME: Only machines with external 885 if (chip->has_iic || chip->device_id = 886 /* chip->_device_id == 0x8 || */ 887 chip->device_id == 0xb) 888 chip->awacs_reg[1] |= MASK_PAR 889 /* get default volume from nvram */ 890 // vol = (~nvram_read_byte(0x1308) & 7 891 // vol = ((pmac_xpram_read( 8 ) & 7 ) 892 vol = 0x0f; /* no, on alsa, muted as d 893 vol = vol + (vol << 6); 894 chip->awacs_reg[2] = vol; 895 chip->awacs_reg[4] = vol; 896 if (chip->model == PMAC_SCREAMER) { 897 /* FIXME: screamer has loopthr 898 chip->awacs_reg[5] = vol; 899 /* FIXME: maybe should be vol 900 chip->awacs_reg[6] = MASK_MIC_ 901 chip->awacs_reg[7] = 0; 902 } 903 904 awacs_restore_all_regs(chip); 905 chip->manufacturer = (in_le32(&chip->a 906 screamer_recalibrate(chip); 907 908 chip->revision = (in_le32(&chip->awacs 909 #ifdef PMAC_AMP_AVAIL 910 if (chip->revision == 3 && chip->has_i 911 struct awacs_amp *amp = kzallo 912 if (! amp) 913 return -ENOMEM; 914 chip->mixer_data = amp; 915 chip->mixer_free = awacs_amp_f 916 /* mute and zero vol */ 917 awacs_amp_set_vol(amp, 0, 63, 918 awacs_amp_set_vol(amp, 1, 63, 919 awacs_amp_set_tone(amp, 7, 7); 920 awacs_amp_set_master(amp, 79); 921 } 922 #endif /* PMAC_AMP_AVAIL */ 923 924 if (chip->hp_stat_mask == 0) { 925 /* set headphone-jack detectio 926 switch (chip->model) { 927 case PMAC_AWACS: 928 chip->hp_stat_mask = p 929 : MASK_LOCONN; 930 break; 931 case PMAC_SCREAMER: 932 switch (chip->device_i 933 case 0x08: 934 case 0x0B: 935 chip->hp_stat_ 936 ? MASK 937 MASK_H 938 MASK_H 939 : MASK 940 break; 941 case 0x00: 942 case 0x05: 943 chip->hp_stat_ 944 break; 945 default: 946 chip->hp_stat_ 947 break; 948 } 949 break; 950 default: 951 snd_BUG(); 952 break; 953 } 954 } 955 956 /* 957 * build mixers 958 */ 959 strcpy(chip->card->mixername, "PowerMa 960 961 err = build_mixers(chip, ARRAY_SIZE(sn 962 snd_pmac_awacs 963 if (err < 0) 964 return err; 965 if (beige || g4agp) 966 ; 967 else if (chip->model == PMAC_SCREAMER 968 err = build_mixers(chip, ARRAY 969 snd_pmac_sc 970 else if (!pm7500) 971 err = build_mixers(chip, ARRAY 972 snd_pmac_aw 973 if (err < 0) 974 return err; 975 if (pm5500) { 976 err = build_mixers(chip, 977 ARRAY_SIZE( 978 snd_pmac_aw 979 if (err < 0) 980 return err; 981 } 982 master_vol = NULL; 983 if (pm7500) 984 err = build_mixers(chip, 985 ARRAY_SIZE( 986 snd_pmac_aw 987 else if (pm5500) 988 err = snd_ctl_add(chip->card, 989 (master_vol = snd_ctl_new1 990 991 else if (beige) 992 err = build_mixers(chip, 993 ARRAY_SIZE( 994 snd_pmac_sc 995 else if (imac || lombard) { 996 err = snd_ctl_add(chip->card, 997 (master_vol = snd_ctl_new1 998 999 if (err < 0) 1000 return err; 1001 err = build_mixers(chip, 1002 ARRAY_SIZE 1003 snd_pmac_s 1004 } else if (g4agp) 1005 err = build_mixers(chip, 1006 ARRAY_SIZE 1007 snd_pmac_s 1008 else 1009 err = build_mixers(chip, 1010 ARRAY_SIZE 1011 snd_pmac_a 1012 if (err < 0) 1013 return err; 1014 chip->master_sw_ctl = snd_ctl_new1((p 1015 ? &snd_pmac_awacs_mas 1016 : pm5500 1017 ? &snd_pmac_awacs_mas 1018 : &snd_pmac_awacs_mas 1019 err = snd_ctl_add(chip->card, chip->m 1020 if (err < 0) 1021 return err; 1022 #ifdef PMAC_AMP_AVAIL 1023 if (chip->mixer_data) { 1024 /* use amplifier. the signal 1025 * to the amp. the amp has i 1026 * volumes and mute switches, 1027 * screamer registers. 1028 * in this case, it seems the 1029 */ 1030 err = build_mixers(chip, ARRA 1031 snd_p 1032 if (err < 0) 1033 return err; 1034 /* overwrite */ 1035 chip->master_sw_ctl = snd_ctl 1036 1037 err = snd_ctl_add(chip->card, 1038 if (err < 0) 1039 return err; 1040 chip->speaker_sw_ctl = snd_ct 1041 1042 err = snd_ctl_add(chip->card, 1043 if (err < 0) 1044 return err; 1045 } else 1046 #endif /* PMAC_AMP_AVAIL */ 1047 { 1048 /* route A = headphone, route 1049 err = snd_ctl_add(chip->card, 1050 (speaker_vol = snd_ctl_ne 1051 1052 if (err < 0) 1053 return err; 1054 chip->speaker_sw_ctl = snd_ct 1055 ? &snd_pmac_a 1056 : imac2 1057 ? &snd_pmac_a 1058 : &snd_pmac_a 1059 err = snd_ctl_add(chip->card, 1060 if (err < 0) 1061 return err; 1062 } 1063 1064 if (pm5500 || imac || lombard) { 1065 vmaster_sw = snd_ctl_make_vir 1066 "Master Playback Swit 1067 err = snd_ctl_add_follower_un 1068 1069 if (err < 0) 1070 return err; 1071 err = snd_ctl_add_follower_un 1072 1073 if (err < 0) 1074 return err; 1075 err = snd_ctl_add(chip->card, 1076 if (err < 0) 1077 return err; 1078 vmaster_vol = snd_ctl_make_vi 1079 "Master Playback Volu 1080 err = snd_ctl_add_follower(vm 1081 if (err < 0) 1082 return err; 1083 err = snd_ctl_add_follower(vm 1084 if (err < 0) 1085 return err; 1086 err = snd_ctl_add(chip->card, 1087 if (err < 0) 1088 return err; 1089 } 1090 1091 if (beige || g4agp) 1092 err = build_mixers(chip, 1093 ARRAY_SIZE(sn 1094 snd_pmac_scre 1095 else if (imac) 1096 err = build_mixers(chip, 1097 ARRAY_SIZE(sn 1098 snd_pmac_scre 1099 else if (chip->model == PMAC_SCREAMER 1100 err = build_mixers(chip, 1101 ARRAY_SIZE(sn 1102 snd_pmac_scre 1103 else if (pm7500) 1104 err = build_mixers(chip, 1105 ARRAY_SIZE(sn 1106 snd_pmac_awac 1107 else 1108 err = build_mixers(chip, ARRA 1109 snd_pmac_awac 1110 if (err < 0) 1111 return err; 1112 1113 /* 1114 * set lowlevel callbacks 1115 */ 1116 chip->set_format = snd_pmac_awacs_set 1117 #ifdef CONFIG_PM 1118 chip->suspend = snd_pmac_awacs_suspen 1119 chip->resume = snd_pmac_awacs_resume; 1120 #endif 1121 #ifdef PMAC_SUPPORT_AUTOMUTE 1122 err = snd_pmac_add_automute(chip); 1123 if (err < 0) 1124 return err; 1125 chip->detect_headphone = snd_pmac_awa 1126 chip->update_automute = snd_pmac_awac 1127 snd_pmac_awacs_update_automute(chip, 1128 #endif 1129 if (chip->model == PMAC_SCREAMER) { 1130 snd_pmac_awacs_write_noreg(ch 1131 snd_pmac_awacs_write_noreg(ch 1132 } 1133 1134 return 0; 1135 } 1136
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.