At Thu, 30 Jan 2014 11:52:16 -0700, Stephen Warren wrote: > > From: Stephen Warren <swarren@xxxxxxxxxx> > > 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@xxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> # v3.13 > Signed-off-by: Stephen Warren <swarren@xxxxxxxxxx> Thanks, pulled now. > --- > v3.12 or earlier stable require some manual back-porting effort, or > perhaps just a variety of other commits to be backported. I'm > investigating exactly which commits, and whether they're appropriate > for stable. OK, that's appreciated. Takashi > --- > sound/pci/hda/patch_hdmi.c | 40 ++++++++++++++++++++++++++++++++++++---- > 1 file 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 { > > struct hdmi_eld temp_eld; > struct hdmi_ops ops; > + > + bool dyn_pin_out; > + > /* > * Non-generic VIA/NVIDIA specific > */ > @@ -500,15 +503,25 @@ static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, > > static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) > { > + struct hdmi_spec *spec = codec->spec; > + int pin_out; > + > /* Unmute */ > if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) > snd_hda_codec_write(codec, pin_nid, 0, > AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); > - /* Enable pin out: some machines with GM965 gets broken output when > - * the pin is disabled or changed while using with HDMI > - */ > + > + if (spec->dyn_pin_out) > + /* Disable pin out until stream is active */ > + pin_out = 0; > + else > + /* Enable pin out: some machines with GM965 gets broken output > + * when the pin is disabled or changed while using with HDMI > + */ > + pin_out = PIN_OUT; > + > snd_hda_codec_write(codec, pin_nid, 0, > - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); > + AC_VERB_SET_PIN_WIDGET_CONTROL, pin_out); > } > > 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, > struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); > hda_nid_t pin_nid = per_pin->pin_nid; > bool non_pcm; > + int pinctl; > > non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); > mutex_lock(&per_pin->lock); > @@ -1744,6 +1758,14 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, > hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); > mutex_unlock(&per_pin->lock); > > + if (spec->dyn_pin_out) { > + pinctl = snd_hda_codec_read(codec, pin_nid, 0, > + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); > + snd_hda_codec_write(codec, pin_nid, 0, > + AC_VERB_SET_PIN_WIDGET_CONTROL, > + pinctl | PIN_OUT); > + } > + > return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); > } > > @@ -1763,6 +1785,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, > int cvt_idx, pin_idx; > struct hdmi_spec_per_cvt *per_cvt; > struct hdmi_spec_per_pin *per_pin; > + int pinctl; > > if (hinfo->nid) { > cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); > @@ -1779,6 +1802,14 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, > return -EINVAL; > per_pin = get_pin(spec, pin_idx); > > + if (spec->dyn_pin_out) { > + pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, > + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); > + snd_hda_codec_write(codec, per_pin->pin_nid, 0, > + AC_VERB_SET_PIN_WIDGET_CONTROL, > + pinctl & ~PIN_OUT); > + } > + > snd_hda_spdif_ctls_unassign(codec, pin_idx); > > mutex_lock(&per_pin->lock); > @@ -2840,6 +2871,7 @@ static int patch_nvhdmi(struct hda_codec *codec) > return err; > > spec = codec->spec; > + spec->dyn_pin_out = true; > > spec->ops.chmap_cea_alloc_validate_get_type = > nvhdmi_chmap_cea_alloc_validate_get_type; > -- > 1.8.1.5 > -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html