From: Mengdong Lin mengdong.lin@intel.com
The pin:converter connection may get reset after S3 on Intel Broadwell HDMI codec. And this can cause multiple pins share a same convertor and mute control will affect each other. We observed a resumed audio playback become silent after S3.
This patch verifies pin:cvt connection on preparing a stream, to assure the pin selects the right convetor and an assigned convertor is not shared by other unused pins. Apply this fix-up on Haswell, Broadwell and Baytrail.
Signed-off-by: Mengdong Lin mengdong.lin@intel.com
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 3ab7063..6000ce9 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -68,6 +68,7 @@ struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + int mux_idx; hda_nid_t cvt_nid;
struct hda_codec *codec; @@ -1342,6 +1343,8 @@ static int hdmi_choose_cvt(struct hda_codec *codec, if (cvt_idx == spec->num_cvts) return -ENODEV;
+ per_pin->mux_idx = mux_idx; + if (cvt_id) *cvt_id = cvt_idx; if (mux_id) @@ -1350,6 +1353,22 @@ static int hdmi_choose_cvt(struct hda_codec *codec, return 0; }
+/* Assure the pin select the right convetor */ +static void intel_verify_pin_cvt_connect(struct hda_codec *codec, + struct hdmi_spec_per_pin *per_pin) +{ + hda_nid_t pin_nid = per_pin->pin_nid; + int mux_idx, curr; + + mux_idx = per_pin->mux_idx; + curr = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONNECT_SEL, 0); + if (curr != mux_idx) + snd_hda_codec_write_cache(codec, pin_nid, 0, + AC_VERB_SET_CONNECT_SEL, + mux_idx); +} + /* Intel HDMI workaround to fix audio routing issue: * For some Intel display codecs, pins share the same connection list. * So a conveter can be selected by multiple pins and playback on any of these @@ -1751,6 +1770,12 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, bool non_pcm; int pinctl;
+ if (is_haswell_plus(codec) || is_valleyview(codec)) { + /* the pin:cvt connection may get reset after S3 */ + intel_verify_pin_cvt_connect(codec, per_pin); + intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx); + } + non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); per_pin->channels = substream->runtime->channels;