[alsa-devel] [PATCH] ALSA: hda - hdmi: Fallback to ALSA allocation when selecting CA
hdmi_channel_allocation() tries to find a HDMI channel allocation that matches the number channels in the playback stream and contains only speakers that the HDMI sink has reported as available via EDID. If no such allocation is found, 0 (stereo audio) is used.
Using CA 0 causes the audio causes the sink to discard everything except the first two channels (front left and front right).
However, the sink may be capable of receiving more channels than it has speakers (and then perform downmix or discard the extra channels), in which case it is preferable to use a CA that contains extra channels than to use CA 0 which discards all the non-stereo channels.
Additionally, it seems that HBR (HD) passthrough output does not work on Intel HDMI codecs when CA is set to 0 (possibly the codec zeroes channels not present in CA). This happens with all receivers that report a 5.1 speaker mask since a HBR stream is carried on 8 channels to the codec.
Add a fallback in the CA selection so that the CA channel count at least matches the stream channel count, even if the stream contains channels not present in the sink speaker descriptor.
Thanks to GrimGriefer at OpenELEC forums for discovering that changing the sink speaker mask allowed HBR output.
Reported-by: GrimGriefer Reported-by: Ashecrow Reported-by: Frank Zafka kafkaesque1978@gmail.com Reported-by: Peter Frühberger fritsch@xbmc.org Signed-off-by: Anssi Hannula anssi.hannula@iki.fi Cc: stable@vger.kernel.org ---
Hopefully this fixes HBR (HD passthrough) for the remaining Intel users who were still experiencing problems.
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)? Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
+ if (!ca) { + /* if there was no match, select the regular ALSA channel + * allocation with the matching number of channels */ + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + if (channels == channel_allocations[i].channels) { + ca = channel_allocations[i].ca_index; + break; + } + } + } + snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf);
At Sun, 1 Sep 2013 14:36:47 +0300, Anssi Hannula wrote:
hdmi_channel_allocation() tries to find a HDMI channel allocation that matches the number channels in the playback stream and contains only speakers that the HDMI sink has reported as available via EDID. If no such allocation is found, 0 (stereo audio) is used.
Using CA 0 causes the audio causes the sink to discard everything except the first two channels (front left and front right).
However, the sink may be capable of receiving more channels than it has speakers (and then perform downmix or discard the extra channels), in which case it is preferable to use a CA that contains extra channels than to use CA 0 which discards all the non-stereo channels.
Additionally, it seems that HBR (HD) passthrough output does not work on Intel HDMI codecs when CA is set to 0 (possibly the codec zeroes channels not present in CA). This happens with all receivers that report a 5.1 speaker mask since a HBR stream is carried on 8 channels to the codec.
Add a fallback in the CA selection so that the CA channel count at least matches the stream channel count, even if the stream contains channels not present in the sink speaker descriptor.
Thanks to GrimGriefer at OpenELEC forums for discovering that changing the sink speaker mask allowed HBR output.
Reported-by: GrimGriefer Reported-by: Ashecrow Reported-by: Frank Zafka kafkaesque1978@gmail.com Reported-by: Peter Frühberger fritsch@xbmc.org Signed-off-by: Anssi Hannula anssi.hannula@iki.fi Cc: stable@vger.kernel.org
Hopefully this fixes HBR (HD passthrough) for the remaining Intel users who were still experiencing problems.
Thanks, I applied the patch now.
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)?
If per_pin->chmap_set is set beforehand, hdmi_manual_channel_allocation() is called instead. So it should be fine.
Takashi
Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
- if (!ca) {
/* if there was no match, select the regular ALSA channel
* allocation with the matching number of channels */
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
if (channels == channel_allocations[i].channels) {
ca = channel_allocations[i].ca_index;
break;
}
}
- }
- snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf);
-- 1.8.1.5
02.09.2013 16:06, Takashi Iwai kirjoitti:
At Sun, 1 Sep 2013 14:36:47 +0300, Anssi Hannula wrote:
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)?
If per_pin->chmap_set is set beforehand, hdmi_manual_channel_allocation() is called instead. So it should be fine.
I was talking about the "non-chmap" case.
Example:
Sink has FL + FR + FC + LFE.
Application plays 4 channel audio via ALSA, i.e. FL + FR + RL + RR as per ALSA API channel allocation.
Instead of sending CA for FL + FR + RL + RR (0x06) which is what the audio really is, hdmi_channel_allocation() selects CA for FL + FR + FC + LFE (0x03), since that is what the sink reported as present. As a result rear channels are mapped to FC and LFE.
Of course this is rather unusual case (in terms of sink speaker mask), and it may be argued that the user actually _wanted_ to output the second pair of channels to FC+LFE despite them normally being RL+RR in ALSA.
Takashi
Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
- if (!ca) {
/* if there was no match, select the regular ALSA channel
* allocation with the matching number of channels */
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
if (channels == channel_allocations[i].channels) {
ca = channel_allocations[i].ca_index;
break;
}
}
- }
- snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf);
-- 1.8.1.5
At Mon, 02 Sep 2013 17:14:02 +0300, Anssi Hannula wrote:
02.09.2013 16:06, Takashi Iwai kirjoitti:
At Sun, 1 Sep 2013 14:36:47 +0300, Anssi Hannula wrote:
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)?
If per_pin->chmap_set is set beforehand, hdmi_manual_channel_allocation() is called instead. So it should be fine.
I was talking about the "non-chmap" case.
Example:
Sink has FL + FR + FC + LFE.
Application plays 4 channel audio via ALSA, i.e. FL + FR + RL + RR as per ALSA API channel allocation.
Instead of sending CA for FL + FR + RL + RR (0x06) which is what the audio really is, hdmi_channel_allocation() selects CA for FL + FR + FC
- LFE (0x03), since that is what the sink reported as present. As a
result rear channels are mapped to FC and LFE.
Of course this is rather unusual case (in terms of sink speaker mask), and it may be argued that the user actually _wanted_ to output the second pair of channels to FC+LFE despite them normally being RL+RR in ALSA.
Yeah, of course, it's just a best effort and the channel map is incomplete and might mismatch unless you explicitly set the channel map. This was the very reason we introduced this new API...
Takashi
Takashi
Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
- if (!ca) {
/* if there was no match, select the regular ALSA channel
* allocation with the matching number of channels */
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
if (channels == channel_allocations[i].channels) {
ca = channel_allocations[i].ca_index;
break;
}
}
- }
- snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf);
-- 1.8.1.5
-- Anssi Hannula
Hi guys, Anssi, thank you very much for your work! I'll test the patch asap and I'll keep you posted.
Takashi, where can I get patched kernel sources, or on which branch do I apply the patch to?
Thanks Etienne
Le 2 sept. 2013 à 15:06, Takashi Iwai tiwai@suse.de a écrit :
At Sun, 1 Sep 2013 14:36:47 +0300, Anssi Hannula wrote:
hdmi_channel_allocation() tries to find a HDMI channel allocation that matches the number channels in the playback stream and contains only speakers that the HDMI sink has reported as available via EDID. If no such allocation is found, 0 (stereo audio) is used.
Using CA 0 causes the audio causes the sink to discard everything except the first two channels (front left and front right).
However, the sink may be capable of receiving more channels than it has speakers (and then perform downmix or discard the extra channels), in which case it is preferable to use a CA that contains extra channels than to use CA 0 which discards all the non-stereo channels.
Additionally, it seems that HBR (HD) passthrough output does not work on Intel HDMI codecs when CA is set to 0 (possibly the codec zeroes channels not present in CA). This happens with all receivers that report a 5.1 speaker mask since a HBR stream is carried on 8 channels to the codec.
Add a fallback in the CA selection so that the CA channel count at least matches the stream channel count, even if the stream contains channels not present in the sink speaker descriptor.
Thanks to GrimGriefer at OpenELEC forums for discovering that changing the sink speaker mask allowed HBR output.
Reported-by: GrimGriefer Reported-by: Ashecrow Reported-by: Frank Zafka kafkaesque1978@gmail.com Reported-by: Peter Frühberger fritsch@xbmc.org Signed-off-by: Anssi Hannula anssi.hannula@iki.fi Cc: stable@vger.kernel.org
Hopefully this fixes HBR (HD passthrough) for the remaining Intel users who were still experiencing problems.
Thanks, I applied the patch now.
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)?
If per_pin->chmap_set is set beforehand, hdmi_manual_channel_allocation() is called instead. So it should be fine.
Takashi
Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
- if (!ca) {
/* if there was no match, select the regular ALSA channel
* allocation with the matching number of channels */
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
if (channels == channel_allocations[i].channels) {
ca = channel_allocations[i].ca_index;
break;
}
}
- }
- snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf);
-- 1.8.1.5
At Fri, 6 Sep 2013 10:43:17 +0200, Ashecrow wrote:
Hi guys, Anssi, thank you very much for your work! I'll test the patch asap and I'll keep you posted.
Takashi, where can I get patched kernel sources, or on which branch do I apply the patch to?
The patch was already merged to Linus git tree now, so it'll be in 3.12-rc1. The commit was marked with Cc to stable, thus it'll be picked up to stable kernels eventually later.
Takashi
Thanks Etienne
Le 2 sept. 2013 à 15:06, Takashi Iwai tiwai@suse.de a écrit :
At Sun, 1 Sep 2013 14:36:47 +0300, Anssi Hannula wrote:
hdmi_channel_allocation() tries to find a HDMI channel allocation that matches the number channels in the playback stream and contains only speakers that the HDMI sink has reported as available via EDID. If no such allocation is found, 0 (stereo audio) is used.
Using CA 0 causes the audio causes the sink to discard everything except the first two channels (front left and front right).
However, the sink may be capable of receiving more channels than it has speakers (and then perform downmix or discard the extra channels), in which case it is preferable to use a CA that contains extra channels than to use CA 0 which discards all the non-stereo channels.
Additionally, it seems that HBR (HD) passthrough output does not work on Intel HDMI codecs when CA is set to 0 (possibly the codec zeroes channels not present in CA). This happens with all receivers that report a 5.1 speaker mask since a HBR stream is carried on 8 channels to the codec.
Add a fallback in the CA selection so that the CA channel count at least matches the stream channel count, even if the stream contains channels not present in the sink speaker descriptor.
Thanks to GrimGriefer at OpenELEC forums for discovering that changing the sink speaker mask allowed HBR output.
Reported-by: GrimGriefer Reported-by: Ashecrow Reported-by: Frank Zafka kafkaesque1978@gmail.com Reported-by: Peter Frühberger fritsch@xbmc.org Signed-off-by: Anssi Hannula anssi.hannula@iki.fi Cc: stable@vger.kernel.org
Hopefully this fixes HBR (HD passthrough) for the remaining Intel users who were still experiencing problems.
Thanks, I applied the patch now.
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)?
If per_pin->chmap_set is set beforehand, hdmi_manual_channel_allocation() is called instead. So it should be fine.
Takashi
Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
- if (!ca) {
/* if there was no match, select the regular ALSA channel
* allocation with the matching number of channels */
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
if (channels == channel_allocations[i].channels) {
ca = channel_allocations[i].ca_index;
break;
}
}
- }
- snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf);
-- 1.8.1.5
Hi guys, Let me tell you, you rock!!!! I have compiled kernel sources from Linus master branch in his GIT repo and it works flawlessly, I now have DTS-HD MSTR.
Thanks Anssi for your great work! Thanks to any one who contributed to it. I can't believe I've struggled for so many months and only 8 lines of kernel code fix it.
Hail ALSA and hail Linux :), I now have the perfect media center
Le 6 sept. 2013 à 10:43, Ashecrow a écrit :
Hi guys, Anssi, thank you very much for your work! I'll test the patch asap and I'll keep you posted.
Takashi, where can I get patched kernel sources, or on which branch do I apply the patch to?
Thanks Etienne
Le 2 sept. 2013 à 15:06, Takashi Iwai tiwai@suse.de a écrit :
At Sun, 1 Sep 2013 14:36:47 +0300, Anssi Hannula wrote:
hdmi_channel_allocation() tries to find a HDMI channel allocation that matches the number channels in the playback stream and contains only speakers that the HDMI sink has reported as available via EDID. If no such allocation is found, 0 (stereo audio) is used.
Using CA 0 causes the audio causes the sink to discard everything except the first two channels (front left and front right).
However, the sink may be capable of receiving more channels than it has speakers (and then perform downmix or discard the extra channels), in which case it is preferable to use a CA that contains extra channels than to use CA 0 which discards all the non-stereo channels.
Additionally, it seems that HBR (HD) passthrough output does not work on Intel HDMI codecs when CA is set to 0 (possibly the codec zeroes channels not present in CA). This happens with all receivers that report a 5.1 speaker mask since a HBR stream is carried on 8 channels to the codec.
Add a fallback in the CA selection so that the CA channel count at least matches the stream channel count, even if the stream contains channels not present in the sink speaker descriptor.
Thanks to GrimGriefer at OpenELEC forums for discovering that changing the sink speaker mask allowed HBR output.
Reported-by: GrimGriefer Reported-by: Ashecrow Reported-by: Frank Zafka kafkaesque1978@gmail.com Reported-by: Peter Frühberger fritsch@xbmc.org Signed-off-by: Anssi Hannula anssi.hannula@iki.fi Cc: stable@vger.kernel.org
Hopefully this fixes HBR (HD passthrough) for the remaining Intel users who were still experiencing problems.
Thanks, I applied the patch now.
BTW, the hdmi_channel_allocation() logic seems also otherwise somewhat suspect to me. Shouldn't we always select an allocation matching ALSA channel mapping, instead of re-assigning channels received from userspace "randomly" to sink speakers (in case of unusual sink speaker mask)?
If per_pin->chmap_set is set beforehand, hdmi_manual_channel_allocation() is called instead. So it should be fine.
Takashi
Anyway, I let it be for now at least.
sound/pci/hda/patch_hdmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 030ca86..354fc55 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -551,6 +551,17 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) } }
- if (!ca) {
/* if there was no match, select the regular ALSA channel
* allocation with the matching number of channels */
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
if (channels == channel_allocations[i].channels) {
ca = channel_allocations[i].ca_index;
break;
}
}
- }
snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf)); snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", ca, channels, buf); -- 1.8.1.5
participants (3)
-
Anssi Hannula
-
Ashecrow
-
Takashi Iwai