ALSA: hda/hdmi - allow PIN_OUT to be dynamically enabled

Commit 384a48d71520 "ALSA: hda: HDMI: Support codecs with fewer cvts
than pins" dynamically enabled each pin widget's PIN_OUT only when the
pin was actively in use. This was required on certain NVIDIA CODECs for
correct operation. Specifically, if multiple pin widgets each had their
mux input select the same audio converter widget and each pin widget had
PIN_OUT enabled, then only one of the pin widgets would actually receive
the audio, and often not the one the user wanted!

However, this apparently broke some Intel systems, and commit
6169b673618b "ALSA: hda - Always turn on pins for HDMI/DP" reverted the
dynamic setting of PIN_OUT. This in turn broke the afore-mentioned NVIDIA
CODECs.

This change supports either dynamic or static handling of PIN_OUT,
selected by a flag set up during CODEC initialization. This flag is
enabled for all recent NVIDIA GPUs.

Reported-by: Uosis <uosisl@gmail.com>
Cc: <stable@vger.kernel.org> # v3.13
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by Stephen Warren and committed by Takashi Iwai 75fae117 5e87d580

+36 -4
+36 -4
sound/pci/hda/patch_hdmi.c
··· 132 133 struct hdmi_eld temp_eld; 134 struct hdmi_ops ops; 135 /* 136 * Non-generic VIA/NVIDIA specific 137 */ ··· 503 504 static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) 505 { 506 /* Unmute */ 507 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) 508 snd_hda_codec_write(codec, pin_nid, 0, 509 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 510 - /* Enable pin out: some machines with GM965 gets broken output when 511 - * the pin is disabled or changed while using with HDMI 512 - */ 513 snd_hda_codec_write(codec, pin_nid, 0, 514 - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 515 } 516 517 static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) ··· 1748 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 1749 hda_nid_t pin_nid = per_pin->pin_nid; 1750 bool non_pcm; 1751 1752 non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); 1753 mutex_lock(&per_pin->lock); ··· 1757 1758 hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); 1759 mutex_unlock(&per_pin->lock); 1760 1761 return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); 1762 } ··· 1785 int cvt_idx, pin_idx; 1786 struct hdmi_spec_per_cvt *per_cvt; 1787 struct hdmi_spec_per_pin *per_pin; 1788 1789 if (hinfo->nid) { 1790 cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); ··· 1801 if (snd_BUG_ON(pin_idx < 0)) 1802 return -EINVAL; 1803 per_pin = get_pin(spec, pin_idx); 1804 1805 snd_hda_spdif_ctls_unassign(codec, pin_idx); 1806 ··· 2871 return err; 2872 2873 spec = codec->spec; 2874 2875 spec->ops.chmap_cea_alloc_validate_get_type = 2876 nvhdmi_chmap_cea_alloc_validate_get_type;
··· 132 133 struct hdmi_eld temp_eld; 134 struct hdmi_ops ops; 135 + 136 + bool dyn_pin_out; 137 + 138 /* 139 * Non-generic VIA/NVIDIA specific 140 */ ··· 500 501 static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) 502 { 503 + struct hdmi_spec *spec = codec->spec; 504 + int pin_out; 505 + 506 /* Unmute */ 507 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) 508 snd_hda_codec_write(codec, pin_nid, 0, 509 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 510 + 511 + if (spec->dyn_pin_out) 512 + /* Disable pin out until stream is active */ 513 + pin_out = 0; 514 + else 515 + /* Enable pin out: some machines with GM965 gets broken output 516 + * when the pin is disabled or changed while using with HDMI 517 + */ 518 + pin_out = PIN_OUT; 519 + 520 snd_hda_codec_write(codec, pin_nid, 0, 521 + AC_VERB_SET_PIN_WIDGET_CONTROL, pin_out); 522 } 523 524 static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) ··· 1735 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 1736 hda_nid_t pin_nid = per_pin->pin_nid; 1737 bool non_pcm; 1738 + int pinctl; 1739 1740 non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); 1741 mutex_lock(&per_pin->lock); ··· 1743 1744 hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); 1745 mutex_unlock(&per_pin->lock); 1746 + 1747 + if (spec->dyn_pin_out) { 1748 + pinctl = snd_hda_codec_read(codec, pin_nid, 0, 1749 + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 1750 + snd_hda_codec_write(codec, pin_nid, 0, 1751 + AC_VERB_SET_PIN_WIDGET_CONTROL, 1752 + pinctl | PIN_OUT); 1753 + } 1754 1755 return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); 1756 } ··· 1763 int cvt_idx, pin_idx; 1764 struct hdmi_spec_per_cvt *per_cvt; 1765 struct hdmi_spec_per_pin *per_pin; 1766 + int pinctl; 1767 1768 if (hinfo->nid) { 1769 cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); ··· 1778 if (snd_BUG_ON(pin_idx < 0)) 1779 return -EINVAL; 1780 per_pin = get_pin(spec, pin_idx); 1781 + 1782 + if (spec->dyn_pin_out) { 1783 + pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, 1784 + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 1785 + snd_hda_codec_write(codec, per_pin->pin_nid, 0, 1786 + AC_VERB_SET_PIN_WIDGET_CONTROL, 1787 + pinctl & ~PIN_OUT); 1788 + } 1789 1790 snd_hda_spdif_ctls_unassign(codec, pin_idx); 1791 ··· 2840 return err; 2841 2842 spec = codec->spec; 2843 + spec->dyn_pin_out = true; 2844 2845 spec->ops.chmap_cea_alloc_validate_get_type = 2846 nvhdmi_chmap_cea_alloc_validate_get_type;