meta-st-stm32mp/recipes-kernel/linux/linux-stm32mp/5.15/5.15.118/0020-v5.15-stm32mp-r2.1-SOU...

309 lines
9.5 KiB
Diff

From 73957b4c529874c1c4ddcad2db33caff026973e1 Mon Sep 17 00:00:00 2001
From: Romuald Jeanne <romuald.jeanne@st.com>
Date: Tue, 25 Jul 2023 10:57:46 +0200
Subject: [PATCH 20/22] v5.15-stm32mp-r2.1 SOUND
Signed-off-by: Romuald Jeanne <romuald.jeanne@st.com>
---
sound/soc/codecs/Kconfig | 2 +-
sound/soc/codecs/wm8994.c | 81 ++++++++++++++++++++++++++++++++---
sound/soc/stm/stm32_adfsdm.c | 11 +++--
sound/soc/stm/stm32_i2s.c | 6 ++-
sound/soc/stm/stm32_sai_sub.c | 4 +-
sound/soc/stm/stm32_spdifrx.c | 4 ++
6 files changed, 95 insertions(+), 13 deletions(-)
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c3deb82c5da3..76981d82b005 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1774,7 +1774,7 @@ config SND_SOC_WM8993
depends on I2C
config SND_SOC_WM8994
- tristate
+ tristate "Wolfson Microelectronics WM8994 codec"
config SND_SOC_WM8995
tristate
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 6759db92f6c4..c037368acdd4 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -7,6 +7,7 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -838,6 +839,37 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(comp);
+ int ret, mclk_id = 0;
+
+ if (!strncmp(w->name, "MCLK2", 5))
+ mclk_id = 1;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dev_dbg(comp->dev, "Enable master clock %s\n",
+ mclk_id ? "MCLK2" : "MCLK1");
+
+ ret = clk_prepare_enable(wm8994->mclk[mclk_id].clk);
+ if (ret < 0) {
+ dev_err(comp->dev, "Failed to enable clock: %d\n", ret);
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ dev_dbg(comp->dev, "Disable master clock %s\n",
+ mclk_id ? "MCLK2" : "MCLK1");
+ clk_disable_unprepare(wm8994->mclk[mclk_id].clk);
+ break;
+ }
+
+ return 0;
+}
+
static void vmid_reference(struct snd_soc_component *component)
{
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
@@ -1225,7 +1257,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
else
adc = WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA;
-
val = snd_soc_component_read(component, WM8994_AIF2_CONTROL_2);
if ((val & WM8994_AIF2DACL_SRC) &&
(val & WM8994_AIF2DACR_SRC))
@@ -1847,6 +1878,16 @@ static const struct snd_soc_dapm_widget wm8994_specific_dapm_widgets[] = {
SND_SOC_DAPM_MUX("AIF3ADC Mux", SND_SOC_NOPM, 0, 0, &wm8994_aif3adc_mux),
};
+static const struct snd_soc_dapm_widget wm8994_mclk1_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("MCLK1", SND_SOC_NOPM, 0, 0, mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static const struct snd_soc_dapm_widget wm8994_mclk2_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("MCLK2", SND_SOC_NOPM, 0, 0, mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
static const struct snd_soc_dapm_widget wm8958_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("AIF3", WM8994_POWER_MANAGEMENT_6, 5, 1, NULL, 0),
SND_SOC_DAPM_MUX("Mono PCM Out Mux", SND_SOC_NOPM, 0, 0, &mono_pcm_out_mux),
@@ -2071,10 +2112,10 @@ static const struct snd_soc_dapm_route wm8994_lateclk_intercon[] = {
};
static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
- { "AIF1DACDAT", NULL, "AIF2DACDAT" },
- { "AIF2DACDAT", NULL, "AIF1DACDAT" },
- { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
- { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
+// { "AIF1DACDAT", NULL, "AIF2DACDAT" },
+// { "AIF2DACDAT", NULL, "AIF1DACDAT" },
+// { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
+// { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
{ "MICBIAS1", NULL, "CLK_SYS" },
{ "MICBIAS1", NULL, "MICBIAS Supply" },
{ "MICBIAS2", NULL, "CLK_SYS" },
@@ -2506,11 +2547,24 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
{
struct snd_soc_component *component = dai->component;
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
- int ret, i;
+ int i, ret;
+ /*
+ * Simple card provides unconditionnaly clock_id = 0.
+ * Workaround to select master clock for aif1/2
+ */
switch (dai->id) {
case 1:
+ if (wm8994->mclk[0].clk)
+ clk_id = WM8994_SYSCLK_MCLK1;
+ else if (wm8994->mclk[1].clk)
+ clk_id = WM8994_SYSCLK_MCLK2;
+ break;
case 2:
+ if (wm8994->mclk[1].clk)
+ clk_id = WM8994_SYSCLK_MCLK2;
+ else if (wm8994->mclk[0].clk)
+ clk_id = WM8994_SYSCLK_MCLK1;
break;
default:
@@ -2522,6 +2576,10 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
case WM8994_SYSCLK_MCLK1:
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1;
+ /* Avoid busy error on exclusive rate change request */
+ if (!freq)
+ break;
+
ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
if (ret < 0)
return ret;
@@ -2535,6 +2593,9 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
/* TODO: Set GPIO AF */
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2;
+ if (!freq)
+ break;
+
ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
if (ret < 0)
return ret;
@@ -4443,6 +4504,14 @@ static int wm8994_component_probe(struct snd_soc_component *component)
ARRAY_SIZE(wm8994_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
ARRAY_SIZE(wm8994_specific_dapm_widgets));
+ if (wm8994->mclk[0].clk)
+ snd_soc_dapm_new_controls(dapm, wm8994_mclk1_dapm_widgets,
+ ARRAY_SIZE(wm8994_mclk1_dapm_widgets));
+
+ if (wm8994->mclk[1].clk)
+ snd_soc_dapm_new_controls(dapm, wm8994_mclk2_dapm_widgets,
+ ARRAY_SIZE(wm8994_mclk2_dapm_widgets));
+
if (control->revision < 4) {
snd_soc_dapm_new_controls(dapm, wm8994_lateclk_revd_widgets,
ARRAY_SIZE(wm8994_lateclk_revd_widgets));
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
index 1e9b4b1df69e..75e75cc7fa02 100644
--- a/sound/soc/stm/stm32_adfsdm.c
+++ b/sound/soc/stm/stm32_adfsdm.c
@@ -12,7 +12,7 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-
+#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
#include <linux/iio/consumer.h>
#include <linux/iio/adc/stm32-dfsdm-adc.h>
@@ -374,15 +374,20 @@ static int stm32_adfsdm_probe(struct platform_device *pdev)
#endif
ret = snd_soc_add_component(component, NULL, 0);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&pdev->dev, "%s: Failed to register PCM platform\n",
__func__);
+ return ret;
+ }
- return ret;
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
}
static int stm32_adfsdm_remove(struct platform_device *pdev)
{
+ pm_runtime_disable(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
return 0;
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 717f45a83445..f16dd7608b7e 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/spinlock.h>
@@ -1087,7 +1088,7 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
if (irq < 0)
return irq;
- ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, IRQF_ONESHOT,
+ ret = devm_request_irq(&pdev->dev, irq, stm32_i2s_isr, 0,
dev_name(&pdev->dev), i2s);
if (ret) {
dev_err(&pdev->dev, "irq request returned %d\n", ret);
@@ -1113,6 +1114,7 @@ static int stm32_i2s_remove(struct platform_device *pdev)
{
snd_dmaengine_pcm_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
@@ -1195,6 +1197,8 @@ static int stm32_i2s_probe(struct platform_device *pdev)
FIELD_GET(I2S_VERR_MIN_MASK, val));
}
+ pm_runtime_enable(&pdev->dev);
+
return ret;
error:
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 9c3b8e209656..95cd38a502bb 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -1294,7 +1294,7 @@ static struct snd_soc_dai_driver stm32_sai_playback_dai = {
.id = 1, /* avoid call to fmt_single_name() */
.playback = {
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 16,
.rate_min = 8000,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
@@ -1312,7 +1312,7 @@ static struct snd_soc_dai_driver stm32_sai_capture_dai = {
.id = 1, /* avoid call to fmt_single_name() */
.capture = {
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 16,
.rate_min = 8000,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index 48145f553588..e885796ca5f4 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
@@ -955,6 +956,7 @@ static int stm32_spdifrx_remove(struct platform_device *pdev)
snd_dmaengine_pcm_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
@@ -1045,6 +1047,8 @@ static int stm32_spdifrx_probe(struct platform_device *pdev)
FIELD_GET(SPDIFRX_VERR_MIN_MASK, ver));
}
+ pm_runtime_enable(&pdev->dev);
+
return ret;
error:
--
2.17.1