mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-28 17:48:58 +00:00
138 lines
4.2 KiB
Diff
138 lines
4.2 KiB
Diff
|
From e866f9fc7c6dd6af1e74ce6fa50db9ba21acae5e Mon Sep 17 00:00:00 2001
|
||
|
From: Matthias Reichl <hias@horus.com>
|
||
|
Date: Sat, 24 Jun 2023 18:52:16 +0200
|
||
|
Subject: [PATCH] ALSA: pcm: fix ELD constraints for (E)AC3, DTS(-HD) and MLP
|
||
|
formats
|
||
|
|
||
|
commit 04b49b90caeed0b5544ff616d654900d27d403b6 upstream.
|
||
|
|
||
|
The SADs of compressed formats contain the channel and sample rate
|
||
|
info of the audio data inside the compressed stream, but when
|
||
|
building constraints we must use the rates and channels used to
|
||
|
transport the compressed streams.
|
||
|
|
||
|
eg 48kHz 6ch EAC3 needs to be transmitted as a 2ch 192kHz stream.
|
||
|
|
||
|
This patch fixes the constraints for the common AC3 and DTS formats,
|
||
|
the constraints for the less common MPEG, DSD etc formats are copied
|
||
|
directly from the info in the SADs as before as I don't have the specs
|
||
|
and equipment to test those.
|
||
|
|
||
|
Signed-off-by: Matthias Reichl <hias@horus.com>
|
||
|
Link: https://lore.kernel.org/r/20230624165216.5719-1-hias@horus.com
|
||
|
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||
|
---
|
||
|
sound/core/pcm_drm_eld.c | 73 ++++++++++++++++++++++++++++++++++++++--
|
||
|
1 file changed, 70 insertions(+), 3 deletions(-)
|
||
|
|
||
|
--- a/sound/core/pcm_drm_eld.c
|
||
|
+++ b/sound/core/pcm_drm_eld.c
|
||
|
@@ -2,11 +2,25 @@
|
||
|
/*
|
||
|
* PCM DRM helpers
|
||
|
*/
|
||
|
+#include <linux/bitfield.h>
|
||
|
#include <linux/export.h>
|
||
|
+#include <linux/hdmi.h>
|
||
|
#include <drm/drm_edid.h>
|
||
|
#include <sound/pcm.h>
|
||
|
#include <sound/pcm_drm_eld.h>
|
||
|
|
||
|
+#define SAD0_CHANNELS_MASK GENMASK(2, 0) /* max number of channels - 1 */
|
||
|
+#define SAD0_FORMAT_MASK GENMASK(6, 3) /* audio format */
|
||
|
+
|
||
|
+#define SAD1_RATE_MASK GENMASK(6, 0) /* bitfield of supported rates */
|
||
|
+#define SAD1_RATE_32000_MASK BIT(0)
|
||
|
+#define SAD1_RATE_44100_MASK BIT(1)
|
||
|
+#define SAD1_RATE_48000_MASK BIT(2)
|
||
|
+#define SAD1_RATE_88200_MASK BIT(3)
|
||
|
+#define SAD1_RATE_96000_MASK BIT(4)
|
||
|
+#define SAD1_RATE_176400_MASK BIT(5)
|
||
|
+#define SAD1_RATE_192000_MASK BIT(6)
|
||
|
+
|
||
|
static const unsigned int eld_rates[] = {
|
||
|
32000,
|
||
|
44100,
|
||
|
@@ -17,9 +31,62 @@ static const unsigned int eld_rates[] =
|
||
|
192000,
|
||
|
};
|
||
|
|
||
|
+static unsigned int map_rate_families(const u8 *sad,
|
||
|
+ unsigned int mask_32000,
|
||
|
+ unsigned int mask_44100,
|
||
|
+ unsigned int mask_48000)
|
||
|
+{
|
||
|
+ unsigned int rate_mask = 0;
|
||
|
+
|
||
|
+ if (sad[1] & SAD1_RATE_32000_MASK)
|
||
|
+ rate_mask |= mask_32000;
|
||
|
+ if (sad[1] & (SAD1_RATE_44100_MASK | SAD1_RATE_88200_MASK | SAD1_RATE_176400_MASK))
|
||
|
+ rate_mask |= mask_44100;
|
||
|
+ if (sad[1] & (SAD1_RATE_48000_MASK | SAD1_RATE_96000_MASK | SAD1_RATE_192000_MASK))
|
||
|
+ rate_mask |= mask_48000;
|
||
|
+ return rate_mask;
|
||
|
+}
|
||
|
+
|
||
|
+static unsigned int sad_rate_mask(const u8 *sad)
|
||
|
+{
|
||
|
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_PCM:
|
||
|
+ return sad[1] & SAD1_RATE_MASK;
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_AC3:
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_DTS:
|
||
|
+ return map_rate_families(sad,
|
||
|
+ SAD1_RATE_32000_MASK,
|
||
|
+ SAD1_RATE_44100_MASK,
|
||
|
+ SAD1_RATE_48000_MASK);
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_MLP:
|
||
|
+ return map_rate_families(sad,
|
||
|
+ 0,
|
||
|
+ SAD1_RATE_176400_MASK,
|
||
|
+ SAD1_RATE_192000_MASK);
|
||
|
+ default:
|
||
|
+ /* TODO adjust for other compressed formats as well */
|
||
|
+ return sad[1] & SAD1_RATE_MASK;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
static unsigned int sad_max_channels(const u8 *sad)
|
||
|
{
|
||
|
- return 1 + (sad[0] & 7);
|
||
|
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_PCM:
|
||
|
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_AC3:
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_DTS:
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
|
||
|
+ return 2;
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
|
||
|
+ case HDMI_AUDIO_CODING_TYPE_MLP:
|
||
|
+ return 8;
|
||
|
+ default:
|
||
|
+ /* TODO adjust for other compressed formats as well */
|
||
|
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static int eld_limit_rates(struct snd_pcm_hw_params *params,
|
||
|
@@ -42,7 +109,7 @@ static int eld_limit_rates(struct snd_pc
|
||
|
* requested number of channels.
|
||
|
*/
|
||
|
if (c->min <= max_channels)
|
||
|
- rate_mask |= sad[1];
|
||
|
+ rate_mask |= sad_rate_mask(sad);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -70,7 +137,7 @@ static int eld_limit_channels(struct snd
|
||
|
rate_mask |= BIT(i);
|
||
|
|
||
|
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
|
||
|
- if (rate_mask & sad[1])
|
||
|
+ if (rate_mask & sad_rate_mask(sad))
|
||
|
t.max = max(t.max, sad_max_channels(sad));
|
||
|
}
|
||
|
|