aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2014-01-30 13:52:16 -0500
committerTakashi Iwai <tiwai@suse.de>2014-01-31 11:57:02 -0500
commit75fae117a5dbde5ab984fa5c60705758cfbc6433 (patch)
treeea4167a1d71eaf6e3a5a742b4204bb90b3757967 /sound/pci/hda/patch_hdmi.c
parent5e87d5807110afd6bd659e1b98929fab43f3732f (diff)
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>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 64f0a5e73a25..5ef95034d041 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -132,6 +132,9 @@ struct hdmi_spec {
132 132
133 struct hdmi_eld temp_eld; 133 struct hdmi_eld temp_eld;
134 struct hdmi_ops ops; 134 struct hdmi_ops ops;
135
136 bool dyn_pin_out;
137
135 /* 138 /*
136 * Non-generic VIA/NVIDIA specific 139 * Non-generic VIA/NVIDIA specific
137 */ 140 */
@@ -500,15 +503,25 @@ static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
500 503
501static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) 504static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid)
502{ 505{
506 struct hdmi_spec *spec = codec->spec;
507 int pin_out;
508
503 /* Unmute */ 509 /* Unmute */
504 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) 510 if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
505 snd_hda_codec_write(codec, pin_nid, 0, 511 snd_hda_codec_write(codec, pin_nid, 0,
506 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); 512 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
507 /* Enable pin out: some machines with GM965 gets broken output when 513
508 * the pin is disabled or changed while using with HDMI 514 if (spec->dyn_pin_out)
509 */ 515 /* Disable pin out until stream is active */
516 pin_out = 0;
517 else
518 /* Enable pin out: some machines with GM965 gets broken output
519 * when the pin is disabled or changed while using with HDMI
520 */
521 pin_out = PIN_OUT;
522
510 snd_hda_codec_write(codec, pin_nid, 0, 523 snd_hda_codec_write(codec, pin_nid, 0,
511 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 524 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_out);
512} 525}
513 526
514static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) 527static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid)
@@ -1735,6 +1748,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1735 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 1748 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
1736 hda_nid_t pin_nid = per_pin->pin_nid; 1749 hda_nid_t pin_nid = per_pin->pin_nid;
1737 bool non_pcm; 1750 bool non_pcm;
1751 int pinctl;
1738 1752
1739 non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); 1753 non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
1740 mutex_lock(&per_pin->lock); 1754 mutex_lock(&per_pin->lock);
@@ -1744,6 +1758,14 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1744 hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); 1758 hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
1745 mutex_unlock(&per_pin->lock); 1759 mutex_unlock(&per_pin->lock);
1746 1760
1761 if (spec->dyn_pin_out) {
1762 pinctl = snd_hda_codec_read(codec, pin_nid, 0,
1763 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1764 snd_hda_codec_write(codec, pin_nid, 0,
1765 AC_VERB_SET_PIN_WIDGET_CONTROL,
1766 pinctl | PIN_OUT);
1767 }
1768
1747 return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); 1769 return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
1748} 1770}
1749 1771
@@ -1763,6 +1785,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
1763 int cvt_idx, pin_idx; 1785 int cvt_idx, pin_idx;
1764 struct hdmi_spec_per_cvt *per_cvt; 1786 struct hdmi_spec_per_cvt *per_cvt;
1765 struct hdmi_spec_per_pin *per_pin; 1787 struct hdmi_spec_per_pin *per_pin;
1788 int pinctl;
1766 1789
1767 if (hinfo->nid) { 1790 if (hinfo->nid) {
1768 cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); 1791 cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
@@ -1779,6 +1802,14 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
1779 return -EINVAL; 1802 return -EINVAL;
1780 per_pin = get_pin(spec, pin_idx); 1803 per_pin = get_pin(spec, pin_idx);
1781 1804
1805 if (spec->dyn_pin_out) {
1806 pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
1807 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1808 snd_hda_codec_write(codec, per_pin->pin_nid, 0,
1809 AC_VERB_SET_PIN_WIDGET_CONTROL,
1810 pinctl & ~PIN_OUT);
1811 }
1812
1782 snd_hda_spdif_ctls_unassign(codec, pin_idx); 1813 snd_hda_spdif_ctls_unassign(codec, pin_idx);
1783 1814
1784 mutex_lock(&per_pin->lock); 1815 mutex_lock(&per_pin->lock);
@@ -2840,6 +2871,7 @@ static int patch_nvhdmi(struct hda_codec *codec)
2840 return err; 2871 return err;
2841 2872
2842 spec = codec->spec; 2873 spec = codec->spec;
2874 spec->dyn_pin_out = true;
2843 2875
2844 spec->ops.chmap_cea_alloc_validate_get_type = 2876 spec->ops.chmap_cea_alloc_validate_get_type =
2845 nvhdmi_chmap_cea_alloc_validate_get_type; 2877 nvhdmi_chmap_cea_alloc_validate_get_type;