alsa/0007-pcm-iec958-implement-HDMI-HBR-audio-formatting.patch
Takashi Iwai 4f7fd72c0e Accepting request 836375 from home:tiwai:branches:multimedia:libs
- Backport upstream fixes:
  0001-ucm-substitution-remove-duplicate-allow_empty-assign.patch
  0002-ucm-fix-parse_get_safe_name-safe-name-must-be-checke.patch
  0003-ucm-substitute-the-merged-tree-completely.patch
  0004-ctl-improve-documentation-for-identifier-of-control-.patch
  0005-pcm-dmix-make-lockless-operation-optional.patch
  0006-pcm-dmix-Fix-semaphore-usage-with-lockless-operation.patch
  0007-pcm-iec958-implement-HDMI-HBR-audio-formatting.patch
  0008-pcm-iec958-set-channel-status-bits-according-to-rate.patch
  0009-conf-pcm-USB-Added-S-PDIF-fix-for-Asus-Xonar-SE.patch
  0010-control-ctlparse-fix-enum-values-in-or.patch
  0011-conf-USB-Audio-Disable-IEC958-on-Lenovo-ThinkStation.patch
  0012-pcm-dmix-fix-access-to-sum-buffer-in-non-interleaved.patch
  0014-control-Add-documentation-for-snd_ctl_elem_list_.patch
  0015-conf-quote-also-strings-with-and-characters-in-strin.patch
  0016-topology-decode-Fix-channel-map-memory-allocation.patch
  0017-topology-decode-Fix-infinite-loop-in-decoding-enum-c.patch
  0018-topology-decode-Remove-decoding-values-for-enum-cont.patch
  0019-topology-decode-Add-enum-control-texts-as-separate-e.patch
  0020-topology-decode-Fix-printing-texts-section.patch
  0021-topology-decode-Change-declaration-of-enum-decoding-.patch
  0022-topology-decode-Fix-decoding-PCM-formats-and-rates.patch
  0023-topology-decode-Print-sig_bits-field-in-PCM-capabili.patch
  0024-topology-decode-Add-DAI-name-printing.patch
  0025-topology-Make-buffer-for-saving-dynamic-size.patch
  0026-topology-return-correct-value-in-tplg_save_printf.patch
  0027-topology-fix-some-gcc10-warnings-labs-signess.patch
  0028-topology-fix-sort_config.patch
  0029-topology-fix-the-unaligned-access.patch
  0030-topology-improve-the-printf-buffer-management.patch

OBS-URL: https://build.opensuse.org/request/show/836375
OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=281
2020-09-23 16:47:30 +00:00

152 lines
5.1 KiB
Diff

