aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.10/950-0633-snd-iec958-split-status-creation-and-fill.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0633-snd-iec958-split-status-creation-and-fill.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.10/950-0633-snd-iec958-split-status-creation-and-fill.patch209
1 files changed, 209 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0633-snd-iec958-split-status-creation-and-fill.patch b/target/linux/bcm27xx/patches-5.10/950-0633-snd-iec958-split-status-creation-and-fill.patch
new file mode 100644
index 0000000000..3ea53da658
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.10/950-0633-snd-iec958-split-status-creation-and-fill.patch
@@ -0,0 +1,209 @@
+From 5dea9e48e2a2bd39524e21c1a743f08edd8e4ef6 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Wed, 28 Apr 2021 15:29:13 +0200
+Subject: [PATCH] snd: iec958: split status creation and fill
+
+In some situations, like a codec probe, we need to provide an IEC status
+default but don't have access to the sampling rate and width yet since
+no stream has been configured yet.
+
+Each and every driver has its own default, whereas the core iec958 code
+also has some buried in the snd_pcm_create_iec958_consumer functions.
+
+Let's split these functions in two to provide a default that doesn't
+rely on the sampling rate and width, and another function to fill them
+when available.
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ include/sound/pcm_iec958.h | 8 +++
+ sound/core/pcm_iec958.c | 129 +++++++++++++++++++++++++------------
+ 2 files changed, 95 insertions(+), 42 deletions(-)
+
+--- a/include/sound/pcm_iec958.h
++++ b/include/sound/pcm_iec958.h
+@@ -4,6 +4,14 @@
+
+ #include <linux/types.h>
+
++int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len);
++
++int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
++ size_t len);
++
++int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
++ u8 *cs, size_t len);
++
+ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+ size_t len);
+
+--- a/sound/core/pcm_iec958.c
++++ b/sound/core/pcm_iec958.c
+@@ -9,41 +9,68 @@
+ #include <sound/pcm_params.h>
+ #include <sound/pcm_iec958.h>
+
+-static int create_iec958_consumer(uint rate, uint sample_width,
+- u8 *cs, size_t len)
++int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len)
+ {
+- unsigned int fs, ws;
+-
+ if (len < 4)
+ return -EINVAL;
+
+- switch (rate) {
+- case 32000:
+- fs = IEC958_AES3_CON_FS_32000;
+- break;
+- case 44100:
+- fs = IEC958_AES3_CON_FS_44100;
+- break;
+- case 48000:
+- fs = IEC958_AES3_CON_FS_48000;
+- break;
+- case 88200:
+- fs = IEC958_AES3_CON_FS_88200;
+- break;
+- case 96000:
+- fs = IEC958_AES3_CON_FS_96000;
+- break;
+- case 176400:
+- fs = IEC958_AES3_CON_FS_176400;
+- break;
+- case 192000:
+- fs = IEC958_AES3_CON_FS_192000;
+- break;
+- default:
++ memset(cs, 0, len);
++
++ cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
++ cs[1] = IEC958_AES1_CON_GENERAL;
++ cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
++ cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
++
++ if (len > 4)
++ cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
++
++ return len;
++}
++EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_default);
++
++static int fill_iec958_consumer(uint rate, uint sample_width,
++ u8 *cs, size_t len)
++{
++ if (len < 4)
+ return -EINVAL;
++
++ if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
++ unsigned int fs;
++
++ switch (rate) {
++ case 32000:
++ fs = IEC958_AES3_CON_FS_32000;
++ break;
++ case 44100:
++ fs = IEC958_AES3_CON_FS_44100;
++ break;
++ case 48000:
++ fs = IEC958_AES3_CON_FS_48000;
++ break;
++ case 88200:
++ fs = IEC958_AES3_CON_FS_88200;
++ break;
++ case 96000:
++ fs = IEC958_AES3_CON_FS_96000;
++ break;
++ case 176400:
++ fs = IEC958_AES3_CON_FS_176400;
++ break;
++ case 192000:
++ fs = IEC958_AES3_CON_FS_192000;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ cs[3] &= ~IEC958_AES3_CON_FS;
++ cs[3] |= fs;
+ }
+
+- if (len > 4) {
++ if (len > 4 &&
++ (cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
++ unsigned int ws;
++
+ switch (sample_width) {
+ case 16:
+ ws = IEC958_AES4_CON_WORDLEN_20_16;
+@@ -64,20 +91,29 @@ static int create_iec958_consumer(uint r
+ default:
+ return -EINVAL;
+ }
+- }
+
+- memset(cs, 0, len);
++ cs[4] &= ~IEC958_AES4_CON_WORDLEN;
++ cs[4] |= ws;
++ }
+
+- cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
+- cs[1] = IEC958_AES1_CON_GENERAL;
+- cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
+- cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
++ return len;
++}
+
+- if (len > 4)
+- cs[4] = ws;
++int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
++ u8 *cs, size_t len)
++{
++ return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
++}
++EXPORT_SYMBOL(snd_pcm_fill_iec958_consumer_hw_params);
+
+- return len;
++int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime,
++ u8 *cs, size_t len)
++{
++ return fill_iec958_consumer(runtime->rate,
++ snd_pcm_format_width(runtime->format),
++ cs, len);
+ }
++EXPORT_SYMBOL(snd_pcm_fill_iec958_consumer);
+
+ /**
+ * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
+@@ -95,9 +131,13 @@ static int create_iec958_consumer(uint r
+ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+ size_t len)
+ {
+- return create_iec958_consumer(runtime->rate,
+- snd_pcm_format_width(runtime->format),
+- cs, len);
++ int ret;
++
++ ret = snd_pcm_create_iec958_consumer_default(cs, len);
++ if (ret < 0)
++ return ret;
++
++ return snd_pcm_fill_iec958_consumer(runtime, cs, len);
+ }
+ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
+
+@@ -117,7 +157,12 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_cons
+ int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
+ u8 *cs, size_t len)
+ {
+- return create_iec958_consumer(params_rate(params), params_width(params),
+- cs, len);
++ int ret;
++
++ ret = snd_pcm_create_iec958_consumer_default(cs, len);
++ if (ret < 0)
++ return ret;
++
++ return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
+ }
+ EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);