diff options
Diffstat (limited to 'sound/pci/hda/patch_cirrus.c')
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 072755c8289c..fc492ac24caa 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -47,6 +47,10 @@ struct cs_spec { | |||
47 | unsigned int spdif_present:1; | 47 | unsigned int spdif_present:1; |
48 | unsigned int sense_b:1; | 48 | unsigned int sense_b:1; |
49 | hda_nid_t vendor_nid; | 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 | /* available models with CS420x */ | 56 | /* available models with CS420x */ |
@@ -331,10 +335,21 @@ static int cs_init(struct hda_codec *codec) | |||
331 | return 0; | 335 | return 0; |
332 | } | 336 | } |
333 | 337 | ||
338 | static int cs_build_controls(struct hda_codec *codec) | ||
339 | { | ||
340 | int err; | ||
341 | |||
342 | err = snd_hda_gen_build_controls(codec); | ||
343 | if (err < 0) | ||
344 | return err; | ||
345 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); | ||
346 | return 0; | ||
347 | } | ||
348 | |||
334 | #define cs_free snd_hda_gen_free | 349 | #define cs_free snd_hda_gen_free |
335 | 350 | ||
336 | static const struct hda_codec_ops cs_patch_ops = { | 351 | static const struct hda_codec_ops cs_patch_ops = { |
337 | .build_controls = snd_hda_gen_build_controls, | 352 | .build_controls = cs_build_controls, |
338 | .build_pcms = snd_hda_gen_build_pcms, | 353 | .build_pcms = snd_hda_gen_build_pcms, |
339 | .init = cs_init, | 354 | .init = cs_init, |
340 | .free = cs_free, | 355 | .free = cs_free, |
@@ -599,12 +614,14 @@ static int patch_cs420x(struct hda_codec *codec) | |||
599 | enum { | 614 | enum { |
600 | CS4208_MAC_AUTO, | 615 | CS4208_MAC_AUTO, |
601 | CS4208_MBA6, | 616 | CS4208_MBA6, |
617 | CS4208_MBP11, | ||
602 | CS4208_GPIO0, | 618 | CS4208_GPIO0, |
603 | }; | 619 | }; |
604 | 620 | ||
605 | static const struct hda_model_fixup cs4208_models[] = { | 621 | static const struct hda_model_fixup cs4208_models[] = { |
606 | { .id = CS4208_GPIO0, .name = "gpio0" }, | 622 | { .id = CS4208_GPIO0, .name = "gpio0" }, |
607 | { .id = CS4208_MBA6, .name = "mba6" }, | 623 | { .id = CS4208_MBA6, .name = "mba6" }, |
624 | { .id = CS4208_MBP11, .name = "mbp11" }, | ||
608 | {} | 625 | {} |
609 | }; | 626 | }; |
610 | 627 | ||
@@ -615,6 +632,7 @@ static const struct snd_pci_quirk cs4208_fixup_tbl[] = { | |||
615 | 632 | ||
616 | /* codec SSID matching */ | 633 | /* codec SSID matching */ |
617 | static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = { | 634 | static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = { |
635 | SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11), | ||
618 | SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6), | 636 | SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6), |
619 | SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6), | 637 | SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6), |
620 | {} /* terminator */ | 638 | {} /* terminator */ |
@@ -646,6 +664,36 @@ static void cs4208_fixup_mac(struct hda_codec *codec, | |||
646 | snd_hda_apply_fixup(codec, action); | 664 | snd_hda_apply_fixup(codec, action); |
647 | } | 665 | } |
648 | 666 | ||
667 | static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol, | ||
668 | struct snd_ctl_elem_value *ucontrol) | ||
669 | { | ||
670 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
671 | struct cs_spec *spec = codec->spec; | ||
672 | hda_nid_t pin = spec->gen.autocfg.dig_out_pins[0]; | ||
673 | int pinctl = ucontrol->value.integer.value[0] ? PIN_OUT : 0; | ||
674 | |||
675 | snd_hda_set_pin_ctl_cache(codec, pin, pinctl); | ||
676 | return spec->spdif_sw_put(kcontrol, ucontrol); | ||
677 | } | ||
678 | |||
679 | /* hook the SPDIF switch */ | ||
680 | static void cs4208_fixup_spdif_switch(struct hda_codec *codec, | ||
681 | const struct hda_fixup *fix, int action) | ||
682 | { | ||
683 | if (action == HDA_FIXUP_ACT_BUILD) { | ||
684 | struct cs_spec *spec = codec->spec; | ||
685 | struct snd_kcontrol *kctl; | ||
686 | |||
687 | if (!spec->gen.autocfg.dig_out_pins[0]) | ||
688 | return; | ||
689 | kctl = snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch"); | ||
690 | if (!kctl) | ||
691 | return; | ||
692 | spec->spdif_sw_put = kctl->put; | ||
693 | kctl->put = cs4208_spdif_sw_put; | ||
694 | } | ||
695 | } | ||
696 | |||
649 | static const struct hda_fixup cs4208_fixups[] = { | 697 | static const struct hda_fixup cs4208_fixups[] = { |
650 | [CS4208_MBA6] = { | 698 | [CS4208_MBA6] = { |
651 | .type = HDA_FIXUP_PINS, | 699 | .type = HDA_FIXUP_PINS, |
@@ -653,6 +701,12 @@ static const struct hda_fixup cs4208_fixups[] = { | |||
653 | .chained = true, | 701 | .chained = true, |
654 | .chain_id = CS4208_GPIO0, | 702 | .chain_id = CS4208_GPIO0, |
655 | }, | 703 | }, |
704 | [CS4208_MBP11] = { | ||
705 | .type = HDA_FIXUP_FUNC, | ||
706 | .v.func = cs4208_fixup_spdif_switch, | ||
707 | .chained = true, | ||
708 | .chain_id = CS4208_GPIO0, | ||
709 | }, | ||
656 | [CS4208_GPIO0] = { | 710 | [CS4208_GPIO0] = { |
657 | .type = HDA_FIXUP_FUNC, | 711 | .type = HDA_FIXUP_FUNC, |
658 | .v.func = cs4208_fixup_gpio0, | 712 | .v.func = cs4208_fixup_gpio0, |