Skip to content

Commit 75fae11

Browse files
nvswarrentiwai
authored andcommitted
ALSA: hda/hdmi - allow PIN_OUT to be dynamically enabled
Commit 384a48d "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 6169b67 "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>
1 parent 5e87d58 commit 75fae11

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

sound/pci/hda/patch_hdmi.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ struct hdmi_spec {
132132

133133
struct hdmi_eld temp_eld;
134134
struct hdmi_ops ops;
135+
136+
bool dyn_pin_out;
137+
135138
/*
136139
* Non-generic VIA/NVIDIA specific
137140
*/
@@ -500,15 +503,25 @@ static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
500503

501504
static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid)
502505
{
506+
struct hdmi_spec *spec = codec->spec;
507+
int pin_out;
508+
503509
/* Unmute */
504510
if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
505511
snd_hda_codec_write(codec, pin_nid, 0,
506512
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
507-
/* Enable pin out: some machines with GM965 gets broken output when
508-
* the pin is disabled or changed while using with HDMI
509-
*/
513+
514+
if (spec->dyn_pin_out)
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+
510523
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);
512525
}
513526

514527
static 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,
17351748
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
17361749
hda_nid_t pin_nid = per_pin->pin_nid;
17371750
bool non_pcm;
1751+
int pinctl;
17381752

17391753
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
17401754
mutex_lock(&per_pin->lock);
@@ -1744,6 +1758,14 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
17441758
hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
17451759
mutex_unlock(&per_pin->lock);
17461760

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+
17471769
return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
17481770
}
17491771

@@ -1763,6 +1785,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
17631785
int cvt_idx, pin_idx;
17641786
struct hdmi_spec_per_cvt *per_cvt;
17651787
struct hdmi_spec_per_pin *per_pin;
1788+
int pinctl;
17661789

17671790
if (hinfo->nid) {
17681791
cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
@@ -1779,6 +1802,14 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
17791802
return -EINVAL;
17801803
per_pin = get_pin(spec, pin_idx);
17811804

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+
17821813
snd_hda_spdif_ctls_unassign(codec, pin_idx);
17831814

17841815
mutex_lock(&per_pin->lock);
@@ -2840,6 +2871,7 @@ static int patch_nvhdmi(struct hda_codec *codec)
28402871
return err;
28412872

28422873
spec = codec->spec;
2874+
spec->dyn_pin_out = true;
28432875

28442876
spec->ops.chmap_cea_alloc_validate_get_type =
28452877
nvhdmi_chmap_cea_alloc_validate_get_type;

0 commit comments

Comments
 (0)