At Mon, 7 Oct 2013 19:24:52 +0300, Anssi Hannula wrote:
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: Anssi Hannula anssi.hannula@iki.fi Cc: stable@vger.kernel.org
Here is a simpler version of the map switch fix.
Thanks, applied now.
The for-linus branch including this fix was merged back to for-next branch, too, so you can use for-next branch for the further development.
Takashi
sound/pci/hda/patch_hdmi.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 7ea0245..50173d4 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -937,6 +937,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, }
/*
* 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(*dp_ai) to avoid partial match/update problems when
- the user switches between HDMI/DP monitors.
@@ -947,20 +955,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, "pin=%d channels=%d\n", pin_nid, 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_fill_audio_infoframe(codec, pin_nid, ai.bytes, sizeof(ai)); 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;
-- 1.8.1.5