aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorAnssi Hannula <anssi.hannula@iki.fi>2013-10-04 19:25:39 -0400
committerTakashi Iwai <tiwai@suse.de>2013-10-07 06:46:26 -0400
commit90f28002110d783f49639f0db2ccdc0b58302cbd (patch)
tree5436f9081bdeed0098f65b0454a9fe5ae62ea973 /sound/pci/hda/patch_hdmi.c
parent56cac413dd6d43af8355f5d1f90a199b540f73fc (diff)
ALSA: hda - hdmi: Fix incorrect default channel mapping for unusual CAs
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@iki.fi> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index dcc4c1cb0ab1..b187cce64fa4 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -595,22 +595,32 @@ static void hdmi_std_setup_channel_mapping(struct hda_codec *codec,
595 bool non_pcm, 595 bool non_pcm,
596 int ca) 596 int ca)
597{ 597{
598 struct cea_channel_speaker_allocation *ch_alloc;
598 int i; 599 int i;
599 int err; 600 int err;
600 int order; 601 int order;
601 int non_pcm_mapping[8]; 602 int non_pcm_mapping[8];
602 603
603 order = get_channel_allocation_order(ca); 604 order = get_channel_allocation_order(ca);
605 ch_alloc = &channel_allocations[order];
604 606
605 if (hdmi_channel_mapping[ca][1] == 0) { 607 if (hdmi_channel_mapping[ca][1] == 0) {
606 for (i = 0; i < channel_allocations[order].channels; i++) 608 int hdmi_slot = 0;
607 hdmi_channel_mapping[ca][i] = i | (i << 4); 609 /* fill actual channel mappings in ALSA channel (i) order */
608 for (; i < 8; i++) 610 for (i = 0; i < ch_alloc->channels; i++) {
609 hdmi_channel_mapping[ca][i] = 0xf | (i << 4); 611 while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8))
612 hdmi_slot++; /* skip zero slots */
613
614 hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
615 }
616 /* fill the rest of the slots with ALSA channel 0xf */
617 for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
618 if (!ch_alloc->speakers[7 - hdmi_slot])
619 hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot;
610 } 620 }
611 621
612 if (non_pcm) { 622 if (non_pcm) {
613 for (i = 0; i < channel_allocations[order].channels; i++) 623 for (i = 0; i < ch_alloc->channels; i++)
614 non_pcm_mapping[i] = i | (i << 4); 624 non_pcm_mapping[i] = i | (i << 4);
615 for (; i < 8; i++) 625 for (; i < 8; i++)
616 non_pcm_mapping[i] = 0xf | (i << 4); 626 non_pcm_mapping[i] = 0xf | (i << 4);