diff options
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.patch | 209 |
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); |