Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: hda - Control SPDIF out pin on MacBookPro 11,2

The SPDIF output MBP11,2 requires the pin control to be set/cleared
for turning on/off the optical SPDIF. The red light turns off only
when the corresponding pin control is cleared (or powered to D3).

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=64401
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+55 -1
+55 -1
sound/pci/hda/patch_cirrus.c
··· 47 47 unsigned int spdif_present:1; 48 48 unsigned int sense_b:1; 49 49 hda_nid_t vendor_nid; 50 + 51 + /* for MBP SPDIF control */ 52 + int (*spdif_sw_put)(struct snd_kcontrol *kcontrol, 53 + struct snd_ctl_elem_value *ucontrol); 50 54 }; 51 55 52 56 /* available models with CS420x */ ··· 335 331 return 0; 336 332 } 337 333 334 + static int cs_build_controls(struct hda_codec *codec) 335 + { 336 + int err; 337 + 338 + err = snd_hda_gen_build_controls(codec); 339 + if (err < 0) 340 + return err; 341 + snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); 342 + return 0; 343 + } 344 + 338 345 #define cs_free snd_hda_gen_free 339 346 340 347 static const struct hda_codec_ops cs_patch_ops = { 341 - .build_controls = snd_hda_gen_build_controls, 348 + .build_controls = cs_build_controls, 342 349 .build_pcms = snd_hda_gen_build_pcms, 343 350 .init = cs_init, 344 351 .free = cs_free, ··· 614 599 enum { 615 600 CS4208_MAC_AUTO, 616 601 CS4208_MBA6, 602 + CS4208_MBP11, 617 603 CS4208_GPIO0, 618 604 }; 619 605 620 606 static const struct hda_model_fixup cs4208_models[] = { 621 607 { .id = CS4208_GPIO0, .name = "gpio0" }, 622 608 { .id = CS4208_MBA6, .name = "mba6" }, 609 + { .id = CS4208_MBP11, .name = "mbp11" }, 623 610 {} 624 611 }; 625 612 ··· 632 615 633 616 /* codec SSID matching */ 634 617 static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = { 618 + SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11), 635 619 SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6), 636 620 SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6), 637 621 {} /* terminator */ ··· 664 646 snd_hda_apply_fixup(codec, action); 665 647 } 666 648 649 + static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol, 650 + struct snd_ctl_elem_value *ucontrol) 651 + { 652 + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 653 + struct cs_spec *spec = codec->spec; 654 + hda_nid_t pin = spec->gen.autocfg.dig_out_pins[0]; 655 + int pinctl = ucontrol->value.integer.value[0] ? PIN_OUT : 0; 656 + 657 + snd_hda_set_pin_ctl_cache(codec, pin, pinctl); 658 + return spec->spdif_sw_put(kcontrol, ucontrol); 659 + } 660 + 661 + /* hook the SPDIF switch */ 662 + static void cs4208_fixup_spdif_switch(struct hda_codec *codec, 663 + const struct hda_fixup *fix, int action) 664 + { 665 + if (action == HDA_FIXUP_ACT_BUILD) { 666 + struct cs_spec *spec = codec->spec; 667 + struct snd_kcontrol *kctl; 668 + 669 + if (!spec->gen.autocfg.dig_out_pins[0]) 670 + return; 671 + kctl = snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch"); 672 + if (!kctl) 673 + return; 674 + spec->spdif_sw_put = kctl->put; 675 + kctl->put = cs4208_spdif_sw_put; 676 + } 677 + } 678 + 667 679 static const struct hda_fixup cs4208_fixups[] = { 668 680 [CS4208_MBA6] = { 669 681 .type = HDA_FIXUP_PINS, 670 682 .v.pins = mba6_pincfgs, 683 + .chained = true, 684 + .chain_id = CS4208_GPIO0, 685 + }, 686 + [CS4208_MBP11] = { 687 + .type = HDA_FIXUP_FUNC, 688 + .v.func = cs4208_fixup_spdif_switch, 671 689 .chained = true, 672 690 .chain_id = CS4208_GPIO0, 673 691 },