Commit 39edac70 authored by Anssi Hannula's avatar Anssi Hannula Committed by Takashi Iwai

ALSA: hda - hdmi: Fix channel map switch not taking effect

Currently hdmi_setup_audio_infoframe() reprograms the HDA channel
mapping only when the infoframe is not up-to-date or the non-PCM flag
has changed.

However, when just the channel map has been changed, the infoframe may
still be up-to-date and non-PCM flag may not have changed, so the new
channel map is not actually programmed into the HDA codec.

Notably, this failing case is also always triggered when the device is
already in a prepared state and a new channel map is configured while
changing only the channel positions (for example, plain
"speaker-test -c2 -m FR,FL").

Fix that by always programming the channel map in
hdmi_setup_audio_infoframe(). Tested on Intel HDMI.
Signed-off-by: default avatarAnssi Hannula <anssi.hannula@iki.fi>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 338cae56
...@@ -936,6 +936,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, ...@@ -936,6 +936,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
return; return;
} }
/*
* always configure channel mapping, it may have been changed by the
* user in the meantime
*/
hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
channels, per_pin->chmap,
per_pin->chmap_set);
/* /*
* sizeof(ai) is used instead of sizeof(*hdmi_ai) or * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
* sizeof(*dp_ai) to avoid partial match/update problems when * sizeof(*dp_ai) to avoid partial match/update problems when
...@@ -947,20 +955,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, ...@@ -947,20 +955,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
"pin=%d channels=%d\n", "pin=%d channels=%d\n",
pin_nid, pin_nid,
channels); channels);
hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
channels, per_pin->chmap,
per_pin->chmap_set);
hdmi_stop_infoframe_trans(codec, pin_nid); hdmi_stop_infoframe_trans(codec, pin_nid);
hdmi_fill_audio_infoframe(codec, pin_nid, hdmi_fill_audio_infoframe(codec, pin_nid,
ai.bytes, sizeof(ai)); ai.bytes, sizeof(ai));
hdmi_start_infoframe_trans(codec, pin_nid); hdmi_start_infoframe_trans(codec, pin_nid);
} else {
/* For non-pcm audio switch, setup new channel mapping
* accordingly */
if (per_pin->non_pcm != non_pcm)
hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
channels, per_pin->chmap,
per_pin->chmap_set);
} }
per_pin->non_pcm = non_pcm; per_pin->non_pcm = non_pcm;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment