* [PATCH] ALSA: hda: codecs: hdmi: disable keep-alive before audio format change
@ 2026-07-15 18:06 Kai Vehmanen
2026-07-16 6:33 ` Takashi Iwai
0 siblings, 1 reply; 2+ messages in thread
From: Kai Vehmanen @ 2026-07-15 18:06 UTC (permalink / raw)
To: linux-sound, tiwai
Cc: peter.ujfalusi, Uma Shankar, kai.vehmanen, Alexander Kaplan,
stable
When a keep-alive (KAE) silent stream is active on an Intel HDMI/DP
codec, opening a real PCM stream reprograms the converter format and the
audio infoframe in snd_hda_hdmi_generic_pcm_prepare(). Part of that
reprogramming - the converter channel count and the channel mapping in
snd_hda_hdmi_setup_audio_infoframe() - is not safe to do while a
keep-alive stream is active. This is most visible when switching to a
multichannel PCM configuration, where the active channel count actually
changes. In that case the newly opened PCM stream plays no sound.
Add an optional hdmi_ops .prepare hook, called at the start of the
PCM prepare sequence (before the format and infoframe are touched), and
implement it for HSW+ to release keep-alive. Keep-alive is then
re-enabled as before once the new stream has been set up, in the
setup_stream op.
Fixes: 15175a4f2bbb ("ALSA: hda/hdmi: add keep-alive support for ADL-P and DG2")
Reported-by: Alexander Kaplan <alexander.kaplan@sms-medipool.de>
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/8412
Tested-by: Alexander Kaplan <alexander.kaplan@sms-medipool.de>
Cc: <stable@vger.kernel.org>
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
---
sound/hda/codecs/hdmi/hdmi.c | 3 +++
sound/hda/codecs/hdmi/hdmi_local.h | 9 ++++++++
sound/hda/codecs/hdmi/intelhdmi.c | 36 +++++++++++++++++++++++++-----
3 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/sound/hda/codecs/hdmi/hdmi.c b/sound/hda/codecs/hdmi/hdmi.c
index 0b6816018a42..053c41d98028 100644
--- a/sound/hda/codecs/hdmi/hdmi.c
+++ b/sound/hda/codecs/hdmi/hdmi.c
@@ -1688,6 +1688,9 @@ int snd_hda_hdmi_generic_pcm_prepare(struct hda_pcm_stream *hinfo,
per_pin->channels = substream->runtime->channels;
per_pin->setup = true;
+ if (spec->ops.prepare)
+ spec->ops.prepare(codec, per_pin);
+
if (get_wcaps(codec, cvt_nid) & AC_WCAP_STRIPE) {
stripe = snd_hdac_get_stream_stripe_ctl(&codec->bus->core,
substream);
diff --git a/sound/hda/codecs/hdmi/hdmi_local.h b/sound/hda/codecs/hdmi/hdmi_local.h
index 548241ad3fa9..dce9a335cff2 100644
--- a/sound/hda/codecs/hdmi/hdmi_local.h
+++ b/sound/hda/codecs/hdmi/hdmi_local.h
@@ -74,6 +74,15 @@ struct hdmi_ops {
hda_nid_t pin_nid, int dev_id, u32 stream_tag,
int format);
+ /*
+ * Optional hook invoked at the beginning of the PCM prepare
+ * sequence, before the audio infoframe and stream format are
+ * (re)programmed. Used to disable keep-alive / silent stream so
+ * that the format change is not done while keep-alive is active.
+ */
+ void (*prepare)(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin);
+
void (*pin_cvt_fixup)(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin,
hda_nid_t cvt_nid);
diff --git a/sound/hda/codecs/hdmi/intelhdmi.c b/sound/hda/codecs/hdmi/intelhdmi.c
index 6a7882544ab7..73141046d502 100644
--- a/sound/hda/codecs/hdmi/intelhdmi.c
+++ b/sound/hda/codecs/hdmi/intelhdmi.c
@@ -418,6 +418,28 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
intel_not_share_assigned_cvt(codec, pin_nid, dev_id, mux_idx);
}
+/*
+ * prepare ops override for HSW+
+ *
+ * Disable keep-alive before the converter format and audio infoframe are
+ * reprogrammed by the PCM prepare sequence. Changing the audio format (e.g.
+ * the channel count when switching to multichannel PCM) while a keep-alive
+ * stream is active is not safe, so release keep-alive here, early in the
+ * sequence. It is re-enabled once the new stream has been set up, in
+ * i915_hsw_setup_stream().
+ */
+static void i915_hsw_prepare(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin)
+{
+ struct hdmi_spec *spec = codec->spec;
+
+ if (spec->silent_stream_type == SILENT_STREAM_KAE && per_pin->silent_stream) {
+ silent_stream_set_kae(codec, per_pin, false);
+ /* wait for pending transfers in codec to clear */
+ usleep_range(100, 200);
+ }
+}
+
/* setup_stream ops override for HSW+ */
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,
@@ -435,15 +457,16 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
haswell_verify_D0(codec, cvt_nid, pin_nid);
- 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 = snd_hda_hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id,
stream_tag, format);
+ /*
+ * Keep-alive was disabled in i915_hsw_prepare(), re-enable it now.
+ * The pin lookup above resolves to the same per_pin that prepare
+ * used (pin_nid comes from that per_pin), so this stays balanced; a
+ * NULL per_pin only occurs on a lookup failure that also implies no
+ * active keep-alive stream to restore.
+ */
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);
@@ -607,6 +630,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
codec->depop_delay = 0;
codec->auto_runtime_pm = 1;
+ spec->ops.prepare = i915_hsw_prepare;
spec->ops.setup_stream = i915_hsw_setup_stream;
spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
spec->ops.silent_stream = i915_set_silent_stream;
base-commit: 41f1f6d8d2cfaba1fba07af993c9319a1ff2c81f
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] ALSA: hda: codecs: hdmi: disable keep-alive before audio format change
2026-07-15 18:06 [PATCH] ALSA: hda: codecs: hdmi: disable keep-alive before audio format change Kai Vehmanen
@ 2026-07-16 6:33 ` Takashi Iwai
0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-07-16 6:33 UTC (permalink / raw)
To: Kai Vehmanen
Cc: linux-sound, tiwai, peter.ujfalusi, Uma Shankar, Alexander Kaplan,
stable
On Wed, 15 Jul 2026 20:06:10 +0200,
Kai Vehmanen wrote:
>
> When a keep-alive (KAE) silent stream is active on an Intel HDMI/DP
> codec, opening a real PCM stream reprograms the converter format and the
> audio infoframe in snd_hda_hdmi_generic_pcm_prepare(). Part of that
> reprogramming - the converter channel count and the channel mapping in
> snd_hda_hdmi_setup_audio_infoframe() - is not safe to do while a
> keep-alive stream is active. This is most visible when switching to a
> multichannel PCM configuration, where the active channel count actually
> changes. In that case the newly opened PCM stream plays no sound.
>
> Add an optional hdmi_ops .prepare hook, called at the start of the
> PCM prepare sequence (before the format and infoframe are touched), and
> implement it for HSW+ to release keep-alive. Keep-alive is then
> re-enabled as before once the new stream has been set up, in the
> setup_stream op.
>
> Fixes: 15175a4f2bbb ("ALSA: hda/hdmi: add keep-alive support for ADL-P and DG2")
> Reported-by: Alexander Kaplan <alexander.kaplan@sms-medipool.de>
> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/8412
> Tested-by: Alexander Kaplan <alexander.kaplan@sms-medipool.de>
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Applied now. Thanks.
Takashi
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-16 6:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-15 18:06 [PATCH] ALSA: hda: codecs: hdmi: disable keep-alive before audio format change Kai Vehmanen
2026-07-16 6:33 ` Takashi Iwai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox