[PATCH 3.12 006/175] ALSA: hda - hdmi: Fix incorrect default channel mapping for unusual CAs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Anssi Hannula <anssi.hannula@xxxxxx>

3.12-stable review patch.  If anyone has any objections, please let me know.

===============

commit 90f28002110d783f49639f0db2ccdc0b58302cbd upstream.

hdmi_std_setup_channel_mapping() selects a Channel Allocation according
to the sink reported speaker mask, preferring the ALSA standard layouts.

If the channel allocation is not one of the ALSA standard layouts, the
ALSA channels are mapped directly to HDMI channels in order. However,
the function does not take into account that there a holes in the HDMI
channel map.

Additionally, the function tries to disable a slot by using
AC_VERB_SET_CHAN_SLOT with parameter ((alsa_ch << 8) | 0xf), while the
correct parameter is ((0xf << 8) | hdmi_slot), i.e. the slot should be
unassigned, not the ALSA channel.

Fix both of the issues for non-ALSA-default layouts.

Tested on Intel HDMI with a speaker mask of FL | FR | FC | RC, which
causes CA 0x06 to be selected for 4-channel audio, which causes
incorrect output (sound destined to RC goes to FC and FC goes nowhere)
without the patch.

Signed-off-by: Anssi Hannula <anssi.hannula@xxxxxx>
Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>
---
 sound/pci/hda/patch_hdmi.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 417e0fc2d119..3b9002e00f30 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -608,22 +608,32 @@ static void hdmi_std_setup_channel_mapping(struct hda_codec *codec,
 				       bool non_pcm,
 				       int ca)
 {
+	struct cea_channel_speaker_allocation *ch_alloc;
 	int i;
 	int err;
 	int order;
 	int non_pcm_mapping[8];
 
 	order = get_channel_allocation_order(ca);
+	ch_alloc = &channel_allocations[order];
 
 	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[order].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+		int hdmi_slot = 0;
+		/* fill actual channel mappings in ALSA channel (i) order */
+		for (i = 0; i < ch_alloc->channels; i++) {
+			while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8))
+				hdmi_slot++; /* skip zero slots */
+
+			hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
+		}
+		/* fill the rest of the slots with ALSA channel 0xf */
+		for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
+			if (!ch_alloc->speakers[7 - hdmi_slot])
+				hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot;
 	}
 
 	if (non_pcm) {
-		for (i = 0; i < channel_allocations[order].channels; i++)
+		for (i = 0; i < ch_alloc->channels; i++)
 			non_pcm_mapping[i] = i | (i << 4);
 		for (; i < 8; i++)
 			non_pcm_mapping[i] = 0xf | (i << 4);
-- 
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]