From 8defc5c2a65345a1aee613ebf0999d203c2e0433 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Mon, 13 Jul 2020 23:17:03 +0200
Subject: [PATCH 07/32] pcm: iec958: implement HDMI HBR audio formatting
High bitrate compressed audio data like DTS HD or MAT is usually
packed into 8-channel data. The HDMI specs state this has to be
formatted as a single IEC958 stream, compared to normal multi-
channel PCM data which has to be formatted as parallel IEC958 streams.
As this single-stream formatting mode may break existing setups that
expect non-PCM multichannel data to be formatted as parallel IEC958
streams it needs to be explicitly selected by setting the hdmi_mode
option to true.
The single-stream formatting implementation is prepared to cope with
arbitrary channel counts but only limited testing was done for channel
counts other than 8.
Signed-off-by: Matthias Reichl <hias@horus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
src/pcm/pcm_iec958.c | 37 +++++++++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/src/pcm/pcm_iec958.c b/src/pcm/pcm_iec958.c
index 76d3ca7b8e3c..17ade9571cae 100644
--- a/src/pcm/pcm_iec958.c
+++ b/src/pcm/pcm_iec958.c
@@ -63,6 +63,7 @@ struct snd_pcm_iec958 {
unsigned int byteswap;
unsigned char preamble[3]; /* B/M/W or Z/X/Y */
snd_pcm_fast_ops_t fops;
+ int hdmi_mode;
};
enum { PREAMBLE_Z, PREAMBLE_X, PREAMBLE_Y };
@@ -193,6 +194,10 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec,
unsigned int channel;
int32_t sample = 0;
int counter = iec->counter;
+ int single_stream = iec->hdmi_mode &&
+ (iec->status[0] & IEC958_AES0_NONAUDIO) &&
+ (channels == 8);
+ int counter_step = single_stream ? ((channels + 1) >> 1) : 1;
for (channel = 0; channel < channels; ++channel) {
const char *src;
uint32_t *dst;
@@ -205,7 +210,12 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec,
src_step = snd_pcm_channel_area_step(src_area);
dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(uint32_t);
frames1 = frames;
- iec->counter = counter;
+
+ if (single_stream)
+ iec->counter = (counter + (channel >> 1)) % 192;
+ else
+ iec->counter = counter;
+
while (frames1-- > 0) {
goto *get;
#define GET32_END after
@@ -217,9 +227,11 @@ static void snd_pcm_iec958_encode(snd_pcm_iec958_t *iec,
*dst = sample;
src += src_step;
dst += dst_step;
- iec->counter++;
+ iec->counter += counter_step;
iec->counter %= 192;
}
+ if (single_stream) /* set counter to ch0 value for next iteration */
+ iec->counter = (counter + frames * counter_step) % 192;
}
}
#endif /* DOC_HIDDEN */
@@ -473,6 +485,7 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
* \param close_slave When set, the slave PCM handle is closed with copy PCM
* \param status_bits The IEC958 status bits
* \param preamble_vals The preamble byte values
+ * \param hdmi_mode When set, enable HDMI compliant formatting
* \retval zero on success otherwise a negative error code
* \warning Using of this function might be dangerous in the sense
* of compatibility reasons. The prototype might be freely
@@ -481,7 +494,8 @@ static const snd_pcm_ops_t snd_pcm_iec958_ops = {
int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat,
snd_pcm_t *slave, int close_slave,
const unsigned char *status_bits,
- const unsigned char *preamble_vals)
+ const unsigned char *preamble_vals,
+ int hdmi_mode)
{
snd_pcm_t *pcm;
snd_pcm_iec958_t *iec;
@@ -519,6 +533,8 @@ int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sfo
memcpy(iec->preamble, preamble_vals, 3);
+ iec->hdmi_mode = hdmi_mode;
+
err = snd_pcm_new(&pcm, SND_PCM_TYPE_IEC958, name, slave->stream, slave->mode);
if (err < 0) {
free(iec);
@@ -566,9 +582,14 @@ pcm.name {
[preamble.z or preamble.b val]
[preamble.x or preamble.m val]
[preamble.y or preamble.w val]
+ [hdmi_mode true]
}
\endcode
+When <code>hdmi_mode</code> is true, 8-channel compressed data is
+formatted as 4 contiguous frames of a single IEC958 stream as required
+by the HDMI HBR specification.
+
\subsection pcm_plugins_iec958_funcref Function reference
<UL>
@@ -605,6 +626,7 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
unsigned char preamble_vals[3] = {
0x08, 0x02, 0x04 /* Z, X, Y */
};
+ int hdmi_mode = 0;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@@ -633,6 +655,13 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
preamble = n;
continue;
}
+ if (strcmp(id, "hdmi_mode") == 0) {
+ err = snd_config_get_bool(n);
+ if (err < 0)
+ continue;
+ hdmi_mode = err;
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@@ -707,7 +736,7 @@ int _snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name,
return err;
err = snd_pcm_iec958_open(pcmp, name, sformat, spcm, 1,
status ? status_bits : NULL,
- preamble_vals);
+ preamble_vals, hdmi_mode);
if (err < 0)
snd_pcm_close(spcm);
return err;
--
2.16.4