From 1cc133bee40f47bf8da3bbe7983a0708b4855b6b Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 9 Dec 2022 12:18:20 +0200 Subject: [PATCH] ALSA: hda/hdmi: fix i915 silent stream programming flow [ Upstream commit ada261b690ecd5c2f55f0c51bdf11d852a4561a6 ] The i915 display codec may not successfully transition to normal audio streaming mode, if the stream id is programmed while codec is actively transmitting data. This can happen when silent stream is enabled in KAE mode. Fix the issue by implementing a i915 specific programming flow, where the silent streaming is temporarily stopped, a small delay is applied to ensure display codec becomes idle, and then proceed with reprogramming the stream ID. Fixes: 15175a4f2bbb ("ALSA: hda/hdmi: add keep-alive support for ADL-P and DG2") Link: https://gitlab.freedesktop.org/drm/intel/-/issues/7353 Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Tested-by: Rodrigo Vivi Link: https://lore.kernel.org/r/20221209101822.3893675-2-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/pci/hda/patch_hdmi.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 21edf7a..35bef8f 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2878,9 +2878,33 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, hda_nid_t pin_nid, int dev_id, u32 stream_tag, int format) { + struct hdmi_spec *spec = codec->spec; + int pin_idx = pin_id_to_pin_index(codec, pin_nid, dev_id); + struct hdmi_spec_per_pin *per_pin; + int res; + + if (pin_idx < 0) + per_pin = NULL; + else + per_pin = get_pin(spec, pin_idx); + haswell_verify_D0(codec, cvt_nid, pin_nid); - return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, - stream_tag, format); + + if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) { + silent_stream_set_kae(codec, per_pin, false); + /* wait for pending transfers in codec to clear */ + usleep_range(100, 200); + } + + res = hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, + stream_tag, format); + + if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin && per_pin->silent_stream) { + usleep_range(100, 200); + silent_stream_set_kae(codec, per_pin, true); + } + + return res; } /* pin_cvt_fixup ops override for HSW+ and VLV+ */ -- 2.7.4