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>
This commit is contained in:
Takashi Iwai 2013-11-08 13:03:57 +01:00
Родитель a6bc732b5a
Коммит 0c52db8cca
1 изменённых файлов: 55 добавлений и 1 удалений

Просмотреть файл

@ -47,6 +47,10 @@ struct cs_spec {
unsigned int spdif_present:1; unsigned int spdif_present:1;
unsigned int sense_b:1; unsigned int sense_b:1;
hda_nid_t vendor_nid; hda_nid_t vendor_nid;
/* for MBP SPDIF control */
int (*spdif_sw_put)(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
}; };
/* available models with CS420x */ /* available models with CS420x */
@ -331,10 +335,21 @@ static int cs_init(struct hda_codec *codec)
return 0; return 0;
} }
static int cs_build_controls(struct hda_codec *codec)
{
int err;
err = snd_hda_gen_build_controls(codec);
if (err < 0)
return err;
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
return 0;
}
#define cs_free snd_hda_gen_free #define cs_free snd_hda_gen_free
static const struct hda_codec_ops cs_patch_ops = { static const struct hda_codec_ops cs_patch_ops = {
.build_controls = snd_hda_gen_build_controls, .build_controls = cs_build_controls,
.build_pcms = snd_hda_gen_build_pcms, .build_pcms = snd_hda_gen_build_pcms,
.init = cs_init, .init = cs_init,
.free = cs_free, .free = cs_free,
@ -599,12 +614,14 @@ static int patch_cs420x(struct hda_codec *codec)
enum { enum {
CS4208_MAC_AUTO, CS4208_MAC_AUTO,
CS4208_MBA6, CS4208_MBA6,
CS4208_MBP11,
CS4208_GPIO0, CS4208_GPIO0,
}; };
static const struct hda_model_fixup cs4208_models[] = { static const struct hda_model_fixup cs4208_models[] = {
{ .id = CS4208_GPIO0, .name = "gpio0" }, { .id = CS4208_GPIO0, .name = "gpio0" },
{ .id = CS4208_MBA6, .name = "mba6" }, { .id = CS4208_MBA6, .name = "mba6" },
{ .id = CS4208_MBP11, .name = "mbp11" },
{} {}
}; };
@ -615,6 +632,7 @@ static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
/* codec SSID matching */ /* codec SSID matching */
static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = { static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6), SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6), SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
{} /* terminator */ {} /* terminator */
@ -646,6 +664,36 @@ static void cs4208_fixup_mac(struct hda_codec *codec,
snd_hda_apply_fixup(codec, action); snd_hda_apply_fixup(codec, action);
} }
static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cs_spec *spec = codec->spec;
hda_nid_t pin = spec->gen.autocfg.dig_out_pins[0];
int pinctl = ucontrol->value.integer.value[0] ? PIN_OUT : 0;
snd_hda_set_pin_ctl_cache(codec, pin, pinctl);
return spec->spdif_sw_put(kcontrol, ucontrol);
}
/* hook the SPDIF switch */
static void cs4208_fixup_spdif_switch(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_BUILD) {
struct cs_spec *spec = codec->spec;
struct snd_kcontrol *kctl;
if (!spec->gen.autocfg.dig_out_pins[0])
return;
kctl = snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch");
if (!kctl)
return;
spec->spdif_sw_put = kctl->put;
kctl->put = cs4208_spdif_sw_put;
}
}
static const struct hda_fixup cs4208_fixups[] = { static const struct hda_fixup cs4208_fixups[] = {
[CS4208_MBA6] = { [CS4208_MBA6] = {
.type = HDA_FIXUP_PINS, .type = HDA_FIXUP_PINS,
@ -653,6 +701,12 @@ static const struct hda_fixup cs4208_fixups[] = {
.chained = true, .chained = true,
.chain_id = CS4208_GPIO0, .chain_id = CS4208_GPIO0,
}, },
[CS4208_MBP11] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs4208_fixup_spdif_switch,
.chained = true,
.chain_id = CS4208_GPIO0,
},
[CS4208_GPIO0] = { [CS4208_GPIO0] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = cs4208_fixup_gpio0, .v.func = cs4208_fixup_gpio0,